From 7e8a8851ff2be65206745b82f3028916b0136415 Mon Sep 17 00:00:00 2001 From: iks Date: Mon, 23 Nov 2020 17:43:24 +0900 Subject: [PATCH] Revert "Revert "Merge branch 'master' of git.osdn.net:/gitroot/hengband/hengband"" This reverts commit 7eb4f5a85e0241b107140d937026ab939bb6323a. --- .clang-format | 115 + .gitignore | 17 +- Hengband/Bakabakaband.sln | 36 + Hengband/Hengband/Bakabakaband.vcxproj | 1750 +++++ Hengband/Hengband/Bakabakaband.vcxproj.filters | 4928 ++++++++++++ Hengband/Hengband/packages.config | 8 + Hengband_vcs2015/Hengband.sln | 23 - Hengband_vcs2015/Hengband/Hengband.vcxproj | 327 - Hengband_vcs2017/Hengband.sln | 30 - Hengband_vcs2017/Hengband/Hengband.vcxproj | 378 - Hengband_vcs2017/Hengband/Hengband.vcxproj.filters | 492 -- Makefile.am | 16 +- autopick.txt | 14 +- autopick_eng.txt | 12 +- configure.ac | 11 +- doxygen/Hengband.doxyfile | 8 +- hengband.spec | 104 +- lib/edit/Makefile.am | 4 +- lib/edit/a_info.txt | 262 +- lib/edit/d_info.txt | 4 +- lib/edit/e_info.txt | 4 +- lib/edit/f_info.txt | 18 +- lib/edit/k_info.txt | 57 +- lib/edit/misc.txt | 4 +- lib/edit/q0000004.txt | 2 +- lib/edit/q0000005.txt | 2 +- lib/edit/q0dumpwitness.txt | 4 +- lib/edit/q0willow.txt | 2 +- lib/edit/qdarkelf.txt | 2 +- lib/edit/qhaunted.txt | 2 +- lib/edit/r_info.txt | 1240 ++- lib/edit/t0000001.txt | 2 +- lib/edit/t_lite.txt | 2 +- lib/edit/v_info.txt | 34 + lib/file/Makefile.am | 2 +- lib/file/a_med.txt | 2 +- lib/file/death.txt | 2 +- lib/file/mondeath.txt | 2 +- lib/file/mondeath_j.txt | 3 + lib/file/monfear_j.txt | 3 + lib/file/monfrien.txt | 6 +- lib/file/monfrien_j.txt | 3 + lib/file/monspeak.txt | 12 +- lib/file/monspeak_j.txt | 9 + lib/file/news.txt | 6 +- lib/file/news_j.txt | 6 +- lib/file/rumors.txt | 22 +- lib/file/rumors_j.txt | 20 +- lib/file/seppuku.txt | 2 +- lib/file/timefun.txt | 2 +- lib/file/timefun_j.txt | 2 +- lib/file/w_low.txt | 4 +- lib/file/w_med.txt | 2 +- lib/help/Makefile.am | 2 +- lib/help/attack.txt | 31 +- lib/help/birth.txt | 58 +- lib/help/bldg.txt | 16 +- lib/help/command.hlp | 4 +- lib/help/command.txt | 26 +- lib/help/commdesc.hlp | 2 +- lib/help/commdesc.txt | 30 +- lib/help/defend.txt | 30 +- lib/help/dungeon.txt | 16 +- lib/help/editor.txt | 15 +- lib/help/faq.txt | 32 +- lib/help/general.hlp | 6 +- lib/help/general.txt | 32 +- lib/help/help.hlp | 10 +- lib/help/helpinfo.txt | 2 +- lib/help/jattack.txt | 18 +- lib/help/jbirth.txt | 6 +- lib/help/jbldg.txt | 2 +- lib/help/jcommand.hlp | 4 +- lib/help/jcommand.txt | 12 +- lib/help/jcommdesc.hlp | 2 +- lib/help/jcommdesc.txt | 4 +- lib/help/jdefend.txt | 16 +- lib/help/jdungeon.txt | 12 +- lib/help/jeditor.txt | 8 +- lib/help/jgeneral.hlp | 4 +- lib/help/jgeneral.txt | 22 +- lib/help/jhelp.hlp | 2 +- lib/help/jhelpinfo.txt | 2 +- lib/help/jlicense.txt | 14 +- lib/help/jmagic.hlp | 4 +- lib/help/jmagic.txt | 10 +- lib/help/jmonster.hlp | 4 +- lib/help/jmonster.txt | 20 +- lib/help/jobjects.hlp | 4 +- lib/help/jobjects.txt | 20 +- lib/help/joption.hlp | 4 +- lib/help/joption.txt | 8 +- lib/help/jpref.txt | 14 +- lib/help/jraceclas.txt | 14 +- lib/help/jtang.txt | 42 +- lib/help/jtown.txt | 8 +- lib/help/jversion.txt | 16 +- lib/help/magic.hlp | 4 +- lib/help/magic.txt | 44 +- lib/help/monster.hlp | 4 +- lib/help/monster.txt | 28 +- lib/help/objects.hlp | 4 +- lib/help/objects.txt | 58 +- lib/help/option.hlp | 4 +- lib/help/option.txt | 36 +- lib/help/pref.txt | 28 +- lib/help/raceclas.txt | 232 +- lib/help/tang.txt | 89 +- lib/help/town.txt | 22 +- lib/help/version.txt | 82 +- lib/pref/Makefile.am | 2 +- lib/pref/graf-ne2.prf | 2 +- lib/pref/graf-win.prf | 2 +- lib/xtra/music/Makefile.am | 3 +- lib/xtra/music/music.cfg | 2 +- lib/xtra/sound/Makefile.am | 20 +- markdown/history.md | 8 +- markdown/history/history1.0.10.md | 2 +- markdown/history/history1.0.6.md | 2 +- markdown/history/history1.0.9.md | 2 +- markdown/history/history1.6.6.md | 2 +- markdown/template.html | 10 +- readme.txt | 22 +- readme_eng.txt | 28 +- src/Makefile.am | 997 ++- src/action/action-limited.c | 105 + src/action/action-limited.h | 11 + src/action/activation-execution.c | 245 + src/action/activation-execution.h | 5 + src/action/movement-execution.c | 334 + src/action/movement-execution.h | 5 + src/action/mutation-execution.c | 282 + src/action/mutation-execution.h | 5 + src/action/open-close-execution.c | 333 + src/action/open-close-execution.h | 10 + src/action/open-util.c | 67 + src/action/open-util.h | 6 + src/action/racial-execution.c | 128 + src/action/racial-execution.h | 14 + src/action/run-execution.c | 381 + src/action/run-execution.h | 12 + src/action/throw-util.c | 18 + src/action/throw-util.h | 48 + src/action/travel-execution.c | 121 + src/action/travel-execution.h | 18 + src/action/tunnel-execution.c | 112 + src/action/tunnel-execution.h | 5 + src/action/weapon-shield.c | 71 + src/action/weapon-shield.h | 5 + src/angband.h | 103 - src/art-definition/art-accessory-types.h | 37 + src/art-definition/art-armor-types.h | 33 + src/art-definition/art-bow-types.h | 17 + src/art-definition/art-protector-types.h | 61 + src/art-definition/art-sword-types.h | 66 + src/art-definition/art-weapon-types.h | 69 + src/art-definition/random-art-effects.h | 134 + src/artifact.c | 2329 ------ src/artifact.h | 294 - src/artifact/artifact-info.c | 64 + src/artifact/artifact-info.h | 7 + src/artifact/fixed-art-generator.c | 332 + src/artifact/fixed-art-generator.h | 7 + src/artifact/random-art-activation.c | 235 + src/artifact/random-art-activation.h | 5 + src/artifact/random-art-bias-types.h | 25 + src/artifact/random-art-characteristics.c | 226 + src/artifact/random-art-characteristics.h | 7 + src/artifact/random-art-generator.c | 438 ++ src/artifact/random-art-generator.h | 5 + src/artifact/random-art-misc.c | 344 + src/artifact/random-art-misc.h | 5 + src/artifact/random-art-pval-investor.c | 243 + src/artifact/random-art-pval-investor.h | 6 + src/artifact/random-art-resistance.c | 473 ++ src/artifact/random-art-resistance.h | 5 + src/artifact/random-art-slay.c | 354 + src/artifact/random-art-slay.h | 5 + src/autopick.c | 6140 --------------- src/autopick/autopick-command-menu.c | 143 + src/autopick/autopick-command-menu.h | 3 + src/autopick/autopick-commands-table.h | 86 + src/autopick/autopick-describer.c | 596 ++ src/autopick/autopick-describer.h | 5 + src/autopick/autopick-destroyer.c | 127 + src/autopick/autopick-destroyer.h | 5 + src/autopick/autopick-dirty-flags.h | 13 + src/autopick/autopick-drawer.c | 309 + src/autopick/autopick-drawer.h | 6 + src/autopick/autopick-editor-command.c | 778 ++ src/autopick/autopick-editor-command.h | 13 + src/autopick/autopick-editor-table.h | 76 + src/autopick/autopick-editor-util.c | 318 + src/autopick/autopick-editor-util.h | 12 + src/autopick/autopick-entry.c | 652 ++ src/autopick/autopick-entry.h | 10 + src/autopick/autopick-finder.c | 391 + src/autopick/autopick-finder.h | 12 + src/autopick/autopick-flags-table.h | 56 + src/autopick/autopick-initializer.c | 28 + src/autopick/autopick-initializer.h | 3 + src/autopick/autopick-inserter-killer.c | 244 + src/autopick/autopick-inserter-killer.h | 11 + src/autopick/autopick-key-flag-process.h | 18 + src/autopick/autopick-keys-table.h | 57 + src/autopick/autopick-matcher.c | 375 + src/autopick/autopick-matcher.h | 6 + src/autopick/autopick-menu-data-table.c | 117 + src/autopick/autopick-menu-data-table.h | 14 + src/autopick/autopick-methods-table.h | 8 + src/autopick/autopick-pref-processor.c | 43 + src/autopick/autopick-pref-processor.h | 3 + src/autopick/autopick-reader-writer.c | 197 + src/autopick/autopick-reader-writer.h | 9 + src/autopick/autopick-registry.c | 199 + src/autopick/autopick-registry.h | 7 + src/autopick/autopick-util.c | 102 + src/autopick/autopick-util.h | 85 + src/autopick/autopick.c | 153 + src/autopick/autopick.h | 9 + src/avatar.c | 530 -- src/avatar.h | 8 - src/birth.c | 4709 ----------- src/birth/auto-roller.c | 443 ++ src/birth/auto-roller.h | 19 + src/birth/birth-body-spec.c | 73 + src/birth/birth-body-spec.h | 7 + src/birth/birth-explanations-table.c | 308 + src/birth/birth-explanations-table.h | 11 + src/birth/birth-select-class.c | 172 + src/birth/birth-select-class.h | 5 + src/birth/birth-select-personality.c | 204 + src/birth/birth-select-personality.h | 5 + src/birth/birth-select-race.c | 159 + src/birth/birth-select-race.h | 5 + src/birth/birth-select-realm.c | 384 + src/birth/birth-select-realm.h | 5 + src/birth/birth-stat.c | 181 + src/birth/birth-stat.h | 9 + src/birth/birth-util.c | 62 + src/birth/birth-util.h | 16 + src/birth/birth-wizard.c | 547 ++ src/birth/birth-wizard.h | 5 + src/birth/character-builder.c | 108 + src/birth/character-builder.h | 5 + src/birth/game-play-initializer.c | 229 + src/birth/game-play-initializer.h | 7 + src/birth/history-editor.c | 178 + src/birth/history-editor.h | 5 + src/birth/history-generator.c | 154 + src/birth/history-generator.h | 5 + src/birth/history.c | 1646 ++++ src/birth/history.h | 17 + src/birth/initial-equipments-table.c | 174 + src/birth/initial-equipments-table.h | 5 + src/birth/inventory-initializer.c | 269 + src/birth/inventory-initializer.h | 7 + src/birth/quick-start.c | 152 + src/birth/quick-start.h | 40 + src/bldg.c | 4368 ----------- src/blue-magic/blue-magic-ball-bolt.c | 257 + src/blue-magic/blue-magic-ball-bolt.h | 28 + src/blue-magic/blue-magic-breath.c | 257 + src/blue-magic/blue-magic-breath.h | 27 + src/blue-magic/blue-magic-caster.c | 395 + src/blue-magic/blue-magic-caster.h | 5 + src/blue-magic/blue-magic-checker.c | 96 + src/blue-magic/blue-magic-checker.h | 7 + src/blue-magic/blue-magic-spirit-curse.c | 78 + src/blue-magic/blue-magic-spirit-curse.h | 12 + src/blue-magic/blue-magic-status.c | 52 + src/blue-magic/blue-magic-status.h | 10 + src/blue-magic/blue-magic-summon.c | 249 + src/blue-magic/blue-magic-summon.h | 21 + src/blue-magic/blue-magic-util.c | 19 + src/blue-magic/blue-magic-util.h | 20 + src/blue-magic/learnt-info.c | 176 + src/blue-magic/learnt-info.h | 6 + src/blue-magic/learnt-power-getter.c | 439 ++ src/blue-magic/learnt-power-getter.h | 5 + src/chest.c | 331 - src/chest.h | 4 - src/chuukei.c | 1128 --- src/cmd-action/cmd-attack.c | 312 + src/cmd-action/cmd-attack.h | 6 + src/cmd-action/cmd-hissatsu.c | 427 + src/cmd-action/cmd-hissatsu.h | 6 + src/cmd-action/cmd-mane.c | 1143 +++ src/cmd-action/cmd-mane.h | 5 + src/cmd-action/cmd-mind.c | 442 ++ src/cmd-action/cmd-mind.h | 8 + src/cmd-action/cmd-move.c | 429 + src/cmd-action/cmd-move.h | 10 + src/cmd-action/cmd-open-close.c | 368 + src/cmd-action/cmd-open-close.h | 9 + src/cmd-action/cmd-others.c | 183 + src/cmd-action/cmd-others.h | 7 + src/cmd-action/cmd-pet.c | 821 ++ src/cmd-action/cmd-pet.h | 9 + src/cmd-action/cmd-racial.c | 313 + src/cmd-action/cmd-racial.h | 5 + src/cmd-action/cmd-shoot.c | 74 + src/cmd-action/cmd-shoot.h | 5 + src/cmd-action/cmd-spell.c | 1341 ++++ src/cmd-action/cmd-spell.h | 29 + src/cmd-action/cmd-travel.c | 175 + src/cmd-action/cmd-travel.h | 5 + src/cmd-action/cmd-tunnel.c | 69 + src/cmd-action/cmd-tunnel.h | 5 + src/cmd-activate.c | 1780 ----- src/cmd-activate.h | 143 - src/cmd-building/cmd-building.c | 417 + src/cmd-building/cmd-building.h | 23 + src/cmd-building/cmd-inn.c | 248 + src/cmd-building/cmd-inn.h | 5 + src/cmd-building/cmd-store.c | 201 + src/cmd-building/cmd-store.h | 5 + src/cmd-eat.c | 519 -- src/cmd-eat.h | 3 - src/cmd-hissatsu.c | 436 - src/cmd-hissatsu.h | 5 - src/cmd-io/cmd-autopick.c | 212 + src/cmd-io/cmd-autopick.h | 5 + src/cmd-io/cmd-diary.c | 162 + src/cmd-io/cmd-diary.h | 5 + src/cmd-io/cmd-dump.c | 317 + src/cmd-io/cmd-dump.h | 10 + src/cmd-io/cmd-floor.c | 97 + src/cmd-io/cmd-floor.h | 7 + src/cmd-io/cmd-gameoption.c | 713 ++ src/cmd-io/cmd-gameoption.h | 7 + src/cmd-io/cmd-help.c | 17 + src/cmd-io/cmd-help.h | 5 + src/cmd-io/cmd-knowledge.c | 146 + src/cmd-io/cmd-knowledge.h | 5 + src/cmd-io/cmd-lore.c | 208 + src/cmd-io/cmd-lore.h | 5 + src/cmd-io/cmd-macro.c | 333 + src/cmd-io/cmd-macro.h | 5 + src/cmd-io/cmd-menu-content-table.c | 131 + src/cmd-io/cmd-menu-content-table.h | 27 + src/cmd-io/cmd-process-screen.c | 486 ++ src/cmd-io/cmd-process-screen.h | 7 + src/cmd-io/cmd-save.c | 60 + src/cmd-io/cmd-save.h | 6 + src/cmd-io/diary-subtitle-table.c | 79 + src/cmd-io/diary-subtitle-table.h | 7 + src/cmd-io/feeling-table.c | 52 + src/cmd-io/feeling-table.h | 9 + src/cmd-io/macro-util.c | 137 + src/cmd-io/macro-util.h | 18 + src/cmd-item.c | 1600 ---- src/cmd-item.h | 17 - src/cmd-item/cmd-destroy.c | 221 + src/cmd-item/cmd-destroy.h | 5 + src/cmd-item/cmd-eat.c | 441 ++ src/cmd-item/cmd-eat.h | 6 + src/cmd-item/cmd-equipment.c | 337 + src/cmd-item/cmd-equipment.h | 7 + src/cmd-item/cmd-item.c | 305 + src/cmd-item/cmd-item.h | 11 + src/cmd-item/cmd-magiceat.c | 607 ++ src/cmd-item/cmd-magiceat.h | 9 + src/cmd-item/cmd-quaff.c | 43 + src/cmd-item/cmd-quaff.h | 5 + src/cmd-item/cmd-read.c | 46 + src/cmd-item/cmd-read.h | 5 + src/cmd-item/cmd-refill.c | 110 + src/cmd-item/cmd-refill.h | 5 + src/cmd-item/cmd-smith.c | 1196 +++ src/cmd-item/cmd-smith.h | 24 + src/cmd-item/cmd-throw.c | 556 ++ src/cmd-item/cmd-throw.h | 5 + src/cmd-item/cmd-usestaff.c | 455 ++ src/cmd-item/cmd-usestaff.h | 7 + src/cmd-item/cmd-zaprod.c | 435 + src/cmd-item/cmd-zaprod.h | 7 + src/cmd-item/cmd-zapwand.c | 467 ++ src/cmd-item/cmd-zapwand.h | 7 + src/cmd-magiceat.c | 587 -- src/cmd-magiceat.h | 1 - src/cmd-mane.c | 985 --- src/cmd-mane.h | 4 - src/cmd-pet.c | 1089 --- src/cmd-pet.h | 8 - src/cmd-quaff.c | 615 -- src/cmd-quaff.h | 4 - src/cmd-read.c | 640 -- src/cmd-read.h | 4 - src/cmd-smith.c | 1517 ---- src/cmd-smith.h | 3 - src/cmd-spell.c | 1446 ---- src/cmd-spell.h | 24 - src/cmd-usestaff.c | 447 -- src/cmd-usestaff.h | 3 - src/cmd-visual/cmd-draw.c | 287 + src/cmd-visual/cmd-draw.h | 8 + src/cmd-visual/cmd-map.c | 65 + src/cmd-visual/cmd-map.h | 5 + src/cmd-visual/cmd-visuals.c | 443 ++ src/cmd-visual/cmd-visuals.h | 5 + src/cmd-zaprod.c | 417 - src/cmd-zaprod.h | 3 - src/cmd-zapwand.c | 468 -- src/cmd-zapwand.h | 3 - src/cmd2.c | 2923 ------- src/cmd4.c | 8291 -------------------- src/combat/attack-accuracy.c | 157 + src/combat/attack-accuracy.h | 10 + src/combat/attack-criticality.c | 168 + src/combat/attack-criticality.h | 8 + src/combat/attack-power-table.c | 215 + src/combat/attack-power-table.h | 11 + src/combat/aura-counterattack.c | 221 + src/combat/aura-counterattack.h | 6 + src/combat/combat-options-type.h | 36 + src/combat/hallucination-attacks-table.c | 134 + src/combat/hallucination-attacks-table.h | 11 + src/combat/martial-arts-table.c | 23 + src/combat/martial-arts-table.h | 19 + src/combat/shoot.c | 1186 +++ src/combat/shoot.h | 13 + src/combat/slaying.c | 202 + src/combat/slaying.h | 10 + src/core/asking-player.c | 410 + src/core/asking-player.h | 20 + src/core/disturbance.c | 48 + src/core/disturbance.h | 5 + src/core/game-closer.c | 109 + src/core/game-closer.h | 5 + src/core/game-play.c | 391 + src/core/game-play.h | 5 + src/core/hp-mp-processor.c | 447 ++ src/core/hp-mp-processor.h | 6 + src/core/hp-mp-regenerator.c | 236 + src/core/hp-mp-regenerator.h | 11 + src/core/magic-effects-timeout-reducer.c | 224 + src/core/magic-effects-timeout-reducer.h | 5 + src/core/object-compressor.c | 130 + src/core/object-compressor.h | 5 + src/core/output-updater.c | 16 + src/core/output-updater.h | 5 + src/core/player-processor.c | 414 + src/core/player-processor.h | 9 + src/core/player-redraw-types.h | 32 + src/core/player-update-types.h | 21 + src/core/scores.c | 946 +++ src/core/scores.h | 51 + src/core/show-file.c | 524 ++ src/core/show-file.h | 6 + src/core/special-internal-keys.h | 9 + src/core/speed-table.c | 51 + src/core/speed-table.h | 13 + src/core/status-reseter.c | 93 + src/core/status-reseter.h | 5 + src/core/stuff-handler.c | 71 + src/core/stuff-handler.h | 11 + src/core/turn-compensator.c | 78 + src/core/turn-compensator.h | 6 + src/core/visuals-reseter.c | 42 + src/core/visuals-reseter.h | 5 + src/core/window-redrawer.c | 292 + src/core/window-redrawer.h | 21 + src/defines.h | 4564 ----------- src/dungeon.c | 6241 --------------- src/dungeon/dungeon-flag-types.h | 38 + src/dungeon/dungeon-processor.c | 229 + src/dungeon/dungeon-processor.h | 5 + src/dungeon/dungeon.c | 104 + src/dungeon/dungeon.h | 87 + src/dungeon/quest-completion-checker.c | 179 + src/dungeon/quest-completion-checker.h | 6 + src/dungeon/quest-monster-placer.c | 81 + src/dungeon/quest-monster-placer.h | 5 + src/dungeon/quest.c | 345 + src/dungeon/quest.h | 97 + src/effect/effect-characteristics.h | 24 + src/effect/effect-feature.c | 436 + src/effect/effect-feature.h | 5 + src/effect/effect-item.c | 256 + src/effect/effect-item.h | 5 + src/effect/effect-monster-charm.c | 395 + src/effect/effect-monster-charm.h | 14 + src/effect/effect-monster-curse.c | 65 + src/effect/effect-monster-curse.h | 10 + src/effect/effect-monster-evil.c | 267 + src/effect/effect-monster-evil.h | 18 + src/effect/effect-monster-lite-dark.c | 71 + src/effect/effect-monster-lite-dark.h | 9 + src/effect/effect-monster-oldies.c | 309 + src/effect/effect-monster-oldies.h | 16 + src/effect/effect-monster-psi.c | 264 + src/effect/effect-monster-psi.h | 9 + src/effect/effect-monster-resist-hurt.c | 531 ++ src/effect/effect-monster-resist-hurt.h | 31 + src/effect/effect-monster-spirit.c | 164 + src/effect/effect-monster-spirit.h | 9 + src/effect/effect-monster-switcher.c | 460 ++ src/effect/effect-monster-switcher.h | 7 + src/effect/effect-monster-util.c | 83 + src/effect/effect-monster-util.h | 45 + src/effect/effect-monster.c | 600 ++ src/effect/effect-monster.h | 6 + src/effect/effect-player-curse.c | 57 + src/effect/effect-player-curse.h | 9 + src/effect/effect-player-oldies.c | 53 + src/effect/effect-player-oldies.h | 9 + src/effect/effect-player-resist-hurt.c | 540 ++ src/effect/effect-player-resist-hurt.h | 29 + src/effect/effect-player-spirit.c | 140 + src/effect/effect-player-spirit.h | 8 + src/effect/effect-player-switcher.c | 269 + src/effect/effect-player-switcher.h | 6 + src/effect/effect-player-util.h | 19 + src/effect/effect-player.c | 214 + src/effect/effect-player.h | 9 + src/effect/effect-processor.c | 793 ++ src/effect/effect-processor.h | 6 + src/effect/spells-effect-util.c | 19 + src/effect/spells-effect-util.h | 21 + src/effects.c | 4613 ----------- src/externs.h | 1323 ---- src/feature.c | 27 - src/feature.h | 3 - src/files.c | 7364 ----------------- src/flavor.c | 2823 ------- src/flavor/flag-inscriptions-table.c | 130 + src/flavor/flag-inscriptions-table.h | 41 + src/flavor/flavor-describer.c | 512 ++ src/flavor/flavor-describer.h | 5 + src/flavor/flavor-util.c | 469 ++ src/flavor/flavor-util.h | 52 + src/flavor/named-item-describer.c | 392 + src/flavor/named-item-describer.h | 6 + src/flavor/object-flavor-types.h | 12 + src/flavor/object-flavor.c | 292 + src/flavor/object-flavor.h | 10 + src/flavor/tval-description-switcher.c | 426 + src/flavor/tval-description-switcher.h | 6 + src/floor-events.c | 115 - src/floor-events.h | 4 - src/floor-generate.c | 2150 ----- src/floor-generate.h | 3 - src/floor-save.c | 1518 ---- src/floor-save.h | 5 - src/floor-streams.c | 455 -- src/floor-streams.h | 20 - src/floor.h | 15 - src/floor/cave-generator.c | 379 + src/floor/cave-generator.h | 5 + src/floor/cave.c | 133 + src/floor/cave.h | 22 + src/floor/dungeon-tunnel-util.c | 12 + src/floor/dungeon-tunnel-util.h | 11 + src/floor/fixed-map-generator.c | 449 ++ src/floor/fixed-map-generator.h | 20 + src/floor/floor-allocation-types.h | 17 + src/floor/floor-base-definitions.h | 47 + src/floor/floor-changer.c | 397 + src/floor/floor-changer.h | 5 + src/floor/floor-events.c | 324 + src/floor/floor-events.h | 10 + src/floor/floor-generator-util.h | 3 + src/floor/floor-generator.c | 416 + src/floor/floor-generator.h | 7 + src/floor/floor-leaver.c | 422 + src/floor/floor-leaver.h | 5 + src/floor/floor-mode-changer.c | 9 + src/floor/floor-mode-changer.h | 19 + src/floor/floor-object.c | 633 ++ src/floor/floor-object.h | 16 + src/floor/floor-save-util.c | 13 + src/floor/floor-save-util.h | 26 + src/floor/floor-save.c | 214 + src/floor/floor-save.h | 12 + src/floor/floor-streams.c | 485 ++ src/floor/floor-streams.h | 9 + src/floor/floor-town.c | 7 + src/floor/floor-town.h | 19 + src/floor/floor-util.c | 210 + src/floor/floor-util.h | 11 + src/floor/geometry.c | 245 + src/floor/geometry.h | 42 + src/floor/line-of-sight.c | 201 + src/floor/line-of-sight.h | 5 + src/floor/object-allocator.c | 200 + src/floor/object-allocator.h | 7 + src/floor/object-scanner.c | 167 + src/floor/object-scanner.h | 7 + src/floor/pattern-walk.c | 245 + src/floor/pattern-walk.h | 6 + src/floor/sight-definitions.h | 31 + src/floor/tunnel-generator.c | 433 + src/floor/tunnel-generator.h | 8 + src/floor/wild.c | 905 +++ src/floor/wild.h | 49 + src/game-option/auto-destruction-options.c | 12 + src/game-option/auto-destruction-options.h | 14 + src/game-option/birth-options.c | 23 + src/game-option/birth-options.h | 21 + src/game-option/cheat-options.c | 12 + src/game-option/cheat-options.h | 14 + src/game-option/cheat-types.h | 8 + src/game-option/disturbance-options.c | 18 + src/game-option/disturbance-options.h | 20 + src/game-option/game-play-options.c | 14 + src/game-option/game-play-options.h | 16 + src/game-option/input-options.c | 21 + src/game-option/input-options.h | 23 + src/game-option/keymap-directory-getter.c | 42 + src/game-option/keymap-directory-getter.h | 9 + src/game-option/map-screen-options.c | 17 + src/game-option/map-screen-options.h | 19 + src/game-option/option-flags.c | 6 + src/game-option/option-flags.h | 8 + src/game-option/option-types-table.c | 317 + src/game-option/option-types-table.h | 31 + src/game-option/play-record-options.c | 17 + src/game-option/play-record-options.h | 20 + src/game-option/runtime-arguments.c | 11 + src/game-option/runtime-arguments.h | 13 + src/game-option/special-options.c | 12 + src/game-option/special-options.h | 14 + src/game-option/text-display-options.c | 16 + src/game-option/text-display-options.h | 22 + src/gameoption.c | 637 -- src/gameoption.h | 171 - src/gamevalue.h | 133 - src/generate.h | 105 - src/geometry.c | 20 - src/geometry.h | 19 - src/grid.c | 5630 ------------- src/grid.h | 290 - src/grid/door.c | 205 + src/grid/door.h | 9 + src/grid/feature-flag-types.h | 74 + src/grid/feature-generator.c | 169 + src/grid/feature-generator.h | 10 + src/grid/feature.c | 291 + src/grid/feature.h | 126 + src/grid/grid.c | 1424 ++++ src/grid/grid.h | 256 + src/grid/lighting-colors-table.c | 62 + src/grid/lighting-colors-table.h | 8 + src/grid/object-placer.c | 104 + src/grid/object-placer.h | 6 + src/grid/stair.c | 78 + src/grid/stair.h | 6 + src/grid/trap.c | 635 ++ src/grid/trap.h | 56 + src/h-basic.h | 34 - src/h-config.h | 264 - src/h-define.h | 139 - src/h-system.h | 121 - src/h-type.h | 300 - src/history.c | 1561 ---- src/history.h | 21 - src/inet.c | 523 -- src/info-reader/artifact-reader.c | 157 + src/info-reader/artifact-reader.h | 6 + src/info-reader/dungeon-info-tokens-table.c | 41 + src/info-reader/dungeon-info-tokens-table.h | 7 + src/info-reader/dungeon-reader.c | 310 + src/info-reader/dungeon-reader.h | 6 + src/info-reader/ego-reader.c | 141 + src/info-reader/ego-reader.h | 6 + src/info-reader/feature-info-tokens-table.c | 124 + src/info-reader/feature-info-tokens-table.h | 6 + src/info-reader/feature-reader.c | 475 ++ src/info-reader/feature-reader.h | 10 + src/info-reader/fixed-map-parser.c | 282 + src/info-reader/fixed-map-parser.h | 7 + src/info-reader/general-parser.c | 273 + src/info-reader/general-parser.h | 23 + src/info-reader/info-reader-util.c | 154 + src/info-reader/info-reader-util.h | 20 + src/info-reader/kind-info-tokens-table.c | 190 + src/info-reader/kind-info-tokens-table.h | 9 + src/info-reader/kind-reader.c | 205 + src/info-reader/kind-reader.h | 6 + src/info-reader/magic-reader.c | 108 + src/info-reader/magic-reader.h | 6 + src/info-reader/parse-error-types.h | 16 + src/info-reader/race-info-tokens-table.c | 471 ++ src/info-reader/race-info-tokens-table.h | 29 + src/info-reader/race-reader.c | 305 + src/info-reader/race-reader.h | 6 + src/info-reader/random-grid-effect-types.h | 12 + src/info-reader/skill-reader.c | 52 + src/info-reader/skill-reader.h | 6 + src/info-reader/vault-reader.c | 56 + src/info-reader/vault-reader.h | 6 + src/init.h | 140 - src/init1.c | 5025 ------------ src/init2.c | 1953 ----- src/inventory/floor-item-getter.c | 847 ++ src/inventory/floor-item-getter.h | 6 + src/inventory/inventory-curse.c | 375 + src/inventory/inventory-curse.h | 6 + src/inventory/inventory-damage.c | 94 + src/inventory/inventory-damage.h | 10 + src/inventory/inventory-describer.c | 152 + src/inventory/inventory-describer.h | 6 + src/inventory/inventory-object.c | 431 + src/inventory/inventory-object.h | 13 + src/inventory/inventory-slot-types.h | 20 + src/inventory/inventory-util.c | 304 + src/inventory/inventory-util.h | 16 + src/inventory/item-getter.c | 615 ++ src/inventory/item-getter.h | 6 + src/inventory/item-selection-util.c | 49 + src/inventory/item-selection-util.h | 71 + src/inventory/pack-overflow.c | 36 + src/inventory/pack-overflow.h | 5 + src/inventory/player-inventory.c | 298 + src/inventory/player-inventory.h | 9 + src/inventory/recharge-processor.c | 122 + src/inventory/recharge-processor.h | 5 + src/io-dump/character-dump.c | 585 ++ src/io-dump/character-dump.h | 6 + src/io-dump/dump-remover.c | 99 + src/io-dump/dump-remover.h | 5 + src/io-dump/dump-util.c | 303 + src/io-dump/dump-util.h | 23 + src/io-dump/player-status-dump.c | 65 + src/io-dump/player-status-dump.h | 6 + src/io-dump/random-art-info-dumper.c | 116 + src/io-dump/random-art-info-dumper.h | 5 + src/io-dump/special-class-dump.c | 254 + src/io-dump/special-class-dump.h | 5 + src/io/chuukei.c | 938 +++ src/io/chuukei.h | 18 + src/io/command-repeater.c | 57 + src/io/command-repeater.h | 7 + src/io/cursor.c | 147 + src/io/cursor.h | 8 + src/io/exit-panic.c | 40 + src/io/exit-panic.h | 8 + src/io/files-util.c | 319 + src/io/files-util.h | 33 + src/io/gf-descriptions.c | 109 + src/io/gf-descriptions.h | 13 + src/io/inet.c | 312 + src/io/inet.h | 12 + src/io/input-key-acceptor.c | 397 + src/io/input-key-acceptor.h | 31 + src/io/input-key-processor.c | 647 ++ src/io/input-key-processor.h | 6 + src/io/input-key-requester.c | 347 + src/io/input-key-requester.h | 19 + src/io/interpret-pref-file.c | 532 ++ src/io/interpret-pref-file.h | 10 + src/io/mutations-dump.c | 314 + src/io/mutations-dump.h | 5 + src/io/pref-file-expressor.c | 212 + src/io/pref-file-expressor.h | 6 + src/io/read-pref-file.c | 384 + src/io/read-pref-file.h | 17 + src/io/report.c | 527 ++ src/io/report.h | 12 + src/io/screen-util.c | 92 + src/io/screen-util.h | 7 + src/io/signal-handlers.c | 279 + src/io/signal-handlers.h | 8 + src/io/store-key-processor.c | 272 + src/io/store-key-processor.h | 7 + src/io/tokenizer.c | 54 + src/io/tokenizer.h | 7 + src/io/uid-checker.c | 64 + src/io/uid-checker.h | 6 + src/io/write-diary.c | 414 + src/io/write-diary.h | 53 + src/japanese.c | 538 -- src/knowledge/knowledge-autopick.c | 85 + src/knowledge/knowledge-autopick.h | 6 + src/knowledge/knowledge-experiences.c | 173 + src/knowledge/knowledge-experiences.h | 7 + src/knowledge/knowledge-features.c | 402 + src/knowledge/knowledge-features.h | 6 + src/knowledge/knowledge-inventory.c | 300 + src/knowledge/knowledge-inventory.h | 5 + src/knowledge/knowledge-items.c | 450 ++ src/knowledge/knowledge-items.h | 6 + src/knowledge/knowledge-monsters.c | 547 ++ src/knowledge/knowledge-monsters.h | 8 + src/knowledge/knowledge-mutations.c | 28 + src/knowledge/knowledge-mutations.h | 5 + src/knowledge/knowledge-quests.c | 323 + src/knowledge/knowledge-quests.h | 8 + src/knowledge/knowledge-self.c | 211 + src/knowledge/knowledge-self.h | 7 + src/knowledge/knowledge-uniques.c | 164 + src/knowledge/knowledge-uniques.h | 5 + src/knowledge/lighting-level-table.c | 11 + src/knowledge/lighting-level-table.h | 6 + src/knowledge/monster-group-table.c | 200 + src/knowledge/monster-group-table.h | 6 + src/knowledge/object-group-table.c | 155 + src/knowledge/object-group-table.h | 10 + src/load.c | 4191 ---------- src/load/angband-version-comparer.c | 63 + src/load/angband-version-comparer.h | 6 + src/load/birth-loader.c | 59 + src/load/birth-loader.h | 3 + src/load/dummy-loader.c | 81 + src/load/dummy-loader.h | 9 + src/load/dungeon-loader.c | 143 + src/load/dungeon-loader.h | 5 + src/load/extra-loader.c | 41 + src/load/extra-loader.h | 5 + src/load/floor-loader.c | 354 + src/load/floor-loader.h | 7 + src/load/info-loader.c | 89 + src/load/info-loader.h | 6 + src/load/inventory-loader.c | 84 + src/load/inventory-loader.h | 5 + src/load/item-loader.c | 315 + src/load/item-loader.h | 7 + src/load/load-util.c | 159 + src/load/load-util.h | 19 + src/load/load-v1-3-0.c | 13 + src/load/load-v1-3-0.h | 5 + src/load/load-v1-5-0.c | 780 ++ src/load/load-v1-5-0.h | 42 + src/load/load-v1-7-0.c | 51 + src/load/load-v1-7-0.h | 8 + src/load/load-zangband.c | 315 + src/load/load-zangband.h | 26 + src/load/load.c | 366 + src/load/load.h | 6 + src/load/lore-loader.c | 98 + src/load/lore-loader.h | 5 + src/load/monster-loader.c | 142 + src/load/monster-loader.h | 6 + src/load/old-feature-types.h | 12 + src/load/option-loader.c | 111 + src/load/option-loader.h | 3 + src/load/player-attack-loader.c | 49 + src/load/player-attack-loader.h | 8 + src/load/player-info-loader.c | 480 ++ src/load/player-info-loader.h | 10 + src/load/quest-loader.c | 142 + src/load/quest-loader.h | 8 + src/load/savedata-flag-types.h | 52 + src/load/store-loader.c | 132 + src/load/store-loader.h | 6 + src/load/world-loader.c | 198 + src/load/world-loader.h | 12 + src/locale/english.c | 149 + src/locale/english.h | 6 + src/locale/japanese.c | 541 ++ src/locale/japanese.h | 17 + src/locale/language-switcher.h | 7 + src/lore/combat-types-setter.c | 194 + src/lore/combat-types-setter.h | 7 + src/lore/lore-calculator.c | 151 + src/lore/lore-calculator.h | 11 + src/lore/lore-store.c | 122 + src/lore/lore-store.h | 6 + src/lore/lore-util.c | 48 + src/lore/lore-util.h | 58 + src/lore/magic-types-setter.c | 534 ++ src/lore/magic-types-setter.h | 13 + src/lore/monster-lore.c | 214 + src/lore/monster-lore.h | 5 + src/maid-x11.c | 34 +- src/main-cap.c | 38 +- src/main-dos.c | 2197 ------ src/main-gcu.c | 286 +- src/main-ibm.c | 1415 ---- src/main-mac.c | 7420 ------------------ src/main-win.c | 8032 +++++++------------ src/main-x11.c | 1819 +---- src/main-xaw.c | 38 +- src/main.c | 356 +- src/main/angband-headers.c | 11 + src/main/angband-headers.h | 44 + src/main/angband-initializer.c | 267 + src/main/angband-initializer.h | 21 + src/main/game-data-initializer.c | 192 + src/main/game-data-initializer.h | 8 + src/main/info-initializer.c | 370 + src/main/info-initializer.h | 14 + src/main/init-error-messages-table.c | 18 + src/main/init-error-messages-table.h | 6 + src/main/music-definitions-table.c | 27 + src/main/music-definitions-table.h | 28 + src/main/sound-definitions-table.c | 73 + src/main/sound-definitions-table.h | 73 + src/main/sound-of-music.c | 124 + src/main/sound-of-music.h | 8 + src/main/x11-gamma-builder.c | 132 + src/main/x11-gamma-builder.h | 4 + src/main/x11-type-string.c | 42 + src/main/x11-type-string.h | 5 + src/makefile.bcc | 2 +- src/makefile.dos | 174 - src/makefile.ibm | 85 - src/makefile.std | 26 +- src/market/arena-info-table.c | 62 + src/market/arena-info-table.h | 8 + src/market/arena.c | 388 + src/market/arena.h | 7 + src/market/articles-on-sale.c | 564 ++ src/market/articles-on-sale.h | 8 + src/market/bounty-prize-table.c | 31 + src/market/bounty-prize-table.h | 15 + src/market/bounty.c | 353 + src/market/bounty.h | 10 + src/market/building-actions-table.h | 56 + src/market/building-craft-armor.c | 83 + src/market/building-craft-armor.h | 5 + src/market/building-craft-fix.c | 291 + src/market/building-craft-fix.h | 5 + src/market/building-craft-weapon.c | 426 + src/market/building-craft-weapon.h | 5 + src/market/building-enchanter.c | 87 + src/market/building-enchanter.h | 6 + src/market/building-initializer.c | 97 + src/market/building-initializer.h | 6 + src/market/building-monster.c | 207 + src/market/building-monster.h | 5 + src/market/building-quest.c | 126 + src/market/building-quest.h | 5 + src/market/building-recharger.c | 273 + src/market/building-recharger.h | 6 + src/market/building-service.c | 144 + src/market/building-service.h | 8 + src/market/building-util.c | 30 + src/market/building-util.h | 6 + src/market/gold-magnification-table.c | 236 + src/market/gold-magnification-table.h | 5 + src/market/play-gamble.c | 323 + src/market/play-gamble.h | 5 + src/market/poker.c | 693 ++ src/market/poker.h | 3 + src/melee.h | 42 - src/melee/melee-postprocess.c | 284 + src/melee/melee-postprocess.h | 6 + src/melee/melee-spell-flags-checker.c | 377 + src/melee/melee-spell-flags-checker.h | 6 + src/melee/melee-spell-util.c | 30 + src/melee/melee-spell-util.h | 34 + src/melee/melee-spell.c | 154 + src/melee/melee-spell.h | 5 + src/melee/melee-switcher.c | 267 + src/melee/melee-switcher.h | 15 + src/melee/melee-util.c | 34 + src/melee/melee-util.h | 44 + src/melee/monster-attack-monster.c | 326 + src/melee/monster-attack-monster.h | 5 + src/melee1.c | 3658 --------- src/mind.c | 2100 ----- src/mind/drs-types.h | 26 + src/mind/mind-archer.c | 170 + src/mind/mind-archer.h | 5 + src/mind/mind-berserker.c | 83 + src/mind/mind-berserker.h | 6 + src/mind/mind-blue-mage.c | 115 + src/mind/mind-blue-mage.h | 13 + src/mind/mind-cavalry.c | 69 + src/mind/mind-cavalry.h | 5 + src/mind/mind-chaos-warrior.c | 121 + src/mind/mind-chaos-warrior.h | 5 + src/mind/mind-explanations-table.c | 299 + src/mind/mind-explanations-table.h | 20 + src/mind/mind-force-trainer.c | 339 + src/mind/mind-force-trainer.h | 13 + src/mind/mind-hobbit.c | 17 + src/mind/mind-hobbit.h | 5 + src/mind/mind-info.c | 239 + src/mind/mind-info.h | 5 + src/mind/mind-mage.c | 198 + src/mind/mind-mage.h | 5 + src/mind/mind-magic-eater.c | 86 + src/mind/mind-magic-eater.h | 5 + src/mind/mind-magic-resistance.c | 49 + src/mind/mind-magic-resistance.h | 5 + src/mind/mind-mindcrafter.c | 259 + src/mind/mind-mindcrafter.h | 8 + src/mind/mind-mirror-master.c | 543 ++ src/mind/mind-mirror-master.h | 17 + src/mind/mind-monk.c | 87 + src/mind/mind-monk.h | 5 + src/mind/mind-ninja.c | 471 ++ src/mind/mind-ninja.h | 15 + src/mind/mind-numbers.h | 90 + src/mind/mind-power-getter.c | 292 + src/mind/mind-power-getter.h | 5 + src/mind/mind-priest.c | 139 + src/mind/mind-priest.h | 5 + src/mind/mind-samurai.c | 483 ++ src/mind/mind-samurai.h | 13 + src/mind/mind-sniper.c | 598 ++ src/mind/mind-sniper.h | 11 + src/mind/mind-types.h | 9 + src/mind/mind-warrior-mage.c | 37 + src/mind/mind-warrior-mage.h | 6 + src/mind/mind-warrior.c | 59 + src/mind/mind-warrior.h | 6 + src/mind/mind-weaponsmith.c | 49 + src/mind/mind-weaponsmith.h | 6 + src/mind/monk-attack.c | 267 + src/mind/monk-attack.h | 7 + src/mind/snipe-types.h | 20 + src/mind/stances-table.c | 21 + src/mind/stances-table.h | 13 + src/monster-attack/insults-moans.c | 23 + src/monster-attack/insults-moans.h | 9 + src/monster-attack/monster-attack-describer.c | 243 + src/monster-attack/monster-attack-describer.h | 5 + src/monster-attack/monster-attack-effect.h | 43 + src/monster-attack/monster-attack-player.c | 498 ++ src/monster-attack/monster-attack-player.h | 5 + src/monster-attack/monster-attack-processor.c | 133 + src/monster-attack/monster-attack-processor.h | 8 + src/monster-attack/monster-attack-status.c | 180 + src/monster-attack/monster-attack-status.h | 11 + src/monster-attack/monster-attack-switcher.c | 404 + src/monster-attack/monster-attack-switcher.h | 6 + src/monster-attack/monster-attack-types.c | 179 + src/monster-attack/monster-attack-types.h | 45 + src/monster-attack/monster-attack-util.c | 27 + src/monster-attack/monster-attack-util.h | 40 + src/monster-attack/monster-eating.c | 280 + src/monster-attack/monster-eating.h | 15 + src/monster-floor/monster-death-util.c | 50 + src/monster-floor/monster-death-util.h | 21 + src/monster-floor/monster-death.c | 381 + src/monster-floor/monster-death.h | 6 + src/monster-floor/monster-direction.c | 255 + src/monster-floor/monster-direction.h | 6 + src/monster-floor/monster-dist-offsets.c | 113 + src/monster-floor/monster-dist-offsets.h | 6 + src/monster-floor/monster-generator.c | 487 ++ src/monster-floor/monster-generator.h | 14 + src/monster-floor/monster-lite-util.c | 12 + src/monster-floor/monster-lite-util.h | 12 + src/monster-floor/monster-lite.c | 338 + src/monster-floor/monster-lite.h | 6 + src/monster-floor/monster-move.c | 508 ++ src/monster-floor/monster-move.h | 10 + src/monster-floor/monster-object.c | 201 + src/monster-floor/monster-object.h | 7 + src/monster-floor/monster-remover.c | 160 + src/monster-floor/monster-remover.h | 7 + src/monster-floor/monster-runaway.c | 107 + src/monster-floor/monster-runaway.h | 6 + src/monster-floor/monster-safety-hiding.c | 182 + src/monster-floor/monster-safety-hiding.h | 7 + src/monster-floor/monster-summon.c | 152 + src/monster-floor/monster-summon.h | 10 + src/monster-floor/monster-sweep-grid.c | 426 + src/monster-floor/monster-sweep-grid.h | 6 + src/monster-floor/one-monster-placer.c | 429 + src/monster-floor/one-monster-placer.h | 5 + src/monster-floor/place-monster-types.h | 20 + src/monster-floor/quantum-effect.c | 101 + src/monster-floor/quantum-effect.h | 5 + src/monster-floor/special-death-switcher.c | 392 + src/monster-floor/special-death-switcher.h | 6 + src/monster-process.c | 3506 --------- src/monster-race/monster-race-hook.c | 893 +++ src/monster-race/monster-race-hook.h | 58 + src/monster-race/monster-race.c | 12 + src/monster-race/monster-race.h | 10 + src/monster-race/race-flags-ability1.h | 36 + src/monster-race/race-flags-ability2.h | 36 + src/monster-race/race-flags-resistance.h | 45 + src/monster-race/race-flags1.h | 36 + src/monster-race/race-flags2.h | 36 + src/monster-race/race-flags3.h | 36 + src/monster-race/race-flags4.h | 36 + src/monster-race/race-flags7.h | 29 + src/monster-race/race-flags8.h | 16 + src/monster-race/race-flags9.h | 36 + src/monster-race/race-indice-types.h | 155 + src/monster-spell.h | 158 - src/monster-status.c | 1385 ---- src/monster-status.h | 6 - src/monster.h | 57 - src/monster/horror-descriptions.c | 205 + src/monster/horror-descriptions.h | 17 + src/monster/monster-compaction.c | 148 + src/monster/monster-compaction.h | 5 + src/monster/monster-describer.c | 519 ++ src/monster/monster-describer.h | 7 + src/monster/monster-description-types.h | 17 + src/monster/monster-flag-types.h | 20 + src/monster/monster-info.c | 268 + src/monster/monster-info.h | 24 + src/monster/monster-list.c | 435 + src/monster/monster-list.h | 12 + src/monster/monster-processor-util.c | 370 + src/monster/monster-processor-util.h | 61 + src/monster/monster-processor.c | 611 ++ src/monster/monster-processor.h | 6 + src/monster/monster-status-setter.c | 402 + src/monster/monster-status-setter.h | 17 + src/monster/monster-status.c | 1039 +++ src/monster/monster-status.h | 28 + src/monster/monster-timed-effect-types.h | 12 + src/monster/monster-update.c | 563 ++ src/monster/monster-update.h | 13 + src/monster/monster-util.c | 369 + src/monster/monster-util.h | 14 + src/monster/smart-learn-types.h | 36 + src/monster1.c | 3238 -------- src/monster2.c | 4042 ---------- src/monsterrace-hook.c | 774 -- src/monsterrace-hook.h | 70 - src/mspell/assign-monster-spell.c | 251 + src/mspell/assign-monster-spell.h | 6 + src/mspell/element-resistance-checker.c | 231 + src/mspell/element-resistance-checker.h | 7 + src/mspell/high-resistance-checker.c | 206 + src/mspell/high-resistance-checker.h | 7 + src/mspell/improper-mspell-remover.c | 57 + src/mspell/improper-mspell-remover.h | 5 + src/mspell/monster-power-table.c | 209 + src/mspell/monster-power-table.h | 19 + src/mspell/mspell-attack-util.c | 23 + src/mspell/mspell-attack-util.h | 39 + src/mspell/mspell-attack.c | 370 + src/mspell/mspell-attack.h | 5 + src/mspell/mspell-ball.c | 336 + src/mspell/mspell-ball.h | 16 + src/mspell/mspell-bolt.c | 308 + src/mspell/mspell-bolt.h | 15 + src/mspell/mspell-breath.c | 211 + src/mspell/mspell-breath.h | 5 + src/mspell/mspell-checker.c | 322 + src/mspell/mspell-checker.h | 13 + src/mspell/mspell-curse.c | 151 + src/mspell/mspell-curse.h | 9 + src/mspell/mspell-damage-calculator.c | 471 ++ src/mspell/mspell-damage-calculator.h | 19 + src/mspell/mspell-dispel.c | 136 + src/mspell/mspell-dispel.h | 5 + src/mspell/mspell-floor.c | 414 + src/mspell/mspell-floor.h | 14 + src/mspell/mspell-judgement.c | 330 + src/mspell/mspell-judgement.h | 10 + src/mspell/mspell-learn-checker.c | 20 + src/mspell/mspell-learn-checker.h | 5 + src/mspell/mspell-lite.c | 199 + src/mspell/mspell-lite.h | 11 + src/mspell/mspell-mask-definitions.h | 103 + src/mspell/mspell-particularity.c | 88 + src/mspell/mspell-particularity.h | 7 + src/mspell/mspell-selector.c | 378 + src/mspell/mspell-selector.h | 6 + src/mspell/mspell-special.c | 242 + src/mspell/mspell-special.h | 5 + src/mspell/mspell-status.c | 564 ++ src/mspell/mspell-status.h | 17 + src/mspell/mspell-summon.c | 682 ++ src/mspell/mspell-summon.h | 21 + src/mspell/mspell-type.h | 100 + src/mspell/mspell-util.c | 104 + src/mspell/mspell-util.h | 18 + src/mspell/smart-mspell-util.c | 31 + src/mspell/smart-mspell-util.h | 16 + src/mspell/specified-summon.c | 209 + src/mspell/specified-summon.h | 12 + src/mspell/summon-checker.c | 221 + src/mspell/summon-checker.h | 5 + src/mspells1.c | 1830 ----- src/mspells2.c | 764 -- src/mspells3.c | 1588 ---- src/mspells4.c | 4154 ---------- src/mutation.c | 2372 ------ src/mutation.h | 9 - src/mutation/gain-mutation-switcher.c | 596 ++ src/mutation/gain-mutation-switcher.h | 6 + src/mutation/lose-mutation-switcher.c | 593 ++ src/mutation/lose-mutation-switcher.h | 6 + src/mutation/mutation-calculator.c | 55 + src/mutation/mutation-calculator.h | 5 + src/mutation/mutation-flag-types.h | 106 + src/mutation/mutation-investor-remover.c | 290 + src/mutation/mutation-investor-remover.h | 7 + src/mutation/mutation-processor.c | 493 ++ src/mutation/mutation-processor.h | 6 + src/mutation/mutation-techniques.c | 65 + src/mutation/mutation-techniques.h | 5 + src/mutation/mutation-util.c | 11 + src/mutation/mutation-util.h | 14 + src/mutation/mutation.c | 1180 +++ src/object-activation/activation-bolt-ball.c | 346 + src/object-activation/activation-bolt-ball.h | 33 + src/object-activation/activation-breath.c | 80 + src/object-activation/activation-breath.h | 7 + src/object-activation/activation-charm.c | 46 + src/object-activation/activation-charm.h | 9 + src/object-activation/activation-genocide.c | 17 + src/object-activation/activation-genocide.h | 6 + src/object-activation/activation-others.c | 348 + src/object-activation/activation-others.h | 39 + src/object-activation/activation-resistance.c | 141 + src/object-activation/activation-resistance.h | 11 + src/object-activation/activation-switcher.c | 355 + src/object-activation/activation-switcher.h | 6 + src/object-activation/activation-teleport.c | 82 + src/object-activation/activation-teleport.h | 10 + src/object-activation/activation-util.c | 10 + src/object-activation/activation-util.h | 15 + src/object-boost.c | 456 -- src/object-boost.h | 18 - src/object-broken.c | 168 - src/object-broken.h | 2 - src/object-curse.c | 99 - src/object-curse.h | 2 - src/object-enchant/activation-info-table.c | 142 + src/object-enchant/activation-info-table.h | 17 + src/object-enchant/apply-magic-accessory.c | 692 ++ src/object-enchant/apply-magic-accessory.h | 5 + src/object-enchant/apply-magic-armor.c | 448 ++ src/object-enchant/apply-magic-armor.h | 5 + src/object-enchant/apply-magic-others.c | 221 + src/object-enchant/apply-magic-others.h | 6 + src/object-enchant/apply-magic-weapon.c | 261 + src/object-enchant/apply-magic-weapon.h | 5 + src/object-enchant/apply-magic.c | 366 + src/object-enchant/apply-magic.h | 5 + src/object-enchant/dragon-breaths-table.c | 25 + src/object-enchant/dragon-breaths-table.h | 12 + src/object-enchant/item-apply-magic.h | 13 + src/object-enchant/item-feeling.h | 19 + src/object-enchant/object-boost.c | 458 ++ src/object-enchant/object-boost.h | 18 + src/object-enchant/object-curse.c | 114 + src/object-enchant/object-curse.h | 6 + src/object-enchant/object-ego.c | 54 + src/object-enchant/object-ego.h | 246 + src/object-enchant/old-ego-extra-values.h | 12 + src/object-enchant/special-object-flags.h | 14 + src/object-enchant/tr-types.h | 151 + src/object-enchant/trc-types.h | 32 + src/object-enchant/trg-types.h | 22 + src/object-enchant/vorpal-weapon.c | 89 + src/object-enchant/vorpal-weapon.h | 6 + src/object-hook.c | 959 --- src/object-hook.h | 53 - src/object-hook/hook-armor.c | 53 + src/object-hook/hook-armor.h | 7 + src/object-hook/hook-bow.c | 55 + src/object-hook/hook-bow.h | 7 + src/object-hook/hook-checker.c | 11 + src/object-hook/hook-checker.h | 8 + src/object-hook/hook-enchant.c | 111 + src/object-hook/hook-enchant.h | 10 + src/object-hook/hook-expendable.c | 142 + src/object-hook/hook-expendable.h | 11 + src/object-hook/hook-magic.c | 136 + src/object-hook/hook-magic.h | 9 + src/object-hook/hook-perception.c | 85 + src/object-hook/hook-perception.h | 9 + src/object-hook/hook-quest.c | 62 + src/object-hook/hook-quest.h | 6 + src/object-hook/hook-weapon.c | 307 + src/object-hook/hook-weapon.h | 20 + src/object-use/quaff-execution.c | 624 ++ src/object-use/quaff-execution.h | 5 + src/object-use/read-execution.c | 520 ++ src/object-use/read-execution.h | 5 + src/object/item-tester-hooker.c | 43 + src/object/item-tester-hooker.h | 8 + src/object/item-use-flags.h | 13 + src/object/lite-processor.c | 68 + src/object/lite-processor.h | 7 + src/object/object-broken.c | 468 ++ src/object/object-broken.h | 15 + src/object/object-flags.c | 179 + src/object/object-flags.h | 7 + src/object/object-generator.c | 66 + src/object/object-generator.h | 7 + src/object/object-info.c | 294 + src/object/object-info.h | 13 + src/object/object-kind-hook.c | 289 + src/object/object-kind-hook.h | 16 + src/object/object-kind.c | 32 + src/object/object-kind.h | 61 + src/object/object-mark-types.h | 19 + src/object/object-stack.c | 271 + src/object/object-stack.h | 9 + src/object/object-value-calc.c | 432 + src/object/object-value-calc.h | 5 + src/object/object-value.c | 319 + src/object/object-value.h | 7 + src/object/tval-types.h | 84 + src/object/warning.c | 596 ++ src/object/warning.h | 6 + src/object1.c | 5080 ------------ src/object2.c | 5852 -------------- src/objectkind-hook.c | 242 - src/objectkind-hook.h | 13 - src/patron.c | 672 -- src/patron.h | 45 - src/perception/identification.c | 727 ++ src/perception/identification.h | 7 + src/perception/object-perception.c | 96 + src/perception/object-perception.h | 12 + src/perception/simple-perception.c | 442 ++ src/perception/simple-perception.h | 9 + src/pet/pet-fall-off.c | 180 + src/pet/pet-fall-off.h | 7 + src/pet/pet-util.c | 47 + src/pet/pet-util.h | 44 + src/player-attack/attack-chaos-effect.c | 181 + src/player-attack/attack-chaos-effect.h | 6 + src/player-attack/blood-sucking-processor.c | 160 + src/player-attack/blood-sucking-processor.h | 8 + src/player-attack/player-attack-util.h | 40 + src/player-attack/player-attack.c | 503 ++ src/player-attack/player-attack.h | 7 + src/player-damage.c | 588 -- src/player-damage.h | 14 - src/player-info/avatar.c | 551 ++ src/player-info/avatar.h | 35 + src/player-info/base-status-info.c | 78 + src/player-info/base-status-info.h | 7 + src/player-info/base-status-types.h | 11 + src/player-info/body-improvement-info.c | 120 + src/player-info/body-improvement-info.h | 9 + src/player-info/class-ability-info.c | 150 + src/player-info/class-ability-info.h | 6 + src/player-info/mutation-info.c | 318 + src/player-info/mutation-info.h | 8 + src/player-info/race-ability-info.c | 192 + src/player-info/race-ability-info.h | 6 + src/player-info/resistance-info.c | 91 + src/player-info/resistance-info.h | 7 + src/player-info/self-info-util.c | 10 + src/player-info/self-info-util.h | 16 + src/player-info/self-info.c | 391 + src/player-info/self-info.h | 4 + src/player-info/weapon-effect-info.c | 105 + src/player-info/weapon-effect-info.h | 6 + src/player-move.c | 2359 ------ src/player-move.h | 2 - src/player-status.c | 4602 ----------- src/player-status.h | 40 - src/player/attack-defense-types.h | 28 + src/player/digestion-processor.c | 195 + src/player/digestion-processor.h | 6 + src/player/eldritch-horror.c | 329 + src/player/eldritch-horror.h | 6 + src/player/mimic-info-table.c | 69 + src/player/mimic-info-table.h | 7 + src/player/patron.c | 576 ++ src/player/patron.h | 48 + src/player/permanent-resistances.c | 613 ++ src/player/permanent-resistances.h | 5 + src/player/player-class.c | 1199 +++ src/player/player-class.h | 78 + src/player/player-classes-types.h | 33 + src/player/player-damage.c | 732 ++ src/player/player-damage.h | 18 + src/player/player-move.c | 306 + src/player/player-move.h | 33 + src/player/player-personalities-types.h | 18 + src/player/player-personality.c | 143 + src/player/player-personality.h | 31 + src/player/player-race-types.h | 46 + src/player/player-race.c | 121 + src/player/player-race.h | 68 + src/player/player-realm.c | 80 + src/player/player-realm.h | 30 + src/player/player-sex.c | 37 + src/player/player-sex.h | 15 + src/player/player-skill.c | 16 + src/player/player-skill.h | 51 + src/player/player-status-flags.c | 2186 ++++++ src/player/player-status-flags.h | 102 + src/player/player-status-table.c | 294 + src/player/player-status-table.h | 29 + src/player/player-status.c | 4138 ++++++++++ src/player/player-status.h | 575 ++ src/player/player-view.c | 350 + src/player/player-view.h | 5 + src/player/process-death.c | 403 + src/player/process-death.h | 7 + src/player/process-name.c | 169 + src/player/process-name.h | 6 + src/player/race-info-table.c | 593 ++ src/player/race-info-table.h | 6 + src/player/race-resistances.c | 118 + src/player/race-resistances.h | 8 + src/player/selfinfo.c | 1430 ++++ src/player/special-defense-types.h | 25 + src/player/temporary-resistances.c | 133 + src/player/temporary-resistances.h | 5 + src/projection.c | 346 - src/projection.h | 21 - src/quest.c | 504 -- src/quest.h | 29 - src/racial.c | 2029 ----- src/racial/class-racial-switcher.c | 288 + src/racial/class-racial-switcher.h | 6 + src/racial/mutation-racial-selector.c | 297 + src/racial/mutation-racial-selector.h | 6 + src/racial/race-racial-command-setter.c | 281 + src/racial/race-racial-command-setter.h | 7 + src/racial/racial-android.c | 144 + src/racial/racial-android.h | 6 + src/racial/racial-balrog.c | 17 + src/racial/racial-balrog.h | 5 + src/racial/racial-draconian.c | 127 + src/racial/racial-draconian.h | 5 + src/racial/racial-kutar.c | 49 + src/racial/racial-kutar.h | 5 + src/racial/racial-switcher.c | 437 ++ src/racial/racial-switcher.h | 7 + src/racial/racial-util.c | 19 + src/racial/racial-util.h | 34 + src/racial/racial-vampire.c | 55 + src/racial/racial-vampire.h | 5 + src/readdib.c | 373 - src/realm-arcane.c | 559 -- src/realm-arcane.h | 1 - src/realm-chaos.c | 590 -- src/realm-chaos.h | 1 - src/realm-craft.c | 505 -- src/realm-craft.h | 1 - src/realm-crusade.c | 571 -- src/realm-crusade.h | 1 - src/realm-daemon.c | 588 -- src/realm-daemon.h | 2 - src/realm-death.c | 634 -- src/realm-death.h | 1 - src/realm-hex.c | 1123 --- src/realm-hex.h | 14 - src/realm-hissatsu.c | 943 --- src/realm-hissatsu.h | 1 - src/realm-life.c | 483 -- src/realm-life.h | 1 - src/realm-nature.c | 569 -- src/realm-nature.h | 1 - src/realm-song.c | 929 --- src/realm-song.h | 1 - src/realm-sorcery.c | 554 -- src/realm-sorcery.h | 1 - src/realm-trump.c | 632 -- src/realm-trump.h | 1 - src/realm/realm-arcane.c | 651 ++ src/realm/realm-arcane.h | 6 + src/realm/realm-chaos.c | 684 ++ src/realm/realm-chaos.h | 6 + src/realm/realm-craft.c | 575 ++ src/realm/realm-craft.h | 6 + src/realm/realm-crusade.c | 666 ++ src/realm/realm-crusade.h | 6 + src/realm/realm-death.c | 722 ++ src/realm/realm-death.h | 6 + src/realm/realm-demon.c | 681 ++ src/realm/realm-demon.h | 7 + src/realm/realm-hex-numbers.h | 40 + src/realm/realm-hex.c | 889 +++ src/realm/realm-hex.h | 6 + src/realm/realm-hissatsu.c | 1019 +++ src/realm/realm-hissatsu.h | 6 + src/realm/realm-life.c | 578 ++ src/realm/realm-life.h | 6 + src/realm/realm-names-table.c | 58 + src/realm/realm-names-table.h | 16 + src/realm/realm-nature.c | 672 ++ src/realm/realm-nature.h | 6 + src/realm/realm-song-numbers.h | 30 + src/realm/realm-song.c | 998 +++ src/realm/realm-song.h | 6 + src/realm/realm-sorcery.c | 642 ++ src/realm/realm-sorcery.h | 6 + src/realm/realm-trump.c | 681 ++ src/realm/realm-trump.h | 6 + src/realm/realm-types.h | 21 + src/report.c | 604 -- src/room/cave-filler.c | 486 ++ src/room/cave-filler.h | 7 + src/room/door-definition.c | 3 + src/room/door-definition.h | 23 + src/room/lake-types.h | 12 + src/room/pit-nest-kinds-table.c | 63 + src/room/pit-nest-kinds-table.h | 47 + src/room/room-generator.c | 230 + src/room/room-generator.h | 6 + src/room/room-info-table.c | 60 + src/room/room-info-table.h | 13 + src/room/room-types.h | 23 + src/room/rooms-builder.c | 404 + src/room/rooms-builder.h | 11 + src/room/rooms-city.c | 227 + src/room/rooms-city.h | 20 + src/room/rooms-fractal.c | 73 + src/room/rooms-fractal.h | 6 + src/room/rooms-maze-vault.c | 138 + src/room/rooms-maze-vault.h | 6 + src/room/rooms-normal.c | 996 +++ src/room/rooms-normal.h | 11 + src/room/rooms-pit-nest.c | 925 +++ src/room/rooms-pit-nest.h | 14 + src/room/rooms-special.c | 260 + src/room/rooms-special.h | 6 + src/room/rooms-trap.c | 88 + src/room/rooms-trap.h | 6 + src/room/rooms-vault.c | 1217 +++ src/room/rooms-vault.h | 24 + src/room/space-finder.c | 235 + src/room/space-finder.h | 6 + src/room/treasure-deployment.c | 91 + src/room/treasure-deployment.h | 5 + src/room/vault-builder.c | 163 + src/room/vault-builder.h | 7 + src/rooms-city.c | 259 - src/rooms-city.h | 17 - src/rooms-fractal.c | 68 - src/rooms-fractal.h | 2 - src/rooms-normal.c | 1047 --- src/rooms-normal.h | 6 - src/rooms-pitnest.c | 1001 --- src/rooms-pitnest.h | 12 - src/rooms-special.c | 243 - src/rooms-special.h | 2 - src/rooms-trap.c | 88 - src/rooms-trap.h | 1 - src/rooms-vault.c | 1299 --- src/rooms-vault.h | 5 - src/rooms.c | 2333 ------ src/rooms.h | 100 - src/rumor.c | 155 - src/rumor.h | 3 - src/save.c | 2160 ----- src/save/floor-writer.c | 309 + src/save/floor-writer.h | 12 + src/save/info-writer.c | 176 + src/save/info-writer.h | 8 + src/save/item-writer.c | 222 + src/save/item-writer.h | 6 + src/save/monster-writer.c | 192 + src/save/monster-writer.h | 7 + src/save/player-writer.c | 238 + src/save/player-writer.h | 5 + src/save/save-util.c | 81 + src/save/save-util.h | 15 + src/save/save.c | 293 + src/save/save.h | 6 + src/scores.c | 908 --- src/selfinfo.c | 1808 ----- src/selfinfo.h | 8 - src/shoot.c | 1120 --- src/shoot.h | 9 - src/snipe.c | 580 -- src/sort.c | 623 -- src/sort.h | 26 - src/specific-object/blade-turner.c | 30 + src/specific-object/blade-turner.h | 5 + src/specific-object/bloody-moon.c | 67 + src/specific-object/bloody-moon.h | 6 + src/specific-object/bow.c | 34 + src/specific-object/bow.h | 5 + src/specific-object/chest.c | 351 + src/specific-object/chest.h | 6 + src/specific-object/death-crimson.c | 59 + src/specific-object/death-crimson.h | 5 + src/specific-object/death-scythe.c | 157 + src/specific-object/death-scythe.h | 6 + src/specific-object/monster-ball.c | 190 + src/specific-object/monster-ball.h | 6 + src/specific-object/muramasa.c | 25 + src/specific-object/muramasa.h | 5 + src/specific-object/ring-of-power.c | 64 + src/specific-object/ring-of-power.h | 5 + src/specific-object/toragoroshi.c | 11 + src/specific-object/toragoroshi.h | 5 + src/specific-object/torch.c | 292 + src/specific-object/torch.h | 10 + src/spell-kind/blood-curse.c | 134 + src/spell-kind/blood-curse.h | 5 + src/spell-kind/earthquake.c | 349 + src/spell-kind/earthquake.h | 5 + src/spell-kind/magic-item-recharger.c | 209 + src/spell-kind/magic-item-recharger.h | 5 + src/spell-kind/spells-beam.c | 53 + src/spell-kind/spells-beam.h | 8 + src/spell-kind/spells-charm.c | 56 + src/spell-kind/spells-charm.h | 8 + src/spell-kind/spells-curse-removal.c | 63 + src/spell-kind/spells-curse-removal.h | 6 + src/spell-kind/spells-detection.c | 645 ++ src/spell-kind/spells-detection.h | 19 + src/spell-kind/spells-enchant.c | 155 + src/spell-kind/spells-enchant.h | 6 + src/spell-kind/spells-equipment.c | 118 + src/spell-kind/spells-equipment.h | 5 + src/spell-kind/spells-fetcher.c | 171 + src/spell-kind/spells-fetcher.h | 6 + src/spell-kind/spells-floor.c | 475 ++ src/spell-kind/spells-floor.h | 8 + src/spell-kind/spells-genocide.c | 222 + src/spell-kind/spells-genocide.h | 8 + src/spell-kind/spells-grid.c | 145 + src/spell-kind/spells-grid.h | 7 + src/spell-kind/spells-launcher.c | 271 + src/spell-kind/spells-launcher.h | 14 + src/spell-kind/spells-lite.c | 426 + src/spell-kind/spells-lite.h | 10 + src/spell-kind/spells-neighbor.c | 161 + src/spell-kind/spells-neighbor.h | 14 + src/spell-kind/spells-perception.c | 197 + src/spell-kind/spells-perception.h | 9 + src/spell-kind/spells-pet.c | 71 + src/spell-kind/spells-pet.h | 5 + src/spell-kind/spells-polymorph.c | 128 + src/spell-kind/spells-polymorph.h | 5 + src/spell-kind/spells-random.c | 486 ++ src/spell-kind/spells-random.h | 8 + src/spell-kind/spells-sight.c | 407 + src/spell-kind/spells-sight.h | 29 + src/spell-kind/spells-specific-bolt.c | 30 + src/spell-kind/spells-specific-bolt.h | 6 + src/spell-kind/spells-teleport.c | 586 ++ src/spell-kind/spells-teleport.h | 16 + src/spell-kind/spells-world.c | 469 ++ src/spell-kind/spells-world.h | 12 + src/spell-realm/spells-arcane.c | 39 + src/spell-realm/spells-arcane.h | 5 + src/spell-realm/spells-chaos.c | 224 + src/spell-realm/spells-chaos.h | 7 + src/spell-realm/spells-craft.c | 300 + src/spell-realm/spells-craft.h | 9 + src/spell-realm/spells-crusade.c | 186 + src/spell-realm/spells-crusade.h | 7 + src/spell-realm/spells-demon.c | 49 + src/spell-realm/spells-demon.h | 5 + src/spell-realm/spells-hex.c | 324 + src/spell-realm/spells-hex.h | 20 + src/spell-realm/spells-nature.c | 48 + src/spell-realm/spells-nature.h | 5 + src/spell-realm/spells-song.c | 116 + src/spell-realm/spells-song.h | 6 + src/spell-realm/spells-sorcery.c | 84 + src/spell-realm/spells-sorcery.h | 5 + src/spell-realm/spells-trump.c | 229 + src/spell-realm/spells-trump.h | 6 + src/spell/range-calc.c | 280 + src/spell/range-calc.h | 7 + src/spell/spell-info.c | 337 + src/spell/spell-info.h | 10 + src/spell/spell-types.h | 106 + src/spell/spells-describer.c | 20 + src/spell/spells-describer.h | 6 + src/spell/spells-diceroll.c | 88 + src/spell/spells-diceroll.h | 8 + src/spell/spells-execution.c | 44 + src/spell/spells-execution.h | 6 + src/spell/spells-object.c | 734 ++ src/spell/spells-object.h | 21 + src/spell/spells-staff-only.c | 66 + src/spell/spells-staff-only.h | 6 + src/spell/spells-status.c | 579 ++ src/spell/spells-status.h | 33 + src/spell/spells-summon.c | 540 ++ src/spell/spells-summon.h | 17 + src/spell/spells-util.h | 26 + src/spell/summon-types.h | 49 + src/spell/technic-info-table.c | 124 + src/spell/technic-info-table.h | 19 + src/spells-diceroll.c | 85 - src/spells-diceroll.h | 5 - src/spells-floor.c | 241 - src/spells-floor.h | 7 - src/spells-object.c | 1120 --- src/spells-object.h | 18 - src/spells-status.c | 546 -- src/spells-status.h | 29 - src/spells-summon.c | 437 -- src/spells-summon.h | 19 - src/spells-world.c | 24 - src/spells-world.h | 1 - src/spells.h | 6 - src/spells1.c | 6658 ---------------- src/spells2.c | 5187 ------------ src/spells3.c | 4012 ---------- src/status/action-setter.c | 112 + src/status/action-setter.h | 5 + src/status/bad-status-setter.c | 582 ++ src/status/bad-status-setter.h | 13 + src/status/base-status.c | 283 + src/status/base-status.h | 11 + src/status/body-improvement.c | 242 + src/status/body-improvement.h | 9 + src/status/buff-setter.c | 220 + src/status/buff-setter.h | 9 + src/status/element-resistance.c | 238 + src/status/element-resistance.h | 14 + src/status/experience.c | 81 + src/status/experience.h | 9 + src/status/shape-changer.c | 401 + src/status/shape-changer.h | 11 + src/status/sight-setter.c | 137 + src/status/sight-setter.h | 7 + src/status/temporary-resistance.c | 160 + src/status/temporary-resistance.h | 8 + src/store.c | 6187 --------------- src/store.h | 44 - src/store/black-market.c | 47 + src/store/black-market.h | 6 + src/store/home.c | 201 + src/store/home.h | 6 + src/store/museum.c | 55 + src/store/museum.h | 5 + src/store/owner-insults.c | 190 + src/store/owner-insults.h | 9 + src/store/pricing.c | 76 + src/store/pricing.h | 6 + src/store/purchase-order.c | 460 ++ src/store/purchase-order.h | 5 + src/store/rumor.c | 135 + src/store/rumor.h | 5 + src/store/say-comments.c | 222 + src/store/say-comments.h | 11 + src/store/sell-order.c | 351 + src/store/sell-order.h | 5 + src/store/service-checker.c | 423 + src/store/service-checker.h | 7 + src/store/store-owner-comments.c | 319 + src/store/store-owner-comments.h | 37 + src/store/store-owners.c | 726 ++ src/store/store-owners.h | 18 + src/store/store-util.c | 323 + src/store/store-util.h | 47 + src/store/store.c | 359 + src/store/store.h | 29 + src/sv-definition/sv-amulet-types.h | 30 + src/sv-definition/sv-armor-types.h | 65 + src/sv-definition/sv-bow-types.h | 13 + src/sv-definition/sv-digging-types.h | 12 + src/sv-definition/sv-food-types.h | 33 + src/sv-definition/sv-lite-types.h | 15 + src/sv-definition/sv-other-types.h | 25 + src/sv-definition/sv-potion-types.h | 72 + src/sv-definition/sv-protector-types.h | 57 + src/sv-definition/sv-ring-types.h | 60 + src/sv-definition/sv-rod-types.h | 36 + src/sv-definition/sv-scroll-types.h | 62 + src/sv-definition/sv-staff-types.h | 38 + src/sv-definition/sv-wand-types.h | 37 + src/sv-definition/sv-weapon-types.h | 91 + src/system/alloc-entries.c | 13 + src/system/alloc-entries.h | 10 + src/system/alloc-entry-definition.h | 31 + src/system/angband-version.h | 44 + src/system/angband.h | 95 + src/system/artifact-type-definition.c | 13 + src/system/artifact-type-definition.h | 41 + src/system/building-type-definition.c | 4 + src/system/building-type-definition.h | 39 + src/system/dungeon-data-definition.h | 76 + src/system/floor-type-definition.h | 54 + src/system/game-option-types.h | 14 + src/system/gamevalue.h | 148 + src/system/h-basic.h | 43 + src/system/h-config.h | 262 + src/system/h-define.h | 58 + src/system/h-system.h | 79 + src/system/h-type.h | 256 + src/system/monster-race-definition.h | 109 + src/system/monster-type-definition.h | 46 + src/system/object-type-definition.h | 47 + src/system/system-variables.c | 32 + src/system/system-variables.h | 23 + src/tables.c | 4777 ----------- src/target/grid-selector.c | 199 + src/target/grid-selector.h | 5 + src/target/projection-path-calculator.c | 275 + src/target/projection-path-calculator.h | 9 + src/target/target-checker.c | 134 + src/target/target-checker.h | 10 + src/target/target-describer.c | 561 ++ src/target/target-describer.h | 8 + src/target/target-getter.c | 250 + src/target/target-getter.h | 7 + src/target/target-preparation.c | 151 + src/target/target-preparation.h | 6 + src/target/target-setter.c | 481 ++ src/target/target-setter.h | 6 + src/target/target-types.h | 9 + src/term.c | 188 - src/term.h | 5 - src/term/gameterm.c | 602 ++ src/term/gameterm.h | 34 + src/term/readdib.c | 369 + src/{ => term}/readdib.h | 0 src/term/screen-processor.c | 233 + src/term/screen-processor.h | 15 + src/term/term-color-types.h | 26 + src/term/z-form.c | 822 ++ src/term/z-form.h | 55 + src/term/z-rand.c | 403 + src/term/z-rand.h | 103 + src/term/z-term.c | 2269 ++++++ src/term/z-term.h | 179 + src/term/z-util.c | 326 + src/term/z-util.h | 69 + src/term/z-virt.c | 154 + src/term/z-virt.h | 175 + src/trap.c | 652 -- src/trap.h | 42 - src/types.h | 1928 ----- src/util.c | 5548 ------------- src/util/angband-files.c | 518 ++ src/util/angband-files.h | 51 + src/util/bit-flags-calculator.h | 7 + src/util/buffer-shaper.c | 83 + src/util/buffer-shaper.h | 5 + src/util/int-char-converter.h | 16 + src/util/object-sort.c | 110 + src/util/object-sort.h | 5 + src/util/quarks.c | 58 + src/util/quarks.h | 18 + src/util/sort.c | 692 ++ src/util/sort.h | 30 + src/util/string-processor.c | 476 ++ src/util/string-processor.h | 25 + src/util/tag-sorter.c | 100 + src/util/tag-sorter.h | 13 + src/variable.c | 890 --- src/view-mainwindow.c | 2467 ------ src/view/display-birth.c | 37 + src/view/display-birth.h | 5 + src/view/display-characteristic.c | 479 ++ src/view/display-characteristic.h | 11 + src/view/display-fruit.c | 84 + src/view/display-fruit.h | 3 + src/view/display-inventory.c | 177 + src/view/display-inventory.h | 7 + src/view/display-lore-attacks.c | 109 + src/view/display-lore-attacks.h | 7 + src/view/display-lore-drops.c | 103 + src/view/display-lore-drops.h | 10 + src/view/display-lore-magics.c | 92 + src/view/display-lore-magics.h | 7 + src/view/display-lore-status.c | 436 + src/view/display-lore-status.h | 17 + src/view/display-lore.c | 561 ++ src/view/display-lore.h | 23 + src/view/display-map.c | 318 + src/view/display-map.h | 12 + src/view/display-messages.c | 439 ++ src/view/display-messages.h | 33 + src/view/display-monster-status.c | 47 + src/view/display-monster-status.h | 6 + src/view/display-player-middle.c | 313 + src/view/display-player-middle.h | 5 + src/view/display-player-misc-info.c | 48 + src/view/display-player-misc-info.h | 5 + src/view/display-player-stat-info.c | 384 + src/view/display-player-stat-info.h | 5 + src/view/display-player.c | 375 + src/view/display-player.h | 6 + src/view/display-self-info.c | 122 + src/view/display-self-info.h | 10 + src/view/display-store.c | 209 + src/view/display-store.h | 8 + src/view/display-util.c | 140 + src/view/display-util.h | 5 + src/view/object-describer.c | 122 + src/view/object-describer.h | 7 + src/view/status-bars-table.c | 35 + src/view/status-bars-table.h | 84 + src/view/status-first-page.c | 395 + src/view/status-first-page.h | 55 + src/warning.c | 523 -- src/warning.h | 4 - src/wild.c | 1180 --- src/wild.h | 28 - src/window/display-sub-window-items.c | 68 + src/window/display-sub-window-items.h | 8 + src/window/display-sub-window-spells.c | 190 + src/window/display-sub-window-spells.h | 5 + src/window/display-sub-windows.c | 488 ++ src/window/display-sub-windows.h | 16 + src/window/main-window-equipments.c | 126 + src/window/main-window-equipments.h | 6 + src/window/main-window-left-frame.c | 397 + src/window/main-window-left-frame.h | 14 + src/window/main-window-row-column.h | 77 + src/window/main-window-stat-poster.c | 650 ++ src/window/main-window-stat-poster.h | 14 + src/window/main-window-util.c | 392 + src/window/main-window-util.h | 22 + src/wizard/artifact-analyzer.c | 336 + src/wizard/artifact-analyzer.h | 7 + src/wizard/artifact-bias-table.c | 27 + src/wizard/artifact-bias-table.h | 6 + src/wizard/cmd-wizard.c | 301 + src/wizard/cmd-wizard.h | 5 + src/wizard/fixed-artifacts-spoiler.c | 189 + src/wizard/fixed-artifacts-spoiler.h | 6 + src/wizard/items-spoiler.c | 168 + src/wizard/items-spoiler.h | 5 + src/wizard/monster-info-spoiler.c | 242 + src/wizard/monster-info-spoiler.h | 6 + src/wizard/spoiler-table.c | 177 + src/wizard/spoiler-table.h | 46 + src/wizard/spoiler-util.c | 205 + src/wizard/spoiler-util.h | 48 + src/wizard/tval-descriptions-table.c | 25 + src/wizard/tval-descriptions-table.h | 17 + src/wizard/wizard-item-modifier.c | 499 ++ src/wizard/wizard-item-modifier.h | 5 + src/wizard/wizard-messages.c | 48 + src/wizard/wizard-messages.h | 6 + src/wizard/wizard-special-process.c | 582 ++ src/wizard/wizard-special-process.h | 17 + src/wizard/wizard-spells.c | 181 + src/wizard/wizard-spells.h | 37 + src/wizard/wizard-spoiler.c | 206 + src/wizard/wizard-spoiler.h | 5 + src/wizard1.c | 2599 ------ src/wizard2.c | 2103 ----- src/world.c | 43 - src/world.h | 2 - src/world/world-movement-processor.c | 150 + src/world/world-movement-processor.h | 6 + src/world/world-object.c | 138 + src/world/world-object.h | 6 + src/world/world-turn-processor.c | 253 + src/world/world-turn-processor.h | 6 + src/world/world.c | 60 + src/world/world.h | 76 + src/xtra2.c | 2259 ------ src/z-config.h | 552 -- src/z-form.c | 822 -- src/z-form.h | 55 - src/z-rand.c | 403 - src/z-rand.h | 106 - src/z-term.c | 2991 ------- src/z-term.h | 206 - src/z-util.c | 326 - src/z-util.h | 69 - src/z-virt.c | 181 - src/z-virt.h | 175 - 1943 files changed, 232010 insertions(+), 251019 deletions(-) create mode 100644 .clang-format create mode 100644 Hengband/Bakabakaband.sln create mode 100644 Hengband/Hengband/Bakabakaband.vcxproj create mode 100644 Hengband/Hengband/Bakabakaband.vcxproj.filters create mode 100644 Hengband/Hengband/packages.config delete mode 100644 Hengband_vcs2015/Hengband.sln delete mode 100644 Hengband_vcs2015/Hengband/Hengband.vcxproj delete mode 100644 Hengband_vcs2017/Hengband.sln delete mode 100644 Hengband_vcs2017/Hengband/Hengband.vcxproj delete mode 100644 Hengband_vcs2017/Hengband/Hengband.vcxproj.filters create mode 100644 src/action/action-limited.c create mode 100644 src/action/action-limited.h create mode 100644 src/action/activation-execution.c create mode 100644 src/action/activation-execution.h create mode 100644 src/action/movement-execution.c create mode 100644 src/action/movement-execution.h create mode 100644 src/action/mutation-execution.c create mode 100644 src/action/mutation-execution.h create mode 100644 src/action/open-close-execution.c create mode 100644 src/action/open-close-execution.h create mode 100644 src/action/open-util.c create mode 100644 src/action/open-util.h create mode 100644 src/action/racial-execution.c create mode 100644 src/action/racial-execution.h create mode 100644 src/action/run-execution.c create mode 100644 src/action/run-execution.h create mode 100644 src/action/throw-util.c create mode 100644 src/action/throw-util.h create mode 100644 src/action/travel-execution.c create mode 100644 src/action/travel-execution.h create mode 100644 src/action/tunnel-execution.c create mode 100644 src/action/tunnel-execution.h create mode 100644 src/action/weapon-shield.c create mode 100644 src/action/weapon-shield.h delete mode 100644 src/angband.h create mode 100644 src/art-definition/art-accessory-types.h create mode 100644 src/art-definition/art-armor-types.h create mode 100644 src/art-definition/art-bow-types.h create mode 100644 src/art-definition/art-protector-types.h create mode 100644 src/art-definition/art-sword-types.h create mode 100644 src/art-definition/art-weapon-types.h create mode 100644 src/art-definition/random-art-effects.h delete mode 100644 src/artifact.c delete mode 100644 src/artifact.h create mode 100644 src/artifact/artifact-info.c create mode 100644 src/artifact/artifact-info.h create mode 100644 src/artifact/fixed-art-generator.c create mode 100644 src/artifact/fixed-art-generator.h create mode 100644 src/artifact/random-art-activation.c create mode 100644 src/artifact/random-art-activation.h create mode 100644 src/artifact/random-art-bias-types.h create mode 100644 src/artifact/random-art-characteristics.c create mode 100644 src/artifact/random-art-characteristics.h create mode 100644 src/artifact/random-art-generator.c create mode 100644 src/artifact/random-art-generator.h create mode 100644 src/artifact/random-art-misc.c create mode 100644 src/artifact/random-art-misc.h create mode 100644 src/artifact/random-art-pval-investor.c create mode 100644 src/artifact/random-art-pval-investor.h create mode 100644 src/artifact/random-art-resistance.c create mode 100644 src/artifact/random-art-resistance.h create mode 100644 src/artifact/random-art-slay.c create mode 100644 src/artifact/random-art-slay.h delete mode 100644 src/autopick.c create mode 100644 src/autopick/autopick-command-menu.c create mode 100644 src/autopick/autopick-command-menu.h create mode 100644 src/autopick/autopick-commands-table.h create mode 100644 src/autopick/autopick-describer.c create mode 100644 src/autopick/autopick-describer.h create mode 100644 src/autopick/autopick-destroyer.c create mode 100644 src/autopick/autopick-destroyer.h create mode 100644 src/autopick/autopick-dirty-flags.h create mode 100644 src/autopick/autopick-drawer.c create mode 100644 src/autopick/autopick-drawer.h create mode 100644 src/autopick/autopick-editor-command.c create mode 100644 src/autopick/autopick-editor-command.h create mode 100644 src/autopick/autopick-editor-table.h create mode 100644 src/autopick/autopick-editor-util.c create mode 100644 src/autopick/autopick-editor-util.h create mode 100644 src/autopick/autopick-entry.c create mode 100644 src/autopick/autopick-entry.h create mode 100644 src/autopick/autopick-finder.c create mode 100644 src/autopick/autopick-finder.h create mode 100644 src/autopick/autopick-flags-table.h create mode 100644 src/autopick/autopick-initializer.c create mode 100644 src/autopick/autopick-initializer.h create mode 100644 src/autopick/autopick-inserter-killer.c create mode 100644 src/autopick/autopick-inserter-killer.h create mode 100644 src/autopick/autopick-key-flag-process.h create mode 100644 src/autopick/autopick-keys-table.h create mode 100644 src/autopick/autopick-matcher.c create mode 100644 src/autopick/autopick-matcher.h create mode 100644 src/autopick/autopick-menu-data-table.c create mode 100644 src/autopick/autopick-menu-data-table.h create mode 100644 src/autopick/autopick-methods-table.h create mode 100644 src/autopick/autopick-pref-processor.c create mode 100644 src/autopick/autopick-pref-processor.h create mode 100644 src/autopick/autopick-reader-writer.c create mode 100644 src/autopick/autopick-reader-writer.h create mode 100644 src/autopick/autopick-registry.c create mode 100644 src/autopick/autopick-registry.h create mode 100644 src/autopick/autopick-util.c create mode 100644 src/autopick/autopick-util.h create mode 100644 src/autopick/autopick.c create mode 100644 src/autopick/autopick.h delete mode 100644 src/avatar.c delete mode 100644 src/avatar.h delete mode 100644 src/birth.c create mode 100644 src/birth/auto-roller.c create mode 100644 src/birth/auto-roller.h create mode 100644 src/birth/birth-body-spec.c create mode 100644 src/birth/birth-body-spec.h create mode 100644 src/birth/birth-explanations-table.c create mode 100644 src/birth/birth-explanations-table.h create mode 100644 src/birth/birth-select-class.c create mode 100644 src/birth/birth-select-class.h create mode 100644 src/birth/birth-select-personality.c create mode 100644 src/birth/birth-select-personality.h create mode 100644 src/birth/birth-select-race.c create mode 100644 src/birth/birth-select-race.h create mode 100644 src/birth/birth-select-realm.c create mode 100644 src/birth/birth-select-realm.h create mode 100644 src/birth/birth-stat.c create mode 100644 src/birth/birth-stat.h create mode 100644 src/birth/birth-util.c create mode 100644 src/birth/birth-util.h create mode 100644 src/birth/birth-wizard.c create mode 100644 src/birth/birth-wizard.h create mode 100644 src/birth/character-builder.c create mode 100644 src/birth/character-builder.h create mode 100644 src/birth/game-play-initializer.c create mode 100644 src/birth/game-play-initializer.h create mode 100644 src/birth/history-editor.c create mode 100644 src/birth/history-editor.h create mode 100644 src/birth/history-generator.c create mode 100644 src/birth/history-generator.h create mode 100644 src/birth/history.c create mode 100644 src/birth/history.h create mode 100644 src/birth/initial-equipments-table.c create mode 100644 src/birth/initial-equipments-table.h create mode 100644 src/birth/inventory-initializer.c create mode 100644 src/birth/inventory-initializer.h create mode 100644 src/birth/quick-start.c create mode 100644 src/birth/quick-start.h delete mode 100644 src/bldg.c create mode 100644 src/blue-magic/blue-magic-ball-bolt.c create mode 100644 src/blue-magic/blue-magic-ball-bolt.h create mode 100644 src/blue-magic/blue-magic-breath.c create mode 100644 src/blue-magic/blue-magic-breath.h create mode 100644 src/blue-magic/blue-magic-caster.c create mode 100644 src/blue-magic/blue-magic-caster.h create mode 100644 src/blue-magic/blue-magic-checker.c create mode 100644 src/blue-magic/blue-magic-checker.h create mode 100644 src/blue-magic/blue-magic-spirit-curse.c create mode 100644 src/blue-magic/blue-magic-spirit-curse.h create mode 100644 src/blue-magic/blue-magic-status.c create mode 100644 src/blue-magic/blue-magic-status.h create mode 100644 src/blue-magic/blue-magic-summon.c create mode 100644 src/blue-magic/blue-magic-summon.h create mode 100644 src/blue-magic/blue-magic-util.c create mode 100644 src/blue-magic/blue-magic-util.h create mode 100644 src/blue-magic/learnt-info.c create mode 100644 src/blue-magic/learnt-info.h create mode 100644 src/blue-magic/learnt-power-getter.c create mode 100644 src/blue-magic/learnt-power-getter.h delete mode 100644 src/chest.c delete mode 100644 src/chest.h delete mode 100644 src/chuukei.c create mode 100644 src/cmd-action/cmd-attack.c create mode 100644 src/cmd-action/cmd-attack.h create mode 100644 src/cmd-action/cmd-hissatsu.c create mode 100644 src/cmd-action/cmd-hissatsu.h create mode 100644 src/cmd-action/cmd-mane.c create mode 100644 src/cmd-action/cmd-mane.h create mode 100644 src/cmd-action/cmd-mind.c create mode 100644 src/cmd-action/cmd-mind.h create mode 100644 src/cmd-action/cmd-move.c create mode 100644 src/cmd-action/cmd-move.h create mode 100644 src/cmd-action/cmd-open-close.c create mode 100644 src/cmd-action/cmd-open-close.h create mode 100644 src/cmd-action/cmd-others.c create mode 100644 src/cmd-action/cmd-others.h create mode 100644 src/cmd-action/cmd-pet.c create mode 100644 src/cmd-action/cmd-pet.h create mode 100644 src/cmd-action/cmd-racial.c create mode 100644 src/cmd-action/cmd-racial.h create mode 100644 src/cmd-action/cmd-shoot.c create mode 100644 src/cmd-action/cmd-shoot.h create mode 100644 src/cmd-action/cmd-spell.c create mode 100644 src/cmd-action/cmd-spell.h create mode 100644 src/cmd-action/cmd-travel.c create mode 100644 src/cmd-action/cmd-travel.h create mode 100644 src/cmd-action/cmd-tunnel.c create mode 100644 src/cmd-action/cmd-tunnel.h delete mode 100644 src/cmd-activate.c delete mode 100644 src/cmd-activate.h create mode 100644 src/cmd-building/cmd-building.c create mode 100644 src/cmd-building/cmd-building.h create mode 100644 src/cmd-building/cmd-inn.c create mode 100644 src/cmd-building/cmd-inn.h create mode 100644 src/cmd-building/cmd-store.c create mode 100644 src/cmd-building/cmd-store.h delete mode 100644 src/cmd-eat.c delete mode 100644 src/cmd-eat.h delete mode 100644 src/cmd-hissatsu.c delete mode 100644 src/cmd-hissatsu.h create mode 100644 src/cmd-io/cmd-autopick.c create mode 100644 src/cmd-io/cmd-autopick.h create mode 100644 src/cmd-io/cmd-diary.c create mode 100644 src/cmd-io/cmd-diary.h create mode 100644 src/cmd-io/cmd-dump.c create mode 100644 src/cmd-io/cmd-dump.h create mode 100644 src/cmd-io/cmd-floor.c create mode 100644 src/cmd-io/cmd-floor.h create mode 100644 src/cmd-io/cmd-gameoption.c create mode 100644 src/cmd-io/cmd-gameoption.h create mode 100644 src/cmd-io/cmd-help.c create mode 100644 src/cmd-io/cmd-help.h create mode 100644 src/cmd-io/cmd-knowledge.c create mode 100644 src/cmd-io/cmd-knowledge.h create mode 100644 src/cmd-io/cmd-lore.c create mode 100644 src/cmd-io/cmd-lore.h create mode 100644 src/cmd-io/cmd-macro.c create mode 100644 src/cmd-io/cmd-macro.h create mode 100644 src/cmd-io/cmd-menu-content-table.c create mode 100644 src/cmd-io/cmd-menu-content-table.h create mode 100644 src/cmd-io/cmd-process-screen.c create mode 100644 src/cmd-io/cmd-process-screen.h create mode 100644 src/cmd-io/cmd-save.c create mode 100644 src/cmd-io/cmd-save.h create mode 100644 src/cmd-io/diary-subtitle-table.c create mode 100644 src/cmd-io/diary-subtitle-table.h create mode 100644 src/cmd-io/feeling-table.c create mode 100644 src/cmd-io/feeling-table.h create mode 100644 src/cmd-io/macro-util.c create mode 100644 src/cmd-io/macro-util.h delete mode 100644 src/cmd-item.c delete mode 100644 src/cmd-item.h create mode 100644 src/cmd-item/cmd-destroy.c create mode 100644 src/cmd-item/cmd-destroy.h create mode 100644 src/cmd-item/cmd-eat.c create mode 100644 src/cmd-item/cmd-eat.h create mode 100644 src/cmd-item/cmd-equipment.c create mode 100644 src/cmd-item/cmd-equipment.h create mode 100644 src/cmd-item/cmd-item.c create mode 100644 src/cmd-item/cmd-item.h create mode 100644 src/cmd-item/cmd-magiceat.c create mode 100644 src/cmd-item/cmd-magiceat.h create mode 100644 src/cmd-item/cmd-quaff.c create mode 100644 src/cmd-item/cmd-quaff.h create mode 100644 src/cmd-item/cmd-read.c create mode 100644 src/cmd-item/cmd-read.h create mode 100644 src/cmd-item/cmd-refill.c create mode 100644 src/cmd-item/cmd-refill.h create mode 100644 src/cmd-item/cmd-smith.c create mode 100644 src/cmd-item/cmd-smith.h create mode 100644 src/cmd-item/cmd-throw.c create mode 100644 src/cmd-item/cmd-throw.h create mode 100644 src/cmd-item/cmd-usestaff.c create mode 100644 src/cmd-item/cmd-usestaff.h create mode 100644 src/cmd-item/cmd-zaprod.c create mode 100644 src/cmd-item/cmd-zaprod.h create mode 100644 src/cmd-item/cmd-zapwand.c create mode 100644 src/cmd-item/cmd-zapwand.h delete mode 100644 src/cmd-magiceat.c delete mode 100644 src/cmd-magiceat.h delete mode 100644 src/cmd-mane.c delete mode 100644 src/cmd-mane.h delete mode 100644 src/cmd-pet.c delete mode 100644 src/cmd-pet.h delete mode 100644 src/cmd-quaff.c delete mode 100644 src/cmd-quaff.h delete mode 100644 src/cmd-read.c delete mode 100644 src/cmd-read.h delete mode 100644 src/cmd-smith.c delete mode 100644 src/cmd-smith.h delete mode 100644 src/cmd-spell.c delete mode 100644 src/cmd-spell.h delete mode 100644 src/cmd-usestaff.c delete mode 100644 src/cmd-usestaff.h create mode 100644 src/cmd-visual/cmd-draw.c create mode 100644 src/cmd-visual/cmd-draw.h create mode 100644 src/cmd-visual/cmd-map.c create mode 100644 src/cmd-visual/cmd-map.h create mode 100644 src/cmd-visual/cmd-visuals.c create mode 100644 src/cmd-visual/cmd-visuals.h delete mode 100644 src/cmd-zaprod.c delete mode 100644 src/cmd-zaprod.h delete mode 100644 src/cmd-zapwand.c delete mode 100644 src/cmd-zapwand.h delete mode 100644 src/cmd2.c delete mode 100644 src/cmd4.c create mode 100644 src/combat/attack-accuracy.c create mode 100644 src/combat/attack-accuracy.h create mode 100644 src/combat/attack-criticality.c create mode 100644 src/combat/attack-criticality.h create mode 100644 src/combat/attack-power-table.c create mode 100644 src/combat/attack-power-table.h create mode 100644 src/combat/aura-counterattack.c create mode 100644 src/combat/aura-counterattack.h create mode 100644 src/combat/combat-options-type.h create mode 100644 src/combat/hallucination-attacks-table.c create mode 100644 src/combat/hallucination-attacks-table.h create mode 100644 src/combat/martial-arts-table.c create mode 100644 src/combat/martial-arts-table.h create mode 100644 src/combat/shoot.c create mode 100644 src/combat/shoot.h create mode 100644 src/combat/slaying.c create mode 100644 src/combat/slaying.h create mode 100644 src/core/asking-player.c create mode 100644 src/core/asking-player.h create mode 100644 src/core/disturbance.c create mode 100644 src/core/disturbance.h create mode 100644 src/core/game-closer.c create mode 100644 src/core/game-closer.h create mode 100644 src/core/game-play.c create mode 100644 src/core/game-play.h create mode 100644 src/core/hp-mp-processor.c create mode 100644 src/core/hp-mp-processor.h create mode 100644 src/core/hp-mp-regenerator.c create mode 100644 src/core/hp-mp-regenerator.h create mode 100644 src/core/magic-effects-timeout-reducer.c create mode 100644 src/core/magic-effects-timeout-reducer.h create mode 100644 src/core/object-compressor.c create mode 100644 src/core/object-compressor.h create mode 100644 src/core/output-updater.c create mode 100644 src/core/output-updater.h create mode 100644 src/core/player-processor.c create mode 100644 src/core/player-processor.h create mode 100644 src/core/player-redraw-types.h create mode 100644 src/core/player-update-types.h create mode 100644 src/core/scores.c create mode 100644 src/core/scores.h create mode 100644 src/core/show-file.c create mode 100644 src/core/show-file.h create mode 100644 src/core/special-internal-keys.h create mode 100644 src/core/speed-table.c create mode 100644 src/core/speed-table.h create mode 100644 src/core/status-reseter.c create mode 100644 src/core/status-reseter.h create mode 100644 src/core/stuff-handler.c create mode 100644 src/core/stuff-handler.h create mode 100644 src/core/turn-compensator.c create mode 100644 src/core/turn-compensator.h create mode 100644 src/core/visuals-reseter.c create mode 100644 src/core/visuals-reseter.h create mode 100644 src/core/window-redrawer.c create mode 100644 src/core/window-redrawer.h delete mode 100644 src/defines.h delete mode 100644 src/dungeon.c create mode 100644 src/dungeon/dungeon-flag-types.h create mode 100644 src/dungeon/dungeon-processor.c create mode 100644 src/dungeon/dungeon-processor.h create mode 100644 src/dungeon/dungeon.c create mode 100644 src/dungeon/dungeon.h create mode 100644 src/dungeon/quest-completion-checker.c create mode 100644 src/dungeon/quest-completion-checker.h create mode 100644 src/dungeon/quest-monster-placer.c create mode 100644 src/dungeon/quest-monster-placer.h create mode 100644 src/dungeon/quest.c create mode 100644 src/dungeon/quest.h create mode 100644 src/effect/effect-characteristics.h create mode 100644 src/effect/effect-feature.c create mode 100644 src/effect/effect-feature.h create mode 100644 src/effect/effect-item.c create mode 100644 src/effect/effect-item.h create mode 100644 src/effect/effect-monster-charm.c create mode 100644 src/effect/effect-monster-charm.h create mode 100644 src/effect/effect-monster-curse.c create mode 100644 src/effect/effect-monster-curse.h create mode 100644 src/effect/effect-monster-evil.c create mode 100644 src/effect/effect-monster-evil.h create mode 100644 src/effect/effect-monster-lite-dark.c create mode 100644 src/effect/effect-monster-lite-dark.h create mode 100644 src/effect/effect-monster-oldies.c create mode 100644 src/effect/effect-monster-oldies.h create mode 100644 src/effect/effect-monster-psi.c create mode 100644 src/effect/effect-monster-psi.h create mode 100644 src/effect/effect-monster-resist-hurt.c create mode 100644 src/effect/effect-monster-resist-hurt.h create mode 100644 src/effect/effect-monster-spirit.c create mode 100644 src/effect/effect-monster-spirit.h create mode 100644 src/effect/effect-monster-switcher.c create mode 100644 src/effect/effect-monster-switcher.h create mode 100644 src/effect/effect-monster-util.c create mode 100644 src/effect/effect-monster-util.h create mode 100644 src/effect/effect-monster.c create mode 100644 src/effect/effect-monster.h create mode 100644 src/effect/effect-player-curse.c create mode 100644 src/effect/effect-player-curse.h create mode 100644 src/effect/effect-player-oldies.c create mode 100644 src/effect/effect-player-oldies.h create mode 100644 src/effect/effect-player-resist-hurt.c create mode 100644 src/effect/effect-player-resist-hurt.h create mode 100644 src/effect/effect-player-spirit.c create mode 100644 src/effect/effect-player-spirit.h create mode 100644 src/effect/effect-player-switcher.c create mode 100644 src/effect/effect-player-switcher.h create mode 100644 src/effect/effect-player-util.h create mode 100644 src/effect/effect-player.c create mode 100644 src/effect/effect-player.h create mode 100644 src/effect/effect-processor.c create mode 100644 src/effect/effect-processor.h create mode 100644 src/effect/spells-effect-util.c create mode 100644 src/effect/spells-effect-util.h delete mode 100644 src/effects.c delete mode 100644 src/externs.h delete mode 100644 src/feature.c delete mode 100644 src/feature.h delete mode 100644 src/files.c delete mode 100644 src/flavor.c create mode 100644 src/flavor/flag-inscriptions-table.c create mode 100644 src/flavor/flag-inscriptions-table.h create mode 100644 src/flavor/flavor-describer.c create mode 100644 src/flavor/flavor-describer.h create mode 100644 src/flavor/flavor-util.c create mode 100644 src/flavor/flavor-util.h create mode 100644 src/flavor/named-item-describer.c create mode 100644 src/flavor/named-item-describer.h create mode 100644 src/flavor/object-flavor-types.h create mode 100644 src/flavor/object-flavor.c create mode 100644 src/flavor/object-flavor.h create mode 100644 src/flavor/tval-description-switcher.c create mode 100644 src/flavor/tval-description-switcher.h delete mode 100644 src/floor-events.c delete mode 100644 src/floor-events.h delete mode 100644 src/floor-generate.c delete mode 100644 src/floor-generate.h delete mode 100644 src/floor-save.c delete mode 100644 src/floor-save.h delete mode 100644 src/floor-streams.c delete mode 100644 src/floor-streams.h delete mode 100644 src/floor.h create mode 100644 src/floor/cave-generator.c create mode 100644 src/floor/cave-generator.h create mode 100644 src/floor/cave.c create mode 100644 src/floor/cave.h create mode 100644 src/floor/dungeon-tunnel-util.c create mode 100644 src/floor/dungeon-tunnel-util.h create mode 100644 src/floor/fixed-map-generator.c create mode 100644 src/floor/fixed-map-generator.h create mode 100644 src/floor/floor-allocation-types.h create mode 100644 src/floor/floor-base-definitions.h create mode 100644 src/floor/floor-changer.c create mode 100644 src/floor/floor-changer.h create mode 100644 src/floor/floor-events.c create mode 100644 src/floor/floor-events.h create mode 100644 src/floor/floor-generator-util.h create mode 100644 src/floor/floor-generator.c create mode 100644 src/floor/floor-generator.h create mode 100644 src/floor/floor-leaver.c create mode 100644 src/floor/floor-leaver.h create mode 100644 src/floor/floor-mode-changer.c create mode 100644 src/floor/floor-mode-changer.h create mode 100644 src/floor/floor-object.c create mode 100644 src/floor/floor-object.h create mode 100644 src/floor/floor-save-util.c create mode 100644 src/floor/floor-save-util.h create mode 100644 src/floor/floor-save.c create mode 100644 src/floor/floor-save.h create mode 100644 src/floor/floor-streams.c create mode 100644 src/floor/floor-streams.h create mode 100644 src/floor/floor-town.c create mode 100644 src/floor/floor-town.h create mode 100644 src/floor/floor-util.c create mode 100644 src/floor/floor-util.h create mode 100644 src/floor/geometry.c create mode 100644 src/floor/geometry.h create mode 100644 src/floor/line-of-sight.c create mode 100644 src/floor/line-of-sight.h create mode 100644 src/floor/object-allocator.c create mode 100644 src/floor/object-allocator.h create mode 100644 src/floor/object-scanner.c create mode 100644 src/floor/object-scanner.h create mode 100644 src/floor/pattern-walk.c create mode 100644 src/floor/pattern-walk.h create mode 100644 src/floor/sight-definitions.h create mode 100644 src/floor/tunnel-generator.c create mode 100644 src/floor/tunnel-generator.h create mode 100644 src/floor/wild.c create mode 100644 src/floor/wild.h create mode 100644 src/game-option/auto-destruction-options.c create mode 100644 src/game-option/auto-destruction-options.h create mode 100644 src/game-option/birth-options.c create mode 100644 src/game-option/birth-options.h create mode 100644 src/game-option/cheat-options.c create mode 100644 src/game-option/cheat-options.h create mode 100644 src/game-option/cheat-types.h create mode 100644 src/game-option/disturbance-options.c create mode 100644 src/game-option/disturbance-options.h create mode 100644 src/game-option/game-play-options.c create mode 100644 src/game-option/game-play-options.h create mode 100644 src/game-option/input-options.c create mode 100644 src/game-option/input-options.h create mode 100644 src/game-option/keymap-directory-getter.c create mode 100644 src/game-option/keymap-directory-getter.h create mode 100644 src/game-option/map-screen-options.c create mode 100644 src/game-option/map-screen-options.h create mode 100644 src/game-option/option-flags.c create mode 100644 src/game-option/option-flags.h create mode 100644 src/game-option/option-types-table.c create mode 100644 src/game-option/option-types-table.h create mode 100644 src/game-option/play-record-options.c create mode 100644 src/game-option/play-record-options.h create mode 100644 src/game-option/runtime-arguments.c create mode 100644 src/game-option/runtime-arguments.h create mode 100644 src/game-option/special-options.c create mode 100644 src/game-option/special-options.h create mode 100644 src/game-option/text-display-options.c create mode 100644 src/game-option/text-display-options.h delete mode 100644 src/gameoption.c delete mode 100644 src/gameoption.h delete mode 100644 src/gamevalue.h delete mode 100644 src/generate.h delete mode 100644 src/geometry.c delete mode 100644 src/geometry.h delete mode 100644 src/grid.c delete mode 100644 src/grid.h create mode 100644 src/grid/door.c create mode 100644 src/grid/door.h create mode 100644 src/grid/feature-flag-types.h create mode 100644 src/grid/feature-generator.c create mode 100644 src/grid/feature-generator.h create mode 100644 src/grid/feature.c create mode 100644 src/grid/feature.h create mode 100644 src/grid/grid.c create mode 100644 src/grid/grid.h create mode 100644 src/grid/lighting-colors-table.c create mode 100644 src/grid/lighting-colors-table.h create mode 100644 src/grid/object-placer.c create mode 100644 src/grid/object-placer.h create mode 100644 src/grid/stair.c create mode 100644 src/grid/stair.h create mode 100644 src/grid/trap.c create mode 100644 src/grid/trap.h delete mode 100644 src/h-basic.h delete mode 100644 src/h-config.h delete mode 100644 src/h-define.h delete mode 100644 src/h-system.h delete mode 100644 src/h-type.h delete mode 100644 src/history.c delete mode 100644 src/history.h delete mode 100644 src/inet.c create mode 100644 src/info-reader/artifact-reader.c create mode 100644 src/info-reader/artifact-reader.h create mode 100644 src/info-reader/dungeon-info-tokens-table.c create mode 100644 src/info-reader/dungeon-info-tokens-table.h create mode 100644 src/info-reader/dungeon-reader.c create mode 100644 src/info-reader/dungeon-reader.h create mode 100644 src/info-reader/ego-reader.c create mode 100644 src/info-reader/ego-reader.h create mode 100644 src/info-reader/feature-info-tokens-table.c create mode 100644 src/info-reader/feature-info-tokens-table.h create mode 100644 src/info-reader/feature-reader.c create mode 100644 src/info-reader/feature-reader.h create mode 100644 src/info-reader/fixed-map-parser.c create mode 100644 src/info-reader/fixed-map-parser.h create mode 100644 src/info-reader/general-parser.c create mode 100644 src/info-reader/general-parser.h create mode 100644 src/info-reader/info-reader-util.c create mode 100644 src/info-reader/info-reader-util.h create mode 100644 src/info-reader/kind-info-tokens-table.c create mode 100644 src/info-reader/kind-info-tokens-table.h create mode 100644 src/info-reader/kind-reader.c create mode 100644 src/info-reader/kind-reader.h create mode 100644 src/info-reader/magic-reader.c create mode 100644 src/info-reader/magic-reader.h create mode 100644 src/info-reader/parse-error-types.h create mode 100644 src/info-reader/race-info-tokens-table.c create mode 100644 src/info-reader/race-info-tokens-table.h create mode 100644 src/info-reader/race-reader.c create mode 100644 src/info-reader/race-reader.h create mode 100644 src/info-reader/random-grid-effect-types.h create mode 100644 src/info-reader/skill-reader.c create mode 100644 src/info-reader/skill-reader.h create mode 100644 src/info-reader/vault-reader.c create mode 100644 src/info-reader/vault-reader.h delete mode 100644 src/init.h delete mode 100644 src/init1.c delete mode 100644 src/init2.c create mode 100644 src/inventory/floor-item-getter.c create mode 100644 src/inventory/floor-item-getter.h create mode 100644 src/inventory/inventory-curse.c create mode 100644 src/inventory/inventory-curse.h create mode 100644 src/inventory/inventory-damage.c create mode 100644 src/inventory/inventory-damage.h create mode 100644 src/inventory/inventory-describer.c create mode 100644 src/inventory/inventory-describer.h create mode 100644 src/inventory/inventory-object.c create mode 100644 src/inventory/inventory-object.h create mode 100644 src/inventory/inventory-slot-types.h create mode 100644 src/inventory/inventory-util.c create mode 100644 src/inventory/inventory-util.h create mode 100644 src/inventory/item-getter.c create mode 100644 src/inventory/item-getter.h create mode 100644 src/inventory/item-selection-util.c create mode 100644 src/inventory/item-selection-util.h create mode 100644 src/inventory/pack-overflow.c create mode 100644 src/inventory/pack-overflow.h create mode 100644 src/inventory/player-inventory.c create mode 100644 src/inventory/player-inventory.h create mode 100644 src/inventory/recharge-processor.c create mode 100644 src/inventory/recharge-processor.h create mode 100644 src/io-dump/character-dump.c create mode 100644 src/io-dump/character-dump.h create mode 100644 src/io-dump/dump-remover.c create mode 100644 src/io-dump/dump-remover.h create mode 100644 src/io-dump/dump-util.c create mode 100644 src/io-dump/dump-util.h create mode 100644 src/io-dump/player-status-dump.c create mode 100644 src/io-dump/player-status-dump.h create mode 100644 src/io-dump/random-art-info-dumper.c create mode 100644 src/io-dump/random-art-info-dumper.h create mode 100644 src/io-dump/special-class-dump.c create mode 100644 src/io-dump/special-class-dump.h create mode 100644 src/io/chuukei.c create mode 100644 src/io/chuukei.h create mode 100644 src/io/command-repeater.c create mode 100644 src/io/command-repeater.h create mode 100644 src/io/cursor.c create mode 100644 src/io/cursor.h create mode 100644 src/io/exit-panic.c create mode 100644 src/io/exit-panic.h create mode 100644 src/io/files-util.c create mode 100644 src/io/files-util.h create mode 100644 src/io/gf-descriptions.c create mode 100644 src/io/gf-descriptions.h create mode 100644 src/io/inet.c create mode 100644 src/io/inet.h create mode 100644 src/io/input-key-acceptor.c create mode 100644 src/io/input-key-acceptor.h create mode 100644 src/io/input-key-processor.c create mode 100644 src/io/input-key-processor.h create mode 100644 src/io/input-key-requester.c create mode 100644 src/io/input-key-requester.h create mode 100644 src/io/interpret-pref-file.c create mode 100644 src/io/interpret-pref-file.h create mode 100644 src/io/mutations-dump.c create mode 100644 src/io/mutations-dump.h create mode 100644 src/io/pref-file-expressor.c create mode 100644 src/io/pref-file-expressor.h create mode 100644 src/io/read-pref-file.c create mode 100644 src/io/read-pref-file.h create mode 100644 src/io/report.c create mode 100644 src/io/report.h create mode 100644 src/io/screen-util.c create mode 100644 src/io/screen-util.h create mode 100644 src/io/signal-handlers.c create mode 100644 src/io/signal-handlers.h create mode 100644 src/io/store-key-processor.c create mode 100644 src/io/store-key-processor.h create mode 100644 src/io/tokenizer.c create mode 100644 src/io/tokenizer.h create mode 100644 src/io/uid-checker.c create mode 100644 src/io/uid-checker.h create mode 100644 src/io/write-diary.c create mode 100644 src/io/write-diary.h delete mode 100644 src/japanese.c create mode 100644 src/knowledge/knowledge-autopick.c create mode 100644 src/knowledge/knowledge-autopick.h create mode 100644 src/knowledge/knowledge-experiences.c create mode 100644 src/knowledge/knowledge-experiences.h create mode 100644 src/knowledge/knowledge-features.c create mode 100644 src/knowledge/knowledge-features.h create mode 100644 src/knowledge/knowledge-inventory.c create mode 100644 src/knowledge/knowledge-inventory.h create mode 100644 src/knowledge/knowledge-items.c create mode 100644 src/knowledge/knowledge-items.h create mode 100644 src/knowledge/knowledge-monsters.c create mode 100644 src/knowledge/knowledge-monsters.h create mode 100644 src/knowledge/knowledge-mutations.c create mode 100644 src/knowledge/knowledge-mutations.h create mode 100644 src/knowledge/knowledge-quests.c create mode 100644 src/knowledge/knowledge-quests.h create mode 100644 src/knowledge/knowledge-self.c create mode 100644 src/knowledge/knowledge-self.h create mode 100644 src/knowledge/knowledge-uniques.c create mode 100644 src/knowledge/knowledge-uniques.h create mode 100644 src/knowledge/lighting-level-table.c create mode 100644 src/knowledge/lighting-level-table.h create mode 100644 src/knowledge/monster-group-table.c create mode 100644 src/knowledge/monster-group-table.h create mode 100644 src/knowledge/object-group-table.c create mode 100644 src/knowledge/object-group-table.h delete mode 100644 src/load.c create mode 100644 src/load/angband-version-comparer.c create mode 100644 src/load/angband-version-comparer.h create mode 100644 src/load/birth-loader.c create mode 100644 src/load/birth-loader.h create mode 100644 src/load/dummy-loader.c create mode 100644 src/load/dummy-loader.h create mode 100644 src/load/dungeon-loader.c create mode 100644 src/load/dungeon-loader.h create mode 100644 src/load/extra-loader.c create mode 100644 src/load/extra-loader.h create mode 100644 src/load/floor-loader.c create mode 100644 src/load/floor-loader.h create mode 100644 src/load/info-loader.c create mode 100644 src/load/info-loader.h create mode 100644 src/load/inventory-loader.c create mode 100644 src/load/inventory-loader.h create mode 100644 src/load/item-loader.c create mode 100644 src/load/item-loader.h create mode 100644 src/load/load-util.c create mode 100644 src/load/load-util.h create mode 100644 src/load/load-v1-3-0.c create mode 100644 src/load/load-v1-3-0.h create mode 100644 src/load/load-v1-5-0.c create mode 100644 src/load/load-v1-5-0.h create mode 100644 src/load/load-v1-7-0.c create mode 100644 src/load/load-v1-7-0.h create mode 100644 src/load/load-zangband.c create mode 100644 src/load/load-zangband.h create mode 100644 src/load/load.c create mode 100644 src/load/load.h create mode 100644 src/load/lore-loader.c create mode 100644 src/load/lore-loader.h create mode 100644 src/load/monster-loader.c create mode 100644 src/load/monster-loader.h create mode 100644 src/load/old-feature-types.h create mode 100644 src/load/option-loader.c create mode 100644 src/load/option-loader.h create mode 100644 src/load/player-attack-loader.c create mode 100644 src/load/player-attack-loader.h create mode 100644 src/load/player-info-loader.c create mode 100644 src/load/player-info-loader.h create mode 100644 src/load/quest-loader.c create mode 100644 src/load/quest-loader.h create mode 100644 src/load/savedata-flag-types.h create mode 100644 src/load/store-loader.c create mode 100644 src/load/store-loader.h create mode 100644 src/load/world-loader.c create mode 100644 src/load/world-loader.h create mode 100644 src/locale/english.c create mode 100644 src/locale/english.h create mode 100644 src/locale/japanese.c create mode 100644 src/locale/japanese.h create mode 100644 src/locale/language-switcher.h create mode 100644 src/lore/combat-types-setter.c create mode 100644 src/lore/combat-types-setter.h create mode 100644 src/lore/lore-calculator.c create mode 100644 src/lore/lore-calculator.h create mode 100644 src/lore/lore-store.c create mode 100644 src/lore/lore-store.h create mode 100644 src/lore/lore-util.c create mode 100644 src/lore/lore-util.h create mode 100644 src/lore/magic-types-setter.c create mode 100644 src/lore/magic-types-setter.h create mode 100644 src/lore/monster-lore.c create mode 100644 src/lore/monster-lore.h delete mode 100644 src/main-dos.c delete mode 100644 src/main-ibm.c delete mode 100644 src/main-mac.c create mode 100644 src/main/angband-headers.c create mode 100644 src/main/angband-headers.h create mode 100644 src/main/angband-initializer.c create mode 100644 src/main/angband-initializer.h create mode 100644 src/main/game-data-initializer.c create mode 100644 src/main/game-data-initializer.h create mode 100644 src/main/info-initializer.c create mode 100644 src/main/info-initializer.h create mode 100644 src/main/init-error-messages-table.c create mode 100644 src/main/init-error-messages-table.h create mode 100644 src/main/music-definitions-table.c create mode 100644 src/main/music-definitions-table.h create mode 100644 src/main/sound-definitions-table.c create mode 100644 src/main/sound-definitions-table.h create mode 100644 src/main/sound-of-music.c create mode 100644 src/main/sound-of-music.h create mode 100644 src/main/x11-gamma-builder.c create mode 100644 src/main/x11-gamma-builder.h create mode 100644 src/main/x11-type-string.c create mode 100644 src/main/x11-type-string.h delete mode 100644 src/makefile.dos delete mode 100644 src/makefile.ibm create mode 100644 src/market/arena-info-table.c create mode 100644 src/market/arena-info-table.h create mode 100644 src/market/arena.c create mode 100644 src/market/arena.h create mode 100644 src/market/articles-on-sale.c create mode 100644 src/market/articles-on-sale.h create mode 100644 src/market/bounty-prize-table.c create mode 100644 src/market/bounty-prize-table.h create mode 100644 src/market/bounty.c create mode 100644 src/market/bounty.h create mode 100644 src/market/building-actions-table.h create mode 100644 src/market/building-craft-armor.c create mode 100644 src/market/building-craft-armor.h create mode 100644 src/market/building-craft-fix.c create mode 100644 src/market/building-craft-fix.h create mode 100644 src/market/building-craft-weapon.c create mode 100644 src/market/building-craft-weapon.h create mode 100644 src/market/building-enchanter.c create mode 100644 src/market/building-enchanter.h create mode 100644 src/market/building-initializer.c create mode 100644 src/market/building-initializer.h create mode 100644 src/market/building-monster.c create mode 100644 src/market/building-monster.h create mode 100644 src/market/building-quest.c create mode 100644 src/market/building-quest.h create mode 100644 src/market/building-recharger.c create mode 100644 src/market/building-recharger.h create mode 100644 src/market/building-service.c create mode 100644 src/market/building-service.h create mode 100644 src/market/building-util.c create mode 100644 src/market/building-util.h create mode 100644 src/market/gold-magnification-table.c create mode 100644 src/market/gold-magnification-table.h create mode 100644 src/market/play-gamble.c create mode 100644 src/market/play-gamble.h create mode 100644 src/market/poker.c create mode 100644 src/market/poker.h delete mode 100644 src/melee.h create mode 100644 src/melee/melee-postprocess.c create mode 100644 src/melee/melee-postprocess.h create mode 100644 src/melee/melee-spell-flags-checker.c create mode 100644 src/melee/melee-spell-flags-checker.h create mode 100644 src/melee/melee-spell-util.c create mode 100644 src/melee/melee-spell-util.h create mode 100644 src/melee/melee-spell.c create mode 100644 src/melee/melee-spell.h create mode 100644 src/melee/melee-switcher.c create mode 100644 src/melee/melee-switcher.h create mode 100644 src/melee/melee-util.c create mode 100644 src/melee/melee-util.h create mode 100644 src/melee/monster-attack-monster.c create mode 100644 src/melee/monster-attack-monster.h delete mode 100644 src/melee1.c delete mode 100644 src/mind.c create mode 100644 src/mind/drs-types.h create mode 100644 src/mind/mind-archer.c create mode 100644 src/mind/mind-archer.h create mode 100644 src/mind/mind-berserker.c create mode 100644 src/mind/mind-berserker.h create mode 100644 src/mind/mind-blue-mage.c create mode 100644 src/mind/mind-blue-mage.h create mode 100644 src/mind/mind-cavalry.c create mode 100644 src/mind/mind-cavalry.h create mode 100644 src/mind/mind-chaos-warrior.c create mode 100644 src/mind/mind-chaos-warrior.h create mode 100644 src/mind/mind-explanations-table.c create mode 100644 src/mind/mind-explanations-table.h create mode 100644 src/mind/mind-force-trainer.c create mode 100644 src/mind/mind-force-trainer.h create mode 100644 src/mind/mind-hobbit.c create mode 100644 src/mind/mind-hobbit.h create mode 100644 src/mind/mind-info.c create mode 100644 src/mind/mind-info.h create mode 100644 src/mind/mind-mage.c create mode 100644 src/mind/mind-mage.h create mode 100644 src/mind/mind-magic-eater.c create mode 100644 src/mind/mind-magic-eater.h create mode 100644 src/mind/mind-magic-resistance.c create mode 100644 src/mind/mind-magic-resistance.h create mode 100644 src/mind/mind-mindcrafter.c create mode 100644 src/mind/mind-mindcrafter.h create mode 100644 src/mind/mind-mirror-master.c create mode 100644 src/mind/mind-mirror-master.h create mode 100644 src/mind/mind-monk.c create mode 100644 src/mind/mind-monk.h create mode 100644 src/mind/mind-ninja.c create mode 100644 src/mind/mind-ninja.h create mode 100644 src/mind/mind-numbers.h create mode 100644 src/mind/mind-power-getter.c create mode 100644 src/mind/mind-power-getter.h create mode 100644 src/mind/mind-priest.c create mode 100644 src/mind/mind-priest.h create mode 100644 src/mind/mind-samurai.c create mode 100644 src/mind/mind-samurai.h create mode 100644 src/mind/mind-sniper.c create mode 100644 src/mind/mind-sniper.h create mode 100644 src/mind/mind-types.h create mode 100644 src/mind/mind-warrior-mage.c create mode 100644 src/mind/mind-warrior-mage.h create mode 100644 src/mind/mind-warrior.c create mode 100644 src/mind/mind-warrior.h create mode 100644 src/mind/mind-weaponsmith.c create mode 100644 src/mind/mind-weaponsmith.h create mode 100644 src/mind/monk-attack.c create mode 100644 src/mind/monk-attack.h create mode 100644 src/mind/snipe-types.h create mode 100644 src/mind/stances-table.c create mode 100644 src/mind/stances-table.h create mode 100644 src/monster-attack/insults-moans.c create mode 100644 src/monster-attack/insults-moans.h create mode 100644 src/monster-attack/monster-attack-describer.c create mode 100644 src/monster-attack/monster-attack-describer.h create mode 100644 src/monster-attack/monster-attack-effect.h create mode 100644 src/monster-attack/monster-attack-player.c create mode 100644 src/monster-attack/monster-attack-player.h create mode 100644 src/monster-attack/monster-attack-processor.c create mode 100644 src/monster-attack/monster-attack-processor.h create mode 100644 src/monster-attack/monster-attack-status.c create mode 100644 src/monster-attack/monster-attack-status.h create mode 100644 src/monster-attack/monster-attack-switcher.c create mode 100644 src/monster-attack/monster-attack-switcher.h create mode 100644 src/monster-attack/monster-attack-types.c create mode 100644 src/monster-attack/monster-attack-types.h create mode 100644 src/monster-attack/monster-attack-util.c create mode 100644 src/monster-attack/monster-attack-util.h create mode 100644 src/monster-attack/monster-eating.c create mode 100644 src/monster-attack/monster-eating.h create mode 100644 src/monster-floor/monster-death-util.c create mode 100644 src/monster-floor/monster-death-util.h create mode 100644 src/monster-floor/monster-death.c create mode 100644 src/monster-floor/monster-death.h create mode 100644 src/monster-floor/monster-direction.c create mode 100644 src/monster-floor/monster-direction.h create mode 100644 src/monster-floor/monster-dist-offsets.c create mode 100644 src/monster-floor/monster-dist-offsets.h create mode 100644 src/monster-floor/monster-generator.c create mode 100644 src/monster-floor/monster-generator.h create mode 100644 src/monster-floor/monster-lite-util.c create mode 100644 src/monster-floor/monster-lite-util.h create mode 100644 src/monster-floor/monster-lite.c create mode 100644 src/monster-floor/monster-lite.h create mode 100644 src/monster-floor/monster-move.c create mode 100644 src/monster-floor/monster-move.h create mode 100644 src/monster-floor/monster-object.c create mode 100644 src/monster-floor/monster-object.h create mode 100644 src/monster-floor/monster-remover.c create mode 100644 src/monster-floor/monster-remover.h create mode 100644 src/monster-floor/monster-runaway.c create mode 100644 src/monster-floor/monster-runaway.h create mode 100644 src/monster-floor/monster-safety-hiding.c create mode 100644 src/monster-floor/monster-safety-hiding.h create mode 100644 src/monster-floor/monster-summon.c create mode 100644 src/monster-floor/monster-summon.h create mode 100644 src/monster-floor/monster-sweep-grid.c create mode 100644 src/monster-floor/monster-sweep-grid.h create mode 100644 src/monster-floor/one-monster-placer.c create mode 100644 src/monster-floor/one-monster-placer.h create mode 100644 src/monster-floor/place-monster-types.h create mode 100644 src/monster-floor/quantum-effect.c create mode 100644 src/monster-floor/quantum-effect.h create mode 100644 src/monster-floor/special-death-switcher.c create mode 100644 src/monster-floor/special-death-switcher.h delete mode 100644 src/monster-process.c create mode 100644 src/monster-race/monster-race-hook.c create mode 100644 src/monster-race/monster-race-hook.h create mode 100644 src/monster-race/monster-race.c create mode 100644 src/monster-race/monster-race.h create mode 100644 src/monster-race/race-flags-ability1.h create mode 100644 src/monster-race/race-flags-ability2.h create mode 100644 src/monster-race/race-flags-resistance.h create mode 100644 src/monster-race/race-flags1.h create mode 100644 src/monster-race/race-flags2.h create mode 100644 src/monster-race/race-flags3.h create mode 100644 src/monster-race/race-flags4.h create mode 100644 src/monster-race/race-flags7.h create mode 100644 src/monster-race/race-flags8.h create mode 100644 src/monster-race/race-flags9.h create mode 100644 src/monster-race/race-indice-types.h delete mode 100644 src/monster-spell.h delete mode 100644 src/monster-status.c delete mode 100644 src/monster-status.h delete mode 100644 src/monster.h create mode 100644 src/monster/horror-descriptions.c create mode 100644 src/monster/horror-descriptions.h create mode 100644 src/monster/monster-compaction.c create mode 100644 src/monster/monster-compaction.h create mode 100644 src/monster/monster-describer.c create mode 100644 src/monster/monster-describer.h create mode 100644 src/monster/monster-description-types.h create mode 100644 src/monster/monster-flag-types.h create mode 100644 src/monster/monster-info.c create mode 100644 src/monster/monster-info.h create mode 100644 src/monster/monster-list.c create mode 100644 src/monster/monster-list.h create mode 100644 src/monster/monster-processor-util.c create mode 100644 src/monster/monster-processor-util.h create mode 100644 src/monster/monster-processor.c create mode 100644 src/monster/monster-processor.h create mode 100644 src/monster/monster-status-setter.c create mode 100644 src/monster/monster-status-setter.h create mode 100644 src/monster/monster-status.c create mode 100644 src/monster/monster-status.h create mode 100644 src/monster/monster-timed-effect-types.h create mode 100644 src/monster/monster-update.c create mode 100644 src/monster/monster-update.h create mode 100644 src/monster/monster-util.c create mode 100644 src/monster/monster-util.h create mode 100644 src/monster/smart-learn-types.h delete mode 100644 src/monster1.c delete mode 100644 src/monster2.c delete mode 100644 src/monsterrace-hook.c delete mode 100644 src/monsterrace-hook.h create mode 100644 src/mspell/assign-monster-spell.c create mode 100644 src/mspell/assign-monster-spell.h create mode 100644 src/mspell/element-resistance-checker.c create mode 100644 src/mspell/element-resistance-checker.h create mode 100644 src/mspell/high-resistance-checker.c create mode 100644 src/mspell/high-resistance-checker.h create mode 100644 src/mspell/improper-mspell-remover.c create mode 100644 src/mspell/improper-mspell-remover.h create mode 100644 src/mspell/monster-power-table.c create mode 100644 src/mspell/monster-power-table.h create mode 100644 src/mspell/mspell-attack-util.c create mode 100644 src/mspell/mspell-attack-util.h create mode 100644 src/mspell/mspell-attack.c create mode 100644 src/mspell/mspell-attack.h create mode 100644 src/mspell/mspell-ball.c create mode 100644 src/mspell/mspell-ball.h create mode 100644 src/mspell/mspell-bolt.c create mode 100644 src/mspell/mspell-bolt.h create mode 100644 src/mspell/mspell-breath.c create mode 100644 src/mspell/mspell-breath.h create mode 100644 src/mspell/mspell-checker.c create mode 100644 src/mspell/mspell-checker.h create mode 100644 src/mspell/mspell-curse.c create mode 100644 src/mspell/mspell-curse.h create mode 100644 src/mspell/mspell-damage-calculator.c create mode 100644 src/mspell/mspell-damage-calculator.h create mode 100644 src/mspell/mspell-dispel.c create mode 100644 src/mspell/mspell-dispel.h create mode 100644 src/mspell/mspell-floor.c create mode 100644 src/mspell/mspell-floor.h create mode 100644 src/mspell/mspell-judgement.c create mode 100644 src/mspell/mspell-judgement.h create mode 100644 src/mspell/mspell-learn-checker.c create mode 100644 src/mspell/mspell-learn-checker.h create mode 100644 src/mspell/mspell-lite.c create mode 100644 src/mspell/mspell-lite.h create mode 100644 src/mspell/mspell-mask-definitions.h create mode 100644 src/mspell/mspell-particularity.c create mode 100644 src/mspell/mspell-particularity.h create mode 100644 src/mspell/mspell-selector.c create mode 100644 src/mspell/mspell-selector.h create mode 100644 src/mspell/mspell-special.c create mode 100644 src/mspell/mspell-special.h create mode 100644 src/mspell/mspell-status.c create mode 100644 src/mspell/mspell-status.h create mode 100644 src/mspell/mspell-summon.c create mode 100644 src/mspell/mspell-summon.h create mode 100644 src/mspell/mspell-type.h create mode 100644 src/mspell/mspell-util.c create mode 100644 src/mspell/mspell-util.h create mode 100644 src/mspell/smart-mspell-util.c create mode 100644 src/mspell/smart-mspell-util.h create mode 100644 src/mspell/specified-summon.c create mode 100644 src/mspell/specified-summon.h create mode 100644 src/mspell/summon-checker.c create mode 100644 src/mspell/summon-checker.h delete mode 100644 src/mspells1.c delete mode 100644 src/mspells2.c delete mode 100644 src/mspells3.c delete mode 100644 src/mspells4.c delete mode 100644 src/mutation.c delete mode 100644 src/mutation.h create mode 100644 src/mutation/gain-mutation-switcher.c create mode 100644 src/mutation/gain-mutation-switcher.h create mode 100644 src/mutation/lose-mutation-switcher.c create mode 100644 src/mutation/lose-mutation-switcher.h create mode 100644 src/mutation/mutation-calculator.c create mode 100644 src/mutation/mutation-calculator.h create mode 100644 src/mutation/mutation-flag-types.h create mode 100644 src/mutation/mutation-investor-remover.c create mode 100644 src/mutation/mutation-investor-remover.h create mode 100644 src/mutation/mutation-processor.c create mode 100644 src/mutation/mutation-processor.h create mode 100644 src/mutation/mutation-techniques.c create mode 100644 src/mutation/mutation-techniques.h create mode 100644 src/mutation/mutation-util.c create mode 100644 src/mutation/mutation-util.h create mode 100644 src/mutation/mutation.c create mode 100644 src/object-activation/activation-bolt-ball.c create mode 100644 src/object-activation/activation-bolt-ball.h create mode 100644 src/object-activation/activation-breath.c create mode 100644 src/object-activation/activation-breath.h create mode 100644 src/object-activation/activation-charm.c create mode 100644 src/object-activation/activation-charm.h create mode 100644 src/object-activation/activation-genocide.c create mode 100644 src/object-activation/activation-genocide.h create mode 100644 src/object-activation/activation-others.c create mode 100644 src/object-activation/activation-others.h create mode 100644 src/object-activation/activation-resistance.c create mode 100644 src/object-activation/activation-resistance.h create mode 100644 src/object-activation/activation-switcher.c create mode 100644 src/object-activation/activation-switcher.h create mode 100644 src/object-activation/activation-teleport.c create mode 100644 src/object-activation/activation-teleport.h create mode 100644 src/object-activation/activation-util.c create mode 100644 src/object-activation/activation-util.h delete mode 100644 src/object-boost.c delete mode 100644 src/object-boost.h delete mode 100644 src/object-broken.c delete mode 100644 src/object-broken.h delete mode 100644 src/object-curse.c delete mode 100644 src/object-curse.h create mode 100644 src/object-enchant/activation-info-table.c create mode 100644 src/object-enchant/activation-info-table.h create mode 100644 src/object-enchant/apply-magic-accessory.c create mode 100644 src/object-enchant/apply-magic-accessory.h create mode 100644 src/object-enchant/apply-magic-armor.c create mode 100644 src/object-enchant/apply-magic-armor.h create mode 100644 src/object-enchant/apply-magic-others.c create mode 100644 src/object-enchant/apply-magic-others.h create mode 100644 src/object-enchant/apply-magic-weapon.c create mode 100644 src/object-enchant/apply-magic-weapon.h create mode 100644 src/object-enchant/apply-magic.c create mode 100644 src/object-enchant/apply-magic.h create mode 100644 src/object-enchant/dragon-breaths-table.c create mode 100644 src/object-enchant/dragon-breaths-table.h create mode 100644 src/object-enchant/item-apply-magic.h create mode 100644 src/object-enchant/item-feeling.h create mode 100644 src/object-enchant/object-boost.c create mode 100644 src/object-enchant/object-boost.h create mode 100644 src/object-enchant/object-curse.c create mode 100644 src/object-enchant/object-curse.h create mode 100644 src/object-enchant/object-ego.c create mode 100644 src/object-enchant/object-ego.h create mode 100644 src/object-enchant/old-ego-extra-values.h create mode 100644 src/object-enchant/special-object-flags.h create mode 100644 src/object-enchant/tr-types.h create mode 100644 src/object-enchant/trc-types.h create mode 100644 src/object-enchant/trg-types.h create mode 100644 src/object-enchant/vorpal-weapon.c create mode 100644 src/object-enchant/vorpal-weapon.h delete mode 100644 src/object-hook.c delete mode 100644 src/object-hook.h create mode 100644 src/object-hook/hook-armor.c create mode 100644 src/object-hook/hook-armor.h create mode 100644 src/object-hook/hook-bow.c create mode 100644 src/object-hook/hook-bow.h create mode 100644 src/object-hook/hook-checker.c create mode 100644 src/object-hook/hook-checker.h create mode 100644 src/object-hook/hook-enchant.c create mode 100644 src/object-hook/hook-enchant.h create mode 100644 src/object-hook/hook-expendable.c create mode 100644 src/object-hook/hook-expendable.h create mode 100644 src/object-hook/hook-magic.c create mode 100644 src/object-hook/hook-magic.h create mode 100644 src/object-hook/hook-perception.c create mode 100644 src/object-hook/hook-perception.h create mode 100644 src/object-hook/hook-quest.c create mode 100644 src/object-hook/hook-quest.h create mode 100644 src/object-hook/hook-weapon.c create mode 100644 src/object-hook/hook-weapon.h create mode 100644 src/object-use/quaff-execution.c create mode 100644 src/object-use/quaff-execution.h create mode 100644 src/object-use/read-execution.c create mode 100644 src/object-use/read-execution.h create mode 100644 src/object/item-tester-hooker.c create mode 100644 src/object/item-tester-hooker.h create mode 100644 src/object/item-use-flags.h create mode 100644 src/object/lite-processor.c create mode 100644 src/object/lite-processor.h create mode 100644 src/object/object-broken.c create mode 100644 src/object/object-broken.h create mode 100644 src/object/object-flags.c create mode 100644 src/object/object-flags.h create mode 100644 src/object/object-generator.c create mode 100644 src/object/object-generator.h create mode 100644 src/object/object-info.c create mode 100644 src/object/object-info.h create mode 100644 src/object/object-kind-hook.c create mode 100644 src/object/object-kind-hook.h create mode 100644 src/object/object-kind.c create mode 100644 src/object/object-kind.h create mode 100644 src/object/object-mark-types.h create mode 100644 src/object/object-stack.c create mode 100644 src/object/object-stack.h create mode 100644 src/object/object-value-calc.c create mode 100644 src/object/object-value-calc.h create mode 100644 src/object/object-value.c create mode 100644 src/object/object-value.h create mode 100644 src/object/tval-types.h create mode 100644 src/object/warning.c create mode 100644 src/object/warning.h delete mode 100644 src/object1.c delete mode 100644 src/object2.c delete mode 100644 src/objectkind-hook.c delete mode 100644 src/objectkind-hook.h delete mode 100644 src/patron.c delete mode 100644 src/patron.h create mode 100644 src/perception/identification.c create mode 100644 src/perception/identification.h create mode 100644 src/perception/object-perception.c create mode 100644 src/perception/object-perception.h create mode 100644 src/perception/simple-perception.c create mode 100644 src/perception/simple-perception.h create mode 100644 src/pet/pet-fall-off.c create mode 100644 src/pet/pet-fall-off.h create mode 100644 src/pet/pet-util.c create mode 100644 src/pet/pet-util.h create mode 100644 src/player-attack/attack-chaos-effect.c create mode 100644 src/player-attack/attack-chaos-effect.h create mode 100644 src/player-attack/blood-sucking-processor.c create mode 100644 src/player-attack/blood-sucking-processor.h create mode 100644 src/player-attack/player-attack-util.h create mode 100644 src/player-attack/player-attack.c create mode 100644 src/player-attack/player-attack.h delete mode 100644 src/player-damage.c delete mode 100644 src/player-damage.h create mode 100644 src/player-info/avatar.c create mode 100644 src/player-info/avatar.h create mode 100644 src/player-info/base-status-info.c create mode 100644 src/player-info/base-status-info.h create mode 100644 src/player-info/base-status-types.h create mode 100644 src/player-info/body-improvement-info.c create mode 100644 src/player-info/body-improvement-info.h create mode 100644 src/player-info/class-ability-info.c create mode 100644 src/player-info/class-ability-info.h create mode 100644 src/player-info/mutation-info.c create mode 100644 src/player-info/mutation-info.h create mode 100644 src/player-info/race-ability-info.c create mode 100644 src/player-info/race-ability-info.h create mode 100644 src/player-info/resistance-info.c create mode 100644 src/player-info/resistance-info.h create mode 100644 src/player-info/self-info-util.c create mode 100644 src/player-info/self-info-util.h create mode 100644 src/player-info/self-info.c create mode 100644 src/player-info/self-info.h create mode 100644 src/player-info/weapon-effect-info.c create mode 100644 src/player-info/weapon-effect-info.h delete mode 100644 src/player-move.c delete mode 100644 src/player-move.h delete mode 100644 src/player-status.c delete mode 100644 src/player-status.h create mode 100644 src/player/attack-defense-types.h create mode 100644 src/player/digestion-processor.c create mode 100644 src/player/digestion-processor.h create mode 100644 src/player/eldritch-horror.c create mode 100644 src/player/eldritch-horror.h create mode 100644 src/player/mimic-info-table.c create mode 100644 src/player/mimic-info-table.h create mode 100644 src/player/patron.c create mode 100644 src/player/patron.h create mode 100644 src/player/permanent-resistances.c create mode 100644 src/player/permanent-resistances.h create mode 100644 src/player/player-class.c create mode 100644 src/player/player-class.h create mode 100644 src/player/player-classes-types.h create mode 100644 src/player/player-damage.c create mode 100644 src/player/player-damage.h create mode 100644 src/player/player-move.c create mode 100644 src/player/player-move.h create mode 100644 src/player/player-personalities-types.h create mode 100644 src/player/player-personality.c create mode 100644 src/player/player-personality.h create mode 100644 src/player/player-race-types.h create mode 100644 src/player/player-race.c create mode 100644 src/player/player-race.h create mode 100644 src/player/player-realm.c create mode 100644 src/player/player-realm.h create mode 100644 src/player/player-sex.c create mode 100644 src/player/player-sex.h create mode 100644 src/player/player-skill.c create mode 100644 src/player/player-skill.h create mode 100644 src/player/player-status-flags.c create mode 100644 src/player/player-status-flags.h create mode 100644 src/player/player-status-table.c create mode 100644 src/player/player-status-table.h create mode 100644 src/player/player-status.c create mode 100644 src/player/player-status.h create mode 100644 src/player/player-view.c create mode 100644 src/player/player-view.h create mode 100644 src/player/process-death.c create mode 100644 src/player/process-death.h create mode 100644 src/player/process-name.c create mode 100644 src/player/process-name.h create mode 100644 src/player/race-info-table.c create mode 100644 src/player/race-info-table.h create mode 100644 src/player/race-resistances.c create mode 100644 src/player/race-resistances.h create mode 100644 src/player/selfinfo.c create mode 100644 src/player/special-defense-types.h create mode 100644 src/player/temporary-resistances.c create mode 100644 src/player/temporary-resistances.h delete mode 100644 src/projection.c delete mode 100644 src/projection.h delete mode 100644 src/quest.c delete mode 100644 src/quest.h delete mode 100644 src/racial.c create mode 100644 src/racial/class-racial-switcher.c create mode 100644 src/racial/class-racial-switcher.h create mode 100644 src/racial/mutation-racial-selector.c create mode 100644 src/racial/mutation-racial-selector.h create mode 100644 src/racial/race-racial-command-setter.c create mode 100644 src/racial/race-racial-command-setter.h create mode 100644 src/racial/racial-android.c create mode 100644 src/racial/racial-android.h create mode 100644 src/racial/racial-balrog.c create mode 100644 src/racial/racial-balrog.h create mode 100644 src/racial/racial-draconian.c create mode 100644 src/racial/racial-draconian.h create mode 100644 src/racial/racial-kutar.c create mode 100644 src/racial/racial-kutar.h create mode 100644 src/racial/racial-switcher.c create mode 100644 src/racial/racial-switcher.h create mode 100644 src/racial/racial-util.c create mode 100644 src/racial/racial-util.h create mode 100644 src/racial/racial-vampire.c create mode 100644 src/racial/racial-vampire.h delete mode 100644 src/readdib.c delete mode 100644 src/realm-arcane.c delete mode 100644 src/realm-arcane.h delete mode 100644 src/realm-chaos.c delete mode 100644 src/realm-chaos.h delete mode 100644 src/realm-craft.c delete mode 100644 src/realm-craft.h delete mode 100644 src/realm-crusade.c delete mode 100644 src/realm-crusade.h delete mode 100644 src/realm-daemon.c delete mode 100644 src/realm-daemon.h delete mode 100644 src/realm-death.c delete mode 100644 src/realm-death.h delete mode 100644 src/realm-hex.c delete mode 100644 src/realm-hex.h delete mode 100644 src/realm-hissatsu.c delete mode 100644 src/realm-hissatsu.h delete mode 100644 src/realm-life.c delete mode 100644 src/realm-life.h delete mode 100644 src/realm-nature.c delete mode 100644 src/realm-nature.h delete mode 100644 src/realm-song.c delete mode 100644 src/realm-song.h delete mode 100644 src/realm-sorcery.c delete mode 100644 src/realm-sorcery.h delete mode 100644 src/realm-trump.c delete mode 100644 src/realm-trump.h create mode 100644 src/realm/realm-arcane.c create mode 100644 src/realm/realm-arcane.h create mode 100644 src/realm/realm-chaos.c create mode 100644 src/realm/realm-chaos.h create mode 100644 src/realm/realm-craft.c create mode 100644 src/realm/realm-craft.h create mode 100644 src/realm/realm-crusade.c create mode 100644 src/realm/realm-crusade.h create mode 100644 src/realm/realm-death.c create mode 100644 src/realm/realm-death.h create mode 100644 src/realm/realm-demon.c create mode 100644 src/realm/realm-demon.h create mode 100644 src/realm/realm-hex-numbers.h create mode 100644 src/realm/realm-hex.c create mode 100644 src/realm/realm-hex.h create mode 100644 src/realm/realm-hissatsu.c create mode 100644 src/realm/realm-hissatsu.h create mode 100644 src/realm/realm-life.c create mode 100644 src/realm/realm-life.h create mode 100644 src/realm/realm-names-table.c create mode 100644 src/realm/realm-names-table.h create mode 100644 src/realm/realm-nature.c create mode 100644 src/realm/realm-nature.h create mode 100644 src/realm/realm-song-numbers.h create mode 100644 src/realm/realm-song.c create mode 100644 src/realm/realm-song.h create mode 100644 src/realm/realm-sorcery.c create mode 100644 src/realm/realm-sorcery.h create mode 100644 src/realm/realm-trump.c create mode 100644 src/realm/realm-trump.h create mode 100644 src/realm/realm-types.h delete mode 100644 src/report.c create mode 100644 src/room/cave-filler.c create mode 100644 src/room/cave-filler.h create mode 100644 src/room/door-definition.c create mode 100644 src/room/door-definition.h create mode 100644 src/room/lake-types.h create mode 100644 src/room/pit-nest-kinds-table.c create mode 100644 src/room/pit-nest-kinds-table.h create mode 100644 src/room/room-generator.c create mode 100644 src/room/room-generator.h create mode 100644 src/room/room-info-table.c create mode 100644 src/room/room-info-table.h create mode 100644 src/room/room-types.h create mode 100644 src/room/rooms-builder.c create mode 100644 src/room/rooms-builder.h create mode 100644 src/room/rooms-city.c create mode 100644 src/room/rooms-city.h create mode 100644 src/room/rooms-fractal.c create mode 100644 src/room/rooms-fractal.h create mode 100644 src/room/rooms-maze-vault.c create mode 100644 src/room/rooms-maze-vault.h create mode 100644 src/room/rooms-normal.c create mode 100644 src/room/rooms-normal.h create mode 100644 src/room/rooms-pit-nest.c create mode 100644 src/room/rooms-pit-nest.h create mode 100644 src/room/rooms-special.c create mode 100644 src/room/rooms-special.h create mode 100644 src/room/rooms-trap.c create mode 100644 src/room/rooms-trap.h create mode 100644 src/room/rooms-vault.c create mode 100644 src/room/rooms-vault.h create mode 100644 src/room/space-finder.c create mode 100644 src/room/space-finder.h create mode 100644 src/room/treasure-deployment.c create mode 100644 src/room/treasure-deployment.h create mode 100644 src/room/vault-builder.c create mode 100644 src/room/vault-builder.h delete mode 100644 src/rooms-city.c delete mode 100644 src/rooms-city.h delete mode 100644 src/rooms-fractal.c delete mode 100644 src/rooms-fractal.h delete mode 100644 src/rooms-normal.c delete mode 100644 src/rooms-normal.h delete mode 100644 src/rooms-pitnest.c delete mode 100644 src/rooms-pitnest.h delete mode 100644 src/rooms-special.c delete mode 100644 src/rooms-special.h delete mode 100644 src/rooms-trap.c delete mode 100644 src/rooms-trap.h delete mode 100644 src/rooms-vault.c delete mode 100644 src/rooms-vault.h delete mode 100644 src/rooms.c delete mode 100644 src/rooms.h delete mode 100644 src/rumor.c delete mode 100644 src/rumor.h delete mode 100644 src/save.c create mode 100644 src/save/floor-writer.c create mode 100644 src/save/floor-writer.h create mode 100644 src/save/info-writer.c create mode 100644 src/save/info-writer.h create mode 100644 src/save/item-writer.c create mode 100644 src/save/item-writer.h create mode 100644 src/save/monster-writer.c create mode 100644 src/save/monster-writer.h create mode 100644 src/save/player-writer.c create mode 100644 src/save/player-writer.h create mode 100644 src/save/save-util.c create mode 100644 src/save/save-util.h create mode 100644 src/save/save.c create mode 100644 src/save/save.h delete mode 100644 src/scores.c delete mode 100644 src/selfinfo.c delete mode 100644 src/selfinfo.h delete mode 100644 src/shoot.c delete mode 100644 src/shoot.h delete mode 100644 src/snipe.c delete mode 100644 src/sort.c delete mode 100644 src/sort.h create mode 100644 src/specific-object/blade-turner.c create mode 100644 src/specific-object/blade-turner.h create mode 100644 src/specific-object/bloody-moon.c create mode 100644 src/specific-object/bloody-moon.h create mode 100644 src/specific-object/bow.c create mode 100644 src/specific-object/bow.h create mode 100644 src/specific-object/chest.c create mode 100644 src/specific-object/chest.h create mode 100644 src/specific-object/death-crimson.c create mode 100644 src/specific-object/death-crimson.h create mode 100644 src/specific-object/death-scythe.c create mode 100644 src/specific-object/death-scythe.h create mode 100644 src/specific-object/monster-ball.c create mode 100644 src/specific-object/monster-ball.h create mode 100644 src/specific-object/muramasa.c create mode 100644 src/specific-object/muramasa.h create mode 100644 src/specific-object/ring-of-power.c create mode 100644 src/specific-object/ring-of-power.h create mode 100644 src/specific-object/toragoroshi.c create mode 100644 src/specific-object/toragoroshi.h create mode 100644 src/specific-object/torch.c create mode 100644 src/specific-object/torch.h create mode 100644 src/spell-kind/blood-curse.c create mode 100644 src/spell-kind/blood-curse.h create mode 100644 src/spell-kind/earthquake.c create mode 100644 src/spell-kind/earthquake.h create mode 100644 src/spell-kind/magic-item-recharger.c create mode 100644 src/spell-kind/magic-item-recharger.h create mode 100644 src/spell-kind/spells-beam.c create mode 100644 src/spell-kind/spells-beam.h create mode 100644 src/spell-kind/spells-charm.c create mode 100644 src/spell-kind/spells-charm.h create mode 100644 src/spell-kind/spells-curse-removal.c create mode 100644 src/spell-kind/spells-curse-removal.h create mode 100644 src/spell-kind/spells-detection.c create mode 100644 src/spell-kind/spells-detection.h create mode 100644 src/spell-kind/spells-enchant.c create mode 100644 src/spell-kind/spells-enchant.h create mode 100644 src/spell-kind/spells-equipment.c create mode 100644 src/spell-kind/spells-equipment.h create mode 100644 src/spell-kind/spells-fetcher.c create mode 100644 src/spell-kind/spells-fetcher.h create mode 100644 src/spell-kind/spells-floor.c create mode 100644 src/spell-kind/spells-floor.h create mode 100644 src/spell-kind/spells-genocide.c create mode 100644 src/spell-kind/spells-genocide.h create mode 100644 src/spell-kind/spells-grid.c create mode 100644 src/spell-kind/spells-grid.h create mode 100644 src/spell-kind/spells-launcher.c create mode 100644 src/spell-kind/spells-launcher.h create mode 100644 src/spell-kind/spells-lite.c create mode 100644 src/spell-kind/spells-lite.h create mode 100644 src/spell-kind/spells-neighbor.c create mode 100644 src/spell-kind/spells-neighbor.h create mode 100644 src/spell-kind/spells-perception.c create mode 100644 src/spell-kind/spells-perception.h create mode 100644 src/spell-kind/spells-pet.c create mode 100644 src/spell-kind/spells-pet.h create mode 100644 src/spell-kind/spells-polymorph.c create mode 100644 src/spell-kind/spells-polymorph.h create mode 100644 src/spell-kind/spells-random.c create mode 100644 src/spell-kind/spells-random.h create mode 100644 src/spell-kind/spells-sight.c create mode 100644 src/spell-kind/spells-sight.h create mode 100644 src/spell-kind/spells-specific-bolt.c create mode 100644 src/spell-kind/spells-specific-bolt.h create mode 100644 src/spell-kind/spells-teleport.c create mode 100644 src/spell-kind/spells-teleport.h create mode 100644 src/spell-kind/spells-world.c create mode 100644 src/spell-kind/spells-world.h create mode 100644 src/spell-realm/spells-arcane.c create mode 100644 src/spell-realm/spells-arcane.h create mode 100644 src/spell-realm/spells-chaos.c create mode 100644 src/spell-realm/spells-chaos.h create mode 100644 src/spell-realm/spells-craft.c create mode 100644 src/spell-realm/spells-craft.h create mode 100644 src/spell-realm/spells-crusade.c create mode 100644 src/spell-realm/spells-crusade.h create mode 100644 src/spell-realm/spells-demon.c create mode 100644 src/spell-realm/spells-demon.h create mode 100644 src/spell-realm/spells-hex.c create mode 100644 src/spell-realm/spells-hex.h create mode 100644 src/spell-realm/spells-nature.c create mode 100644 src/spell-realm/spells-nature.h create mode 100644 src/spell-realm/spells-song.c create mode 100644 src/spell-realm/spells-song.h create mode 100644 src/spell-realm/spells-sorcery.c create mode 100644 src/spell-realm/spells-sorcery.h create mode 100644 src/spell-realm/spells-trump.c create mode 100644 src/spell-realm/spells-trump.h create mode 100644 src/spell/range-calc.c create mode 100644 src/spell/range-calc.h create mode 100644 src/spell/spell-info.c create mode 100644 src/spell/spell-info.h create mode 100644 src/spell/spell-types.h create mode 100644 src/spell/spells-describer.c create mode 100644 src/spell/spells-describer.h create mode 100644 src/spell/spells-diceroll.c create mode 100644 src/spell/spells-diceroll.h create mode 100644 src/spell/spells-execution.c create mode 100644 src/spell/spells-execution.h create mode 100644 src/spell/spells-object.c create mode 100644 src/spell/spells-object.h create mode 100644 src/spell/spells-staff-only.c create mode 100644 src/spell/spells-staff-only.h create mode 100644 src/spell/spells-status.c create mode 100644 src/spell/spells-status.h create mode 100644 src/spell/spells-summon.c create mode 100644 src/spell/spells-summon.h create mode 100644 src/spell/spells-util.h create mode 100644 src/spell/summon-types.h create mode 100644 src/spell/technic-info-table.c create mode 100644 src/spell/technic-info-table.h delete mode 100644 src/spells-diceroll.c delete mode 100644 src/spells-diceroll.h delete mode 100644 src/spells-floor.c delete mode 100644 src/spells-floor.h delete mode 100644 src/spells-object.c delete mode 100644 src/spells-object.h delete mode 100644 src/spells-status.c delete mode 100644 src/spells-status.h delete mode 100644 src/spells-summon.c delete mode 100644 src/spells-summon.h delete mode 100644 src/spells-world.c delete mode 100644 src/spells-world.h delete mode 100644 src/spells.h delete mode 100644 src/spells1.c delete mode 100644 src/spells2.c delete mode 100644 src/spells3.c create mode 100644 src/status/action-setter.c create mode 100644 src/status/action-setter.h create mode 100644 src/status/bad-status-setter.c create mode 100644 src/status/bad-status-setter.h create mode 100644 src/status/base-status.c create mode 100644 src/status/base-status.h create mode 100644 src/status/body-improvement.c create mode 100644 src/status/body-improvement.h create mode 100644 src/status/buff-setter.c create mode 100644 src/status/buff-setter.h create mode 100644 src/status/element-resistance.c create mode 100644 src/status/element-resistance.h create mode 100644 src/status/experience.c create mode 100644 src/status/experience.h create mode 100644 src/status/shape-changer.c create mode 100644 src/status/shape-changer.h create mode 100644 src/status/sight-setter.c create mode 100644 src/status/sight-setter.h create mode 100644 src/status/temporary-resistance.c create mode 100644 src/status/temporary-resistance.h delete mode 100644 src/store.c delete mode 100644 src/store.h create mode 100644 src/store/black-market.c create mode 100644 src/store/black-market.h create mode 100644 src/store/home.c create mode 100644 src/store/home.h create mode 100644 src/store/museum.c create mode 100644 src/store/museum.h create mode 100644 src/store/owner-insults.c create mode 100644 src/store/owner-insults.h create mode 100644 src/store/pricing.c create mode 100644 src/store/pricing.h create mode 100644 src/store/purchase-order.c create mode 100644 src/store/purchase-order.h create mode 100644 src/store/rumor.c create mode 100644 src/store/rumor.h create mode 100644 src/store/say-comments.c create mode 100644 src/store/say-comments.h create mode 100644 src/store/sell-order.c create mode 100644 src/store/sell-order.h create mode 100644 src/store/service-checker.c create mode 100644 src/store/service-checker.h create mode 100644 src/store/store-owner-comments.c create mode 100644 src/store/store-owner-comments.h create mode 100644 src/store/store-owners.c create mode 100644 src/store/store-owners.h create mode 100644 src/store/store-util.c create mode 100644 src/store/store-util.h create mode 100644 src/store/store.c create mode 100644 src/store/store.h create mode 100644 src/sv-definition/sv-amulet-types.h create mode 100644 src/sv-definition/sv-armor-types.h create mode 100644 src/sv-definition/sv-bow-types.h create mode 100644 src/sv-definition/sv-digging-types.h create mode 100644 src/sv-definition/sv-food-types.h create mode 100644 src/sv-definition/sv-lite-types.h create mode 100644 src/sv-definition/sv-other-types.h create mode 100644 src/sv-definition/sv-potion-types.h create mode 100644 src/sv-definition/sv-protector-types.h create mode 100644 src/sv-definition/sv-ring-types.h create mode 100644 src/sv-definition/sv-rod-types.h create mode 100644 src/sv-definition/sv-scroll-types.h create mode 100644 src/sv-definition/sv-staff-types.h create mode 100644 src/sv-definition/sv-wand-types.h create mode 100644 src/sv-definition/sv-weapon-types.h create mode 100644 src/system/alloc-entries.c create mode 100644 src/system/alloc-entries.h create mode 100644 src/system/alloc-entry-definition.h create mode 100644 src/system/angband-version.h create mode 100644 src/system/angband.h create mode 100644 src/system/artifact-type-definition.c create mode 100644 src/system/artifact-type-definition.h create mode 100644 src/system/building-type-definition.c create mode 100644 src/system/building-type-definition.h create mode 100644 src/system/dungeon-data-definition.h create mode 100644 src/system/floor-type-definition.h create mode 100644 src/system/game-option-types.h create mode 100644 src/system/gamevalue.h create mode 100644 src/system/h-basic.h create mode 100644 src/system/h-config.h create mode 100644 src/system/h-define.h create mode 100644 src/system/h-system.h create mode 100644 src/system/h-type.h create mode 100644 src/system/monster-race-definition.h create mode 100644 src/system/monster-type-definition.h create mode 100644 src/system/object-type-definition.h create mode 100644 src/system/system-variables.c create mode 100644 src/system/system-variables.h delete mode 100644 src/tables.c create mode 100644 src/target/grid-selector.c create mode 100644 src/target/grid-selector.h create mode 100644 src/target/projection-path-calculator.c create mode 100644 src/target/projection-path-calculator.h create mode 100644 src/target/target-checker.c create mode 100644 src/target/target-checker.h create mode 100644 src/target/target-describer.c create mode 100644 src/target/target-describer.h create mode 100644 src/target/target-getter.c create mode 100644 src/target/target-getter.h create mode 100644 src/target/target-preparation.c create mode 100644 src/target/target-preparation.h create mode 100644 src/target/target-setter.c create mode 100644 src/target/target-setter.h create mode 100644 src/target/target-types.h delete mode 100644 src/term.c delete mode 100644 src/term.h create mode 100644 src/term/gameterm.c create mode 100644 src/term/gameterm.h create mode 100644 src/term/readdib.c rename src/{ => term}/readdib.h (100%) create mode 100644 src/term/screen-processor.c create mode 100644 src/term/screen-processor.h create mode 100644 src/term/term-color-types.h create mode 100644 src/term/z-form.c create mode 100644 src/term/z-form.h create mode 100644 src/term/z-rand.c create mode 100644 src/term/z-rand.h create mode 100644 src/term/z-term.c create mode 100644 src/term/z-term.h create mode 100644 src/term/z-util.c create mode 100644 src/term/z-util.h create mode 100644 src/term/z-virt.c create mode 100644 src/term/z-virt.h delete mode 100644 src/trap.c delete mode 100644 src/trap.h delete mode 100644 src/types.h delete mode 100644 src/util.c create mode 100644 src/util/angband-files.c create mode 100644 src/util/angband-files.h create mode 100644 src/util/bit-flags-calculator.h create mode 100644 src/util/buffer-shaper.c create mode 100644 src/util/buffer-shaper.h create mode 100644 src/util/int-char-converter.h create mode 100644 src/util/object-sort.c create mode 100644 src/util/object-sort.h create mode 100644 src/util/quarks.c create mode 100644 src/util/quarks.h create mode 100644 src/util/sort.c create mode 100644 src/util/sort.h create mode 100644 src/util/string-processor.c create mode 100644 src/util/string-processor.h create mode 100644 src/util/tag-sorter.c create mode 100644 src/util/tag-sorter.h delete mode 100644 src/variable.c delete mode 100644 src/view-mainwindow.c create mode 100644 src/view/display-birth.c create mode 100644 src/view/display-birth.h create mode 100644 src/view/display-characteristic.c create mode 100644 src/view/display-characteristic.h create mode 100644 src/view/display-fruit.c create mode 100644 src/view/display-fruit.h create mode 100644 src/view/display-inventory.c create mode 100644 src/view/display-inventory.h create mode 100644 src/view/display-lore-attacks.c create mode 100644 src/view/display-lore-attacks.h create mode 100644 src/view/display-lore-drops.c create mode 100644 src/view/display-lore-drops.h create mode 100644 src/view/display-lore-magics.c create mode 100644 src/view/display-lore-magics.h create mode 100644 src/view/display-lore-status.c create mode 100644 src/view/display-lore-status.h create mode 100644 src/view/display-lore.c create mode 100644 src/view/display-lore.h create mode 100644 src/view/display-map.c create mode 100644 src/view/display-map.h create mode 100644 src/view/display-messages.c create mode 100644 src/view/display-messages.h create mode 100644 src/view/display-monster-status.c create mode 100644 src/view/display-monster-status.h create mode 100644 src/view/display-player-middle.c create mode 100644 src/view/display-player-middle.h create mode 100644 src/view/display-player-misc-info.c create mode 100644 src/view/display-player-misc-info.h create mode 100644 src/view/display-player-stat-info.c create mode 100644 src/view/display-player-stat-info.h create mode 100644 src/view/display-player.c create mode 100644 src/view/display-player.h create mode 100644 src/view/display-self-info.c create mode 100644 src/view/display-self-info.h create mode 100644 src/view/display-store.c create mode 100644 src/view/display-store.h create mode 100644 src/view/display-util.c create mode 100644 src/view/display-util.h create mode 100644 src/view/object-describer.c create mode 100644 src/view/object-describer.h create mode 100644 src/view/status-bars-table.c create mode 100644 src/view/status-bars-table.h create mode 100644 src/view/status-first-page.c create mode 100644 src/view/status-first-page.h delete mode 100644 src/warning.c delete mode 100644 src/warning.h delete mode 100644 src/wild.c delete mode 100644 src/wild.h create mode 100644 src/window/display-sub-window-items.c create mode 100644 src/window/display-sub-window-items.h create mode 100644 src/window/display-sub-window-spells.c create mode 100644 src/window/display-sub-window-spells.h create mode 100644 src/window/display-sub-windows.c create mode 100644 src/window/display-sub-windows.h create mode 100644 src/window/main-window-equipments.c create mode 100644 src/window/main-window-equipments.h create mode 100644 src/window/main-window-left-frame.c create mode 100644 src/window/main-window-left-frame.h create mode 100644 src/window/main-window-row-column.h create mode 100644 src/window/main-window-stat-poster.c create mode 100644 src/window/main-window-stat-poster.h create mode 100644 src/window/main-window-util.c create mode 100644 src/window/main-window-util.h create mode 100644 src/wizard/artifact-analyzer.c create mode 100644 src/wizard/artifact-analyzer.h create mode 100644 src/wizard/artifact-bias-table.c create mode 100644 src/wizard/artifact-bias-table.h create mode 100644 src/wizard/cmd-wizard.c create mode 100644 src/wizard/cmd-wizard.h create mode 100644 src/wizard/fixed-artifacts-spoiler.c create mode 100644 src/wizard/fixed-artifacts-spoiler.h create mode 100644 src/wizard/items-spoiler.c create mode 100644 src/wizard/items-spoiler.h create mode 100644 src/wizard/monster-info-spoiler.c create mode 100644 src/wizard/monster-info-spoiler.h create mode 100644 src/wizard/spoiler-table.c create mode 100644 src/wizard/spoiler-table.h create mode 100644 src/wizard/spoiler-util.c create mode 100644 src/wizard/spoiler-util.h create mode 100644 src/wizard/tval-descriptions-table.c create mode 100644 src/wizard/tval-descriptions-table.h create mode 100644 src/wizard/wizard-item-modifier.c create mode 100644 src/wizard/wizard-item-modifier.h create mode 100644 src/wizard/wizard-messages.c create mode 100644 src/wizard/wizard-messages.h create mode 100644 src/wizard/wizard-special-process.c create mode 100644 src/wizard/wizard-special-process.h create mode 100644 src/wizard/wizard-spells.c create mode 100644 src/wizard/wizard-spells.h create mode 100644 src/wizard/wizard-spoiler.c create mode 100644 src/wizard/wizard-spoiler.h delete mode 100644 src/wizard1.c delete mode 100644 src/wizard2.c delete mode 100644 src/world.c delete mode 100644 src/world.h create mode 100644 src/world/world-movement-processor.c create mode 100644 src/world/world-movement-processor.h create mode 100644 src/world/world-object.c create mode 100644 src/world/world-object.h create mode 100644 src/world/world-turn-processor.c create mode 100644 src/world/world-turn-processor.h create mode 100644 src/world/world.c create mode 100644 src/world/world.h delete mode 100644 src/xtra2.c delete mode 100644 src/z-config.h delete mode 100644 src/z-form.c delete mode 100644 src/z-form.h delete mode 100644 src/z-rand.c delete mode 100644 src/z-rand.h delete mode 100644 src/z-term.c delete mode 100644 src/z-term.h delete mode 100644 src/z-util.c delete mode 100644 src/z-util.h delete mode 100644 src/z-virt.c delete mode 100644 src/z-virt.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..5a899e772 --- /dev/null +++ b/.clang-format @@ -0,0 +1,115 @@ +--- +Language: Cpp +# BasedOnStyle: WebKit +AccessModifierOffset: -4 +AlignAfterOpenBracket: DontAlign +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: false +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: All +BreakBeforeBraces: WebKit +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 160 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: Inner +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +RawStringFormats: + - Delimiters: [pb] + Language: TextProto + BasedOnStyle: google +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 8 +UseTab: Never +... + diff --git a/.gitignore b/.gitignore index 3a3836b59..73206c8c1 100644 --- a/.gitignore +++ b/.gitignore @@ -13,22 +13,24 @@ autoconf.h.in config.log config.status Makefile -src/.deps -src/autoconf.h -src/stamp-h1 +src/**/.deps +src/**/.dirstamp +src/**/autoconf.h +src/**/stamp-h1 # generated by gcc -src/*.o -src/hengband +src/**/*.o +src/Bakabakaband # Ignore generated documents by Doxygen doxygen/html/ # Windows binary -Hengband.exe +Bakabakaband.exe +Bakabakaband.exe.lastcodeanalysissucceeded # game data files auto generated -Hengband.INI +Bakabakaband.INI lib/user/ lib/save/ *.raw @@ -50,6 +52,7 @@ lib/save/ *.userprefs # Build results +[Ee]nglish-[Dd]ebug/ [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ diff --git a/Hengband/Bakabakaband.sln b/Hengband/Bakabakaband.sln new file mode 100644 index 000000000..ed17804ec --- /dev/null +++ b/Hengband/Bakabakaband.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30011.22 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{82CF9010-9443-4FFF-ADF0-0D3E81C732CC}" + ProjectSection(SolutionItems) = preProject + ..\.clang-format = ..\.clang-format + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bakabakaband", "Hengband\Bakabakaband.vcxproj", "{C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + English-Debug|x86 = English-Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Debug|x86.ActiveCfg = Debug|Win32 + {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Debug|x86.Build.0 = Debug|Win32 + {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.English-Debug|x86.ActiveCfg = English-Debug|Win32 + {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.English-Debug|x86.Build.0 = English-Debug|Win32 + {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Release|x86.ActiveCfg = Release|Win32 + {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2} = {82CF9010-9443-4FFF-ADF0-0D3E81C732CC} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4A5E2796-8815-4A42-BF8D-FFEA2E38264E} + EndGlobalSection +EndGlobal diff --git a/Hengband/Hengband/Bakabakaband.vcxproj b/Hengband/Hengband/Bakabakaband.vcxproj new file mode 100644 index 000000000..004d2b6cd --- /dev/null +++ b/Hengband/Hengband/Bakabakaband.vcxproj @@ -0,0 +1,1750 @@ + + + + + + + + + StaticLibrary + true + v120 + Unicode + + + StaticLibrary + false + v120 + Unicode + + + + Debug + Win32 + + + English-Debug + Win32 + + + Release + Win32 + + + + {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2} + Bakabakaband + 10.0 + Bakabakaband + + + + Application + MultiByte + true + v142 + + + Application + MultiByte + false + v142 + false + + + Application + MultiByte + false + v142 + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + ..\..\ + ..\..\ + $(Configuration)\ + $(Configuration)\ + ../../\ + $(Configuration)\ + + + ..\..\src\cmd;..\..\src\combat;..\..\src;$(IncludePath) + + + ..\..\src\cmd;..\..\src\combat;..\..\src;$(IncludePath) + + + ..\..\src\cmd;..\..\src\combat;..\..\src;$(IncludePath) + + + + Disabled + WINDOWS;JP;SJIS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions);HAVE_STDINT_H; + false + EnableFastChecks + MultiThreadedDLL + EnableAllWarnings + EditAndContinue + CompileAsC + 4061;4062;4127;4244;4255;4668;4710;4820;4996;4774;5045;%(DisableSpecificWarnings) + true + + + winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;wsock32.lib;%(AdditionalDependencies) + true + MachineX86 + LinkVerbose + Windows + + + + + + + + + Disabled + WINDOWS;SJIS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level4 + EditAndContinue + CompileAsC + 4127;4996;4244;%(DisableSpecificWarnings) + + + winmm.lib;wsock32.lib;%(AdditionalDependencies) + true + MachineX86 + LinkVerbose + Windows + + + + + MaxSpeed + true + WINDOWS;JP;SJIS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions);HAVE_STDINT_H; + MultiThreaded + true + Level3 + ProgramDatabase + 4244;4996;%(DisableSpecificWarnings) + + + winmm.lib;wsock32.lib;%(AdditionalDependencies) + true + true + true + MachineX86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + このプロジェクトは、このコンピューター上にない NuGet パッケージを参照しています。それらのパッケージをダウンロードするには、[NuGet パッケージの復元] を使用します。詳細については、http://go.microsoft.com/fwlink/?LinkID=322105 を参照してください。見つからないファイルは {0} です。 + + + + + + + + \ No newline at end of file diff --git a/Hengband/Hengband/Bakabakaband.vcxproj.filters b/Hengband/Hengband/Bakabakaband.vcxproj.filters new file mode 100644 index 000000000..9f2e764fb --- /dev/null +++ b/Hengband/Hengband/Bakabakaband.vcxproj.filters @@ -0,0 +1,4928 @@ + + + + + + combat + + + view + + + view + + + player + + + player + + + view + + + player + + + view + + + player + + + io + + + view + + + view + + + view + + + io + + + player + + + core + + + io + + + io + + + monster + + + io + + + market + + + market + + + market + + + market + + + view + + + market + + + market + + + player + + + player + + + main + + + main + + + knowledge + + + knowledge + + + object + + + object + + + knowledge + + + knowledge + + + knowledge + + + knowledge + + + knowledge + + + knowledge + + + knowledge + + + io + + + knowledge + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + room + + + io + + + io + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + effect + + + effect + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + effect + + + spell + + + spell + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + core + + + birth + + + core + + + core + + + floor + + + core + + + core + + + core + + + mutation + + + object + + + core + + + inventory + + + inventory + + + wizard + + + wizard + + + io + + + inventory + + + core + + + player + + + world + + + world + + + world + + + dungeon + + + dungeon + + + core + + + floor + + + floor + + + floor + + + floor + + + object + + + room + + + room + + + room + + + room + + + room + + + room + + + room + + + player + + + player + + + player + + + player + + + player + + + player + + + player + + + player + + + monster + + + system + + + spell + + + spell + + + spell + + + spell + + + locale + + + locale + + + grid + + + grid + + + grid + + + monster + + + inventory + + + term + + + term + + + term + + + term + + + term + + + term + + + floor + + + io + + + floor + + + player + + + birth + + + term + + + object + + + io + + + io + + + dungeon + + + core + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + view + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + io + + + io + + + market + + + market + + + market + + + market + + + market + + + market + + + market + + + market + + + market + + + market + + + market + + + store + + + store + + + store + + + store + + + store + + + store + + + store + + + combat + + + combat + + + combat + + + combat + + + combat + + + combat + + + inventory + + + mind + + + combat + + + pet + + + pet + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-action + + + cmd-action + + + cmd-action + + + cmd-action + + + cmd-action + + + cmd-io + + + knowledge + + + knowledge + + + io-dump + + + io-dump + + + io-dump + + + io-dump + + + io-dump + + + knowledge + + + floor + + + view + + + inventory + + + object + + + realm + + + cmd-building + + + cmd-building + + + world + + + object + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + perception + + + perception + + + object + + + util + + + object + + + spell + + + spell + + + specific-object + + + specific-object + + + specific-object + + + specific-object + + + spell + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + mind + + + mind + + + mind + + + mind + + + mind + + + mind + + + mind + + + mind + + + spell-realm + + + spell-realm + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-realm + + + player-attack + + + player-attack + + + player-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + melee + + + melee + + + melee + + + melee + + + object-enchant + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + floor + + + info-reader + + + perception + + + core + + + object + + + object + + + object-enchant + + + object-enchant + + + monster-race + + + monster-race + + + mind + + + player + + + monster + + + monster + + + core + + + monster + + + mspell + + + cmd-io + + + view + + + monster + + + monster + + + monster + + + monster + + + lore + + + lore + + + lore + + + view + + + lore + + + lore + + + view + + + view + + + view + + + lore + + + view + + + monster-attack + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + util + + + system + + + util + + + cmd-io + + + main + + + io + + + util + + + view + + + core + + + term + + + util + + + io + + + io + + + game-option + + + util + + + util + + + system + + + spell-realm + + + mspell + + + view + + + core + + + cmd-visual + + + view + + + cmd-visual + + + cmd-visual + + + floor + + + grid + + + io + + + io + + + core + + + realm + + + wizard + + + wizard + + + wizard + + + spell-realm + + + spell-kind + + + spell-kind + + + mind + + + spell + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + mind + + + object + + + player + + + status + + + status + + + status + + + wizard + + + spell-realm + + + status + + + status + + + status + + + spell-realm + + + mind + + + status + + + status + + + mspell + + + status + + + status + + + inventory + + + inventory + + + inventory + + + floor + + + inventory + + + view + + + inventory + + + spell-kind + + + spell-realm + + + spell-kind + + + spell-kind + + + mutation + + + specific-object + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + object-use + + + flavor + + + flavor + + + flavor + + + flavor + + + flavor + + + flavor + + + action + + + cmd-action + + + action + + + cmd-action + + + action + + + action + + + cmd-action + + + action + + + cmd-action + + + cmd-item + + + action + + + cmd-action + + + action + + + action + + + core + + + window + + + window + + + window + + + window + + + window + + + window + + + window + + + cmd-action + + + artifact + + + wizard + + + artifact + + + artifact + + + artifact + + + artifact + + + artifact + + + artifact + + + artifact + + + artifact + + + system + + + view + + + store + + + io + + + cmd-building + + + store + + + store + + + store + + + store + + + store + + + store + + + mind + + + racial + + + racial + + + racial + + + racial + + + racial + + + racial + + + floor + + + save + + + save + + + save + + + save + + + save + + + save + + + save + + + load + + + blue-magic + + + blue-magic + + + mind + + + blue-magic + + + blue-magic + + + blue-magic + + + blue-magic + + + mspell + + + blue-magic + + + blue-magic + + + blue-magic + + + blue-magic + + + melee + + + mspell + + + melee + + + melee + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + object-use + + + player + + + room + + + room + + + room + + + room + + + room + + + room + + + room + + + room + + + target + + + target + + + target + + + target + + + target + + + target + + + mind + + + mind + + + mind + + + mind + + + cmd-action + + + mutation + + + mutation + + + mutation + + + mutation + + + action + + + mutation + + + wizard + + + wizard + + + wizard + + + wizard + + + wizard + + + wizard + + + io-dump + + + wizard + + + floor + + + floor + + + floor + + + floor + + + floor + + + dungeon + + + grid + + + mind + + + cmd-action + + + racial + + + racial + + + racial + + + action + + + racial + + + action + + + player + + + monster-floor + + + monster-floor + + + dungeon + + + monster + + + player + + + floor + + + floor + + + floor + + + floor + + + action + + + object-activation + + + object-activation + + + object-activation + + + object-activation + + + object-activation + + + specific-object + + + specific-object + + + specific-object + + + object-activation + + + specific-object + + + object-activation + + + specific-object + + + object-activation + + + specific-object + + + object-activation + + + effect + + + cmd-io + + + cmd-item + + + cmd-item + + + cmd-item + + + target + + + grid + + + floor + + + room + + + grid + + + grid + + + core + + + main + + + main + + + main + + + market + + + main + + + main + + + player-info + + + player-info + + + player-info + + + player-info + + + player-info + + + player-info + + + player-info + + + player-info + + + player-info + + + view + + + player-info + + + mind + + + mind + + + mind + + + spell-realm + + + spell-realm + + + mind + + + mind + + + monster-floor + + + monster-floor + + + + + combat + + + view + + + view + + + player + + + player + + + view + + + player + + + view + + + player + + + io + + + view + + + view + + + view + + + io + + + player + + + core + + + io + + + io + + + monster + + + io + + + market + + + market + + + market + + + market + + + view + + + market + + + market + + + player + + + player + + + main + + + main + + + knowledge + + + knowledge + + + object + + + object + + + knowledge + + + knowledge + + + knowledge + + + knowledge + + + knowledge + + + knowledge + + + knowledge + + + io + + + knowledge + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + room + + + io + + + io + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + autopick + + + effect + + + effect + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + realm + + + effect + + + spell + + + spell + + + spell + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + effect + + + core + + + core + + + birth + + + core + + + core + + + floor + + + core + + + core + + + core + + + mutation + + + object + + + core + + + inventory + + + inventory + + + wizard + + + wizard + + + io + + + inventory + + + core + + + player + + + world + + + world + + + world + + + dungeon + + + dungeon + + + core + + + floor + + + floor + + + floor + + + floor + + + object + + + room + + + room + + + room + + + room + + + room + + + room + + + player + + + player + + + player + + + player + + + player + + + player + + + player + + + player + + + monster + + + system + + + system + + + system + + + system + + + system + + + system + + + system + + + spell + + + spell + + + spell + + + spell + + + grid + + + grid + + + grid + + + monster + + + inventory + + + term + + + term + + + term + + + term + + + term + + + term + + + floor + + + io + + + floor + + + system + + + system + + + player + + + term + + + object + + + io + + + io + + + dungeon + + + core + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + view + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + birth + + + io + + + io + + + market + + + market + + + market + + + market + + + market + + + market + + + market + + + market + + + market + + + market + + + market + + + market + + + store + + + store + + + store + + + store + + + store + + + store + + + store + + + combat + + + combat + + + combat + + + combat + + + combat + + + combat + + + combat + + + inventory + + + mind + + + object + + + object + + + combat + + + pet + + + pet + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-item + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-io + + + cmd-action + + + cmd-action + + + cmd-action + + + cmd-action + + + cmd-action + + + cmd-io + + + knowledge + + + knowledge + + + io-dump + + + io-dump + + + io-dump + + + io-dump + + + io-dump + + + knowledge + + + floor + + + view + + + inventory + + + object + + + realm + + + cmd-building + + + cmd-building + + + world + + + object + + + sv-definition + + + sv-definition + + + sv-definition + + + sv-definition + + + sv-definition + + + sv-definition + + + sv-definition + + + sv-definition + + + sv-definition + + + sv-definition + + + sv-definition + + + sv-definition + + + sv-definition + + + sv-definition + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + sv-definition + + + object + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + object-enchant + + + perception + + + perception + + + object + + + util + + + object + + + spell + + + spell + + + realm + + + realm + + + specific-object + + + specific-object + + + specific-object + + + specific-object + + + spell + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + mind + + + mind + + + mind + + + mind + + + mind + + + mind + + + mind + + + mind + + + spell-realm + + + spell-realm + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-realm + + + player-attack + + + player-attack + + + player-attack + + + player-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + monster-attack + + + melee + + + melee + + + melee + + + melee + + + object-enchant + + + info-reader + + + info-reader + + + info-reader + + + term + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + info-reader + + + floor + + + info-reader + + + perception + + + core + + + object-enchant + + + art-definition + + + art-definition + + + art-definition + + + art-definition + + + art-definition + + + art-definition + + + object + + + object + + + object-enchant + + + object-enchant + + + art-definition + + + monster-race + + + monster-race + + + monster-race + + + mind + + + monster + + + mind + + + monster + + + room + + + monster + + + monster + + + player + + + system + + + monster + + + monster + + + core + + + system + + + monster + + + monster-race + + + monster-race + + + monster-race + + + monster-race + + + monster-race + + + monster-race + + + monster-race + + + monster-race + + + monster-race + + + monster-race + + + mspell + + + cmd-io + + + view + + + monster + + + monster + + + monster + + + monster + + + lore + + + lore + + + lore + + + view + + + lore + + + lore + + + view + + + view + + + view + + + lore + + + view + + + monster-attack + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + monster-floor + + + system + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + game-option + + + util + + + system + + + player + + + player + + + spell + + + system + + + player + + + realm + + + util + + + cmd-io + + + main + + + io + + + util + + + view + + + locale + + + locale + + + core + + + term + + + util + + + io + + + io + + + util + + + game-option + + + util + + + util + + + util + + + locale + + + system + + + system + + + spell-realm + + + mind + + + mspell + + + mspell + + + view + + + core + + + cmd-visual + + + view + + + cmd-visual + + + cmd-visual + + + floor + + + grid + + + io + + + io + + + player + + + core + + + realm + + + wizard + + + wizard + + + wizard + + + spell-realm + + + spell-kind + + + spell-kind + + + mind + + + spell + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + object-hook + + + mind + + + object + + + player + + + status + + + status + + + status + + + wizard + + + spell-realm + + + status + + + status + + + status + + + spell-realm + + + mind + + + status + + + status + + + mspell + + + status + + + status + + + inventory + + + inventory + + + inventory + + + floor + + + inventory + + + view + + + inventory + + + inventory + + + mutation + + + spell-kind + + + spell-realm + + + spell-kind + + + spell-kind + + + mutation + + + specific-object + + + spell-kind + + + spell-kind + + + spell-kind + + + spell-kind + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + player + + + load + + + load + + + load + + + load + + + load + + + load + + + load + + + core + + + core + + + object-use + + + flavor + + + flavor + + + flavor + + + flavor + + + flavor + + + flavor + + + flavor + + + action + + + cmd-action + + + action + + + cmd-action + + + action + + + action + + + cmd-action + + + action + + + cmd-action + + + cmd-item + + + action + + + cmd-action + + + grid + + + action + + + action + + + core + + + window + + + window + + + window + + + window + + + window + + + window + + + window + + + window + + + cmd-action + + + artifact + + + artifact + + + wizard + + + artifact + + + artifact + + + artifact + + + artifact + + + artifact + + + artifact + + + artifact + + + artifact + + + system + + + view + + + store + + + io + + + cmd-building + + + store + + + store + + + store + + + store + + + store + + + store + + + mind + + + racial + + + racial + + + racial + + + racial + + + racial + + + mind + + + racial + + + floor + + + floor + + + system + + + dungeon + + + floor + + + save + + + save + + + save + + + save + + + save + + + save + + + save + + + load + + + blue-magic + + + blue-magic + + + blue-magic + + + blue-magic + + + blue-magic + + + blue-magic + + + mspell + + + blue-magic + + + blue-magic + + + blue-magic + + + blue-magic + + + melee + + + mspell + + + melee + + + melee + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + mspell + + + object-use + + + player + + + room + + + room + + + room + + + room + + + room + + + system + + + room + + + room + + + room + + + room + + + room + + + target + + + target + + + target + + + target + + + target + + + target + + + target + + + mind + + + mind + + + mind + + + mind + + + mind + + + cmd-action + + + mind + + + mutation + + + mutation + + + mutation + + + mutation + + + action + + + mutation + + + wizard + + + wizard + + + wizard + + + wizard + + + wizard + + + wizard + + + io-dump + + + wizard + + + floor + + + floor + + + floor + + + floor + + + floor + + + floor + + + floor + + + dungeon + + + grid + + + mind + + + cmd-action + + + racial + + + racial + + + racial + + + action + + + racial + + + action + + + player + + + monster-floor + + + monster-floor + + + dungeon + + + monster + + + player + + + floor + + + floor + + + floor + + + floor + + + action + + + object-activation + + + object-activation + + + object-activation + + + object-activation + + + object-activation + + + specific-object + + + specific-object + + + specific-object + + + object-activation + + + specific-object + + + object-activation + + + specific-object + + + object-activation + + + specific-object + + + object-activation + + + effect + + + cmd-io + + + cmd-item + + + cmd-item + + + cmd-item + + + target + + + grid + + + floor + + + room + + + grid + + + grid + + + core + + + main + + + main + + + main + + + market + + + main + + + main + + + player-info + + + player-info + + + player-info + + + player-info + + + player-info + + + player-info + + + player-info + + + player-info + + + player-info + + + player-info + + + view + + + player-info + + + mind + + + mind + + + mind + + + spell-realm + + + spell-realm + + + mind + + + mind + + + monster-floor + + + monster-floor + + + spell + + + + + + + + + {c7e2056b-fda5-410a-8d23-03ba3f11c051} + + + {52a3c5b6-2312-47a9-bb95-15c0d5e95192} + + + {8fc15fd9-029b-4e7f-ae0b-75b2db215ad0} + + + {282dc0ea-8c5c-4253-b38c-4f4f0ad87ff9} + + + {1be1a971-e67f-4d7c-ace0-aab22a039851} + + + {dae7a35f-36af-4097-905f-b9b9aad50d6e} + + + {64225309-2ea6-4822-aeac-0e6165df9a8f} + + + {cbc72021-c88c-4625-b89b-ef126e300cf8} + + + {4bdec353-0cac-4e25-98f9-bcc55f2c0ec3} + + + {95a48e4b-b55a-4e99-a3c6-e8badbd1b2cf} + + + {e8e836da-e12b-42cc-9c09-17432cb83432} + + + {0e8eb37a-0944-4897-a2fd-e6097df5e5f8} + + + {7f5cb078-a335-428e-a2db-27ee6263155b} + + + {318835ed-a803-4459-921e-f6afc5411baa} + + + {ed8a9f97-b54e-4204-9076-f32f646f3762} + + + {4e443fe1-9ff8-4786-b43f-7e4d106760dc} + + + {c4ce5c0c-f907-4e62-abc1-5d9dbe7f1abf} + + + {c2383613-69b3-4973-bb9b-6fce783afa1d} + + + {060db85f-39b1-48fd-8b5f-7409eb6209b2} + + + {0e652835-2887-4970-9fa2-4ba77974e921} + + + {22328846-3669-435a-9731-f0998a1c3dfa} + + + {cbd4a56f-0cd0-47a4-96be-a0a4d85ad7d1} + + + {b37a544f-cca2-4c1f-b069-f109a6b6b119} + + + {12dd43b2-8ba5-4fc4-8d11-1901ec804390} + + + {93b0c1d1-0841-44fe-8503-d6729d290350} + + + {ad847f1c-b291-4640-93d2-21895fbee308} + + + {235e3199-b059-4a3c-a053-dd8604c8e9fd} + + + {738b47ea-2ba6-49a3-9bf8-a833ef46e218} + + + {be097f30-d18c-4e9a-a13f-eac4ee7a9d9a} + + + {d9907626-9c01-48b8-89da-065f7b8540b5} + + + {7c81caa7-dbd8-43f3-8481-9a2ae3967776} + + + {7af80633-259f-406b-a33d-23f6a83013d7} + + + {cefa5b29-56a9-41dc-a32e-8b9568821503} + + + {f578e89d-2670-4f24-8028-61896d5b733e} + + + {739c9774-e51a-46eb-87c1-cd7cd332e97c} + + + {9e020507-fdf0-4cfb-9d60-d9c26cbcf325} + + + {c7db74bd-7f58-4044-96c8-c5916d0ebaf1} + + + {e42f1944-e95c-42a8-97bf-9f959b313142} + + + {d12d97f4-76e6-4f8e-9f45-9905cf3863f9} + + + {2ed79129-9b65-4718-b9c4-ce4ef793c81f} + + + {1ce2167d-011b-47b5-8934-24c6d4d036e3} + + + {cc3a34dc-4ff0-473f-afa5-3b5ec0da5aaf} + + + {f197a2c1-d277-4d4d-b08b-586cf1f4f8f5} + + + {642ec95b-f054-4958-a614-49ccf88cfc25} + + + {fffcb35e-069c-4a97-ab60-0010a4d5d488} + + + {8de4a55f-fa83-496b-a42f-81078346c918} + + + {9db4d67c-5c55-4cc0-a9cd-643e5ffc3e73} + + + {d266d557-ad7c-4751-a1b1-04ced61292a6} + + + {14acbc0e-8760-48c6-860f-4c9fd993feef} + + + {149ff96c-b8c9-4df9-845d-d0618427d100} + + + {30be068e-64fc-431f-a90b-07f12e2539a4} + + + {6982e0e0-d2db-422e-8e92-77b1276e4030} + + + {e466c69b-eaf4-4110-bc9d-e865b36cc732} + + + {c2656391-c200-4334-8150-88f4691c6079} + + + {3e8ea357-82a2-4978-a257-338b953d1469} + + + {64e5a4de-e0d4-4090-93b9-314234362569} + + + {52768eef-323a-49a4-a895-f0030b35f667} + + + {9e0105e8-8250-4ac4-8a1c-cefd30485ecc} + + + {7554e8b1-1c3c-447b-8f1e-c18c09039419} + + + {aaa1b0db-fb73-43df-b204-45c07a934cd5} + + + {beb4a41a-dee4-4bdd-ac20-78da62c44fdf} + + + {2bfe9405-f65a-4dac-afde-56800ae04b9f} + + + {6b429e6d-e548-430e-9413-8bc2e0bda1ed} + + + {1789a1b0-5c89-4dfc-a4ba-1c3b711705b5} + + + {14dcf604-bbe5-4084-b4ff-124ea8c55654} + + + {9b6116c6-24e1-4d33-b3b5-3591f58fb9e1} + + + + + + \ No newline at end of file diff --git a/Hengband/Hengband/packages.config b/Hengband/Hengband/packages.config new file mode 100644 index 000000000..6659b9c20 --- /dev/null +++ b/Hengband/Hengband/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Hengband_vcs2015/Hengband.sln b/Hengband_vcs2015/Hengband.sln deleted file mode 100644 index 4caf8dc99..000000000 --- a/Hengband_vcs2015/Hengband.sln +++ /dev/null @@ -1,23 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 14.00 -# Visual C++ Express 2015 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hengband", "Hengband\Hengband.vcxproj", "{C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - English-Debug|Win32 = English-Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Debug|Win32.ActiveCfg = Debug|Win32 - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Debug|Win32.Build.0 = Debug|Win32 - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.English-Debug|Win32.ActiveCfg = English-Debug|Win32 - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.English-Debug|Win32.Build.0 = English-Debug|Win32 - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Release|Win32.ActiveCfg = Release|Win32 - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/Hengband_vcs2015/Hengband/Hengband.vcxproj b/Hengband_vcs2015/Hengband/Hengband.vcxproj deleted file mode 100644 index 872bc9535..000000000 --- a/Hengband_vcs2015/Hengband/Hengband.vcxproj +++ /dev/null @@ -1,327 +0,0 @@ - - - - StaticLibrary - true - v120 - Unicode - - - StaticLibrary - false - v120 - Unicode - - - - Debug - Win32 - - - English-Debug - Win32 - - - Release - Win32 - - - - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2} - Hengband - - - - Application - MultiByte - true - v140 - - - Application - MultiByte - false - v140 - - - Application - MultiByte - false - v140 - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - ..\..\ - ..\..\ - $(Configuration)\ - $(Configuration)\ - ../../\ - $(Configuration)\ - - - - Disabled - WINDOWS;JP;SJIS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - EnableAllWarnings - EditAndContinue - CompileAsC - 4127;4244;4255;4668;4710;4820;4996;4774;%(DisableSpecificWarnings) - - - winmm.lib;wsock32.lib;%(AdditionalDependencies) - true - MachineX86 - LinkVerbose - Windows - - - - - Disabled - WINDOWS;SJIS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level4 - EditAndContinue - CompileAsC - 4127;4996;4244;%(DisableSpecificWarnings) - - - winmm.lib;wsock32.lib;%(AdditionalDependencies) - true - MachineX86 - LinkVerbose - Windows - - - - - MaxSpeed - true - WINDOWS;JP;SJIS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions) - MultiThreaded - true - Level3 - ProgramDatabase - 4244;4996;%(DisableSpecificWarnings) - - - winmm.lib;wsock32.lib;%(AdditionalDependencies) - true - true - true - MachineX86 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CppCode - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Hengband_vcs2017/Hengband.sln b/Hengband_vcs2017/Hengband.sln deleted file mode 100644 index 1c91227aa..000000000 --- a/Hengband_vcs2017/Hengband.sln +++ /dev/null @@ -1,30 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.106 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hengband", "Hengband\Hengband.vcxproj", "{C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{82CF9010-9443-4FFF-ADF0-0D3E81C732CC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - English-Debug|Win32 = English-Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Debug|Win32.ActiveCfg = Debug|Win32 - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Debug|Win32.Build.0 = Debug|Win32 - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.English-Debug|Win32.ActiveCfg = English-Debug|Win32 - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.English-Debug|Win32.Build.0 = English-Debug|Win32 - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Release|Win32.ActiveCfg = Release|Win32 - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {4A5E2796-8815-4A42-BF8D-FFEA2E38264E} - EndGlobalSection -EndGlobal diff --git a/Hengband_vcs2017/Hengband/Hengband.vcxproj b/Hengband_vcs2017/Hengband/Hengband.vcxproj deleted file mode 100644 index 7fd1a1fcb..000000000 --- a/Hengband_vcs2017/Hengband/Hengband.vcxproj +++ /dev/null @@ -1,378 +0,0 @@ - - - - StaticLibrary - true - v120 - Unicode - - - StaticLibrary - false - v120 - Unicode - - - - Debug - Win32 - - - English-Debug - Win32 - - - Release - Win32 - - - - {C00503B6-18FF-42F1-BAC0-6C94EDE62CB2} - Hengband - 10.0.17763.0 - - - - Application - MultiByte - true - v141 - - - Application - MultiByte - false - v141 - false - - - Application - MultiByte - false - v141 - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - ..\..\ - ..\..\ - $(Configuration)\ - $(Configuration)\ - ../../\ - $(Configuration)\ - - - - Disabled - WINDOWS;JP;SJIS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions);HAVE_STDINT_H; - false - EnableFastChecks - MultiThreadedDLL - EnableAllWarnings - EditAndContinue - CompileAsC - 4127;4244;4255;4668;4710;4820;4996;4774;5045;%(DisableSpecificWarnings) - true - - - winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;wsock32.lib;%(AdditionalDependencies) - true - MachineX86 - LinkVerbose - Windows - - - - - Disabled - WINDOWS;SJIS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level4 - EditAndContinue - CompileAsC - 4127;4996;4244;%(DisableSpecificWarnings) - - - winmm.lib;wsock32.lib;%(AdditionalDependencies) - true - MachineX86 - LinkVerbose - Windows - - - - - MaxSpeed - true - WINDOWS;JP;SJIS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions);HAVE_STDINT_H; - MultiThreaded - true - Level3 - ProgramDatabase - 4244;4996;%(DisableSpecificWarnings) - - - winmm.lib;wsock32.lib;%(AdditionalDependencies) - true - true - true - MachineX86 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CppCode - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Hengband_vcs2017/Hengband/Hengband.vcxproj.filters b/Hengband_vcs2017/Hengband/Hengband.vcxproj.filters deleted file mode 100644 index a5949a62f..000000000 --- a/Hengband_vcs2017/Hengband/Hengband.vcxproj.filters +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - spell - - - spell - - - spell - - - spell - - - spell - - - spell - - - spell - - - spell - - - spell - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - object - - - object - - - object - - - object - - - object - - - object - - - player - - - player - - - player - - - player - - - player - - - player - - - player - - - object - - - object - - - object - - - floor - - - monster - - - monster - - - monster - - - monster - - - monster - - - monster - - - monster - - - monster - - - monster - - - object - - - cmd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - cmd - - - spell - - - spell - - - spell - - - spell - - - spell - - - spell - - - spell - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - floor - - - object - - - object - - - object - - - object - - - player - - - player - - - player - - - player - - - player - - - player - - - object - - - object - - - floor - - - monster - - - monster - - - monster - - - object - - - floor - - - floor - - - monster - - - cmd - - - cmd - - - - - - - - - - - {587cee92-bfe4-4674-9635-eed1992633f3} - - - {4e443fe1-9ff8-4786-b43f-7e4d106760dc} - - - {c7e2056b-fda5-410a-8d23-03ba3f11c051} - - - {52a3c5b6-2312-47a9-bb95-15c0d5e95192} - - - {8fc15fd9-029b-4e7f-ae0b-75b2db215ad0} - - - {282dc0ea-8c5c-4253-b38c-4f4f0ad87ff9} - - - \ No newline at end of file diff --git a/Makefile.am b/Makefile.am index 6b0aa7b6c..77e6051e4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,20 @@ AUTOMAKE_OPTIONS = foreign -EXTRA_DIST = autopick.txt autopick_eng.txt readme.txt readme_angband readme_eng.txt hengband.spec +visual_studio_files = \ + Bakabakaband/Bakabakaband.sln \ + Bakabakaband/Bakabakaband/Bakabakaband.vcxproj \ + Bakabakaband/Bakabakaband/Bakabakaband.vcxproj.filters \ + Bakabakaband/Bakabakaband/packages.config + +EXTRA_DIST = \ + autopick.txt \ + autopick_eng.txt \ + bootstrap \ + readme.txt \ + readme_angband \ + readme_eng.txt \ + Bakabakaband.spec \ + $(visual_studio_files) SUBDIRS = src lib diff --git a/autopick.txt b/autopick.txt index 7c4c97c7a..218b0550d 100644 --- a/autopick.txt +++ b/autopick.txt @@ -1,10 +1,10 @@ -# autopick.txt 変愚蛮怒仕様 +# autopick.txt 馬鹿馬鹿蛮怒仕様 # # このファイルの一番最後は実際に使用できる設定ファイルの具体例になって # います。このファイルを 'picktype.prf' という名前で -# lib\user\picktype.prf か ~/.angband/Hengband/picktype.prf としてコピー +# lib\user\picktype.prf か ~/.angband/Bakabakaband/picktype.prf としてコピー # すれば、そのまま自動拾いファイルとして使用することができます。 -# (Unix の場合は ~/.angband/Hengband/ のみが使用可能。Windows等、Unix以 +# (Unix の場合は ~/.angband/Bakabakaband/ のみが使用可能。Windows等、Unix以 # 外の場合は、lib\user\ のみが使用可能です。) # # ●自動拾いの使い方 @@ -29,8 +29,8 @@ # 'n' : 次にマッチする行を検索。(条件分岐を考慮しません) # 'N' : 前にマッチする行を検索。(条件分岐を考慮しません) # -# 設定は全て変愚蛮怒ディレクトリの中の lib\user\ の下か -# ~/.angband/Hengband/ の下に「picktype-(名前).prf」 という名前の +# 設定は全て馬鹿馬鹿蛮怒ディレクトリの中の lib\user\ の下か +# ~/.angband/Bakabakaband/ の下に「picktype-(名前).prf」 という名前の # ファイルで記録されるので、これをメモ帳等の適当なエディタで編集 # して、'$'コマンドで読み込み直すこともできます。このファイルはプ # レイヤーキャラクターの名前が「(名前)」であるときに使用されます @@ -205,7 +205,7 @@ # # ・ファイルの挿入の書式 # %:ファイル名 -# lib\user\ファイル名 か ~/.angband/Hengband/ファイル名 を自 +# lib\user\ファイル名 か ~/.angband/Bakabakaband/ファイル名 を自 # 動拾いの登録ファイルとして読み込みます。 # # ・使用可能な演算子 @@ -263,7 +263,7 @@ # # これ以下は具体的に使用可能な設定例です。 # このファイルをpicktype.prfという名前でlib\user\ か -# ~/.angband/Hengband/ にコピーすれば自動拾いファイルとして +# ~/.angband/Bakabakaband/ にコピーすれば自動拾いファイルとして # 使用することができます。 # #------------------------------------------------------------------ diff --git a/autopick_eng.txt b/autopick_eng.txt index 277262ad3..47a7105c5 100644 --- a/autopick_eng.txt +++ b/autopick_eng.txt @@ -1,9 +1,9 @@ -# autopick.txt for Hengband +# autopick.txt for Bakabakaband # # The last part of this file is an example of 'pickpref.prf'. -# You can copy this file to lib\user\ or ~/.angband/Hengband/ +# You can copy this file to lib\user\ or ~/.angband/Bakabakaband/ # to use as preference of auto-picker. -# (UNIX user must copy to ~/.angband/Hengband/. Others must +# (UNIX user must copy to ~/.angband/Bakabakaband/. Others must # copy to lib\user\ .) # # ===== How to use auto-picker/destroyer ======== @@ -30,7 +30,7 @@ # # The preference will be saved in a file named # "pickpref-<>.prf" in your user directory; This will be -# ~/.angband/Hengband/ for UNIX, or hengband\lib\user\ for other +# ~/.angband/Bakabakaband/ for UNIX, or Bakabakaband\lib\user\ for other # operating systems. You may edit this file using any text # editor, and may use the '$' command within the game to reread # this file. When you don't use the in-game editor, you may use @@ -260,8 +260,8 @@ #------------------------------------------------------------------ # # Below is an example 'pickpref.prf' file. -# You can copy this file to lib\user\ or ~/.angband/Hengband/. -# (UNIX user must copy to ~/.angband/Hengband/. Others must copy +# You can copy this file to lib\user\ or ~/.angband/Bakabakaband/. +# (UNIX user must copy to ~/.angband/Bakabakaband/. Others must copy # to lib\user\ .) # #------------------------------------------------------------------ diff --git a/configure.ac b/configure.ac index 814ea4641..52ec8b9d4 100644 --- a/configure.ac +++ b/configure.ac @@ -1,12 +1,12 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT(hengband, 2.1.5) +AC_INIT(Bakabakaband, 2.1.5) AC_CONFIG_HEADERS(src/autoconf.h) AC_CONFIG_SRCDIR(src/main.c) AM_INIT_AUTOMAKE AC_ARG_WITH(setgid, -[ --with-setgid=NAME install hengband as group NAME], +[ --with-setgid=NAME install Bakabakaband as group NAME], [case "${withval}" in no) GAMEGROUP="";; yes) AC_MSG_ERROR(missing argument for --with-setgid);; @@ -53,6 +53,8 @@ AC_ARG_ENABLE(xim, [ --disable-xim disable xim support], use_xim=no, use_xim=yes) AC_ARG_ENABLE(fontset, [ --disable-fontset disable fontset support], use_fontset=no, use_fontset=yes) +AC_ARG_ENABLE([xft], + AS_HELP_STRING([--enable-xft], [Enable xft support])) AC_ARG_ENABLE(worldscore, [ --disable-worldscore disable worldscore support], ,AC_DEFINE(WORLD_SCORE, 1, [Allow the game to send scores to the score server])) AC_ARG_ENABLE(chuukei, @@ -103,6 +105,11 @@ if test "$have_x" = yes; then AC_CHECK_LIB(X11, _Xsetlocale, AC_DEFINE(X_LOCALE, 1, [Use XLocale])) AC_CHECK_LIB(xpg4, setlocale, LIBS="$LIBS -lxpg4") fi + + AS_IF([test "x$enable_xft" = "xyes"], [ + PKG_CHECK_MODULES(XFT, [xft], + [AC_DEFINE([USE_XFT], [1], [Use XFT])]) + ]) fi if test "$use_japanese" != no; then diff --git a/doxygen/Hengband.doxyfile b/doxygen/Hengband.doxyfile index 1f5f449e7..b471b5d2a 100644 --- a/doxygen/Hengband.doxyfile +++ b/doxygen/Hengband.doxyfile @@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = Hengband +PROJECT_NAME = Bakabakaband # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version @@ -51,7 +51,7 @@ PROJECT_BRIEF = # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. -PROJECT_LOGO = hengband_title.png +PROJECT_LOGO = Bakabakaband_title.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is @@ -813,7 +813,7 @@ INPUT = ../src # possible encodings. # The default value is: UTF-8. -INPUT_ENCODING = EUC-JP +INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and @@ -836,7 +836,7 @@ FILE_PATTERNS = *.c \ # be searched for input files as well. # The default value is: NO. -RECURSIVE = NO +RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a diff --git a/hengband.spec b/hengband.spec index 6a4272fbf..c6a2a9a33 100644 --- a/hengband.spec +++ b/hengband.spec @@ -1,34 +1,34 @@ %define version 1.1.0b %define release 3 -Summary: hengband %{version} -Name: hengband +Summary: Bakabakaband %{version} +Name: Bakabakaband Version: %{version} Release: %{release} Copyright: unknown Group: Amusements/Games Packager: Takahiro MIZUNO Url: http://echizen.s5.xrea.com/heng/index.html -Source: hengband-%{version}.tar.bz2 +Source: Bakabakaband-%{version}.tar.bz2 Buildroot: %{_tmppath}/%{name}-%{version}-root %description -Hengband is a variant of ZAngband. +Bakabakaband is a variant of ZAngband. Official page is this, -http://echizen.s5.xrea.com/heng/eng-hengband/index.html +http://echizen.s5.xrea.com/heng/eng-Bakabakaband/index.html -More infomation is /usr/doc/hengband-hoge/readme_eng.txt +More infomation is /usr/doc/Bakabakaband-hoge/readme_eng.txt -Summary(ja): ÊѶòÈÚÅÜ %{version} +Summary(ja): �Ѷ����� %{version} %description -l ja -ÊѶòÈÚÅÜ¤Ï Angband ¤Î¥Ð¥ê¥¢¥ó¥È¤Ç¤¹¡£ +�Ѷ����ܤ� Angband �ΥХꥢ��ȤǤ��� -ËÜ¥½¥Õ¥È¥¦¥§¥¢¤ÎºÇ¿·ÈǤϰʲ¼¤Î¾ì½ê¤«¤éÆþ¼ê¤Ç¤­¤Þ¤¹¡£ +�ܥ��եȥ������κǿ��Ǥϰʲ��ξ�꤫������Ǥ��ޤ��� http://echizen.s5.xrea.com/heng/index.html -¾Ü¤·¤¯¤Ï /usr/doc/hengband-hoge/readme.txt ¤ò»²¾È¡£ +�ܤ�����Bakabakabandc/hengband-hoge/readme.txt �ò»²¾È¡ï¿½ %prep rm -rf $RPM_BUILD_ROOT @@ -36,65 +36,65 @@ rm -rf $RPM_BUILD_ROOT %setup -n %{name}-%{version} %build -./configure --prefix=%{_prefix} --bindir=%{_bindir} --with-libpath=%{_datadir}/games/hengband/lib +./configure --prefix=%{_prefix} --bindir=%{_bindir} --with-libpath=%{_datadir}/games/Bakabakaband/lib make %install mkdir -p $RPM_BUILD_ROOT/%{_bindir} -mkdir -p $RPM_BUILD_ROOT/%{_datadir}/games/hengband -cp src/hengband $RPM_BUILD_ROOT/%{_bindir} -cp -R lib/ -p $RPM_BUILD_ROOT/%{_datadir}/games/hengband/ -touch $RPM_BUILD_ROOT/%{_datadir}/games/hengband/lib/apex/scores.raw +mkdir -p $RPM_BUILD_ROOT/%{_datadir}/games/Bakabakaband +cp src/Bakabakaband $RPM_BUILD_ROOT/%{_bindir} +cp -R lib/ -p $RPM_BUILD_ROOT/%{_datadir}/games/Bakabakaband/ +touch $RPM_BUILD_ROOT/%{_datadir}/games/Bakabakaband/lib/apex/scores.raw %clean rm -rf $RPM_BUILD_ROOT %preun -if [ -e %{_datadir}/games/hengband/lib/data/f_info_j.raw ] +if [ -e %{_datadir}/games/Bakabakaband/lib/data/f_info_j.raw ] then -rm -rf %{_datadir}/games/hengband/lib/data/*.raw +rm -rf %{_datadir}/games/Bakabakaband/lib/data/*.raw fi exit 0 %files %defattr(-,root,root) -%attr(2755,root,games) %{_bindir}/hengband -%dir %{_datadir}/games/hengband/lib -%attr(775,root,games) %dir %{_datadir}/games/hengband/lib/apex -%attr(775,root,games) %dir %{_datadir}/games/hengband/lib/bone -%attr(775,root,games) %dir %{_datadir}/games/hengband/lib/data -%dir %{_datadir}/games/hengband/lib/edit -%dir %{_datadir}/games/hengband/lib/file -%dir %{_datadir}/games/hengband/lib/help -%dir %{_datadir}/games/hengband/lib/info -%dir %{_datadir}/games/hengband/lib/pref -%attr(775,root,games) %dir %{_datadir}/games/hengband/lib/save -%dir %{_datadir}/games/hengband/lib/script -%dir %{_datadir}/games/hengband/lib/user -%dir %{_datadir}/games/hengband/lib/xtra -%dir %{_datadir}/games/hengband/lib/xtra/graf -%{_datadir}/games/hengband/lib/apex/h_scores.raw -%{_datadir}/games/hengband/lib/apex/readme.txt -%attr(664 root,games) %config(noreplace) %{_datadir}/games/hengband/lib/apex/scores.raw -%{_datadir}/games/hengband/lib/bone/delete.me -%{_datadir}/games/hengband/lib/data/delete.me -%{_datadir}/games/hengband/lib/edit/*.txt -%{_datadir}/games/hengband/lib/file/*.txt -%{_datadir}/games/hengband/lib/help/*.hlp -%{_datadir}/games/hengband/lib/help/*.txt -%{_datadir}/games/hengband/lib/info/delete.me -%{_datadir}/games/hengband/lib/pref/*.prf -%{_datadir}/games/hengband/lib/save/delete.me -%{_datadir}/games/hengband/lib/script/delete.me -%{_datadir}/games/hengband/lib/user/delete.me -%{_datadir}/games/hengband/lib/xtra/graf/8x8.bmp +%attr(2755,root,games) %{_bindir}/Bakabakaband +%dir %{_datadir}/games/Bakabakaband/lib +%attr(775,root,games) %dir %{_datadir}/games/Bakabakaband/lib/apex +%attr(775,root,games) %dir %{_datadir}/games/Bakabakaband/lib/bone +%attr(775,root,games) %dir %{_datadir}/games/Bakabakaband/lib/data +%dir %{_datadir}/games/Bakabakaband/lib/edit +%dir %{_datadir}/games/Bakabakaband/lib/file +%dir %{_datadir}/games/Bakabakaband/lib/help +%dir %{_datadir}/games/Bakabakaband/lib/info +%dir %{_datadir}/games/Bakabakaband/lib/pref +%attr(775,root,games) %dir %{_datadir}/games/Bakabakaband/lib/save +%dir %{_datadir}/games/Bakabakaband/lib/script +%dir %{_datadir}/games/Bakabakaband/lib/user +%dir %{_datadir}/games/Bakabakaband/lib/xtra +%dir %{_datadir}/games/Bakabakaband/lib/xtra/graf +%{_datadir}/games/Bakabakaband/lib/apex/h_scores.raw +%{_datadir}/games/Bakabakaband/lib/apex/readme.txt +%attr(664 root,games) %config(noreplace) %{_datadir}/games/Bakabakaband/lib/apex/scores.raw +%{_datadir}/games/Bakabakaband/lib/bone/delete.me +%{_datadir}/games/Bakabakaband/lib/data/delete.me +%{_datadir}/games/Bakabakaband/lib/edit/*.txt +%{_datadir}/games/Bakabakaband/lib/file/*.txt +%{_datadir}/games/Bakabakaband/lib/help/*.hlp +%{_datadir}/games/Bakabakaband/lib/help/*.txt +%{_datadir}/games/Bakabakaband/lib/info/delete.me +%{_datadir}/games/Bakabakaband/lib/pref/*.prf +%{_datadir}/games/Bakabakaband/lib/save/delete.me +%{_datadir}/games/Bakabakaband/lib/script/delete.me +%{_datadir}/games/Bakabakaband/lib/user/delete.me +%{_datadir}/games/Bakabakaband/lib/xtra/graf/8x8.bmp %doc readme.txt readme_angband readme_eng.txt %changelog * Fri Jul 05 2002 Takahiro MIZUNO -- hengband RPM 1.0.0b release 3 +- Bakabakaband RPM 1.0.0b release 3 - Add %preun script. - Change source extension. (tar.gz -> bz2) - Fix Copyright. @@ -102,12 +102,12 @@ exit 0 - Fix %description. * Mon Jun 17 2002 Takahiro MIZUNO -- hengband RPM 1.0.0b release 2 -- Fix setgid permission. (Mogami¤µ¤ó¿¼Õ) +- Bakabakaband RPM 1.0.0b release 2 +- Fix setgid permission. (Mogami����¿��) * Sun Jun 16 2002 Takahiro MIZUNO -- hengband RPM 1.0.0b release 1 +- Bakabakaband RPM 1.0.0b release 1 * Sun Jun 16 2002 Takahiro MIZUNO -- hengband RPM 1.0.0 release 1 +- Bakabakaband RPM 1.0.0 release 1 diff --git a/lib/edit/Makefile.am b/lib/edit/Makefile.am index 71511fefa..acf521d8d 100644 --- a/lib/edit/Makefile.am +++ b/lib/edit/Makefile.am @@ -9,8 +9,8 @@ angband_files = \ q0000027.txt \ q0000028.txt q00000ms.txt q000chao.txt q000dekn.txt \ q000eric.txt q000lyeh.txt q000natu.txt q000sorc.txt \ - q00water.txt q0clone0.txt q0fields.txt q0thief1.txt \ - q0thief2.txt q0willow.txt q_info.txt q_oberon.txt \ + q00water.txt q0clone0.txt q0dumpwitness.txt q0fields.txt \ + q0thief1.txt q0thief2.txt q0willow.txt q_info.txt q_oberon.txt \ q_pref.txt q_random.txt q_serpen.txt q_warg.txt \ qdarkelf.txt qhaunted.txt r_info.txt t0000001.txt \ t0000002.txt t0000003.txt t0000004.txt t0000005.txt \ diff --git a/lib/edit/a_info.txt b/lib/edit/a_info.txt index 3cd4c61c1..3c163a206 100644 --- a/lib/edit/a_info.txt +++ b/lib/edit/a_info.txt @@ -135,8 +135,8 @@ P:0:1d1:0:0:0 F:ACTIVATE | SEE_INVIS | HOLD_EXP | RES_CONF | RES_CHAOS | LITE_3 | F:INSTA_ART | SPEED | WIS | INT U:JUDGE -D:$This crimson jewelry which is chained with a gold chain is -D:$ deeply related to creation of this universe. +D:$This ruby pendant in a simple setting with a heavy gold chain is deeply +D:$ related to the creation of this universe. D:$ (R.Zelazny, 'The Chronicles of Amber', vol.3-10) D:金の鎖に取り付けられた、この宇宙の創世に深い関わりを持つ真紅の宝石。 D:(R.ゼラズニイ、真世界アンバーシリーズ 3~10巻) @@ -212,7 +212,7 @@ I:40:12:3 W:70:70:3:75000 F:STR | CON | INFRA | HIDE_TYPE | F:SEE_INVIS | FREE_ACT | REGEN | LITE | INSTA_ART -D:$The Nauglamir; a carencet of gold set with a multitude of shining gems of +D:$The Nauglamir; a carcanet of gold set with a multitude of shining gems of D:$Valinor, accenting a radiant Silmaril. The sturdy spirits of Dwarvish D:$craftsmen who labored long in mountain smithies lie within it still, and D:$as gossamer it rests upon the bearer. @@ -252,10 +252,10 @@ W:50:40:2:75000 F:STR | INT | WIS | DEX | CON | CHR | STEALTH | HIDE_TYPE | F:RES_POIS | ACTIVATE | SEE_INVIS | SEARCH | WARNING | INSTA_ART U:HYPODYNAMIA_1 -D:$This bracelet has its own will, which was created by Marlin -D:$ the prince of chaos. It is invisible but it sometimes -D:$ ripples to warn owner's dangers. It can morph to strangle -D:$ enemy's neck, if owner commands to it. +D:$This bracelet has its own will. It was created by Merlin, a prince of Chaos +D:$ and son of Corwin. The bracelet is invisible, but it sometimes ripples or +D:$ constricts to warn its owner of danger. When commanded by its owner, it +D:$ can morph to strangle an enemy's neck. D:$ (R.Zelazny, 'The Chronicles of Amber', vol.6-10) D:混沌の王子マーリンがログルスから生み出した意思を持った腕輪だ。 D:普段は目に見えないが脈動して危険を知らせてくれる。装備するものが @@ -547,8 +547,8 @@ F:HOLD_EXP | RES_NETHER | RES_DARK | RES_FEAR | F:ACTIVATE U:CHOIR_SINGS D:$The shining armor of Lohengrin the son of Parsifal. -D:$ If you wears it, the holy grail gives to you the devine protection -D:$ from all evils. (W.R.Wagner, 'Parsifal') +D:$ The Holy Grail gives divine protection from all evils to the wearer. +D:$ (W.R.Wagner, 'Parsifal') D:聖杯守護の騎士パルジファルの息子、ローエングリンの輝く鎧だ。 D:身に付ける者はあらゆる邪悪なものを退け聖杯の加護を得る。 D:(ワーグナー、「パルジファル」) @@ -627,7 +627,7 @@ P:12:1d2:3:4:20 F:BLOWS | RES_SHARDS | HOLD_EXP | SLOW_DIGEST | F:SUST_STR | SUST_DEX | SUST_CON | SUST_INT | SUST_WIS | SUST_CHR | F:RES_ACID | RES_ELEC | RES_FIRE | RES_COLD -D:$The leather armor which has a power of Shiva the god of destruction. +D:$The leather armor of Shiva, the god of destruction. D:ヒンズー教の最高神は創造の神ブラフマン、維持の神ヴィシュヌ、 D:そして破壊神シヴァだ。これはその中でも最も強力なシヴァの力が宿った D:鎧だ。 @@ -692,9 +692,9 @@ I:34:4:0 W:30:3:60:30000 P:6:1d2:0:0:20 F:RES_ACID | RES_ELEC | RES_FIRE | RES_COLD | RES_LITE | RES_DARK | XTRA_H_RES -D:$This shield emblazoned with a multitude of creatures not seen for ages -D:$once protected Celegorm, lord of Himlad; around it lies a mystic balance -D:$that contains the conflicts of the elements. +D:$This shield, emblazoned with a multitude of creatures not seen for ages, +D:$ once protected Celegorm, lord of Himlad; around it, a mystic balance lies +D:$ containing the conflicts of the elements. D:いまでは見られなくなった数々の伝説の生き物の D:装飾が施されたこの盾は、かつてヒムラドの王ケレゴルムを D:守っていた。地水火風のエレメントのせめぎ合いを内包し、 @@ -734,7 +734,7 @@ I:32:2:5 W:30:50:15:100000 P:2:0d0:0:0:18 F:INT | WIS | CHR | SUST_INT | SUST_WIS | SUST_CHR | RES_BLIND | IM_ELEC -D:$This is the helm of Indra the god of thunderstorms. +D:$This is the helm of Indra, the god of thunderstorms. D:雷神インドラの兜だ。 # The Massive Iron Crown of Morgoth @@ -881,18 +881,18 @@ F:SEE_INVIS | NO_MAGIC | ACTIVATE | F:RES_DISEN | RES_FEAR | FREE_ACT | RES_ACID | RES_COLD | RES_POIS | F:TELEPORT U:TERROR -D:$This is terrible, scary, fearful, dreadful, bloodcurding, hair-rising -D:$ frightening mask. +D:$You run out of adjectives to describe the dread this mask inspires: +D:$ terrifying, scary, creepy, bloodcurdling, hair-rising, frightening, .... D:なんとも恐ろしい、不気味で、おどろおどろしく、髪が逆立ち、血も凍り、 D:ぞっとして鳥肌が立つような仮面だ。 D:仮面の奥の瞳に睨まれれば、怖くて逃げ出さずにはいられない。 -# The Golden Crown of Gondor -> Amber +# The Golden Crown of Gondor -> Jewel Encrusted Crown of Amber #JZ# N:42:真世界アンバーの E:of Amber -I:33:11:3 +I:33:12:3 W:40:40:30:125000 P:0:1d1:0:0:15 F:STR | WIS | CON | HIDE_TYPE | SPEED | @@ -900,8 +900,9 @@ F:RES_COLD | RES_FIRE | RES_LITE | RES_BLIND | RES_ELEC | RES_CONF | F:RES_CHAOS | LITE | SEE_INVIS | REGEN | ACTIVATE F:XTRA_POWER | XTRA_H_RES U:CURE_700 -D:$The gold grown which is decorated with much jewerly is the symbol -D:$ of the throne of Amber. Princes of Amber scrambled for it violently. +D:$Wrought of silver with seven high points each topped by a gem, this crown +D:$ is the symbol of the throne of Amber. The Princes of Amber scrambled for +D:$ it violently. D:アンバーの王位の象徴である、多数の宝石で飾られた金の王冠だ。 D:これをめぐって骨肉の争いが王子たちの間で繰り広げられた。 @@ -1097,7 +1098,7 @@ W:10:20:25:15000 P:2:1d1:0:0:15 F:STR | RES_FIRE | MAGIC_MASTERY | ACTIVATE U:BO_FIRE_1 -D:$A firey set of gauntlets that can even shoot fire from the user's +D:$A fiery set of gauntlets that can even shoot fire from the user's D:$hands. D:シンダール語で「跳ねる炎の拳」の名を持つこの篭手は炎に D:包まれており、身に付ける者は火の球を撃ち出すことも出来る。 @@ -1112,6 +1113,8 @@ I:31:2:4 W:10:40:25:43000 P:2:1d1:0:0:15 F:SUST_CON | CON | REGEN | RES_COLD | FREE_ACT +D:$These gauntlets belonged to Prince Corwin of Amber and are imbued with +D:$ his extraordinary toughness. D:並外れた強靭さを持つアンバーの王子コーウィンのガントレットだ。 # The Set of Gauntlets 'Pauraegen' @@ -1215,6 +1218,9 @@ P:2:1d1:0:0:15 U:CURE_POISON F:DEX | HIDE_TYPE | CHR | SUST_CHR | ACTIVATE | FREE_ACT | F:RES_NETHER | RES_CHAOS | SUST_CON +D:$Flora is away from Amber's palace most of the time and enjoys finding +D:$ new boyfriends in the parallel worlds that are shadows of Amber. Her +D:$ boots are enchanted with magic to make the wearer more attractive. D:フローラはほとんどの時間アンバーの宮殿を離れていて、 D:影の世界で新しいボーイフレンドを見つけては楽しんでいる。 D:彼女のブーツには身に付けた者を魅力的に見せる魔法がかかっている。 @@ -1252,7 +1258,7 @@ I:30:2:4 W:30:20:20:100000 P:4:1d1:5:5:16 F:SPEED | DEX | SUST_DEX | RES_NEXUS | FREE_ACT | LEVITATION -D:$The boots has an agility of Shiva the god of destruction. +D:$The boots have the agility of Shiva, the god of destruction. D:破壊神シヴァの力を持った革の靴だ。 @@ -1290,7 +1296,7 @@ P:0:2d4:10:15:5 F:DEX | HIDE_TYPE | STEALTH | SEARCH | SLAY_HUMAN | F:SLAY_EVIL | SLAY_TROLL | SLAY_ORC | BRAND_POIS | F:FREE_ACT | RES_DARK | SUST_DEX | SEE_INVIS | SHOW_MODS | THROW -D:$The dagger of Caine the leader of Amber fleets. +D:$The dagger of Caine, the leader of Amber's fleets. D:アンバーの艦隊を指揮するケインのダガーだ。 # The Dagger 'Narthanc' @@ -1404,7 +1410,7 @@ F:RES_CHAOS | RES_NETHER | HOLD_EXP | RES_FEAR | F:RES_COLD | BRAND_COLD | F:SLAY_DEMON | SLAY_EVIL | SLAY_DRAGON | SLAY_UNDEAD | F:SLOW_DIGEST | SHOW_MODS | HIDE_TYPE | BLESSED | RIDING -D:$The silver sable forged by moonlights, which Corwin the prince of +D:$The is the silver sabre, forged by moonlight, which Corwin the prince of D:$ Amber wielded. It shows contrasts between silver and black like D:$ its owner does. D:アンバーの王子コーウィンが使っていた、月の光により @@ -1455,9 +1461,9 @@ P:0:2d5:12:16:0 F:SEARCH | BRAND_ELEC | SLAY_ORC | KILL_DRAGON | RES_FEAR | F:RES_ELEC | LITE | RES_FIRE | RES_POIS | F:SLOW_DIGEST | SHOW_MODS | RIDING -D:$The sword of Sigurd which is alos called Balmung or Gram. -D:$ He slashed the anvil of Mime's blacksmith and used to -D:$ kill the dragon Fafnir. +D:$The sword of Sigurd which is also called Balmung or Gram. +D:$ With it, Sigurd cut the anvil at Mime's forge in half and slew Fafner, +D:$ the dragon. D:「ノートゥングさ、その名は。ヴォータンがとねりこの幹 D:に突き立てた剣だ。それを引き抜くことのでき D:た者だけが、わがものとしうるわけだ。」 @@ -1564,8 +1570,7 @@ P:0:4d6:-40:-60:-50 F:SPEED | IM_FIRE | RES_FIRE | BRAND_FIRE | RES_DISEN | RES_FEAR | F:AGGRAVATE | CURSED | HEAVY_CURSE | SHOW_MODS | TY_CURSE | LITE F:RANDOM_CURSE2 -D:$The flame sword with which Surtr set fire all over the world -D:$ at Ragnarok. +D:$The flame sword with which Surtr set the world on fire at Ragnarok. D:北欧神話において炎の巨人スルトが世界に火を放った燃える剣だ。 # The Cutlass 'Gondricam' @@ -1636,7 +1641,7 @@ F:ESP_ORC | ESP_TROLL | ESP_GIANT U:BA_COLD_2 D:$The weapon of Fingolfin, High King of the Noldor; it shines like a column D:$of ice lit by light unquenchable. Morgoth came but unwillingly to meet it -D:$of old; his lame foot will remind him of its might should be meet it again. +D:$of old; his lame foot will remind him of its might should he meet it again. D:ノルドールの上級王フィンゴルフィンの武器。氷の柱の如く輝いている。 D:かつてモルゴスは期せずしてこの剣に対峙し深い傷を D:刻み込まれた。彼はこの剣の力を再び思い知ることになるだろう。 @@ -1704,7 +1709,7 @@ F:DEX | CHR | STEALTH | HIDE_TYPE | SPEED | AGGRAVATE | VORPAL | F:SLAY_HUMAN | SLAY_TROLL | SLAY_ORC | SEE_INVIS | SHOW_MODS | F:ESP_ORC | ESP_TROLL | ESP_HUMAN D:$Take care! This sword will make you a murderer if you wield it. -D:$ Do you hear cries of this sword that want more blood thirstily? +D:$ Do you hear the bloodthirsty screams of this sword? D:持った者を殺戮マシーンに変える呪われた剣だ。あなたにはこの剣の D:血に飢えた叫びが聞こえるだろう。 @@ -1785,9 +1790,9 @@ W:20:8:80:35000 P:0:1d7:3:7:0 F:BLOWS | F:SLAY_ANIMAL | SLOW_DIGEST | REGEN | SHOW_MODS | SEE_INVIS | RES_DISEN -D:$Merlin the prince of chaos hates carrying a heavy sword, so he invokes -D:$ a power of chaos to take his sword from another dimension when he -D:$ needs. This sword is also one of such things. +D:$Merlin, a prince of chaos and Corwin's son, hates carrying a heavy sword. +D:$ When he needs one, he invokes a power of chaos to summon a blade from some +D:$ nearby parallel world. This sword is one of those he summoned. D:$ (R.Zelazny, 'The Chronicles of Amber', vol.6-10) D:地球暮らしの長いマーリンは現代っ子らしく重く長い剣を持ち歩くのが嫌いで、 D:必要な時カオスの力で剣を異世界から取り寄せる。この剣もそうした物の @@ -1897,8 +1902,8 @@ P:0:2d5:10:12:10 F:INT | HIDE_TYPE | F:BRAND_COLD | BRAND_FIRE | SLAY_DEMON | SLAY_TROLL | SLAY_GIANT | F:RES_FIRE | RES_COLD | SUST_INT | SLOW_DIGEST | SHOW_MODS | LITE -D:$Within this long thrusting spear lie the spirits of frost giants and fire -D:$demons, who war forever, trapped by magely spells. +D:$Within this long thrusting spear, the spirits of frost giants and fire +D:$ demons war forever, trapped by magely spells. D:この両手持ちの長槍の中には D:氷の巨人と炎の悪魔の二つの魂が魔法により D:封印されていて永遠に争っている。 @@ -1916,8 +1921,8 @@ F:SLAY_TROLL | SLAY_ORC | SLAY_GIANT | F:FREE_ACT | RES_FIRE | RES_ELEC | RES_LITE | F:SLOW_DIGEST | ACTIVATE | BLESSED | SHOW_MODS | LITE | RIDING U:BA_ELEC_2 -D:$The spear which Odin created from a branch of the world tree. -D:$It is craved magical runes. +D:$The spear which Odin created from a branch of the world tree. Magical +D:$ runes have been carved into the shaft. D:主神オーディンが世界樹の枝から作り上げた槍で、魔力を込めた D:ルーン文字が刻まれている。(北欧神話) @@ -2417,9 +2422,9 @@ F:WIS | INFRA | HIDE_TYPE | BLESSED | F:BRAND_COLD | SLAY_ORC | RES_COLD | RES_LITE | LITE | REGEN | F:ACTIVATE | SHOW_MODS | XTRA_H_RES U:DRAIN_2 -D:$Wielded by the High Priest of Meneltarma, this great mace gleams coldly as -D:$though moonlit, and it can strike as mighty a blow spiritually as -D:$physically. +D:$Wielded by the High Priest of Meneltarma, this great hammer gleams coldly +D:$ as though moonlit, and it can strike as mighty a blow spiritually as +D:$ physically. D:メネルタルマの高僧が使っていた大鎚で、月の光のように冷たく輝いている。 D:その打撃は敵の肉体だけでなく精神をも打ち砕くことができる。 @@ -2433,6 +2438,8 @@ W:30:60:260:200000 P:0:4d5:15:15:0 F:BLOWS | VAMPIRIC | HOLD_EXP | SLAY_UNDEAD | SLAY_EVIL | SLAY_HUMAN | F:REGEN | RES_FEAR | RES_BLIND | SLOW_DIGEST | SHOW_MODS +D:$This bloodthirsty blade, which has lopped countless heads, heals the body +D:$ and safeguards the soul of the wielder. D:数え切れないほどの首を落としてきたこの血に飢えた刃は D:敵の血と魂を吸って手にする者の体を癒す。 @@ -2477,7 +2484,7 @@ W:50:25:110:100000 P:0:0d0:10:14:0 F:SPEED | RES_FIRE | XTRA_MIGHT | ACTIVATE | SHOW_MODS | XTRA_RES_OR_POWER U:BRAND_FIRE_BOLTS -D:$Magic power of this crossbow of Brand the prince of Amber will enable +D:$The magic power of this crossbow of Brand, the prince of Amber, will enable D:$ you to move faster. D:トランプの魔力を自分の物にし、新たな宇宙を創造しようとした D:アンバーの王子ブランドが使っていたクロスボウだ。 @@ -2506,10 +2513,10 @@ F:RES_ACID | RES_ELEC | RES_FIRE | RES_COLD | ACTIVATE | F:SLAY_EVIL | SLAY_ANIMAL | SLAY_DEMON | SLAY_DRAGON | F:SEE_INVIS | REGEN | BLESSED | LITE | SHOW_MODS U:ESCAPE -D:$One of the three imperial spiritual artifacts of Japan. -D:$Susanoo found this tsurugi at Izumo, then Yamato Takeru -D:$got and used for conquesting Japan. -D:$It guards its owner from many dangers by its spiritual power. +D:$It is one of the three imperial spiritual artifacts of Japan. +D:$ Susanoo found this tsurugi, a straight double-edged sword, at Izumo. +D:$ Many years later, Yamato Takeru received it as a gift. +D:$ The tsurugi's spiritual power guards its owner from many dangers. D:三種の神器の一つ。出雲の国で素戔嗚尊(すさのおのみこと)により D:見出され、後に日本武尊(やまとたけるのみこと)の剣となる。 D:使う者を様々な危機から守る霊力が備わっている。 @@ -2661,6 +2668,10 @@ W:20:25:150:40000 P:0:2d5:10:10:0 F:STR | DEX | HIDE_TYPE | FORCE_WEAPON | KILL_EVIL F:SHOW_MODS | RIDING +D:$This legendary weapon is said to have killed Zanaffer, the beast that +D:$ destroyed the magic city of Sairaag. As the wielder's will augments the +D:$ powers of this blade of light, all evil creatures have reason to fear its +D:$ power. D:かつて魔導都市サイラーグを破壊つくした魔獣、ザナッファー。 D:それを滅ぼしたといわれるのが、この伝説の武器である。 D:持つ者の、意思の力を刃と成して、魔族すらも両断する。 @@ -2689,8 +2700,8 @@ P:0:8d6:0:30:0 F:STEALTH | INT | WIS | AGGRAVATE | CURSED | HEAVY_CURSE | F:SHOW_MODS | CHAOTIC | IMPACT | SPEED F:RANDOM_CURSE0 -D:$This is disruptive heave thing made by Micro$oft. -D:$It will bring many troubles to its user. +D:$This is a destructive heavy thing made by Micro$oft. +D:$ It will bring many troubles to its user. D:マイクロンフトによって作られたもので、重くて破壊力がある。 D:使用する者に災いをもたらす。 @@ -2701,8 +2712,8 @@ W:30:15:75:100000 P:0:2d6:17:12:0 F:DEX | BLOWS | SLAY_EVIL | SLAY_UNDEAD | SLAY_ORC | SLAY_DEMON | F:FREE_ACT | SEE_INVIS | SHOW_MODS | RES_DARK | RES_DISEN | SPEED -D:$The silver light sabre of Polnareff's stand Silver Chariot. -D:$It can pierce enemies rapidly. +D:$The silver light sabre of Polnareff's stand, Silver Chariot. +D:$ It can pierce enemies rapidly. D:ポルナレフのスタンド「シルバーチャリオッツ」が手にしていた D:軽量のサーベルだ。一瞬にして敵に無数の風穴をあけることがで D:きるはずだッ! @@ -2718,8 +2729,8 @@ F:LEVITATION | SLOW_DIGEST | REGEN | SEARCH | LITE | WARNING | F:INSTA_ART | QUESTITEM | FULL_NAME U:RECHARGE_XTRA D:$Yaaaaaaaaay! Platinum card of Yendorian Express!!! -D:$Wait a minute, you can not pay any more with this card. -D:$You must think other way of using it. +D:$ Wait a minute, you can not pay any more with this card. +D:$ You must think of another way of using it. D:金色に光り輝くイェンダー印のプラチナカードだ。 D:まるで億万長者になった気分がする。限度額まで使い込もう。 @@ -2755,9 +2766,10 @@ F:HIDE_TYPE | BLOWS | VORPAL | VAMPIRIC | SLAY_HUMAN | F:SHOW_MODS | SPEED | ACTIVATE | RES_DISEN | NO_TELE | F:DRAIN_EXP | AGGRAVATE | RES_DARK | RES_NETHER | TY_CURSE | U:MURAMASA -D:$Muramasa the legendaly bracksmith forged this sword 'Muramasa'. -D:$ It always wants more blood thirstily, although it already -D:$ drained blood from many person. +D:$"If you encounter a demon, you will cut the demon. If you encounter a god +D:$ you will cut the god." Muramasa, the legendary swordsmith, forged this +D:$ sword. It always wants more blood, even though it has already drained the +D:$ blood of many. D:「魔物に遭うては魔物を斬り、神に遭うては神を斬る。」 D:伝説の刀匠村正が全身全霊を込めて鍛えたこの妖刀は D:数え切れない人間の血を啜ってきた。その刃は @@ -2772,6 +2784,9 @@ F:STEALTH | SUST_STR | SUST_DEX | SUST_CON | F:SPEED | RES_FIRE | BRAND_FIRE | F:SLAY_ANIMAL | SLAY_DRAGON | RES_FEAR | FREE_ACT | F:REGEN | SHOW_MODS | HIDE_TYPE +D:$This a powerful nunchaku with the spiritual power of a legendary fighter. +D:$ In skilled hands, it can deliver blows as fast as someone fighting +D:$ barehanded. D:伝説の格闘家の霊力が宿った強力なヌンチャクだ。 D:拳法を操る者が手にすれば自らの体の一部のように D:操ることができ、素手の時と同じくらい素早い攻撃が @@ -2787,6 +2802,7 @@ F:RES_CONF | RES_NETHER | RES_COLD | RES_POIS | RES_DARK | RES_FEAR | F:SEE_INVIS | ACTIVATE | DRAIN_EXP | F:SH_COLD | HOLD_EXP | LEVITATION | REGEN U:TERROR +D:$It is the stone mask of Dio Brando that turns the wearer into a vampire. D:装備した者を吸血鬼に変えてしまうというディオの石仮面だ。 N:147:飛行 @@ -2796,6 +2812,7 @@ W:60:60:10:60000 P:0:1d1:0:0:0 F:INT | CHR | SPEED | ACTIVATE | LEVITATION | HOLD_EXP | INSTA_ART | LITE_3 | U:BA_MANA +D:$This glowing blue gem allows the wielder to levitate. D:浮遊の力を与えてくれる青く仄光る宝石だ。 N:148:『与一の弓』 @@ -2804,6 +2821,7 @@ I:19:13:4 W:35:30:40:30000 P:0:0d0:40:13:0 F:DEX | HIDE_TYPE | SEE_INVIS | XTRA_MIGHT | SHOW_MODS +D:$It is the bow of Nasu no Yoichi, known for making impossible shots. D:「与一鏑を取つて番ひ、能つ引いてひやうと放つ。小兵といふ条、 D:十二束三伏、弓はつよし、鏑は浦響くほどに長鳴して、過たず扇の D:要ぎは一寸ばかり置いて、ひいふつとぞ射切つたる。」(平家物語)。 @@ -2825,6 +2843,7 @@ I:23:20:2 W:30:25:120:80000 P:0:10d4:17:21:0 F:STR | DEX | VORPAL | TUNNEL | SHOW_MODS +D:$It's a sharp Japanese sword said to be capable of cutting anything. D:鋼をも切り裂く、切れ味抜群の日本刀だ。 N:151:八咫 @@ -2843,6 +2862,11 @@ W:40:20:400:98765 P:0:3d6:5:23:5 F:STR | CON | SLAY_EVIL | SLAY_UNDEAD | SLAY_ORC | SLAY_TROLL | RES_FEAR | F:FREE_ACT | REGEN | SHOW_MODS +D:$Musashibo Benkei, sometimes said to be a demon, used his power to obtain +D:$ this naginata. With it, he won 999 swords from samurai in duels +D:$ around Kyoto. Trying to win an additional sword, Benkei fought Minamoto +D:$ no Yoshitsune on Gojo Bridge and lost. Benkei later became Yoshitsune's +D:$ retainer. D:後に義経に仕えた怪僧・武蔵坊弁慶は、この大薙刀を得物に武力を振るい、 D:五条大橋の上で999本の刀を狩った。 @@ -2913,6 +2937,8 @@ W:10:150:30:10000 P:0:1d1:0:0:0 F:ACTIVATE | INSTA_ART U:FISHING +D:$Taikobo's daily routine was to fish with this fishing rod. Eventually, +D:$ Taikobo was himself caught by Zhou Wen Wang. D:太公望はこの釣り竿を用いて釣りを楽しむのが日課であったが、 D:結局は彼自身が周の文王に釣られてしまったのであった。 @@ -2924,6 +2950,8 @@ W:60:150:130:100000 P:0:4d5:-10:25:0 F:VORPAL | VAMPIRIC | SLAY_EVIL | KILL_DEMON | ESP_DEMON | F:AGGRAVATE | LITE | CON +D:$As you handle this reddish gold blade, you have the strong urge to find +D:$ and kill some demons. D:彼女は史上最強の破妖刀だ。 D:朱金に輝く刀身で魔性の心臓をつらぬき、その命を食べつくす。 @@ -2935,9 +2963,9 @@ P:0:4d9:6:23:10 F:STR | DEX | HIDE_TYPE | SEARCH | FREE_ACT | SLAY_HUMAN | F:SLAY_TROLL | SLAY_GIANT | SLAY_ANIMAL | SLAY_ORC | RES_FIRE | RES_COLD | F:RES_ELEC | RES_ACID | RES_FEAR | SHOW_MODS | RIDING -D:$Because of very superb sharpness such as dragon flies are -D:$cut which perches on the tip of this spear, it is called -D:$'Tonbo giri' which means 'dragon fry cutter'. +D:$Said to belong to Honda Tadakatsu, a leading general for Tokugawa Ieyasu, +D:$ this spear got its name, 'Tonbo giri' or dragonfly cutter, because a +D:$ dragonfly that tried to perch on the tip was cut in two. D:徳川四天王の1人本多忠勝の愛用の槍だ。 D:その切れ味は穂先に止まった蜻蛉が切れて落ちるほどである。 @@ -2963,6 +2991,9 @@ F:BRAND_ELEC | SLAY_EVIL | SLAY_GIANT | F:RES_ELEC | RES_LITE | RES_DARK | F:LITE | SEE_INVIS | RES_BLIND | SHOW_MODS | RIDING U:BA_STAR +D:$This is spear of the Celtic hero, Cuchulainn. Carved from the bone of +D:$ a sea dragon, it protects the sight of the wielder and can flash to dazzle +D:$ an opponent. D:ケルトの英雄クーフーリンの、海竜の骨から削られた長槍だ。 D:つねに目映く発せられるその閃光は敵の目をくらまし、 D:逆に所有者の視力を守る。 @@ -3036,6 +3067,9 @@ W:25:5:15:808 P:0:1d2:-3:-7:6 F:SEARCH | ACTIVATE | SHOW_MODS | HIDE_TYPE U:AGGRAVATE +D:$It is two wooden prisms joined by a thin rope. Though a poor weapon, +D:$ firefighters use such devices as percussion instruments to warn others of +D:$ danger. D:角柱二本の互いの端が、細い縄で結ばれている。 D:武器としては見るからに貧相だが、 防火をその任とする衛士たちが使った、 D:由緒正しい武器だといわれている。 @@ -3047,6 +3081,11 @@ W:40:5:100:808 P:0:1d7:-5:10:3 F:STR | CHR | RES_FIRE | ACTIVATE | U:HERO +D:$It is a short staff with an attached flag. The opposite end of the staff +D:$ from the flag has a disk with the mark of a firefighting squad. Staffs +D:$ like this were used to rally firefighters to sites of fires in Edo period +D:$ Japan. The bearers, matoimachi, of such staffs were noted for their +D:$ courage. D:消火作業にあたって、士気を鼓舞すべく振りたてられた杖だ。 D:杖の先に隊のマーク入りの円盤があり、その下側から D:長い帯状の飾りが幾本ものびている。 @@ -3081,6 +3120,9 @@ W:45:40:666:66666 P:0:25d4:-30:0:20 F:SPEED | STEALTH | WIS | IMPACT | SHOW_MODS | HIDE_TYPE | F:CURSED | HEAVY_CURSE +D:$It is a very heavy iron ball, likely too cumbersome to be effective as +D:$ a weapon, with an attached chain and metal ring, ready to be fastened to +D:$ an ankle or wrist. D:不信心者の足にくくりつけられ、その動きを阻害する。 D:重いが武器としても使えない事はない。 @@ -3130,6 +3172,7 @@ W:50:30:130:0 P:0:5d5:-50:-50:-5 F:WIS | CHR | F:TY_CURSE | AGGRAVATE | DRAIN_EXP | SHOW_MODS | THROW +D:$"What's this! Isn't it the strongest sword!?" (Final Fantasy V) D:「なんだこれは!最強の剣じゃないのか!?」 D:(FINAL FANTASY V) @@ -3139,6 +3182,9 @@ I:21:1:3 W:10:20:50:40000 P:0:2d4:8:10:0 F:STR | CON | RES_FEAR | SEE_INVIS | SLAY_EVIL | SLAY_UNDEAD +D:$This is the donkey's jawbone that Samson used to defeat a Philistine Army. +D:$ Lightweight but effective, this club's sacred power is especially deadly +D:$ against evil foes. D:怪力サムソンがペルシア人兵士の包囲を撃ち破ったときに使っていた D:棍棒。骨でできているために軽く、その聖なる力は邪悪なモンスター D:を打ち払う。 @@ -3152,6 +3198,9 @@ F:BLOWS F:SLAY_UNDEAD | SLAY_DRAGON | SLAY_ANIMAL | F:RES_FIRE | RES_FEAR | BLESSED | F:SLOW_DIGEST | SHOW_MODS +D:$It is similar to the fabled Excalibur but is slightly smaller. It also +D:$ also happens to talk, calling itself "E.J." and admitting to a severe case +D:$ of arachnophobia. D:かの宝剣エクスカリバーに似た作りの、少し小型の剣だ。 D:自分のことを「E.J.」と呼び、ごくたまに話もする。 D:蜘蛛と対峙すると、恐れのあまりプリンのようにぷるぷると震える。 @@ -3190,6 +3239,7 @@ F:SPEED | INT | WIS | SUST_INT | SUST_WIS | XTRA_SHOTS | XTRA_MIGHT | F:DEC_MANA | F:RES_DARK | RES_LITE | RES_DISEN | RES_BLIND | IM_COLD | SLOW_DIGEST | F:HIDE_TYPE | SHOW_MODS | QUESTITEM | INSTA_ART +D:$It's a very ridiculous bow. D:すごくいいかげんな作りの弓だ。 N:183:やる気のない @@ -3300,6 +3350,8 @@ P:0:2d6:6:9:0 F:DEX | CHR | HIDE_TYPE | RIDING | F:KILL_ANIMAL | ESP_ANIMAL | BRAND_FIRE | ACTIVATE U:CHARM_ANIMAL +D:$This is the whip of a venerable beastmaster from a country circus. The +D:$ crack of this whip can shake any beast. D:某国サーカス団で使用された由緒正しい猛獣使いの証だ。 D:このムチの音はどんな猛獣でも震え上がらせることができる。 @@ -3335,7 +3387,7 @@ W:20:4:130:20000 P:0:2d2:6:10:0 F:STR | BLOWS | HIDE_TYPE | F:SLAY_ORC | SLAY_TROLL | RES_FIRE -D:$A blade of Elendil that was broken by his fall as the battled Sauron upon +D:$A blade of Elendil that was broken by his fall as he battled Sauron upon D:$ the steps of Barad-Dur. D:「金はすべて光るとは限らぬ、 D:放浪する者すべてが、まよう者ではない。 @@ -3360,6 +3412,8 @@ W:60:60:320:200000 P:0:4d5:20:20:5 F:STR | DEX | CON | SLAY_EVIL | SLAY_HUMAN | F:VORPAL | SHOW_MODS +D:$Guan Yu, who has a long, lush beard, knocked many great men to the ground +D:$ with this blue dragon sword. D:豊かな髯を蓄えた義人・関羽はこの青龍刀で多くの豪傑を地に D:叩き伏せて来た。 @@ -3369,6 +3423,8 @@ I:21:16:6 W:40:40:350:100000 P:0:4d7:0:20:10 F:STR | RES_FEAR +D:$It is the heavy gold war club of Shuten-douji, sake lover and leader of the +D:$ ogres on Mt. Oe. D:大江山の鬼の首領たる酒呑童子の重い金棒だ。 N:195:『ゴールデンハンマー』 @@ -3392,6 +3448,8 @@ W:30:10:65:45000 P:5:1d2:0:0:15 F:STR | RES_ACID | RES_COLD | RES_FEAR | F:REFLECT | SUST_STR | +D:$Perseus evaded the snake-haired Medusa's petrifying gaze with this +D:$ reflective shield in hand. D:蛇の髪を持つメドゥーサの石化の睨みも、この反射の盾の前には D:効果がなかった。 @@ -3418,6 +3476,7 @@ I:36:8:-10 W:20:3:110:0 P:8:1d1:-1:0:64 F:AGGRAVATE | SUST_CHR | CHR +D:$It's a rugged cuirass with a noticeable and offensive odor. D:なんとゴツゴツとした鎧だこと。 N:201:『青龍の霊鱗』 @@ -3429,6 +3488,9 @@ F:RES_ACID | RES_FIRE | RES_COLD | RES_ELEC | F:RES_DARK | RES_CONF | RES_POIS | F:FREE_ACT | SEE_INVIS | ACTIVATE U:RESIST_ALL +D:$This blue dragon scale armor has been blessed by the azure dragon that +D:$ guards the east and the three other guardians, Byakko, Genbu, and Suzaku. +D:$ Even a god would be envious of the protection this armor provides. D:玄武、白虎、朱雀とともに四獣と呼ばれる青龍の鱗鎧を D:身に纏えば、神の如き守護の力が得られる。 @@ -3442,6 +3504,9 @@ F:SLAY_EVIL | SLAY_DEMON | SLAY_UNDEAD | F:RES_ACID | RES_COLD | RES_BLIND | RES_CHAOS | F:LITE | ACTIVATE | BLESSED | SEE_INVIS | SHOW_MODS U:BA_WATER +D:$From the bridge between heaven and earth, Izanagi and Izanami churned the +D:$ sea with this jeweled weapon. The first land sprung up from where drops +D:$ of salty water fell from the weapon's tip. D:「是に天つ神、諸の命以ちて、伊邪那岐命、伊邪那美命、 D:二柱の神に、『是の多陀用弊流国を修め理り固め成せ。』 D:と詔りて、天の沼矛を賜ひて、言依さし賜ひき。故、二柱 @@ -3452,7 +3517,7 @@ D:是れ淤能碁呂島なり。」(古事記)。 # モーロックの高僧の錆びた鎖かたびら N:203:モーロックの高僧の -E:of The High Preist of Morlok +E:of The High Priest of Moloch I:37:1:-2 W:90:8:200:100000 P:14:1d4:-5:0:-40 @@ -3460,6 +3525,9 @@ F:INT | WIS | CHR | HIDE_TYPE | RES_LITE | RES_DARK | F:RES_ACID | RES_ELEC | RES_FIRE | RES_COLD | F:RES_POIS | RES_CONF | RES_CHAOS | RES_NETHER | F:RES_NEXUS | AGGRAVATE | CURSED | HEAVY_CURSE | TY_CURSE +D:$This badly rusted chain mail was once worn by a high priest who guarded a +D:$ powerful magic amulet. That priest's despair and the amulet's magic have +D:$ left their mark in the mail. D:この赤々と錆びた今にも崩れ去りそうな鎖かたびらには、 D:かつて愚かにも守護する魔除けを奪われ朽ち果てた、 D:太古の高僧の怨念がこもっている。 @@ -3473,6 +3541,8 @@ P:4:0d0:0:0:0 F:STR | CON | SUST_STR | SUST_CON | F:RES_FEAR | FREE_ACT | ACTIVATE U:SHIKOFUMI +D:$It is the traditional garb for a Sumo wrestler. Just touching it makes you +D:$ feel stronger. D:遥か東の国のスモー戦士が身につける正装だ。 D:その豪華な宝飾は力強さを感じさせる。 @@ -3483,6 +3553,7 @@ W:20:20:30:50000 P:3:0d0:0:0:20 F:RES_COLD | RES_ACID | RES_CHAOS | LEVITATION | ACTIVATE U:RESIST_COLD +D:$This is the fur cloak of Mook, a red Yeti and Gachapin's friend. D:ガチャピンと対をなす赤い獣の毛皮のクロークだ。 # 金属製ラメラー・アーマー『バテレン鎧』 @@ -3495,6 +3566,7 @@ W:45:5:340:80000 P:23:1d6:5:5:17 F:CHR | REFLECT | F:RES_FIRE | RES_CHAOS | LITE +D:$It is the suit of shining western-style armor that Nobunaga Oda loved. D:織田信長の愛用した光り輝く西洋の鎧だ。 # グレート・ソード『真魔剛竜剣』 (from ダイの大冒険) @@ -3548,6 +3620,10 @@ W:20:15:150:40000 P:6:1d1:-5:10:20 F:INT | WIS | CHR | STEALTH | SPEED | RES_FIRE | F:SUST_STR | SUST_CON | SH_FIRE | REGEN | RES_FEAR +D:$Since ancient times, some martial artists have trained with weighted sandals +D:$ to build leg strength. This is a pair of those, warm to the touch and +D:$ with soles fashioned out of iron. Wear them enough, you'll feel light as +D:$ a feather when you take them off. D:古来より伝わる、男を磨くための靴だ。 D:ふだん身に付けていれば、外したときに自分のからだが羽根のように D:軽く感じられるだろう。 @@ -3592,13 +3668,17 @@ D:この正視するもかなわぬ眩い炎のムチをひとたび手に取れ D:バルログの長ゴズモグは戦において負け知らずであった。 N:213:天性寺聖地蔵尊の六環 -E:of The Bonze Octopus +E:of The Bronze Octopus I:21:7:2 W:35:40:70:125000 P:0:1d7:8:8:8 F:STR | WIS | BLOWS | TUNNEL | ACTIVATE | RES_ACID | RES_ELEC F:REGEN | FREE_ACT | BRAND_ELEC | BLESSED | XTRA_H_RES U:SUMMON_OCTOPUS +D:$It is a walking stick bound with six rings of bronze. According to legend, +D:$ an incarnation of Jizo Daibosatsu carried this staff when he defended +D:$ Kishiwada castle with the assistance of a horde of octopuses he had called +D:$ from the sea. D:その昔、蛸を引き連れて岸和田の地を守るために戦かったという D:蛸法師こと地蔵大菩薩の化身が使っていた六環の錫杖だ。 D:「…その時。一人の法師がどこからともなく現れて、何万という敵に飛びかかり、 @@ -3631,6 +3711,8 @@ F:STEALTH | SEARCH | HIDE_TYPE | SEE_INVIS | F:RES_DARK | ACTIVATE | LITE_M1 | F:INSTA_ART U:BA_DARK +D:$It is a necklace decorated with jet-black jewels. Wear it and feel yourself +D:$ in the dark. D:漆黒の宝玉がつけられた頸飾りだ。 D:身に付けると自分が暗闇の中にいるのを感じる。 @@ -3662,7 +3744,7 @@ U:DISP_CURSE_XTRA D:これを身につけたプレイヤーは呪いをはね返すことができる。 N:218:地獄の -E:of the Hell +E:of Hell I:40:26:-2 W:50:40:30:66666 P:0:0d0:15:15:-5 @@ -3671,6 +3753,8 @@ F:RES_DARK | RES_NETHER | F:SEE_INVIS | AGGRAVATE | ESP_UNDEAD | ACTIVATE | F:INSTA_ART U:BA_DARK +D:$It is one of the restraining collars used for the prisoners in Hell. The +D:$ spite of many prisoners is palpable when near the collar. D:地獄の囚人を拘束する首輪だ。多くの囚人の怨念が込められている。 N:219:帯魔力ペンダント @@ -3700,7 +3784,7 @@ W:20:15:30:50000 P:0:2d1:15:17:0 F:DEX | CHR | STEALTH | F:XTRA_MIGHT | HIDE_TYPE | SHOW_MODS | XTRA_H_RES -D:$This is of Robin Hood who live in the deep forest. +D:$It is the bow of Robin Hood, the bandit in Sherwood Forest. D:シャーウッドの森に住む義賊ロビン・フッドの弓だ。 # from Slash'EM @@ -3712,7 +3796,8 @@ P:0:2d1:15:17:0 F:STR | INFRA | RES_FIRE | SH_FIRE | F:ACTIVATE | HIDE_TYPE | SHOW_MODS U:BRAND_FIRE_BOLTS -D:$This crossbow gives flame energy to bolts which it fires. +D:$This fiery-colored crossbow can cause the bolts it fires to burst into +D:$ flame upon impact. D:この燃えるような色のクロスボウは、発射するボルトに炎の力を D:与えることができる。 @@ -3722,9 +3807,8 @@ I:19:23:4 W:35:30:110:50000 P:0:0d0:40:13:0 F:DEX | HIDE_TYPE | SEE_INVIS | XTRA_MIGHT | SHOW_MODS -D:$With this crossbow, Swiss hero Tell shot an apple exactly -D:$though it was on his son's head, and then he defeated evil -D:$magistrate Gessler. +D:$With this crossbow, the Swiss hero, Tell, shot an apple from his son's +D:$ head and then defeated the Gessler, the tyrannical magistrate. D:スイスの英雄ウィリアム・テルの使ったクロスボウだ。 D:彼は我が子の頭の上のリンゴを正確に撃ち抜き、民衆を苦しめる D:悪代官ゲスラーを打ち破った。 @@ -3735,14 +3819,14 @@ I:18:1:0 W:35:35:2:5000 P:0:6d5:20:16:0 F:KILL_HUMAN -D:$It is said that this bolt sticked onto the heart of Gessler -D:$when Wilhelm Tell shot it. +D:$It is said that Wilhelm Tell slew Gessler, the Austrian magistrate, with +D:$ this bolt. D:かつてウィリアム・テルが撃ち放った1本のクロスボウの矢だ。 D:悪代官ゲスラーの命を正確に奪ったという。 #JX# N:225:アスクレピオスの -E:of Aesculapius +E:of Asclepius I:21:14:3 W:40:45:160:300000 P:0:2d11:15:15:5 @@ -3752,8 +3836,8 @@ F:VAMPIRIC | SLAY_ANIMAL | SLAY_DRAGON | SLAY_HUMAN | F:SLAY_ORC | SLAY_TROLL | SLAY_GIANT | F:RES_POIS | RES_CONF | RES_CHAOS | U:REST_ALL -D:$This is the staff of Aesculapius, who is a greek god of -D:$the medicine. +D:$This is the staff of Asclepius, a hero and god of medicine in Greek +D:$ mythology. D:これは、医学の神アスクレピオスの奇跡の六尺棒だ。 D:どんな怪我もたちまち癒してしまう。 @@ -3816,11 +3900,11 @@ D:大きな太刀を手にして多くの敵兵の命を奪いさった。その D:えに敵陣に突っ込みすぎたという。 N:230:手品師の -E:of Magician +E:of a Magician I:23:1:0 W:1:1:5:3000 P:0:1d1:0:0:0 -D:$This dagger can not injure someone almostly. +D:$This dull dagger has a very faint magic aura about it. D:このダガーは人を傷つけることはないだろう。 N:231:暗殺者荊軻の @@ -3920,6 +4004,7 @@ I:21:5:0 W:45:18:250:2500 P:0:4d6:15:15:0 F:RIDING | WARNING | SLAY_EVIL | KILL_DEMON | ESP_DEMON +D:$What, this useless sword again? Oh! Wait a minute .... D:なんだ、またこの役立たずの剣か。おや?ちょっと待てよ…… # The Light Crossbow 'Wiizapper' (x3) @@ -3931,9 +4016,8 @@ P:0:1d1:13:13:0 F:INFRA | DEX | XTRA_SHOTS | LITE | F:SEE_INVIS | WARNING | F:HIDE_TYPE | SHOW_MODS -D:$The white light crossbow that the fighter Link, wearing green clothes, -D:$bought for training of shooting.'Enjoy shootings at the living room.' -D:$(Nintendo) +D:$Link, a warrior dressed in green, allegedly bought this white light crossbow +D:$ for training. "Enjoy shooting in the living room" (Nintendo) D:緑の服の戦士リンクがボウガンのトレーニングのために購入した D:と言われる軽くて白いクロスボウだ。「リビングで射撃を楽しむ」 D:(Nintendo) @@ -3953,15 +4037,16 @@ D:この不気味に黒光るクロスボウはずっしりと重い。その一 # The Heavy Crossbow of Guanzi (x4) N:241:管子の +E:of Guan Zhong I:19:24:3 W:40:20:200:99999 P:0:4d1:10:15:0 F:INT | WIS | SUST_INT | SUST_WIS | MAGIC_MASTERY | XTRA_SHOTS | F:RES_CONF | RES_NEXUS | FREE_ACT | F:HIDE_TYPE | SHOW_MODS -D:$This is Guan Zhong's heavy crossbow for assassinating. -D:$He took prime minister's post of Qi, although he failed to -D:$take the life of the prince of Qi. +D:$This is Guan Zhong's heavy crossbow. Tutor to a prince of Qi, he +D:$ attempted to use it to kill another prince of Qi but failed. Spared by +D:$ his target, he became the chancellor of Qi. D:斉の管仲が暗殺用に用いた重い弩だ。公子小白を射抜くことはできなかった D:が、後に斉の宰相の座を見事に射止めた。 @@ -4010,18 +4095,22 @@ D:この聖なる鞭は、錬金術師の知恵と乙女の代償によって生 D:退魔の血族ベルモンド家代々の手で振るわれてきた。 D:その力は邪悪な夜の一族に対する呪詛そのものであり、 D:汚れた魂を過たず撃ち滅ぼすだろう。 -D:$This holy whip was generated with wise of a alchemist and a maiden's -D:$sacrifice, wielded by Belmond family, the vampire hunters. -D:$That power is indeed curse of evil household of night -D:$and vanish the poisonous souls. +D:$This holy whip was generated by an alchemist's wisdom and a maiden's +D:$ sacrifice. It has been wielded by generations of the Belmont family, the +D:$ vampire hunters, and is the great bane of any with an unclean soul. N:245:運命のオーブ E:The Orb of Fate I:39:10:3 W:70:70:15:45000 P:0:1d1:0:0:20 -F:WIS | CON | WARNING | ACTIVATE | FULL_NAME | LITE_3 | +F:WIS | CON | WARNING | ACTIVATE | FULL_NAME | LITE_3 | INSTA_ART U:TELEPORT_LEVEL +D:"You may take the Orb of Fate with you. I have removed from it the power +D: to foretell the future, for that power no mortal should have. Its other +D: abilities, however, you have at your disposal. You must now begin in Tyr's +D: name to search for the Amulet of Yendor. May your steps be guided by Tyr, +D: my child." (Norn, Nethack) D:「運命のオーブを持っていきなさい。わたしは運命のオーブから D:人間の手に触れてはならぬ未来を告げる力を取り除きました。 D:しかしながら運命のオーブの他の力は,あなたの思い通りに @@ -4040,6 +4129,9 @@ F:SUST_CHR | SUST_CON | F:RES_SOUND | RES_DISEN | REFLECT | FREE_ACT | ACTIVATE F:IGNORE_ACID | IGNORE_ELEC | IGNORE_FIRE | IGNORE_COLD | AGGRAVATE U:STRAIN_HASTE +D:$A result of Steel Staff Ymir's research project, this swimsuit, powered by +D:$ a hyper vibration crystal, provides much more protection than you might +D:$ expect. D:ドワーフの姫、鋼鉄参謀ユーミルの研究の成果だ。 D:超振動クリスタルが高い防御力をもたらしているらしい。 diff --git a/lib/edit/d_info.txt b/lib/edit/d_info.txt index 5aa9142b2..05c872fcf 100644 --- a/lib/edit/d_info.txt +++ b/lib/edit/d_info.txt @@ -155,7 +155,7 @@ M:IM_FIRE | CAN_FLY | WILD_VOLCANO N:9:地獄 E:Hell -D:$the stairway to the Hell +D:$the stairway to Hell D:地獄への階段 P:62:94 W:666:696:50:1:14:160:90:77:0x0188:0x0280 @@ -167,7 +167,7 @@ M:IM_FIRE | EVIL N:10:天界 E:Heaven -D:$the way to the heaven +D:$the way to Heaven D:天界へと通じる道 P:2:94 W:555:585:50:1:18:160:85:35:0x0040:0x0104 diff --git a/lib/edit/e_info.txt b/lib/edit/e_info.txt index addd70511..dbc6efad8 100644 --- a/lib/edit/e_info.txt +++ b/lib/edit/e_info.txt @@ -117,7 +117,7 @@ F:RES_ACID | RES_ELEC | RES_FIRE | RES_COLD | F:IGNORE_ACID | IGNORE_ELEC | IGNORE_FIRE | IGNORE_COLD | XTRA_H_RES N:10:ドワーフの -E:of Dwarven +E:of the Dwarves X:31:10 W:0:10:0:1500 C:0:0:15:3 @@ -222,7 +222,7 @@ C:0:0:15:0 F:IGNORE_ACID | IGNORE_ELEC | IGNORE_FIRE | IGNORE_COLD N:239:ドワーフの -E:of Dwarven +E:of the Dwarves X:25:20 W:0:15:0:2000 C:0:0:8:2 diff --git a/lib/edit/f_info.txt b/lib/edit/f_info.txt index 2cabc6783..146851294 100644 --- a/lib/edit/f_info.txt +++ b/lib/edit/f_info.txt @@ -912,7 +912,7 @@ F:PERMANENT | GLOW N:76:WEAPON_SMITHS J:武器専門店 -E:Weapon Smiths +E:Weaponsmith's Shop G:3:w W:10 F:SUBTYPE_2 | LOS | PROJECT | MOVE | NOTICE | REMEMBER | STORE | DOOR | @@ -1007,7 +1007,7 @@ F:TELEPORTABLE N:86:SHALLOW_LAVA J:浅い溶岩の流れ E:shallow lava -G:~:U +G:~:o W:2 F:LOS | PROJECT | MOVE | PLACE | DROP | REMEMBER | LAVA | SHALLOW | CAN_FLY | F:TELEPORTABLE @@ -1800,15 +1800,15 @@ F:HURT_DISI | GLASS N:227:HEAVY_COLD_ZONE J:極低温帯 E:heavy cold zone -G:~:W +G:^:b W:2 -F:LOS | PROJECT | MOVE | PLACE | REMEMBER | GLOW | COLD_PUDDLE | DEEP | CAN_FLY | +F:LOS | PROJECT | MOVE | PLACE | REMEMBER | COLD_PUDDLE | DEEP | CAN_FLY | F:TELEPORTABLE N:228:COLD_ZONE J:低温帯 E:cold zone -G:~:w +G:^:B W:2 F:LOS | PROJECT | MOVE | PLACE | DROP | REMEMBER | COLD_PUDDLE | SHALLOW | CAN_FLY | F:TELEPORTABLE @@ -1816,7 +1816,7 @@ F:TELEPORTABLE N:229:HEAVY_ELECTRICAL_ZONE J:高圧帯電帯 E:heavy electrical zone -G:~:y +G:^:y W:2 F:LOS | PROJECT | MOVE | PLACE | REMEMBER | GLOW | ELEC_PUDDLE | DEEP | CAN_FLY | F:TELEPORTABLE @@ -1824,7 +1824,7 @@ F:TELEPORTABLE N:230:ELECTRICAL_ZONE J:帯電帯 E:electrical zone -G:~:o +G:^:o W:2 F:LOS | PROJECT | MOVE | PLACE | DROP | REMEMBER | ELEC_PUDDLE | SHALLOW | CAN_FLY | F:TELEPORTABLE @@ -1834,7 +1834,7 @@ J:深い酸の沼 E:deep acid puddle G:~:u W:2 -F:LOS | PROJECT | MOVE | PLACE | REMEMBER | GLOW | ACID_PUDDLE | DEEP | CAN_FLY | +F:LOS | PROJECT | MOVE | PLACE | REMEMBER | ACID_PUDDLE | DEEP | CAN_FLY | F:TELEPORTABLE N:232:SHALLOW_ACID_PUDDLE @@ -1850,7 +1850,7 @@ J:深い毒の沼 E:deep poisonous puddle G:~:g W:2 -F:LOS | PROJECT | MOVE | PLACE | REMEMBER | GLOW | POISON_PUDDLE | DEEP | CAN_FLY | +F:LOS | PROJECT | MOVE | PLACE | REMEMBER | POISON_PUDDLE | DEEP | CAN_FLY | F:TELEPORTABLE N:234:SHALLOW_POISONOUS_PUDDLE diff --git a/lib/edit/k_info.txt b/lib/edit/k_info.txt index 15dd4304b..317c12646 100644 --- a/lib/edit/k_info.txt +++ b/lib/edit/k_info.txt @@ -320,7 +320,7 @@ E:& Strip~ of Venison G:,:u I:80:33:1500 W:0:0:2:2 -D:$A strip of jerked beef that seems never to spoil. +D:$A strip of jerked beef that never seems to spoil. D:良く乾燥させた肉。決して腐る事が無さそうだ。 N:24:スライムモルド @@ -805,6 +805,8 @@ W:10:0:300:230 A:10/1 P:0:2d8:0:0:0 F:SHOW_MODS | RIDING +D:$A spear with a long conical tip. It is well-suited for the rider of +D:$ a charging horse. D:大きく長い円錐形の穂先を持った槍だ。 D:馬上で構えて突撃する為に作られている。 @@ -921,9 +923,8 @@ I:19:24:0 W:30:0:200:500 A:30/2:40/2 F:SHOW_MODS -# Not all heavy crossbow is the arbalest with a crank! -#D:$The arbalest is so powerful it has to be reinforced with metal and -#D:$requires a crank to be cocked. +D:$A heavy mechanical bow. It is slower to fire than its lighter +D:$ cousin but each bolt fired is deadlier. D:鋼鉄製の弦をあらかじめ引いておき、機械式の引き金を引くだけで矢を発射 D:する事ができる。ショート・ボウやロング・ボウに比べて扱いが簡単な武器だ。 D:ヘヴィ・クロスボウはライト・クロスボウに比べて威力は強いが、 @@ -2262,7 +2263,7 @@ G:?:w I:70:0:0 W:1:0:5:0 A:1/1 -D:$It darkens nearby area or current room and blinds you when you read it. +D:$It darkens the nearby area or current room and blinds you when you read it. D:それは読むと自分の周囲もしくは部屋全体が暗闇に包まれ、盲目になる。 N:209:対邪悪結界:頭森 地跳 真骨 @@ -2369,7 +2370,7 @@ G:?:w I:70:11:0 W:5:0:5:150 A:5/1 -D:$It recalls you to the town, or back into the dungeon you have entered when +D:$It recalls you to the town or back into the dungeon you have entered when D:$you read it. D:それは読むと地上にいる時は行ったことのあるダンジョンの最深階へ、 D:ダンジョンにいる時は地上へと移動する。 @@ -2625,7 +2626,8 @@ I:75:59:0 W:65:0:4:25000 A:65/1 P:0:1d1:0:0:0 -D:$You gain experience half of your experience (max: 100000) when you quaff it. +D:$You gain experience equal to the lesser of 100000 or half of your current +D:$ experience when you quaff it. D:それは飲むと現在の経験値の半分(100000を超えない)の経験を得る。 N:245:眠り:ぼやけた色の @@ -2656,8 +2658,8 @@ I:75:9:50 W:0:0:4:0 A:0/1 P:0:1d1:0:0:0 -D:$It confuses and hallucinates you when you quaff it. If you are a monk, -D:$you may be a drunken master. +D:$It confuses you and causes you to hallucinate when you quaff it. If you are +D:$ a monk, you may be a drunken master. D:それは飲むと混乱し、幻覚に侵される。修行僧が飲むと酔拳を使えるらしい。 N:248:毒:薄い緑色の @@ -2879,7 +2881,7 @@ A:20/1:45/1:80/1:100/1 P:0:1d1:0:0:0 F:IGNORE_ACID | IGNORE_ELEC | IGNORE_FIRE | IGNORE_COLD D:$You get temporary resistances to elements and poison when you quaff it. -D:$These resistances is cumulative with equipment. +D:$These resistances are cumulative with equipment. D:それは飲むと一時的に酸・電撃・火炎・冷気・毒の耐性を得る。 D:装備による耐性に累積する。 @@ -3017,7 +3019,8 @@ I:65:5:15 W:10:0:10:100 A:10/1 P:0:1d1:0:0:0 -D:$It fires a beam destroys all traps and doors on the line when you use it. +D:$It fires a beam that destroys all traps and doors along a line when you +D:$ use it. D:それは使うとトラップやドアを破壊するビームを放つ。 N:282:マジック・ミサイル:チタンの @@ -3058,7 +3061,7 @@ I:65:3:12 W:20:0:10:350 A:20/1 P:0:1d1:0:0:0 -D:$It fires a beam teleports all monsters on the line when you use it. +D:$It fires a beam that teleports all monsters along a line when you use it. D:それは使うとモンスターをテレポートさせるビームを放つ。 N:286:トラップ解除:銅メッキの @@ -3068,7 +3071,7 @@ I:65:4:10 W:20:0:10:700 A:20/1 P:0:1d1:0:0:0 -D:$It fires a beam destroys all traps on the line when you use it. +D:$It fires a beam that destroys all traps along a line when you use it. D:それは使うとトラップを破壊するビームを放つ。 N:287:サンダー・ボール:金メッキの @@ -3310,7 +3313,7 @@ I:55:7:12 W:20:0:50:800 A:20/1 P:0:1d2:0:0:0 -D:$It fires a line of light directed randomly for 5d3 times when you use it. +D:$It fires 5d3 random lines of light when you use it. D:それは使うとランダムな方向への光線を5d3回放つ。 N:309:スピード・モンスター:ユーカリの @@ -3453,7 +3456,7 @@ I:55:0:10 W:5:0:50:0 A:5/1:50/1 P:0:1d2:0:0:0 -D:$It darkens nearby area or current room and blinds you when you use it. +D:$It darkens the nearby area or current room and blinds you when you use it. D:それは使うと自分の周囲もしくは部屋全体が暗闇に包まれ、盲目になる。 N:323:抹殺:チークの @@ -3507,7 +3510,7 @@ W:70:0:50:4500 A:70/2 P:0:1d2:0:0:0 D:$It does 150 damage to all evil monsters in sight, gives temporary -D:$protection from lesser evil creature, cures poison, stuuned, cuts, removes +D:$protection from lesser evil creatures, cures poison, stuuned, cuts, removes D:$fear and heals you 50 when you use it. D:それは使うと視界内の邪悪なモンスターに150のダメージを与え、 D:一時的に弱い邪悪な者の攻撃を回避しやすくなる結界を張り、 @@ -3769,7 +3772,7 @@ I:66:3:60 W:30:0:15:4000 A:15/16:30/4 P:0:1d1:0:0:0 -D:$It recalls you to the town, or back into the dungeon you have entered when +D:$It recalls you to the town or back into the dungeon you have entered when D:$you zap it. D:それは振ると地上にいる時は行ったことのあるダンジョンの最深階へ、 D:ダンジョンにいる時は地上へと移動する。 @@ -3872,7 +3875,7 @@ I:66:13:25 W:45:0:15:1400 A:23/8:45/2 P:0:1d1:0:0:0 -D:$It fires a beam teleports all monsters on the line when you zap it. +D:$It fires a beam that teleports all monsters along a line when you zap it. D:それは振るとモンスターをテレポートさせるビームを放つ。 N:365:トラップ解除:ジルコンの @@ -3882,7 +3885,7 @@ I:66:14:22 W:35:0:15:2100 A:18/4:35/1 P:0:1d1:0:0:0 -D:$It fires a beam destroys all traps on the line when you zap it. +D:$It fires a beam that destroys all traps along a line when you zap it. D:それは振るとトラップを破壊するビームを放つ。 N:366:サンダー・ボール:亜鉛の @@ -5800,8 +5803,8 @@ G:?:w I:70:43:0 W:10:0:5:1000 A:10/8 -D:$It increases the number you can study spells when you read. If you are the -D:$class can't study or don't need to study, it effects none. +D:$It increases the number of spells you can study when read. If you are a +D:$ class that can't study or don't need to study, it has no effect. D:それは読むと呪文を1つ学習できるようになる。 D:学習できない、または学習する必要のない職業では何も起きない。 @@ -5873,8 +5876,8 @@ I:55:30:8 W:35:0:50:800 A:35/1 P:0:1d2:0:0:0 -D:$It raises corpses and skeletons nearby you from dead and makes them your -D:$pet when you use it. +D:$It raises nearby corpses and skeletons from the dead and makes them your +D:$ pets when you use it. D:それは使うと自分の周囲の死体や骨を生き返らせてペットにする。 N:609:石 @@ -6041,7 +6044,7 @@ W:65:0:10:4000 A:65/3 P:0:1d1:0:0:0 F:IGNORE_ACID | IGNORE_ELEC | IGNORE_FIRE | IGNORE_COLD -D:$It fires a bolt of meteor (damage: (15+level/3)d13) when you use it. +D:$It fires a bolt of meteors (damage: (15+level/3)d13) when you use it. D:それは使うとダメージ(15+レベル/3)d13の隕石の矢を放つ。 N:629:魔力の嵐:トネリコの @@ -6239,7 +6242,7 @@ G:?:w I:70:54:0 W:30:0:5:1000 A:30/2 -D:$It summons a monster corresponds to your race as your pet when you read it. +D:$It summons a monster that corresponds to your race as your pet when you read it. D:それは読むと自分の種族に対応したモンスター1体をペットとして召喚する。 N:651:魔法の笛 @@ -6378,7 +6381,7 @@ G:?:w I:70:55:0 W:20:0:5:100 A:20/6 -D:$It creates one amuzing item when you read it. +D:$It creates one amusing item when you read it. D:それは読むと誰の得なのかわからないものを1個作り出す。 N:668:*誰得*:挽怒 那 務故 @@ -6387,7 +6390,7 @@ G:?:w I:70:56:0 W:20:0:5:500 A:60/8 -D:$It creates some amuzing item when you read it. +D:$It creates some amusing item when you read it. D:それは読むと誰の得なのかわからないものを複数作り出す。 N:669:オーブ diff --git a/lib/edit/misc.txt b/lib/edit/misc.txt index 9d1171bda..2b03b4645 100644 --- a/lib/edit/misc.txt +++ b/lib/edit/misc.txt @@ -13,13 +13,13 @@ M:WX:99 M:WY:66 # Maximum number of monsters in r_info.txt -M:R:1123 +M:R:1172 # Maximum number of items in k_info.txt M:K:672 # Maximum number of vaults in v_info.txt -M:V:171 +M:V:173 # Maximum number of terrain features in f_info.txt M:F:255 diff --git a/lib/edit/q0000004.txt b/lib/edit/q0000004.txt index 94ed48894..50a309cad 100644 --- a/lib/edit/q0000004.txt +++ b/lib/edit/q0000004.txt @@ -50,7 +50,7 @@ Q:4:T:蔵の物品はお礼にお持ちください。空いた蔵は演劇場 # Description for quest failed ?:[AND [EQU $QUEST4 5] [EQU $QUEST_TYPE4 3]] Q:$4:T:You didn't find the weapon? Well, the monsters have probably -Q:$4:T:carried it away. Too bad, it would have been quiet helpful +Q:$4:T:carried it away. Too bad, it would have been quite helpful Q:$4:T:in driving the evil out of our town. Q:4:T:あの武器を見つけられなかったのですか?おそらく、モンスターどもが持っていって Q:4:T:しまったんでしょうな。とても残念です。アレはこの街から悪を一掃する diff --git a/lib/edit/q0000005.txt b/lib/edit/q0000005.txt index e91e028e6..3d6af9a61 100644 --- a/lib/edit/q0000005.txt +++ b/lib/edit/q0000005.txt @@ -32,7 +32,7 @@ Q:5:T:どうかモンスターどもを一掃して塔を取り戻してくだ Q:$5:T:Thank you for cleaning the tower of all these strange creatures. Q:$5:T:I've talked with Astinus, the local librarian, Suiyan, the local Q:$5:T:weaponmaster, and Lorien, the local beastmaster. They will offer you -Q:$5:T:a special discount price when they serve you. And a small reward +Q:$5:T:a special discount price when they serve you, and a small reward Q:$5:T:awaits you outside. Q:5:T:塔の怪物を一掃して下さって有難うございます。この街の司書のアスティヌス、 Q:5:T:武器匠の水庵、モンスター仙人のロリエンに話を付けておいたので、 diff --git a/lib/edit/q0dumpwitness.txt b/lib/edit/q0dumpwitness.txt index 4b987f7d7..ac3835a3f 100644 --- a/lib/edit/q0dumpwitness.txt +++ b/lib/edit/q0dumpwitness.txt @@ -11,8 +11,8 @@ Q:34:Q:6:0:0:0:5:0:0:0:6 # Description for quest ?:[LEQ $QUEST34 2] -Q:$34:T:Adventures are dead in the building behind this one. All windows and -Q:$34:T:doors are locked, we guess the murderer still hide in the house. +Q:$34:T:Adventurers are dead in the building behind this one. All windows and +Q:$34:T:doors are locked. We guess the murderer still hides in the house. Q:$34:T:Your task is to clean everything up in the room. Q:34:T:この建物の裏の一軒家で冒険者が不審な死に方をしているとの報告がありました。 Q:34:T:窓にも扉にも鍵がかかっており、殺戮者はまだ内部に潜んでいると思われます。 diff --git a/lib/edit/q0willow.txt b/lib/edit/q0willow.txt index d86f0bf34..1caec8710 100644 --- a/lib/edit/q0willow.txt +++ b/lib/edit/q0willow.txt @@ -25,7 +25,7 @@ Q:31:T:クエストは街の東の平地にあります。 # Description for quest reward ?:[EQU $QUEST31 3] -Q:$31:T:Thank you! Your reward is wating outside. +Q:$31:T:Thank you! Your reward is waiting outside. Q:31:T:ありがとうございます!外にお礼が置いてあります。 ?:1 diff --git a/lib/edit/qdarkelf.txt b/lib/edit/qdarkelf.txt index 856da5717..8cd8f7087 100644 --- a/lib/edit/qdarkelf.txt +++ b/lib/edit/qdarkelf.txt @@ -25,7 +25,7 @@ Q:32:T:たくさん護衛がいますから注意して下さい。 # Description for quest reward ?:[EQU $QUEST32 3] -Q:$32:T:Thank you! Your reward is wating outside. +Q:$32:T:Thank you! Your reward is waiting outside. Q:32:T:ありがとうございます!外にお礼が置いてあります。 ?:1 diff --git a/lib/edit/qhaunted.txt b/lib/edit/qhaunted.txt index 3facf6902..796b775f4 100644 --- a/lib/edit/qhaunted.txt +++ b/lib/edit/qhaunted.txt @@ -23,7 +23,7 @@ Q:25:T:我々はその家に住み着いている悪霊を退治してくれる ?:[EQU $QUEST25 3] Q:$25:T:Well done, indeed! Our citizens can finally sigh in relief. Q:$25:T:As a reward, we would like to give you something that will -Q:$25:T:help you sence enemy even more efficiently! +Q:$25:T:help you sense the enemy even more efficiently! Q:25:T:本当に良くやってくれました!我々住民はようやく安心することが出来ます。 Q:25:T:お礼として、邪悪な者どもを更に効果的に感知することができるアイテムを Q:25:T:差し上げます。 diff --git a/lib/edit/r_info.txt b/lib/edit/r_info.txt index 680afdf6a..eeec9e694 100644 --- a/lib/edit/r_info.txt +++ b/lib/edit/r_info.txt @@ -2036,7 +2036,7 @@ F:EVIL | UNDEAD | IM_POIS | RES_NETH | F:NO_CONF | NO_SLEEP | HURT_LITE S:1_IN_10 S:CAUSE_1 | S_UNDEAD -D:$Frightening skeletal figures in black robes. +D:$Is a frightening skeletal figure in a black robe. D:黒装束に身を包んだ恐ろしげな骸骨の姿だ。 D:(ロバート・ブロック「窖に潜むもの」) @@ -2051,7 +2051,7 @@ B:CLAW:POISON:1d4 F:OPEN_DOOR | BASH_DOOR | FRIENDS | F:NO_CONF | NO_SLEEP | UNDEAD | EVIL | NO_FEAR | IM_POIS F:IM_COLD | RES_NETH | COLD_BLOOD | EMPTY_MIND -D:$Corpses awakened from their sleep by dark sorceries. +D:$It is a corpse awakened from its sleep by dark sorceries. D:暗黒魔術により眠りを覚まされた死体だ。 #J0# @@ -2270,7 +2270,7 @@ S:SHOOT | HEAL | TRAPS A:221:1:5 V:75 D:$The legendary archer steals from the rich (you qualify). -D:この伝説の射手は金持ち(あなたは合格)から金を盗む +D:この伝説の射手は金持ち(あなたは合格)から金を盗む。 #JZ# N:139:ナーグリング @@ -2501,7 +2501,7 @@ B:CLAW:EAT_FOOD:1d2 B:BITE:EAT_FOOD:1d4 F:MULTIPLY | IM_POIS | RES_DARK | HURT_LITE | EVIL | DEMON | OPEN_DOOR | F:TAKE_ITEM | CAN_SWIM -D:$Don't splash water on them, and don't feed them after midnight! +D:$Don't splash water on them and don't feed them after midnight! D:水を掛けたり、真夜中を過ぎてから餌をやってはいけない! #J0# @@ -3500,7 +3500,7 @@ F:FRIENDS | F:BASH_DOOR | WILD_WASTE | F:ANIMAL | IM_COLD | DROP_SKELETON | DROP_CORPSE D:$A large and muscled wolf from the northern wastes. Its breath is cold and -D:$icy and its fur coated in frost. +D:$icy, and its fur is coated in frost. D:北の荒れ地からやって来た、大きくて屈強な狼だ。その息は氷のようで、毛皮は D:冷気に覆われている。 @@ -4115,7 +4115,7 @@ W:14:1:0:60:0:0 B:HIT:HURT:6d3 B:HIT:HURT:6d3 F:AQUATIC | WILD_ALL | RES_WATE -D:$A race of fair yet belligrent sea elves. +D:$A race of fair yet belligerent sea elves. D:洗練された、しかも好戦的な海のエルフの種族だ。 #JZ# @@ -4291,7 +4291,7 @@ B:BITE:HURT:1d2 F:RAND_50 | CAN_FLY | F:WEIRD_MIND | MULTIPLY | F:ANIMAL -D:$It makes you itch just to look at it. +D:$It makes you itch just looking at it. D:それを見るだけで体がむずがゆくなってくる。 #J0# @@ -4380,7 +4380,7 @@ F:MALE | WILD_ALL | F:FRIENDS | DROP_60 | F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE F:EVIL | ORC | RES_DARK -D:$He is a hideous deformed cross-breed with man and orc, combining man's +D:$He is a hideous deformed cross-breed of man and orc, combining man's D:$strength and cunning with orcish evil. D:彼は人間とオークの混血でひどく醜い容貌をしている。人間の力強さとオークの邪悪 D:なずる賢さを受け継いでいる。 @@ -4450,7 +4450,7 @@ S:SCARE | S_ANT | CAUSE_2 | SLOW D:$An unfortunate individual, who was killed by the incurable D:$disease known as Nurgle's Rot, and was transformed into a D:$rotting demon zombie. It has but one eye, and a single -D:$pale horn in its forehead. +D:$pale horn on its forehead. D:<ナーグル>の腐れ病という名で知られる不治の病によって死んだ不運な人間で、 D:腐乱した悪魔のゾンビになってしまっている。目は一つだけで、一本の D:青白い角が額に生えている。 @@ -4541,7 +4541,7 @@ B:BITE:POISON:1d3 B:BITE:LOSE_STR:1d4 F:UNDEAD | EVIL | IM_POIS | IM_COLD | WEIRD_MIND | NO_FEAR | CAN_FLY | F:RES_NETH | NO_CONF | NO_SLEEP | DROP_60 | BASH_DOOR | FRIENDS | COLD_BLOOD -D:$A skullpack animated by necromantic spells. +D:$A skull animated by necromantic spells. D:死霊術の呪文により動いている髑髏だ。 #JZ# @@ -5580,7 +5580,7 @@ F:ONLY_GOLD | DROP_60 | DROP_90 | IM_POIS | CAN_FLY | F:OPEN_DOOR | BASH_DOOR | MOVE_BODY | DRAGON | F:WILD_WOOD | WILD_MOUNTAIN | DROP_SKELETON | DROP_CORPSE | F:ANIMAL | EVIL | RIDING | EAT_POISONOUS -D:$A fast-moving and deadly dragonian animal. Beware its poisonous sting! +D:$A fast-moving and deadly dragon-like animal. Beware its poisonous sting! D:それは素早く動く危険なドラゴンのような生き物だ。 D:その毒爪には気をつけろ! @@ -5675,7 +5675,7 @@ B:BITE:HURT:1d10 B:BITE:HURT:1d10 F:BASH_DOOR | WILD_WOOD | WILD_GRASS | F:ANIMAL | DROP_SKELETON | DROP_CORPSE | EAT_SPEED -D:$A fierce and dangerous cat, its huge tusks and sharp claws would lacerate +D:$A fierce and dangerous cat, its huge tusks and sharp claws would pierce D:$even the strongest armour. D:獰猛で危険なネコであり、その巨大な牙と鋭い爪は最強の鎧でさえも切り D:裂いてしまう。 @@ -9193,9 +9193,8 @@ B:HIT:EXP_20:13d1 F:FORCE_MAXHP | OPEN_DOOR | FRIENDS | DROP_60 | REGENERATE | F:ONLY_ITEM | NO_FEAR | NONLIVING | F:EVIL | IM_POIS | IM_COLD | IM_FIRE | RES_CHAO | DEMON -D:$Slender, red-skinned demons twisting in nightmarish shapes. -D:$They are armed with hellblades, which will suck the life from -D:$your body. +D:$It is a slender, red-skinned demon twisted into a nightmarish shape. +D:$ It is armed with a hellblade, which will suck the life from your body. D:流血の神<コーン>の配下の下級悪魔。 D:悪夢のような姿に捻じ曲がった、細身で赤い肌をした悪魔だ。 D:ヘルブレードを装備していて、その刃はあなたの生命力を @@ -9341,6 +9340,10 @@ B:EXPLODE:SHATTER:100d2 F:FORCE_SLEEP | FORCE_MAXHP | UNIQUE | REFLECTING | F:EMPTY_MIND | COLD_BLOOD | BASH_DOOR | IM_FIRE | IM_COLD | IM_ELEC | IM_POIS F:NO_FEAR | NO_CONF | NO_SLEEP | NONLIVING | RES_TELE +D:$It is the left hand of Killer Queen, the visual manifestation of the life +D:$ energy of Yoshikage Kira. It will follow the heat of the adventurer's +D:$ body forever. "Sheer Heart Attack in Killer Queen will definitely kill +D:$ the prey at which he's aimed ...." D:吉良吉影のスタンド『キラークイーン』の左手だ。冒険者の体温を頼りに D:どこまでも追いかける。「『キラークイーン』の『シアーハートアタック』 D:は狙った獲物は絶対に仕留める……」 @@ -9574,7 +9577,7 @@ F:ANIMAL | RES_INER | NO_CONF | NO_SLEEP S:1_IN_5 | S:BR_INER D:$Bizarrely, this hound seems to be hardly moving at all, yet it approaches -D:$you with deadly menace. It makes you tired just to look at it. +D:$you with deadly menace. It makes you tired just looking at it. D:奇怪なことだが、この犬は全然動いていないように見えるにも関わらず、何故か D:恐ろしい勢いで近づいてくるのだ。それを見ているだけで疲労してくる。 @@ -9835,7 +9838,7 @@ S:1_IN_4| S:BO_FIRE V:150 D:$Back from the grave, to wreak vengeance upon the living. A gaunt, tall, -D:$skeletal figure wearing a ruined plate mail. +D:$skeletal figure wearing ruined plate mail. D:生ける者たちへ復讐するために墓から甦った亡霊だ。 D:気味の悪い、背の高い骸骨の姿で D:壊れたプレートメイルを身につけている。 @@ -13741,8 +13744,7 @@ F:BASH_DOOR | STUPID | DROP_CORPSE F:EVIL | IM_FIRE | FORCE_SLEEP | FORCE_MAXHP S:1_IN_5 | S:BO_PLAS | BA_FIRE -D:$It is a belligrent minotaur with some destructive magical arsenal, armed -D:$with a hammer. +D:$It is a belligerent minotaur with some magic powers and armed with a hammer. D:破壊的な魔法の火器を持ち、ハンマーを装備した好戦的なミノタウロスだ。 #J0# @@ -14321,7 +14323,7 @@ S:MIND_BLAST | BA_CHAO | SCARE | BRAIN_SMASH | DRAIN_MANA | S:S_HOUND | S_DEMON | S_DRAGON | TPORT | HASTE | CONF | S:TELE_AWAY | FORGET D:$The most powerful of Tzeentch's servitors. This demon looks like -D:$a huge bird-creature, with the head of a predatory bird and +D:$a huge bird-like creature, with the head of a predatory bird and D:$fantastically multi-coloured wings. D:混沌の魔神<ティーンチ>の最も強力な手下だ。この悪魔は巨大な鳥のようで、 D:頭部は肉食の猛禽類、羽根は幻想的な虹色に彩られている。 @@ -16163,7 +16165,7 @@ V:60 D:$"He saw why the shadow on the frosted pane yesterday had been D:$headless and he screamed... but before he could scream out his D:$protest his breath was cut off, as the hands descended on his -D:$face and the wed ret mouths opened in their palms." +D:$face and the wed red mouths opened in their palms." D:煉瓦の壁の向こう側にある広大な廃虚の地下に住む、邪悪な神。 D:頭の無い太った人間のような姿をしている。 D:両手に濡れた赤い口が付いており、全身が白熱して光り輝いている。 @@ -16346,7 +16348,7 @@ F:IM_POIS | IM_FIRE | FORCE_SLEEP | FORCE_MAXHP | NONLIVING S:1_IN_4 | S:ROCKET V:166 -D:$Reverbrant metal steps announce the arrival of this huge creature, +D:$Reverberant metal steps announce the arrival of this huge creature, D:$half demon half machine. It has an unsurpassable firepower. D:響き渡る金属的な足音がこの巨大な、半悪魔半機械の怪物の D:到来を告げる。その火力には何者もかなわない。 @@ -17815,7 +17817,7 @@ F:DROP_GOOD | DROP_GREAT | RES_CHAO | RES_NETH | F:SMART | KILL_WALL | KILL_BODY | POWERFUL | F:REGENERATE | NONLIVING | CAN_FLY | RIDING | F:EVIL | IM_ACID | IM_FIRE | IM_COLD | IM_ELEC | IM_POIS | -F:NO_CONF | NO_SLEEP | NO_FEAR | NO_STUN | RES_TELE | GUARDIAN | +F:NO_CONF | NO_SLEEP | NO_FEAR | NO_STUN | RES_TELE | S:1_IN_3 | S:S_MONSTERS | BR_CHAO | BA_CHAO | ROCKET | S_CYBER | S_KIN | S:BR_NETH | BR_MANA | S_HI_UNDEAD | S_HI_DRAGON | S_UNIQUE | @@ -18028,6 +18030,7 @@ F:RES_ALL | POWERFUL | F:NO_CONF | NO_SLEEP | NO_STUN | EMPTY_MIND | RES_TELE | S:1_IN_1 | S:BLINK | BO_MANA | BA_CHAO | BA_FIRE | TPORT | PSY_SPEAR +D:$Is a bit of magical slime wrapped in hard metal. D:硬い金属に包まれたスライムだ。 N:872:『八岐大蛇』 @@ -18049,6 +18052,8 @@ S:1_IN_2 | S:BR_FIRE | BR_NEXU | BR_CHAO | BR_POIS | BR_DISE | BR_PLAS | BR_NUKE | BR_DARK A:128:1:25 V:150 +D:$Is a legendary snake, with eight necks and eight tails, living in Izumo. +D:$ If denied sacrificial victims, it causes floods and annihilates people. D:出雲の国に棲む伝説の蛇で、八つの首と八つの尾を持つ。 D:いけにえを拒むと洪水を起こして人々を全滅させる。 @@ -18073,12 +18078,11 @@ S:1_IN_2 | S:ROCKET | HEAL | BLINK | INVULNER A:16:1:50 V:900 -D:$His favorite food is roasting rice noodle. -D:$He is the lone wolf filled with the adventurous spirit. +D:$His favorite food is grilled rice noodle. +D:$He is a lone wolf filled with the adventurous spirit. D:$His righteousness and courage are more than the average. D:$He sometimes become emotional. -D:$He would like to choose a haphazard life rather than an intentional life. -D:$He is poor at treating women. +D:$He prefers a haphazard life to an intentional one and is a known misogynist. D:好きな食べ物は焼きビーフン。抑えてはいるが、冒険心旺盛な D:一匹狼。正義感、勇気とも平均以上だがカッとしやすい所もある。 D:計画的人生より行き当たりばったりの人生を選んでしまうタイプで、 @@ -18175,6 +18179,10 @@ F:NO_CONF | NO_SLEEP | RES_TIME | RES_TELE | REFLECTING | S:1_IN_4 | S:SCARE | S_KIN | WORLD | TELE_TO A:146:1:20 +D:$Dio, who became an immortal vampire with the help of a stone mask, +D:$ looks only at the adventurer. Watch out for The World, Dio's stand +D:$ or visual manifestation of his life energy: "I don't know what his +D:$ stand is, but it is certain that it can only be used at close range." D:石仮面の力で不死の吸血鬼となったディオは冒険者を餌としか見ていない。 D:『ザ・ワールド』に気をつけろ!「奴のスタンドの正体は分からないが、 D:至近距離でしか使えないことは確かだッ」 @@ -18190,6 +18198,8 @@ F:KILL_WALL | CAN_SWIM | DROP_CORPSE | MOVE_BODY | F:FORCE_MAXHP | ONLY_GOLD | DROP_2D2 | DROP_3D2 | S:1_IN_3 S:SPECIAL +D:$A mass of worms, mad with rage, rushes towards you strewing miasma in +D:$ its wake. D:怒りに狂った王蟲の群は瘴気をまき散らしながら突進してくる。 N:880:時を統べる者『リチャード・ウォン』 @@ -18211,6 +18221,9 @@ S:TPORT | SCARE | S_KIN | BLINK | HEAL | S:TELE_TO | CONF | BO_MANA | BRAIN_SMASH | S:BA_WATE | TELE_AWAY | S:DISPEL | WORLD | PSY_SPEAR +D:$He has psychic powers that allow him to freely manipulate time and space. +D:$ He keeps calm and is always smiling, but beneath that mask is a +D:$ cold-blooded soul. D:時間と空間を自在に操る超能力者。 D:冷静沈着で、常に余裕の笑みを浮かべている。 D:だが、その仮面の下には冷血な魂が宿り、自分自身の欲望の為なら手段を選ばない。 @@ -18233,6 +18246,9 @@ F:NO_SLEEP | RES_TELE | RES_NETH | RES_TIME | POWERFUL | CAN_FLY | S:1_IN_3 | S:TPORT | BLIND | HOLD | BLINK | HEAL | HASTE | S:TELE_TO | CONF | BO_MANA | BRAIN_SMASH | PSY_SPEAR +D:$Seeing the look in your eyes, he asks, "Do you know me?" You're very +D:$ tempted to answer, "Of course! You're Superman Locke! Immortal, +D:$ the strongest ESPer ever!" D:「そうだ!超人ロック!」「僕を知っているのか?」 D:「もちろん!不老不死にして、史上最強のエスパー!」 D:(聖悠紀、超人ロック「赤いサーペント」) @@ -18257,6 +18273,8 @@ S:TPORT | BLIND | BLINK | HEAL | HASTE | S:CONF | BO_MANA | BRAIN_SMASH | PSY_SPEAR | S:BA_NETH | BA_DARK | BA_CHAO | S:S_MONSTERS | S_DEMON | S_KIN +D:$She tried to destroy Earth solely because she wanted to fight Locke, the +D:$ Superman, as a superhuman. D:彼女はただ超人として超人との戦いを望むが故に、皇帝に扮し地球を D:滅ぼそうとした。「とにかくある朝起きてみるとディナールは皇帝 D:レイザークの神聖なる領地となっていたのだ」 @@ -18284,6 +18302,8 @@ S:1_IN_3 | S:S_MONSTERS | BR_CHAO | BA_CHAO | ROCKET | S_CYBER | S_KIN | S:BR_NETH | BR_MANA | S_HI_UNDEAD | S_HI_DRAGON | S_UNIQUE | S:BR_NUKE | BR_DISI | HAND_DOOM | DISPEL +D:$Has returned from the bottom of Hell to take revenge on those who +D:$ destroyed it. D:自分を滅ぼした者に復讐するため、地獄の底から復活した! N:884:有毒ガス @@ -18429,8 +18449,8 @@ F:SMART | OPEN_DOOR | BASH_DOOR | HAS_LITE_2 | F:IM_ACID | IM_COLD | IM_ELEC | IM_POIS | NO_CONF | NO_SLEEP | S:1_IN_2 | S:CAUSE_3 | BO_WATE | BO_MANA -D:$This body of once-mighty warrior was so dominated by Sauron's power that he -D:$became little more than a mindless undead of evil. +D:$This body of a once-mighty warrior was so dominated by Sauron's power that +D:$ he became little more than a mindless undead of evil. D:かつて屈強さを誇ったこの戦士の肉体はサウロンの力に完全に支配され、 D:今ではほとんど意思を持たない邪悪なアンデッドに成り下がってしまった。 @@ -18480,7 +18500,7 @@ F:EVIL | TROLL | IM_POIS | NO_CONF | NO_SLEEP | NO_FEAR | REGENERATE S:1_IN_8 | S:BLINK D:$This troll is a king, which means it's still stupid, but has even more power. -D:$It never comes alone, and can call out to other trolls. +D:$It never comes alone and can call out to other trolls. D:このトロルはトロルの中の王だ。彼は依然としてトロルであり、頭は良くないが、 D:その力はさらに強力だ。彼は一人でいる事はなく常に手下を連れている。 @@ -18923,6 +18943,8 @@ S:1_IN_3 | S:BLIND | CONF | SCARE | S:BA_DARK | BO_NETH | BR_NETH | BR_DARK | BR_NUKE | BR_POIS | HAND_DOOM | S:S_DEMON | S_KIN | DISPEL +D:$Said to be the commander of a hellish army, this terrifying demon can cause +D:$ ruin merely by saying his own name. D:その名を口にするだけで破滅をもたらすほどの恐るべきデーモンであり、 D:地獄の軍勢の指揮官であると言われている。 @@ -18940,6 +18962,8 @@ F:RES_CHAO | RES_DISE | RES_WALL | RES_INER | RES_TIME | RES_GRAV | RES_TELE | F:NO_FEAR | NO_STUN | NO_CONF | NO_SLEEP | CAN_FLY | S:1_IN_3 | S:HOLD | BLIND | CONF | SCARE | SLOW +D:$This is Bull Gates's most devastating weapon, propagating fear and ruin +D:$ throughout the world. D:ブル・ゲイツの究極兵器であり、全世界に破滅をもたらす恐怖の存在だ。 N:922:ピカチャウ @@ -18954,6 +18978,7 @@ F:DROP_CORPSE | ONLY_GOLD | DROP_1D2 | IM_ELEC | ANIMAL | AURA_ELEC | F:SELF_LITE_1 | S:1_IN_5 | S:BR_ELEC | BO_ELEC +D:$It's shockingly pretty, for a rat. D:かわいらしい外見をしているが、油断すると思わぬ衝撃を受けるだろう。 N:923:雪女 @@ -18967,6 +18992,13 @@ B:TOUCH:COLD:3d5 F:FEMALE | IM_COLD | DROP_1D2 | NONLIVING | AURA_COLD | S:1_IN_5 S:BR_COLD | BO_COLD | BA_COLD +D:$This female figure stirs the memory of a tale of two woodcutters sheltering +D:$ from a winter storm in a small hut: "He was awakened by a showering of +D:$ snow in his face. The door of the hut had been forced open; and, by the +D:$ snow-light he saw a woman in the room, - a woman all in white. She was +D:$ bending above Mosaku, and blowing her breath upon him; - and her breath +D:$ was like a bright white smoke." (from Lafcadio Hearn's "Yuki-onna" in his +D:$ collection of stories, "Kwaidan: Stories and Studies of Strange Things") D:顔に雪がさかんに降りかかるので、巳之吉は目をさました。 D:小屋の戸はむりにこじ開けられて、小屋の中に一人の女―すっかり白い装いをした D:女がいるのが、雪明かりで見えた。女は茂作のうえに身をかがめて、 @@ -18993,6 +19025,8 @@ W:18:3:0:50:0:0 B:HIT:HURT:2d7 B:HIT:HURT:2d7 F:DROP_60 | ANIMAL | DROP_SKELETON | DROP_CORPSE | FRIENDS | ONLY_GOLD +D:$It is one of the wise monkeys of the Nikko Tosho-gu shrine and very likely +D:$ has friends nearby. D:常に集団で現れる。つまり、日光猿の軍団なわけで…… N:926:ツチノコ @@ -19005,6 +19039,8 @@ B:CLAW:HURT:2d5 B:BITE:HURT:3d4 B:CRUSH:SUPERHURT:5d8 F:ANIMAL | DROP_SKELETON | DROP_CORPSE +D:$It is snake-like but much wider in the middle than the ends. You've heard +D:$ rumors of someone paying 1,000,000 gold for one captured alive. D:それを捕えた者には $1,000,000 の賞金が出るといわれている。 # Description in English by Nick Keulmann @@ -19217,6 +19253,9 @@ F:OPEN_DOOR | RES_NETH | RES_PLAS | F:EVIL | IM_FIRE | NO_CONF | NO_SLEEP S:1_IN_3 | S:S_DEMON | BA_CHAO | BO_PLAS | BR_FIRE | BR_PLAS +D:$This horrible creature has four legs, nine arms, and bluish skin. It wears +D:$ a high golden crown with horns on either side. Large fangs protude from +D:$ its mouth. According to legend, it guards an artifact that Ishtar wants. D:脚が4本。腕は9本。 D:両脇から角が出ている丈高めの黄金の冠をかぶる。体色は青。牙を持つ。 D:女神イシターを封印したと伝えられる。 @@ -19237,6 +19276,8 @@ F:DROP_2D2 | DROP_1D2 | DROP_GOOD | ONLY_ITEM | CAN_SWIM | F:GOOD | IM_COLD | IM_POIS | IM_ACID | IM_ELEC | IM_FIRE | REGENERATE | S:1_IN_3 | S:CAUSE_4 | TELE_TO +D:$He is the rightful master of the martial art, Hokuto Shinken. At a time +D:$ when power seems to be everything, he lives in love and fights for love. D:一子相伝とされる北斗神拳の伝承者だ。力が全てを支配すると思われた D:時代にあって愛に生き、愛のために戦っている。 @@ -19298,8 +19339,8 @@ S:1_IN_3 | S:BLIND | HOLD | SCARE | CAUSE_3 | CAUSE_4 | MIND_BLAST | S:BO_COLD | BA_COLD | BA_NETH | S:S_UNDEAD | S_HI_UNDEAD -D:$A Ringwraith powerful in fell sorcery, he yearns for the life he has lost -D:$for a life of everlasting torment. +D:$Is a Ringwraith powerful in fell sorcery. He suffers eternally yearning +D:$ for his lost soul. D:堕落した魔法使いである強力な指輪の幽鬼だ。彼は魂を失って永劫の苦しみの中に D:いるため、新たな魂を心から渇望している。 @@ -19511,6 +19552,7 @@ F:ONLY_GOLD | DROP_90 | F:EMPTY_MIND | BASH_DOOR | REFLECTING | F:IM_FIRE | IM_COLD | IM_ELEC | IM_POIS | IM_ACID | F:NO_CONF | NO_SLEEP | NO_FEAR | NONLIVING +D:$It walks on four legs and has a shiny shell like that of a beetle. D:このモンスターに対してはあまりの魔法の無力さに呆然とするであろう。 D:噂では中にクリボーが入っているとか…… @@ -19524,6 +19566,7 @@ F:FORCE_SLEEP | F:FRIENDS | F:OPEN_DOOR | BASH_DOOR | F:ANIMAL | NO_CONF | NO_SLEEP +D:$This dog is about to explode. D:今にも爆発しそうな犬だ。 N:953:折れたデスソード @@ -19538,6 +19581,7 @@ B:HIT:POISON:1d1 F:NONLIVING | NO_FEAR | F:STUPID | COLD_BLOOD | NO_CONF | NO_SLEEP | F:EVIL | IM_COLD | IM_FIRE | IM_ELEC | IM_POIS +D:$This broken sword moves about, searching for prey. D:獲物の血を求めて動き回る折れた剣だ。 N:954:オークの弩弓隊 @@ -19572,7 +19616,6 @@ F:ANIMAL | DROP_SKELETON | DROP_CORPSE | RIDING D:$This pitiful horse has not been well fed, it walks unsteadily. D:満足に飼葉も与えられていないがりがりでふらふらの哀れな馬だ。 -# Description in English by Nick Keulmann N:956:馬 E:Horse G:q:o @@ -19582,8 +19625,8 @@ B:BITE:HURT:1d8 B:KICK:HURT:2d4 F:WILD_WASTE | BASH_DOOR | F:ANIMAL | DROP_SKELETON | DROP_CORPSE | RIDING -D:$As for the horse with the animal of four feet which can run fast, -D:$it was utilized for a long time as the vehicle of the human. +D:$This four-legged beast is capable of running quickly. Others like it +D:$ have been used by humans as vehicles since ancient times. D:馬は速く駆けることのできる四本足の獣で、 D:古くから人間の乗り物として利用されてきた。 @@ -19687,6 +19730,10 @@ F:REGENERATE | EAT_GIVE_STR | EAT_GIVE_CON | EAT_LOSE_INT | EAT_LOSE_CHR | S:1_IN_6 | S:BR_SHAR | TELE_TO V:150 +D:$This muscle-bound man with a horned helmet has won the Great Galaxy +D:$ Bodybuiling championship ten times in a row. He is eager to prevent +D:$ anyone from challenging his title. He's also know for his signature +D:$ move, the Bo Emperor Building Cutter. D:銀河ボディビルコンテスト十連続グランドチャンピオン。 D:必殺技はボ帝ビルカッター。 @@ -19715,6 +19762,9 @@ F:NO_CONF | NO_SLEEP | NO_FEAR S:1_IN_5 | S:BLIND | CONF | SCARE | CAUSE_2 | BA_POIS | S:S_MONSTER +D:$This strange creature, transformed into an image of a strange creature +D:$ that is transformed into an abandoned box, waits for a stupid adventurer +D:$ to get close to its poisonous claws. D:放置された箱に化けている奇妙な生物の像に化けている奇妙な生物で、 D:愚かな冒険者がその毒のある爪の射程に入るのを待ち構えている。 @@ -19733,6 +19783,7 @@ F:OPEN_DOOR | GOOD | CAN_SWIM | CAN_FLY | F:NO_CONF | NO_SLEEP | FRIENDLY | TAKE_ITEM | S:1_IN_4 | S:BA_FIRE | HASTE | HOLD | CONF | BLIND +D:$Absolutely not a Mario analog! D:断じてマリオの類似品ではない!(本人主張) N:967:ガキ大将『ジャイアン』 @@ -19751,6 +19802,7 @@ F:OPEN_DOOR | BASH_DOOR | TAKE_ITEM | MOVE_BODY | RES_SOUN S:1_IN_5 | S:BR_SOUN | V:150 +D:$What's yours is mine, and what's mine is mine. D:お前のものは俺のもの。俺のものは俺のもの。 N:968:氷竜『ブラムド』 @@ -19811,7 +19863,7 @@ F:NO_FEAR | NO_STUN | RIDING | SELF_DARK_2 | S:1_IN_3 | S:BRAIN_SMASH | BR_DARK | BR_NETH | BA_NETH D:$One of the ancient dragons of Lodoss, it causes destruction with -D:$an dark and nether breath. +D:$a dark and nether breath. D:ロードスの古代竜の一匹で、暗黒と地獄のブレスで破壊を引き起こす。 N:971:金鱗の竜王『マイセン』 @@ -19852,7 +19904,7 @@ F:NO_FEAR | NO_STUN | RIDING | S:1_IN_3 | S:BRAIN_SMASH | BR_FIRE | BA_FIRE D:$One of the ancient dragons of Lodoss, it causes destruction -D:$with it's breath of fire. +D:$with its breath of fire. D:ロードスの古代竜の一匹で、その火炎のブレスで全てを焼き尽くす。 N:973:暗黒の島マーモの皇帝『ベルド』 @@ -19989,6 +20041,8 @@ F:ONLY_ITEM | DROP_1D2 | DROP_2D2 | DROP_GOOD | DROP_CORPSE | F:OPEN_DOOR | BASH_DOOR | CAN_SWIM | AURA_ELEC | F:EVIL | GIANT | IM_POIS | IM_FIRE | IM_ELEC A:194:1:33 +D:$Living on Mt. Oe, in the province of Tanba, this large ogre seized young +D:$ women and treasure from nearby Kyoto. D:丹波の国の大江山をねぐらとし、京の都を襲っては財宝と娘を D:奪う凶悪な鬼どもの首領だ。 @@ -20035,6 +20089,7 @@ F:COLD_BLOOD | OPEN_DOOR | CAN_FLY | F:EVIL | UNDEAD | IM_COLD | IM_POIS | RES_NETH | NO_CONF | NO_SLEEP | S:1_IN_5 S:BLIND | HOLD | SCARE | CAUSE_4 | BO_NETH | S_UNDEAD +D:$Carrying its head in its hand, this ominous monster comes to announce death. D:この不吉なモンスターは自分の首を脇に抱え、死を告げにやってくる。 N:983:ヒバゴン @@ -20047,6 +20102,9 @@ B:CLAW:HURT:1d7 B:BITE:HURT:2d7 F:OPEN_DOOR | BASH_DOOR | WILD_MOUNTAIN | DROP_CORPSE | F:ANIMAL +D:$Resembling a monkey but, at five feet tall, much larger than monkey, this +D:$ animal must be one of the mysterious beasts that live around Mt. Hiba in +D:$ Hiroshima Prefecture. D:広島県の比婆山一帯に現れる「サルに似ているが、サルよりも大きな」謎の動物。 N:984:鵺 @@ -20059,6 +20117,10 @@ B:CLAW:HURT:1d10 B:BITE:POISON:1d10 F:FORCE_SLEEP | DROP_CORPSE | ANIMAL | F:BASH_DOOR | WILD_MOUNTAIN | +D:$This strange hybrid has the head of a monkey, the body of a racoon dog, +D:$ the legs of a tiger and a tail that is the front half of a snake. It +D:$ makes an eerie, sorrowful cry, like that of a scaly thrush, and is +D:$ wreathed with clouds of black smoke. D:頭がサル、胴はタヌキ、尾はヘビ、手足はトラで、鳴き声はトラツグミに D:似ていたという奇妙な生物だ。非常に変わった D:外見をしていて、近寄りがたい雰囲気がある。 @@ -20075,6 +20137,7 @@ B:BITE:LOSE_ALL:3d8 F:REFLECTING | DROP_1D2 | DROP_2D2 | RES_DISE | ANIMAL | F:REGENERATE | IM_ACID | IM_FIRE | IM_COLD | IM_ELEC | IM_POIS | F:NO_CONF | NO_SLEEP | RES_TELE | CAN_SWIM | RIDING +D:It is a white horse with a horn on its forehead. D:額に一本の角を持った白馬で、乙女にのみ心を許すと言われる。 N:986:猫又 @@ -20088,6 +20151,8 @@ F:MALE | EVIL | FORCE_SLEEP | DROP_1D2 | ANIMAL | F:SMART | OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE S:1_IN_3 | S:SCARE | CAUSE_2 | S_MONSTER +D:$This cat has a second tail. There are fables about old cats becoming +D:$ such creatures and bedeviling people. D:猫が年老いると次第に高い知能と分かれた尻尾を持ち、猫又になるという。 N:987:九尾の狐 @@ -20105,6 +20170,7 @@ F:NO_CONF | NO_SLEEP | RES_TELE | RIDING | S:1_IN_2 S:S_MONSTERS | CAUSE_3 | CAUSE_4 | CONF | BRAIN_SMASH | DRAIN_MANA | SCARE | S:HASTE | HOLD | +D:It is a fox with nine tails, and you can sense its strong magical power. D:尾が九つに分かれた狐で、強い妖力を秘めている。 N:988:鳳凰 @@ -20126,6 +20192,10 @@ S:1_IN_3 | S:SCARE | BRAIN_SMASH | DRAIN_MANA | S:BR_FIRE | BR_LITE | BR_SOUN | HEAL | S_ANGEL V:133 +D:$It is a ruler among the birds and a symbol of virtue and grace. It has +D:$ the beak of a rooster, the face of a swallow, the forehead of a fowl, +D:$ the neck of a snake, the back of a tortoise, the hindquarters of a stag, +D:$ and tail of a fish. D:伝説の聖なる鳥だ。前は鴻、後は麟、顎は燕、嘴は鶏、頸は蛇、尾は魚、額は鸛、 D:顋は鴛、背は亀甲、羽は五采を備え、龍の紋様を持つと言う。 @@ -20147,6 +20217,8 @@ F:NO_STUN | NO_CONF | NO_SLEEP | RIDING S:1_IN_6 | S:BLIND | SHRIEK | DISPEL | INVULNER | S_ANGEL V:133 +D:$It is deer-like but with the scales of a dragon and the tail of an ox. All +D:$ accounts attest to its holiness and power. D:龍の鱗に牛の尾、馬の蹄を持ち、角の生えた四本足の聖なる獣で、 D:王者が仁のある政治を行った時に姿を現わすと言われている。 @@ -20160,10 +20232,11 @@ B:BITE:HURT:3d8 B:KICK:HURT:4d10 B:KICK:HURT:4d10 F:DROP_2D2 | ANIMAL | NO_SLEEP | CAN_FLY | RIDING +D:$It is a large white horse with wings. D:翼の生えた天駆ける白馬だ。 N:991:オーディンの乗馬『スレイプニル』 -E:Sleipnir, the Odin's Steed +E:Sleipnir, Odin's Steed G:q:o I:130:40d100:20:140:50 W:51:3:0:17000:0:0 @@ -20174,6 +20247,8 @@ B:BITE:HURT:10d10 F:FORCE_MAXHP | UNIQUE | ANIMAL | CAN_FLY | F:REGENERATE | BASH_DOOR | IM_FIRE | IM_COLD | IM_ELEC | F:IM_POIS | NO_CONF | NO_SLEEP | NO_FEAR | DROP_CORPSE | RIDING +D:$This great eight-legged horse is Odin's mount. It is said to be the child +D:$ of Loki, the giant. D:オーディンの乗馬たるスレイプニルは、8本の足を持つ名馬である。 D:巨人ロキの子供であると言われている。 @@ -20190,6 +20265,10 @@ F:UNIQUE | MALE | CAN_SPEAK | DROP_CORPSE | WILD_WOOD | F:FORCE_SLEEP | FORCE_MAXHP | RAND_25 | GOOD | FRIENDLY | F:SMART | OPEN_DOOR | BASH_DOOR | MOVE_BODY | RIDING | F:ANIMAL | IM_FIRE | IM_POIS | NO_CONF | NO_SLEEP +D:$As large as a small horse, Huan, the hound of Valinor, has the ability to +D:$ understand and speak the languages of elves and men. However, he never +D:$ speaks in front of Feanor's sons as he's only allowed to speak three times +D:$ before he dies. D:ヴァリノールの猟犬たるフアンは特別な力を持ち、人語を理解し、そして D:話すことができる。しかし、フェアノールの子息達の前で話すことは無い。 D:なぜならば彼は死ぬまでに3度しか話をすることを許されておらず、 @@ -20339,8 +20418,8 @@ B:HIT:SUPERHURT:4d8 B:HIT:SUPERHURT:4d8 F:MALE | DROP_CORPSE | DROP_SKELETON | FORCE_MAXHP | HAS_LITE_2 | HUMAN | F:OPEN_DOOR | BASH_DOOR | NO_FEAR | UNIQUE2 -D:$He is always traveling togather with -D:$Mitsukuni of the Yellow Gate, Grand Duke of Mito +D:$He is always traveling together with +D:$ Mitsukuni of the Yellow Gate, Grand Duke of Mito. D:ご老公を助けて旅から旅へ。とんだ爺に仕えたもんだ。 N:1002:『格さん』 @@ -20352,8 +20431,8 @@ B:HIT:SUPERHURT:4d8 B:HIT:SUPERHURT:4d8 F:MALE | DROP_CORPSE | DROP_SKELETON | FORCE_MAXHP | HAS_LITE_2 | HUMAN | F:OPEN_DOOR | BASH_DOOR | NO_FEAR | UNIQUE2 -D:$He is always traveling togather with -D:$Mitsukuni of the Yellow Gate, Grand Duke of Mito +D:$He is always traveling together with +D:$ Mitsukuni of the Yellow Gate, Grand Duke of Mito. D:ご老公を助けて旅から旅へ。とんだ爺に仕えたもんだ。 N:1003:ゴースト『Q』 @@ -20372,12 +20451,12 @@ F:ONLY_ITEM | DROP_90 | DROP_GOOD | F:INVISIBLE | COLD_BLOOD | PASS_WALL | RES_NETH F:UNDEAD | NO_SLEEP V:25 -D:$He has only three hair. He is careless, but kind, and always a bit hungry. +D:$He has only three hairs. He is careless, but kind, and always a bit hungry. D:毛が三本しかないんだよ。ずっこけなんだ優しい奴さ。 D:いつもおなかを空かせているんだよ。 N:1004:異世界からの勇者『ピップ』 -E:Pip, the Braver from Another World +E:Pip, the Adventurer from Another World G:p:u I:110:20d48:20:80:15 W:35:3:0:1800:0:0 @@ -20392,6 +20471,9 @@ F:NO_CONF | NO_SLEEP | FRIENDLY | TAKE_ITEM | S:1_IN_5 | S:BA_FIRE | HOLD | BO_FIRE | HEAL A:179:1:50 +D:$Merlin the magician summoned this young warrior to complete a variety of +D:$ tasks. Pip carries a dubious sword, created by Merlin and modeled on King +D:$ Arthur's Excalibur. D:かの大魔術師マーリンが異世界から召喚した(と言い張っている)戦士だ。 D:「若者はエクスカリバーを短くしたような怪しげな剣を持ち、 D:稲妻だとか火の玉だとか、わけのわからぬことを呟いている。」 @@ -20414,6 +20496,8 @@ F:IM_ACID | IM_ELEC | IM_POIS | NO_CONF | NO_SLEEP | EVIL S:1_IN_2 | CAUSE_3 | BA_FIRE | HOLD | BLIND | CONF | SCARE S:TRAPS | BO_PLAS | BO_NETH S:BA_DARK | S_HOUND +D:$This black-haired sorceror does all he can to wither crops, steal pigs, +D:$ dry up waterways, and kidnap a queen. D:「そこには、魔法の杖を持った黒髪、黒髭、黒い目をして、 D:黒いローブをまとったいかにも極悪非道といった感じの男が描かれた絵が、 D:無造作に貼り付けてある」 @@ -20608,8 +20692,7 @@ B:EXPLODE:HURT:30d2 F:EMPTY_MIND | COLD_BLOOD | F:IM_FIRE | IM_COLD | IM_ELEC | IM_POIS | F:NO_FEAR | NO_CONF | NO_SLEEP | NONLIVING | RES_TELE -D:$It is a small bomb of a form like a spider. -D:$It walks toward you! +D:$It is a small bomb in a spider-like package. It walks toward you! D:蜘蛛のような形の小さな爆弾で、あなたに向って歩き、爆発する。 # @@ -20643,6 +20726,10 @@ F:DROP_2D2 | DROP_1D2 | DROP_GOOD | ONLY_ITEM | CAN_SWIM | F:GOOD | IM_COLD | IM_POIS | IM_ACID | IM_ELEC | IM_FIRE | REGENERATE | S:1_IN_3 | S:CAUSE_3 | TELE_TO +D:$Raou is the eldest of four honorary brothers, another being Kenshirou, +D:$ who were trained by the master of Hokuto Shinken, a martial art. +D:$ Headstrong, Raou tries to forge a new order through conquest in a +D:$ turbulent dark era. D:ラオウは北斗神拳伝承者ケンシロウの義兄であり北斗神拳の使い手である。 D:激動の闇の時代に、己の信念で新たな時代を築こうとした。 @@ -20660,6 +20747,7 @@ B:BITE:HURT:6d6 F:FORCE_MAXHP | UNIQUE | ANIMAL | F:REGENERATE | BASH_DOOR | IM_FIRE | IM_COLD | IM_ELEC | F:IM_POIS | NO_CONF | NO_SLEEP | NO_FEAR | DROP_CORPSE | RIDING +D:$This rough horse, with its large black body, is just right for Raou. D:黒く大きな体をしたこの荒ぶる馬は、まさにラオウの乗馬にふさわしい。 # @@ -20714,10 +20802,9 @@ F:EVIL | REGENERATE | F:OPEN_DOOR | BASH_DOOR | RES_WALL S:1_IN_8 | S:TELE_TO | BO_MANA -D:$He looks like brawny human being apparently. -D:$However, unlike man, it has the tail of a monkey. -D:$This tail proves he is a Saiyan. -D:$A Saiyan's fighting power is far superior to human's and will bring many destruction. +D:$He looks like a brawny human. However, unlike a man, he has the tail of a +D:$ monkey. This tail proves he is a Saiyan. A Saiyan's fighting power is +D:$ far superior to a human's and will cause much destruction. D:逞しい人間のようだが、猿の尻尾が付いている。これこそがサイヤ人の証だ。 D:その戦闘力は人間を凌駕し、多くの破壊を呼び起こすだろう。 @@ -20747,8 +20834,9 @@ F:TAKE_ITEM | OPEN_DOOR | BASH_DOOR | F:EVIL | S:1_IN_2 | S:BLINK | TPORT | TELE_TO | CONF | TRAPS -D:$A class of its own: you are already too late to protect your possessions -D:$and he seems to have studied magic too, and is a master of setting traps. +D:$He is a thief almost without equal; you are already too late to protect +D:$ your possessions. He seems to have studied magic too and is a master +D:$ of setting traps. D:その技、だれにも真似はできない。今さら財産を守っても手遅れだ。 D:彼は魔法を学び、罠を仕掛けることを覚えているのだ。 @@ -20771,8 +20859,8 @@ S:1_IN_3 | S:BLIND | HOLD | SCARE | CAUSE_3 | DARKNESS | S:BO_ICEE | BO_NETH | BA_COLD | BA_NETH | BA_WATE | S:S_UNDEAD -D:$The ferryman across the river Styx to the land of the dead. -D:$He wishes to receive payment for your entry. +D:$He is the ferryman for the boat to cross the river Styx to the land of +D:$ the dead. He wishes to receive payment for your entry. D:三途の川の死者の国への渡し守だ。 D:あなたを乗せて渡し賃をもらおうと考えている。 @@ -20813,8 +20901,8 @@ B:BITE:HURT:3d10 F:MALE | ESCORT F:BASH_DOOR | FORCE_MAXHP | UNIQUE | DROP_CORPSE F:ANIMAL | EVIL | WILD_WOOD | WILD_MOUNTAIN | NO_SLEEP | NO_FEAR -D:$A king of mad bear. He had built his stronghold at Hutago mountain, -D:$and is reigning over there. +D:$He is king of the mad bears. He has built his stronghold at Hutago +D:$ mountain and reigns from there. D:二子峠に己の牙城を築き上げ君臨する凶熊どもの王だ。 N:1028:凶熊 @@ -20827,7 +20915,7 @@ B:CLAW:HURT:2d5 B:BITE:HURT:3d6 F:WEIRD_MIND | BASH_DOOR | FRIENDS | DROP_SKELETON | DROP_CORPSE F:ANIMAL | EVIL | WILD_WOOD | WILD_MOUNTAIN -D:$These bears are followers of Red Helm. +D:$This bear is a follower of Red Helm. D:『赤カブト』の配下の熊だ。 N:1029:ベビーサタン @@ -20845,7 +20933,7 @@ D:$A demon small in stature whose face you can't help but love. D:憎めない顔をした小柄な悪魔だ。 N:1030:南蛮王『孟獲』 -E:Meng Huo, the King of Southerings +E:Meng Huo, the King of the Southerners G:p:o I:110:38d10:20:50:20 W:18:2:0:250:0:0 @@ -20879,8 +20967,9 @@ F:NO_CONF | NO_SLEEP | CAN_FLY | F:COLD_BLOOD | BASH_DOOR | POWERFUL | RAND_25 | F:GOOD | DROP_CORPSE | SELF_LITE_2 V:150 -D:$He was the braver of Atlantis. His body was converted by a Shinto priest, -D:$in order to fight against "Papa". His body is now made by Orihalcon. +D:$He is a robotic soldier from the lost city of Atlantis. Rediscovered in +D:$ Tokyo, a Shinto priest converted his body into orihalcon to fight against +D:$ "Papa". D:もとはアトランティスの勇者。 D:『パパ』に立ち向かうために神官の手によってオリハルコンの体に改造された。 @@ -20954,7 +21043,7 @@ B:CRUSH:HURT:4d8 F:NEVER_MOVE | NONLIVING | NO_FEAR | F:STUPID | COLD_BLOOD | CHAR_MULTI | NO_CONF | NO_SLEEP | F:EVIL | IM_COLD | IM_FIRE | FORCE_MAXHP | IM_ELEC | IM_POIS -D:$It resembles a normal armor until some poor fool ventures too close! +D:$It resembles normal armor until some poor fool ventures too close! D:哀れで愚かな冒険者が近づいて来るまでは普通の鎧に似ている。 N:1036:トラップマスター @@ -20967,6 +21056,7 @@ F:MALE | HUMAN | DROP_SKELETON | DROP_CORPSE | F:DROP_1D2 | EAT_GIVE_DEX | EAT_LOSE_WIS | OPEN_DOOR | BASH_DOOR | EVIL | S:1_IN_2 | S:TRAPS | BLINK +D:$Be careful! When you see him, you're likely already surrounded with traps. D:気をつけろ!姿を見たときはすでに罠に囲まれているぞ。 N:1037:聖堂騎士 @@ -21025,7 +21115,7 @@ F:TAKE_ITEM | OPEN_DOOR | BASH_DOOR S:1_IN_4 | S:SHOOT | MISSILE | S_MONSTER | BO_ELEC | BLINK D:$A warrior who is at one with nature. A master of both bow and sword, with -D:$minor spellcasting skills, and animals come to do his bidding. +D:$minor spellcasting skills and animals that come to do his bidding. D:自然と共に戦う戦士だ。弓にも剣にも達者で、多少の魔法も使うことができ、 D:動物達を飼い、従えている。 @@ -21038,6 +21128,7 @@ F:CHAMELEON | WILD_WOOD | DROP_1D2 | DROP_CORPSE | DROP_SKELETON | ANIMAL | F:CAN_FLY | IM_FIRE | IM_COLD | IM_ELEC | IM_ACID | IM_POIS | S:1_IN_1 S:SPECIAL +D:$This lizard can change its appearance to blend in with its surroundings. D:周囲の環境に合わせてその姿を変えると言われる生物だ。 N:1041:カメレオンの王 @@ -21050,8 +21141,8 @@ F:CHAMELEON | DROP_3D2 | DROP_CORPSE | DROP_SKELETON | ANIMAL | F:CAN_FLY | IM_FIRE | IM_COLD | IM_ELEC | IM_ACID | IM_POIS S:1_IN_1 S:SPECIAL -D:カメレオンは周囲の環境に合わせてその姿を変えると言われるが、 -D:それは王とて例外ではない。 +D:$This king of the chameleons, like its lesser kin, can change its appearance +D:$ to blend in with its surroundings. N:1042:幻の鯨『イッカク』 E:Narwhal @@ -21067,9 +21158,8 @@ F:ONLY_ITEM | DROP_2D2 | DROP_GOOD | F:IM_COLD | RES_WATE | F:IM_POIS | NO_CONF | NO_SLEEP | NO_STUN | F:RIDING -D:$This is the whale of the tradition which gets across to the Inuit -D:$who lives in the world of winter. It is said that the mystical horn -D:$of this whale cures all illnesses. +D:$This is the legendary whale of the Inuit living in the winter world. It +D:$ is said that the horn of this whale can cure any disease. D:冬の世界に住むイヌイット族に伝わる伝説の鯨で, D:その神秘の角はあらゆる病に効くとされる。 @@ -21093,8 +21183,8 @@ F:OPEN_DOOR | BASH_DOOR | SMART | F:ANIMAL | IM_ACID | IM_FIRE | IM_COLD | IM_POIS | NO_CONF | NO_SLEEP S:1_IN_3 | S:BO_COLD | BA_COLD | BO_ICEE | BR_COLD -D:$This bird is the porter of the mansion in which Dio Brando hides and lives. -D:$For it, a dog may be a favorite food. +D:$This bird guards the mansion in which Dio Brando hides and lives. Dogs +D:$ may be its favorite food. D:ディオが隠れ棲む館の門番であるこの鳥は犬が D:大好物なのかもしれない。 @@ -21119,7 +21209,7 @@ D:彼にとっては冒険者など獲物にすぎない。 #J0# N:1045:分解ボルテックス -E:Disintegrate vortex +E:Disintegration vortex G:v:s I:140:32d20:100:80:0 W:65:6:0:5000:0:0 @@ -21129,6 +21219,8 @@ F:EMPTY_MIND | BASH_DOOR | POWERFUL | KILL_WALL | KILL_ITEM | F:NO_CONF | NO_SLEEP | NO_FEAR | NO_STUN | NONLIVING S:1_IN_6 | S:BR_DISI +D:$You see streams of dust spiraling inward from rapidly crumbling stone on +D:$ the walls or floor. D:周囲のものが渦巻き状に分解されていくのが見える。 N:1046:黒色王『ウルファング』 @@ -21145,7 +21237,7 @@ F:FORCE_MAXHP | HAS_LITE_1 | DROP_SKELETON | DROP_CORPSE | F:ONLY_ITEM | DROP_2D2 | DROP_GOOD | F:TAKE_ITEM | OPEN_DOOR | BASH_DOOR | F:EVIL -D:$A short and swarthy Easterling dressed in Black. +D:$A short and swarthy Easterling dressed in black. D:背が低くて浅黒い肌をした東夷で、黒い服に身を包んでいる。 N:1047:黄衣の修行僧 @@ -21256,7 +21348,7 @@ F:SMART | TAKE_ITEM | OPEN_DOOR | BASH_DOOR | POWERFUL | F:IM_FIRE | IM_COLD | IM_POIS | NO_CONF | NO_SLEEP | RES_TELE | S:1_IN_3 | S:HEAL | HASTE | BLIND | CONF | SCARE | TPORT | BLINK -D:$A shabby humanoid with a wrinkled skin. It seems to shift +D:$A shabby humanoid with wrinkled skin. It seems to shift D:$in and out of existance as you watch. D:しわくちゃの肌を持つみすぼらしい姿の人間型モンスターだ。 D:実存と非実存の間を行ったり来たりしている。 @@ -21393,7 +21485,7 @@ F:FORCE_MAXHP | DROP_CORPSE | WILD_TOWN | WILD_ONLY #F:ONLY_ITEM | DROP_90 | DROP_GOOD | FRIENDLY | F:OPEN_DOOR | BASH_DOOR | HAS_LITE_1 | F:NO_CONF | NO_SLEEP -D:$Brazen faced this creature is more impudent than normal troll. +D:$Brazen faced, this creature is more impudent than a normal troll. D:面の皮は普通のトロルよりも厚い。 N:1061:『恐竜バーニーちゃん』 @@ -21435,7 +21527,7 @@ D:グルーの頭を笑う者は、そのうち笑えないことに気づくだ D:ていうかグルーを笑って生きのびた者はいない。 N:1063:巨大白シラミの王『lousy』 -E:Lousy, the King of Louses +E:Lousy, the King of Lice G:I:W I:130:11d11:8:10:10 W:9:3:0:100:0:0 @@ -21451,7 +21543,7 @@ F:ONLY_ITEM | DROP_1D2 | DROP_GOOD | S:1_IN_6 S:S_KIN D:$This huge louse is the ruin of the sad man -D:$who had become a louse just because he loves louses. +D:$who had become a louse just because he loves lice. D:この巨大なシラミはシラミを愛するあまりシラミになってしまった D:哀れな人間のなれの果てだ。 @@ -21473,6 +21565,9 @@ S:TPORT | BLINK | TELE_AWAY | TELE_LEVEL | HASTE | S:SLOW | HOLD | S:BR_TIME | BR_NEXU | BR_GRAV | BR_INER | S:S_DRAGON +D:$The figure is distorted, like but not like the way swirling water or air +D:$ above a hot surface can twist a shape, but it appears to be a huge dragon, +D:$ somehow. D:このような存在にはかつて出会ったことがない。 D:その周囲の空間も時も歪んで見えるためよく分からないが、 D:なんとなく巨大なドラゴンがいるように見える。 @@ -21528,8 +21623,9 @@ B:HIT:HURT:1d5 B:CRUSH:HURT:1d6 F:TAKE_ITEM | OPEN_DOOR | DROP_CORPSE | RAND_25 F:ANIMAL | TANUKI -D:$Tanuki (raccoon dog) is thought to bewitch people in Japanese. -D:$Tanuki can disguise as human beings by putting a magic leaf on his/her head. +D:$It is a dog-like carnivorous mammal with markings like a raccoon. In +D:$ Japanese tales, a tanuki (raccoon dog) can bewitch people or disguise +D:$ itself as a human being by placing a magic leaf on its head. D:日本の伝説では、たぬきは人を化かすと伝えられている。 D:魔法の木の葉を頭に載せて人に化けるのだ。 @@ -21553,7 +21649,7 @@ F:INVISIBLE | PASS_WALL | F:UNDEAD | EVIL S:1_IN_2 | S:SHOOT | TELE_AWAY | TPORT | HASTE | BLINK | HEAL -D:$He is one of the greatest trickster. Even greatest warrior cannot +D:$He is one of the greatest tricksters. Even the greatest warrior cannot D:$ defeat him, and his storm of holy might arrows from the dark have D:$ defeated numerous victims. D:彼はこの世界で最も偉大ないかさま師だ。いかなる剣の達人も彼に深い傷を @@ -21644,7 +21740,7 @@ F:UNIQUE | MALE | EVIL | HAS_LITE_2 | HUMAN | F:FORCE_MAXHP | CAN_SPEAK | WILD_ALL | DROP_SKELETON | DROP_CORPSE | F:ONLY_ITEM | DROP_1D2 | DROP_GOOD | F:OPEN_DOOR | BASH_DOOR -D:$He is a junior brother of king of southerings Meng Huo. +D:$He is a junior brother of the king of the southerners, Meng Huo. D:南蛮王孟獲の弟だ。武勇には多少の自信がある。 N:1074:火の神『祝融』 @@ -21660,13 +21756,13 @@ F:FORCE_MAXHP | CAN_SPEAK | WILD_ALL | DROP_SKELETON | DROP_CORPSE | F:ONLY_ITEM | DROP_1D2 | DROP_GOOD | OPEN_DOOR | BASH_DOOR | S:1_IN_9 S:SHRIEK -D:$She is the wife of king Meng Huo. She is called as the avater of -D:$flame spirit. +D:$She is the wife of king Meng Huo. She is said to be an avatar of a +D:$ flame spirit. D:南蛮王孟獲の妻だ。彼女は火の神の化身と言われている。 D:その武勇を侮るな。 N:1075:南蛮人『帯来洞主』 -E:Dailai Dongzhu, the Captain of Southerings +E:Dailai Dongzhu, the Captain of the Southerners G:p:u I:110:22d10:20:35:20 W:10:2:0:100:0:0 @@ -21684,7 +21780,7 @@ D:$He comes to help his sister and her husband Meng Huo. D:南蛮王孟獲の援軍として現れた南蛮の将だ。孟獲の義理の弟にあたる。 N:1076:禿竜洞主『朶思大王』 -E:King Duosi, the Chief of Southerings +E:King Duosi, the Chief of the Southerners G:p:v I:110:25d10:20:45:20 W:11:2:0:150:0:0 @@ -21701,7 +21797,7 @@ D:$the enemy. D:南蛮随一の知恵者と言われる有力領主だ。彼の知略は蜀軍を苦しめた。 N:1077:南蛮の酋長『木鹿大王』 -E:King Mulu, the Chief of Southerings +E:King Mulu, the Chief of the Southerners G:p:g I:110:35d10:20:45:20 W:16:2:0:250:0:0 @@ -21714,12 +21810,12 @@ F:FORCE_MAXHP | CAN_SPEAK | DROP_SKELETON | DROP_CORPSE | F:ONLY_ITEM | DROP_1D2 | DROP_GOOD | OPEN_DOOR | BASH_DOOR S:1_IN_6 | S:S_ANT | S_SPIDER -D:$He is one of chiefs of Nanman. He is also good beast master. +D:$He is one of chiefs of Nanman. He is also a good beast master. D:南蛮を支配する酋長の一人だ。彼の動物軍団には孟獲も絶大な信頼を寄せる。 D:ただしカラクリは嫌いだ。 N:1078:烏戈国王『兀突骨』 -E:Wutugu, the Chief of Southerings +E:Wutugu, the Chief of the Southerners G:P:u I:110:35d10:20:60:20 W:17:2:0:250:0:0 @@ -21814,13 +21910,16 @@ F:ONLY_ITEM | DROP_1D2 | DROP_GOOD | DROP_GREAT | WILD_WOOD | F:TAKE_ITEM | OPEN_DOOR | BASH_DOOR | EVIL | DROP_SKELETON | DROP_CORPSE S:1_IN_4 S:SHOOT | BLINK +D:$He is an elementary school student who, with his weapons such as the +D:$ Alpha Gun, Visual Belt, and Sky Rod, indiscriminately slaughters +D:$ Juralians on a daily basis. D:アルファガン、ビジュームベルト、スカイロッドなどの破壊兵器を所持し、 D:毎日のようにジュラル星人を大量虐殺している小学生だ。 D:「チャージマン!殺してやる!」「それは僕が言う言葉だ!」 D:(『チャージマン研!』アニメ第36話・『戦慄!悪魔の病院』) N:1082:ジュラル星人 -E:Alien Jural +E:Juralian G:h:v I:105:3d6:10:10:10 W:5:8:0:20:0:0 @@ -21831,6 +21930,10 @@ F:DROP_90 | OPEN_DOOR | BASH_DOOR | FRIENDS | DROP_CORPSE | F:WILD_WOOD | HAS_LITE_1 | S:1_IN_6 S:SHOOT +D:$This maroon-colored, vaguely humanoid, creature with one eye, tentacle-like +D:$ limbs, slim waist and broad chest is a member of an advanced +D:$ civilization from another world. They have invaded this world to steal its +D:$ resources. D:彼等の文明は地球より500年進んでいるそうだ。 D:「これから毎日家を焼こうぜ」 D:(『チャージマン研!』アニメ第25話・『雄一少年を救え!』) @@ -21861,8 +21964,8 @@ F:DROP_CORPSE | ONLY_GOLD | DROP_2D2 | DROP_4D2 | F:NO_SLEEP | RES_INER | IM_POIS | S:1_IN_5 | S:SHRIEK -D:$It will make animals into stone-like objects. Be aware, -D:$you become to stone if you touch it with your empty hand! +D:$It can turn an animal into a stone statue. Beware, you will turn to +D:$ stone if you touch it with your bare hand! D:こいつは獲物を石像のようにしちまうんだ。 D:気をつけろ!素手で触ると石になっちまうぞ。 @@ -21969,6 +22072,7 @@ F:ONLY_ITEM | DROP_2D2 | DROP_GOOD | F:OPEN_DOOR | BASH_DOOR S:1_IN_2 S:SHOOT | SHRIEK +D:$He leads the force of Juralians invading this world. D:環境の悪化したジュラル星に変わる新天地を求め、 D:地球侵略を企てるジュラル星人の統率者だ。 D:「諸君、今から命令をすりゅ!地球の子供達をかたっぱしからとらえて君! 」 @@ -21983,6 +22087,10 @@ B:EXPLODE:SHATTER:15d8 F:GOOD | DROP_GOOD | DROP_GREAT | ONLY_ITEM | DROP_90 | FORCE_MAXHP | F:UNIQUE | EMPTY_MIND | WILD_TOWN | CAN_SPEAK | F:OPEN_DOOR | BASH_DOOR | NONLIVING | RES_TELE +D:$He was a West German scientist, but the Jurians turned him into a bomb +D:$ delivery system: "Dr. Volga, you have been killed. With a bomb in your +D:$ head, you are now a human robot!" ("Chargeman Ken!" episode 35, +D:$ "Dynamite in the Brain!") D:ジュラル星人の魔の手により爆弾を頭に仕込まれた西ドイツの科学者だ。 D:「ボルガ博士、あなたは殺されたんです。 D:その頭の中に爆弾を仕掛けられて、今のあなたは人間ロボットなんだ!」 @@ -22001,11 +22109,15 @@ F:FORCE_SLEEP | FORCE_MAXHP | SMART | RES_CHAO | MALE | HUMAN | F:ONLY_ITEM | DROP_1D2 | DROP_2D2 | NO_FEAR | NO_CONF F:OPEN_DOOR | BASH_DOOR | F:IM_FIRE | IM_POIS | HAS_LITE_1 | +D:$Formerly one of Lord Gwyn's Silver Knights, he fought the demons from the +D:$ Bed of Chaos and accompanied the lord to the Kiln of the First Flame. Now +D:$ burned beyond recognition and clad in charred armor, he wanders the world +D:$ for eternity. D:太陽の光の王グウィンの火継ぎの輝きに焼かれ、灰となった神代の騎士だ。 D:以来、彼らは世界を彷徨い歩く存在となった。 N:1092:オーラントの公使 -E:Fat offcial of Allant +E:Fat official of Allant G:p:D I:108:80d12:10:110:20 W:34:4:0:2000:0:0 @@ -22015,6 +22127,10 @@ F:IM_POIS | OPEN_DOOR | BASH_DOOR | MALE | FORCE_MAXHP F:NO_CONF | NO_SLEEP | EVIL | DEMON | HUMAN S:1_IN_2 | S:BO_FIRE | BA_FIRE +D:$After the land of Boletaria, King Allant's kingdom, is engulfed in a +D:$ colorless fog, this creature is one of King Allant's officials who take +D:$ charge. Shaking his fat and ugly body, he rolls out a fireball with an +D:$ eerie laugh and attacks with a crescent ax. D:ボーレタリアが色のない霧に包まれた後、 D:オーラント王の手先として彼の地を統率する異形の者だ。 D:その醜く太った体を揺らしながら、不気味な笑いと共に火の玉を繰り出し、 @@ -22046,6 +22162,13 @@ F:IM_FIRE | IM_POIS | NO_SLEEP | NO_CONF F:MALE | DROP_CORPSE | DROP_SKELETON S:1_IN_3 | S:SHOOT +D:$Firearms were not used in Amber since gunpowder does not work there: +D:$ chemistry is not always the same in Amber and the parallel worlds that +D:$ are shadows of it. Prince Corwin, by accident, had found a substance in +D:$ Avalon that could work as powder and primer in Amber and its closest +D:$ shadows. With that in mind, he devised a plan to take Amber using a small +D:$ force armed with automatic rifles. This gunner, from a parallel world +D:$ where Corwin is worshipped as a god, is one of that force. D:アンバーの王子コーウィンは、並行世界の化学的作用が必ずしも D:共通でない事を知っている。そこで彼はあらゆる影から数多くの鉱物を取り寄せ、 D:各世界で作用する火薬を生産し、現代地球の銃器で利用できる手法を確立した。 @@ -22069,7 +22192,7 @@ F:EVIL | ORC | RES_DARK S:1_IN_3 | S:SHOOT D:$A captain of a regiment of weaker orcs, -D:$Muzgash schemes promotion by flattety to his superiors. +D:$Muzgash schemes promotion by flattering his superiors. D:$"I've told you twice that Gorbag's swine got to the gate first, and none D:$of ours got out. Lagduf and Muzgash ran through, but they were shot." D:ムズガッシュは弱いオークの部隊を指揮する隊長で、上役にへつらい出世を企んでいる。 @@ -22190,8 +22313,8 @@ B:HIT:SUPERHURT:5d4 B:BITE:POISON:9d3 F:EVIL | DROP_1D2 | DROP_SKELETON | DROP_CORPSE | FORCE_SLEEP F:OPEN_DOOR | MALE | WILD_WASTE | WILD_SWAMP | NO_FEAR -D:$It's a biped walking monster, seems subspecies of Skaven, -D:$but it's larger and more terrible than them. +D:$Walking on two legs, this creature looks like a Skaven, of sorts, but it's +D:$ larger and more terrible than a Skaven. D:それはスケイヴンの亜種と思われるが、より大きくおぞましい二足歩行の怪物だ。 N:1103:拡散の尖兵 @@ -22206,6 +22329,9 @@ F:FORCE_SLEEP | FORCE_MAXHP | F:ONLY_ITEM | DROP_4D2 | F:OPEN_DOOR | BASH_DOOR | POWERFUL | NONLIVING | F:EVIL | DEMON | NO_CONF | NO_SLEEP +D:$This giant demon carrying an axe has three yellow eyes and grey skin +D:$ covered with spikes. It is one of the first demons to emerge from the +D:$ colorless fog engulfing Boletaria. D:ボーレタリアの色のない霧から最初に現れたデーモンの尖兵だ。 D:刺々しい灰色の巨体が斧を握りしめている。 @@ -22232,8 +22358,8 @@ B:KICK:HURT:8d4 F:WILD_ALL | BASH_DOOR | RAND_25 | CAN_SWIM F:NO_FEAR | POWERFUL | FRIENDS F:ANIMAL | DROP_SKELETON | DROP_CORPSE | RIDING -D:$This horse is produced in ancient Fergana. -D:$It was able to run 1000 Li a day and shed bloogy sweat. +D:$It is one of the famed horses from Central Asia. They are said to sweat +D:$ blood and to be able to run 300 miles in a day. D:大宛で産出する名馬だ。血の汗を流し、千里を走ることができた。 N:1106:光の堕天使『エミリオ・ミハイロフ』 @@ -22255,6 +22381,8 @@ S:1_IN_4 | S:BLIND | SCARE | S:BO_MANA | HOLD | S:PSY_SPEAR | BA_LITE | BR_LITE +D:$He is a light-manipulating psychics with a neutral appearance. +D:$His back has shining light feathers. D:光を操るサイキッカーで、中性的な容姿と背中に輝く光の羽根を背負っている。 N:1107:さまようもの @@ -22329,71 +22457,73 @@ D:自分を含めた全ての人々に及ぶことを常に望んでいる。 N:1111:ファイア・コボルド E:Fire kobold G:k:R -I:110:11d9:20:35:30 +I:110:12d10:20:35:25 W:12:1:0:42:800:1116 B:HIT:FIRE:4d5 F:DROP_90 F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE F:EVIL | IM_POIS | EAT_POISONOUS F:IM_FIRE | WILD_VOLCANO -D:$It seems only a red kobold, but it learned the use of fire. +D:$It's a red kobold. Wait, are its hands on fire? D:それは単なる赤いコボルドに見えるが、火の使い方を覚えている。 N:1112:アイス・コボルド E:Ice kobold G:k:W -I:110:11d9:20:35:30 +I:110:12d10:20:35:25 W:12:1:0:42:800:1117 B:HIT:COLD:4d5 F:DROP_90 F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE F:EVIL | IM_POIS | EAT_POISONOUS F:IM_COLD | WILD_SWAMP -D:$It seems only a white kobold, but it learned the use of ice. +D:$It's a white kobold. Wait, is that frost on its hands? D:それは単なる白いコボルドに見えるが、冷気の浴びせ方を覚えている。 +# Eric氏の翻訳、これはひどい(称賛の意) N:1113:サンダー・コボルド E:Electric kobold G:k:B -I:110:11d9:20:35:30 +I:110:12d10:20:35:25 W:12:1:0:42:800:1118 B:HIT:ELEC:4d5 F:DROP_90 F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE F:EVIL | IM_POIS | EAT_POISONOUS F:IM_ELEC | WILD_MOUNTAIN -D:$It seems only a blue kobold, but it learned the use of electricity. +D:$Its a blue kobold, but why do its hands glow with St. Elmo's fire? D:それは単なる青いコボルドに見えるが、電撃の浴びせ方を覚えている。 N:1114:アシッド・コボルド E:Acid kobold G:k:s -I:110:11d9:20:35:30 +I:110:12d10:20:35:25 W:12:1:0:42:800:1119 B:HIT:ACID:4d5 F:DROP_90 F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE F:EVIL | IM_POIS | EAT_POISONOUS F:IM_ACID | WILD_WOOD -D:$It seems only a black kobold, but it learned the use of acid. +D:$It's a black kobold, but its hands drip with some sort of caustic substance. D:それは単なる黒いコボルドに見えるが、酸の浴びせ方を覚えている。 N:1115:ポイズン・コボルド E:Poison kobold G:k:G -I:115:12d10:25:45:35 +I:115:13d11:25:45:20 W:14:1:0:55:1100:1120 B:HIT:POISON:4d6 F:DROP_90 F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE F:EVIL | IM_POIS | EAT_POISONOUS -D:$It seems only a green kobold, but it learned the use of poison. +D:$It's a green kobold, but there's something strange about the oily +D:$ secretions on its hands. D:それは単なる緑色のコボルドに見えるが、毒のくらわし方を覚えている。 N:1116:フレイム・コボルド E:Flame kobold G:k:r -I:110:20d10:25:40:35 +I:110:20d10:25:40:20 W:23:1:0:240:0:0 B:HIT:FIRE:8d6 B:HIT:FIRE:8d6 @@ -22403,16 +22533,15 @@ F:DROP_90 F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE F:EVIL | IM_POIS | EAT_POISONOUS | CAN_SWIM F:IM_FIRE | FRIENDS -D:$It is a kobold which emits the fire breath enough to burns down a big tree. -D:$They are sometimes shunned by other kobolds on the ground that -D:$he is a somothering guy. +D:$This red kobold has flames on its hands and wisps of smoke issuing +D:$ from its mouth. D:大木を焼き尽くすほどの強力な炎を吐き出すことができるようになったコボルドだ。 D:コボルド仲間の間でも暑苦しいと煙たがれることがある。 N:1117:ブリザード・コボルド E:Blizzard kobold G:k:w -I:110:20d10:25:40:35 +I:110:20d10:25:40:20 W:23:1:0:240:0:0 B:HIT:COLD:8d6 B:HIT:COLD:8d6 @@ -22422,15 +22551,15 @@ F:DROP_90 F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE F:EVIL | IM_POIS | EAT_POISONOUS | CAN_SWIM F:IM_COLD | FRIENDS -D:$It can freeze a room eternally by its strong breath. -D:$Around him, you may be able to see the diamond dust. +D:$This white kobold has frost covering its hands, and small ice crystals swirl +D:$ in the air around it. D:部屋の全てを永遠に凍りつかせるほどの強力な冷気を吐き出すことができる。 D:それの周りではダイアモンドダストを見ることができるという。 N:1118:ライトニング・コボルド E:Lightning kobold G:k:b -I:110:20d10:25:40:35 +I:110:20d10:25:40:20 W:23:1:0:240:0:0 B:HIT:ELEC:8d6 B:HIT:ELEC:8d6 @@ -22441,15 +22570,14 @@ F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE F:EVIL | IM_POIS | EAT_POISONOUS | CAN_SWIM F:IM_ELEC | FRIENDS F:SELF_LITE_1 -D:$Have you seen the very experiment by Edison? -D:$This kobold can kill an elephant easily by its breath! -D:君は見たことがあるだろうか、あのエジソンの忌まわしい実験を! +D:$Electric sparks fly from the hands and mouth of this blue kobold. +D:君は見たことがあるだろうか、あのヱヅソンの忌まわしい実験を! D:このコボルドはあれと同じことができる! N:1119:カルボラン・コボルド E:Carborane kobold G:k:D -I:110:20d10:25:40:35 +I:110:20d10:25:40:20 W:23:1:0:240:0:0 B:HIT:ACID:8d6 B:HIT:ACID:8d6 @@ -22459,15 +22587,14 @@ F:DROP_90 F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE F:EVIL | IM_POIS | EAT_POISONOUS | CAN_SWIM F:IM_ACID | FRIENDS -D:$O my god! -D:$This kobold can resolve a candle via its breath! +D:$This black kobold has caustic liquid dripping from its hands and mouth. D:ああ、何ということだ! D:このコボルドが吐き出す酸はロウソクをも溶かしてしまう! N:1120:アポトキシン・コボルド E:Apotoxin kobold G:k:g -I:115:21d11:30:45:40 +I:115:21d11:30:45:15 W:24:1:0:333:0:0 B:HIT:POISON:9d6 B:HIT:POISON:9d6 @@ -22477,14 +22604,14 @@ F:DROP_1D2 F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE F:EVIL | IM_POIS | EAT_POISONOUS | CAN_SWIM D:$Be aware! -D:$This kobold's poison can change a tough guy to a frail kid! +D:$ This kobold's poison can change a tough guy to a frail kid! D:気をつけろ! D:やつの毒は大の大人を無力な子供に変えてしまう! N:1121:ジャイアンの腰巾着『スネヲ』 E:Suneo, the Follower of Jaian G:k:u -I:120:35d20:30:50:40 +I:120:35d20:30:50:10 W:25:1:0:410:0:0 B:HIT:HURT:10d6 S:1_IN_8 | S_KIN | SHRIEK @@ -22495,7 +22622,7 @@ F:EVIL | IM_POIS | EAT_POISONOUS F:ESCORT | ESCORTS | RES_SOUN | CAN_FLY F:NO_CONF D:$"Hey Nobita, I regret to say, but the capacity of this dungeon is 3." -D:$However, obviously there are many money mongers around him! +D:$ However, there are clearly more than three money mongers around him! D:「悪いなのび太、このダンジョンは3人用なんだ」 D:しかし、彼に群がる金の亡者は明らかに3人よりも多い! @@ -22510,10 +22637,869 @@ B:HIT:FIRE:8d4 F:MALE | F:FORCE_MAXHP | FRIENDS | DROP_60 | F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE | EAT_POISONOUS | -F:EVIL | ORC | IM_POIS | RES_DARK | IM_FIRE | RES_CHAO | DEMON | WILD_VOLCANO | AURA_FIRE +F:EVIL | ORC | IM_POIS | RES_DARK | IM_FIRE | RES_CHAO +F:DEMON | WILD_VOLCANO | AURA_FIRE S:1_IN_8 S:SHOOT | BO_FIRE | -D:$This orc is succeeding demon blood. He wears brack flame. -D:$This unclean combination is bred in unclean tribe +D:$Cloaked in black flame, this orc must be the descendant of a demon. +D:$ Such creatures are often seen among the foulest orcs. D:このオークの体にはデーモンの血が流れており、そこから来る暗黒の炎をまとっている。 -D:この不浄な結合は、暗き風習を持つ生き物の中でしばしば育まれる。 \ No newline at end of file +D:この不浄な結合は、暗き風習を持つ生き物の中でしばしば育まれる。 + +#Heng 弦ちゃん無性に出したくなった(DSKL) +N:1123:巴流『葦名弦一郎』 +E:Way of Tomoe, Genichiro Ashina +G:p:o +I:120:30d24:20:70:10 +W:29:2:0:1800:0:0 +B:SHOOT:HURT:10d10 +B:SLASH:HURT:8d4 +B:KICK:HURT:4d5 +B:SLASH:ELEC:14d4 +F:UNIQUE | BASH_DOOR | OPEN_DOOR | ESCORT | DROP_90 | +F:NO_SLEEP | NO_CONF | FORCE_MAXHP | DROP_4D2 | DROP_GOOD | +F:MALE | DROP_CORPSE | DROP_SKELETON | CAN_SPEAK | HUMAN +S:1_IN_5 | S_KIN | SHOOT | BO_ELEC +D:$The leader of this family, worried about the death of his homeland +D:$ after the death of Isshin Ashina, +D:$ seeks to obtain it without regard to any monstrous power. +D:$ Therefore, it will also be inevitable that +D:$ he sought them and went to Angband. +D:葦名一心亡き後の故国の存亡を憂うこの一門の将は、 +D:いかなる異形の力をも顧みず手に入れようとする。 +D:ゆえにそれらを求め鉄獄に至ったこともまた必然であるだろう。 + +N:1124:撲殺の天使 +E:Dokuro, the Bludgeoning Angel +G:A:B +I:115:30d30:30:60:10 +W:30:2:0:1300:0:0 +B:SLASH:SUPERHURT:15d2 +B:HIT:SUPERHURT:15d2 +B:CRAWL:SUPERHURT:15d2 +B:STING:SUPERHURT:15d2 +F:UNIQUE | FORCE_MAXHP | GOOD | FEMALE | ANGEL +F:IM_FIRE | RES_LITE | RES_GRAV | CAN_FLY +F:BASH_DOOR | NO_SLEEP | NO_CONF | NO_FEAR +F:DROP_GOOD | DROP_GREAT | ONLY_ITEM | DROP_1D2 +S:1_IN_6 +S:ANIM_DEAD | BA_LITE | CAUSE_3 | CONF | HOLD | BLIND | SHRIEK | BLINK +D:$You are a UNIQUE. +D:$ She will surely fail your animation! +D:あなたはユニークな存在だ。 +D:あなたの死体は蘇ることなく灰になるだろう。 + +N:1125:赤鬼 +E:Red ogre +G:O:R +I:110:20d18:20:65:15 +W:36:1:0:800:0:0 +B:CRUSH:HURT:10d4 +B:CRUSH:HURT:10d4 +F:FORCE_MAXHP | BASH_DOOR | MOVE_BODY | EVIL +F:DROP_CORPSE | DROP_SKELETON +F:IM_FIRE | RES_NETH | NO_FEAR | HURT_COLD | DROP_60 +S:1_IN_9 +S:SCARE | BLIND | CONF | HOLD +S:BA_FIRE | BO_NETH | BO_PLAS +D:$This ogre is the one of the weakest residents in hell. +D:$ It hits sinners and gives punishment to them in the blood pond. +D:地獄に住む鬼達の中では、最も力のない者どもの一人だ。 +D:それは罪人を殴りつけ、血の池で劫罰を与え続ける。 + +N:1126:青鬼 +E:Blue ogre +G:O:b +I:110:20d18:20:65:15 +W:36:1:0:800:0:0 +B:SLASH:HURT:10d4 +B:SLASH:HURT:10d4 +F:FORCE_MAXHP | BASH_DOOR | MOVE_BODY | EVIL +F:DROP_CORPSE | DROP_SKELETON +F:IM_COLD | RES_NETH | NO_FEAR | HURT_FIRE | DROP_60 +S:1_IN_9 +S:SCARE | BLIND | CONF | HOLD +S:BA_COLD | BO_NETH | BO_ICEE +D:$This ogre is the one of the weakest residents in hell. +D:$ It hashes sinners and gives punishment to them on the mountain of needles. +D:地獄に住む鬼達の中では、最も力のない者どもの一人だ。 +D:それは罪人を斬りつけ、針の山で劫罰を与え続ける。 + +N:1127:緑鬼 +E:Green ogre +G:O:G +I:110:20d18:20:65:15 +W:36:1:0:800:0:0 +B:SLASH:HURT:10d4 +B:SLASH:HURT:10d4 +F:FORCE_MAXHP | BASH_DOOR | MOVE_BODY | EVIL +F:DROP_CORPSE | DROP_SKELETON +F:IM_FIRE | IM_COLD | RES_NETH | NO_FEAR | DROP_60 +S:1_IN_9 +S:SCARE | BLIND | CONF | HOLD +S:BO_PLAS | BO_ICEE | BO_NETH +D:$This ogre is the one of the weakest residents in hell. +D:$ It slashes sinners and gives punishment to them with its heated axe. +D:地獄に住む鬼達の中では、最も力のない者どもの一人だ。 +D:それは罪人を斬りつけ、灼けた斧で劫罰を与え続ける。 + +N:1128:首なし鬼 +E:Headless ogre +G:O:U +I:115:21d19:20:70:15 +W:38:1:0:900:0:0 +B:SLASH:HURT:11d4 +B:CRUSH:HURT:11d4 +F:FORCE_MAXHP | BASH_DOOR | MOVE_BODY | EVIL | UNDEAD | INVISIBLE +F:DROP_CORPSE | DROP_SKELETON | HURT_LITE +F:IM_POIS | RES_NETH | NO_FEAR | NO_CONF | NO_SLEEP +S:1_IN_9 +S:SCARE | BLIND | CONF | HOLD +S:BA_FIRE | BA_COLD | BO_NETH +D:$Considering its position as hell guard, this ogre has gone to Asura realm. +D:$ It attacks whoever is innocent or guilty. +D:鬼とあろうものが罪を犯して修羅の道へ堕ちた姿だ。 +D:それは罪人でも天上人でもなりふり構わず攻撃する。 + +# 流石にAC777は攻撃が通らないので控えめに +N:1129:金銀パールプレゼントの鬼 +E:Ogre gifting gold, silver and pearl +G:O:y +I:120:37d21:20:177:15 +W:40:77:0:7777:0:0 +B:CRUSH:HURT:14d10 +B:SLASH:HURT:14d10 +F:FORCE_MAXHP | BASH_DOOR | MOVE_BODY | EVIL +F:ONLY_GOLD | DROP_60 | DROP_90 | DROP_1D2 | DROP_2D2 | DROP_3D2 | DROP_4D2 +F:RES_LITE | RES_NETH | NO_FEAR | NO_CONF | NO_SLEEP | HURT_ROCK +S:1_IN_7 +S:SCARE | BLIND | CONF | HOLD | BR_LITE | BA_LITE | CAUSE_2 +D:$Hmmm, you may have seen this ogre a long time ago. +D:おや、どこかで見たことがあるぞ? + +N:1130:冥界オーガ +E:Styx ogre +G:O:s +I:115:35d20:20:75:15 +W:44:1:0:1000:0:0 +B:CRUSH:SUPERHURT:10d4 +B:SLASH:SUPERHURT:10d4 +F:FORCE_MAXHP | BASH_DOOR | MOVE_BODY | EVIL | INVISIBLE +F:DROP_CORPSE | DROP_SKELETON | HURT_LITE +F:IM_FIRE | RES_DARK | RES_NETH | NO_FEAR | NO_CONF | NO_SLEEP +S:1_IN_8 +S:SCARE | BLIND | CONF | HOLD | BO_NETH | BR_NETH +D:$It is an ogre who guards Styx following its masters. +D:$ It destroys cairn piled up by children having died before their parents. +D:奪衣婆と懸衣翁に仕え、三途の川に佇む鬼だ。 +D:それは時々賽の河原を見回って、積石塚を破壊して回る。 +N:1131:土の鬼 +E:Earth ogre +G:O:u +I:115:40d20:25:80:10 +W:45:2:0:1100:0:0 +B:CRUSH:SUPERHURT:10d4 +B:CRUSH:SUPERHURT:10d4 +F:FORCE_MAXHP | BASH_DOOR | MOVE_BODY | EVIL | INVISIBLE +F:DROP_CORPSE | DROP_SKELETON +F:IM_FIRE | RES_DARK | RES_NETH +F:NO_FEAR | NO_CONF | NO_SLEEP | DROP_90 +S:1_IN_7 +S:SCARE | BLIND | CONF | HOLD +S:BR_WALL | BA_NETH | BR_PLAS | S_DEMON +R:1125:5d3 +D:$This ogre has earthy colored skin. +D:$ Besides punishing sinners, it also leads lower-class ogres. +D:土気色の肌をした鬼だ。 +D:それは罪人を処罰すると同時に、下級の鬼達を統率している。 + +N:1132:水の鬼 +E:Water ogre +G:O:B +I:115:40d20:25:80:10 +W:45:2:0:1100:0:0 +B:SLASH:SUPERHURT:10d4 +B:SLASH:SUPERHURT:10d4 +F:FORCE_MAXHP | BASH_DOOR | MOVE_BODY | EVIL | INVISIBLE +F:DROP_CORPSE | DROP_SKELETON +F:IM_COLD | RES_DARK | RES_NETH +F:NO_FEAR | NO_CONF | NO_SLEEP | DROP_90 | CAN_SWIM +S:1_IN_7 +S:SCARE | BLIND | CONF | HOLD +S:BO_WATE | BA_WATE | BA_NETH | S_DEMON +R:1126:5d3 +D:$This ogre has stagnant river colored skin. +D:$ Besides punishing sinners, it also leads lower-class ogres. +D:淀んだ川の色の肌をした鬼だ。 +D:それは罪人を処罰すると同時に、下級の鬼達を統率している。 + +# 元は羅城門ともいったそうで、英語の発音はそれにならうこととした +# In Japanese, both "Rashoumon" and "Rajoumon" are valid pronunciation +N:1133:羅生門の鬼 +E:Ogre in Rajoumon +G:O:v +I:115:90d10:25:85:10 +W:46:2:0:1400:0:0 +B:SLASH:SUPERHURT:10d5 +B:SLASH:SUPERHURT:10d5 +F:FORCE_MAXHP | BASH_DOOR | MOVE_BODY | EVIL | INVISIBLE +F:DROP_CORPSE | DROP_SKELETON | DROP_90 +F:IM_FIRE | IM_COLD | RES_DARK | RES_NETH | NO_FEAR | NO_CONF +S:1_IN_6 +S:SCARE | BLIND | CONF | HOLD +S:BA_NUKE | BA_NETH | BR_GRAV | S_DEMON +R:1127:5d3 +D:$It lives in Rajoumon. +D:$ Besides punishing sinners, it also leads lower-class ogres. +D:羅生門に巣食う鬼だ。 +D:それは罪人を処罰すると同時に、下級の鬼達を統率している。 + +N:1134:冥界の裁判長『閻魔大王』 +E:Yama, the Judge of the afterlife +G:O:v +I:120:50d60:30:100:10 +W:57:2:0:24000:0:0 +B:SLASH:HURT:10d5 +B:SLASH:HURT:10d5 +B:CRUSH:SUPERHURT:40d1 +F:UNIQUE | FORCE_MAXHP +F:ONLY_ITEM | DROP_GOOD | DROP_1D2 | DROP_GREAT +F:ATTR_MULTI | ESCORT | ESCORTS +F:IM_FIRE | IM_COLD | IM_ELEC | RES_NETH | RES_LITE | RES_DARK +F:NO_FEAR | NO_CONF | NO_SLEEP | CAN_SWIM +S:1_IN_5 +S:BLIND | CONF | HOLD | SCARE +S:BO_NETH | BR_NETH | BA_NETH | CAUSE_4 | S_KIN +D:$Be honest with him. Otherwise, he will send you straight to hell. +D:彼の前では正直でいることだ。さもなくば地獄へ一直線だろう。 + +N:1135:狂気を紡ぎしもの『アブドゥル・アルハザード』 +E:Abdul Alhazred, the Mad Arab +G:p:g +I:120:50d100:20:100:1 +W:60:1:0:35000:0:0 +B:SLASH:LOSE_ALL:5d5 +B:SLASH:LOSE_ALL:5d5 +B:SLASH:LOSE_ALL:6d8 +B:SLASH:LOSE_ALL:6d8 +F:UNIQUE | FORCE_MAXHP | ONLY_ITEM | DROP_GOOD | DROP_GREAT | DROP_2D2 +F:DROP_CORPSE | DROP_SKELETON +F:REGENERATE | ELDRITCH_HORROR | OPEN_DOOR | BASH_DOOR | MOVE_BODY +F:HUMAN | MALE | SELF_DARK_2 | SMART | POWERFUL +F:IM_FIRE | IM_COLD | IM_ELEC | IM_ACID | IM_POIS +F:NO_FEAR | NO_CONF | NO_SLEEP +S:1_IN_2 | BA_NETH | BA_WATE | BA_DARK | BA_NUKE | BA_CHAO +S:S_HI_UNDEAD | S_DEMON | DISPEL +D:$Undoubtedly, it was this man who released the cursed artifacts +D:$ and called upon the great old ones who came from the outside world +D:$ and settled in Llouis. +D:$ It is said that his book, Necronomicon, namely stargate to the abyss, +D:$ still sleeps somewhere in the land. +D:呪われしアーティファクトを世に解き放ち、 +D:外界より来たりてルルイエに住み着いた旧支配者達を呼び寄せたのは、 +D:紛れもなくこの男である。 +D:彼の著した深淵の書『ネクロノミコン』は、今もこの地のどこかに眠ると云う。 + +N:1136:スケイヴン・ウォーリア +E:Skaven warrior +G:r:u +I:110:11d11:20:10:25 +W:12:1:0:48:0:0 +B:BITE:HURT:6d3 +B:BITE:HURT:6d3 +F:MALE | WILD_SWAMP | WILD_WASTE +F:OPEN_DOOR | BASH_DOOR | DROP_CORPSE | DROP_SKELETON +F:ANIMAL | EVIL | DROP_60 | FRIENDS +D:$A warrior of skaven mess around with the power of chaos +D:$ and slaughter their prey from one end. +D:スケイヴン族の戦士は混沌の力をいたずらに振り回し、 +D:目についた獲物を片っ端から屠っていく。 + +N:1137:殺人イタチ +E:Killer weasel +G:r:W +I:110:12d12:20:10:25 +W:15:1:0:55:0:0 +B:BITE:HURT:5d2 +B:BITE:HURT:5d2 +B:CRUSH:HURT:5d2 +F:OPEN_DOOR | BASH_DOOR | DROP_60 +F:ANIMAL | EVIL | DROP_CORPSE | DROP_SKELETON +D:$It has a bushy tail, but does not allow adventurers to stroke it. +D:それはふさふさのしっぽを持っているが、冒険者が撫でることを許さない。 + +N:1138:白き悪魔『ノロイ』 +E:Norowi, the White Devil +G:r:w +I:115:20d16:25:35:10 +W:16:2:0:220:0:0 +B:BITE:HURT:7d3 +B:CRUSH:HURT:7d3 +F:ANIMAL | EVIL | ESCORT | ESCORTS | MALE | UNIQUE | FORCE_MAXHP +F:DROP_GOOD | DROP_60 | DROP_90 | ONLY_ITEM | DROP_CORPSE | DROP_SKELETON +S:1_IN_8 | CAUSE_2 | MISSILE | SCARE | S_KIN +D:$It is the head of weasel who works with wisdom. +D:$ He is obeying not only the weasels, +D:$ but also the rats with a fearful intimidation. +D:$ Your adventure will be terminated soon. +D:悪知恵の働くイタチどもの頭領だ。 +D:イタチだけでなく、その恐怖を引き起こす威圧感でネズミ達をも従わせている。 +D:あなたの冒険は間もなく打ち切られるだろう。 + +# Beginning small letter "lain" is correct. +N:1139:遍在する意識『岩倉玲音』 +E:lain, the Master of Wired +G:p:u +I:135:130d50:60:100:5 +W:80:3:0:45000:0:0 +B:TOUCH:LOSE_ALL:8d7 +B:TOUCH:UN_BONUS:8d7 +B:TOUCH:UN_POWER:8d7 +B:TOUCH:TIME:8d7 +F:QUANTUM | UNIQUE | FEMALE | ATTR_CLEAR | FORCE_MAXHP | RAND_25 +F:ONLY_ITEM | DROP_GOOD | DROP_GREAT | DROP_3D2 +F:DROP_CORPSE | DROP_SKELETON +F:SMART | REFLECTING | INVISIBLE | WEIRD_MIND | REGENERATE +F:POWERFUL | ELDRITCH_HORROR | AURA_ELEC | PASS_WALL +F:MOVE_BODY | TAKE_ITEM | NO_FEAR | NO_CONF | NO_SLEEP | NO_STUN +F:IM_FIRE | IM_COLD | IM_ELEC | IM_ACID | IM_POIS +F:RES_LITE | RES_DARK | RES_CHAO | RES_NEXU | RES_TIME +F:CAN_FLY | SELF_DARK_2 +S:1_IN_2 +S:DISPEL | BA_CHAO | BA_LITE | BA_DARK | BA_MANA | HAND_DOOM | BRAIN_SMASH +S:SLOW | HASTE | HEAL | INVULNER | TPORT | WORLD | PSY_SPEAR +D:$She recognizes you as a bug that appears to be +D:$ a myriad of connected consciousness in the Wired. +D:あなたは、相互に結合している無数の意識達に表れたちっぽけなバグだと +D:認識されている。 + +N:1140:ウェンディゴ +E:Wendigo +G:Y:v +I:120:30d19:30:55:10 +W:30:3:0:500:0:0 +B:BITE:LOSE_WIS:3d4 +B:CLAW:COLD:3d4 +B:TOUCH:TERRIFY:3d4 +B:WAIL:CONFUSE:3d4 +F:ONLY_GOLD | DROP_2D2 | +F:COLD_BLOOD | OPEN_DOOR | BASH_DOOR | CAN_FLY | WEIRD_MIND | ELDRITCH_HORROR +F:EVIL | DEMON | IM_COLD | IM_POIS | RES_NETH | NO_CONF | NO_SLEEP | HURT_FIRE +S:1_IN_6 | +S:MIND_BLAST +D:$It looks like a skinny large humanoid. +D:$ Folklore has it that those who commit cannibalism are brought to cognate +D:それは痩せこけた巨人の姿をしていて、人食いの罪を犯した者を +D:同族にすると言われている。 + +N:1141:年経た風のエレメンタル +E:Elder air elemental +G:E:B +I:125:95d20:12:60:50 +W:43:2:0:5000:0:0 +B:CLAW:HURT:5d10 +B:HIT:CONFUSE:2d10 +B:CLAW:HURT:5d10 +F:FORCE_SLEEP | RAND_25 | +F:COLD_BLOOD | CAN_FLY | NONLIVING | +F:KILL_BODY | KILL_ITEM | BASH_DOOR | +F:EVIL | IM_ACID | IM_FIRE | IM_COLD | IM_ELEC | IM_POIS | +F:NO_CONF | NO_SLEEP | NO_FEAR | POWERFUL | RIDING | RES_TELE +S:1_IN_8 | +S:BA_ELEC | BR_SOUN | S_DRAGON +R:241:4d5 +R:379:1d3 +R:526:1d3 +R:560:1d2 +R:1113:4d5 +R:1118:4d5 +D:$It is a too huge towering tornado of winds that looks vaguely like dragons or other winged beast +D:$ This violent wind enjoying, dragons comes. +D:それはあまりにも高くそびえ立つような風の竜巻で、漠然とドラゴンか他の翼ある魔獣に見える。 +D:風の暴威を楽しんでドラゴンがやってくる。 + +N:1142:年経たマグマのエレメンタル +E:Elder magma elemental +G:E:o +I:115:100d20:10:70:90 +W:45:2:0:4500:0:0 +B:HIT:FIRE:5d7 +B:BITE:HURT:6d6 +B:HIT:FIRE:5d7 +F:FORCE_SLEEP | +F:AURA_FIRE | WILD_VOLCANO | +F:KILL_ITEM | KILL_BODY | PASS_WALL | +F:EVIL | IM_FIRE | IM_ELEC | NONLIVING | +F:IM_POIS | +F:NO_CONF | NO_SLEEP | NO_FEAR | POWERFUL | RES_TELE +S:1_IN_7 | +S:BO_PLAS | BA_FIRE | BR_POIS +R:584:1d3 +R:884:4d10 +R:899:4d5 +R:1098:1d2 +R:1111:4d5 +R:1131:1d3 +D:$It is a too huge towering glowing form of molten hate.that looks vaguely like spiders or other arthropod that live in lava cave. +D:$ Molten mineral give off toxic gas. +D:それはあまりにも高くそびえ立つような光を発する憎悪が溶けてできたような塊で、漠然と溶岩洞窟に生息する蜘蛛か他の虫のように見える。 +D:溶けた鉱物が有毒ガスを噴出している。 + +N:1143:年経た火のエレメンタル +E:Elder fire elemental +G:E:r +I:120:135d20:12:70:50 +W:44:2:0:6000:0:0 +B:HIT:FIRE:4d10 +B:HIT:FIRE:4d10 +B:SLASH:FIRE:5d12 +F:FORCE_SLEEP | RAND_25 | SELF_LITE_2 | +F:CAN_FLY | WILD_VOLCANO | +F:KILL_ITEM | KILL_BODY | BASH_DOOR | AURA_FIRE | +F:EVIL | IM_FIRE | IM_POIS | NONLIVING | HURT_COLD | +F:NO_CONF | NO_SLEEP | NO_FEAR | POWERFUL | RES_TELE +S:1_IN_5 | +S:BA_FIRE | S_DEMON | BR_FIRE +R:264:4d5 +R:1111:4d5 +R:1116:4d5 +R:510:1d3 +R:589:1d2 +D:$It is a too huge towering inferno of flames that looks vaguely like Balrog or other demons. +D:$ This flame of destruction respecting, demons comes. +D:それはあまりにも高くそびえ立つような火炎地獄で、漠然とバルログか他のデーモンのように見える。 +D:その破壊の炎を慕ってデーモンがやってくる。 + +N:1144:年経た氷のエレメンタル +E:Elder ice elemental +G:E:w +I:120:125d20:10:70:90 +W:43:2:0:3500:0:0 +B:BITE:COLD:3d10 +B:CLAW:HURT:5d10 +B:BITE:COLD:3d10 +F:FORCE_SLEEP | POWERFUL +F:COLD_BLOOD | AURA_COLD | +F:KILL_ITEM | KILL_BODY | BASH_DOOR | +F:EVIL | IM_COLD | IM_ELEC | CAN_SWIM | HURT_FIRE | +F:IM_POIS | NONLIVING | +F:NO_CONF | NO_SLEEP | NO_FEAR | RES_TELE +S:1_IN_5 | +S:BO_ICEE | BA_COLD | BR_COLD +R:343:1d2 +R:379:4d5 +R:549:1d2 +R:570:1d3 +R:1112:4d5 +R:1117:4d5 +D:$It is a too huge towering glacier of ice that looks vaguely like Animals in cold regions. +D:それはあまりにも高くそびえ立つような氷河で、漠然と寒冷地の動物のように見える。 + +N:1145:年経た汚物エレメンタル +E:Elder ooze elemental +G:E:U +I:120:118d20:10:100:90 +W:45:3:0:3600:0:0 +B:TOUCH:ACID:1d12 +B:TOUCH:ACID:1d12 +B:TOUCH:ACID:1d12 +B:BITE:POISON:1d12 +F:FORCE_SLEEP | POWERFUL +F:COLD_BLOOD | WILD_SHORE | WILD_SWAMP | +F:KILL_ITEM | KILL_BODY | BASH_DOOR | +F:EVIL | IM_ACID | IM_FIRE | CAN_SWIM | NONLIVING | +F:IM_COLD | IM_ELEC | IM_POIS | +F:NO_CONF | NO_SLEEP | NO_FEAR | RES_TELE +S:1_IN_5 | +S:BR_ACID | BA_ACID +R:509:4d6 +R:545:1d3 +R:592:1d2 +R:1115:4d6 +R:1131:1d3 +R:1132:1d3 +D:$It is a too huge towering mass of filth that looks vaguely like Hydras, crocodilians or frogs. +D:それはあまりにも高くそびえ立つような汚物の塊で、漠然とヒドラやワニやカエルのように見える。 + +# 紫電は航続距離が短いので鉄獄に入れませんでした +# Storing cherry-blossom +N:1146:ハヤブサ +E:Betty G4M 'Falcon' +G:B:g +I:115:40d25:100:50:50 +W:45:2:0:2000:0:0 +B:CRUSH:HURT:5d10 +B:CRUSH:HURT:5d10 +F:FORCE_MAXHP | COLD_BLOOD | CAN_FLY | GOOD | UNDEAD +F:NO_CONF | NO_SLEEP | NO_FEAR +S:1_IN_5 | ROCKET +R:1147:5d5 +D:$It is a ghost of those who made human life a part, +D:$ ran on the battlefield with iron wings, +D:$ and continued to shed a lot of blood on both sides. +D:それは人の命を部品にし、鉄の翼を纏って戦場を駆け、敵味方共に幾多の血を流し続けた者達の亡霊だ。 + +N:1147:ハヤブサ +E:Betty G4M 'Falcon' +G:B:g +I:120:25d25:100:50:50 +W:45:2:0:2000:0:0 +B:CRUSH:HURT:5d10 +B:EXPLODE:SUPERHURT:10d10 +F:COLD_BLOOD | CAN_FLY | GOOD | UNDEAD +F:NO_CONF | NO_SLEEP | NO_FEAR | DROP_60 | ONLY_ITEM +S:1_IN_6 | BO_MANA | MISSILE | BLINK +D:$It is a ghost of those who made human life a part, +D:$ ran on the battlefield with iron wings, +D:$ and continued to shed a lot of blood on both sides. +D:それは人の命を部品にし、鉄の翼を纏って戦場を駆け、敵味方共に幾多の血を流し続けた者達の亡霊だ。 + +N:1148:放火魔『雄一』 +E:Yu'uichi, the Arsonist +G:t:U +I:109:7d5:5:15:100 +W:3:1:0:30:0:0 +B:WAIL:HURT:2d5 +F:UNIQUE | FORCE_MAXHP | HUMAN | MALE | EVIL | DROP_CORPSE | DROP_SKELETON +F:DROP_90 | ONLY_ITEM | DROP_GOOD +S:1_IN_12 | BA_FIRE +D:$He puts a laughing home into misery every day to eradicate his happy family. +D:$ He has no intention of compensating for what he does. +D:彼は幸せな家族を根絶やしにするため、日々笑い声の聞こえてくる家庭を不幸の底に沈めている。 +D:彼は自分の行いを償うつもりはない。 + +N:1149:全開装甲『カバード・コア』 +E:Opened core, the uncovered fortress +G:#:G +I:110:9d5:35:1:10 +W:4:1:0:40:0:0 +B:SHOOT:HURT:2d6 +B:CRUSH:HURT:4d4 +F:UNIQUE | FORCE_MAXHP | EVIL | NONLIVING +F:DROP_90 | DROP_4D2 | ONLY_GOLD +S:1_IN_8 | MISSILE | ROCKET +D:$This aircraft protects the home of the Bacterian army +D:$ with the power reactor exposed. +D:$ Recently this unit was fired. +D:この機体は動力炉を剥き出しにしたままバクテリアン軍の本拠地を守っていた。 +D:最近暇を出されたようだ。 + +N:1150:蜘蛛地獄『ゴライアス』 +E:Goliath, the king of ant-lion +G:S:r +I:110:20d10:30:30:20 +W:10:1:0:50:0:0 +B:BITE:HURT:2d10 +B:STING:HURT:2d10 +F:UNIQUE | FORCE_MAXHP | EVIL | DROP_CORPSE | DROP_SKELETON +F:DROP_60 | DROP_90 | ONLY_ITEM | DROP_GOOD | NO_SLEEP | ANIMAL +S:1_IN_8 | S_KIN | BLIND +D:$It waits to prey on all living things. +D:それはあらゆる生き物を餌食にしようと待ち構えている。 + +N:1151:小さな泡 +E:Small aqua illusion +G:j:B +I:110:12d12:10:30:10 +W:15:1:0:50:0:0 +B:CRUSH:HURT:6d6 +B:CRUSH:HURT:6d6 +F:RAND_25 | RAND_50 | FRIENDS | WILD_SWAMP | NONLIVING | EMPTY_MIND +F:NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR | RES_TELE | RES_WATE +D:$It is a small bubble that makes an weird movement. +D:$ It collapses suddenly. +D:不気味な動きをする小さな泡だ。ぷちぷちと潰れる。 + +# 倒すと小さな泡×4に分裂する +N:1152:やや大きな泡 +E:Middle aqua illusion +G:j:B +I:110:12d12:10:30:10 +W:18:1:0:100:0:0 +B:CRUSH:HURT:7d7 +B:CRUSH:HURT:7d7 +F:RAND_25 | RAND_50 | WILD_SWAMP | NONLIVING | EMPTY_MIND +F:NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR | RES_TELE | RES_WATE +D:$It is a middle bubble that makes an weird movement. +D:$ When it is crushed, it becomes a small bubble. +D:不気味な動きをする、やや大きな泡だ。潰すと小さな泡になる。 + +# 倒すとやや大きな泡×4に分裂する +N:1153:大きな泡 +E:Large aqua illusion +G:j:B +I:110:18d18:10:30:10 +W:21:1:0:250:0:0 +B:CRUSH:HURT:8d8 +B:CRUSH:HURT:8d8 +F:RAND_25 | RAND_50 | WILD_SWAMP | NONLIVING | EMPTY_MIND +F:NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR | RES_TELE | RES_WATE +D:$It is a large bubble that makes an weird movement. +D:$ When it is crushed, it becomes a middle bubble. +D:不気味な動きをする大きな泡だ。潰しても中々なくならない。 + +# 倒すと大きな泡×4に分裂する +N:1154:特大の泡 +E:Extra large aqua illusion +G:j:B +I:110:18d18:10:30:10 +W:24:1:0:500:0:0 +B:CRUSH:HURT:9d9 +B:CRUSH:HURT:9d9 +F:RAND_25 | RAND_50 | WILD_SWAMP | NONLIVING | EMPTY_MIND +F:NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR | RES_TELE | RES_WATE +D:$It is a extra large bubble that makes an weird movement. +D:$ You must decide whether running away or squashing them all! +D:不気味な動きをする巨大な泡だ。逃げるか潰すか二つに一つだ! + +N:1155:二週目の小さな泡 +E:Small aqua illusion in 2nd lap +G:j:b +I:120:20d20:10:50:10 +W:25:1:0:120:0:0 +B:CRUSH:HURT:6d6 +B:CRUSH:HURT:6d6 +B:CRUSH:HURT:6d6 +F:RAND_25 | RAND_50 | FRIENDS | WILD_SWAMP | NONLIVING | EMPTY_MIND +F:NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR | RES_TELE | RES_WATE | POWERFUL +S:1_IN_4 | MISSILE +D:$Holy shit! It will shoot you back at this bubble! +D:なんてこった、こいつ泡のくせに撃ち返してくるぞ! + +# 倒すと小さな泡×4に分裂する +# 実際の2周目では一番小さいのしか撃ち返してこないが変愚向けに調整 +N:1156:二周目のやや大きな泡 +E:Middle aqua illusion in 2nd lap +G:j:b +I:120:20d20:10:50:10 +W:28:1:0:240:0:0 +B:CRUSH:HURT:7d7 +B:CRUSH:HURT:7d7 +B:CRUSH:HURT:7d7 +F:RAND_25 | RAND_50 | WILD_SWAMP | NONLIVING | EMPTY_MIND +F:NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR | RES_TELE | RES_WATE | POWERFUL +S:1_IN_4 | MISSILE +D:$It is a middle bubble that makes an weird movement and shoots you back. +D:$ When it is crushed, it becomes a small bubble. +D:不気味な動きをして撃ち返してくる、やや大きな泡だ。潰すと小さな泡になる。 + +# 倒すとやや大きな泡×4に分裂する +N:1157:二周目の大きな泡 +E:Large aqua illusion in 2nd lap +G:j:b +I:120:25d25:10:50:10 +W:31:1:0:600:0:0 +B:CRUSH:HURT:8d8 +B:CRUSH:HURT:8d8 +B:CRUSH:HURT:8d8 +F:RAND_25 | RAND_50 | WILD_SWAMP | NONLIVING | EMPTY_MIND +F:NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR | RES_TELE | RES_WATE | POWERFUL +S:1_IN_4 | MISSILE +D:$It is a large bubble that makes an weird movement and shoots you back. +D:$ When it is crushed, it becomes a middle bubble. +D:不気味な動きをして撃ち返してくる大きな泡だ。潰しても中々なくならない。 + +# 倒すと大きな泡×4に分裂する +N:1158:二週目の特大の泡 +E:Extra large aqua illusion in 2nd lap +G:j:b +I:120:25d25:10:50:10 +W:34:1:0:1200:0:0 +B:CRUSH:HURT:9d9 +B:CRUSH:HURT:9d9 +B:CRUSH:HURT:9d9 +F:RAND_25 | RAND_50 | WILD_SWAMP | NONLIVING | EMPTY_MIND +F:NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR | RES_TELE | RES_WATE | POWERFUL +S:1_IN_4 | MISSILE +D:$It is a extra large bubble that makes an weird movement and shoots you back! +D:$ You must decide whether running away or squashing them all! +D:不気味な動きをして撃ち返してくる巨大な泡だ。逃げるか潰すか二つに一つだ! + +# 実質召喚専用にしたいのでRarはかなり高め +N:1159:プチモアイ +E:Small Moai +G:g:s +I:120:15d15:10:50:10 +W:34:50:0:250:0:0 +B:CRUSH:HURT:8d8 +F:IM_ELEC | HURT_ROCK | RES_GRAV | DROP_60 | DROP_1D2 | ONLY_GOLD +F:NONLIVING | NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR +S:1_IN_2 | BR_ELEC | BR_PLAS +D:$ Do NOT get behind this Moai! +D:こいつの背後には近寄るな! + +N:1160:モアイ +E:Moai +G:g:U +I:105:30d25:10:85:50 +W:40:1:0:700:0:0 +F:IM_ELEC | HURT_ROCK | RES_TELE | RES_GRAV | FRIENDS | FORCE_SLEEP | DROP_90 +F:NONLIVING | NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR +F:NEVER_MOVE | NEVER_BLOW +S:1_IN_2 | BR_ELEC | BR_PLAS +D:$It is Moai who landed in Angband. You can not destroy this ion ring. +D:鉄獄に降り立ったモアイだ。こいつの吐き出すイオンリングは破壊できない。 + +# 死に際に7/8の確率で自分自身を召喚する +N:1161:トーテムモアイ +E:Totem Moai +G:g:U +I:110:20d20:10:90:30 +W:40:1:0:750:0:0 +F:IM_ELEC | HURT_ROCK | RES_TELE | RES_GRAV | DROP_90 +F:NONLIVING | NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR +F:NEVER_MOVE | NEVER_BLOW +S:1_IN_2 | BR_ELEC | BR_PLAS +D:$It is a Moai piled up like a totem pole. There is no end in destroying it. +D:トーテムポール状に積み上がったモアイだ。倒してもきりがない。 + +# プチモアイのみ召喚 +N:1162:モアイの総大将『ヴァイフ』 +E:Vaif, the general of Moais +G:g:D +I:120:60d50:25:100:20 +W:49:1:0:11000:0:0 +B:CRUSH:SUPERHURT:12d15 +F:UNIQUE | FORCE_MAXHP | NEVER_MOVE +F:IM_ELEC | RES_GRAV | RES_TELE | ONLY_ITEM | DROP_2D2 | DROP_GOOD | DROP_GREAT +F:NONLIVING | NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR +S:1_IN_2 | S_KIN | HOLD | CONF | BLIND | HEAL +D:$It is a mighty thug from the Bacterian army. It summons many small Moais. +D:バクテリアン軍が放った強大な刺客だ。それは大量のプチモアイを生み出す。 + +# テストプレイした結果、戦士なら毒針なしでもギリギリ刺さった +# メイジ系は塔2F&クローン地獄に毒針必須かも +N:1163:クリスタル・キューブ +E:Crystal cube +G:g:B +I:140:2d2:10:200:30 +W:50:2:0:1500:0:0 +B:CRUSH:SHATTER:10d6 +B:CRUSH:SHATTER:10d8 +B:CRUSH:SHATTER:10d10 +B:CRUSH:SHATTER:10d12 +F:RES_ALL | FRIENDS | NONLIVING | RAND_25 | RAND_50 +F:NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR +D:$If you can dodge them, you are an expert! +D:避けきれたら君も上級者だ! + +N:1164:鬼滅隊の『先輩』 +E:Senior, the nameless member of Demon Slayer Corps +G:p:g +I:110:25d10:10:35:100 +W:14:1:0:300:0:0 +B:SLASH:HURT:2d13 +B:HIT:HURT:2d15 +B:TOUCH:TERRIFY +F:UNIQUE | FORCE_MAXHP | HUMAN | MALE | EVIL +F:DROP_60 | DROP_90 | ONLY_ITEM | DROP_GOOD +S:1_IN_8 | S_KIN +D:$This stupid man can not determine his enemy's ability. +D:この愚かな男は敵の力量を見極めることができない。 + +N:1165:鬼滅隊の隊士 +E:Members of Demon Slayer Corps +G:p:U +I:110:15d10:10:30:100 +W:14:50:0:200:0:0 +F:NAZGUL | FORCE_MAXHP | HUMAN | MALE | UNDEAD +F:DROP_60 +B:SHOOT:HURT:8d7 +B:SLASH:HURT:2d10 +B:HIT:HURT:2d12 +S:1_IN_6 +D:$These corps are the ghosts killed by Rui. +D:累に殺された者たちの亡霊だ。 + +N:1166:チーターマン『アリエス』 +E:Aries, the youngest cheetahmen +G:h:y +I:110:15d15:20:30:25 +W:12:1:0:200:0:0 +B:CLAW:HURT:4d6 +B:BITE:HURT:4d6 +F:UNIQUE | FORCE_MAXHP | MALE | GOOD | ANIMAL +F:DROP_60 | DROP_90 | DROP_GOOD | RES_SOUN | NO_STUN +D:$He is the youngest of three brothers and swings a club. +D:三兄弟の末っ子で、棍棒を振り回している。 + +N:1167:チーターマン『ヘラクレス』 +G:h:y +E:Hercules, the second eldest cheetahmen +I:110:15d16:20:35:25 +W:13:1:0:250:0:0 +B:PUNCH:HURT:4d6 +B:KICK:HURT:4d6 +F:UNIQUE | FORCE_MAXHP | MALE | GOOD | ANIMAL +F:DROP_60 | DROP_90 | DROP_GOOD | RES_SOUN | NO_STUN +D:$He is the second son of three brothers and is good at karate. +D:三兄弟の次男で、空手が得意だ。 + +N:1168:チーターマン『アポロ』 +G:h:y +E:Apollo, the eldest cheetahmen +I:110:15d18:25:40:30 +W:14:1:0:300:0:0 +B:SHOOT:HURT:8d8 +B:STING:HURT:5d6 +B:STING:HURT:5d6 +F:UNIQUE | FORCE_MAXHP | MALE | GOOD | ANIMAL +F:DROP_90 | DROP_1D2 | DROP_GOOD | RES_SOUN | NO_STUN +D:$He is the eldest son of the three brothers, +D:$ and be aware the shot by his cross bow! +D:三兄弟の長男で、クロスボウからの一撃に要注意だ! + +N:1169:怪物の太母『エキドナ』 +E:Echidna, Great mother of monsters +G:n:u +I:130:60d100:40:125:30 +W:75:3:0:23500:0:0 +B:CRUSH:SUPERHURT:12d15 +B:CRUSH:SUPERHURT:12d15 +B:CRUSH:SUPERHURT:12d15 +B:BITE:POISON:12d15 +F:FORCE_SLEEP | FORCE_MAXHP | DROP_SKELETON | DROP_CORPSE +F:ONLY_ITEM | DROP_4D2 | DROP_3D2 | DROP_GREAT | MOVE_BODY | +F:SMART | TAKE_ITEM | OPEN_DOOR | BASH_DOOR | POWERFUL +F:EVIL | FEMALE | UNIQUE | RES_LITE | RES_TIME | RES_DARK | RES_NETH +F:IM_COLD | IM_POIS | IM_ACID | IM_ELEC | IM_FIRE | RES_TELE +S:1_IN_5 | +S:S_MONSTERS | SCARE | BA_DARK | BA_NETH | BR_POIS +D:$This sacred and untouchable female monster is half a nymph and half a snake, becoming the mother of many monsters. +D:この半分がニンフで半分は蛇の神聖にして手の付けられない女怪は、数々のモンスターの母となった。 + +N:1170:ハリモグラ +E:Echidna +G:r:u +I:110:1d2:30:1:10 +W:1:3:0:6:0:0 +B:CRUSH:HURT:3d1 +F:RAND_50 | WILD_GRASS | WILD_WOOD | +F:ANIMAL | DROP_SKELETON | DROP_CORPSE +D:$It is relative of platypus and was thought to be a composite of reptiles and mammals, +D:$ so it was named after the Greek monster. +D:それはカモノハシの類縁で、爬虫類と哺乳類の合成と考えられたためギリシアの怪物にちなんで英名を名付けられた。 + +N:1171:虚界の魔獣『ジェノサイバー』 +E:Genocyber the Vajura Beast +G:U:w +I:132:70d100:40:160:10 +W:72:3:0:27500:0:0 +B:PUNCH:HURT:12d12 +B:PUNCH:HURT:12d12 +B:CRUSH:SHATTER:16d11 +B:CRUSH:SHATTER:16d11 +F:UNIQUE | FEMALE | RES_TELE | CAN_FLY +F:DROP_SKELETON | DROP_CORPSE +F:FORCE_SLEEP | FORCE_MAXHP | KILL_WALL | DEMON | HUMAN +F:ONLY_ITEM | DROP_4D2 | DROP_3D2 | DROP_GREAT | MOVE_BODY +F:REGENERATE | NO_CONF | NO_STUN | NO_SLEEP | NO_FEAR | POWERFUL +F:IM_COLD | IM_POIS | IM_ACID | IM_ELEC | IM_FIRE +F:OPEN_DOOR | BASH_DOOR | RES_WALL +S:1_IN_8 | +S:TELE_TO | BO_MANA | BR_MANA | BR_WALL | BR_PLAS | BR_DISI | HEAL | HASTE +D:$It is the fusion of twin sisters born at the end of the vaunted study of Vajura energy. +D:$Its outrageous power will destroy a star and eventually become a new myth. +D:ヴァジュラエネルギーのおぞましい研究の果てに産みだされた双子の姉妹の融合体だ。 +D:その無法図な力は一個の星を滅ぼし、やがて新たな神話の存在となるに足るものだろう。 + diff --git a/lib/edit/t0000001.txt b/lib/edit/t0000001.txt index 85ce87600..9a29367f6 100644 --- a/lib/edit/t0000001.txt +++ b/lib/edit/t0000001.txt @@ -514,7 +514,7 @@ B:$13:A:1:Wanted unique list:0:0:b:39:0 B:13:A:1:賞金首リスト:0:0:b:39:0 B:$13:A:2:Special target:0:0:s:37:0 B:13:A:2:スペシャル・ターゲット:0:0:s:37:0 -B:$13:A:3:Recieve prize:0:0:c:40:0 +B:$13:A:3:Receive prize:0:0:c:40:0 B:13:A:3:報酬を受け取る:0:0:c:40:0 diff --git a/lib/edit/t_lite.txt b/lib/edit/t_lite.txt index 24fbe2ad6..6ded37646 100644 --- a/lib/edit/t_lite.txt +++ b/lib/edit/t_lite.txt @@ -662,7 +662,7 @@ B:$15:A:1:Wanted unique list:0:0:b:39:0 B:15:A:1:賞金首リスト:0:0:b:39:0 B:$15:A:2:Special target:0:0:s:37:0 B:15:A:2:スペシャル・ターゲット:0:0:s:37:0 -B:$15:A:3:Recieve prize:0:0:c:40:0 +B:$15:A:3:Receive prize:0:0:c:40:0 B:15:A:3:換金する:0:0:c:40:0 ############### Town Layout ############### diff --git a/lib/edit/v_info.txt b/lib/edit/v_info.txt index 053504d26..fe7be5bda 100644 --- a/lib/edit/v_info.txt +++ b/lib/edit/v_info.txt @@ -3850,3 +3850,37 @@ D:%.###.#.#.#...%% D:%............%% D:%%%%%%%%%%%%%% +N:171:Fixed room [A] +X:17:8:14:19 +D: %%%%%%% +D: %%.....%% +D: %%.......%% +D: %%...###...%% +D: %%...#####...%% +D: %%...#######...%% +D:%%...............%% +D:%.................% +D:%.................% +D:%...###########...% +D:%...###########...% +D:%...###########...% +D:%...###########...% +D:%%%%%%%%%%%%%%%%%%% + +N:172:Fixed room [B] +X:17:8:14:19 +D:%%%%%%%%%%%%%% +D:%............%% +D:%............ %% +D:%...########...%% +D:%...########... % +D:%...########...%% +D:%............. % +D:%...########...%% +D:%...##########.. %% +D:%...##########....% +D:%...##########....% +D:%.................% +D:%................%% +D:%%%%%%%%%%%%%%%%%% + diff --git a/lib/file/Makefile.am b/lib/file/Makefile.am index 142b9de0b..e259adad4 100644 --- a/lib/file/Makefile.am +++ b/lib/file/Makefile.am @@ -12,7 +12,7 @@ angband_files = \ chainswd.txt dead.txt \ death.txt elvish.txt error.txt mondeath.txt \ monfear.txt monfrien.txt monspeak.txt news.txt \ - rumors.txt seppuku.txt silly.txt timefun.txt \ + rumors.txt seppuku.txt silly.txt sname.txt timefun.txt \ timenorm.txt w_cursed.txt w_high.txt w_low.txt\ w_med.txt diff --git a/lib/file/a_med.txt b/lib/file/a_med.txt index 554b1796f..a21d6ab60 100644 --- a/lib/file/a_med.txt +++ b/lib/file/a_med.txt @@ -74,7 +74,7 @@ of the Ruler of Wallachia N:15:BIAS_LAW N:13:BIAS_PRIESTLY N: 8:BIAS_WIS -'Enlightenment from Heven' +'Enlightenment from Heaven' 'Holy Chant' 'Holy Prayer' 'Righteousness' diff --git a/lib/file/death.txt b/lib/file/death.txt index 09b7c5316..87b6cf626 100644 --- a/lib/file/death.txt +++ b/lib/file/death.txt @@ -229,7 +229,7 @@ I don't care. I have a Ring of Regeneration. I have this dungeon at home, I know where everything is! This HAS to be an illusion. I attempt to disbelieve it. I thought you could be trusted. -Never try to sneak in a plate mail. +Never try to sneak in plate mail. I'll never surrender. I'll use the Cheat Death option... I'm invincible! diff --git a/lib/file/mondeath.txt b/lib/file/mondeath.txt index 3366c1a74..1b6e1ffbf 100644 --- a/lib/file/mondeath.txt +++ b/lib/file/mondeath.txt @@ -50,7 +50,7 @@ N:1018:Raou points at himself and shouts, 'I finished my life with no regrets!' N:1063:lousy, the King of louses -says, 'Ah, Hengband is too difficult!' +says, 'Ah, Bakabakaband is too difficult!' N:*:Default shouts, 'AAAARRRGGGHHH!!!' diff --git a/lib/file/mondeath_j.txt b/lib/file/mondeath_j.txt index cf62da133..786957cd8 100644 --- a/lib/file/mondeath_j.txt +++ b/lib/file/mondeath_j.txt @@ -70,5 +70,8 @@ N:1096:濃尾無双『岩本虎眼』 N:1106:光の堕天使『エミリオ・ミハイロフ』 「何で僕がーー!」 +N:1123:巴流『葦名弦一郎』 +「あし…な……」 + N:*:Default 「グアァァァ!」 diff --git a/lib/file/monfear_j.txt b/lib/file/monfear_j.txt index 9430cf798..12c400933 100644 --- a/lib/file/monfear_j.txt +++ b/lib/file/monfear_j.txt @@ -557,6 +557,9 @@ N:1081:チャージマン『研』 「僕は世話をかけないよ!」 「ちぇっ、…くっそぉ~」 +N:1090:『ボルガ博士』 +「何をする!?」 + N:1096:濃尾無双『岩本虎眼』 「い、いくぅ・・・」 「た、種ぇ・・・」 diff --git a/lib/file/monfrien.txt b/lib/file/monfrien.txt index de0324eee..36b1ca48c 100644 --- a/lib/file/monfrien.txt +++ b/lib/file/monfrien.txt @@ -31,7 +31,7 @@ mumbles something about mushrooms. N:19:Lion Heart says, 'We must stand up with firm resolve to strive for the eradication of terrorism, together with other nations of the world' -says, 'Japan supports the U.S. position that it will not bow to terrorism. Ithink it is only natural for President Bush to hunt down the culprits and take firm steps against this serious crime.' +says, 'Japan supports the U.S. position that it will not bow to terrorism. I think it is only natural for President Bush to hunt down the culprits and take firm steps against this serious crime.' says, 'The terrorist acts are extremely heinous and outrageous and cannot be forgiven.' says, 'It is a challenge not only to the U.S. but also to democracy, and I am outraged.' says, 'Japan-U.S. alliance is becoming bigger and bigger.' @@ -41,8 +41,8 @@ says, 'The safe society is crumbling and this is a significant incident.' ### says, 'I am not a entertainer but a politician.' sings, 'As K*izumi as the day is long...' says, 'I don't think there's any going back to what politics was in this country even three weeks ago.' -says, 'What will the prime minister do if the anti-reform forces within the Liveral Democratic Party regain power?' -says, 'People are driving the LDP members, and the LDP members are driveing the party. That is a total reversal of the past.' +says, 'What will the prime minister do if the anti-reform forces within the Liberal Democratic Party regain power?' +says, 'People are driving the LDP members, and the LDP members are driving the party. That is a total reversal of the past.' says, 'No pain, no gain.' says, 'Here's a present for you. A compact disc of X-JAPAN!' sings, 'Forever...' diff --git a/lib/file/monfrien_j.txt b/lib/file/monfrien_j.txt index 79fbba97b..b6e61c442 100644 --- a/lib/file/monfrien_j.txt +++ b/lib/file/monfrien_j.txt @@ -119,6 +119,9 @@ N:1004:Pip, the Braver from Another World 「火の指2!」 「でくのぼうめ!」 +N:1090:『ボルガ博士』 +「お菓子好きかい?」 + #N:63:Smeagol #N:135:Mughash the Kobold Lord #N:137:Wormtongue, Agent of Saruman diff --git a/lib/file/monspeak.txt b/lib/file/monspeak.txt index ddd1dc020..f369ac56e 100644 --- a/lib/file/monspeak.txt +++ b/lib/file/monspeak.txt @@ -52,8 +52,8 @@ says, 'The safe society is crumbling and this is a significant incident.' ### says, 'I am not a entertainer but a politician.' sings, 'As K*izumi as the day is long...' says, 'I don't think there's any going back to what politics was in this country even three weeks ago.' -says, 'What will the prime minister do if the anti-reform forces within the Liveral Democratic Party regain power?' -says, 'People are driving the LDP members, and the LDP members are driveing the party. That is a total reversal of the past.' +says, 'What will the prime minister do if the anti-reform forces within the Liberal Democratic Party regain power?' +says, 'People are driving the LDP members, and the LDP members are driving the party. That is a total reversal of the past.' says, 'No pain, no gain.' says, 'Here's a present for you. A compact disc of X-JAPAN!' sings, 'Forever...' @@ -324,7 +324,7 @@ says, 'You aren't a caitiff that throws a cloak?!' #N:596:Mother Hydra N:598:Mandor, Master of the Logrus -enjoys espresso coffee between battle. +enjoys espresso coffee between battles. says, 'My slaves fight with you.' says, 'Excuse me, I have no time to continue a small fight.' says, 'It is a great pleasure to fight with such a worthy opponent as you.' @@ -479,7 +479,7 @@ says, 'You'll become a good mounting' #N:805:Omarax the Eye Tyrant N:807:Gerard, Strongman of Amber -rush toward you wordlessly. +rushes toward you wordlessly. #N:809:Atlach-Nacha, the Spider God @@ -601,7 +601,7 @@ says, 'Maybe I won't kill you... NOT!' yawns at your pathetic efforts to kill it. says, 'Another day, another bastard to slaughter...' says, 'I can't be bothered... minions, slaughter this fool!' -says, 'Such a doomed, pathetic gesture as yours verges on the heroic!' +says, 'Such a doomed, pathetic gesture as yours verges on the heroic!' says, 'Mere mortals such as you should not meddle the affair of the Powers!' N:873:Combat-Echizen @@ -748,7 +748,7 @@ says, 'Thou shalt repent of thy cunning.' says, 'Verily, thou shalt be one dead cretin.' says, 'Surrender or die!' says, 'Savor thy breath, it be thine last.' -says, 'Prepare do die, miscreant!' +says, 'Prepare to die, miscreant!' says, 'You're history, dude!' says, 'Feeling lucky, punk?' says, 'You're toast!' diff --git a/lib/file/monspeak_j.txt b/lib/file/monspeak_j.txt index d120b9cfa..4e8c296c3 100644 --- a/lib/file/monspeak_j.txt +++ b/lib/file/monspeak_j.txt @@ -1032,6 +1032,9 @@ N:1081:チャージマン『研』 「院長、あなたは狂っているんだ!」 「どうも怪しいと思ったら やっぱり そうだったのか」 +N:1090:『ボルガ博士』 +「お菓子好きかい?」 + N:1096:濃尾無双『岩本虎眼』 について「剣術流祖録」はこのような詩を記す― 狂ほしく 血のごとき 月はのぼれり 秘めおきし 魔剣 いずこぞや が構えたる星流れの型が蘇らせた忌まわしき記憶は鮮明であったが 目の前の@がその一件と無関係であることは明確だろうか? @@ -1045,6 +1048,12 @@ N:1106:光の堕天使『エミリオ・ミハイロフ』 「僕は今とっても楽しいんだ」 「いい歌だな、もっと歌ってよ」 +N:1123:巴流『葦名弦一郎』 +「俺が芦名を守る」 +「踏みにじらせはせぬぞ」 +「卑怯とは言うまいな」 +「巴の雷、見せてやろう」 + N:*:Default lines #cackles evilly. は邪悪に笑っている。 diff --git a/lib/file/news.txt b/lib/file/news.txt index 8c37b64d1..11df82175 100644 --- a/lib/file/news.txt +++ b/lib/file/news.txt @@ -15,8 +15,8 @@ ZAngband 2.3.0 - ???: The ZAngband DevTeam ZAngband Jap ver.: Mitsuhiro Itakura - Hengband: Mr.Hoge (echizen @ users.sourceforge.jp) & Many others - http://hengband.sourceforge.jp/ + Bakabakaband: Mr.Hoge (echizen @ users.sourceforge.jp) & Many others + http://Bakabakaband.sourceforge.jp/ - Send bug report to "hengband-dev@lists.sourceforge.jp" + Send bug report to "Bakabakaband-dev@lists.sourceforge.jp" diff --git a/lib/file/news_j.txt b/lib/file/news_j.txt index d1aca73c7..f0154126a 100644 --- a/lib/file/news_j.txt +++ b/lib/file/news_j.txt @@ -15,8 +15,8 @@ ZAngband 2.3.0 - ???: The ZAngband DevTeam ZAngband 日本語版: 板倉充洋 < itakuraï¼ users.sourceforge.net > - 変愚蛮怒: Mr.hoge (echizenï¼ users.sourceforge.jp) & 多くの方々 - http://hengband.sourceforge.jp/ + 馬鹿馬鹿蛮怒: Mr.hoge (echizenï¼ users.sourceforge.jp) & 多くの方々 + http://Bakabakaband.sourceforge.jp/ - 変愚蛮怒 は UNIX/X11, Windows, Macintosh で動作しています。 + 馬鹿馬鹿蛮怒 は UNIX/X11, Windows, Macintosh で動作しています。 バグ情報などは上記 URL にある掲示板へお願いします。 diff --git a/lib/file/rumors.txt b/lib/file/rumors.txt index c4fc2ac36..bfadb499a 100644 --- a/lib/file/rumors.txt +++ b/lib/file/rumors.txt @@ -24,9 +24,9 @@ There are Black Market stores hidden deep in the dungeon, with COOL stuff! Have you ever seen a Rod of Havoc inscribed {BFG9000}? What a pity, you cannot read it! You will encounter a dark, tall stranger... -A Mithril mail will not rust. -An Adamantite mail will not rust. -A Rusty Chain Mail cannot rust any further. +Mithril mail will not rust. +Adamantite mail will not rust. +Rusty Chain Mail cannot rust any further. If you are a mage, you will NOT want to find Raal's Tome of Destruction! You won't want to find Raal's Tome of Destruction! You won't want to find Raal's Tome of Destruction, unless you are a mage. @@ -241,7 +241,7 @@ Autorollers aren't wary bright things. The Wargs give ah very sharpee Choir tonightee! The depths are about as unreliable as a dish of over-ripe figs. May all the Crows of the Volcano pick your bones clean! -Ever made your dance around enthousiastic lice without a certain staff? +Ever made your dance around enthusiastic lice without a certain staff? A staff is just like a colleague. But a reliable one! You are prepared to thrill us with a traditional heroic display? Some underworld lads would *LOVE* to blacken your name! @@ -297,7 +297,7 @@ Have a rest and a rumor in the inn over some comfortable pitchers of beer. The stakes are far too high for a weak bluff, so watch the scores? Be not like the others. Proceed carefully, cover yourself at all times. You wouldn't want to fool with the Trumps! Aren't they of Doom quality? -Smeagols removal is high on your list of things that needed knowing or doing? +Smeagol's removal is high on your list of things that needed knowing or doing? Matter of recollection: find the inn and nurse some rumors for a while. Served you right: 3 quarters dead. Wasn't it purely a result of your arrogance? Confident - Cocky - Lazy - Dead. The Old Man's mantra, and a serious good one. @@ -395,7 +395,7 @@ Morgoth is the very brink where hope and despair are akin. Give little heed to the wreck and slaughter that will lay around the pits. Accidents? what accidents? Mighty were your fallen ancestors. Fortune has betrayed you but for the momentum. Confidence! -On the long run - IF you're survivor - winds of fortune will not wreck you. +In the long run - IF you're survivor - winds of fortune will not wreck you. As a spell-striking egghead you'd need convincing offensive powers! Once no Recall is left the way up will seem never ending to you. The simple scheme ended in failure. That demon called lots of companions. @@ -418,7 +418,7 @@ Zelazny said: "Sometimes it's damned hard to tell the dancer from the dance." If it's not quite visible if you caught a gear curse look it up by Ctrl-C. Any lesser titan will not just summon a monster but several combos of them. Robin Hood nowadays leads a wretched existence as a trapper and master thief. -Too many different Zephyrs are the heroes death. IF caught on open ground. +Too many different Zephyrs are the hero's death. IF caught on open ground. If you ever confront a Hru have a Teleport Other at hand! Any Hru will rage, spreading earthquake and ruin. Only Shudde is worse. You cannot escape a Hru just by blinking. Your life will be shattered! @@ -497,7 +497,7 @@ You are starting to loose your temper? So what? Gnaw your pistachios! It shrieks? Don't bother! Presumably there will be just innocent bystanders. Still you might still fade out again! Been seeing so many ghostly apparitions. Even if the bluff fails them never give up! The caves are hotbed of banditry. -Before I settled down, in my younger days I won the arena price. +Before I settled down, in my younger days I won the arena prize. Are you not the refined sensitive type you're disguised as? However you shouldn't want to upset sensitivities hereabout. Learn xenology! Critters? If action was taken early this conspiracy could be nipped in the bed. @@ -548,7 +548,7 @@ It's deciding which things are crucial that separates the wise from others. Invulnerability is impenetrable. Invulnerability may be penetrated by evil creatures. Resistance to nether will guard against invulnerability-penetration. -Creatures of good alignment are not deterred by invlnerability. +Creatures of good alignment are not deterred by invulnerability. Being clocked backwards is just a terrible irony of fate. Time is a weird attack - not even sustained stats will save you. Stumble on a death mold: another unsettling occurrence in an unsettling world. @@ -572,7 +572,7 @@ There are no guarantees in life, but it's smarter to take fewer chances. Artsi is not susceptible to sorcery, ideal warrior! If ever get him in melee. It's a crying shame, but 30000's the highest you'll ever sell an item for. There is a shopkeeper who may pay 50000 gold for an item. -Is it really true that a good chain armour once rusted can't be restored? +Is it really true that good chain armour once rusted can't be restored? Never thought about that daylight might be not just an illumination? Stone Skin is valuable as diamonds: even the tougher foes will miss you. You WILL need some means to prevent to be teleported to and fro unwanted. @@ -600,7 +600,7 @@ Survival challenges use up superabundant energies, burn off the gland-juices. Kittens. Always going for the dramatic. Watching too many adventure holos. Young Heroes-to-be are always kept on diet, to increase their aggressiveness. Free at last from the blood curse: mirth welled up, boiled over as pure laughter. -If you encounter groups of usual solitary cats look out for Bast, Cat's godess! +If you encounter groups of usual solitary cats look out for Bast, Cat's goddess! Even protected Books are destroyed by breathers of chaos balls. It is more secure to carry precious books yourself, IF you provide resistances. Do not cast stone-to-mud while your skin is made of stone. diff --git a/lib/file/rumors_j.txt b/lib/file/rumors_j.txt index 47724584c..7ffc500e6 100644 --- a/lib/file/rumors_j.txt +++ b/lib/file/rumors_j.txt @@ -24,7 +24,7 @@ N:0:Default 動物園を見学することはいろんな動物に会え教育上非常によろしい。 ディスプレイを蹴ったところで怪物は傷つかない。 誰も噂を流すことを許してないそうだ。 -単なる楽しみで変愚蛮怒をプレイできる者などいないそうだ。 +単なる楽しみで馬鹿馬鹿蛮怒をプレイできる者などいないそうだ。 多少の誤訳でも報告してほしいそうだ。 多小の五時奪字には目を潰る寛太さが…心要ないそうだ。 スピードの靴を履くと,不慮の攻撃や衝突の心配がないそうだ。 @@ -33,7 +33,7 @@ N:0:Default 上手くいく方法が判らないなら、上手くいかない方法を楽しめばよい。 勝利のための戦略を発見するには気長にやるしかないそうだ。 手が輝いているときに食事をしてはならない。 -仕事中に変愚蛮怒で遊んではならない。ボスに怒られるぞ! +仕事中に馬鹿馬鹿蛮怒で遊んではならない。ボスに怒られるぞ! 剣の世界に生きるなら、剣によって死ぬと言われている。 鎧は「ステンレス」と銘を付けるとよいそうだ。 怪物はあらゆるところで君を打ちまかそうと、どこからともなくやって来る。 @@ -43,11 +43,11 @@ N:0:Default #670 悪魔といっしょに眠ったならば、頭痛ともに目が覚めるであろう。 ランニングは足によい。 -変愚蛮怒の翻訳はとても大変だったそうだ。 -変愚蛮怒は単なるコンピューターゲーム以上のものがあるそうだ。 -変愚蛮怒の最大の障害は。あなたの心だそうだ。 -変愚蛮怒は常習癖がつきやすい。君はもう手遅れだ。 -変愚蛮怒の存在意義などないそうだ。 +馬鹿馬鹿蛮怒の翻訳はとても大変だったそうだ。 +馬鹿馬鹿蛮怒は単なるコンピューターゲーム以上のものがあるそうだ。 +馬鹿馬鹿蛮怒の最大の障害は。あなたの心だそうだ。 +馬鹿馬鹿蛮怒は常習癖がつきやすい。君はもう手遅れだ。 +馬鹿馬鹿蛮怒の存在意義などないそうだ。 トライデントは水面下で使用するものだ。 スフィンクスが出す問題には答えのないものもある。 エルフのクロークを身につけてるとセンスがよいと言われる。 @@ -57,8 +57,8 @@ N:0:Default その昔、アルルという名のメイジはサソリマンに苦しんだそうだ。 その昔、ヨシミツという名の剣術家は剣を回して空を飛べたそうだ。 さまよう目は背後から攻撃するよう心がけよ。 -変愚蛮怒は2001年冬にPlayStation2で発売される。 -変愚蛮怒の攻略本絶賛発売中!定価2500円! +馬鹿馬鹿蛮怒は2001年冬にPlayStation2で発売される。 +馬鹿馬鹿蛮怒の攻略本絶賛発売中!定価2500円! 20歳未満の未成年が酔っぱらいの薬を飲んだら牢屋行きになる。 次のことをすれば一つの指輪を手に入れることができる: --続く-- 裏口から店を出ることはできない。そんなものはないのだ! @@ -827,7 +827,7 @@ You are starting to loose your temper? So what? Gnaw your pistachios! It shrieks? Don't bother! Presumably there will be just innocent bystanders. Still you might still fade out again! Been seeing so many ghostly apparitions. Even if the bluff fails them never give up! The caves are hotbed of banditry. -#Before I settled down, in my younger days I won the arena price. +#Before I settled down, in my younger days I won the arena prize. わしゃ隠居する前にアリーナで優勝したぞ。 Yegh! Assuming you are not the refined sensitive type you're disguised as? However you shouldn't want to upset sensitivities hereabout. Learn xenology! diff --git a/lib/file/seppuku.txt b/lib/file/seppuku.txt index 14ec57d3e..ab0dc163a 100644 --- a/lib/file/seppuku.txt +++ b/lib/file/seppuku.txt @@ -1,2 +1,2 @@ N:*:Default -Meaning of Bushi-do is found in the death. +Meaning of bushido is found in the death. diff --git a/lib/file/timefun.txt b/lib/file/timefun.txt index 23fe8c93b..7fc4b4cb4 100644 --- a/lib/file/timefun.txt +++ b/lib/file/timefun.txt @@ -8,7 +8,7 @@ D:There may be Vampires around! S:0200 E:0359 -D:Only Hengband players are up now! +D:Only Bakabakaband players are up now! S:0400 E:0459 diff --git a/lib/file/timefun_j.txt b/lib/file/timefun_j.txt index 3c6294f2f..b43578402 100644 --- a/lib/file/timefun_j.txt +++ b/lib/file/timefun_j.txt @@ -8,7 +8,7 @@ D:ヴァンパイアがそこら中にいるだろう! S:0200 E:0459 -D:変愚蛮怒のプレイヤーしか起きていない! +D:馬鹿馬鹿蛮怒のプレイヤーしか起きていない! S:0100 E:0459 diff --git a/lib/file/w_low.txt b/lib/file/w_low.txt index 1f63f4ae4..596790df0 100644 --- a/lib/file/w_low.txt +++ b/lib/file/w_low.txt @@ -30,7 +30,7 @@ N: 3:BIAS_FIRE 'Fire Ant' 'Hot Blood' 'Fervent Soul' -of the Damn +of the Damned N: 4:BIAS_COLD 'Freezing' @@ -81,7 +81,7 @@ N:14:BIAS_NECROMANTIC 'Dungeon Shade' 'Elfrist' of Misery -of Boodoo +of Voodoo N:15:BIAS_LAW N:13:BIAS_PRIESTLY diff --git a/lib/file/w_med.txt b/lib/file/w_med.txt index 4379104b8..e6800bf86 100644 --- a/lib/file/w_med.txt +++ b/lib/file/w_med.txt @@ -98,7 +98,7 @@ N:14:BIAS_NECROMANTIC 'Dark Banisher' 'Bloody Mary' of Helthing -of Darkness Strom +of Stormy Darkness of Genocide of Thuringwethil diff --git a/lib/help/Makefile.am b/lib/help/Makefile.am index 25b99f18c..60b7be311 100644 --- a/lib/help/Makefile.am +++ b/lib/help/Makefile.am @@ -4,7 +4,7 @@ angband_files = \ attack.hlp attack.txt birth.hlp birth.txt \ bldg.txt raceclas.hlp raceclas.txt command.hlp \ command.txt commdesc.hlp commdesc.txt editor.txt \ - defend.hlp defend.txt dungeon.hlp dungeon.txt \ + defend.hlp defend.txt dungeon.hlp dungeon.txt faq.txt \ gambling.txt general.hlp general.txt help.hlp helpinfo.txt \ j_general.txt j_item1.txt j_item2.txt j_trans.txt \ jattack.hlp jattack.txt jbirth.hlp jbirth.txt \ diff --git a/lib/help/attack.txt b/lib/help/attack.txt index e052a6403..ce2cac0d3 100644 --- a/lib/help/attack.txt +++ b/lib/help/attack.txt @@ -1,6 +1,6 @@ === Attacking and Weapons=== -Attacking is simple in Hengband. If you move into a creature, you +Attacking is simple in Bakabakaband. If you move into a creature, you attack it. If you are wielding a weapon (including digging implements which are considered to be weapons) when you do so, the damage for the weapon is used when you hit a creature. Otherwise, you will attack with @@ -26,7 +26,7 @@ devices. You can attack creatures from a distance by firing a missile from a bow or other missile launcher, by throwing an object or by using magical -items such as wands, rods and staves. If you have chosen to play a +items such as wands, rods and staffs. If you have chosen to play a spell casting class, you may be able to learn some spells which allow you to attack a creature from a distance. You can use distance attacks even when your target is next to you. @@ -54,11 +54,11 @@ creature. If the creature is invisible and you do not have the ability to see invisible creatures, you must tunnel into the wall space containing the creature. -Bolt spells does full damage to such creature in a wall, but ball -spells will be stopped and blow up just in front of a wall and does -only half damages. Inversely, when you have ghost like form, and are -in a wall, you will take only half damage from ball spells and -breathes of monsters, which is very important privilege. +Bolt spells do full damage to a creature in a wall, but ball spells +will be stopped and blow up just in front of a wall and do only half +damage. Inversely, when you have ghost like form and are in a wall, +you will take only half damage from ball spells and breaths of +monsters, which is a very important privilege. ***** === Melee Weapons === @@ -70,13 +70,13 @@ when needed. Weapons have two main magical characteristics, their enchanted ability to hit and their enchanted ability to do damage, expressed as -`(+#,+#)'. A normal weapon would be `(+0,+0)'. Many weapons in Hengband +`(+#,+#)'. A normal weapon would be `(+0,+0)'. Many weapons in Bakabakaband have bonuses to hit and/or do damage. Some weapons are cursed, and have penalties that hurt the player. Cursed weapons cannot be unwielded until the curse is lifted. Identifying a weapon will inform you of the magical bonuses and penalties and whether or not it is cursed. -Hengband assumes that your youth in the rough environment near the +Bakabakaband assumes that your youth in the rough environment near the dungeons has taught you the relative merits of different weapons, and displays as part of their description the damage dice which define their capabilities. Any damage enchantment is added to the dice roll @@ -323,7 +323,7 @@ Weapon of *Slay* Animal Weapon of *Slay* Evil This weapon is especially effective against evil creatures and - will inflict damage with two times the normal dice against such + will inflict damage with 3.5 times the normal dice against such creatures, and allows wielder to sense the presence of evil creatures. It will increase your wisdom and will also be a blessed blade. @@ -417,7 +417,8 @@ Ammunition of Slaying This ammunition will have unusually large damage dice. Ammunition of Wounding - This ammunition will have unusually bonuses +to-hit and +to-dam. + This ammunition will have unusually large bonuses +to-hit and + +to-dam. --- Other Items --- @@ -446,8 +447,8 @@ realms contain equivalent spells. ***** === Monk Attacks === -The Monk and ForceTrainer is designed to be a barehanded fighter -rather than using a weapon like the other Hengband classes. As a +The Monk and ForceTrainer are designed to be barehanded fighters +rather than using a weapon like the other Bakabakaband classes. As a Monk's level increases the number of attacks they get per round increases and new, increasingly powerful attacks become available. Higher level attacks have a chance to stun the Monk's @@ -490,7 +491,7 @@ Crushing Blow 48 10d13 18 Pillardancing ------------- -Not recommended in Hengband: monsters move at irregular speeds. +Not recommended in Bakabakaband: monsters move at irregular speeds. Shoot'n Scoot @@ -527,7 +528,7 @@ monsters. Original : (??) Chris Weisiger and Leon Marrick Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.5.2 +Updated : Bakabakaband 1.5.2 ***** Begin Hyperlinks ***** [b] commdesc.txt#ThrowFire diff --git a/lib/help/birth.txt b/lib/help/birth.txt index 2d008b8d2..0d1896067 100644 --- a/lib/help/birth.txt +++ b/lib/help/birth.txt @@ -1,7 +1,7 @@ === Creating a Character === -Hengband is a role playing game, in which you, the player, control a -character in the world of Hengband. Perhaps the most important thing +Bakabakaband is a role playing game, in which you, the player, control a +character in the world of Bakabakaband. Perhaps the most important thing you control is the birth of your character, in which you choose or allow to be chosen various attributes that will affect the future life of your character. @@ -37,7 +37,7 @@ Each character has a few secondary attributes, height, weight, social class, and background history, which are randomly determined, but which are affected by the sex and race of the character. In general, these attributes are only used to provide "flavor" to the character, -to assist in the roll playing, but they do have a few minor effects on +to assist in role playing, but they do have a few minor effects on the game. For example, background history affects social class, which affects the amount of money the character will start with. And weight affects riding ability. @@ -159,7 +159,7 @@ quantum of this modification can be found in the stat bonus table (see raceclas.txt#StatBonusTable [h]). Once a character that matches or exceeds your expectations has been -rolled, Hengband stops to ask you whether you accept or not. If you +rolled, Bakabakaband stops to ask you whether you accept or not. If you accept the rolled character (by pressing Enter), you will be asked for its name. If not, you may press 'r' to resume rolling and searching for the next match or, if this is not your first match, 'p' to return @@ -183,26 +183,28 @@ above. === Background Edit-Mode === The computer will randomly generate background information text of the -character for you. But you can modify or rewrite it after rolling up -the character in Background edit-mode. Use key-pad or cursor keys to -move cursor, the Enter key to finish edit-mode, and the Escape key to -finish edit-mode with discarding changes. Use Ctrl-A key to load the -background information text from "histpref-<>.prf" or -"histpref.prf" on lib/user. +character for you. After rolling up the character, you can modify or +rewrite that text in Background edit-mode. Use key-pad or cursor keys +to move the cursor. Use the Enter key to finish edit-mode and save any +changes. Use the Escape key to finish edit-mode and discard any +changes. Use Ctrl-A to load the background information text from +"histpref-<>.prf" or "histpref.prf" in lib/user. -You can use conditional expressions like other pref files. Background -information text can be modified in background information pref files -as lines of the form "H:". Text area is not much large, so too -long text will cut down. +Background information text can be supplied in the background +information pref files as lines of the form "H:". You can use +conditional expressions as in other pref files. When displayed, the +background information will be cropped to fit the area available for +display, which is not very large. ***** === Quick Start === -Once you have generated a character and dead or quit game, you will be -asked whether you want to use quick start or not at start up. If you -choose to use quick start, you get new character with exactly same -race, class, stat, background and etc. as your last character. +If you have already generated a character and that character died or +quit, you will be asked whether you want to use quick start or not at +start up. If you choose to use quick start, you get a new character +with exactly same race, class, stat, background and etc. as your last +character. ***** @@ -229,7 +231,7 @@ after the "18/" is as "tenth" points, since it often takes the same magic to raise a stat from, say, 4 to 5, or 16 to 17, as it does from, say, 18/40 to 18/50. The important thing to remember is that almost all internal calculations "ignore" the final digit of any "bonus", so that, -for example, "18/40" and "18/49" are always have the same effects. +for example, "18/40" and "18/49" always have the same effects. --- The Primary Statistics --- @@ -356,22 +358,22 @@ Searching (Searching Ability) entirely upon race and class, and will never improve unless magically enhanced. -Infra-vision - Infra-vision is the ability to see heat sources. Since most of - the dungeon is cool or cold, infra-vision will not allow the - player to see walls and objects. Infra-vision will allow a +Infravision + Infravision is the ability to see heat sources. Since most of + the dungeon is cool or cold, infravision will not allow the + player to see walls and objects. Infravision will allow a character to see any warm-blooded creatures up to a certain distance. This ability works equally well with or with out a - light source. The majority of Hengband's creatures are + light source. The majority of Bakabakaband's creatures are cold-blooded, and will not be detected unless lit up by a light - source. Most non-human races have innate infra-vision ability. - Humans can gain infra-vision only if it is magically enhanced. + source. Most non-human races have innate infravision ability. + Humans can gain infravision only if it is magically enhanced. ***** === Proficiency Levels === -In Hengband, characters possess different proficiency levels or +In Bakabakaband, characters possess different proficiency levels or experiences for each weapon type, spells, and a few other skills. The starting proficiency levels and the maximum proficiency levels of a character are based upon class. Each proficiency level may increase @@ -405,7 +407,7 @@ monster.txt#Pets [i]) Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.5.2 +Updated : Bakabakaband 1.5.2 ***** [a] raceclas.hlp ***** [b] magic.hlp diff --git a/lib/help/bldg.txt b/lib/help/bldg.txt index ba27f2d35..ed09a0692 100644 --- a/lib/help/bldg.txt +++ b/lib/help/bldg.txt @@ -4,23 +4,23 @@ The town is composed of both stores and buildings. Classical stores: Magic Shop: buy your wands, staffs, rings and amulets here. -Alchemist: for all sorts of bubbling potions and scrolls. -Weaponsmith: they deal in anything sharp and to the point. -Armorer: to offer protection from the ravages of the dungeon. +Alchemy Shop: for all sorts of bubbling potions and scrolls. +Weaponsmith's Shop: they deal in anything sharp and to the point. +Armoury: to offer protection from the ravages of the dungeon. General Store: food, torches, ammo, some necessities. -Temple Trade: those items permitted to the pious in life. -Black Market: the prices are usurious, but some depths items! +Temple: those items permitted to the pious in life. +Black Market: the prices are usurious, but may have powerful items! Home: to store some of your precious treasures. Zangband additional (if you do not prefer Ironman/Vanilla): -The Fighter's Halls, Order of Paladins, Ranger's Taverns, -Gilds of Thieves, and the diverse Towers of magic realms +The Fighters' Halls, Order of Paladins, Rangers' Taverns, +Thieves' Guilds, and the diverse Towers of magic realms are no longer restricted to the professionals involved. Nevertheless some of the services are exclusive for members. Look out for ambitious quests! Buildings that anyone can visit if in need of some diversion: -Gambling Houses: Read the rules before paying. And, the games +Gambling Houses: Read the rules before playing. And, the games are not rigged, just naturally difficult. Authorities: Ask for quests to gain reputation and rewards. Libraries: For information indexes of all kinds. diff --git a/lib/help/command.hlp b/lib/help/command.hlp index 42ba324a3..1b1468917 100644 --- a/lib/help/command.hlp +++ b/lib/help/command.hlp @@ -1,8 +1,8 @@ -Hengband Commands. +Bakabakaband Commands. Please choose one of the following online help files: - (a) Hengband Commands (command.txt) + (a) Bakabakaband Commands (command.txt) (b) Original Keyset (command.txt#OriginalKeyset) (c) Roguelike Keyset (command.txt#RogueKeyset) (d) Special Keys (command.txt#SpecialKeys) diff --git a/lib/help/command.txt b/lib/help/command.txt index 2e3d0d69a..41545e23b 100644 --- a/lib/help/command.txt +++ b/lib/help/command.txt @@ -1,12 +1,12 @@ -=== Hengband Commands === +=== Bakabakaband Commands === -Hengband commands are entered as an "underlying command" (a single key) +Bakabakaband commands are entered as an "underlying command" (a single key) plus a variety of optional or required arguments. You may choose how the "keyboard keys" are mapped to the "underlying commands" by choosing one of two standard "keynotes", the "original" keyset or the "roguelike" keyset. -For beginners, Hengband provides the unified command menu that is very +For beginners, Bakabakaband provides the unified command menu that is very easy to use, and can do every thing only with cursor keys, enter key and escape key. Simply press Enter to show up the command menu. The command menu can be disable/enabled by the option 'command_menu'. @@ -54,7 +54,7 @@ any) whose inscription contains "@#" or "@x#", where "x" is the current the command. Whenever an item inscription contains "!*" or "!x" (with "x" as above) you must verify its selection. -In Hengband, there are items which occasionally teleport you away, +In Bakabakaband, there are items which occasionally teleport you away, asking for permission first. The recurring "Teleport (y/n)?" can be annoying, and this behavior can be eliminated by inscribing the object which causes the teleportation with "." (or any inscription containing @@ -99,7 +99,7 @@ example, use "\" + "." + "6", to specify "run east". 4 6 1 2 3 - a Aim a wand A Activate an equipment + a Aim a wand A Activate equipped item b Browse magic list B Bash a door c Close a door C Character description d Drop an item D Disarm a trap @@ -165,7 +165,7 @@ example, use "\" + "." + "6", to specify "run east". h l b j n - a Zap a rod (Activate) A Activate an artifact + a Zap a rod (Activate) A Activate equipped item b (walk - south west) B (run - south west) c Close a door C Character description d Drop an item D Disarm a trap or chest @@ -231,7 +231,7 @@ keys are control keys, and often, you can disable their special effects. If you are playing on a UNIX or similar system, then Ctrl-C will -interrupt Hengband. The second and third interrupt will induce a +interrupt Bakabakaband. The second and third interrupt will induce a warning bell, and the fourth will induce both a warning bell and a special message, since the fifth will quit the game, after killing your character. Also, Ctrl-Z will suspend the game, and return you to the @@ -249,7 +249,7 @@ Pressing backslash ("\") before a command will bypass all keymaps, and the next keypress will be interpreted as an "underlying command" key, unless it is a caret ("^"), in which case the keypress after that will be turned into a control-key and interpreted as a command in the -underlying Hengband keyset. The backslash key is useful for creating +underlying Bakabakaband keyset. The backslash key is useful for creating macro actions which are not affected by any keymap definitions that may be in force, for example, the sequence "\" + "." + "6" will always mean "run east", even if the "." key has been mapped to a different @@ -291,7 +291,7 @@ any character. This character is ignored, but it is safest to use a SPACE or ESCAPE which are always ignored as commands in case you type the command just after the count expires. -You can tell Hengband to automatically use a repeat count of 99 with +You can tell Bakabakaband to automatically use a repeat count of 99 with commands you normally want to repeat (open, disarm, tunnel, bash, alter, etc) by setting the "always_repeat" option. @@ -328,7 +328,7 @@ If you enter a number between 0 and 9, the first item engraved with if you have a shovel engraved with "@0" and you type "w" (for wield) and then 0, you will wield the shovel. This is very useful for macros (see below), since you can use this to select an object regardless of -its location in your pack. For example, Hengband automatically defines +its location in your pack. For example, Bakabakaband automatically defines a macro for the key "X" to do "w0". If you then engrave both your digging instrument and your primary weapon with @0, pressing X will wield whichever one is not being currently wielded (letting you quickly @@ -337,11 +337,11 @@ object; for example, if a sword is engraved with @1@0, then either "w1" or "w0" will wield it. Normally, you inscribe "@1@0" on your primary weapon, and "@2@0" on your digger or secondary weapon. Note that an inscription containing "@x#" will act like "@#" but only when the -current "Hengband command" is "x". Thus you can put "@z4" on a rod and +current "Bakabakaband command" is "x". Thus you can put "@z4" on a rod and "@u4" on a staff, and then use both "z4" and "u4" as desired. Note that any object containing "!x" in its inscription, where "x" is -the current "Hengband command" (or containing "!*" ever) will induce +the current "Bakabakaband command" (or containing "!*" ever) will induce "verification" whenever that object is "selected". Thus, inscribing, say, "!f!k!d" on an object will greatly reduce the odds of you "losing" it by accident, and inscribing "!*" on an object will allow you to be @@ -355,4 +355,4 @@ Updated : (2.7.6) by Russ Allbery (rra@cs.stanford.edu) Updated : (2.7.9) by Ben Harrison (benh@phial.com) Updated : Zangband 2.2.0 through 2.2.6c by Robert Ruehlmann Updated : Zangband DevTeam -Updated : Hengband 1.0.11 +Updated : Bakabakaband 1.0.11 diff --git a/lib/help/commdesc.hlp b/lib/help/commdesc.hlp index 939df02a2..c8e8128cd 100644 --- a/lib/help/commdesc.hlp +++ b/lib/help/commdesc.hlp @@ -1,4 +1,4 @@ -Hengband Command Descriptions. +Bakabakaband Command Descriptions. Please choose one of the following online help files: diff --git a/lib/help/commdesc.txt b/lib/help/commdesc.txt index 3620a9c97..78c82faae 100644 --- a/lib/help/commdesc.txt +++ b/lib/help/commdesc.txt @@ -24,7 +24,7 @@ Inventory list (i) equipment. Often, many identical objects can be "stacked" into a "pile" which will count as a single item. This is always true of things like potions, scrolls, and food, but you may have to set - options to allow wands, staves, and other such objects to stack. + options to allow wands, staffs, and other such objects to stack. Each object has a weight, and if you carry more objects than your strength permits, you will begin to slow down. @@ -43,7 +43,7 @@ Equipment list (e) Drop an item (d) This drops an item from your inventory or equipment onto the dungeon floor. If the floor spot you are standing on already has - an object in it, Hengband will attempt to drop the item onto an + an object in it, Bakabakaband will attempt to drop the item onto an adjacent space. Be warned that if the floor is full and you attempt to drop something, it may disappear and be destroyed. Doors and traps are considered objects for the purpose of @@ -344,11 +344,11 @@ Inscribe an object ({) displayed inside curly braces after the object description. The inscription is limited to the particular object (or pile) and is not automatically transferred to all similar objects. Under - certain circumstances, Hengband will display "fake" inscriptions + certain circumstances, Bakabakaband will display "fake" inscriptions on certain objects ("cursed", "broken", "tried", "empty", "NN% off") when appropriate. These "fake" inscriptions are "covered up" by real inscriptions, but will re-appear if the real inscription - is removed. In addition, Hengband will occasionally place a "real" + is removed. In addition, Bakabakaband will occasionally place a "real" inscription on an object for you, normally as the result of your character getting a "feeling" about the item. All characters will get "feelings" about weapons and armor after carrying them for a @@ -369,7 +369,7 @@ Uninscribe an object (}) ***** --- Magical Object Commands --- -Activate an artifact (A) +Activate equipped item (A) You have heard rumors of special weapons and armor deep in the Pits, items that can let you breath fire like a dragon or light rooms with just a thought. Should you ever be lucky enough to @@ -390,13 +390,13 @@ Aim a wand (a) or Zap a wand (z) Use a staff (u) or Zap a staff (Z) This command will use a staff. A staff is normally very similar to a scroll, in that they normally either have an area effect or - affect a specific object. Staves are magical devices, and there + affect a specific object. Staffs are magical devices, and there is a chance you will not be able to figure out how to use them. Zap a rod (z) or Activate a rod (a) Rods are extremely powerful magical items, which cannot be burnt or shattered, and which can have either staff-like or wand-like - effects, but unlike staves and wands, they don't have charges. + effects, but unlike staffs and wands, they don't have charges. Instead, they draw on the ambient magical energy to recharge themselves, and therefore can only be activated once every few turns. The recharging time varies depending on the type of rod. @@ -414,7 +414,7 @@ Fire an item (f) or Fire an item (t) throwing an object will often cause it to break, so be careful! If you throw something at a creature, your chances of hitting it are determined by your pluses to hit, your ability at throwing, - and the object's pluses to hit. Once the creature is it, the + and the object's pluses to hit. Once the creature is hit, the object may or may not do any damage to it. You've heard rumors that some objects found in the dungeon can do huge amounts of damage when thrown, but you're not sure which objects those @@ -597,12 +597,12 @@ Save and Quit (Ctrl-X) your savefile to play again with the same options and such. Save (Ctrl-S) - This command saves the game but doesn't exit Hengband. Use this + This command saves the game but doesn't exit Bakabakaband. Use this frequently if you are paranoid about having the computer crash while you are playing. Quit (commit suicide) (Q) - Kills your character and exits Hengband. You will be prompted to + Kills your character and exits Bakabakaband. You will be prompted to make sure you really want to do this, and then asked to verify that choice. Note that dead characters are dead forever. @@ -653,11 +653,11 @@ Edit auto-picker/destroyer pref (_) --- Help --- Help (?) - Brings up the Hengband on-line help system. Note that the help + Brings up the Bakabakaband on-line help system. Note that the help files are just text files in a particular format, and that other help files may be available on the Net. In particular, there are a variety of spoiler files which do not come with the standard - distribution. Check the place you got Hengband from or ask on the + distribution. Check the place you got Bakabakaband from or ask on the newsgroup rec.games.roguelike.angband about them. Identify Symbol (/) @@ -686,7 +686,7 @@ Identify Symbol (/) on. Pressing ESCAPE at any point will exit this command. Game Version (V) - This command will tell you what version of Hengband you are using. + This command will tell you what version of Bakabakaband you are using. For more information, see the "version.txt" help file. @@ -701,7 +701,7 @@ Repeat last command (n) or ([) Toggle Choice Window (^E) Toggles the display in the choice window (if available) between your inventory and your equipment. This command only applies if - you are running Hengband under a windowing environment and the + you are running Bakabakaband under a windowing environment and the choice window is available. This also redraws the choice window. Redraw Screen (^R) @@ -735,5 +735,5 @@ Updated : (2.7.6) by Russ Allbery (rra@cs.stanford.edu) Updated : (2.7.9) by Ben Harrison (benh@phial.com) Updated : Zangband 2.2.0 through 2.2.6c by Robert Ruehlmann Updated : Zangband DevTeam -Updated : Hengband 1.7.0 +Updated : Bakabakaband 1.7.0 diff --git a/lib/help/defend.txt b/lib/help/defend.txt index cd9cf43a8..e841ec363 100644 --- a/lib/help/defend.txt +++ b/lib/help/defend.txt @@ -1,6 +1,6 @@ === Defending and Armor === -In Hengband, monsters may damage and otherwise harm you in a number of +In Bakabakaband, monsters may damage and otherwise harm you in a number of ways: in direct melee combat, by exploding next to you, by breathing on you and by casting spells. Some monsters referred to as "summoners" may not directly harm you but may summon other monsters to do their @@ -15,7 +15,7 @@ attacks which may be of varying type, power and effect. In addition to pure damage, there can be a number of side-effects from a monster hitting you. For example, an especially powerful attack may -stun you wound you. Stunning is cumulative and, if not addressed, may +stun or wound you. Stunning is cumulative and, if not addressed, may eventually result in you becoming knocked out which allows your opponent to continue attacking while you lie helpless. Wounds will cause you to lose hit points each round until you either die or your @@ -59,7 +59,7 @@ no damage is the same as a miss. Two, good armor will absorb some of the damage that your character would have taken from normal attacks. Three, acid damage is reduced by wearing body armor (but the armor will be damaged instead). It is obvious that a high armor class is a must -for surviving the deeper levels of Hengband. Note, however, that armor +for surviving the deeper levels of Bakabakaband. Note, however, that armor class by itself will not protect you from the side effects of monster melee attacks mentioned above. @@ -91,7 +91,7 @@ not apply. Also, there is no saving throw against monster breaths. For these types of attacks, your only recourse it to find items or other means which grant you 'resistance' to that type of attack. -In Hengband there are many forms of resistance which may be obtained +In Bakabakaband there are many forms of resistance which may be obtained either as bonuses from your equipment, as the result of casting a magical spell, activating certain artifacts or as the result of a mutation. Unfortunately, not all attacks available to monsters can be @@ -135,12 +135,12 @@ of attacks. In addition to the ordinary armor items your character may find in the dungeon, some of them may be endowed with additional powers. -These armors are fall into two types(1) artifacts; and (2) ego armors. +Those fall into two types: (1) artifacts and (2) ego armor. Unlike artifacts which are unique and may only be found once in each -game, it is not unusual to find several ego armors of the same type -during the course of a character's adventures. +game, it is not unusual to find several pieces of ego armor of the +same type during the course of a character's adventures. -In general, artifacts and ego armors may boost one or more of your +In general, artifacts and ego armor may boost one or more of your primary statistics, may confer certain abilities upon your character and may grant resistance to certain forms of attack. Each Ego type may only be found on certain types of armor - for example, you can find a @@ -308,7 +308,7 @@ Dragon Shields and Helms random resistances. Other items - Apart from these there are some very rare, and well made armors + Apart from these there are some very rare, and well made armor in the dungeon with not necessarily any special abilities. These include Adamantite Plate Mail, Mithril Plate Mail, Mithril Chain Mail, Shields of Deflection, and Shadow Cloaks. The first four @@ -416,7 +416,7 @@ Shards have sound resistance and not by shard resistance. Nexus - Nexus attacks are one of the most annoying attacks in Hengband but + Nexus attacks are one of the most annoying attacks in Bakabakaband but will rarely kill you directly. A Nexus attack will damage the player and may teleport the player, teleport-level the player or swap two of your primary statistics around. Nexus resistance will reduce the @@ -426,7 +426,7 @@ Nexus Chaos Chaos attacks are one of the most dangerous attack types in - Hengband. They have a relatively high maximum damage, and may also + Bakabakaband. They have a relatively high maximum damage, and may also confuse the player, cause hallucination, reduce your character's experience and cause you to mutate. Chaos resistance will the damage taken from such attacks and negate all side-effects. @@ -522,15 +522,15 @@ Hold-life ***** === Recovering from Attacks === -You cannot combat with the creatures in Hengband and expect to come out +You cannot combat with the creatures in Bakabakaband and expect to come out unscathed every time. When a monster inflicts damage on you, you will need to take steps to recover from the damage as soon as possible. --- Healing Items --- -Healing is available in multiple forms including: Potions and Staves +Healing is available in multiple forms including: Potions and Staffs of Cure Light Wounds, Potions of Cure Serious Wounds, Potions of Cure -Critical Wounds, Potions, Staves and Rods of Healing, Potions of +Critical Wounds, Potions, Staffs and Rods of Healing, Potions of *Healing* and Potions of Life, from weakest to strongest. Both the Life and Nature realms contain spells to heal the player. @@ -590,4 +590,4 @@ exhaustive list is not provided in this document. Original : (??), Leon Marrick and Chris Weisiger Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.0.11 +Updated : Bakabakaband 1.0.11 diff --git a/lib/help/dungeon.txt b/lib/help/dungeon.txt index 66dfbb529..61037690b 100644 --- a/lib/help/dungeon.txt +++ b/lib/help/dungeon.txt @@ -1,7 +1,7 @@ === The Dungeon === -Although Hengband contains an extensive town level featuring multiple +Although Bakabakaband contains an extensive town level featuring multiple towns and a large wilderness area, the bulk of your adventuring will take place in the dungeon. Symbols appearing on your screen will represent the dungeon's walls, floor, objects, features, and creatures @@ -39,7 +39,7 @@ to something you are more comfortable with. [[[[g|.| Patch of grass [[[[b|*| Section of the Pattern [[[[G|:| Flower [[[[U|1| General Store [[[[g|:| Brake [[[[s|2| Armoury - [[[[B|.| Swamp [[[[w|3| Weapon Smiths + [[[[B|.| Swamp [[[[w|3| Weaponsmith's Shop [[[[B|~| Shallow Water [[[[g|4| Temple [[[[b|~| Deep Water [[[[b|5| Alchemy Shop [[[[U|~| Shallow Lava [[[[r|6| Magic Shop @@ -119,7 +119,7 @@ town. It acts in two manners, depending upon your current location. If read within the dungeon, it will teleport you back to town. If read in town, it will teleport you back down to the deepest level of the dungeon which your character has previously been on. This makes the -scroll very useful for getting back to the deeper levels of Hengband. +scroll very useful for getting back to the deeper levels of Bakabakaband. Once the scroll has been read it takes a while for the spell to act, so don't expect it to save you in a crisis. Reading a second scroll before the first has had a chance to take effect will cancel both scrolls. @@ -127,12 +127,12 @@ the first has had a chance to take effect will cancel both scrolls. Since an accidental dive to a new depth (via a trapdoor, for example), may result in the Word of Recall dungeon depth being 'broken', so to speak (meaning that the next Word of Recall in town will take you back -deeper than you would like to), there is a new feature in Hengband +deeper than you would like to), there is a new feature in Bakabakaband which allows you to read a scroll of Word of Recall on a different level and 'reset' the recall depth to that level (instead of the deepest level). -A more complete description of Hengband objects is found elsewhere in +A more complete description of Bakabakaband objects is found elsewhere in the documentation (see object.txt [c]). @@ -229,7 +229,7 @@ other objects that are considered 'great' (see objects.txt)). A feeling is only indicative of the level at the time you entered it and has no impact on subsequent monsters generated or items dropped. -In Hengband, the nastier the feeling prompt, the better the level. From +In Bakabakaband, the nastier the feeling prompt, the better the level. From worst to best, the prompts are as follows: 'What a boring place...' @@ -255,7 +255,7 @@ aura', the prompts will be changed as follows: 'You have an excellent feeling...' 'You have a superb feeling about this level.' -Hengband also uses two other feeling prompts to denote special things. +Bakabakaband also uses two other feeling prompts to denote special things. If you have not yet been on a level long enough to qualify for a prompt and press 'Ctrl-F', you will be given the prompt: @@ -307,7 +307,7 @@ staircase or recall. In such case, the quest will be treated as Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.0.11 +Updated : Bakabakaband 1.0.11 ***** Begin Hyperlinks ***** [b] command.txt diff --git a/lib/help/editor.txt b/lib/help/editor.txt index dfc485d3e..179bf5ba4 100644 --- a/lib/help/editor.txt +++ b/lib/help/editor.txt @@ -3,7 +3,7 @@ Please choose one of the following online help files: (a) The Basics of Auto-picker Editor (#Editor) - (b) Cur and Paste (#CutAndPaste) + (b) Cut and Paste (#CutAndPaste) (c) Register to Auto-picker (#RegisterName) (d) Insert Name from your Inventory (#InsertObjectName) (e) Insert Fixed Keyword (#InsertKeyword) @@ -85,7 +85,7 @@ Selected text will be displayed in yellow. You can press ^X to cut the selected text, or press ^C to copy the selected text to the clipboard. Contents of the clipboard will be pasted on pressing ^V. -Note that it's possible that Hengband cannot recognize shift+arrow +Note that it's possible that Bakabakaband cannot recognize shift+arrow keys on a minor environment. In that case, you can press ^G and then move cursor to select text. @@ -111,10 +111,10 @@ move cursor to select text. ***** [[[[G|--- Format of Auto-picker/destroyer --- -Hengband can automatically pick up or destroy specified objects when +Bakabakaband can automatically pick up or destroy specified objects when you write objects name in the file "pickpref.prf" or "pickpref-<>.prf" in the user directory, this will be -~/.angband/Hengband/ for UNIX, or Hengband\lib\user\ for other +~/.angband/Bakabakaband/ for UNIX, or Bakabakaband\lib\user\ for other operating systems. The game will read the file "pickpref-<>.prf" first and @@ -165,7 +165,7 @@ Keywords: good : {good} items match. nameless : Non ego/non artifact items match. average : {average} items match. - rare : Rare equipment such as Dragon armors etc. match. + rare : Rare equipment such as Dragon armor etc. match. common : Any equipments except 'rare' equipment match. wanted : Wanted monster's corpses or skeletons match. unique monster's : Unique monster's corpses, skeletons or statues match. @@ -181,7 +181,8 @@ Keywords: items : All items match. Use it with an adjective for readability (i.e. "unaware items"). weapons : All weapons including missile weapons match. - armors : All armors match. + armors : Any piece of armor (helm, cloak, body armor, shield, + gloves, or boots) matches. missiles : Arrows, bolts, and shots match. magical devices : Wands, staffs, rods and scrolls match. lights : Light sources match. @@ -194,7 +195,7 @@ Keywords: You may also use keywords which match specified kinds of equipment: weapons, armors, missiles, magical devices, lights, junks, spellbooks, hafted weapons, shields, bows, rings, amulets, suits, cloaks, helms, - gloves, boots + gloves, boots. Character strings: diff --git a/lib/help/faq.txt b/lib/help/faq.txt index 937fcf868..34759c125 100644 --- a/lib/help/faq.txt +++ b/lib/help/faq.txt @@ -1,5 +1,5 @@ -========= Hengband FAQ ========== +========= Bakabakaband FAQ ========== Q. I want to play as an Android, Balrog, Golem, Skeleton, Zombie, @@ -11,7 +11,7 @@ A. Scroll of Satisfy Hunger and Berserker's ability of Satisfy Hunger are obsoleted. And races which previously relied on Satisfy Hunger have new sources of nutrition now; Android can quaff oil. Balrogs can sacrifice human corpse using the 'E'at command. Golems, - Skeletons, Zombies, and Spectres can absorb mana from staves and + Skeletons, Zombies, and Spectres can absorb mana from staffs and wands using the 'E'at command. Ents can gain enough nutrition from potions. @@ -50,9 +50,9 @@ A. Ninja can use Iron Spikes as shuriken; they can throw it as good Q. I'm at normal speed (+0). But normal speed monsters sometimes do double or even triple move! -A. On Hengband, amount of energy needed for a move is somewhat +A. On Bakabakaband, amount of energy needed for a move is somewhat randomized. This method of speed system is an important feature of - Hengband, and is simulating real fighting. So always expect that + Bakabakaband, and is simulating real fighting. So always expect that your enemy can get two or three move. Don't fight when your HP is low, if you don't want to get instakill! @@ -109,39 +109,39 @@ A. You cannot directly control your mount unless you use one hand to Q. Where is the score server? And how do I register my character dumps? -A. Here; 'http://hengband.sourceforge.jp/en/score.html'. - When you die, Hengband will ask you as 'Do you send score to the - world score server?'. And if you answer 'y', Hengband will +A. Here; 'http://Bakabakaband.sourceforge.jp/en/score.html'. + When you die, Bakabakaband will ask you as 'Do you send score to the + world score server?'. And if you answer 'y', Bakabakaband will automatically register your character dump and screen shot. Q. Are there spoiler for more details? -A. Yes. Henkma is writing spoiler page for Hengband; +A. Yes. Henkma is writing spoiler page for Bakabakaband; 'http://www.kmc.gr.jp/~henkma/heng-e/index.html' -Q. Who wrote Hengband? +Q. Who wrote Bakabakaband? -A. Hengband is mainly based on ZAngband 2.2.8 Japanese version. +A. Bakabakaband is mainly based on ZAngband 2.2.8 Japanese version. ZAngband 2.2.8 Japanese version was developed by Mitsuhiro Itakura, based on both ZAngband 2.2.8 and Angband 2.8.3 Japanese version, and has some original features, for example, Auto-picker, in addition to simple translation. - Hengband also includes codes from many other variants including + Bakabakaband also includes codes from many other variants including ToME, OAngband, etc. Mr.Hoge wrote the first original part of - Hengband. And currently, it is maintained by Hengband Development + Bakabakaband. And currently, it is maintained by Bakabakaband Development Team including Mr.Hoge, Habu, Henkma, iks, Kuwa, Mogami and nsk. -Q. Where is Hengband? +Q. Where is Bakabakaband? -A. Here: http://hengband.sourceforge.jp/en/ +A. Here: http://Bakabakaband.sourceforge.jp/en/ - Hengband FAQ written by Mogami + Bakabakaband FAQ written by Mogami -- -Updated : Hengband 1.5.4 +Updated : Bakabakaband 1.5.4 diff --git a/lib/help/general.hlp b/lib/help/general.hlp index 66031c7dd..a8be17488 100644 --- a/lib/help/general.hlp +++ b/lib/help/general.hlp @@ -1,4 +1,4 @@ -An Introduction to Hengband and general information. +An Introduction to Bakabakaband and general information. Please choose one of the following online help files: @@ -6,8 +6,8 @@ Please choose one of the following online help files: (b) First Place to Go (general.txt#First) (c) Winning the Game (general.txt#Winning) (d) Upon Death and Dying (general.txt#UponDeath) - (e) Hengband on the Web (general.txt#Web) - (f) The Hengband Newbie Guide (tang.txt) + (e) Bakabakaband on the Web (general.txt#Web) + (f) The Bakabakaband Newbie Guide (tang.txt) (g) Frequency Asked Questions (faq.txt) (h) Version History (version.txt) diff --git a/lib/help/general.txt b/lib/help/general.txt index 2792ec051..98118311d 100644 --- a/lib/help/general.txt +++ b/lib/help/general.txt @@ -1,12 +1,12 @@ === General Information === -This document gives a brief introduction to Hengband. You will probably +This document gives a brief introduction to Bakabakaband. You will probably want to browse through all the "help files", especially the sections on available commands (see command.txt [b] and commdesc.txt [c]), before beginning any serious adventuring... -The game of Hengband is a single player dungeon simulation. A player +The game of Bakabakaband is a single player dungeon simulation. A player may choose from a number of races, classes and magic realms when creating a character (see birth.hlp [d]), and then "run" that character over a period of days, weeks, even months. Deep down inside, @@ -102,34 +102,34 @@ memory containing all the experience of past incarnations. ***** -=== Hengband on the Web === +=== Bakabakaband on the Web === ---- The official Hengband website --- -(http://hengband.sourceforge.jp/en/) +--- The official Bakabakaband website --- +(http://Bakabakaband.sourceforge.jp/en/) -http://hengband.sourceforge.jp/en/ is the official Hengband website. -It includes information on where to download the Hengband source code +http://Bakabakaband.sourceforge.jp/en/ is the official Bakabakaband website. +It includes information on where to download the Bakabakaband source code and current executables for most popular operating systems as well as information on current development issues. ---- Hengband World Score Board --- -(http://hengband.sourceforge.jp/en/score.html) +--- Bakabakaband World Score Board --- +(http://Bakabakaband.sourceforge.jp/en/score.html) -The official Hengband website includes this score board. You can see +The official Bakabakaband website includes this score board. You can see hundreds of character records at here. And there is translated version of Japanese score board which includes over 5000 records already! ---- Hengband BBS --- +--- Bakabakaband BBS --- (http://6904.teacup.com/combatechizen/bbs) If you read and write Japanese, you can ask question and get various information from this BBS (Bulletin Board System). --- FTP Sites --- -(ftp://clockwork.dementia.org/angband/Variant/Hengband/) +(ftp://clockwork.dementia.org/angband/Variant/Bakabakaband/) -Hengband sources and executables are uploaded to +Bakabakaband sources and executables are uploaded to clockwork.dementia.org FTP site which include most variant of Angband. Links to the files are available at Thangorodrim. (http://www.thangorodrim.net) @@ -137,17 +137,17 @@ Links to the files are available at Thangorodrim. --- The Newsgroup (rec.games.roguelike.angband) --- The newsgroup is a forum for the discussion of all things relating to -Angband and its variants (including Hengband) and is a good place to +Angband and its variants (including Bakabakaband) and is a good place to ask various questions about both game play and game design. Be sure to include '[Heng]' in your subject heading so people know your question -is about Hengband. +is about Bakabakaband. -- Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.5.4 +Updated : Bakabakaband 1.5.4 ***** Begin Hyperlinks diff --git a/lib/help/help.hlp b/lib/help/help.hlp index a950fcbd9..f23bbc400 100644 --- a/lib/help/help.hlp +++ b/lib/help/help.hlp @@ -1,4 +1,4 @@ -Welcome to the Hengband Online Help System. +Welcome to the Bakabakaband Online Help System. Please choose one of the following online help files: @@ -7,13 +7,13 @@ Please choose one of the following online help files: (c) Races, Classes and Personalities (raceclas.hlp) (d) The Town and Wilderness (town.hlp) (e) The Dungeon (dungeon.hlp) - (f) Hengband Objects (objects.hlp) + (f) Bakabakaband Objects (objects.hlp) (g) Monsters and Pets (monster.hlp) (h) Attacking and Weapons (attack.hlp) (i) Defending and Armor (defend.hlp) - (j) Hengband Magic System (magic.hlp) - (k) Hengband Commands (command.hlp) - (l) Hengband Options (option.hlp) + (j) Bakabakaband Magic System (magic.hlp) + (k) Bakabakaband Commands (command.hlp) + (l) Bakabakaband Options (option.hlp) (m) User Preference Files (pref.hlp) (n) Auto-picker/destroyer (editor.txt) diff --git a/lib/help/helpinfo.txt b/lib/help/helpinfo.txt index 895235af6..26e433664 100644 --- a/lib/help/helpinfo.txt +++ b/lib/help/helpinfo.txt @@ -18,6 +18,6 @@ the previous location. [[[[y|Down Arrow|(Go down 1 line) [[[[y]'|'] (Save current document to a file) -- -Updated : Hengband 1.7.0 +Updated : Bakabakaband 1.7.0 ***** [j] monster.txt#Pets diff --git a/lib/help/jattack.txt b/lib/help/jattack.txt index f2177dfe4..21f6fba8e 100644 --- a/lib/help/jattack.txt +++ b/lib/help/jattack.txt @@ -1,6 +1,6 @@ === 攻撃と武器 === -変愚蛮怒 での攻撃は単純です。隣接するモンスターの方に向かって動けば、 +馬鹿馬鹿蛮怒 での攻撃は単純です。隣接するモンスターの方に向かって動けば、 そのモンスターを攻撃します。武器(掘削道具を含む)を装備していれば、攻撃 をしたときに武器のダメージが追加されます。何も装備していなければ拳骨で パンチをすることになりますが、これがダメージの最小値です(修行僧でプレ @@ -295,9 +295,9 @@ せHPやMPの回復を速めます。 *滅邪*の武器 - 邪悪なモンスターに対して有効で通常の 2 倍のダイスでダメージを与え、 - 周囲の邪悪なモンスターの存在を常に感じとる事ができます。また賢さを - 上昇させ祝福されている場合もあります。 + 邪悪なモンスターに対して有効で通常の 3.5 倍のダイスでダメージを与 + え、周囲の邪悪なモンスターの存在を常に感じとる事ができます。また賢 + さを上昇させ祝福されている場合もあります。 *人喰い*の武器 人間タイプのモンスターに対して有効で通常の 4 倍のダイスでダメージ @@ -386,7 +386,7 @@ りません。(ただし劣化する事はありますし、 *破壊*の効果範囲にまきこまれ れば永久に行方不明になる事でしょう。) - 変愚蛮怒の世界には、固定アーティファクトとランダムアーティファクトと + 馬鹿馬鹿蛮怒の世界には、固定アーティファクトとランダムアーティファクトと いう2種類が存在します。ゲーム上ではこの2種類に区別はありませんが、固 定アーティファクトはあらかじめ性能と名前が決定されている為、何度もゲー ムをすれば、同じ固定アーティファクトに出会う事があります。ランダムアー @@ -418,7 +418,7 @@ ***** === 修行僧の攻撃 === -修行僧と練気術師は他の変愚蛮怒の職業のように武器を使うのでなく、素手で +修行僧と練気術師は他の馬鹿馬鹿蛮怒の職業のように武器を使うのでなく、素手で 攻撃する事を好みます。彼らはレベルがあがると攻撃回数が増え、攻撃の技も だんだん強力になっていきます。高レベルの攻撃は相手を朦朧とさせる可能性 があります。 @@ -463,8 +463,8 @@ Pillardancing (柱ダンス) の隣にきたら、彼を攻撃し、そしてそれから彼と壁を挟んで反対側の位置へ逃 げて再び最初から繰り返しという古典的な戦法です。 -しかし、変愚蛮怒ではこの方法は全く役に立ちません!!! -変愚蛮怒のモンスターは本質的に不規則な速度で動きます。しばらく立ち止って +しかし、馬鹿馬鹿蛮怒ではこの方法は全く役に立ちません!!! +馬鹿馬鹿蛮怒のモンスターは本質的に不規則な速度で動きます。しばらく立ち止って いたかと思うと突然何歩も連続で移動してきてあなたを攻撃する事もあります。 @@ -499,7 +499,7 @@ The Anti-Summoning Corridor (穴熊戦法) Original : (??) and Leon Marrick Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.5.2 +Updated : Bakabakaband 1.5.2 ***** Begin Hyperlinks diff --git a/lib/help/jbirth.txt b/lib/help/jbirth.txt index 81693a402..4dc395053 100644 --- a/lib/help/jbirth.txt +++ b/lib/help/jbirth.txt @@ -328,7 +328,7 @@ lib/user/ にある histedit-<名前>.prf または histedit.prf というファ 赤外線視力は熱源を「見る」能力です。ダンジョンの大部分は涼しい、 もしくは寒いので、赤外線視力では壁やものを見ることはできません。 かわりに、一定距離内にいる温血動物の存在を見ることができます。こ - の能力は光源があろうとなかろうと同様に効果を示します。変愚蛮怒の + の能力は光源があろうとなかろうと同様に効果を示します。馬鹿馬鹿蛮怒の 生物の多くは冷血であり、光源で照らされていなければ見つけられませ ん。多くの非人間型種族は生まれつきこの能力を持っています。人間は 魔法的な方法によってのみこの能力を得ることができます。 @@ -337,7 +337,7 @@ lib/user/ にある histedit-<名前>.prf または histedit.prf というファ ***** === 熟練度(武器、魔法、技能の経験値) === -変愚蛮怒ではキャラクターは個々の武器や魔法それぞれについて異なる熟練度 +馬鹿馬鹿蛮怒ではキャラクターは個々の武器や魔法それぞれについて異なる熟練度 を持ちます。初期の熟練度と熟練度の最大値は職業によって決まっていて、練 習によって経験値を得て熟練度を上昇させる事ができます。現在の熟練度は 「様々な情報を表示する」コマンド('~')で確認できます。 @@ -361,7 +361,7 @@ lib/user/ にある histedit-<名前>.prf または histedit.prf というファ Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.5.2 +Updated : Bakabakaband 1.5.2 ***** [a] jraceclas.hlp diff --git a/lib/help/jbldg.txt b/lib/help/jbldg.txt index afa01ab7d..bb9059fb5 100644 --- a/lib/help/jbldg.txt +++ b/lib/help/jbldg.txt @@ -1,4 +1,4 @@ -=== 変愚蛮怒の街の概要 === +=== 馬鹿馬鹿蛮怒の街の概要 === 街はアイテムを扱う店とその他のサービスを提供する建物からなります。 diff --git a/lib/help/jcommand.hlp b/lib/help/jcommand.hlp index 16954e852..58f54dc08 100644 --- a/lib/help/jcommand.hlp +++ b/lib/help/jcommand.hlp @@ -1,8 +1,8 @@ -Hengband コマンド解説 +Bakabakaband コマンド解説 参照したいオンライン・ヘルプを選んで下さい: - (a) Hengband コマンド概説 (jcommand.txt) + (a) Bakabakaband コマンド概説 (jcommand.txt) (b) オリジナルキー配置 (jcommand.txt#OriginalKeyset) (c) ローグ風キー配置 (jcommand.txt#RogueKeyset) (d) 特殊なキー (jcommand.txt#SpecialKeys) diff --git a/lib/help/jcommand.txt b/lib/help/jcommand.txt index 909fb2488..ffc5d13a6 100644 --- a/lib/help/jcommand.txt +++ b/lib/help/jcommand.txt @@ -1,9 +1,9 @@ -=== 変愚蛮怒 のコマンド ==== +=== 馬鹿馬鹿蛮怒 のコマンド ==== はじめに -変愚蛮怒のコマンドはたいていアルファベットや記号一文字です。始めたばか +馬鹿馬鹿蛮怒のコマンドはたいていアルファベットや記号一文字です。始めたばか りの人はコマンドの文字を覚えるまでには時間がかかるでしょう。しかし、変 愚蛮怒にはほとんど全てのコマンドを統一したコマンドメニューが存在します。 リターンキーを押すとコマンドメニューが出ます。あとはカーソルや10 キー @@ -12,7 +12,7 @@ 「メニューによりコマンド選択を有効にする」(command_menu)です。 -変愚蛮怒のコマンドは、基本となる一文字のキー入力と様々な追加的入力とに +馬鹿馬鹿蛮怒のコマンドは、基本となる一文字のキー入力と様々な追加的入力とに よって構成されます。基本となる一文字のキー入力のキー配置は、「オリジナ ルキー配置」と「ローグ風キー配置」の 2 つの標準的なキー配置のどちらか を選ぶことができます。 @@ -57,7 +57,7 @@ h/j/k/l/y/u/b/n キーを歩く方向を指定するのに使えて、SHIFT/CTRL に合った」アイテムだけです。アイテムに "!*" とか "!x" とかの銘が刻まれ ていると、必ず確認をしてからそのアイテムを選択します。 -変愚蛮怒 にはプレイヤーをランダムにテレポートさせるアイテムが存在し、 +馬鹿馬鹿蛮怒 にはプレイヤーをランダムにテレポートさせるアイテムが存在し、 テレポートするたびに実際にテレポートするか聞いてきます。何度も「テレ ポートしますか?(Y/N)」と聞かれるのは煩わしい場合もあるので、そんな時 はそのアイテムに"."(あるいは"."を含む文字列)という銘を刻むとテレポー @@ -240,7 +240,7 @@ CTRL キーを押さなくても、その機能を実現することは可能で キーでのコマンドがシステムに影響を及ぼしてしまうようなシステムにおいて 便利な機能です。 -"\" を押してからコマンドを押すと、それは 変愚蛮怒 の「内部的キー配置」 +"\" を押してからコマンドを押すと、それは 馬鹿馬鹿蛮怒 の「内部的キー配置」 のコマンドと解釈されます。"\" の後に "^" を押してからコマンドを押す と、それは「内部的キー配置」の CTRL キーとの同時押しのコマンドと解釈さ れます。この"\" キーはマクロの行動を作成するときに大変便利です。という @@ -324,7 +324,7 @@ Updated : (2.7.6) by Russ Allbery (rra@cs.stanford.edu) Updated : (2.7.9) by Ben Harrison (benh@phial.com) Updated : Zangband 2.2.0 through 2.2.6c by Robert Ruehlmann Updated : Zangband DevTeam -Updated : Hengband 1.0.11 +Updated : Bakabakaband 1.0.11 ***** Begin Hyperlinks diff --git a/lib/help/jcommdesc.hlp b/lib/help/jcommdesc.hlp index c2dbd3497..ea8fd6707 100644 --- a/lib/help/jcommdesc.hlp +++ b/lib/help/jcommdesc.hlp @@ -1,4 +1,4 @@ -Hengband コマンド詳説 +Bakabakaband コマンド詳説 参照したいオンライン・ヘルプを選んで下さい: diff --git a/lib/help/jcommdesc.txt b/lib/help/jcommdesc.txt index 1849882ff..efd0ef5a3 100644 --- a/lib/help/jcommdesc.txt +++ b/lib/help/jcommdesc.txt @@ -584,7 +584,7 @@ ある jpref.hlp を見て下さい。 オプションの設定 (=) - オプション設定画面を表示して、そこで変愚蛮怒の動作を変更すること + オプション設定画面を表示して、そこで馬鹿馬鹿蛮怒の動作を変更すること ができます。「詐欺オプション」の扱いには注意して下さい。一度でも このオプションを有効にすると、そのことがセーブファイルに記録され てしまって、ハイスコアリストに載ることが不可能になってしまいま @@ -707,7 +707,7 @@ Updated : (2.7.6) by Russ Allbery (rra@cs.stanford.edu) Updated : (2.7.9) by Ben Harrison (benh@phial.com) Updated : Zangband 2.2.0 through 2.2.6c by Robert Ruehlmann Updated : Zangband DevTeam -Updated : Hengband 1.7.0 +Updated : Bakabakaband 1.7.0 ***** Begin Hyperlinks diff --git a/lib/help/jdefend.txt b/lib/help/jdefend.txt index ab9bc6a2e..36c2a4faf 100644 --- a/lib/help/jdefend.txt +++ b/lib/help/jdefend.txt @@ -1,6 +1,6 @@ === 防御と防具 === -変愚蛮怒では、怪物は様々な手段であなたにダメージを与え、傷つけます。直 +馬鹿馬鹿蛮怒では、怪物は様々な手段であなたにダメージを与え、傷つけます。直 接攻撃、隣接ブロックで爆発、ブレス攻撃、呪文などです。"召喚者"として知 られる連中は、直接攻撃するかわりに他の怪物を召喚し攻撃させます。 @@ -52,7 +52,7 @@ す。二つ目は、アーマークラスが高くなると、通常の攻撃によって与えられた ダメージが減少するということです。三つ目は、体に防具を装備していると酸 によるダメージが減少するということです(代わりにその防具がダメージを受 -けますが)。変愚蛮怒のダンジョンの奥底に足を踏み入れれば踏み入れるほ +けますが)。馬鹿馬鹿蛮怒のダンジョンの奥底に足を踏み入れれば踏み入れるほ ど、生き残るのにより高いアーマークラスが必要とされるのは火を見るより明 らかです。ただしアーマークラスが高くても上で述べた敵の直接攻撃による副 作用を防ぐ助けにはなりません。 @@ -87,7 +87,7 @@ を見つけるなり、他の方法で耐性を得るなりすることが唯一頼れる手段となり ます。 -変愚蛮怒では、色々な耐性があります。これらは装備のボーナスや呪文の効 +馬鹿馬鹿蛮怒では、色々な耐性があります。これらは装備のボーナスや呪文の効 果、アーティファクトの発動、それに突然変異の結果として得ることができま す。残念ながらモンスターの攻撃の種類によってはそれに対する耐性は存在せ ず、また多くの攻撃については完全な耐性というのは存在しません。 @@ -331,7 +331,7 @@ (ただし劣化する事はありますし、 *破壊*の効果範囲にまきこまれれば永久に 行方不明になる事でしょう。) - 変愚蛮怒の世界には、固定アーティファクトとランダムアーティファクトと + 馬鹿馬鹿蛮怒の世界には、固定アーティファクトとランダムアーティファクトと いう2種類が存在します。ゲーム上ではこの2種類に区別はありませんが、固 定アーティファクトはあらかじめ性能と名前が決定されている為、何度もゲー ムをすれば、同じ固定アーティファクトに出会う事があります。ランダムアー @@ -427,7 +427,7 @@ く轟音に対する耐性を持っていれば防ぐことができます。 因果混乱 - 因果混乱攻撃は変愚蛮怒でもっともプレイヤーをいらいらさせる攻撃の一 + 因果混乱攻撃は馬鹿馬鹿蛮怒でもっともプレイヤーをいらいらさせる攻撃の一 つですが、直接プレイヤーを殺すことは稀です。因果混乱攻撃はプレイ ヤーにダメージを与え、同時にテレポートさせたり、レベル・テレポート させたり、2つの主要能力値を置換したりします。因果混乱への耐性はこ @@ -436,7 +436,7 @@ せん(これを防ぐには反テレポート効果を持ったアイテムが必要です)。 カオス - カオスの攻撃は変愚蛮怒でもっとも危険な攻撃の一つです。この攻撃のダ + カオスの攻撃は馬鹿馬鹿蛮怒でもっとも危険な攻撃の一つです。この攻撃のダ メージ量の上限は比較的高く、プレイヤーを混乱させたり、幻覚状態にさ せたり、キャラクタの経験値を減らしたり、変異させたりします。カオス への耐性はこの種の攻撃によるダメージを減少させ、全ての副作用を無効 @@ -537,7 +537,7 @@ ***** === 攻撃からの回復 === -変愚蛮怒 ではモンスターと戦って毎回無傷でいることは望めません。ダメー +馬鹿馬鹿蛮怒 ではモンスターと戦って毎回無傷でいることは望めません。ダメー ジを受けたら一刻も早く回復の手立てを講ずることが必要です。 --- 体力回復用アイテム --- @@ -594,5 +594,5 @@ Original : (??), Leon Marrick and Chris Weisiger Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.0.11 +Updated : Bakabakaband 1.0.11 diff --git a/lib/help/jdungeon.txt b/lib/help/jdungeon.txt index c38f03b55..d26f834b3 100644 --- a/lib/help/jdungeon.txt +++ b/lib/help/jdungeon.txt @@ -1,7 +1,7 @@ === ダンジョン === -変愚蛮怒の広大な地上エリアには複数の街や広い荒野がありますが、冒険の大 +馬鹿馬鹿蛮怒の広大な地上エリアには複数の街や広い荒野がありますが、冒険の大 半の時間はダンジョン内部で過ごすことになるでしょう。画面上にある記号は ダンジョンの壁、床、アイテム、地形、そしてダンジョンをうろつくモンスター です。自分のキャラクターに命令を与えるには、キーを一文字押すだけです @@ -125,7 +125,7 @@ この巻物を読んで効果が現れる前に、もう一度この巻物を読むと、その両方の 効果が打ち消し合って無効化されます(テレポートは実行されません)。 -変愚蛮怒のアイテムに関するより完全な解説は他の文章(jobjects.txt[c]を参 +馬鹿馬鹿蛮怒のアイテムに関するより完全な解説は他の文章(jobjects.txt[c]を参 照)にあります。 @@ -181,7 +181,7 @@ "<" は上り階段を表し、">" は下り階段を表します。階段を使用するためには、 まず階段の上にキャラクターを移動させなければなりません。 -変愚蛮怒では階段は階層をひとつだけ移動し、坑道は階層を2つ移動します。 +馬鹿馬鹿蛮怒では階段は階層をひとつだけ移動し、坑道は階層を2つ移動します。 どの階にも、少なくても一つの上り階段と二つの下り階段があります。上手に 隠されたドアを見つけるのは大変なことかもしれませんし、時には階段を見つ @@ -219,7 +219,7 @@ 別」なアイテム(jobjects.txt を参照))です。雰囲気はその階に立ち入った時 のもので、その後に生成されたモンスターやアイテムでは変化しません。 -変愚蛮怒では雰囲気がひどいほど良い階になっています。つまらない階から順 +馬鹿馬鹿蛮怒では雰囲気がひどいほど良い階になっています。つまらない階から順 に以下のようになります: 「なんて退屈なところだ...」 @@ -247,7 +247,7 @@ 「素晴らしい感じがする...」 「この階はこの上なく素晴らしい感じがする。」 -変愚蛮怒にはこの他にも2つの特殊な雰囲気があります。その階にまだ雰囲 +馬鹿馬鹿蛮怒にはこの他にも2つの特殊な雰囲気があります。その階にまだ雰囲 気を感じるだけ長く居るわけでないときに 'CTRL-F'コマンドを使った時、以 下のような文が表示されます: @@ -292,7 +292,7 @@ Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.0.11 +Updated : Bakabakaband 1.0.11 ***** Begin Hyperlinks ***** [b] jcommand.txt diff --git a/lib/help/jeditor.txt b/lib/help/jeditor.txt index 1ce8da845..c547cdbc7 100644 --- a/lib/help/jeditor.txt +++ b/lib/help/jeditor.txt @@ -89,7 +89,7 @@ 事を確認してから「[[[[o|^X|」でカットするなり、「[[[[o|^C|」でコピーするなりしてくだ さい。 -ただし、変愚蛮怒の使用環境によってはうまくシフト+カーソルを認識できな +ただし、馬鹿馬鹿蛮怒の使用環境によってはうまくシフト+カーソルを認識できな いかもしれません。その場合は「[[[[o|^G|」を押した後でカーソルを移動する事で選 択範囲を指定できます。 @@ -376,7 +376,7 @@ [[[[G|==== 自動拾い/破壊設定の書式仕様 ==== ユーザーディレクトリに"picktype.prf"又は "picktype-<名前>.prf" という -ファイルを作って各行にアイテムの名前を書くと、変愚蛮怒にそのアイテムを +ファイルを作って各行にアイテムの名前を書くと、馬鹿馬鹿蛮怒にそのアイテムを 自動的に拾ったり破壊するように指示する事ができます。 この設定ファイルは以下のタイミングで読み込まれます。 @@ -581,10 +581,10 @@ $MONEY --- ファイルの挿入の書式 --- %:ファイル名 - 「lib\user\ファイル名」 か 「~/.angband/Hengband/ファイル名」 を自 + 「lib\user\ファイル名」 か 「~/.angband/Bakabakaband/ファイル名」 を自 動拾いの登録ファイルとして読み込みます。 -- -Updated : Hengband 1.7.0 +Updated : Bakabakaband 1.7.0 diff --git a/lib/help/jgeneral.hlp b/lib/help/jgeneral.hlp index ce3707c8c..e78f785fb 100644 --- a/lib/help/jgeneral.hlp +++ b/lib/help/jgeneral.hlp @@ -1,4 +1,4 @@ -変愚蛮怒の全般的な情報 +馬鹿馬鹿蛮怒の全般的な情報 参照したいオンライン・ヘルプの記号を押して下さい: @@ -6,7 +6,7 @@ (b) はじめに行くべき所 (jgeneral.txt#First) (c) 勝利 (jgeneral.txt#Winning) (d) 死について (jgeneral.txt#UponDeath) - (e) WEB上の 変愚蛮怒 サイト (jgeneral.txt#Web) + (e) WEB上の 馬鹿馬鹿蛮怒 サイト (jgeneral.txt#Web) (f) バージョン履歴 (jversion.txt) (g) 著作権と使用許諾について (jlicense.txt) diff --git a/lib/help/jgeneral.txt b/lib/help/jgeneral.txt index 0a4dfaf20..461c1acfd 100644 --- a/lib/help/jgeneral.txt +++ b/lib/help/jgeneral.txt @@ -1,10 +1,10 @@ === 全般的な情報 === -この文章では 変愚蛮怒 を手短に紹介します。本格的な冒険を始める前に、全 +この文章では 馬鹿馬鹿蛮怒 を手短に紹介します。本格的な冒険を始める前に、全 てのヘルプファイル、特にコマンド関係(jcommand.txt [b] と jcommdesc.txt [c]を参照)に目を通しておいた方がいいでしょう。 -変愚蛮怒 というゲームは一人用のダンジョン・シミュレーターです。プレイ +馬鹿馬鹿蛮怒 というゲームは一人用のダンジョン・シミュレーターです。プレイ ヤーは様々な種族や職業、魔法領域(jbirth.txt [d]を参照)を選択して自 分のキャラクターを作成し、そのキャラクターを操作してダンジョンの中を数 日、いや数週間、いや数カ月の間冒険をすることになるでしょう。ダンジョン @@ -95,27 +95,27 @@ ***** -=== WEB上の変愚蛮怒サイト === +=== WEB上の馬鹿馬鹿蛮怒サイト === ---- http://hengband.sourceforge.jp/ --- +--- http://Bakabakaband.sourceforge.jp/ --- -http://hengband.sourceforge.jp/ は 変愚蛮怒の公式サイトです。ここには +http://Bakabakaband.sourceforge.jp/ は 馬鹿馬鹿蛮怒の公式サイトです。ここには 最新のソースコードやバイナリ、スポイラーへのリンク、また役に立つページ や面白いページへのリンクがあります。また英語版のページへのリンクもあり ます。 ---- http://hengband.sourceforge.jp/score.html +--- http://Bakabakaband.sourceforge.jp/score.html -上記の変愚蛮怒の公式サイトの中にリンクがありますが、ここがスコアサーバ +上記の馬鹿馬鹿蛮怒の公式サイトの中にリンクがありますが、ここがスコアサーバ に登録された何百ものスコアダンプを公開したページです。 --- http://6904.teacup.com/combatechizen/bbs --- -http://6904.teacup.com/combatechizen/bbs は変愚蛮怒について様々な質問 +http://6904.teacup.com/combatechizen/bbs は馬鹿馬鹿蛮怒について様々な質問 や提案ができる掲示板です。何かわからない事があったらここで質問してくだ さい。ただし、最低限 readme.txt は全て読んでおいてください。できれば、 -掲示板の過去ログ http://hengband.sourceforge.jp/x/log-all.html.gz や +掲示板の過去ログ http://Bakabakaband.sourceforge.jp/x/log-all.html.gz や autopick.txt の内容も読んでおくと良いでしょう。 あなたが必要としている情報はきっと何度も誰かが既に聞いていて、何度も繰 @@ -125,7 +125,7 @@ autopick.txt の内容も読んでおくと良いでしょう。 --- #ぐりっどばぐ:*.jp IRC チャンネル --- IRCnet のどれかのサーバーの #ぐりっどばぐ:*.jp チャンネルに参加しましょ -う。開発にかかわるメンバーはここの常連で、変愚蛮怒 について語り合ってい +う。開発にかかわるメンバーはここの常連で、馬鹿馬鹿蛮怒 について語り合ってい ることもあります。 詳しくはHabuさんのWebページを御覧ください。 http://www.kmc.gr.jp/~habu/gridbug.html @@ -135,7 +135,7 @@ http://www.kmc.gr.jp/~habu/gridbug.html Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.5.0 +Updated : Bakabakaband 1.5.0 ***** Begin Hyperlinks diff --git a/lib/help/jhelp.hlp b/lib/help/jhelp.hlp index fa3616144..3ae3f25ee 100644 --- a/lib/help/jhelp.hlp +++ b/lib/help/jhelp.hlp @@ -1,4 +1,4 @@ -[ 変愚蛮怒・オンライン・ヘルプ・システムへようこそ ] +[ 馬鹿馬鹿蛮怒・オンライン・ヘルプ・システムへようこそ ] 参照したいヘルプの記号を押して下さい: (a)全体的な情報 (jgeneral.hlp) (o)追加情報 (jspecial.hlp) diff --git a/lib/help/jhelpinfo.txt b/lib/help/jhelpinfo.txt index e2ff22ba8..bedc9cb9d 100644 --- a/lib/help/jhelpinfo.txt +++ b/lib/help/jhelpinfo.txt @@ -17,7 +17,7 @@ [[[[y]「|」キー] (現在のファイル内容を保存) -- -Updated : Hengband 1.7.0 +Updated : Bakabakaband 1.7.0 ***** [j] jmonster.txt#Pets diff --git a/lib/help/jlicense.txt b/lib/help/jlicense.txt index 7e2a39e52..b52e92f95 100644 --- a/lib/help/jlicense.txt +++ b/lib/help/jlicense.txt @@ -1,5 +1,5 @@ ********************************************************************** - 変愚蛮怒の著作権と使用許諾について + 馬鹿馬鹿蛮怒の著作権と使用許諾について ********************************************************************** @@ -7,7 +7,7 @@ 著作権について -------------- - 変愚蛮怒の、日本語版アングバンドおよび日本語版 Zangbandよりの変 + 馬鹿馬鹿蛮怒の、日本語版アングバンドおよび日本語版 Zangbandよりの変 更部分については以下の者が代表して著作権を有します。 Mr.hoge Email: echizenï¼ users.spamblock.sourceforge.jp @@ -53,7 +53,7 @@ 使用許諾 -------- -変愚蛮怒は、ベースである Angband や ZAngband と同様に以下の +馬鹿馬鹿蛮怒は、ベースである Angband や ZAngband と同様に以下の Moria/Angband使用許諾に従って配布されています。 Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke @@ -70,7 +70,7 @@ are included in all such copies. Other copyrights may also apply. 権が別に適用される事について補足したものかと思われます。) -変愚蛮怒に変更を加えたプログラムか、または変愚蛮怒のプログラムの一部を +馬鹿馬鹿蛮怒に変更を加えたプログラムか、または馬鹿馬鹿蛮怒のプログラムの一部を 含む別のプログラムを配布する場合は、Moria/Angband使用許諾に加えて以下 の条項を満たす場合のみ配布を許可します。ここで変更とは配布されるアーカ イブに含まれる個々のファイルの変更及びファイルの追加・削除を指します。 @@ -79,15 +79,15 @@ are included in all such copies. Other copyrights may also apply. (2) 変更を加えた事実及び変更内容について明確に記載する事。 - (3) 変愚蛮怒のスコアサーバーにスコアを送信できないように必要な変更を + (3) 馬鹿馬鹿蛮怒のスコアサーバーにスコアを送信できないように必要な変更を 加える事。(スコア送信機能を無効にするか、送信先サーバーの場所を - 変える、等の方法で) ただし、全ての変更が変愚蛮怒のゲーム内容自体 + 変える、等の方法で) ただし、全ての変更が馬鹿馬鹿蛮怒のゲーム内容自体 に全く影響を与えない場合はこの条項は適用されない物とします。 上述の使用許諾表記は Angband の dual license (後述)によって GPL のみに 従って配布される可能性を排除するものではありません。現在は GPL に従っ -て変愚蛮怒を配布する事は不可能ですが、将来的にそれが可能になった時は +て馬鹿馬鹿蛮怒を配布する事は不可能ですが、将来的にそれが可能になった時は GPL によって配布を受けた者は上述の使用許諾表示に従う義務はありません。 diff --git a/lib/help/jmagic.hlp b/lib/help/jmagic.hlp index fe22393d5..76378a568 100644 --- a/lib/help/jmagic.hlp +++ b/lib/help/jmagic.hlp @@ -1,8 +1,8 @@ -変愚蛮怒の魔法システム +馬鹿馬鹿蛮怒の魔法システム 参照したいオンライン・ヘルプの記号を押して下さい: - (a) 変愚蛮怒の魔法システム (jmagic.txt) + (a) 馬鹿馬鹿蛮怒の魔法システム (jmagic.txt) (b) 職業別魔法使用能力 (jmagic.txt#ClassSpellAbil) (c) 魔法の領域 (jmagic.txt#MagicRealms) (d) 呪文の使用 (jmagic.txt#CastingSpells) diff --git a/lib/help/jmagic.txt b/lib/help/jmagic.txt index 23e63bd10..7eb97222f 100644 --- a/lib/help/jmagic.txt +++ b/lib/help/jmagic.txt @@ -1,6 +1,6 @@ -=== 変愚蛮怒の魔法システム === +=== 馬鹿馬鹿蛮怒の魔法システム === -変愚蛮怒でプレイヤーが用いることのできる魔法は ZAngband の魔法システム +馬鹿馬鹿蛮怒でプレイヤーが用いることのできる魔法は ZAngband の魔法システム を改良し、新しい要素を沢山加えたものです。魔法は大きく分けて2種類があ り、多くの職業に共通する魔法書を使う魔法と、魔法書を使わない職業特有の 魔法(能力) があります。全ての魔法は'm'コマンドで使用する事ができます。 @@ -161,7 +161,7 @@ ***** --- 匠 --- - 匠の魔法は変愚蛮怒オリジナルの領域で、攻撃力や防御力、スピード等、 + 匠の魔法は馬鹿馬鹿蛮怒オリジナルの領域で、攻撃力や防御力、スピード等、 身体能力を増強する魔法が充実しています。回復力強化や壁抜けは匠の 領域特有の魔法で、レベルが低いわりに強力です。匠には感知やテレポー トの魔法がありませんが、一時的なテレパシー能力を得る魔法がありま @@ -169,7 +169,7 @@ ***** --- 悪魔 --- - 悪魔の魔法は変愚蛮怒オリジナルの領域で、カオス同様攻撃力にすぐれ、 + 悪魔の魔法は馬鹿馬鹿蛮怒オリジナルの領域で、カオス同様攻撃力にすぐれ、 炎や地獄の属性を持った攻撃魔法が充実しています。感知魔法はほとん どありませんが、周辺の地形を感知したり、一時的なテレパシーを得た りすることができます。この領域には一時的な変身系の魔法があり、悪 @@ -296,7 +296,7 @@ Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.7.2 +Updated : Bakabakaband 1.7.2 ***** [a] jraceclas.txt#TheClasses diff --git a/lib/help/jmonster.hlp b/lib/help/jmonster.hlp index 56c677a3f..545d9bdcb 100644 --- a/lib/help/jmonster.hlp +++ b/lib/help/jmonster.hlp @@ -1,8 +1,8 @@ -変愚蛮怒のモンスター +馬鹿馬鹿蛮怒のモンスター 参照したいオンライン・ヘルプの記号を押して下さい: - (a) 変愚蛮怒のモンスター (jmonster.txt) + (a) 馬鹿馬鹿蛮怒のモンスター (jmonster.txt) (b) モンスターの記号 (jmonster.txt#MonsterSymbols) (c) モンスターの色 (jmonster.txt#MonsterColors) (d) モンスターの思い出 (jmonster.txt#MonsterMemory) diff --git a/lib/help/jmonster.txt b/lib/help/jmonster.txt index 92e504af1..f4dce40d9 100644 --- a/lib/help/jmonster.txt +++ b/lib/help/jmonster.txt @@ -1,6 +1,6 @@ -=== 変愚蛮怒 のモンスター === +=== 馬鹿馬鹿蛮怒 のモンスター === -変愚蛮怒には1000を超える種類のモンスターがいて、それそれが独自のチャレ +馬鹿馬鹿蛮怒には1000を超える種類のモンスターがいて、それそれが独自のチャレ ンジを冒険者に提供してくれます。ダンジョンに奥深く潜るほどモンスターは ますます倒すのが困難になっていきます。 @@ -63,7 +63,7 @@ ***** === モンスターの思い出 === -様々な種の能力を覚えておくのは非常に困難ですが、変愚蛮怒では各々の怪物 +様々な種の能力を覚えておくのは非常に困難ですが、馬鹿馬鹿蛮怒では各々の怪物 に関してあなたが経験したことを自動的に記録します。 これはモンスターの思い出と呼ばれます。思い出にはその生物(生物でなくて @@ -88,7 +88,7 @@ ***** === ユニークモンスター === -変愚蛮怒には通常のモンスターとユニーク(唯一の)モンスターと呼ばれる種類 +馬鹿馬鹿蛮怒には通常のモンスターとユニーク(唯一の)モンスターと呼ばれる種類 のモンスターがいます。通常のモンスターゲーム中で何度も出てくるのに対し、 ユニークモンスターは一度倒すと二度と生成されません。また同時に二体出現 することもありません。 @@ -129,7 +129,7 @@ ***** === 正気度チェック === -変愚蛮怒のいくつかのモンスターは人知を遥かに越えた恐ろしい姿をしており、 +馬鹿馬鹿蛮怒のいくつかのモンスターは人知を遥かに越えた恐ろしい姿をしており、 直接そのモンスターを見たり魔法的な方法で感知したりすると正気を失い深刻 な影響をうけることがあります。たとえば知能や賢さが一時的あるいは恒久的 に下がる、混乱するなどです。最悪の場合凶暴化の発作、パラノイア、精神薄 @@ -139,21 +139,21 @@ ***** === ペット === -変愚蛮怒のペットは非常に役に立ち、また安全です。あなたのペットであるヘ +馬鹿馬鹿蛮怒のペットは非常に役に立ち、また安全です。あなたのペットであるヘ ル・ワイアームをトロルの巣に送り込み、外で恐怖と苦痛の叫び声、内臓が撒 き散らされる音や骨が砕ける音を聞きながら待つというのは面倒がなく、とて も楽です。しかし、このような戦闘では経験値や戦利品を得ることを期待して はいけません。経験値や戦利品は、自分自身の手で葬り去った怪物の分だけが 得られるのです。 -ペットに止めを刺されたモンスターがアイテムを落とさないという変愚蛮怒の +ペットに止めを刺されたモンスターがアイテムを落とさないという馬鹿馬鹿蛮怒の 独特の仕様は熟慮の結果として定められたものです。無理矢理解釈しようとす れば、ペットが乱暴に攻撃するためにアイテムが行方不明になったり破壊され ているのだと考える事もできますが、現実的ではないと言って不満を言う人は 多いでしょう。この点については現実性よりもゲームバランスを優先して仕様 を定めてあります。 -変愚蛮怒ではペットを間違って攻撃してしまっても彼らは怒りだしたりはしま +馬鹿馬鹿蛮怒ではペットを間違って攻撃してしまっても彼らは怒りだしたりはしま せん。あなたは魔法的な手段によってペットの自由意志を完全に掌握している のです。また、ペットが他のモンスターにたいしてブレス攻撃や魔法の攻撃を しているとき、通常はあなたを巻き込んで被害を与える事はしません。あなた @@ -274,7 +274,7 @@ --- ペットへの乗馬 --- -変愚蛮怒では馬型やドラゴン型のペットには乗馬する事ができます。乗馬する +馬鹿馬鹿蛮怒では馬型やドラゴン型のペットには乗馬する事ができます。乗馬する ためには片手を乗馬のコントロールの為に空けておかなければなりませんが、 乗馬中のペットはもちろんあなたの敵を一緒に攻撃しますし、敵の攻撃はあな た自身と乗馬とに分散するので、あなたの被害は少なくなるでしょう。 @@ -314,7 +314,7 @@ Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.7.0 +Updated : Bakabakaband 1.7.0 ***** Begin Hyperlinks diff --git a/lib/help/jobjects.hlp b/lib/help/jobjects.hlp index 23f93c56e..e880b35fb 100644 --- a/lib/help/jobjects.hlp +++ b/lib/help/jobjects.hlp @@ -1,8 +1,8 @@ -変愚蛮怒のアイテム +馬鹿馬鹿蛮怒のアイテム 参照したいオンライン・ヘルプの記号を押して下さい: - (a) 変愚蛮怒のアイテム (jobjects.txt) + (a) 馬鹿馬鹿蛮怒のアイテム (jobjects.txt) (b) アイテムの記号 (jobjects.txt#ObjectSymbols) (c) 装備と持ち物 (jobjects.txt#EquipInvent) (d) アイテムの生成 (jobjects.txt#Generation) diff --git a/lib/help/jobjects.txt b/lib/help/jobjects.txt index e32de98b4..30bb1e405 100644 --- a/lib/help/jobjects.txt +++ b/lib/help/jobjects.txt @@ -1,6 +1,6 @@ -=== 変愚蛮怒のアイテム === +=== 馬鹿馬鹿蛮怒のアイテム === -変愚蛮怒のダンジョンにはアイテムが沢山あり、またモンスターもアイテム +馬鹿馬鹿蛮怒のダンジョンにはアイテムが沢山あり、またモンスターもアイテム を持っているので、倒すことができればその死体からアイテムを拾うことがで きるでしょう。オプションの設定によりアイテムの上に行くだけで拾うこと も、拾う前に確認することもできます(joption.txt#UserInterface [b]を参 @@ -67,7 +67,7 @@ ***** === アイテムの生成 === -変愚蛮怒ではアイテムはダンジョンに入った時生成されダンジョンの床にば +馬鹿馬鹿蛮怒ではアイテムはダンジョンに入った時生成されダンジョンの床にば らまかれます。またモンスターを倒した時も生成されます(モンスターがアイ テムを持ち運べる場合)。各アイテムには標準の深さ、つまりそのダンジョン の深さになると普通に現れ始めるという深さが設定されています。標準の深さ @@ -94,7 +94,7 @@ ***** === アイテム圧縮 === -変愚蛮怒は大量のアイテムを記憶できますが、無限ではありません。もしモ +馬鹿馬鹿蛮怒は大量のアイテムを記憶できますが、無限ではありません。もしモ ンスターを倒して生成されたアイテムと既に存在するアイテムの合計が限界を 越えたならば、「アイテム情報を圧縮しています」というメッセージが出ま す。 @@ -185,7 +185,7 @@ ターでは同じ「暗青色の薬」でも全く違う薬になるでしょう。つまり各ゲーム ごとにそのアイテムがなんなのか調べないといけない、ということです。 -変愚蛮怒のオプションには「簡略」なアイテムの表記を行なうオプションが +馬鹿馬鹿蛮怒のオプションには「簡略」なアイテムの表記を行なうオプションが あり、これを使うと既に効果が分かったアイテムには見かけの特徴をつけませ ん。例えば上の例だと、鑑定した後は「ヒーローの薬」と表示されます。 @@ -302,7 +302,7 @@ エゴアイテムの防具については、jdefend.txt#EgoArtifact [h]を参照してください。 (今、'6'や'7'を押すと移動します。読んだらESCで戻ります。) -変愚蛮怒のあらゆるアイテムの中で、最も重要なのはアーティファクトです。 +馬鹿馬鹿蛮怒のあらゆるアイテムの中で、最も重要なのはアーティファクトです。 これらは世界に一つしか存在せず、いくつかの能力値を上昇させたり維持した り、耐性や各技能へのボーナスを与えてくれます。またアーティファクトの一 部は発動 'A'ctivate することにより魔法の効果を発揮します。これは特に魔 @@ -432,7 +432,7 @@ れます。また店で安売りされていた(つまり多少難があるかもしれない)アイテ ムには、割り引き率が「25%引き」のように付けられます。 -それらに加え、変愚蛮怒ではキャラクターがアイテムに対して感じた品質に関 +それらに加え、馬鹿馬鹿蛮怒ではキャラクターがアイテムに対して感じた品質に関 する「印象」をしばしばアイテムに銘として刻みます。全てのキャラクターは 特定のアイテムをしばらく所持することでそのアイテムに対する「印象」を得 ます。 @@ -440,11 +440,11 @@ --- 役に立つ銘 --- 銘を刻む機能を、アイテムをどこでどうやって拾ったかを記録するためやアイ -テムの持つ特性を示すために使っているプレイヤーもいます。変愚蛮怒はあな +テムの持つ特性を示すために使っているプレイヤーもいます。馬鹿馬鹿蛮怒はあな たのためにアイテムの特性を自動的に調べて銘を刻む機能があります。 また、このような使い方に加え、刻まれた銘自体に特別の意味を持つものがあ -ります。変愚蛮怒の多くのコマンドは持ち物などのアイテムを指定して実行し +ります。馬鹿馬鹿蛮怒の多くのコマンドは持ち物などのアイテムを指定して実行し ます。例えば薬を飲む('q')コマンドはどの薬を飲むか、杖を使う('u') コマンドはどの杖を使うかを指定して実行します。銘はこのような場合 の労力を省く強力なツールとなります。 @@ -820,7 +820,7 @@ Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.3.0 +Updated : Bakabakaband 1.3.0 ***** Begin Hyperlinks diff --git a/lib/help/joption.hlp b/lib/help/joption.hlp index f28cdc154..107c35ae0 100644 --- a/lib/help/joption.hlp +++ b/lib/help/joption.hlp @@ -1,8 +1,8 @@ -変愚蛮怒オプション +馬鹿馬鹿蛮怒オプション 参照したいオンライン・ヘルプを選んで下さい: - (a) 変愚蛮怒 オプション一覧 (joption.txt) + (a) 馬鹿馬鹿蛮怒 オプション一覧 (joption.txt) (b) オプション1 -- キー入力 (joption.txt#Input) (c) オプション2 -- マップ画面 (joption.txt#MapScreen) (d) オプション3 -- テキスト表示 (joption.txt#TextDisplay) diff --git a/lib/help/joption.txt b/lib/help/joption.txt index 49388a5e2..bb24b29d3 100644 --- a/lib/help/joption.txt +++ b/lib/help/joption.txt @@ -302,7 +302,7 @@ MPが足りなくても魔法に挑戦する [over_exert] ***** アイテムの記述を簡略にする [plain_descriptions] - 変愚蛮怒では、このオプションをONにすることで識別済みの「色」を持っ + 馬鹿馬鹿蛮怒では、このオプションをONにすることで識別済みの「色」を持っ たオブジェクトのフルネームを表示しないようになります。言い換えれば、 もしこのオプションがOFFであれば、識別したスピードの薬は(例えば) 灰色のスピードの薬と表示されます。あなたがシンプルな表示を好み、冗 @@ -458,7 +458,7 @@ MPが足りなくても魔法に挑戦する [over_exert] ***** スコアサーバにスコアを送る [send_score] - 変愚蛮怒はインターネットを通じてあなたの死亡スコアや引退スコアを、 + 馬鹿馬鹿蛮怒はインターネットを通じてあなたの死亡スコアや引退スコアを、 スコアサーバーに登録する事ができます。登録をしたいときはこのオプショ ンを有効にしてください。 @@ -782,7 +782,7 @@ cheatingオプションを使うと、キャラクタは'cheater'であると見 === 初期オプション === -以下のオプションは変愚蛮怒を難しくしたり簡単にしたりします。初期オプショ +以下のオプションは馬鹿馬鹿蛮怒を難しくしたり簡単にしたりします。初期オプショ ンはキャラクタ生成時にのみ、'='キーを押すことによって設定できます('=' を押さなくても一度は必ずオプション設定画面に入ります)。その後はオプショ ンを変更することはできません。 @@ -911,6 +911,6 @@ Original : Ben Harrison Updated : Zangband 2.1.* by Topi Ylinen Updated : Zangband 2.2.0 through 2.2.6c by Robert Ruehlmann Updated : Zangband DevTeam -Updated : Hengband 1.7.0 +Updated : Bakabakaband 1.7.0 ***** [a] jpref.txt#Options diff --git a/lib/help/jpref.txt b/lib/help/jpref.txt index 3ca73bfb0..f6f6b2f3e 100644 --- a/lib/help/jpref.txt +++ b/lib/help/jpref.txt @@ -1,6 +1,6 @@ === ユーザー設定ファイル === -変愚蛮怒ではゲームの様々な点を自分好みに変更することが出来ます。設定ファ +馬鹿馬鹿蛮怒ではゲームの様々な点を自分好みに変更することが出来ます。設定ファ イルを書き変える事で、キー配置を変更すること(押されたキーに対応する内 部的キー配置の割り当てを変更します)、マクロを作成すること(一つのキーに 一連の複数のキーを押す手順を記憶させます)、画面表示を変更すること(モン @@ -9,15 +9,15 @@ オプションを設定すること(その機能をオン・オフします)、及びアイテムの自 動拾いと自動破壊を設定する事ができます。 -変愚蛮怒ではユーザーの変更した様々な情報を「ユーザー設定ファイル(user +馬鹿馬鹿蛮怒ではユーザーの変更した様々な情報を「ユーザー設定ファイル(user pref file)」と呼ばれるファイルに保存します。そのファイルはコメントと、 簡単な設定変更のコマンドで構成されています。ユーザー設定ファイルを読み 込む方法は色々とありますし、自動的に読み込まれるものもあります。 -変愚蛮怒にもともと用意された設定ファイルは「lib/pref/」ディレクトリに +馬鹿馬鹿蛮怒にもともと用意された設定ファイルは「lib/pref/」ディレクトリに 入っています。ユーザーの設定を保存したりユーザー自身が書く設定ファイル は、「ユーザーディレクトリ」に保管されます。これは標準の設定でコンパイ -ルされた場合ならば、 Unix の場合は ~/.angband/Hengband/ その他の機種の +ルされた場合ならば、 Unix の場合は ~/.angband/Bakabakaband/ その他の機種の 場合は、lib/user/ の下になります。また設定変更コマンド (") を使って、 普通はファイルに書いている設定変更のコマンドをゲーム上で直接打ち込むこ ともできます。ゲームの画面に影響する設定を変更したならば、画面描き直し @@ -57,7 +57,7 @@ pref file)」と呼ばれるファイルに保存します。そのファイル 設定ファイルを読み込んだり、新しいユーザー設定ファイルを作成したり、現 存するユーザー設定ファイルに情報を上書きしたりもできます。 -変愚蛮怒では現存するユーザー設定ファイルに情報を上書きするときに古い設 +馬鹿馬鹿蛮怒では現存するユーザー設定ファイルに情報を上書きするときに古い設 定行は削除してくれます。つまり追加書き込みを繰り返してファイルがどんど ん巨大に膨れ上る心配はありません。ぞんぶんに書き込みましょう。 @@ -66,7 +66,7 @@ pref file)」と呼ばれるファイルに保存します。そのファイル === ユーザー設定ファイルのコマンド === オプションの設定 (=) - オプション設定画面を表示して、そこで変愚蛮怒の動作を変更すること + オプション設定画面を表示して、そこで馬鹿馬鹿蛮怒の動作を変更すること ができます。「詐欺オプション」の扱いには注意して下さい。一度でも このオプションを有効にすると、そのことがセーブファイルに記録され てしまって、ハイスコアリストに載ることが不可能になってしまいま @@ -251,4 +251,4 @@ Updated : (2.7.6) by Russ Allbery (rra@cs.stanford.edu) Updated : (2.7.9) by Ben Harrison (benh@phial.com) Updated : Zangband 2.2.0 through 2.2.6c by Robert Ruehlmann Updated : Zangband DevTeam -Updated : Hengband 1.7.0 +Updated : Bakabakaband 1.7.0 diff --git a/lib/help/jraceclas.txt b/lib/help/jraceclas.txt index da5c44536..dde42dea8 100644 --- a/lib/help/jraceclas.txt +++ b/lib/help/jraceclas.txt @@ -1,6 +1,6 @@ === 種族、職業、性格 === -このファイルには変愚蛮怒でプレイヤーが選ぶ事のできる種族、職業、性格に +このファイルには馬鹿馬鹿蛮怒でプレイヤーが選ぶ事のできる種族、職業、性格に ついて説明しています。ファイルの最後には種族、職業、性格それぞれの能力 値と技能への修正値の表があります。 @@ -8,7 +8,7 @@ ***** === 種族 === -変愚蛮怒には選択可能な37種の種族が存在しています。各々の種族は様々な +馬鹿馬鹿蛮怒には選択可能な37種の種族が存在しています。各々の種族は様々な 長所や短所があり、それぞれに能力値や特性に対する修正が存在します。多く の種族は生まれ持っての特性や力も持っています。 @@ -417,7 +417,7 @@ ***** === 職業 === -変愚蛮怒には27の職業があり、各々に長所と短所およびキャラクターの能 +馬鹿馬鹿蛮怒には27の職業があり、各々に長所と短所およびキャラクターの能 力への補正があります。多くの職業にはまた固有の能力があります。それらは 往々にしてレベルに依存し、ゲーム後半にならないと使えないものもありま す。 @@ -447,7 +447,7 @@ メイジは領域の選択にあたって最も制約が少ない職業で、キャラクター作 成時に自由に2つの領域を選択できます。生命の魔法はプリースト程得意 ではありませんが、それを除けばメイジは非常に上手に呪文を使えます。 - 変愚蛮怒では2つの領域を選べる事は特別な価値があります。そのような + 馬鹿馬鹿蛮怒では2つの領域を選べる事は特別な価値があります。そのような 職業はキャラクター作成時だけでなく冒険中に第二の領域を変更できるか らです。変更したい時は新しい領域の魔法書から呪文を覚える操作('G'コ マンド)をします。ただし、呪文を学習できる数は復活しないのでむやみ @@ -659,7 +659,7 @@ ***** --- 魔獣使い --- - 魔獣使いは変愚蛮怒世界のダンジョンに住む生物と心を通い合わせられま + 魔獣使いは馬鹿馬鹿蛮怒世界のダンジョンに住む生物と心を通い合わせられま す。彼らは最もうまくモンスターを乗りこなすことができ、召喚したり手 なづけたりしたモンスターを自分の手足のように使います。魔法に必要な 能力は魅力です。 @@ -928,7 +928,7 @@ ***** === 性格 === -変愚蛮怒には12の性格があります。それぞれの性格によって、キャラクター +馬鹿馬鹿蛮怒には12の性格があります。それぞれの性格によって、キャラクター の能力値や技能にボーナスやペナルティーを受けます。 ***** @@ -1233,4 +1233,4 @@ 到達したときには -5 + 40/50 * (-5) で -9 になります。 -- -Updated : Hengband 1.7.2 +Updated : Bakabakaband 1.7.2 diff --git a/lib/help/jtang.txt b/lib/help/jtang.txt index a7fcc866e..0655df285 100644 --- a/lib/help/jtang.txt +++ b/lib/help/jtang.txt @@ -1,4 +1,4 @@ -=== 変愚蛮怒初心者ガイド === +=== 馬鹿馬鹿蛮怒初心者ガイド === === 基本的なトレーニング === @@ -12,7 +12,7 @@ 種族や職業に関する基本的な情報を得たいなら、オンラインヘルプコマンド ("?"キー) を使い、「キャラクター作成」「種族、職業、性格」の項目を参照 してください。それ以外の項目についてもなるべく早いうちに目を通しておく -べきです。特に新しく変愚蛮怒をプレイする人にとっては、「コマンドの解説」 +べきです。特に新しく馬鹿馬鹿蛮怒をプレイする人にとっては、「コマンドの解説」 は特に重要です。 キャラクタに名前をつけたら、「辺境の地」という町の入口からゲームは始ま @@ -59,7 +59,7 @@ のが現状で売られていなければ、店の品物が入れ替わるのを待つこともできま す。 -変愚蛮怒は実際のところ、プレイの仕方を学ぶのはそれほど難しくありません。 +馬鹿馬鹿蛮怒は実際のところ、プレイの仕方を学ぶのはそれほど難しくありません。 あなたはその扱い方をかなり早く覚えることができるでしょう。 ここからは、ダンジョンで生き残る為の細かな情報を提供しようと思います。 @@ -194,7 +194,7 @@ === 耐性について === -変愚蛮怒には、様々な種類の攻撃があり、物理的攻撃、魔法攻撃、ブレス攻撃 +馬鹿馬鹿蛮怒には、様々な種類の攻撃があり、物理的攻撃、魔法攻撃、ブレス攻撃 にわけられます。これらは、もしキャラクタが耐性を持っていなければそのキャ ラクタを殺してしまいかねない特別なダメージを引き起こします。様々な攻撃 が、それに対応する耐性を持っています。これらは大きくわけて、"低級な" @@ -404,7 +404,7 @@ XdY. これは武器の基本ダメージです。もし攻撃が命中すると 矢 (1d5) (+0,+0) (16/32) -始めの数値は一回の射撃あたりの平均ダメージで、次の数値は1ターンあたり +始めの数値は一回の射撃あたりの平均ダメージで、次の数値は1ターンあたり の平均ダメージです。上の例は1ターンあたりの射撃回数が2回の場合の例になっ ています。 @@ -413,13 +413,15 @@ XdY. これは武器の基本ダメージです。もし攻撃が命中すると ダンジョン内の多くの武器は特定の種類の敵に対して恐るべき力を発揮します。 それらの特性は総称してスレイと呼ばれます。そうした武器はダイスを振った -ダメージを二倍、あるいは三倍に増やします。しかしダメージ修正値には影響 -しません。以下にスレイ属性の一覧を示します: +ダメージを二倍以上に増やします。しかしダメージ修正値には影響しません。 +以下にスレイ属性の一覧を示します: - 滅邪 : 邪悪なモンスターに対してダメージダイス2倍 - アニマルスレイヤー: 対応するモンスターに対してダメージダイス2倍 - その他の~スレイヤー: 対応するモンスターに対してダメージダイス3倍 - *ドラゴンスレイヤー*:ドラゴンに対してダメージダイス5倍 + 滅邪 (または*破邪*): 邪悪なモンスターに対してダメージダイス2倍 + (*破邪* の場合は3.5倍) + アニマルスレイヤー・人間スレイヤー: 対応するモンスターに対して + ダメージダイス2.5倍(*滅アニマル*・*滅人間* の場合は4倍) + その他の~スレイヤー: 対応するモンスターに対してダメージダイス3倍 + (*~*スレイヤーの場合は5倍) 元素の属性を持つ武器(溶解、焼棄、凍結、電撃、毒殺)はその元素に耐性を持 たないモンスターに対し 2.5倍のダメージダイスで攻撃します。さらに(吸血) @@ -430,7 +432,7 @@ XdY. これは武器の基本ダメージです。もし攻撃が命中すると === 怪物の思い出 === 他の多くのゲームでは、あなたは怪物の弱点や強さ、使ってくる呪文などをメ -モしておく必要があります。変愚蛮怒はこの点について気をつけており、怪物 +モしておく必要があります。馬鹿馬鹿蛮怒はこの点について気をつけており、怪物 の簡単な思い出を記録します。キャラクタがある怪物について何か新しいこと、 例えばブレス攻撃してくるとかいったことを見つけたら、これはあなたの怪物 の情報に加えられます。この情報は、"/"を入力した後に怪物を表す文字を入 @@ -459,7 +461,7 @@ XdY. これは武器の基本ダメージです。もし攻撃が命中すると === ユーザー設定画面 === -ユーザー設定画面は"="を入力することで表示されます。ここには変愚蛮怒を +ユーザー設定画面は"="を入力することで表示されます。ここには馬鹿馬鹿蛮怒を より快適に楽しめるものにする色々な設定があります。ほとんどは初期設定の ままで十分ですが、いくつかは設定をした方が良いでしょう。 @@ -479,7 +481,7 @@ XdY. これは武器の基本ダメージです。もし攻撃が命中すると === æ­» === -変愚蛮怒において、死は永久的なものです。このゲームにおけるセーブとは、 +馬鹿馬鹿蛮怒において、死は永久的なものです。このゲームにおけるセーブとは、 単にゲームを一時中断しておく為の手段に過ぎません。死んでしまうと、セー ブファイルには印がつけられ、次にそのセーブファイルでゲームを始めようと すると新規キャラクタ生成からとなるのです。死んだキャラクタの先祖は怪物 @@ -501,14 +503,14 @@ XdY. これは武器の基本ダメージです。もし攻撃が命中すると 真にゲームの勝利者になるのは不可能です。 -=== 変愚蛮怒でのスピードの扱いについて === +=== 馬鹿馬鹿蛮怒でのスピードの扱いについて === -変愚蛮怒にはプレイヤー(特に Angband系のゲームのベテラン)を混乱させる +馬鹿馬鹿蛮怒にはプレイヤー(特に Angband系のゲームのベテラン)を混乱させる システムがあります。それはスピードに関するものです。他のほとんどの Angband系ゲームではあなたや敵の行動の速度はそのキャラクタの種類や状態 によって固定されています。加速+10(あるいは「素早い」)者は通常のモンス ターの2倍の速度で動き、加速+0のプレイヤー(または「普通の速度」のモンス -ター)が1回動く時間で常に2回行動する事ができます。しかし変愚蛮怒では速 +ター)が1回動く時間で常に2回行動する事ができます。しかし馬鹿馬鹿蛮怒では速 度は一定していません。加速の数字は単純に統計的な平均値を示します。した がって、普通の速度で動くモンスターが突然2回も3回も連続して行動したり、 あるいは1~2ターン止まっていたりします。 @@ -518,9 +520,9 @@ Angband系ゲームではあなたや敵の行動の速度はそのキャラク てからは表示の数値の上昇あたりの実際の速度の上昇はだんだん少なくなって いきます。 -変愚蛮怒の時間のシステムの詳細を知ることでより深くこのシステムを理解で -きます。変愚蛮怒ではプレイヤーやモンスターは時間の経過とともに何点かの -「エナジー」を得ます。前述したように変愚蛮怒は他のAngband系ゲームと違 +馬鹿馬鹿蛮怒の時間のシステムの詳細を知ることでより深くこのシステムを理解で +きます。馬鹿馬鹿蛮怒ではプレイヤーやモンスターは時間の経過とともに何点かの +「エナジー」を得ます。前述したように馬鹿馬鹿蛮怒は他のAngband系ゲームと違 い、得られるエナジーはランダムになります。ただし平均値だけは平等です。 このエナジーポイントが100たまると行動できるようになります。ほとんど の行動はエナジーを100消費します。例外がいくつかあり、例えば強速射の diff --git a/lib/help/jtown.txt b/lib/help/jtown.txt index 37f659749..072673488 100644 --- a/lib/help/jtown.txt +++ b/lib/help/jtown.txt @@ -1,6 +1,6 @@ === 街と荒野 === -キャラクターを作成したら「辺境の地」という街から変愚蛮怒の冒険が始まり +キャラクターを作成したら「辺境の地」という街から馬鹿馬鹿蛮怒の冒険が始まり ます。画面上にある記号はダンジョンの壁、床、アイテム、地形、そしてダン ジョンをうろつくモンスターです。自分のキャラクターに命令を与えるには、 キーを一文字押すだけです(詳細は jcommand.txt[b]を参照)。 @@ -67,11 +67,11 @@ だ場合夜から始まります)。日は時間の経過と共に昇ったり沈んだりし、夜の 街は暗くなります。幸い様々な店や建物は24時間営業しています。 -変愚蛮怒の広大な世界には5つの町とたくさんのダンジョンがあり、街中の建 +馬鹿馬鹿蛮怒の広大な世界には5つの町とたくさんのダンジョンがあり、街中の建 物に入ることで固定クエスト(下 [d]を参照)を受けたり闘技場でチャンピオン を目指したりできます。 -このような広い世界を望まない人のために変愚蛮怒では3つの街オプションが +このような広い世界を望まない人のために馬鹿馬鹿蛮怒では3つの街オプションが 存在します。それは、「標準の地上マップ」、「小規模な街(LiteTown)」、 「元祖の町(Vanilla Town)」です。デフォルトは標準の地上マップで、小規模 な街と元祖の町はキャラクタを生成するときに'='キーを押してオプション画 @@ -330,7 +330,7 @@ Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.7.0 +Updated : Bakabakaband 1.7.0 diff --git a/lib/help/jversion.txt b/lib/help/jversion.txt index 81cbb2c92..5af1eccf6 100644 --- a/lib/help/jversion.txt +++ b/lib/help/jversion.txt @@ -1,5 +1,5 @@ ━━━━━━━━━━━━━━━━━━━━━━━ - 変愚蛮怒バージョン履歴 + 馬鹿馬鹿蛮怒バージョン履歴 ━━━━━━━━━━━━━━━━━━━━━━━ -------------- @@ -42,7 +42,7 @@ 保存フロアの仕様を持たない1.4.xブランチの真の最終版。 一部職業のレベル別称号の変更。 - 変愚蛮怒を起動したままWindowsをシャットダウンした場合にセーブする。 + 馬鹿馬鹿蛮怒を起動したままWindowsをシャットダウンした場合にセーブする。 Windows版とMac版で、バグで強制終了した場合にゲームを緊急セーブする。 練気術師が魔法書を使えない場合に専用プロンプトを通す。 ランダムクエスターはvaultには配置されない。 @@ -442,7 +442,7 @@ X11では、追加オプション -a と -o で16x16か8x8のタイルを選択 8x8タイルで、光源と視界の範囲を明るく表示タイルの重ね合せ表示にも対応 タイル表示でもスクリーンショットを送信できる - 初心者ガイド(lib/help/tang.txt)を変愚蛮怒対応にした + 初心者ガイド(lib/help/tang.txt)を馬鹿馬鹿蛮怒対応にした 幻覚状態の死因は普通に表示 バグ修正 @@ -461,7 +461,7 @@ 浮遊が付いてなくても荷物が軽ければ水の上を走れる モンスターの追跡ルーチン関係を変更 8x8タイルを標準でつける (タイル書いてくれる人募集中) - 日本語版のZ240ヘルプを元に変愚蛮怒ヘルプを作成 + 日本語版のZ240ヘルプを元に馬鹿馬鹿蛮怒ヘルプを作成 ペット爆破の魔法でユニークモンスターを破壊できない オプションの位置変更 仙術の魔法の爆発のルーンと次元の扉を場所交換 @@ -534,7 +534,7 @@ 街の主変更 トロルの王の色変更 標準設定ファイルをlib/prefに移動 - (UNIX限定)ユーザディレクトリをlib/user/から~/.angband/Hengband/に変更 + (UNIX限定)ユーザディレクトリをlib/user/から~/.angband/Bakabakaband/に変更 クエストコマンドの表示を改良 クエストの報酬で既に持っているアーティファクトは出ない(代わりに獲得の巻物) ロケットはモンスターに当たると止まる @@ -1134,7 +1134,7 @@ xxxxxx.x □ 初心者ガイド翻訳 from ZKB-J 斎藤さん ァイルを生成します。新しく作った拡張セーブファイルフォーマットのサポー トを将来万が一放棄することがあっても一旦互換フォーマットでセーブして新 バージョンで読み込むという最終手段として使うこともできます。新しいアイ -テム/モンスターは Mr.Hoge さんの衝撃のバリアント、変愚蛮怒と、KOKA さ +テム/モンスターは Mr.Hoge さんの衝撃のバリアント、馬鹿馬鹿蛮怒と、KOKA さ んの SJNetHack から一部拝借してます。新しいもの好きな人は是非この二つ プレイすべしです。 @@ -1190,7 +1190,7 @@ xxxxxx.x □ 初心者ガイド翻訳 from ZKB-J 斎藤さん 000626.1 ★ アーティファクト矢に関係した機能追加 000627.1 ★ '/'コマンド拡張 冗談メッセージ追加 コメント整備 X11 で漢字の銘に上書きしても落ちないようにした。 -XXXXXXXX ★ 新モンスター/アーティファクト追加 from 変愚蛮怒&SJNH +XXXXXXXX ★ 新モンスター/アーティファクト追加 from 馬鹿馬鹿蛮怒&SJNH ---------------------------- @@ -1743,7 +1743,7 @@ Official Angband Home Page で確認することができます。 an underlying keyset refueling torches better monster memory - nicer targetting mode + nicer targeting mode object stacking the recall window the choice window diff --git a/lib/help/magic.hlp b/lib/help/magic.hlp index 002e602b0..752f74d4a 100644 --- a/lib/help/magic.hlp +++ b/lib/help/magic.hlp @@ -1,8 +1,8 @@ -Hengband Magic System. +Bakabakaband Magic System. Please choose one of the following online help files: - (a) Hengband Magic System (magic.txt) + (a) Bakabakaband Magic System (magic.txt) (b) The Magic Realms (magic.txt#MagicRealms) (c) On Casting Spells ... (magic.txt#CastingSpells) (d) Spell Types (magic.txt#SpellTypes) diff --git a/lib/help/magic.txt b/lib/help/magic.txt index 74713675a..894c52159 100644 --- a/lib/help/magic.txt +++ b/lib/help/magic.txt @@ -1,13 +1,13 @@ -=== Hengband Magic System === +=== Bakabakaband Magic System === -The magic system of Hengband is a modified version of Zangband's, with many -new features added. There are two kind of magic in Hengband: Spellbook +The magic system of Bakabakaband is a modified version of Zangband's, with many +new features added. There are two kind of magic in Bakabakaband: Spellbook magic, similar to the normal magic system of Zangband, and class-specific magic, similar to Zangband's mindcrafting. You might not be able to understand the function of every magic spell -by reading its name or casting it a few times. In Hengband, spells +by reading its name or casting it a few times. In Bakabakaband, spells have descriptions. Use the browse command ("b"/"P") and choose a spell from the list to see its description. @@ -21,12 +21,14 @@ intelligence, wisdom, or charisma. For spellcasting, you must always carry spellbooks which include spells which you want to cast. You can choose either one or two realms, depending on class. -In Hengband, you cannot be as proficient in secondary realm as in -first realm. But you can change secondary realm to other realm of -magic even in the middle of the game. For that, you must choose a -spellbook of new realm in the study command ('G'). But beware! After -changing realm, you will forget all spells of old realm, moreover the -number of learning will not be restored and be lost permanently. +In Bakabakaband, you cannot be as proficient in the second realm as in +the first realm. But you can change the second realm to another realm +of magic even in the middle of the game. For that, you must choose a +spellbook of the new realm in the study command ('G'). But beware! +After changing realms, you will forget all spells of the old realm, +moreover the forgotten spells still count towards the total number of +spells you can learn, limiting the number of new spells you'll be +able to study. Note that certain realms may be prohibited for some classes. In the table below, '1' indicates that the realm may only be the first @@ -89,8 +91,8 @@ See raceclas.txt#TheClasses [a] for more details. --- Life --- Life magic is very good for healing; it relies mostly on healing, - protection and detection spells. Also life magic have a few - attack spells as well. It said that some high level spell of life + protection and detection spells. Also life magic has a few + attack spells as well. It's said that some high level spells of life magic can disintegrate Undead monsters into ash. The fail rate of Life spells goes up if the caster's alignment tends towards evil. @@ -199,7 +201,7 @@ See raceclas.txt#TheClasses [a] for more details. ***** --- Craft --- - Craft magic is an original realm in Hengband. It provides spells + Craft magic is an original realm in Bakabakaband. It provides spells which reinforce the casters physical abilities, including offensive power, defensive power, speed, regeneration, infravision, etc.. The 'Regeneration' and 'Walk through Wall' @@ -211,11 +213,11 @@ See raceclas.txt#TheClasses [a] for more details. ***** --- Daemon --- - Daemon magic is an original realm in Hengband. It offers + Daemon magic is an original realm in Bakabakaband. It offers powerful attack spells with the properties of Fire or Nether. There are a few detection spells which provide a map of the nearby area or temporary telepathy. Daemon magic also provides - temporary trans- formation spells which allow caster to become a + temporary transformation spells which allow caster to become a Demon or a Demon Lord. The fail rate of Daemon spells goes up for casters aligned towards good. @@ -231,10 +233,12 @@ See raceclas.txt#TheClasses [a] for more details. ***** --- Hex --- - Hex is a realm of 'Curse'; It is technics rather than magics, and - casted continually like a songs. Most of spells give terrible - effects during they are spelled. The fail rate of Daemon spells - goes up for casters aligned towards good. + Hex is an abomination of magic, closer to swordsmanship than + spell casting. Some of the spells can be cast continuously, + like songs, for more powerful effects. Hex spells are good + at obstructing opponents and returning damage to those who + have damaged the caster. The fail rate of Hex spells goes + up for casters aligned towards good. ***** @@ -358,7 +362,7 @@ inscriptions). Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.7.2 +Updated : Bakabakaband 1.7.2 ***** [a] raceclas.txt#TheClasses diff --git a/lib/help/monster.hlp b/lib/help/monster.hlp index b8caa5ac2..1b0a1ac45 100644 --- a/lib/help/monster.hlp +++ b/lib/help/monster.hlp @@ -1,8 +1,8 @@ -Hengband Monsters. +Bakabakaband Monsters. Please choose one of the following online help files: - (a) Hengband Monsters (monster.txt) + (a) Bakabakaband Monsters (monster.txt) (b) Monster Symbols (monster.txt#MonsterSymbols) (c) Monster Color (monster.txt#MonsterColors) (d) Monster Memory (monster.txt#MonsterMemory) diff --git a/lib/help/monster.txt b/lib/help/monster.txt index 4559c0b47..ae3acff66 100644 --- a/lib/help/monster.txt +++ b/lib/help/monster.txt @@ -1,6 +1,6 @@ -=== Hengband Monsters === +=== Bakabakaband Monsters === -There are hundreds of different creatures in Hengband each of which +There are hundreds of different creatures in Bakabakaband each of which poses a unique challenge to the adventurer. As you progress deeper into the dungeon, the creatures will become progressively more difficult to defeat. @@ -74,7 +74,7 @@ will probably get cleaned up. Because there are so many monsters and because often different monsters share similar colors and symbols; it is very difficult to keep track of -the capabilities of various creatures. Luckily, Hengband automatically +the capabilities of various creatures. Luckily, Bakabakaband automatically keeps track of your experiences with a particular creature. This feature is called the monster memory. Your monster memory recalls @@ -106,9 +106,9 @@ character. ***** === Unique Monsters === -The monsters in Hengband are unique in that each variety of monsters +The monsters in Bakabakaband are unique in that each variety of monsters has its own set of physical and, where applicable, magical abilities. -However, some monsters in Hengband are truly unique and this group +However, some monsters in Bakabakaband are truly unique and this group of monsters are often referred to as "Uniques". The Unique monsters are made unique for several reasons. Primarily, @@ -153,7 +153,7 @@ check this periodically to gauge your progress. Occasionally, you will find that a Unique monster will speak to you as it approaches. Typically, a monster will shout obscenities and challenges to combat but they may also refer to events relating to -themselves. Hengband has no mechanism to allow you to respond to the +themselves. Bakabakaband has no mechanism to allow you to respond to the monsters (other than with violence). You may prevent Unique monsters from speaking by changing the appropriate option under the options menus. @@ -170,7 +170,7 @@ upon how deep in the dungeon the relevant Unique is normally found. ***** === Eldritch Horrors === -Some of the monsters in the dungeons of Hengband are so fearsome to +Some of the monsters in the dungeons of Bakabakaband are so fearsome to look upon that doing so can have serious repercussions. When you meet one of these sanity blasting monsters, one of several nasty things may happen to you. These include having your intelligence and/or your @@ -181,12 +181,12 @@ an attack of amnesia. ***** === Pets and Riding === -In Hengband, pets are very useful. In other variants (such as +In Bakabakaband, pets are very useful. In other variants (such as Zangband), your pets are often so eager to destroy your opponents that they may forget all about you, and you get trampled under their feet -as they charge at your foe. In Hengband, however, pets will never +as they charge at your foe. In Bakabakaband, however, pets will never attack you by mistake; you can walk around in safety even as your pet -Great Hell Wyrm breaths. Pets will also never be irritated with you; +Great Hell Wyrm breathes. Pets will also never be irritated with you; their will is perfectly dominated by you, and all pets are permanently your pets. @@ -199,7 +199,7 @@ you will only gain experience and items for creatures to whom you deliver the death blow yourself. Monsters which get killed by a pet don't drop items. This feature of -Hengband is unique and severe, and you might complain about it because +Bakabakaband is unique and severe, and you might complain about it because this feature is not very realistic, but this is a well-thought-out result of weighing game balance with reality. @@ -243,7 +243,7 @@ List of pet commands: dismiss pets Dismiss specified pets. Dismissed pets will immediately disappear - from the current level. Hengband asks you whether you want to dismiss + from the current level. Bakabakaband asks you whether you want to dismiss each pet in order from high level named pets to low level unnamed pets. You can press 'U' to dismiss all unnamed pets. @@ -305,7 +305,7 @@ use one hand to control a riding pet --- Riding --- -In Hengband, the player can ride on pet horses or dragons, etc. To +In Bakabakaband, the player can ride on pet horses or dragons, etc. To control your mount, you must keep one hand free for holding the reins. But your pet will attack your target together with you, and enemy's attack will be dispersed. As a result of these, player's @@ -345,7 +345,7 @@ not be commanded using the pet commands. Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.0.11 +Updated : Bakabakaband 1.0.11 ***** Begin Hyperlinks ***** [b] commdesc.txt#Looking diff --git a/lib/help/objects.hlp b/lib/help/objects.hlp index c3a87c7d5..d7309070c 100644 --- a/lib/help/objects.hlp +++ b/lib/help/objects.hlp @@ -1,8 +1,8 @@ -Hengband Objects. +Bakabakaband Objects. Please choose one of the following online help files: - (a) Hengband Objects (objects.txt) + (a) Bakabakaband Objects (objects.txt) (b) Object Symbols (objects.txt#ObjectSymbols) (c) Equipment and Inventory (objects.txt#EquipInvent) (d) Objects Generation (objects.txt#Generation) diff --git a/lib/help/objects.txt b/lib/help/objects.txt index 499414c6a..e33c02913 100644 --- a/lib/help/objects.txt +++ b/lib/help/objects.txt @@ -1,6 +1,6 @@ -=== Hengband Objects === +=== Bakabakaband Objects === -The Hengband dungeons are full of objects and many monsters you meet +The Bakabakaband dungeons are full of objects and many monsters you meet will be carrying one or more items about their person which you may retrieve from their corpse should you be skillful enough to defeat them. You may pick up objects by moving on top of them. By setting @@ -9,7 +9,7 @@ pick up items automatically or to be prompted before picking up objects. Many objects found within the dungeon have special commands for their -use. Wands must be 'a'imed, staves must be 'u'sed, scrolls must be +use. Wands must be 'a'imed, staffs must be 'u'sed, scrolls must be 'r'ead, and potions must be 'q'uaffed. You may, in general, not only use items in your pack, but also items on the ground, if you are standing on top of them. @@ -76,7 +76,7 @@ effects of acid while it is in your backpack. ***** === Object Generation === -Objects are generated by Hengband when you enter a dungeon level and +Objects are generated by Bakabakaband when you enter a dungeon level and spread liberally around the dungeon floor. They may also be generated when a monster is killed (assuming the monster is capable of carrying objects). Each object has a 'native' depth or a depth at which it @@ -107,12 +107,12 @@ objects. ***** === Object Compaction === -Hengband can track a large, but finite, number of objects at any one +Bakabakaband can track a large, but finite, number of objects at any one time. If, as you kill monsters, the number of objects dropped together with the number of objects already lying on the floor exceeds this limit you will be told that the game is 'compacting objects'. -When Hengband compacts objects it first attempts to combine similar +When Bakabakaband compacts objects it first attempts to combine similar objects into piles and, if this does not create sufficient space, will delete already existing items to create space for new ones. To the extent possible the compacting is performed on objects some distance @@ -202,7 +202,7 @@ the dying curse of an Amberite. ***** === Object Flavors === -Some objects (scrolls, potions, wands, rods and staves) are 'flavored +Some objects (scrolls, potions, wands, rods and staffs) are 'flavored items'. This means that with each game they are given a random flavor. For example, the first time you find a Potion of Heroism it might be described as a 'Dark Blue Potion'. Once you have identified it, the @@ -212,7 +212,7 @@ same Dark Blue Potion is now something entirely different. This means that each new character must set about learning exactly what each flavored items is. -One of the Hengband Options allows the player to switch to 'plain' +One of the Bakabakaband Options allows the player to switch to 'plain' object descriptions which removes the flavored description from known flavored items so that the potion above, once identified, would be described simply as a 'Potion of Heroism'. @@ -227,13 +227,13 @@ your backpack. This sensing ability is called 'pseudo-id'. The speed and accuracy of your pseudo-id ability depends on a number of factors but the primary considerations are your class and level. Pseudo-id speed can be 'slow', 'medium' or 'fast'. Pseudo-id method of weapons -and armors can be 'strong' or 'weak'. Pseudo-id method of others is +and armor can be 'strong' or 'weak'. Pseudo-id method of others is always 'strong'. Table 1 - Pseudo-Id ability of the Classes - Weapons and Armors Others + Weapons and Armor Others Class Method Speed Speed -------------------------------------------------------- Warrior Strong Very Fast Impossible @@ -303,7 +303,7 @@ pseudo-id ability to ascertain the quality of some items. For the most part you will need to identify them before you can ascertain how much use they will be to you. There are several methods of identifying items available to you. These include Scrolls of Identify and *Identify*, -Staves and Rods of Perception, spells and prayers and services from +Staffs and Rods of Perception, spells and prayers and services from town buildings among others. There is an important difference between 'identify'ing an object and @@ -334,12 +334,12 @@ in the dungeon, some of them may be endowed with additional powers. These objects fall into three types: (b) artifacts which are dealt with below and can be identified by their name; (c) Ego Weapons which are described more fully in Attacking Monsters (see attack.txt#EgoArtifact -[g]); and (d) Ego Armors which are discussed more fully in Defending -Yourself (see defend.txt#EgoArtifact [h]). +[g]); and (d) pieces of Ego Armor which are discussed more fully in +Defending Yourself (see defend.txt#EgoArtifact [h]). Unlike artifacts which are unique and may only be found once in each -game, it is not unusual to find several Ego Weapons or Ego Armor of the -same type during the course of a character's adventures. +game, it is not unusual to find several Ego Weapons or pieces of Ego +Armor of the same type during the course of a character's adventures. Note that some Ego Armor types are limited to only certain types of armor. For example, you can find a Shield of Elvenkind but not Boots of @@ -349,7 +349,7 @@ Elvenkind. ***** === Artifacts === -Of all the objects in Hengband that you might find, by far the most +Of all the objects in Bakabakaband that you might find, by far the most important group are artifacts. Artifacts are unique items with additional properties such as increasing or sustaining one or more of your stats and granting resistances or abilities. Often an @@ -469,7 +469,7 @@ special meaning to inscriptions containing any text of the form "@#" or "@x#" or "!x" or "!*" (see command.txt#ObjectSelection [i]) . The game provides some "fake" inscriptions to help you keep track of -your possessions. Wands and staves which are known to be empty will be +your possessions. Wands and staffs which are known to be empty will be inscribed with "empty". Objects which have been tried at least once but haven't been identified yet will be inscribed with "tried". Cursed objects are inscribed with "cursed". Broken objects may be inscribed @@ -484,11 +484,11 @@ real inscription if you so desire. Try "_" as a nice short one. Some players use the inscription feature to record useful and/or interesting facts about an object such as where and how it was -acquired or what its abilities and powers are. Hengband have a feature +acquired or what its abilities and powers are. Bakabakaband have a feature to automatically inscribe abilities of items for you. In addition to this, inscriptions can be used in far more powerful -ways. Many commands in Hengband require you to specify an object from +ways. Many commands in Bakabakaband require you to specify an object from your inventory such as which potion you wish to 'q'uaff or which staff you wish to 'u'se. Inscriptions offer a powerful way of managing this and provide a useful labor saving tool. @@ -647,10 +647,10 @@ The {!x} inscription (where 'x' is the key to activate a specific command) will induce "verification" whenever that object is "selected". Thus, inscribing {!v!k!d} on an object will greatly reduce the odds of you "losing" it by accident. This is because any attempt to throw it -('f'), destroy it ('k') or drop it ('d') will prompt Hengband to verify +('f'), destroy it ('k') or drop it ('d') will prompt Bakabakaband to verify whether or not you really wish to take that action. -Note that inscribing {!*} on an object will prompt Hengband to verify +Note that inscribing {!*} on an object will prompt Bakabakaband to verify any action thus you allowing you to be very paranoid about the object. Also note that "selling" and "dropping" both use the "d" command so that inscribing an item with {!d} will also prevent you from selling it @@ -666,7 +666,7 @@ actually doing so. The {=g} Inscription -------------------- -The {=g} inscription on an object prompts Hengband to automatically +The {=g} inscription on an object prompts Bakabakaband to automatically pick it up. This instruction overrides any auto-pickup options chosen chosen by the player (if necessary). The primary purpose is to allow easy retrieval of missiles such as arrows and bolts once they have been @@ -783,15 +783,15 @@ Wands ('-') and most wands will require a target. Staffs ('_') - Staves are a flavored item and are made of various types of wood. + Staffs are a flavored item and are made of various types of wood. Like wands, they contain a limited number of charges and must be - recharged when empty. In general, staves have an area affect or - act on the player. Unlike wands, few staves may be used directly - for offense. Staves must be 'u'sed and do not require a target. + recharged when empty. In general, staffs have an area affect or + act on the player. Unlike wands, few staffs may be used directly + for offense. Staffs must be 'u'sed and do not require a target. Rods ('-') - Rods are similar to both wands and staves in that many magical - effects available from wands and staves are also available from + Rods are similar to both wands and staffs in that many magical + effects available from wands and staffs are also available from rods. The main difference is that a rod carries a single charge but over time will recharge itself. Typically, the better the rod, the longer it will take to recharge itself. This means you have an @@ -847,7 +847,7 @@ Light Sources ('~') Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.3.0 +Updated : Bakabakaband 1.3.0 ***** Begin Hyperlinks ***** [b] option.txt#UserInterface diff --git a/lib/help/option.hlp b/lib/help/option.hlp index 04a626532..08a1ffd69 100644 --- a/lib/help/option.hlp +++ b/lib/help/option.hlp @@ -1,8 +1,8 @@ -Hengband Options. +Bakabakaband Options. Please choose one of the following online help files: - (a) Hengband Options (option.txt) + (a) Bakabakaband Options (option.txt) (b) Option Set 1 - Input from keyboard (option.txt#Input) (c) Option Set 2 - Map Screen (option.txt#MapScreen) (d) Option set 3 - Text Display (option.txt#TextDisplay) diff --git a/lib/help/option.txt b/lib/help/option.txt index 15ad1875e..926811087 100644 --- a/lib/help/option.txt +++ b/lib/help/option.txt @@ -48,7 +48,7 @@ Activate quick messages [quick_messages] ***** Automatically clear '-more-' prompts [auto_more] The game does not wait for a keypress when it comes to a -more- - prompt, but carries on going. + prompt and automatically displays the next message. ***** Enable command selection menu [command_menu] @@ -93,7 +93,7 @@ Prompt before exiting a quest level [confirm_quest] you go up the stairs from such quest levels. ***** -Allow targetting pets [target_pet] +Allow targeting pets [target_pet] Normally, the program doesn't automatically choose pets as target in the targeting mode of attack spells. If this option is set, the program always chooses every monster in sight as target. @@ -127,7 +127,7 @@ Allow unified use command [use_command] ***** Allow casting spells when short of mana [over_exert] - Normally, Hengband restricts you from casting spells when you don't + Normally, Bakabakaband restricts you from casting spells when you don't have enough mana. If this option is set, the program allow you to cast spells at such dangerous situation. @@ -292,8 +292,8 @@ Plain object descriptions [plain_descriptions] ***** Always show list when choosing items [always_show_list] When this option is set, all commands which lets you to choose an - item from inventory or equipment list will automatically show list - when activated. + item from inventory or equipment list will automatically show the + list when activated. ***** Show dungeon level in feet [depth_in_feet] @@ -435,17 +435,17 @@ Leave last words when your character dies [last_words] ***** Send score dump to the world score server [send_score] - If this option is set, Hengband will allow you to send the score + If this option is set, Bakabakaband will allow you to send the score record of your character to the world score board on the Internet when your character dies. ***** Allow use of debug/cheat options [allow_debug_opts] Since use of debug command(^A), wizard mode(^W), and Cheating - options ('C' in options panel) mark the player as "Cheater" who - can't register their score, these debug/cheat options are + options ('C' in options panel) mark the player as a "Cheater" + who can't register their score, these debug/cheat options are forbidden to use on default. The allow_debug_opts option removes - these restrictions, and allow the player to become "Cheater". + these restrictions, and allow the player to become a "Cheater". ***** @@ -535,7 +535,7 @@ Disturb whenever player state changes [disturb_state] ***** Disturb whenever boring things happen [disturb_minor] - This option causes you to be disturbed by various bring things, + This option causes you to be disturbed by various boring things, including monsters bashing down doors, inventory feelings, and beginning to run out of fuel. @@ -559,19 +559,19 @@ Alert when leaving trap detected area [alert_trap_detect] ***** Use easy auto-destroyer [destroy_items] - If this option is set, Hengband will automatically destroy all + If this option is set, Bakabakaband will automatically destroy all objects which you touch unless the object is protected by various 'leave_...' options below. ***** Apply auto-destroy as sense feeling [destroy_feeling] - If this option is set, Hengband will apply auto-destroyer on an + If this option is set, Bakabakaband will apply auto-destroyer on an item just when you sensed its feeling. Typically it will destroy {cursed} items just after the sensing. ***** Apply auto-destroy as identify an item [destroy_identify] - If this option is set, Hengband will apply auto-destroyer on an + If this option is set, Bakabakaband will apply auto-destroyer on an item just when you identified it using magical items or spells. Typically it will destroy {cursed} items and other useless items which you set up to be auto-destroyed. @@ -762,7 +762,7 @@ Display overhead view and does not even look very good. Display monster recall - Display a description of the most monster which has been most recently + Display a description of the monster which has been most recently attacked, targeted, or examined in some way. Display object recall @@ -789,7 +789,7 @@ Display borg status ***** === Option C - Cheating Options === -Using the cheating options marks your character as "Cheater" and +Using the cheating options marks your character as a "Cheater" and you won't get into the high-score list. Turning off the cheating options later does NOT allow your character to get a highscore entry, so think twice before using any cheat. @@ -828,7 +828,7 @@ Ask for saving death [cheat_save] === Birth options === While cheating makes the game easier, the following options can make -Hengband harder or easier. So if you think the game is too easy or too +Bakabakaband harder or easier. So if you think the game is too easy or too hard, or if you want to impress your friends, then switch on the following options. The birth options can only be accessed while creating a new character (press '=' while creating the character). @@ -909,7 +909,7 @@ Always generate very unusual rooms (*) [ironman_rooms] Nightmare mode(it isn't even remotely fair!)(*) [ironman_nightmare] If this option is enabled, all monsters become unusually powerful, and fast. And there will be various unbelievable - happening in various situations. Furthermore, at 12:00 every + happenings from time to time. Furthermore, at 12:00 every night, you will have a real nightmare. ***** @@ -962,4 +962,4 @@ Original : Ben Harrison Updated : Zangband 2.1.* by Topi Ylinen Updated : Zangband 2.2.0 through 2.2.6c by Robert Ruehlmann Updated : Zangband DevTeam -Updated : Hengband 1.5.2 +Updated : Bakabakaband 1.5.2 diff --git a/lib/help/pref.txt b/lib/help/pref.txt index b3aa81261..7b87b0176 100644 --- a/lib/help/pref.txt +++ b/lib/help/pref.txt @@ -1,7 +1,7 @@ === User Pref Files === -Hengband allows you to change various aspects of the game to suit your -tastes. You may define keymaps (changing the way Hengband maps your +Bakabakaband allows you to change various aspects of the game to suit your +tastes. You may define keymaps (changing the way Bakabakaband maps your keypresses to underlying commands), create macros (allowing you to map a single keypress to a series of keypresses), modify the visuals (allowing you to change the appearance of monsters, objects, or terrain @@ -9,19 +9,19 @@ features), change the colors (allowing you to make a given color brighter, darker, or even completely different), or set options (turning them off or on). -Hengband stores your preferences in files called "user pref files", +Bakabakaband stores your preferences in files called "user pref files", which contain comments and "user pref commands", which are simple strings describing one aspect of the system about which the user has a preference. There are many ways to load a user pref file, and in fact, some of these files are automatically loaded for you by the game. All of the files are kept in the user directory, which is -"~/.angband/Hengband/" on Unix, otherwise "lib/user/" , though you may +"~/.angband/Bakabakaband/" on Unix, otherwise "lib/user/" , though you may have to use one of the command line arguments to redirect this directory, especially on multiuser systems. You may also enter single user pref commands directly, using the special "Enter a user pref command" command, activated by "double quote". You may have to use the "redraw" command (^R) after changing certain of the aspects of the -game, to allow Hengband to adapt to your changes. +game, to allow Bakabakaband to adapt to your changes. When the game starts up, after you have loaded an old character, or created a new character, some user pref files are loaded automatically. @@ -51,8 +51,8 @@ intuitive way than the user pref commands allow. The commands include "Interact with macros" (@), "Interact with visuals" (%), and "Interact with colors" (&), described below. -In Hengband, all preference which will be generated in-game are not -simply appended to old files but replaces old lines. You don't need to +In Bakabakaband, all preferences which will be generated in-game are not +simply appended to old files but replace old lines. You don't need to delete old lines with text editor. ***** @@ -112,7 +112,7 @@ of encoding, including "\xHH" for character number HH in hexadecimal, "return" code, "\s" for the "space" code, "\\" for backslash, "\^" for caret, and "^X" for the code for any "control" key "ctrl-X". -In Hengband, name of special keys as macro-trigger is displayed using +In Bakabakaband, name of special keys as macro-trigger is displayed using its real name, for example the Control-key plus the F1-key is displayed as "\[control-F2]", and the Alt-key plus the G is displayed as "\[Alt-G]". In other variant these special keys will be, currently, @@ -126,8 +126,8 @@ both triggers and actions. The special "\" command (which must be encoded in macros as "\\") is very useful in macros, since it bypasses all keymaps and allows the -next keystroke to be considered a command in the underlying Hengband -command set. For a list of the Hengband command set, see the +next keystroke to be considered a command in the underlying Bakabakaband +command set. For a list of the Bakabakaband command set, see the "command.txt" help file. For example, a macro which maps Shift-KP6 to "\" + "." + "6" will induce the "run east" behavior, regardless of what keyset the user has chosen, and regardless of what keymaps have been @@ -144,7 +144,7 @@ the form "P:", which defines the encoded macro trigger. The "Interact with macros" command also allows you to define "keymaps", which are vaguely related to macros. A keymap maps a single keypress to a series of keypresses, which bypass both other keymaps and any macros. -Hengband uses keymaps to map the original and the roguelike keysets to +Bakabakaband uses keymaps to map the original and the roguelike keysets to the underlying command set, and allows the user to modify or add keymaps of their own. Note that all keymap actions must be specified using underlying commands, not keypresses from the original or @@ -196,8 +196,8 @@ The "Interact with colors" command allows you to change the actual internal values used to display various colors. This command may or may not have any effect on your machine. Advanced machines may allow you to change the actual RGB values used to represent each of the 16 colors -used by Hengband, and perhaps even allow you to define new colors which -are not currently used by Hengband. +used by Bakabakaband, and perhaps even allow you to define new colors which +are not currently used by Bakabakaband. Colors can be specified in user pref files as lines of the form "V:::::". @@ -235,4 +235,4 @@ Updated : (2.7.6) by Russ Allbery (rra@cs.stanford.edu) Updated : (2.7.9) by Ben Harrison (benh@phial.com) Updated : Zangband 2.2.0 through 2.2.6c by Robert Ruehlmann Updated : Zangband DevTeam -Updated : Hengband 1.7.0 +Updated : Bakabakaband 1.7.0 diff --git a/lib/help/raceclas.txt b/lib/help/raceclas.txt index 8cf444715..ac9f1df71 100644 --- a/lib/help/raceclas.txt +++ b/lib/help/raceclas.txt @@ -1,7 +1,7 @@ === Races, Classes and Personalities === This file describes about the races, classes and personalities -available in Hengband; racial, class, personality tables are provided +available in Bakabakaband; racial, class, personality tables are provided at the bottom. @@ -9,7 +9,7 @@ at the bottom. === The Races === There are thirty seven different races that you can choose from in -Hengband. Each race has various strengths and weaknesses and its own +Bakabakaband. Each race has various strengths and weaknesses and its own adjustments to a character's stats and abilities. Many races also have intrinsic abilities and powers. Their racial powers can be used by the racial/class power command ("U"/"O"). @@ -53,9 +53,9 @@ by the racial/class power command ("U"/"O"). good saving throws. They also are very good at searching, disarming, perception, and stealth; so they make excellent rogues, but prefer to be called burglars. They are much weaker than - humans, and no good at melee fighting. Halflings have fair + humans and no good at melee fighting. Halflings have fair infravision, so they can detect warm creatures at a distance. - They have a strong hold on their life force, and are thus + They have a strong hold on their life force and are thus intrinsically resistant to life draining. @@ -64,10 +64,10 @@ by the racial/class power command ("U"/"O"). Gnomes are smaller than dwarves but larger than Halflings. They, like the hobbits, live in the earth in burrow-like homes. Gnomes - make excellent mages, and have very good saving throws. They are + make excellent mages and have very good saving throws. They are good at searching, disarming, perception, and stealth. They have lower strength than humans so they are not very good at fighting - with hand weapons. Gnomes have fair infra-vision, so they can + with hand weapons. Gnomes have fair infravision, so they can detect warm-blooded creatures at a distance. Gnomes are intrinsically protected against paralysis. @@ -79,7 +79,7 @@ by the racial/class power command ("U"/"O"). tend to be stronger and tougher but slower and less intelligent than humans. Because they are so headstrong and are somewhat wise, they resist spells which are cast on them. They are very - good at searching, perception, fighting, and bows. Dwarves have a + good at searching, perception, fighting, and bows. Dwarves have miserable stealth. They can never be blinded. @@ -88,7 +88,7 @@ by the racial/class power command ("U"/"O"). Half-orcs make excellent warriors, but are terrible at magic. They are as bad as dwarves at stealth, and horrible at searching, - disarming, and perception. Half-orcs are quite ugly, and tend to + disarming, and perception. Half-orcs are quite ugly and tend to pay more for goods in town. Because of their preference to living underground to on the surface, half-orcs resist darkness attacks. @@ -96,13 +96,13 @@ by the racial/class power command ("U"/"O"). ***** --- Half-Troll --- - Half-Trolls are incredibly strong, and have more hit points than + Half-Trolls are incredibly strong and have more hit points than most other races. They are also very stupid and slow. They are bad at searching, disarming, perception, and stealth. They are so ugly that a Half-Orc grimaces in their presence. They also happen to be fun to run... Half-trolls always have their strength sustained. At higher levels, Half-Trolls regenerate wounds - automatically, and if he or her is warrior slowly. + automatically and, if a warrior, require food less often. ***** @@ -110,8 +110,8 @@ by the racial/class power command ("U"/"O"). The Amberites are a reputedly immortal race, who are endowed with numerous advantages in addition to their longevity. They are very - tough and their constitution cannot be reduced, and their ability - to heal wounds far surpasses that of any other race. Having seen + tough and their constitution cannot be reduced. Their ability to + heal wounds far surpasses that of any other race. Having seen virtually everything, very little is new to them, and they gain levels much slower than the other races. @@ -154,10 +154,10 @@ by the racial/class power command ("U"/"O"). ***** --- Half-Giant --- - Half-Giants limited intelligence makes it difficult for them to - become full spellcasters, but with their huge strength they make - excellent warriors. Their thick skin makes them resistant to - shards, and like Half-Ogres and Half-Trolls, they have their + Half-Giants' limited intelligence makes it difficult for them to + become full spellcasters, but, with their great strength, they + make excellent warriors. Their thick skin makes them resistant + to shards, and, like Half-Ogres and Half-Trolls, they have their strength sustained. @@ -258,9 +258,9 @@ by the racial/class power command ("U"/"O"). ***** --- Imp --- - A demon-creature from the nether-world, naturally resistant to - fire attacks, and capable of learning fire bolt and fire ball - attacks. They are little loved by other races, but can perform + Demon-creatures from the nether-world, imps are naturally resistant + to fire attacks and capable of learning fire bolt and fire ball + attacks. They are little loved by other races but can perform fairly well in most professions. As they advance levels, they gain the powers of See Invisible. @@ -275,7 +275,7 @@ by the racial/class power command ("U"/"O"). poison, they can see invisible things, and move freely. At higher levels, they also become resistant to attacks which threaten to drain away their life force. Golems gain very little nutrition - from ordinary food, but can absorb mana from staves and wands as + from ordinary food, but can absorb mana from staffs and wands as their power source. Golems also gain a natural armor class bonus from their tough body. @@ -293,7 +293,7 @@ by the racial/class power command ("U"/"O"). effects of these will affect the skeleton even without entering the skeleton's (non-existent) belly, the potion or food itself will fall through the skeleton's jaws, giving no nutritional - benefit. They can absorb mana from staves and wands as their + benefit. They can absorb mana from staffs and wands as their energy source. @@ -307,7 +307,7 @@ by the racial/class power command ("U"/"O"). see invisible. While still vulnerable to cuts (unlike skeletons), Zombies are resistant to Nether. Like Golems, they gain very little nutrition from the food of mortals, but can absorb mana - from staves and wands as their energy source. + from staffs and wands as their energy source. ***** @@ -337,14 +337,14 @@ by the racial/class power command ("U"/"O"). cold. They also resist nether. At higher levels they develop telepathic abilities. Spectres make superb spellcasters, but their physical form is very weak. They gain very little nutrition - from the food of mortals, but can absorb mana from staves and + from the food of mortals, but can absorb mana from staffs and wands as their energy source. ***** --- Sprite --- - One of the several fairy races, Sprites are very small. They have + One of several fairy races, Sprites are very small. They have tiny wings and can fly over traps that may open up beneath them. They enjoy sunlight intensely, and need worry little about light based attacks. Although physically among the weakest races, @@ -356,7 +356,7 @@ by the racial/class power command ("U"/"O"). ***** --- Beastman --- - "This race is a blasphemous abomination produced by Chaos. It is + This race is a blasphemous abomination produced by Chaos. It is not an independent race but rather a humanoid creature, most often a human, twisted by the Chaos, or a nightmarish crossbreed of a human and a beast. All Beastmen are accustomed to Chaos so much @@ -418,9 +418,9 @@ by the racial/class power command ("U"/"O"). ***** --- Shadow Fairy --- - Shadow Fairies are one of the several fairy races. They have - wings, and can fly over traps that may open up beneath them. - Shadow Fairies must beware of sunlight, as they are vulnerable to + Shadow Fairies are one of several fairy races. They have wings, + and can fly over traps that may open up beneath them. Shadow + Fairies must beware of sunlight, as they are vulnerable to bright light. They are physically weak, but have advantages in using magic and are amazingly stealthy. Shadow Fairies have a wonderful advantage in that they never aggravate monsters (If @@ -463,7 +463,7 @@ by the racial/class power command ("U"/"O"). === The Classes === There are twenty seven different classes that you can choose from in -Hengband. Each class has various strengths and weaknesses and its own +Bakabakaband. Each class has various strengths and weaknesses and its own adjustments to a character's stats and abilities. Many classes also have intrinsic abilities and powers. These are often linked to the character's experience level and only become available later in the @@ -475,8 +475,8 @@ command("U"/"O"). --- Warrior --- A Warrior is a hack-and-slash character, who solves most of his - problems by cutting them to pieces, but will occasionally fall - back on the help of a magical device. Unfortunately, many + or her problems by cutting them to pieces, but will occasionally + fall back on the help of a magical device. Unfortunately, many high-level devices may be forever beyond their use. Warriors cast no spells. They hate magic. In fact, they even @@ -488,41 +488,43 @@ command("U"/"O"). ***** --- Mage --- - A Mage is a spell caster that must live by his wits as he cannot - hope to simply hack his way through the dungeon like a warrior. - In addition to his spellbooks, a Mage should carry a range of - magical devices to help him in his endeavors which he can master - far more easily than anyone else. A Mage's prime statistic is - Intelligence as this determines his spell casting ability. + A Mage is a spell caster that must live by his or her wits as + a mage cannot hope to simply hack his or her way through the + dungeon like a warrior. In addition to spellbooks, a mage + should carry a range of magical devices to help his or her + endeavors. A mage can master those devices far more easily + than anyone else. A Mage's prime statistic is Intelligence + as this determines his or her spell casting ability. Mages have the least restrictions in choosing and learning spells. They can freely choose any two realms when a character is created. Their natural inclination makes Life magic fairly hard to learn. Otherwise, a mage tends to learn and cast all the spells in his or her realms better than any other character. The ability to choose - second realm of magic has a special meaning in Hengband; only + second realm of magic has a special meaning in Bakabakaband; only second realm can be changed in the middle of the game. You can change second realm by studying ("G") from a spellbook of new realm. They have a class power - 'Eat Magic' - which absorbs mana - from wands, staves or rods. + from wands, staffs or rods. ***** --- Priest --- - A Priest is a character devoted to serving a higher power. They - explore the dungeon in the service of their God. Since Priests - receive new prayers as gifts from their patron deity, they cannot - choose which ones they will learn. Priests are familiar with - magical devices which they believe act as foci for divine - intervention in the natural order of things. A priest wielding an - edged weapon will be so uncomfortable with it that his fighting - ability. A Priest's primary stat is Wisdom since this determine - his success at praying to his deity. + A Priest is a character devoted to serving a higher power. He + or she explores the dungeon in the service of a God. Since + Priests receive new prayers as gifts from their patron deity, + they cannot choose which ones they will learn. Priests are + familiar with magical devices which they believe act as foci for + divine intervention in the natural order of things. A priest + wielding an edged weapon will be so uncomfortable with it that + his or her fighting ability decreases. A Priest's primary stat + is Wisdom since this determines the success of the prayers to + his or her deity. Priest can select from Life, Death, Daemon, or Crusade as a first - realm, and choose second realm almost freely. But pairs of a good - magic and an evil magic from these four realms are not allowed. + realm, and choose a second realm almost freely. But pairs of a + good magic and an evil magic from these four realms are not allowed. Priests can learn all spells in the selected realms, even if not as efficiently as mages. However, when learning spells, priests cannot voluntarily decide which spells to study: they are rewarded @@ -538,14 +540,13 @@ command("U"/"O"). ***** --- Rogue --- - A Rogue is a character that prefers to live by his cunning, but is - capable of fighting his way out of a tight spot. Rogues are good - at locating hidden traps and doors and are the masters of - disarming traps and picking locks. A rogue has a high stealth - allowing him to sneak around many creatures without having to - fight, or to get in a telling first blow. A rogue may also - backstab a fleeing monster. Intelligence determines a Rogue's - spell casting ability. + A Rogue is a character that prefers to live by his or her cunning, + but is capable of fighting out of a tight spot. Rogues are good + at locating hidden traps and doors and are the masters of disarming + traps and picking locks. A rogue is very stealthy, allowing him or + her to sneak around many creatures without having to fight or to + get in a telling first blow. A rogue may also backstab a fleeing + monster. Intelligence determines a Rogue's spell casting ability. Rogues can select one realm from Sorcery, Death, Trump, Arcane, or Craft. All Rogues have certain limitations on which spells they @@ -558,10 +559,10 @@ command("U"/"O"). --- Ranger --- A Ranger is a combination of a warrior and a mage who has - developed a special affinity for the natural world around him. He - is a good fighter and also good about a missile weapon such as a - bow. A ranger has a good stealth, good perception, good - searching, a good saving throw and is good with magical devices. + developed a special affinity for the natural world. He or she + is a good fighter and also good with missile weapons such as + bows. A ranger has good stealth, good perception, good + searching, good saving throws and is good with magical devices. Intelligence determines a Ranger's spell casting ability. All rangers are trained in Nature magic, and all Nature spells are @@ -579,10 +580,10 @@ command("U"/"O"). A Paladin is a combination of a warrior and a priest. Paladins are very good fighters, but not very good at missile weapons. A - paladin lacks much in the way of abilities. He is poor at + paladin lacks much in the way of abilities. He or she is poor at stealth, perception, searching, and magical devices but has a decent saving throw due to his divine alliance. Wisdom determines - a Paladin's success at praying to his deity. + a Paladin's success at praying to his or her deity. Paladins can select a realm from Crusade and Death. Like priests, they cannot select which prayers to learn, but are rewarded with @@ -599,11 +600,11 @@ command("U"/"O"). --- Warrior-Mage --- A Warrior-Mage is precisely what the name suggests: a cross - between the warrior and mage classes. While their brothers, the - rangers, specialize in Nature magic and survival skills, true - Warrior-Mages attempt to reach the best of both worlds. As - warriors they are much superior to the usual Mage class. - Intelligence determines a Warrior-Mage's spell casting ability. + between the warrior and mage classes. Unlike rangers, who + specialize in Nature magic and survival skills, true Warrior- + Mages attempt to reach the best of both worlds. As warriors + they are much superior to the usual Mage class. Intelligence + determines a Warrior-Mage's spell casting ability. Warrior-mages begin the game with Arcane magic, and they can freely select another realm of magic. Although they do not gain @@ -619,14 +620,14 @@ command("U"/"O"). Chaos Warriors are the feared servants of the terrible Demon Lords of Chaos. Every Chaos Warrior has a Patron Demon and, when - gaining a level, may receive a reward from his Patron. He might - be healed or polymorphed, his stats could be increased, or he - might be rewarded with an awesome weapon. On the other hand, the - Patrons might surround him with monsters, drain his stats or wreck - his equipment or they might simply ignore him. The Demon Lords of - Chaos are chaotic and unpredictable indeed. The exact type of - reward depends on both the Patron Demon (different Demons give - different rewards) and chance. + gaining a level, may receive a reward from his or her Patron. He + or she might be healed or polymorphed, given an awesome weapon, + or have his or her stats increased. On the other hand, the Patron + might surround the Chaos Warrior with monsters, drain his or her + stats, wreck his or her equipment, or simply ignore the Chaos + Warrior. The Demon Lords of Chaos are chaotic and unpredictable + indeed. The exact type of reward depends on both the Patron Demon + (different Demons give different rewards) and chance. Chaos Warriors can select a realm from Chaos and Daemon. They are not interested in any other form of magic. They can learn every @@ -641,11 +642,11 @@ command("U"/"O"). Their training in martial arts makes them much more powerful with no armor or weapons. To gain the resistances necessary for survival a monk may need to wear some kind of armor, but if the - armor he wears is too heavy, it will severely disturb his martial - arts maneuvers. As the monk advances levels, new, powerful forms - of attack become available. Their defensive capabilities increase - likewise, but if armour is being worn, this effect decreases. - Wisdom determines a Monk's spell casting ability. + armor he or she wears is too heavy, it will severely disturb his + or her martial arts maneuvers. As the monk advances levels, new, + powerful forms of attack become available. Their defensive + capabilities increase likewise, but if armour is being worn, this + effect decreases. Wisdom determines a Monk's spell casting ability. The different sects of monks are devoted to different areas of magic. They select a realm from Life, Nature, Craft, and Death. @@ -680,13 +681,13 @@ command("U"/"O"). High-mages are mages who specialize in one particular field of magic and learn it very well - much better than the ordinary mage. A high mage's prime statistic is intelligence as this determines - his spell casting ability. + his or her spell casting ability. For the price of giving up a second realm of magic, High-mages gain substantial benefits in the mana costs, minimum levels, and failure rates of the spells in their speciality realm. They have a class power - 'Eat Magic' - which absorbs mana from wands, - staves, or rods. + staffs, or rods. And then, only High-Mages are able to cast Hex spells. @@ -695,7 +696,7 @@ command("U"/"O"). --- Tourist --- Tourists have visited this world for the purpose of sightseeing. - Their fighting skills is bad, and they cannot cast powerful + Their fighting skills are bad, and they cannot cast powerful spells. They are the most difficult class to win the game with. Intelligence determines a tourist's spell casting ability. @@ -719,24 +720,24 @@ command("U"/"O"). When monsters in view use spells, they are added to a temporary spell list which the imitator can choose among. Spells should be imitated quickly, because timing and situation are everything. An - imitator can only repeat a spell once each time he observes it. - They only have a small long-term memory for spells, which ranges - from one to three, depending on their level. When they memorize - more spells than this, they will forget the oldest spell in the - list. They have a class power - 'Double Revenge' - which allows - them to imitate spells at double damage or duration. + imitator can only repeat a spell once each time he or she observes + it. They only have a small long-term memory for spells, which + ranges from one to three, depending on their level. When they + memorize more spells than this, they will forget the oldest spell + in the list. They have a class power - 'Double Revenge' - which + allows them to imitate spells at double damage or duration. ***** --- BeastMaster --- Beastmasters are in tune with the minds of the creatures of the - world of Hengband. They are very good at riding, and have enough - fighting ability. They use monsters which summoned or dominated - by him as his hands and feet. Beastmasters can cast trump magic, - and very good at summoning spell, but they can not summon - non-living creatures. Charisma determines a Beastmaster's spell - casting ability. + world of Bakabakaband. They are very good at riding, and have enough + fighting ability. The monsters that a beastmaster summons or + dominates become the beastmaster's hands and feet. Beastmasters + can cast trump magic and are very good at summoning spells, but + they can not summon non-living creatures. Charisma determines a + Beastmaster's spell casting ability. Beastmasters use Trump magic to make good use of their monster domination and riding abilities. They are very good at summoning @@ -757,7 +758,7 @@ command("U"/"O"). Sorcerers can cast any spell from any spellbooks of all nine magic realms with 'Master' proficiency level without having to learn it. They have a class power - 'Eat Magic' - which absorbs mana from - wands, staves or rods. + wands, staffs or rods. ***** @@ -836,7 +837,7 @@ command("U"/"O"). techniques. Samurai are not good at most other skills, and many magical devices may be too difficult for them to use. Wisdom determines a Samurai's ability to use the special combat - techniques available to him. + techniques available to him or her. Samurai use the art of the blade called Kendo (or Bugei). Books of Kendo are similar to spellbooks, but Samurai don't need to @@ -855,7 +856,7 @@ command("U"/"O"). --- ForceTrainer --- A ForceTrainer is a master of the spiritual Force. They prefer - fighting with neither weapon nor armor. They are not as good + fighting with neither weapons nor armor. They are not as good fighters as are Monks, but they can use both magic and the spiritual Force. Wielding weapons or wearing heavy armor disturbs use of the Force. Wisdom is a ForceTrainer's primary stat. @@ -877,12 +878,12 @@ command("U"/"O"). ***** --- Blue-Mage --- - A Blue-Mage is a spell caster that must live by his wits, as he - cannot hope to simply hack his way through the dungeon like a - warrior. A major difference between the Mage and the Blue-Mage is - the method of learning spells: Blue-Mages may learn spells from - monsters. A Blue-Mage's prime statistic is Intelligence as this - determines his spell casting ability. + A Blue-Mage is a spell caster that must live by his or her wits, + as a Blue-Mage cannot hope to simply hack his or her way through + the dungeon like a warrior. A major difference between the Mage + and the Blue-Mage is the method of learning spells: Blue-Mages + may learn spells from monsters. A Blue-Mage's prime statistic + is Intelligence as this determines his or her spell casting ability. A Blue-Mage can learn and cast monster ranged attacks, spells, or summons as their own spells; this technique is called Blue magic. @@ -931,15 +932,15 @@ command("U"/"O"). ***** --- Weaponsmith --- - A Weaponsmith can improve weapons and armors for him or herself. + A Weaponsmith can improve weapons and armor for him or herself. They are good at fighting, and they have potential ability to - become even better than Warriors using improved equipments. They + become even better than Warriors using improved equipment. They cannot cast spells, and are poor at skills such as stealth or magic defense. A Weaponsmith extract the essences of special effects from weapons - or armors which have various special abilities, and can add these - essences to another weapon or armor. Normally, each equipment can + or armor which have various special abilities, and can add these + essences to another weapon or armor. Normally, each item can be improved only once, but they can remove a previously added essence from improved equipment to improve it with another essence. To-hit, to-damage bonus, and AC can be improved freely @@ -977,7 +978,7 @@ command("U"/"O"). navigate effectively with no light source, catch enemies unawares, and kill with a single blow. Ninjas can use Ninjutsu, and are good at locating hidden traps and doors, disarming traps and - picking locks. Since heavy armors, heavy weapons, or shields will + picking locks. Since heavy armor, heavy weapons, or shields will restrict their motion greatly, they prefer light clothes, and become faster and more stealthy as they gain levels. A Ninja knows no fear and, at high level, becomes almost immune to poison @@ -1011,7 +1012,7 @@ command("U"/"O"). There are twelve different personality that you can choose from in -Hengband. Each personality has various strengths and weaknesses and +Bakabakaband. Each personality has various strengths and weaknesses and its own adjustments to a character's stats and abilities. @@ -1049,8 +1050,7 @@ its own adjustments to a character's stats and abilities. ***** --- Nimble --- - "Nimble" renders you highly skilled comparatively well, but - reduces your physical ability. + "Nimble" improves most skills except for melee combat. ***** @@ -1104,7 +1104,7 @@ its own adjustments to a character's stats and abilities. ***** --- Munchkin --- - "munchkin" is a personality for beginners. It raises all your + "Munchkin" is a personality for beginners. It raises all your stats and skills. With this personality, you can win the game easily, but gain little honor in doing so. @@ -1326,4 +1326,4 @@ the 50th level. -- -Updated : Hengband 1.7.2 +Updated : Bakabakaband 1.7.2 diff --git a/lib/help/tang.txt b/lib/help/tang.txt index 1d7ff66c2..778c7c660 100644 --- a/lib/help/tang.txt +++ b/lib/help/tang.txt @@ -1,9 +1,9 @@ -=== The Hengband Newbie Guide === +=== The Bakabakaband Newbie Guide === Note: This guide has been adapted from The Angband Newbie Guide by Chris Weisiger and has undergone certain revisions to conform more -closely to Hengband. +closely to Bakabakaband. === Basic Training === @@ -15,7 +15,7 @@ spellcaster types; they're much more difficult to play. If you want basic information about races and classes, go to the on-line help (type "?") and read "Character Attributes". You should probably read most of the help files here; the commands list is especially important -to someone new to Hengband. +to someone new to Bakabakaband. After naming your character, you'll start in the town. The various numbers represent stores, where you can buy new equipment and sell @@ -26,7 +26,7 @@ return to the surface. Next, type "<" again on the surface. If there are no hostile monsters near you, you will enters the Global Map mode which displays all the -world of Hengband. Type ">" to return from global map mode to normal +world of Bakabakaband. Type ">" to return from global map mode to normal map mode. If you want to know what a specific symbol stands for, type "/", and @@ -49,15 +49,15 @@ an absolutely ridiculous price. Any good item can show up in this store show up in other stores. -Be sure to visit shops #1 and #2, the General Store and Armory, +Be sure to visit shops #1 and #2, the General Store and Armoury, respectively. At the General Store, buy a cloak and a Brass Lantern, -and a flask of oil or two. Sell your torches. At the Armory, buy some +and a flask of oil or two. Sell your torches. At the Armoury, buy some of the light armor. Suggested: Hard Leather Boots, a Leather Cap, Leather Gloves. If a Small Leather Shield is on sale and you can afford it, buy it. This should have cleaned out your money. However, if it hasn't, it is -strongly recommended that you go to the Alchemist's shop (#5) and +strongly recommended that you go to the Alchemy Shop (#5) and purchase a scroll of Phase Door. If you get surrounded by monsters, read it, and you'll be teleported a short distance away. @@ -67,7 +67,7 @@ rid of old items and buying new ones. If you ever find that there's something you need which the stores don't currently have, you can wait a while for the stores to refresh. -Hengband's not actually all that difficult to learn to play. You should +Bakabakaband's not actually all that difficult to learn to play. You should get the hang of it fairly quickly. From here on we'll be giving detailed dungeon survival information. @@ -170,7 +170,7 @@ damage, and magical bonuses to stats. It also tells you if the item is cursed. It tells you what a wand/rod/staff/potion/scroll/mushroom/etc. does, and this is very important. There are nasty potions deep in the dungeon that you *do not* want to drink! Sometimes, the descriptions of -the items are a little obscure; things like Staves of Holiness and +the items are a little obscure; things like Staffs of Holiness and Power, Mushrooms of Unhealth, and others. You may have to experiment a bit to determine their powers. @@ -208,7 +208,7 @@ not a perfect escape method. === On Resistances ==== -There are many different kinds of attacks in Hengband, generally +There are many different kinds of attacks in Bakabakaband, generally falling under physical, magical, and breath attacks. They can all cause specialized kinds of damage, which can kill a character if he/she does not have resistance to that attack. The majority of attack types have a @@ -224,7 +224,7 @@ draining attacks respectively. Resistances can be provided by certain items and also may be part of your racial characteristics. There are certain types of items that provide all four elemental resistances. These include Defender weapons, -Robes of Permanence, armors/shields of Resistance, armor of Elvenkind, +Robes of Permanence, armor or shields of Resistance, armor of Elvenkind, and Helms/Crowns of the Magi. Many artifacts also provide some or all of the basic resistances, and also perhaps one or two "high" resistances. @@ -275,7 +275,7 @@ you watch, helpless. Confusion and Blindness resistance are vital. If you have these, you can rely on scrolls of Teleportation to get you out of any situation. -Before this, you need Staves of Teleportation which can be activated +Before this, you need Staffs of Teleportation which can be activated when blinded or confused, although with a decent failure rate. Scrolls are fail-safe. @@ -366,7 +366,7 @@ level" which gives you no information whatsoever. === On weapons and armor === Your equipment will always carry around little numbers that tell you -how effective it is. Armors take this form: +how effective it is. Pieces of armor take this form: A Robe (+x,+y) [a,+b] (+c) @@ -374,7 +374,7 @@ Weapons take this form: A Long Sword (XdY) (+x,+y) [+b] (+c) -When unidentified, armors will show just this: +When unidentified, pieces of armor will show just this: A Robe [a] @@ -384,13 +384,14 @@ A Long Sword (XdY) (+x,+y). This is the item's magical bonuses to your to-hit and to-damage bonus respectively. These are added to whatever other -bonuses you have when you attack. Some armors have similar bonuses to -your to-hit and to-damage, but they are mostly artifacts, the -exceptions being Gloves/Gauntlets/Cesti of Slaying and Power. Many -body armors have a small negative number before the base armor bonus -(see below); this is a penalty to your skill (the armor is so heavy -that you have trouble moving around in it). However, this penalty is -small enough for all but the youngest of characters to ignore. +bonuses you have when you attack. Some pieces of armor have +similar bonuses to your to-hit and to-damage, but they are mostly +artifacts, the exceptions being Gloves/Gauntlets/Cesti of Slaying +and Power. Many pieces of body armor have a small negative number +before the base armor bonus (see below); this is a penalty to your +skill (the armor is so heavy that you have trouble moving around +in it). However, this penalty is small enough for all but the +youngest of characters to ignore. Rings of Combat or Skill have a single (+y) or (+x). When worn, they affect your to-damage and to-hit bonus in melee battle respectively. @@ -412,7 +413,7 @@ does not affect every stat in this list! Most items that have a +c only affect one or two of these stats. Some items affect more (A Weapon of Westernesse affects Strength, Dexterity, and Constitution)]. -As a side note for the above: Hengband follows the parenthesis for any +As a side note for the above: Bakabakaband follows the parenthesis for any item. If you see a number in brackets, like this: [b], it is a bonus to AC. If it is in parenthesis, like this: (+x), it is either a bonus to a stat or to hit/damage (and which should normally be obvious by the name @@ -448,19 +449,23 @@ melee weapons.) Many weapons you find in the dungeon are considered to be particularly deadly against a type of creature. These qualities are collectively -known as slays. They double, triple, or multiply by five *the damage -done by the damage dice*. They DO NOT affect bonuses to damage. Thus, -while slays may play an important part in the early game (especially if -you find a weapon of Slay Orc), in the later part of the game, where -magical bonuses to damage all but take over combat, slays play a very -minor role. The rundown on slays: - - Slay (or *Slay*) Evil: x2 damage dice against evil monsters - Slay (or *Slay*) Animal, Undead, Demon, Giant, Dragon: x2 damage - dice against the relevant monster type +known as slays. They multiply *the damage done by the damage dice* by +a value between two and five, depending on the specific quality. They +DO NOT affect bonuses to damage. Thus, while slays may play an +important part in the early game (especially if you find a weapon +of Slay Orc), in the later part of the game, where magical bonuses +to damage all but take over combat, slays play a very minor role. The +rundown on slays: + + Slay (or *Slay*) Evil: x2 (x3.5 for *Slay*) damage dice against + evil monsters + Slay (or *Slay*) Animal, Human: x2.5 (x4.0 for *Slay*) against + the relevant monster type + Slay (or *Slay*) Undead, Demon, Orc, Troll, Giant, Dragon: x3 + (x5 for *Slay*) damage dice against the relevant monster type The brands ("of Melting", "of Burning", "of Freezing", "of Shocking", -and "of Poisoning") all do x2 damage dice to those monsters not +and "of Poisoning") all do x2.5 damage dice to those monsters not resistant to the relevant element. There is also a "(Vampiric)" brand which will suck life from your foes and heal you at the same time and a "(Chaotic)" brand which can cause some unexpected results when using @@ -470,7 +475,7 @@ it! === On the Monster Memory === In many other games, you are required to take notes on monster's -weaknesses, strengths, spells, et cetera. Hengband takes care of this +weaknesses, strengths, spells, et cetera. Bakabakaband takes care of this for you, with the handy Monster Memory. Every time you find out something new about a monster, like that it can breathe fire, this is added to your knowledge of the monster. To look over this knowledge, @@ -502,7 +507,7 @@ are poisonous. A Multi-Hued monster is all of these. === On the Preferences === The preferences screen is reached by typing "=". It contains many -different preferences that make Hengband more enjoyable. There are a few +different preferences that make Bakabakaband more enjoyable. There are a few that I would recommend. Turn both stacking options ON. This maximizes your treasure collection. Turn the Low Hitpoint Warning ON, and place the warning percent at about 50%. You'll see the effects of this @@ -517,12 +522,12 @@ map, and others. === On Death === -Death in Hengband is permanent. Saving in Hengband is meant only to let +Death in Bakabakaband is permanent. Saving in Bakabakaband is meant only to let you pick up where you left off; if you die, your savefile is marked. The next time you try to use the savefile, you will get the new character dialogue. Ancestors of dead characters will retain their monster memory and preferences. Many people here have characters like -"Yuppy XIV"; people die very often in Hengband. +"Yuppy XIV"; people die very often in Bakabakaband. Some people make backup savefiles; if their character dies, they simply load the older character, and pick up where they left off. They lose @@ -538,11 +543,11 @@ truly win the game. It also sets your Social Status to zero, so everyone knows what a scumbag you are. -=== On Hengband Time === +=== On Bakabakaband Time === -If there is one feature of Hengband that tends to confuse people +If there is one feature of Bakabakaband that tends to confuse people (especially veterans of other *band), it is how the speed system in -Hengband works. +Bakabakaband works. As in other variants, the energy you and monsters get each turn depends on speed. Unlike in other variants, this value is only an average; be @@ -563,7 +568,7 @@ Be aware that speeds increases above about +28 to +35 are much less useful. === Advanced techniques for killing monsters === Pillardancing. - Not recommended in Hengband: monsters move at irregular speeds. + Not recommended in Bakabakaband: monsters move at irregular speeds. Shoot'n Scoot. Requires a large room, Phase Door, and some type of missile @@ -594,4 +599,4 @@ The Anti-Summoning Corridor. -- Original : Chris Weisiger (TANG version 1.6.2) Updated : Zangband DevTeam -Updated : Hengband 1.0.11 +Updated : Bakabakaband 1.0.11 diff --git a/lib/help/town.txt b/lib/help/town.txt index daf2f8c56..b8d0c50ea 100644 --- a/lib/help/town.txt +++ b/lib/help/town.txt @@ -1,7 +1,7 @@ === The Town and Wilderness === -After you have created your character, you will begin your Hengband +After you have created your character, you will begin your Bakabakaband adventure in the town called Outpost. Symbols appearing on your screen will represent the walls, floor, objects, features, and creatures lurking about. In order to direct your character through his @@ -72,12 +72,12 @@ passes and if you enter the town at night, the town will be dark. Fortunately, the various shops and the other special buildings are open on a 24-hour basis. -The world of Hengband includes five towns separated by a wilderness +The world of Bakabakaband includes five towns separated by a wilderness and many dungeons. Fixed quests (see below [d]) could be begun by entering certain buildings in the towns. While most people welcome this large world, they are not for everyone -and consequently, there are three possible town options in Hengband - +and consequently, there are three possible town options in Bakabakaband - the 'Standard' town(s), the 'Lite' town and the 'Vanilla' town. The default is the standard town and the lite town and the vanilla town options can be selected by pressing '=' during character @@ -92,7 +92,7 @@ during the creation of your next character. --- The 'Standard' Town --- The 'standard' town consists of a 97x62 square world. Each square -(actually a rectangle) is the size of a standard Hengband dungeon +(actually a rectangle) is the size of a standard Bakabakaband dungeon level and contains themed wilderness terrain (mountainous areas, oceans, plains, etc). There are several towns located in various parts of the world and each town is situated in its own wilderness square. @@ -260,8 +260,8 @@ The General Store ("1") lamps, oil, shovels, picks, and spikes. All of these items and some others can be sold back to the General store for money. -The Armory ("2") - The Armory is where the town's armor is fashioned. All sorts of +The Armoury ("2") + The Armoury is where the town's armor is fashioned. All sorts of protective gear may be bought and sold here. The Weaponsmith's Shop ("3") @@ -274,12 +274,12 @@ The Temple ("4") bless scrolls, word of recall scrolls, some approved priestly weapons, as well as books of Life magic for priests and paladins. -The Alchemy shop ("5") +The Alchemy Shop ("5") The Alchemy Shop deals in all types of potions and scrolls. -The Magic User's Shop ("6") - The Magic User's Shop deals in all sorts of rings, wands, amulets, - and staves, as well as some magic books. +The Magic Shop ("6") + The Magic Shop deals in all sorts of rings, wands, amulets, + and staffs, as well as some magic books. The Black Market ("7") The Black Market will sell and buy anything at extortionate @@ -361,7 +361,7 @@ quest. Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.0.11 +Updated : Bakabakaband 1.0.11 ***** Begin Hyperlinks diff --git a/lib/help/version.txt b/lib/help/version.txt index 1e336287d..85bf34b76 100644 --- a/lib/help/version.txt +++ b/lib/help/version.txt @@ -1,7 +1,7 @@ -=== History of Hengband === +=== History of Bakabakaband === -Jan. 9th, 2004 hengband 1.6.0 (New stable branch) released. +Jan. 9th, 2004 Bakabakaband 1.6.0 (New stable branch) released. This is a bug-fix version of 1.5.4, and the first version of the new stable branch (1.6.x) . @@ -24,7 +24,7 @@ Jan. 9th, 2004 hengband 1.6.0 (New stable branch) released. - All changes for 1.4.5 are also included in 1.6.0 . -Jan. 9th, 2004 hengband 1.4.5 (Old stable branch) released. +Jan. 9th, 2004 Bakabakaband 1.4.5 (Old stable branch) released. This is the final version of old stable branch (1.4.x), and is the final version without the saved floor. @@ -51,7 +51,7 @@ Jan. 9th, 2004 hengband 1.4.5 (Old stable branch) released. Many typo, screen update failures, wrong descriptions etc. -Aug. 12th, 2003 hengband 1.5.4 (Development branch) released. +Aug. 12th, 2003 Bakabakaband 1.5.4 (Development branch) released. - New artifatct amulets. - Special inscription {@ma},{@0} etc. on equip/floor lists are allowed. @@ -65,7 +65,7 @@ Aug. 12th, 2003 hengband 1.5.4 (Development branch) released. - All changes for 1.4.4 are also included in 1.5.4. -Aug. 12th, 2003 hengband 1.4.4 (Stable branch) released. +Aug. 12th, 2003 Bakabakaband 1.4.4 (Stable branch) released. - Various bug fixes: Hidden doors were not hidden on tile graphics mode. @@ -73,7 +73,7 @@ Aug. 12th, 2003 hengband 1.4.4 (Stable branch) released. Repeat didn't work correctly for Forcetrainers when blinded. -Jul. 20th, 2003 hengband 1.5.3 (Development branch) released. +Jul. 20th, 2003 Bakabakaband 1.5.3 (Development branch) released. - Improved Warning ability a bit. - Some English text were corrected. (thanks to an choco) @@ -86,7 +86,7 @@ Jul. 20th, 2003 hengband 1.5.3 (Development branch) released. - All changes for 1.4.3 are also included in 1.5.3. -Jul. 20th, 2003 hengband 1.4.3 (Stable branch) released. +Jul. 20th, 2003 Bakabakaband 1.4.3 (Stable branch) released. - Various bug fixes: Experience gain for killing monsters was zero. @@ -94,7 +94,7 @@ Jul. 20th, 2003 hengband 1.4.3 (Stable branch) released. Mana point was not updated correctly after Clear Mind. -Jul. 10th, 2003 hengband 1.5.2 (Development branch) released. +Jul. 10th, 2003 Bakabakaband 1.5.2 (Development branch) released. - Random artifacts get more 'Construction point' for Android. - Hunter's office gives items as prize now. - Probing gives all monster recall infomations. @@ -130,7 +130,7 @@ Jul. 10th, 2003 hengband 1.5.2 (Development branch) released. - All changes for 1.4.2 are also included in 1.5.2. -Jul. 10th, 2003 hengband 1.4.2 (Stable branch) released. +Jul. 10th, 2003 Bakabakaband 1.4.2 (Stable branch) released. - Cancelling of Racial/Class power no longer takes energy. - The algorism for breath shape is changed. @@ -159,7 +159,7 @@ Jul. 10th, 2003 hengband 1.4.2 (Stable branch) released. Collected update for monster light. etc... - Dec. 24th, 2002 hengband 1.5.1 (Development branch) released. + Dec. 24th, 2002 Bakabakaband 1.5.1 (Development branch) released. - Added visual editor in lists of known objects and etc... (Unangband) - Clairaudience spell of Bard doesn't detect walls with treasure. @@ -170,7 +170,7 @@ Jul. 10th, 2003 hengband 1.4.2 (Stable branch) released. - All changes for 1.4.1 are also included in 1.5.1. - Dec. 24th, 2002 hengband 1.4.1 (Stable branch) released. + Dec. 24th, 2002 Bakabakaband 1.4.1 (Stable branch) released. - Elvish waybread fully satisfies mortals. (from OAngband) - General store sell Elvish waybread. @@ -186,7 +186,7 @@ Jul. 10th, 2003 hengband 1.4.2 (Stable branch) released. Broken name of the Staff, Random teleport in monster arena. - Dec. 9th, 2002 hengband 1.5.0 (Development branch) released. + Dec. 9th, 2002 Bakabakaband 1.5.0 (Development branch) released. Implemented 'Saved Floors': - You can climb back the same stairs to get back to the same floor. @@ -201,12 +201,12 @@ Implemented 'Saved Floors': - Removed detect treasure effect from the Detection spell. - Dec. 9th, 2002 hengband 1.4.0 (Stable branch) released. + Dec. 9th, 2002 Bakabakaband 1.4.0 (Stable branch) released. - Removed scrolls of satisfy hunger and that class power of Berserkers. Androids can quaff flasks of oil. Barlogs can sacrifice corpses with symbol 't','p', or 'h' using the Eat command. - Golems, Zombies, Skeletons, and Spectors can Eat charges of wands and staves. + Golems, Zombies, Skeletons, and Spectors can Eat charges of wands and staffs. Ents can get nutritions from water in any potions. - Added lists of known monsters/objects from Eyangband. - Shift + direction keys will move cursor quickly in the look command. @@ -226,7 +226,7 @@ Implemented 'Saved Floors': Buffer-overflow breaks macro. - Oct. 31st, 2002 hengband 1.3.1 (Development branch) released. + Oct. 31st, 2002 Bakabakaband 1.3.1 (Development branch) released. - Added a new menu 'Keep on top' for subwindows of Windows version - Auto-Inscription-For-Resistances, {%}, will work dynamically. @@ -241,7 +241,7 @@ Implemented 'Saved Floors': - All changes from 1.2.0 to 1.2.2. - Oct. 31st, 2002 hengband 1.2.2 (Stable branch) released. + Oct. 31st, 2002 Bakabakaband 1.2.2 (Stable branch) released. - The Cloning Pits now includes Borshin. - Description of *identified* Light source of darkness now include @@ -251,9 +251,9 @@ Implemented 'Saved Floors': - Fixed many bugs(rod of percention, Royal Crypt, etc...) - Sep. 9th, 2002 hengband 1.2.1 (Stable branch) released. + Sep. 9th, 2002 Bakabakaband 1.2.1 (Stable branch) released. -- Added description about license of Hengband; 'jlicense.txt'. +- Added description about license of Bakabakaband; 'jlicense.txt'. (jlicense.txt is Japanese only for now) - Increased AC of the ego Ring of Protection (Extra Armor) by 7. - Fixed some bug on monster's AI. @@ -266,7 +266,7 @@ Implemented 'Saved Floors': - Fixed some other bug. - Aug. 28th, 2002 hengband 1.3.0 (Development branch) released. + Aug. 28th, 2002 Bakabakaband 1.3.0 (Development branch) released. - Added a new room type; trapped monster pit. - Added object flags of various ESPs. (from Unangband and ToME) @@ -284,7 +284,7 @@ Implemented 'Saved Floors': character making.(from Eyangband) - Aug. 28th, 2002 hengband 1.2.0 (Stable branch) released. + Aug. 28th, 2002 Bakabakaband 1.2.0 (Stable branch) released. - Fixed many bugs - Splited version tree into two branch; @@ -317,13 +317,13 @@ Modifications for auto-picker/destroyer editor: - Do auto-save the game at starting the editor. - Jun. 15th, 2002 hengband 1.1.0 released. + Jun. 15th, 2002 Bakabakaband 1.1.0 released. - Changed behavior of light area. - Various bug fixes and tuning. - Jun. 2nd, 2002 hengband 1.1.0 Release Candidate 1 released. + Jun. 2nd, 2002 Bakabakaband 1.1.0 Release Candidate 1 released. - Splited Life realm into two and new spells added; New 'Life' realm and New 'Crusade' realm. @@ -360,7 +360,7 @@ Modifications for auto-picker/destroyer editor: - Some bugs fixed. - Apl. 6th, 2002 hengband 1.0.11 released. + Apl. 6th, 2002 Bakabakaband 1.0.11 released. - The on-line help files is translated to English - Warning ability of an object can be canceled by its inscription {$}. @@ -379,7 +379,7 @@ Modifications for auto-picker/destroyer editor: - Some bugs fixed. - Mar. 6th, 2002 hengband 1.0.10 released. + Mar. 6th, 2002 Bakabakaband 1.0.10 released. - New artifact, ego-ammo and vault. - Class power of Red-Mage is more useful. @@ -396,11 +396,11 @@ Modifications for auto-picker/destroyer editor: - Screen shot is supported in graphics mode. - Support in MPW environment of Macintosh. - Jan.30th, 2002 hengband 1.0.9 revision 1 released. + Jan.30th, 2002 Bakabakaband 1.0.9 revision 1 released. - Fixed one more bug which cause crash (English version only). - Jan.27th, 2002 hengband 1.0.9 released. + Jan.27th, 2002 Bakabakaband 1.0.9 released. - New character making screen - New character information 'C' screen @@ -411,7 +411,7 @@ Modifications for auto-picker/destroyer editor: 'http://www.kmc.gr.jp/~habu/local/hengscore-en/screens/'. But links on the webpage to the screenshots are not yet available. - Limited support of 8x8 tile graphics. -- Hengband online help in *Japanese*. +- Bakabakaband online help in *Japanese*. (sadly English version of online help is not yet available) - Rune of explosion no longer has anti-summoning effects. - Rune of protection no longer has perfect @@ -422,7 +422,7 @@ Modifications for auto-picker/destroyer editor: - Difficulty to activate random artifact is changed. - Dec.31th, 2001 hengband 108fix2 revision 1 released. + Dec.31th, 2001 Bakabakaband 108fix2 revision 1 released. - 'fix2' is japanese bug fixed version but this bug was not effect on English version. @@ -430,7 +430,7 @@ Modifications for auto-picker/destroyer editor: You can get display of lines of auto picker/destroyer. - Dec.31th, 2001 hengband 108fix1 version 3 released. + Dec.31th, 2001 Bakabakaband 108fix1 version 3 released. - Auto macro dump and other auto dump is now more useful. Old dump lines will be deleted @@ -438,20 +438,20 @@ Modifications for auto-picker/destroyer editor: - A minor typo and a minor bug fixed. - Dec.30th, 2001 hengband 108fix1 version 2 released. + Dec.30th, 2001 Bakabakaband 108fix1 version 2 released. - All remained japanese messages are found and fixed, using a exclusive C program. - You can now define macros in the 'pickpref.prf'. - Dec.29th, 2001 hengband 108fix1 released. + Dec.29th, 2001 Bakabakaband 108fix1 released. - This is a bug fixed japanese version, and almost - same as 108eng3, but a few more bugs are fixed. - Dec.25th, 2001 hengband 108eng2(stable) and 108eng3(test version) released. + Dec.25th, 2001 Bakabakaband 108eng2(stable) and 108eng3(test version) released. - 108eng2: fixed some typo. ']' key now can be used as macro key. - 108eng3: macro trigger is displayed in more suitable way; @@ -460,9 +460,9 @@ Modifications for auto-picker/destroyer editor: key on Windows now; \[alt-A] or \[shift-alt-B]. - Dec.24th, 2001 hengband 108eng1: makefile.bcc was not work. now fixed. + Dec.24th, 2001 Bakabakaband 108eng1: makefile.bcc was not work. now fixed. - Dec.24th, 2001 hengband 1.0.8 released. This is a new Japanese version. + Dec.24th, 2001 Bakabakaband 1.0.8 released. This is a new Japanese version. The source can be used to compile English version too. - The address of the world score server is changed. @@ -474,7 +474,7 @@ The source can be used to compile English version too. - Yet another japanese massage was translated. - Dec.17th, 2001 hengband 1.0.7fix2 english beta4 released. + Dec.17th, 2001 Bakabakaband 1.0.7fix2 english beta4 released. - Yet another remained japanese messages are now translated. - Changed some option info texts and names again. @@ -482,20 +482,20 @@ The source can be used to compile English version too. - Some bugs related groo and Metal Babble is fixed. - Dec.11th, 2001 hengband 1.0.7fix2 english beta3 released. + Dec.11th, 2001 Bakabakaband 1.0.7fix2 english beta3 released. - fixed a compile error. English info message of artifacts added. - changed some info text and name of options. - Dec. 9th, 2001 hengband 1.0.7fix2 english beta2 released. + Dec. 9th, 2001 Bakabakaband 1.0.7fix2 english beta2 released. - fixed a terrible bug, - items in the home was not saved when more than 24 items stored. - Binary for Macintosh (ppc, osX) is now available. - Dec. 8th, 2001 hengband 1.0.7fix2 english beta released. + Dec. 8th, 2001 Bakabakaband 1.0.7fix2 english beta released. - Many mistakes of English messages, and bugs are fixed. @@ -505,10 +505,10 @@ The source can be used to compile English version too. - fixed some mistakes of archives. - Dec. 4th, 2001 hengband 1.0.7fix2 english alpha version released. + Dec. 4th, 2001 Bakabakaband 1.0.7fix2 english alpha version released. -=== The main differences of Hengband 1.0.7 from ZAngband2.2.8 === +=== The main differences of Bakabakaband 1.0.7 from ZAngband2.2.8 === - World score server: You can register scores and character dumps. - Player can write last words when died, which is displayed in the @@ -1200,4 +1200,4 @@ Angband Version 2.7 : 1/1/95 Ben Harrison Original : (??) Updated : (??) Updated : Zangband DevTeam -Updated : Hengband 1.5.3 +Updated : Bakabakaband 1.5.3 diff --git a/lib/pref/Makefile.am b/lib/pref/Makefile.am index 65e6bf0d7..6714e807a 100644 --- a/lib/pref/Makefile.am +++ b/lib/pref/Makefile.am @@ -6,7 +6,7 @@ angband_files = \ font-ami.prf font-dos.prf font-ibm.prf font-mac.prf \ font-mon.prf font-win.prf font-x11.prf font-xxx.prf \ font.prf graf-ami.prf graf-dos.prf graf-gcu.prf \ - graf-ibm.prf graf-mac.prf graf-new.prf graf-win.prf \ + graf-ibm.prf graf-mac.prf graf-new.prf graf-ne2.prf graf-win.prf \ graf-x11.prf graf-xaw.prf graf-xxx.prf graf.prf \ pref-acn.prf pref-ami.prf pref-emx.prf pref-gcu.prf \ pref-key.prf pref-mac.prf pref-opt.prf pref-win.prf \ diff --git a/lib/pref/graf-ne2.prf b/lib/pref/graf-ne2.prf index 935105fe0..8b0dd27bf 100644 --- a/lib/pref/graf-ne2.prf +++ b/lib/pref/graf-ne2.prf @@ -2,7 +2,7 @@ # # This file defines special attr/char mappings for use in "graphics" mode -# with Hengband 32x32. +# with Bakabakaband 32x32. # See "lib/help/command.txt" and "src/files.c" for more information. # diff --git a/lib/pref/graf-win.prf b/lib/pref/graf-win.prf index ed8029984..69098327c 100644 --- a/lib/pref/graf-win.prf +++ b/lib/pref/graf-win.prf @@ -15,6 +15,6 @@ ?:[EQU $GRAF new] %:graf-new.prf -# Hengband tiles +# Bakabakaband tiles ?:[EQU $GRAF ne2] %:graf-ne2.prf diff --git a/lib/xtra/music/Makefile.am b/lib/xtra/music/Makefile.am index 44812f785..c6991e704 100644 --- a/lib/xtra/music/Makefile.am +++ b/lib/xtra/music/Makefile.am @@ -1,4 +1,5 @@ ## Makefile.am -- Process this file with automake to process Makefile.in EXTRA_DIST = \ - delete.me + delete.me \ + music.cfg diff --git a/lib/xtra/music/music.cfg b/lib/xtra/music/music.cfg index e7e3346b1..c241ddbd8 100644 --- a/lib/xtra/music/music.cfg +++ b/lib/xtra/music/music.cfg @@ -1,7 +1,7 @@ # ¡•Ï‹ð”Ø“{BGMÝ’èƒtƒ@ƒCƒ‹ # lib\xtra\music‚É‚±‚̃tƒ@ƒCƒ‹‚ƍж‚µ‚½‚¢BGMƒtƒ@ƒCƒ‹‚ð’u‚«A # ƒRƒƒ“ƒg‚ɏ]‚Á‚Đݒ肵‚ĉº‚³‚¢B -# ƒtƒ@ƒCƒ‹‚̓Xƒy[ƒX‚Å‹æØ‚Á‚Ä8Ží—Þ‚Ü‚ÅŽw’è‚Å‚«‚Ü‚·B +# ƒtƒ@ƒCƒ‹‚̓Xƒy[ƒX‚Å‹æØ‚Á‚Ä16Ží—Þ‚Ü‚ÅŽw’è‚Å‚«‚Ü‚·B # •¡”Žw’肵‚½ê‡ƒ‰ƒ“ƒ_ƒ€‚É‘I‘ð‚³‚ê‚Ü‚·B diff --git a/lib/xtra/sound/Makefile.am b/lib/xtra/sound/Makefile.am index e8d86cdb7..8a1cca798 100644 --- a/lib/xtra/sound/Makefile.am +++ b/lib/xtra/sound/Makefile.am @@ -1,4 +1,22 @@ ## Makefile.am -- Process this file with automake to process Makefile.in EXTRA_DIST = \ - sound.cfg + readme.txt \ + sound.cfg \ + $(sound_files) + +sound_files = \ + se_maoudamashii_voice_monster01.wav \ + apple1-r.wav \ + decision25r.wav \ + drop1.wav \ + enemy-advent1-r.wav \ + sea-lion2-r.wav \ + se_maoudamashii_battle07.wav \ + se_maoudamashii_retro22.wav \ + se_maoudamashii_se_drink01.wav \ + se_maoudamashii_se_footstep01.wav \ + sword-clash1-r.wav \ + sword-drawn1-r.wav \ + sword-gesture3-r.wav \ + sword-slash3-r.wav diff --git a/markdown/history.md b/markdown/history.md index 3f8fd217c..2d5158e81 100644 --- a/markdown/history.md +++ b/markdown/history.md @@ -113,7 +113,7 @@ - 保存フロアの仕様を持たない1.4.xブランチの真の最終版。 - 一部職業のレベル別称号の変更。 - - 変愚蛮怒を起動したままWindowsをシャットダウンした場合にセーブする。 + - 馬鹿馬鹿蛮怒を起動したままWindowsをシャットダウンした場合にセーブする。 - Windows版とMac版で、バグで強制終了した場合にゲームを緊急セーブする。 - 練気術師が魔法書を使えない場合に専用プロンプトを通す。 - ランダムクエスターはvaultには配置されない。 @@ -504,7 +504,7 @@ - X11では、追加オプション -a と -o で16x16か8x8のタイルを選択 - 8x8タイルで、光源と視界の範囲を明るく表示タイルの重ね合せ表示にも対応 - タイル表示でもスクリーンショットを送信できる - - 初心者ガイド(lib/help/tang.txt)を変愚蛮怒対応にした + - 初心者ガイド(lib/help/tang.txt)を馬鹿馬鹿蛮怒対応にした - 幻覚状態の死因は普通に表示 - バグ修正 @@ -524,7 +524,7 @@ - 浮遊が付いてなくても荷物が軽ければ水の上を走れる - モンスターの追跡ルーチン関係を変更 - 8x8タイルを標準でつける (タイル書いてくれる人募集中) - - 日本語版のZ240ヘルプを元に変愚蛮怒ヘルプを作成 + - 日本語版のZ240ヘルプを元に馬鹿馬鹿蛮怒ヘルプを作成 - ペット爆破の魔法でユニークモンスターを破壊できない - オプションの位置変更 - 仙術の魔法の爆発のルーンと次元の扉を場所交換 @@ -600,7 +600,7 @@ - 街の主変更 - トロルの王の色変更 - 標準設定ファイルをlib/prefに移動 - - (UNIX限定)ユーザディレクトリをlib/user/から~/.angband/Hengband/に変更 + - (UNIX限定)ユーザディレクトリをlib/user/から~/.angband/Bakabakaband/に変更 - クエストコマンドの表示を改良 - クエストの報酬で既に持っているアーティファクトは出ない(代わりに獲得の巻物) - ロケットはモンスターに当たると止まる diff --git a/markdown/history/history1.0.10.md b/markdown/history/history1.0.10.md index 646266aeb..95229d2e0 100644 --- a/markdown/history/history1.0.10.md +++ b/markdown/history/history1.0.10.md @@ -26,7 +26,7 @@ - X11では、追加オプション -a と -o で16x16か8x8のタイルを選択 - 8x8タイルで、光源と視界の範囲を明るく表示タイルの重ね合せ表示にも対応 - タイル表示でもスクリーンショットを送信できる - - 初心者ガイド(lib/help/tang.txt)を変愚蛮怒対応にした + - 初心者ガイド(lib/help/tang.txt)を馬鹿馬鹿蛮怒対応にした - 幻覚状態の死因は普通に表示 - バグ修正 diff --git a/markdown/history/history1.0.6.md b/markdown/history/history1.0.6.md index 32a71bdb9..5bf1978ba 100644 --- a/markdown/history/history1.0.6.md +++ b/markdown/history/history1.0.6.md @@ -14,7 +14,7 @@ - 街の主変更 - トロルの王の色変更 - 標準設定ファイルをlib/prefに移動 - - (UNIX限定)ユーザディレクトリをlib/user/から~/.angband/Hengband/に変更 + - (UNIX限定)ユーザディレクトリをlib/user/から~/.angband/Bakabakaband/に変更 - クエストコマンドの表示を改良 - クエストの報酬で既に持っているアーティファクトは出ない(代わりに獲得の巻物) - ロケットはモンスターに当たると止まる diff --git a/markdown/history/history1.0.9.md b/markdown/history/history1.0.9.md index 84b4308f4..df0f38b2f 100644 --- a/markdown/history/history1.0.9.md +++ b/markdown/history/history1.0.9.md @@ -15,7 +15,7 @@ - 浮遊が付いてなくても荷物が軽ければ水の上を走れる - モンスターの追跡ルーチン関係を変更 - 8x8タイルを標準でつける (タイル書いてくれる人募集中) - - 日本語版のZ240ヘルプを元に変愚蛮怒ヘルプを作成 + - 日本語版のZ240ヘルプを元に馬鹿馬鹿蛮怒ヘルプを作成 - ペット爆破の魔法でユニークモンスターを破壊できない - オプションの位置変更 - 仙術の魔法の爆発のルーンと次元の扉を場所交換 diff --git a/markdown/history/history1.6.6.md b/markdown/history/history1.6.6.md index 45e6bdc61..831ed281c 100644 --- a/markdown/history/history1.6.6.md +++ b/markdown/history/history1.6.6.md @@ -3,7 +3,7 @@ - 保存フロアの仕様を持たない1.4.xブランチの真の最終版。 - 一部職業のレベル別称号の変更。 - - 変愚蛮怒を起動したままWindowsをシャットダウンした場合にセーブする。 + - 馬鹿馬鹿蛮怒を起動したままWindowsをシャットダウンした場合にセーブする。 - Windows版とMac版で、バグで強制終了した場合にゲームを緊急セーブする。 - 練気術師が魔法書を使えない場合に専用プロンプトを通す。 - ランダムクエスターはvaultには配置されない。 diff --git a/markdown/template.html b/markdown/template.html index 4287b0a3d..55cb0f836 100644 --- a/markdown/template.html +++ b/markdown/template.html @@ -2,8 +2,8 @@ - - + + $for(author-meta)$ @@ -74,7 +74,7 @@ $endfor$ - 変愚蛮怒 Hengband + 馬鹿馬鹿蛮怒 Bakabakaband @@ -137,8 +137,8 @@ $endfor$ diff --git a/readme.txt b/readme.txt index c09bf1710..8ce7998a7 100644 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ ●Windows Windows用バイナリをダウンロードし、適当なフォルダに展開します。 - 後は展開したフォルダに移動し、hengbandをクリックすれば遊べます。 + 後は展開したフォルダに移動し、Bakabakabandをクリックすれば遊べます。 ・Windows版独自の機能(by Kokaさん) Option - 壁紙を使う で壁紙を設定できます。 @@ -12,18 +12,18 @@ ●UNIX ソースをダウンロードします。そして、 - tar -jxvf hengband-x.x.x.tar.bz2 - cd hengband-x.x.x + tar -jxvf Bakabakaband-x.x.x.tar.bz2 + cd Bakabakaband-x.x.x ./configure make install でコンパイル及びトップディレクトリへのコピーができます(x.x.x はバージョン番号)。 後は、ASCII文字画面なら、 - ./hengband -- -n<ウィンドウの数> + ./Bakabakaband -- -n<ウィンドウの数> タイルグラフィックス画面なら、 - ./hengband -g -- -n<ウィンドウの数> ## 通常の8x8タイル - ./hengband -g -- -b -n<ウィンドウの数> ## 2倍幅サイズのタイル - ./hengband -g -- -a -n<ウィンドウの数> ## 16x16タイル(別配布のタイルが必要) + ./Bakabakaband -g -- -n<ウィンドウの数> ## 通常の8x8タイル + ./Bakabakaband -g -- -b -n<ウィンドウの数> ## 2倍幅サイズのタイル + ./Bakabakaband -g -- -a -n<ウィンドウの数> ## 16x16タイル(別配布のタイルが必要) 等で遊べます。 また、スーパーユーザーとして setgid を付けてインストールしたい場合は、 @@ -247,7 +247,7 @@ ●マクロ - 変愚蛮怒ではある一連の動作を1つのキーに割り当てることができます。 + 馬鹿馬鹿蛮怒ではある一連の動作を1つのキーに割り当てることができます。 例えば、a)の位置に[カオスの徴]を持っているときにマジックミサイルの魔法を 使うとき、普通のコマンド入力ではまず'm'で魔法の使用を選択、'a'で 魔法書[カオスの徴]を選択、'a'でマジックミサイルを選択、というふうになります。 @@ -270,7 +270,7 @@ ●銘 - 変愚蛮怒ではアイテムに対して'{'コマンドで「銘」をつけることができます。 + 馬鹿馬鹿蛮怒ではアイテムに対して'{'コマンドで「銘」をつけることができます。 ただ好きな名前を付けるだけでなく、一部の文字には特別な効果があります。 どの文字にどういう効果があるかについて、次に解説します。 なお、文中のコマンドはオリジナルキー配置でのコマンドを示します。 @@ -392,7 +392,7 @@ ●プレイ記録 - UNIXでは ~/.angband/Hengband/ 、それ以外のOSでは変愚蛮怒の中の lib/user/ の + UNIXでは ~/.angband/Bakabakaband/ 、それ以外のOSでは馬鹿馬鹿蛮怒の中の lib/user/ の ディレクトリに playrecord-(名前).txt というファイル名でプレイ記録があります。 ゲーム中に'|'コマンドで見ることができます。 どういう行動をしたときに記録をするかは'='コマンドのオプション設定で、 @@ -411,5 +411,5 @@ -------- Mr.hoge -http://hengband.sourceforge.jp/ +http://Bakabakaband.sourceforge.jp/ echizenï¼ users.sourceforge.jp diff --git a/readme_eng.txt b/readme_eng.txt index 7d3c4bdaf..39a8f4ccb 100644 --- a/readme_eng.txt +++ b/readme_eng.txt @@ -3,8 +3,8 @@ --- UNIX Download source archive and try... - tar -zxvf hengband-x.x.x.tar.gz - cd hengband-x.x.x + tar -zxvf Bakabakaband-x.x.x.tar.gz + cd Bakabakaband-x.x.x ./configure --disable-japanese make install @@ -13,11 +13,11 @@ If you are a super user, --with-setgid=games option works. then try - ./hengband -- -n ## for normal ASCII graphics + ./Bakabakaband -- -n ## for normal ASCII graphics or - ./hengband -g -- -n<# of windows> ## for 8x8 tile graphics - ./hengband -g -- -b -n<# of windows> ## for Bigtile graphics - ./hengband -g -- -a -n<# of windows> ## for 16x16 tile (need heng_graf.tar.gz) + ./Bakabakaband -g -- -n<# of windows> ## for 8x8 tile graphics + ./Bakabakaband -g -- -b -n<# of windows> ## for Bigtile graphics + ./Bakabakaband -g -- -a -n<# of windows> ## for 16x16 tile (need heng_graf.tar.gz) to play. You can change game windows' font, location, and size, by environment @@ -25,7 +25,7 @@ variables. Ex. setenv ANGBAND_X11_FONT '-*-*-medium-r-normal--24-*-*-*-*-*-iso8859-1' -hengband -- -n +Bakabakaband -- -n Then font size will be changed. @@ -38,7 +38,7 @@ Size of windows are ANGBAND_X11_COLS_n, and ANGBAND_X11_ROWS_n. --- Windows Download the binary archive for Windows. -Unzip it, and click hengband to play. +Unzip it, and click Bakabakaband to play. The makefile.bcc was changed again. If you want to compile from the source with borland compiler (BCC), @@ -56,7 +56,7 @@ or makefile.dos before MAKE with these. --- Macintosh Download the binary archive for Macintosh. -Unpack it, and click hengband to play. +Unpack it, and click Bakabakaband to play. @@ -165,7 +165,7 @@ keyset, and by pushing 'x' in the Rogue-like keyset. --- Inscriptions -Below, only the new features in Hengband are explained. +Below, only the new features in Bakabakaband are explained. - You can inscribe on objects with "@ma" or '@'++. Then, type these alphabet letter in 'm' command to cast from the spellbook. @@ -186,9 +186,9 @@ Below, only the new features in Hengband are explained. ---- Auto pickup/destroy -Hengband offers two different methods of auto-pickup/destroy. +Bakabakaband offers two different methods of auto-pickup/destroy. - Powerful method - Hengband offers a very powerful auto-pickup/auto-destroy system + Bakabakaband offers a very powerful auto-pickup/auto-destroy system which you may customize. Press '_' key to enter edit mode. Please read the file "autopick_eng.txt" about the syntax. @@ -224,7 +224,7 @@ Hengband offers two different methods of auto-pickup/destroy. ------ Play Record Play record will be written to a file named 'playrec-.txt' in the same directory as your user preference file. It is in ~/.angband/ -Hengband/ for UNIX, or hengband/lib/user/ for other OS. +Bakabakaband/ for UNIX, or Bakabakaband/lib/user/ for other OS. '|' command displays play record in the game. @@ -237,5 +237,5 @@ by modifying data or source files, or by restoring from a backed up savefile. The score server is here: - http://hengband.sourceforge.jp/en/score.html + http://Bakabakaband.sourceforge.jp/en/score.html diff --git a/src/Makefile.am b/src/Makefile.am index 99ea8ea79..0f58bb2c0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,73 +1,588 @@ ## Makefile.am -- Process this file with automake to process Makefile.in -AUTOMAKE_OPTIONS = foreign +AUTOMAKE_OPTIONS = foreign subdir-objects nostdinc -bin_PROGRAMS = hengband +bin_PROGRAMS = Bakabakaband -hengband_SOURCES = \ - artifact.c artifact.h \ +Bakabakaband_SOURCES = \ + action/action-limited.c action/action-limited.h \ + action/activation-execution.c action/activation-execution.h \ + action/movement-execution.c action/movement-execution.h \ + action/mutation-execution.c action/mutation-execution.h \ + action/open-util.c action/open-util.h \ + action/open-close-execution.c action/open-close-execution.h \ + action/racial-execution.c action/racial-execution.h \ + action/run-execution.c action/run-execution.h \ + action/throw-util.c action/throw-util.h \ + action/travel-execution.c action/travel-execution.h \ + action/tunnel-execution.c action/tunnel-execution.h \ + action/weapon-shield.c action/weapon-shield.h \ \ - angband.h autopick.c \ + artifact/artifact-info.c artifact/artifact-info.h \ + artifact/fixed-art-generator.c artifact/fixed-art-generator.h \ + artifact/random-art-activation.c artifact/random-art-activation.h \ + artifact/random-art-bias-types.h \ + artifact/random-art-characteristics.c artifact/random-art-characteristics.h \ + artifact/random-art-generator.c artifact/random-art-generator.h \ + artifact/random-art-misc.c artifact/random-art-misc.h \ + artifact/random-art-pval-investor.c artifact/random-art-pval-investor.h \ + artifact/random-art-resistance.c artifact/random-art-resistance.h \ + artifact/random-art-slay.c artifact/random-art-slay.h \ \ - avatar.h avatar.c \ + art-definition/art-accessory-types.h \ + art-definition/art-armor-types.h \ + art-definition/art-bow-types.h \ + art-definition/art-protector-types.h \ + art-definition/art-sword-types.h \ + art-definition/art-weapon-types.h \ + art-definition/random-art-effects.h \ \ - birth.c bldg.c chest.c chest.h chuukei.c \ - cmd2.c cmd4.c cmd-activate.c cmd-activate.h cmd-eat.c cmd-eat.h \ - cmd-item.c cmd-item.h cmd-magiceat.c cmd-magiceat.h \ - cmd-mane.c cmd-mane.h cmd-pet.c cmd-pet.h \ - cmd-quaff.c cmd-quaff.h cmd-read.c cmd-read.h cmd-spell.c cmd-spell.h \ - cmd-usestaff.c cmd-usestaff.h cmd-zaprod.c cmd-zaprod.h cmd-zapwand.c \ - cmd-zapwand.h cmd-smith.c cmd-smith.h cmd-hissatsu.c cmd-hissatsu.h\ + autopick/autopick.c autopick/autopick.h \ + autopick/autopick-commands-table.h autopick/autopick-dirty-flags.h \ + autopick/autopick-editor-table.h autopick/autopick-flags-table.h \ + autopick/autopick-key-flag-process.h autopick/autopick-keys-table.h \ + autopick/autopick-menu-data-table.c autopick/autopick-menu-data-table.h \ + autopick/autopick-methods-table.h \ + autopick/autopick-util.c autopick/autopick-util.h \ + autopick/autopick-entry.c autopick/autopick-entry.h \ + autopick/autopick-initializer.c autopick/autopick-initializer.h \ + autopick/autopick-matcher.c autopick/autopick-matcher.h \ + autopick/autopick-describer.c autopick/autopick-describer.h \ + autopick/autopick-destroyer.c autopick/autopick-destroyer.h \ + autopick/autopick-reader-writer.c autopick/autopick-reader-writer.h \ + autopick/autopick-finder.c autopick/autopick-finder.h \ + autopick/autopick-pref-processor.c autopick/autopick-pref-processor.h \ + autopick/autopick-drawer.c autopick/autopick-drawer.h \ + autopick/autopick-inserter-killer.c autopick/autopick-inserter-killer.h \ + autopick/autopick-registry.c autopick/autopick-registry.h \ + autopick/autopick-command-menu.c autopick/autopick-command-menu.h \ + autopick/autopick-editor-util.c autopick/autopick-editor-util.h \ + autopick/autopick-editor-command.c autopick/autopick-editor-command.h \ \ - defines.h dungeon.c effects.c externs.h files.c flavor.c \ + birth/birth-explanations-table.c birth/birth-explanations-table.h \ + birth/character-builder.c birth/character-builder.h \ + birth/history.c birth/history.h \ + birth/birth-util.c birth/birth-util.h \ + birth/birth-select-realm.c birth/birth-select-realm.h \ + birth/quick-start.c birth/quick-start.h \ + birth/birth-stat.c birth/birth-stat.h \ + birth/history-generator.c birth/history-generator.h \ + birth/birth-body-spec.c birth/birth-body-spec.h \ + birth/initial-equipments-table.c birth/initial-equipments-table.h \ + birth/inventory-initializer.c birth/inventory-initializer.h \ + birth/game-play-initializer.c birth/game-play-initializer.h \ + birth/history-editor.c birth/history-editor.h \ + birth/birth-select-race.c birth/birth-select-race.h \ + birth/birth-select-class.c birth/birth-select-class.h \ + birth/birth-select-personality.c birth/birth-select-personality.h \ + birth/auto-roller.c birth/auto-roller.h \ + birth/birth-wizard.c birth/birth-wizard.h \ \ - floor.h floor-events.c floor-events.h floor-generate.c floor-generate.h \ - floor-save.h floor-save.c \ - floor-streams.c floor-streams.h \ + blue-magic/blue-magic-ball-bolt.c blue-magic/blue-magic-ball-bolt.h \ + blue-magic/blue-magic-breath.c blue-magic/blue-magic-breath.h \ + blue-magic/blue-magic-caster.c blue-magic/blue-magic-caster.h \ + blue-magic/blue-magic-checker.c blue-magic/blue-magic-checker.h \ + blue-magic/blue-magic-spirit-curse.c blue-magic/blue-magic-spirit-curse.h \ + blue-magic/blue-magic-status.c blue-magic/blue-magic-status.h \ + blue-magic/blue-magic-summon.c blue-magic/blue-magic-summon.h \ + blue-magic/blue-magic-util.c blue-magic/blue-magic-util.h \ + blue-magic/learnt-info.c blue-magic/learnt-info.h \ + blue-magic/learnt-power-getter.c blue-magic/learnt-power-getter.h \ \ - feature.c feature.h \ - geometry.c geometry.h \ + cmd-action/cmd-attack.c cmd-action/cmd-attack.h \ + cmd-action/cmd-hissatsu.c cmd-action/cmd-hissatsu.h \ + cmd-action/cmd-mane.c cmd-action/cmd-mane.h \ + cmd-action/cmd-mind.c cmd-action/cmd-mind.h \ + cmd-action/cmd-move.c cmd-action/cmd-move.h \ + cmd-action/cmd-open-close.c cmd-action/cmd-open-close.h \ + cmd-action/cmd-others.c cmd-action/cmd-others.h \ + cmd-action/cmd-pet.c cmd-action/cmd-pet.h \ + cmd-action/cmd-racial.c cmd-action/cmd-racial.h \ + cmd-action/cmd-shoot.c cmd-action/cmd-shoot.h \ + cmd-action/cmd-spell.c cmd-action/cmd-spell.h \ + cmd-action/cmd-travel.c cmd-action/cmd-travel.h \ + cmd-action/cmd-tunnel.c cmd-action/cmd-tunnel.h \ + \ + cmd-building/cmd-building.c cmd-building/cmd-building.h \ + cmd-building/cmd-inn.c cmd-building/cmd-inn.h \ + cmd-building/cmd-store.c cmd-building/cmd-store.h \ + \ + cmd-io/cmd-autopick.c cmd-io/cmd-autopick.h \ + cmd-io/cmd-diary.c cmd-io/cmd-diary.h \ + cmd-io/cmd-dump.c cmd-io/cmd-dump.h \ + cmd-io/cmd-floor.c cmd-io/cmd-floor.h \ + cmd-io/cmd-gameoption.c cmd-io/cmd-gameoption.h \ + cmd-io/cmd-help.c cmd-io/cmd-help.h \ + cmd-io/cmd-knowledge.c cmd-io/cmd-knowledge.h \ + cmd-io/cmd-lore.c cmd-io/cmd-lore.h \ + cmd-io/cmd-macro.c cmd-io/cmd-macro.h \ + cmd-io/cmd-menu-content-table.c cmd-io/cmd-menu-content-table.h \ + cmd-io/cmd-process-screen.c cmd-io/cmd-process-screen.h \ + cmd-io/cmd-save.c cmd-io/cmd-save.h \ + cmd-io/diary-subtitle-table.c cmd-io/diary-subtitle-table.h \ + cmd-io/feeling-table.c cmd-io/feeling-table.h \ + cmd-io/macro-util.c cmd-io/macro-util.h \ + \ + cmd-item/cmd-destroy.c cmd-item/cmd-destroy.h \ + cmd-item/cmd-eat.c cmd-item/cmd-eat.h \ + cmd-item/cmd-equipment.c cmd-item/cmd-equipment.h \ + cmd-item/cmd-item.c cmd-item/cmd-item.h \ + cmd-item/cmd-magiceat.c cmd-item/cmd-magiceat.h \ + cmd-item/cmd-quaff.c cmd-item/cmd-quaff.h \ + cmd-item/cmd-read.c cmd-item/cmd-read.h \ + cmd-item/cmd-refill.c cmd-item/cmd-refill.h \ + cmd-item/cmd-smith.c cmd-item/cmd-smith.h \ + cmd-item/cmd-throw.c cmd-item/cmd-throw.h \ + cmd-item/cmd-usestaff.c cmd-item/cmd-usestaff.h \ + cmd-item/cmd-zaprod.c cmd-item/cmd-zaprod.h \ + cmd-item/cmd-zapwand.c cmd-item/cmd-zapwand.h \ + \ + cmd-visual/cmd-draw.c cmd-visual/cmd-draw.h \ + cmd-visual/cmd-map.c cmd-visual/cmd-map.h \ + cmd-visual/cmd-visuals.c cmd-visual/cmd-visuals.h \ + \ + combat/attack-power-table.c combat/attack-power-table.h \ + combat/aura-counterattack.c combat/aura-counterattack.h \ + combat/hallucination-attacks-table.c combat/hallucination-attacks-table.h \ + combat/martial-arts-table.c combat/martial-arts-table.h \ + combat/attack-accuracy.c combat/attack-accuracy.h \ + combat/slaying.c combat/slaying.h \ + combat/combat-options-type.h \ + combat/attack-criticality.c combat/attack-criticality.h \ + combat/shoot.c combat/shoot.h \ + \ + core/asking-player.c core/asking-player.h \ + core/disturbance.c core/disturbance.h \ + core/game-closer.c core/game-closer.h \ + core/game-play.c core/game-play.h \ + core/hp-mp-processor.c core/hp-mp-processor.h \ + core/hp-mp-regenerator.c core/hp-mp-regenerator.h \ + core/magic-effects-timeout-reducer.c core/magic-effects-timeout-reducer.h \ + core/object-compressor.c core/object-compressor.h \ + core/output-updater.c core/output-updater.h \ + core/player-processor.c core/player-processor.h \ + core/player-redraw-types.h \ + core/player-update-types.h \ + core/scores.c core/scores.h \ + core/show-file.c core/show-file.h \ + core/special-internal-keys.h \ + core/speed-table.c core/speed-table.h \ + core/status-reseter.c core/status-reseter.h \ + core/stuff-handler.c core/stuff-handler.h \ + core/turn-compensator.c core/turn-compensator.h \ + core/visuals-reseter.c core/visuals-reseter.h \ + core/window-redrawer.c core/window-redrawer.h \ + \ + dungeon/dungeon.c dungeon/dungeon.h \ + dungeon/dungeon-flag-types.h \ + dungeon/dungeon-processor.c dungeon/dungeon-processor.h \ + dungeon/quest.h dungeon/quest.c \ + dungeon/quest-completion-checker.c dungeon/quest-completion-checker.h \ + dungeon/quest-monster-placer.c dungeon/quest-monster-placer.h \ + \ + effect/effect-feature.c effect/effect-feature.h \ + effect/effect-item.c effect/effect-item.h \ + effect/spells-effect-util.c effect/spells-effect-util.h \ + effect/effect-player.c effect/effect-player.h \ + effect/effect-monster.c effect/effect-monster.h \ + effect/effect-monster-curse.c effect/effect-monster-curse.h \ + effect/effect-monster-util.c effect/effect-monster-util.h \ + effect/effect-monster-resist-hurt.c effect/effect-monster-resist-hurt.h \ + effect/effect-monster-psi.c effect/effect-monster-psi.h \ + effect/effect-monster-oldies.c effect/effect-monster-oldies.h \ + effect/effect-monster-charm.c effect/effect-monster-charm.h \ + effect/effect-monster-lite-dark.c effect/effect-monster-lite-dark.h \ + effect/effect-monster-evil.c effect/effect-monster-evil.h \ + effect/effect-monster-spirit.c effect/effect-monster-spirit.h \ + effect/effect-monster-switcher.c effect/effect-monster-switcher.h \ + effect/effect-player-util.h \ + effect/effect-player-resist-hurt.c effect/effect-player-resist-hurt.h \ + effect/effect-player-oldies.c effect/effect-player-oldies.h \ + effect/effect-player-curse.c effect/effect-player-curse.h \ + effect/effect-player-spirit.c effect/effect-player-spirit.h \ + effect/effect-player-switcher.c effect/effect-player-switcher.h \ + effect/effect-processor.c effect/effect-processor.h \ + effect/effect-characteristics.h \ + \ + flavor/flag-inscriptions-table.c flavor/flag-inscriptions-table.h \ + flavor/flavor-describer.c flavor/flavor-describer.h \ + flavor/flavor-util.c flavor/flavor-util.h \ + flavor/named-item-describer.c flavor/named-item-describer.h \ + flavor/object-flavor-types.h \ + flavor/object-flavor.c flavor/object-flavor.h \ + flavor/tval-description-switcher.c flavor/tval-description-switcher.h \ + \ + floor/cave.c floor/cave.h \ + floor/cave-generator.c floor/cave-generator.h \ + floor/dungeon-tunnel-util.c floor/dungeon-tunnel-util.h \ + floor/fixed-map-generator.c floor/fixed-map-generator.h \ + floor/floor-allocation-types.h \ + floor/floor-base-definitions.h \ + floor/floor-changer.c floor/floor-changer.h \ + floor/floor-events.c floor/floor-events.h \ + floor/floor-generator-util.h \ + floor/floor-generator.c floor/floor-generator.h \ + floor/floor-leaver.c floor/floor-leaver.h \ + floor/floor-mode-changer.c floor/floor-mode-changer.h \ + floor/floor-object.c floor/floor-object.h \ + floor/floor-save.c floor/floor-save.h \ + floor/floor-save-util.c floor/floor-save-util.h \ + floor/floor-streams.c floor/floor-streams.h \ + floor/floor-town.h floor/floor-town.c \ + floor/floor-util.c floor/floor-util.h \ + floor/geometry.c floor/geometry.h \ + floor/line-of-sight.c floor/line-of-sight.h \ + floor/object-allocator.c floor/object-allocator.h \ + floor/object-scanner.c floor/object-scanner.h \ + floor/pattern-walk.c floor/pattern-walk.h \ + floor/sight-definitions.h \ + floor/tunnel-generator.c floor/tunnel-generator.h \ + floor/wild.h floor/wild.c \ + \ + game-option/auto-destruction-options.c game-option/auto-destruction-options.h \ + game-option/birth-options.c game-option/birth-options.h \ + game-option/cheat-options.c game-option/cheat-options.h \ + game-option/cheat-types.h \ + game-option/disturbance-options.c game-option/disturbance-options.h \ + game-option/game-play-options.c game-option/game-play-options.h \ + game-option/input-options.c game-option/input-options.h \ + game-option/keymap-directory-getter.c game-option/keymap-directory-getter.h \ + game-option/map-screen-options.c game-option/map-screen-options.h \ + game-option/option-flags.c game-option/option-flags.h \ + game-option/option-types-table.c game-option/option-types-table.h \ + game-option/play-record-options.c game-option/play-record-options.h \ + game-option/runtime-arguments.c game-option/runtime-arguments.h \ + game-option/special-options.c game-option/special-options.h \ + game-option/text-display-options.c game-option/text-display-options.h \ + \ + grid/door.c grid/door.h \ + grid/feature-flag-types.h \ + grid/feature-generator.c grid/feature-generator.h \ + grid/feature.c grid/feature.h \ + grid/grid.c grid/grid.h \ + grid/lighting-colors-table.c grid/lighting-colors-table.h \ + grid/object-placer.c grid/object-placer.h \ + grid/stair.c grid/stair.h \ + grid/trap.c grid/trap.h \ + \ + info-reader/artifact-reader.c info-reader/artifact-reader.h \ + info-reader/dungeon-info-tokens-table.c info-reader/dungeon-info-tokens-table.h \ + info-reader/dungeon-reader.c info-reader/dungeon-reader.h \ + info-reader/ego-reader.c info-reader/ego-reader.h \ + info-reader/feature-info-tokens-table.c info-reader/feature-info-tokens-table.h \ + info-reader/feature-reader.c info-reader/feature-reader.h \ + info-reader/fixed-map-parser.c info-reader/fixed-map-parser.h \ + info-reader/general-parser.c info-reader/general-parser.h \ + info-reader/info-reader-util.c info-reader/info-reader-util.h \ + info-reader/kind-info-tokens-table.c info-reader/kind-info-tokens-table.h \ + info-reader/kind-reader.c info-reader/kind-reader.h \ + info-reader/magic-reader.c info-reader/magic-reader.h \ + info-reader/parse-error-types.h \ + info-reader/race-info-tokens-table.c info-reader/race-info-tokens-table.h \ + info-reader/race-reader.c info-reader/race-reader.h \ + info-reader/random-grid-effect-types.h \ + info-reader/skill-reader.c info-reader/skill-reader.h \ + info-reader/vault-reader.c info-reader/vault-reader.h \ + \ + inventory/floor-item-getter.c inventory/floor-item-getter.h \ + inventory/inventory-curse.c inventory/inventory-curse.h \ + inventory/inventory-damage.c inventory/inventory-damage.h \ + inventory/inventory-describer.c inventory/inventory-describer.h \ + inventory/inventory-object.c inventory/inventory-object.h \ + inventory/inventory-slot-types.h \ + inventory/inventory-util.c inventory/inventory-util.h \ + inventory/item-getter.c inventory/item-getter.h \ + inventory/item-selection-util.c inventory/item-selection-util.h \ + inventory/pack-overflow.c inventory/pack-overflow.h \ + inventory/player-inventory.c inventory/player-inventory.h \ + inventory/recharge-processor.c inventory/recharge-processor.h \ + \ + io/chuukei.c io/chuukei.h \ + io/command-repeater.c io/command-repeater.h \ + io/cursor.c io/cursor.h \ + io/exit-panic.c io/exit-panic.h \ + io/files-util.c io/files-util.h \ + io/gf-descriptions.c io/gf-descriptions.h \ + io/inet.c io/inet.h \ + io/input-key-acceptor.c io/input-key-acceptor.h \ + io/input-key-processor.c io/input-key-processor.h \ + io/input-key-requester.c io/input-key-requester.h \ + io/interpret-pref-file.c io/interpret-pref-file.h \ + io/mutations-dump.c io/mutations-dump.h \ + io/pref-file-expressor.c io/pref-file-expressor.h \ + io/read-pref-file.c io/read-pref-file.h \ + io/report.c io/report.h \ + io/screen-util.c io/screen-util.h \ + io/signal-handlers.c io/signal-handlers.h \ + io/store-key-processor.c io/store-key-processor.h \ + io/tokenizer.c io/tokenizer.h \ + io/uid-checker.c io/uid-checker.h \ + io/write-diary.c io/write-diary.h \ + \ + io-dump/character-dump.c io-dump/character-dump.h \ + io-dump/dump-remover.c io-dump/dump-remover.h \ + io-dump/dump-util.c io-dump/dump-util.h \ + io-dump/player-status-dump.c io-dump/player-status-dump.h \ + io-dump/random-art-info-dumper.c io-dump/random-art-info-dumper.h \ + io-dump/special-class-dump.c io-dump/special-class-dump.h \ + \ + knowledge/knowledge-autopick.c knowledge/knowledge-autopick.h \ + knowledge/knowledge-experiences.c knowledge/knowledge-experiences.h \ + knowledge/knowledge-features.c knowledge/knowledge-features.h \ + knowledge/knowledge-inventory.c knowledge/knowledge-inventory.h \ + knowledge/knowledge-items.c knowledge/knowledge-items.h \ + knowledge/knowledge-monsters.c knowledge/knowledge-monsters.h \ + knowledge/knowledge-mutations.c knowledge/knowledge-mutations.h \ + knowledge/knowledge-uniques.c knowledge/knowledge-uniques.h \ + knowledge/knowledge-self.c knowledge/knowledge-self.h \ + knowledge/knowledge-quests.c knowledge/knowledge-quests.h \ + knowledge/lighting-level-table.c knowledge/lighting-level-table.h \ + knowledge/monster-group-table.c knowledge/monster-group-table.h \ + knowledge/object-group-table.c knowledge/object-group-table.h \ + \ + load/angband-version-comparer.c load/angband-version-comparer.h \ + load/birth-loader.c load/birth-loader.h \ + load/dummy-loader.c load/dummy-loader.h \ + load/dungeon-loader.c load/dungeon-loader.h \ + load/extra-loader.c load/extra-loader.h \ + load/floor-loader.c load/floor-loader.h \ + load/info-loader.c load/info-loader.h \ + load/inventory-loader.c load/inventory-loader.h \ + load/item-loader.c load/item-loader.h \ + load/monster-loader.c load/monster-loader.h \ + load/old-feature-types.h \ + load/load-util.c load/load-util.h \ + load/load-v1-3-0.c load/load-v1-3-0.h \ + load/load-v1-5-0.c load/load-v1-5-0.h \ + load/load-v1-7-0.c load/load-v1-7-0.h \ + load/load-zangband.c load/load-zangband.h \ + load/quest-loader.c load/quest-loader.h \ + load/load.c load/load.h \ + load/lore-loader.c load/lore-loader.h \ + load/option-loader.c load/option-loader.h \ + load/player-attack-loader.c load/player-attack-loader.h \ + load/player-info-loader.c load/player-info-loader.h \ + load/savedata-flag-types.h \ + load/store-loader.c load/store-loader.h \ + load/world-loader.c load/world-loader.h \ + \ + locale/english.c locale/english.h \ + locale/japanese.c locale/japanese.h \ + locale/language-switcher.h \ + \ + lore/combat-types-setter.c lore/combat-types-setter.h \ + lore/lore-calculator.c lore/lore-calculator.h \ + lore/lore-store.c lore/lore-store.h \ + lore/lore-util.c lore/lore-util.h \ + lore/magic-types-setter.c lore/magic-types-setter.h \ + lore/monster-lore.c lore/monster-lore.h \ \ - gameoption.c gameoption.h gamevalue.h \ - generate.h grid.c grid.h h-basic.h h-config.h h-define.h \ - history.h history.c \ - h-system.h h-type.h inet.c init1.c init2.c init.h japanese.c load.c \ main.c main-x11.c main-gcu.c \ - melee.h melee1.c mind.c \ \ - monster.h \ - monsterrace-hook.c monsterrace-hook.h monster-process.c \ - monster-process.h monster-status.c monster-status.h monster1.c \ - monster2.c mspells1.c mspells2.c mspells3.c mspells4.c monster-spell.h \ + main/angband-headers.c main/angband-headers.h \ + main/angband-initializer.c main/angband-initializer.h \ + main/game-data-initializer.c main/game-data-initializer.h \ + main/info-initializer.c main/info-initializer.h \ + main/initialization-error-messages-table.c main/initialization-error-messages-table.h \ + main/music-definitions-table.c main/music-definitions-table.h \ + main/sound-definitions-table.c main/sound-definitions-table.h \ + main/sound-of-music.c main/sound-of-music.h \ + main/x11-gamma-builder.c main/x11-gamma-builder.h \ + main/x11-type-string.c main/x11-type-string.h \ + \ + market/arena-info-table.c market/arena-info-table.h \ + market/building-initializer.c market/building-initializer.h \ + market/building-util.c market/building-util.h \ + market/play-gamble.c market/play-gamble.h \ + market/poker.c market/poker.h \ + market/articles-on-sale.c market/articles-on-sale.h \ + market/gold-magnification-table.c market/gold-magnification-table.h \ + market/arena.c market/arena.h \ + market/bounty-prize-table.c market/bounty-prize-table.h \ + market/bounty.c market/bounty.h \ + market/building-recharger.c market/building-recharger.h \ + market/building-quest.c market/building-quest.h \ + market/building-service.c market/building-service.h \ + market/building-craft-weapon.c market/building-craft-weapon.h \ + market/building-craft-armor.c market/building-craft-armor.h \ + market/building-craft-fix.c market/building-craft-fix.h \ + market/building-monster.c market/building-monster.h \ + market/building-enchanter.c market/building-enchanter.h \ + market/building-actions-table.h \ + \ + melee/monster-attack-monster.c melee/monster-attack-monster.h \ + melee/melee-postprocess.c melee/melee-postprocess.h \ + melee/melee-spell.c melee/melee-spell.h \ + melee/melee-spell-flags-checker.c melee/melee-spell-flags-checker.h \ + melee/melee-spell-util.c melee/melee-spell-util.h \ + melee/melee-switcher.c melee/melee-switcher.h \ + melee/melee-util.c melee/melee-util.h \ + \ + mind/drs-types.h \ + mind/mind-archer.c mind/mind-archer.h \ + mind/mind-berserker.c mind/mind-berserker.h \ + mind/mind-blue-mage.c mind/mind-blue-mage.h \ + mind/mind-cavalry.c mind/mind-cavalry.h \ + mind/mind-chaos-warrior.c mind/mind-chaos-warrior.h \ + mind/mind-explanations-table.c mind/mind-explanations-table.h \ + mind/mind-force-trainer.c mind/mind-force-trainer.h \ + mind/mind-info.c mind/mind-info.h \ + mind/mind-hobbit.c mind/mind-hobbit.h \ + mind/mind-mage.c mind/mind-mage.h \ + mind/mind-magic-eater.c mind/mind-magic-eater.h \ + mind/mind-magic-resistance.c mind/mind-magic-resistance.h \ + mind/mind-mindcrafter.c mind/mind-mindcrafter.h \ + mind/mind-mirror-master.c mind/mind-mirror-master.h \ + mind/mind-monk.c mind/mind-monk.h \ + mind/mind-ninja.c mind/mind-ninja.h \ + mind/mind-numbers.h \ + mind/mind-power-getter.c mind/mind-power-getter.h \ + mind/mind-priest.c mind/mind-priest.h \ + mind/mind-samurai.c mind/mind-samurai.h \ + mind/mind-sniper.c mind/mind-sniper.h \ + mind/mind-types.h \ + mind/mind-warrior.c mind/mind-warrior.h \ + mind/mind-warrior-mage.c mind/mind-warrior-mage.h \ + mind/mind-weaponsmith.c mind/mind-weaponsmith.h \ + mind/monk-attack.c mind/monk-attack.h \ + mind/snipe-types.h \ + mind/stances-table.c mind/stances-table.h \ + \ + monster/horror-descriptions.c monster/horror-descriptions.h \ + monster/monster-compaction.c monster/monster-compaction.h \ + monster/monster-describer.c monster/monster-describer.h \ + monster/monster-description-types.h \ + monster/monster-flag-types.h \ + monster/monster-info.c monster/monster-info.h \ + monster/monster-list.c monster/monster-list.h \ + monster/monster-processor.c monster/monster-processor.h \ + monster/monster-processor-util.c monster/monster-processor-util.h \ + monster/monster-timed-effect-types.h \ + monster/smart-learn-types.h \ + monster/monster-status.c monster/monster-status.h \ + monster/monster-status-setter.c monster/monster-status-setter.h \ + monster/monster-update.c monster/monster-update.h \ + monster/monster-util.c monster/monster-util.h \ \ - mutation.h mutation.c \ + monster-attack/insults-moans.c monster-attack/insults-moans.h \ + monster-attack/monster-attack-describer.c monster-attack/monster-attack-describer.h \ + monster-attack/monster-attack-effect.h \ + monster-attack/monster-attack-player.c monster-attack/monster-attack-player.h \ + monster-attack/monster-attack-processor.c monster-attack/monster-attack-processor.h \ + monster-attack/monster-attack-status.c monster-attack/monster-attack-status.h \ + monster-attack/monster-attack-switcher.c monster-attack/monster-attack-switcher.h \ + monster-attack/monster-attack-types.c monster-attack/monster-attack-types.h \ + monster-attack/monster-attack-util.c monster-attack/monster-attack-util.h \ + monster-attack/monster-eating.c monster-attack/monster-eating.h \ \ - object-boost.c object-boost.h \ - object-curse.c object-curse.h object-broken.c object-broken.h \ - object-hook.c object-hook.h object1.c object2.c \ - objectkind-hook.c objectkind-hook.h \ + monster-floor/monster-death.c monster-floor/monster-death.h \ + monster-floor/monster-death-util.c monster-floor/monster-death-util.h \ + monster-floor/monster-direction.c monster-floor/monster-direction.h \ + monster-floor/monster-dist-offsets.c monster-floor/monster-dist-offsets.h \ + monster-floor/monster-generator.c monster-floor/monster-generator.h \ + monster-floor/monster-move.c monster-floor/monster-move.h \ + monster-floor/monster-object.c monster-floor/monster-object.h \ + monster-floor/monster-remover.c monster-floor/monster-remover.h \ + monster-floor/monster-runaway.c monster-floor/monster-runaway.h \ + monster-floor/monster-safety-hiding.c monster-floor/monster-safety-hiding.h \ + monster-floor/monster-summon.c monster-floor/monster-summon.h \ + monster-floor/monster-sweep-grid.c monster-floor/monster-sweep-grid.h \ + monster-floor/monster-lite.c monster-floor/monster-lite.h \ + monster-floor/monster-lite-util.c monster-floor/monster-lite-util.h \ + monster-floor/one-monster-placer.c monster-floor/one-monster-placer.h \ + monster-floor/place-monster-types.h \ + monster-floor/quantum-effect.c monster-floor/quantum-effect.h \ + monster-floor/special-death-switcher.c monster-floor/special-death-switcher.h \ \ - patron.h patron.c \ + monster-race/monster-race.c monster-race/monster-race.h \ + monster-race/monster-race-hook.c monster-race/monster-race-hook.h \ + monster-race/race-flags-resistance.h \ + monster-race/race-flags1.h monster-race/race-flags2.h \ + monster-race/race-flags3.h monster-race/race-flags4.h \ + monster-race/race-flags-ability1.h monster-race/race-flags-ability2.h \ + monster-race/race-flags7.h monster-race/race-flags8.h \ + monster-race/race-flags9.h \ + monster-race/race-indice-types.h \ \ - projection.h projection.c\ + mspell/assign-monster-spell.c mspell/assign-monster-spell.h \ + mspell/element-resistance-checker.c mspell/element-resistance-checker.h \ + mspell/high-resistance-checker.c mspell/high-resistance-checker.h \ + mspell/improper-mspell-remover.c mspell/improper-mspell-remover.h \ + mspell/monster-power-table.c mspell/monster-power-table.h \ + mspell/mspell-attack.c mspell/mspell-attack.h \ + mspell/mspell-attack-util.c mspell/mspell-attack-util.h \ + mspell/mspell-breath.c mspell/mspell-breath.h \ + mspell/mspell-ball.c mspell/mspell-ball.h \ + mspell/mspell-bolt.c mspell/mspell-bolt.h \ + mspell/mspell-checker.c mspell/mspell-checker.h \ + mspell/mspell-curse.c mspell/mspell-curse.h \ + mspell/mspell-dispel.c mspell/mspell-dispel.h \ + mspell/mspell-judgement.c mspell/mspell-judgement.h \ + mspell/mspell-lite.c mspell/mspell-lite.h \ + mspell/mspell-summon.c mspell/mspell-summon.h \ + mspell/mspell-util.c mspell/mspell-util.h \ + mspell/mspell-type.h \ + mspell/mspell-damage-calculator.c mspell/mspell-damage-calculator.h \ + mspell/mspell-learn-checker.c mspell/mspell-learn-checker.h \ + mspell/mspell-floor.c mspell/mspell-floor.h \ + mspell/mspell-mask-definitions.h \ + mspell/mspell-special.c mspell/mspell-special.h \ + mspell/mspell-status.c mspell/mspell-status.h \ + mspell/mspell-particularity.c mspell/mspell-particularity.h \ + mspell/mspell-selector.c mspell/mspell-selector.h \ + mspell/smart-mspell-util.c mspell/smart-mspell-util.h \ + mspell/specified-summon.c mspell/specified-summon.h \ + mspell/summon-checker.c mspell/summon-checker.h \ \ - player-move.c player-move.h player-damage.c player-damage.h player-status.c player-status.h \ + mutation/gain-mutation-switcher.c mutation/gain-mutation-switcher.h \ + mutation/lose-mutation-switcher.c mutation/lose-mutation-switcher.h \ + mutation/mutation-calculator.c mutation/mutation-calculator.h \ + mutation/mutation-investor-remover.c mutation/mutation-investor-remover.h \ + mutation/mutation-util.c mutation/mutation-util.h \ + mutation/mutation-flag-types.h \ + mutation/mutation-processor.c mutation/mutation-processor.h \ + mutation/mutation-techniques.c mutation/mutation-techniques.h \ \ - quest.h quest.c\ + object/item-tester-hooker.c object/item-tester-hooker.h \ + object/object-broken.c object/object-broken.h \ + object/object-flags.c object/object-flags.h \ + object/object-generator.c object/object-generator.h \ + object/object-info.c object/object-info.h \ + object/object-kind.c object/object-kind.h \ + object/object-kind-hook.c object/object-kind-hook.h \ + object/object-stack.c object/object-stack.h \ + object/object-value.c object/object-value.h \ + object/object-value-calc.c object/object-value-calc.h \ + object/lite-processor.c object/lite-processor.h \ + object/tval-types.h \ + object/warning.c object/warning.h \ + object/object-mark-types.h \ + object/item-use-flags.h \ \ - racial.c \ - realm-arcane.c \ - realm-arcane.h realm-chaos.c realm-chaos.h realm-craft.c realm-craft.h \ - realm-crusade.c realm-crusade.h realm-daemon.c realm-daemon.h realm-death.c \ - realm-death.h realm-hex.c realm-hex.h realm-hissatsu.c realm-hissatsu.h \ - realm-life.c realm-life.h realm-nature.c realm-nature.h realm-song.c \ - realm-song.h realm-sorcery.c realm-sorcery.h realm-trump.c realm-trump.h \ - report.c rooms.c rooms-city.c rooms-city.h rooms-fractal.c rooms-fractal.h \ - rooms.h rooms-normal.c rooms-normal.h rooms-pitnest.c rooms-pitnest.h \ - rooms-special.c rooms-special.h rooms-trap.c rooms-trap.h rooms-vault.c \ - rooms-vault.h save.c scores.c selfinfo.c selfinfo.h shoot.c shoot.h snipe.c \ + object-activation/activation-bolt-ball.c object-activation/activation-bolt-ball.h \ + object-activation/activation-breath.c object-activation/activation-breath.h \ + object-activation/activation-charm.c object-activation/activation-charm.h \ + object-activation/activation-genocide.c object-activation/activation-genocide.h \ + object-activation/activation-others.c object-activation/activation-others.h \ + object-activation/activation-resistance.c object-activation/activation-resistance.h \ + object-activation/activation-switcher.c object-activation/activation-switcher.h \ + object-activation/activation-teleport.c object-activation/activation-teleport.h \ \ - rumor.h rumor.c \ + object-enchant/activation-info-table.c object-enchant/activation-info-table.h \ + object-enchant/apply-magic.c object-enchant/apply-magic.h \ + object-enchant/apply-magic-accessory.c object-enchant/apply-magic-accessory.h \ + object-enchant/apply-magic-armor.c object-enchant/apply-magic-armor.h \ + object-enchant/apply-magic-others.c object-enchant/apply-magic-others.h \ + object-enchant/apply-magic-weapon.c object-enchant/apply-magic-weapon.h \ + object-enchant/dragon-breaths-table.c object-enchant/dragon-breaths-table.h \ + object-enchant/object-boost.c object-enchant/object-boost.h \ + object-enchant/object-curse.c object-enchant/object-curse.h \ + object-enchant/object-ego.c object-enchant/object-ego.h \ + object-enchant/item-apply-magic.h object-enchant/item-feeling.h \ + object-enchant/old-ego-extra-values.h object-enchant/special-object-flags.h \ + object-enchant/tr-types.h object-enchant/trc-types.h \ + object-enchant/trg-types.h \ + object-enchant/vorpal-weapon.c object-enchant/vorpal-weapon.h \ \ spells.h \ spells1.c spells2.c spells3.c \ @@ -83,23 +598,381 @@ hengband_SOURCES = \ variable.c wild.h wild.c wizard1.c wizard2.c \ warning.c warning.h world.c world.h \ \ - view-mainwindow.c\ + perception/identification.c perception/identification.h \ + perception/object-perception.c perception/object-perception.h \ + perception/simple-perception.c perception/simple-perception.h \ \ - xtra2.c z-config.h \ - z-form.c z-form.h z-rand.c z-rand.h z-term.c z-term.h z-util.c z-util.h \ - z-virt.c z-virt.h + pet/pet-fall-off.c pet/pet-fall-off.h \ + pet/pet-util.c pet/pet-util.h \ + \ + player/attack-defense-types.h \ + player/eldritch-horror.c player/eldritch-horror.h \ + player/mimic-info-table.c player/mimic-info-table.h \ + player/patron.c player/patron.h \ + player/process-death.c player/process-death.h \ + player/process-name.c player/process-name.h \ + player/race-info-table.c player/race-info-table.h\ + player/race-resistances.c player/race-resistances.h \ + player/permanent-resistances.c player/permanent-resistances.h \ + player/temporary-resistances.c player/temporary-resistances.h \ + player/digestion-processor.c player/digestion-processor.h \ + player/player-classes-types.h \ + player/player-class.c player/player-class.h \ + player/player-damage.c player/player-damage.h \ + player/player-move.c player/player-move.h \ + player/player-personality.c player/player-personality.h \ + player/player-race.c player/player-race.h \ + player/player-race-types.h \ + player/player-realm.c player/player-realm.h \ + player/player-skill.c player/player-skill.h \ + player/player-status.c player/player-status.h \ + player/player-status-flags.c player/player-status-flags.h \ + player/player-status-table.c player/player-status-table.h \ + player/player-personalities-types.h \ + player/player-sex.c player/player-sex.h \ + player/player-view.c player/player-view.h \ + player/special-defense-types.h \ + \ + player-attack/player-attack-util.h \ + player-attack/attack-chaos-effect.c player-attack/attack-chaos-effect.h \ + player-attack/blood-sucking-processor.c player-attack/blood-sucking-processor.h \ + player-attack/player-attack.c player-attack/player-attack.h \ + \ + player-info/avatar.h player-info/avatar.c \ + player-info/base-status-info.c player-info/base-status-info.h \ + player-info/base-status-types.h \ + player-info/body-improvement-info.c player-info/body-improvement-info.h \ + player-info/class-ability-info.c player-info/class-ability-info.h \ + player-info/mutation-info.c player-info/mutation-info.h \ + player-info/race-ability-info.c player-info/race-ability-info.h \ + player-info/resistance-info.c player-info/resistance-info.h \ + player-info/self-info.c player-info/self-info.h \ + player-info/self-info-util.c player-info/self-info-util.h \ + player-info/weapon-effect-info.c player-info/weapon-effect-info.h \ + \ + racial/class-racial-switcher.c racial/class-racial-switcher.h \ + racial/mutation-racial-selector.c racial/mutation-racial-selector.h \ + racial/race-racial-command-setter.c racial/race-racial-command-setter.h \ + racial/racial-android.c racial/racial-android.h \ + racial/racial-balrog.c racial/racial-balrog.h \ + racial/racial-draconian.c racial/racial-draconian.h \ + racial/racial-kutar.c racial/racial-kutar.h \ + racial/racial-switcher.c racial/racial-switcher.h \ + racial/racial-util.c racial/racial-util.h \ + racial/racial-vampire.c racial/racial-vampire.h \ + \ + realm/realm-arcane.c realm/realm-arcane.h \ + realm/realm-chaos.c realm/realm-chaos.h \ + realm/realm-craft.c realm/realm-craft.h \ + realm/realm-crusade.c realm/realm-crusade.h \ + realm/realm-demon.c realm/realm-demon.h \ + realm/realm-death.c realm/realm-death.h \ + realm/realm-hex.c realm/realm-hex.h \ + realm/realm-hex-numbers.h \ + realm/realm-hissatsu.c realm/realm-hissatsu.h \ + realm/realm-life.c realm/realm-life.h \ + realm/realm-names-table.c realm/realm-names-table.h \ + realm/realm-nature.c realm/realm-nature.h \ + realm/realm-song.c realm/realm-song.h \ + realm/realm-song-numbers.h \ + realm/realm-sorcery.c realm/realm-sorcery.h \ + realm/realm-trump.c realm/realm-trump.h \ + realm/realm-types.h \ + \ + room/cave-filler.c room/cave-filler.h \ + room/door-definition.c room/door-definition.h \ + room/lake-types.h room/room-types.h \ + room/room-generator.c room/room-generator.h \ + room/room-info-table.c room/room-info-table.h \ + room/rooms-builder.c room/rooms-builder.h \ + room/rooms-city.c room/rooms-city.h \ + room/rooms-fractal.c room/rooms-fractal.h \ + room/rooms-maze-vault.c room/rooms-maze-vault.h \ + room/rooms-normal.c room/rooms-normal.h \ + room/rooms-pit-nest.c room/rooms-pit-nest.h \ + room/rooms-special.c room/rooms-special.h \ + room/rooms-trap.c room/rooms-trap.h \ + room/rooms-vault.c room/rooms-vault.h \ + room/space-finder.c room/space-finder.h \ + room/pit-nest-kinds-table.c room/pit-nest-kinds-table.h \ + room/treasure-deployment.c room/treasure-deployment.h \ + room/vault-builder.c room/vault-builder.h \ + \ + save/floor-writer.c save/floor-writer.h \ + save/info-writer.c save/info-writer.h \ + save/item-writer.c save/item-writer.h \ + save/monster-writer.c save/monster-writer.h \ + save/player-writer.c save/player-writer.h \ + save/save.c save/save.h \ + save/save-util.c save/save-util.h \ + \ + specific-object/blade-turner.c specific-object/blade-turner.h \ + specific-object/bloody-moon.c specific-object/bloody-moon.h \ + specific-object/bow.c specific-object/bow.h \ + specific-object/chest.c specific-object/chest.h \ + specific-object/death-crimson.c specific-object/death-crimson.h \ + specific-object/death-scythe.c specific-object/death-scythe.h \ + specific-object/monster-ball.c specific-object/monster-ball.h \ + specific-object/muramasa.c specific-object/muramasa.h \ + specific-object/ring-of-power.c specific-object/ring-of-power.h \ + specific-object/toragoroshi.c specific-object/toragoroshi.h \ + specific-object/torch.c specific-object/torch.h \ + \ + spell/range-calc.c spell/range-calc.h \ + spell/spells-describer.c spell/spells-describer.h \ + spell/spells-diceroll.c spell/spells-diceroll.h \ + spell/spells-execution.c spell/spells-execution.h \ + spell/spell-info.c spell/spell-info.h \ + spell/spells-object.c spell/spells-object.h \ + spell/spells-staff-only.c spell/spells-staff-only.h \ + spell/spells-summon.c spell/spells-summon.h \ + spell/spells-status.c spell/spells-status.h \ + spell/spell-types.h spell/spells-util.h \ + spell/summon-types.h \ + spell/technic-info-table.c spell/technic-info-table.h \ + \ + spell-kind/blood-curse.c spell-kind/blood-curse.h \ + spell-kind/earthquake.c spell-kind/earthquake.h \ + spell-kind/magic-item-recharger.c spell-kind/magic-item-recharger.h \ + spell-kind/spells-beam.c spell-kind/spells-beam.h \ + spell-kind/spells-charm.c spell-kind/spells-charm.h \ + spell-kind/spells-curse-removal.c spell-kind/spells-curse-removal.h \ + spell-kind/spells-detection.c spell-kind/spells-detection.h \ + spell-kind/spells-enchant.c spell-kind/spells-enchant.h \ + spell-kind/spells-equipment.c spell-kind/spells-equipment.h \ + spell-kind/spells-fetcher.c spell-kind/spells-fetcher.h \ + spell-kind/spells-floor.c spell-kind/spells-floor.h \ + spell-kind/spells-genocide.c spell-kind/spells-genocide.h \ + spell-kind/spells-grid.c spell-kind/spells-grid.h \ + spell-kind/spells-launcher.c spell-kind/spells-launcher.h \ + spell-kind/spells-lite.c spell-kind/spells-lite.h \ + spell-kind/spells-neighbor.c spell-kind/spells-neighbor.h \ + spell-kind/spells-pet.c spell-kind/spells-pet.h \ + spell-kind/spells-perception.c spell-kind/spells-perception.h \ + spell-kind/spells-polymorph.c spell-kind/spells-polymorph.h \ + spell-kind/spells-random.c spell-kind/spells-random.h \ + spell-kind/spells-sight.c spell-kind/spells-sight.h \ + spell-kind/spells-specific-bolt.c spell-kind/spells-specific-bolt.h \ + spell-kind/spells-teleport.c spell-kind/spells-teleport.h \ + spell-kind/spells-world.c spell-kind/spells-world.h \ + \ + spell-realm/spells-arcane.c spell-realm/spells-arcane.h \ + spell-realm/spells-chaos.c spell-realm/spells-chaos.h \ + spell-realm/spells-craft.c spell-realm/spells-craft.h \ + spell-realm/spells-crusade.c spell-realm/spells-crusade.h \ + spell-realm/spells-demon.c spell-realm/spells-demon.h \ + spell-realm/spells-hex.c spell-realm/spells-hex.h \ + spell-realm/spells-nature.c spell-realm/spells-nature.h \ + spell-realm/spells-song.c spell-realm/spells-song.h \ + spell-realm/spells-sorcery.c spell-realm/spells-sorcery.h \ + spell-realm/spells-trump.c spell-realm/spells-trump.h \ + \ + status/action-setter.c status/action-setter.h \ + status/bad-status-setter.c status/bad-status-setter.h \ + status/base-status.c status/base-status.h \ + status/body-improvement.c status/body-improvement.h \ + status/buff-setter.c status/buff-setter.h \ + status/element-resistance.c status/element-resistance.h \ + status/experience.c status/experience.h \ + status/shape-changer.c status/shape-changer.h \ + status/sight-setter.c status/sight-setter.h \ + status/temporary-resistance.c status/temporary-resistance.h \ + \ + store/home.c store/home.h \ + store/store.c store/store.h \ + store/black-market.c store/black-market.h \ + store/museum.c store/museum.h \ + store/pricing.c store/pricing.h \ + store/purchase-order.c store/purchase-order.h \ + store/owner-insults.c store/owner-insults.h \ + store/rumor.c store/rumor.h \ + store/say-comments.c store/say-comments.h \ + store/sell-order.c store/sell-order.h \ + store/service-checker.c store/service-checker.h \ + store/store-util.c store/store-util.h \ + store/store-owners.c store/store-owners.h \ + store/store-owner-comments.c store/store-owner-comments.h \ + \ + sv-definition/sv-amulet-types.h sv-definition/sv-armor-types.h \ + sv-definition/sv-bow-types.h sv-definition/sv-digging-types.h \ + sv-definition/sv-food-types.h sv-definition/sv-lite-types.h \ + sv-definition/sv-potion-types.h sv-definition/sv-protector-types.h \ + sv-definition/sv-ring-types.h sv-definition/sv-rod-types.h \ + sv-definition/sv-scroll-types.h sv-definition/sv-staff-types.h \ + sv-definition/sv-wand-types.h sv-definition/sv-weapon-types.h \ + sv-definition/sv-other-types.h \ + \ + system/alloc-entries.c system/alloc-entries.h \ + system/alloc-entry-definition.h \ + system/angband.h system/angband-version.h \ + system/artifact-type-definition.c system/artifact-type-definition.h \ + system/building-type-definition.c system/building-type-definition.h \ + system/dungeon-data-definition.h \ + system/floor-type-definition.h \ + system/game-option-types.h \ + system/h-basic.h system/h-config.h \ + system/h-define.h system/h-system.h system/h-type.h \ + system/monster-race-definition.h \ + system/monster-type-definition.h \ + system/object-type-definition.h \ + system/system-variables.c system/system-variables.h \ + system/gamevalue.h \ + \ + target/grid-selector.c target/grid-selector.h \ + target/projection-path-calculator.c target/projection-path-calculator.h + target/target-checker.c target/target-checker.h \ + target/target-describer.c target/target-describer.h \ + target/target-getter.c target/target-getter.h \ + target/target-preparation.c target/target-preparation.h \ + target/target-setter.c target/target-setter.h \ + target/target-types.h \ + \ + term/gameterm.c term/gameterm.h \ + term/screen-processor.c term/screen-processor.h \ + term/term-color-types.h \ + term/z-form.c term/z-form.h term/z-rand.c term/z-rand.h \ + term/z-term.c term/z-term.h term/z-util.c term/z-util.h \ + term/z-virt.c term/z-virt.h \ + \ + util/angband-files.c util/angband-files.h \ + util/buffer-shaper.c util/buffer-shaper.h \ + util/bit-flags-calculator.h \ + util/int-char-converter.h \ + util/object-sort.c util/object-sort.h \ + util/quarks.c util/quarks.h \ + util/sort.c util/sort.h \ + util/string-processor.c util/string-processor.h \ + util/tag-sorter.c util/tag-sorter.h \ + \ + view/display-birth.c view/display-birth.h \ + view/display-characteristic.c view/display-characteristic.h \ + view/display-fruit.c view/display-fruit.h \ + view/display-inventory.c view/display-inventory.h\ + view/display-lore-attacks.c view/display-lore-attacks.h \ + view/display-lore-drops.c view/display-lore-drops.h \ + view/display-lore-magics.c view/display-lore-magics.h \ + view/display-lore-status.c view/display-lore-status.h \ + view/display-lore.c view/display-lore.h \ + view/display-map.c view/display-map.h \ + view/display-messages.c view/display-messages.h \ + view/display-monster-status.c view/display-monster-status.h \ + view/display-player-stat-info.c view/display-player-stat-info.h \ + view/display-player-misc-info.c view/display-player-misc-info.h \ + view/display-player-middle.c view/display-player-middle.h \ + view/display-player.c view/display-player.h \ + view/display-self-info.c view/display-self-info.h \ + view/display-store.c view/display-store.h \ + view/display-util.c view/display-util.h \ + view/object-describer.c view/object-describer.h \ + view/status-first-page.c view/status-first-page.h \ + view/status-bars-table.c view/status-bars-table.h \ + \ + window/display-sub-window-items.c window/display-sub-window-items.h \ + window/display-sub-window-spells.c window/display-sub-window-spells.h \ + window/display-sub-windows.c window/display-sub-windows.h \ + window/main-window-left-frame.c window/main-window-left-frame.h \ + window/main-window-row-column.h \ + window/main-window-stat-poster.c window/main-window-stat-poster.h \ + window/main-window-util.c window/main-window-util.h \ + window/main-window-equipments.c window/main-window-equipments.h \ + \ + wizard/artifact-analyzer.c wizard/artifact-analyzer.h \ + wizard/artifact-bias-table.c wizard/artifact-bias-table.h \ + wizard/cmd-wizard.c wizard/cmd-wizard.h \ + wizard/fixed-artifacts-spoiler.c wizard/fixed-artifacts-spoiler.h \ + wizard/items-spoiler.c wizard/items-spoiler.h \ + wizard/monster-info-spoiler.c wizard/monster-info-spoiler.h \ + wizard/spoiler-table.c wizard/spoiler-table.h \ + wizard/spoiler-util.c wizard/spoiler-util.h \ + wizard/tval-descriptions-table.c wizard/tval-descriptions-table.h \ + wizard/wizard-item-modifier.c wizard/wizard-item-modifier.h \ + wizard/wizard-messages.c wizard/wizard-messages.h \ + wizard/wizard-spells.c wizard/wizard-spells.h \ + wizard/wizard-spoiler.c wizard/wizard-spoiler.h\ + wizard/wizard-special-process.c wizard/wizard-special-process.h \ + \ + world/world.c world/world.h \ + world/world-object.c world/world-object.h \ + world/world-movement-processor.c world/world-movement-processor.h \ + world/world-turn-processor.c world/world-turn-processor.h + +EXTRA_Bakabakaband_SOURCES = \ + angband.ico angband.rc ang_eng.rc maid-x11.c main-win.c \ + makefile.bcc makefile.std term/readdib.c term/readdib.h wall.bmp -EXTRA_hengband_SOURCES = \ - angband.ico angband.rc ang_eng.rc maid-x11.c main-mac.c main-win.c \ - main-dos.c main-ibm.c \ - makefile.bcc makefile.std makefile.dos makefile.ibm \ - readdib.c wall.bmp +EXTRA_DIST = \ + gcc-wrap -COMPILE = ./gcc-wrap $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +DEFAULT_INCLUDES = -I$(srcdir) \ + -I$(srcdir)/artifact \ + -I$(srcdir)/art-definition \ + -I$(srcdir)/autopick \ + -I$(srcdir)/birth \ + -I$(srcdir)/blue-magic \ + -I$(srcdir)/cmd-action \ + -I$(srcdir)/cmd-building \ + -I$(srcdir)/cmd-io \ + -I$(srcdir)/cmd-item \ + -I$(srcdir)/cmd-visual \ + -I$(srcdir)/combat \ + -I$(srcdir)/core \ + -I$(srcdir)/dungeon \ + -I$(srcdir)/effect \ + -I$(srcdir)/flavor \ + -I$(srcdir)/floor \ + -I$(srcdir)/game-option \ + -I$(srcdir)/grid \ + -I$(srcdir)/info-reader \ + -I$(srcdir)/inventory \ + -I$(srcdir)/io \ + -I$(srcdir)/io-dump \ + -I$(srcdir)/knowledge \ + -I$(srcdir)/load \ + -I$(srcdir)/lore \ + -I$(srcdir)/market \ + -I$(srcdir)/melee \ + -I$(srcdir)/mind \ + -I$(srcdir)/monster \ + -I$(srcdir)/monster-attack \ + -I$(srcdir)/monster-floor \ + -I$(srcdir)/monster-race \ + -I$(srcdir)/mspell \ + -I$(srcdir)/mutation \ + -I$(srcdir)/object \ + -I$(srcdir)/object-activation \ + -I$(srcdir)/object-enchant \ + -I$(srcdir)/object-hook \ + -I$(srcdir)/object-use \ + -I$(srcdir)/pet \ + -I$(srcdir)/player \ + -I$(srcdir)/player-attack \ + -I$(srcdir)/player-info \ + -I$(srcdir)/racial \ + -I$(srcdir)/realm \ + -I$(srcdir)/room \ + -I$(srcdir)/save \ + -I$(srcdir)/specific-object \ + -I$(srcdir)/spell \ + -I$(srcdir)/spell-kind \ + -I$(srcdir)/spell-realm \ + -I$(srcdir)/status \ + -I$(srcdir)/sv-definition \ + -I$(srcdir)/system \ + -I$(srcdir)/target \ + -I$(srcdir)/term \ + -I$(srcdir)/util \ + -I$(srcdir)/view \ + -I$(srcdir)/window \ + -I$(srcdir)/wizard \ + -I$(srcdir)/world \ + -I$(top_builddir)/src +CFLAGS += $(XFT_CFLAGS) +LIBS += $(XFT_LIBS) +COMPILE = $(srcdir)/gcc-wrap $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) install-exec-hook: if SET_GID - chgrp "@GAMEGROUP@" "$(DESTDIR)$(bindir)/hengband" - chmod g+s "$(DESTDIR)$(bindir)/hengband" + chgrp "@GAMEGROUP@" "$(DESTDIR)$(bindir)/Bakabakaband" + chmod g+s "$(DESTDIR)$(bindir)/Bakabakaband" endif diff --git a/src/action/action-limited.c b/src/action/action-limited.c new file mode 100644 index 000000000..89303cbc9 --- /dev/null +++ b/src/action/action-limited.c @@ -0,0 +1,105 @@ +#include "action/action-limited.h" +#include "dungeon/dungeon-flag-types.h" +#include "dungeon/dungeon.h" +#include "game-option/disturbance-options.h" +#include "grid/grid.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "system/floor-type-definition.h" +#include "term/screen-processor.h" +#include "view/display-messages.h" + +/*! + * @brief 魔法系コマンドが制限されているかを返す。 + * @return 魔法系コマンドを使用可能ならFALSE、不可能ならば理由をメッセージ表示してTRUEを返す。 + */ +bool cmd_limit_cast(player_type *creature_ptr) +{ + if (creature_ptr->current_floor_ptr->dun_level && (d_info[creature_ptr->dungeon_idx].flags1 & DF1_NO_MAGIC)) { + msg_print(_("ダンジョンが魔法を吸収した!", "The dungeon absorbs all attempted magic!")); + msg_print(NULL); + return TRUE; + } + + if (creature_ptr->anti_magic) { + msg_print(_("反魔法バリアが魔法を邪魔した!", "An anti-magic shell disrupts your magic!")); + return TRUE; + } + + if (creature_ptr->shero) { + msg_format(_("狂戦士化していて頭が回らない!", "You cannot think directly!")); + return TRUE; + } + + return FALSE; +} + +bool cmd_limit_confused(player_type *creature_ptr) +{ + if (creature_ptr->confused) { + msg_print(_("混乱していてできない!", "You are too confused!")); + return TRUE; + } + + return FALSE; +} + +bool cmd_limit_image(player_type *creature_ptr) +{ + if (creature_ptr->image) { + msg_print(_("幻覚が見えて集中できない!", "Your hallucinations prevent you from concentrating!")); + return TRUE; + } + + return FALSE; +} + +bool cmd_limit_stun(player_type *creature_ptr) +{ + if (creature_ptr->stun) { + msg_print(_("頭が朦朧としていて集中できない!", "You are too stunned!")); + return TRUE; + } + + return FALSE; +} + +bool cmd_limit_arena(player_type *creature_ptr) +{ + if (creature_ptr->current_floor_ptr->inside_arena) { + msg_print(_("アリーナが魔法を吸収した!", "The arena absorbs all attempted magic!")); + msg_print(NULL); + return TRUE; + } + + return FALSE; +} + +bool cmd_limit_blind(player_type *creature_ptr) +{ + if (creature_ptr->blind) { + msg_print(_("目が見えない。", "You can't see anything.")); + return TRUE; + } + + if (no_lite(creature_ptr)) { + msg_print(_("明かりがないので見えない。", "You have no light.")); + return TRUE; + } + + return FALSE; +} + +bool cmd_limit_time_walk(player_type *creature_ptr) +{ + if (creature_ptr->timewalk) { + if (flush_failure) + flush(); + + msg_print(_("止まった時の中ではうまく働かないようだ。", "It shows no reaction.")); + sound(SOUND_FAIL); + return TRUE; + } + + return FALSE; +} diff --git a/src/action/action-limited.h b/src/action/action-limited.h new file mode 100644 index 000000000..4676de0f6 --- /dev/null +++ b/src/action/action-limited.h @@ -0,0 +1,11 @@ +#pragma once + +#include "system/angband.h" + +bool cmd_limit_cast(player_type *creature_ptr); +bool cmd_limit_arena(player_type *creature_ptr); +bool cmd_limit_time_walk(player_type *creature_ptr); +bool cmd_limit_blind(player_type *creature_ptr); +bool cmd_limit_confused(player_type *creature_ptr); +bool cmd_limit_image(player_type *creature_ptr); +bool cmd_limit_stun(player_type *creature_ptr); diff --git a/src/action/activation-execution.c b/src/action/activation-execution.c new file mode 100644 index 000000000..886a3a69f --- /dev/null +++ b/src/action/activation-execution.c @@ -0,0 +1,245 @@ +#include "action/activation-execution.h" +#include "action/action-limited.h" +#include "art-definition/random-art-effects.h" +#include "artifact/artifact-info.h" +#include "core/window-redrawer.h" +#include "effect/spells-effect-util.h" +#include "floor/geometry.h" +#include "game-option/disturbance-options.h" +#include "game-option/input-options.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-floor/monster-generator.h" +#include "monster-floor/place-monster-types.h" +#include "monster-race/monster-race.h" +#include "monster/monster-info.h" +#include "monster/monster-util.h" +#include "object-activation/activation-switcher.h" +#include "object-activation/activation-util.h" +#include "object-enchant/object-ego.h" +#include "object-hook/hook-enchant.h" +#include "object/object-info.h" +#include "object/object-kind.h" +#include "racial/racial-android.h" +#include "specific-object/monster-ball.h" +#include "spell-kind/spells-launcher.h" +#include "spell-kind/spells-teleport.h" +#include "spell-realm/spells-hex.h" +#include "spell/spell-types.h" +#include "sv-definition/sv-lite-types.h" +#include "sv-definition/sv-ring-types.h" +#include "system/artifact-type-definition.h" +#include "system/floor-type-definition.h" +#include "system/monster-type-definition.h" +#include "system/object-type-definition.h" +#include "target/target-getter.h" +#include "term/screen-processor.h" +#include "util/quarks.h" +#include "util/sort.h" +#include "view/display-messages.h" +#include "world/world.h" + +static void decide_activation_level(player_type *user_ptr, ae_type *ae_ptr) +{ + if (object_is_fixed_artifact(ae_ptr->o_ptr)) { + ae_ptr->lev = a_info[ae_ptr->o_ptr->name1].level; + return; + } + + if (object_is_random_artifact(ae_ptr->o_ptr)) { + const activation_type *const act_ptr = find_activation_info(user_ptr, ae_ptr->o_ptr); + if (act_ptr != NULL) + ae_ptr->lev = act_ptr->level; + + return; + } + + if (((ae_ptr->o_ptr->tval == TV_RING) || (ae_ptr->o_ptr->tval == TV_AMULET)) && ae_ptr->o_ptr->name2) + ae_ptr->lev = e_info[ae_ptr->o_ptr->name2].level; +} + +static void decide_chance_fail(player_type *user_ptr, ae_type *ae_ptr) +{ + ae_ptr->chance = user_ptr->skill_dev; + if (user_ptr->confused) + ae_ptr->chance = ae_ptr->chance / 2; + + ae_ptr->fail = ae_ptr->lev + 5; + if (ae_ptr->chance > ae_ptr->fail) + ae_ptr->fail -= (ae_ptr->chance - ae_ptr->fail) * 2; + else + ae_ptr->chance -= (ae_ptr->fail - ae_ptr->chance) * 2; + + if (ae_ptr->fail < USE_DEVICE) + ae_ptr->fail = USE_DEVICE; + + if (ae_ptr->chance < USE_DEVICE) + ae_ptr->chance = USE_DEVICE; +} + +static void decide_activation_success(player_type *user_ptr, ae_type *ae_ptr) +{ + if (user_ptr->pclass == CLASS_BERSERKER) { + ae_ptr->success = FALSE; + return; + } + + if (ae_ptr->chance > ae_ptr->fail) { + ae_ptr->success = randint0(ae_ptr->chance * 2) >= ae_ptr->fail; + return; + } + + ae_ptr->success = randint0(ae_ptr->fail * 2) < ae_ptr->chance; +} + +static bool check_activation_success(ae_type *ae_ptr) +{ + if (ae_ptr->success) + return TRUE; + + if (flush_failure) + flush(); + + msg_print(_("‚¤‚Ü‚­Žn“®‚³‚¹‚邱‚Æ‚ª‚Å‚«‚È‚©‚Á‚½B", "You failed to activate it properly.")); + sound(SOUND_FAIL); + return FALSE; +} + +static bool check_activation_conditions(player_type *user_ptr, ae_type *ae_ptr) +{ + if (!check_activation_success(ae_ptr)) + return FALSE; + + if (ae_ptr->o_ptr->timeout) { + msg_print(_("‚»‚ê‚Í”÷‚©‚ɉ¹‚𗧂āA‹P‚«AÁ‚¦‚½...", "It whines, glows and fades...")); + return FALSE; + } + + if (!ae_ptr->o_ptr->xtra4 && (ae_ptr->o_ptr->tval == TV_FLASK) && ((ae_ptr->o_ptr->sval == SV_LITE_TORCH) || (ae_ptr->o_ptr->sval == SV_LITE_LANTERN))) { + msg_print(_("”R—¿‚ª‚È‚¢B", "It has no fuel.")); + free_turn(user_ptr); + return FALSE; + } + + return TRUE; +} + +/*! + * @brief ƒAƒCƒeƒ€‚Ì”­“®Œø‰Ê‚ðˆ—‚·‚éB + * @param user_ptr ƒvƒŒ[ƒ„[‚Ö‚ÌŽQÆƒ|ƒCƒ“ƒ^ + * @param o_ptr ‘Ώۂ̃IƒuƒWƒFƒNƒg\‘¢‘̃|ƒCƒ“ƒ^ + * @return ”­“®ŽÀs‚̐¥”ñ‚ð•Ô‚·B + */ +static bool activate_artifact(player_type *user_ptr, object_type *o_ptr) +{ + concptr name = k_name + k_info[o_ptr->k_idx].name; + const activation_type *const act_ptr = find_activation_info(user_ptr, o_ptr); + if (!act_ptr) { + msg_print("Activation information is not found."); + return FALSE; + } + + if (!switch_activation(user_ptr, o_ptr, act_ptr, name)) + return FALSE; + + if (act_ptr->timeout.constant >= 0) { + o_ptr->timeout = (s16b)act_ptr->timeout.constant; + if (act_ptr->timeout.dice > 0) + o_ptr->timeout += randint1(act_ptr->timeout.dice); + + return TRUE; + } + + switch (act_ptr->index) { + case ACT_BR_FIRE: + o_ptr->timeout = ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_FLAMES)) ? 200 : 250; + return TRUE; + case ACT_BR_COLD: + o_ptr->timeout = ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_ICE)) ? 200 : 250; + return TRUE; + case ACT_TERROR: + o_ptr->timeout = 3 * (user_ptr->lev + 10); + return TRUE; + case ACT_MURAMASA: + return TRUE; + default: + msg_format("Special timeout is not implemented: %d.", act_ptr->index); + return FALSE; + } +} + +static bool activate_whistle(player_type *user_ptr, ae_type *ae_ptr) +{ + if (ae_ptr->o_ptr->tval != TV_WHISTLE) + return FALSE; + + if (music_singing_any(user_ptr)) + stop_singing(user_ptr); + + if (hex_spelling_any(user_ptr)) + stop_hex_spell_all(user_ptr); + + MONSTER_IDX pet_ctr; + MONSTER_IDX *who; + int max_pet = 0; + C_MAKE(who, current_world_ptr->max_m_idx, MONSTER_IDX); + for (pet_ctr = user_ptr->current_floor_ptr->m_max - 1; pet_ctr >= 1; pet_ctr--) + if (is_pet(&user_ptr->current_floor_ptr->m_list[pet_ctr]) && (user_ptr->riding != pet_ctr)) + who[max_pet++] = pet_ctr; + + u16b dummy_why; + ang_sort(user_ptr, who, &dummy_why, max_pet, ang_sort_comp_pet, ang_sort_swap_hook); + for (MONSTER_IDX i = 0; i < max_pet; i++) { + pet_ctr = who[i]; + teleport_monster_to(user_ptr, pet_ctr, user_ptr->y, user_ptr->x, 100, TELEPORT_PASSIVE); + } + + C_KILL(who, current_world_ptr->max_m_idx, MONSTER_IDX); + ae_ptr->o_ptr->timeout = 100 + randint1(100); + return TRUE; +} + +/*! + * @brief ‘•”õ‚ð”­“®‚·‚éƒRƒ}ƒ“ƒh‚̃Tƒuƒ‹[ƒ`ƒ“ / + * Activate a wielded object. Wielded objects never stack. + * And even if they did, activatable objects never stack. + * @param item ”­“®‚·‚éƒIƒuƒWƒFƒNƒg‚̏ŠŽ•iID + * @return ‚È‚µ + * @details + *
+ * Currently, only (some) artifacts, and Dragon Scale Mail, can be activated.
+ * But one could, for example, easily make an activatable "Ring of Plasma".
+ * Note that it always takes a turn to activate an artifact, even if
+ * the user hits "escape" at the "direction" prompt.
+ * 
+ */ +void exe_activate(player_type *user_ptr, INVENTORY_IDX item) +{ + take_turn(user_ptr, 100); + ae_type tmp_ae; + ae_type *ae_ptr = initialize_ae_type(user_ptr, &tmp_ae, item); + decide_activation_level(user_ptr, ae_ptr); + decide_chance_fail(user_ptr, ae_ptr); + if (cmd_limit_time_walk(user_ptr)) + return; + + decide_activation_success(user_ptr, ae_ptr); + if (!check_activation_conditions(user_ptr, ae_ptr)) + return; + + msg_print(_("Žn“®‚³‚¹‚½...", "You activate it...")); + sound(SOUND_ZAP); + if (activation_index(user_ptr, ae_ptr->o_ptr)) { + (void)activate_artifact(user_ptr, ae_ptr->o_ptr); + user_ptr->window |= PW_INVEN | PW_EQUIP; + return; + } + + if (activate_whistle(user_ptr, ae_ptr)) + return; + + if (exe_monster_capture(user_ptr, ae_ptr)) + return; + + msg_print(_("‚¨‚Á‚ƁA‚±‚̃AƒCƒeƒ€‚ÍŽn“®‚Å‚«‚È‚¢B", "Oops. That object cannot be activated.")); +} diff --git a/src/action/activation-execution.h b/src/action/activation-execution.h new file mode 100644 index 000000000..a8a4a38d0 --- /dev/null +++ b/src/action/activation-execution.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void exe_activate(player_type *user_ptr, INVENTORY_IDX item); diff --git a/src/action/movement-execution.c b/src/action/movement-execution.c new file mode 100644 index 000000000..444a16790 --- /dev/null +++ b/src/action/movement-execution.c @@ -0,0 +1,334 @@ +#include "action/movement-execution.h" +#include "action/open-close-execution.h" +#include "art-definition/art-sword-types.h" +#include "cmd-action/cmd-attack.h" +#include "core/disturbance.h" +#include "core/player-update-types.h" +#include "core/stuff-handler.h" +#include "floor/pattern-walk.h" +#include "game-option/input-options.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "inventory/inventory-slot-types.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags-resistance.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags2.h" +#include "monster-race/race-flags7.h" +#include "monster-race/race-flags8.h" +#include "monster/monster-describer.h" +#include "monster/monster-info.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "mutation/mutation-flag-types.h" +#include "object/warning.h" +#include "player/player-move.h" +#include "system/floor-type-definition.h" +#include "system/object-type-definition.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" +#ifdef JP +#else +#include "locale/english.h" +#endif + +/* + * todo 負論理なので反転させたい + * Determine if a "boundary" grid is "floor mimic" + * @param grid_type *g_ptr + * @param feature_type *f_ptr + * @param feature_type *mimic_f_ptr + * @return 移動不能であればTRUE + */ +static bool boundary_floor(grid_type *g_ptr, feature_type *f_ptr, feature_type *mimic_f_ptr) +{ + bool is_boundary_floor = g_ptr->mimic > 0; + is_boundary_floor &= permanent_wall(f_ptr); + is_boundary_floor &= have_flag((mimic_f_ptr)->flags, FF_MOVE) || have_flag((mimic_f_ptr)->flags, FF_CAN_FLY); + is_boundary_floor &= have_flag((mimic_f_ptr)->flags, FF_PROJECT); + is_boundary_floor &= !have_flag((mimic_f_ptr)->flags, FF_OPEN); + return is_boundary_floor; +} + +/*! + * @brief 該当地形のトラップがプレイヤーにとって無効かどうかを判定して返す / + * Move player in the given direction, with the given "pickup" flag. + * @param creature_ptr プレーヤーへの参照ポインタ + * @param dir 移動方向ID + * @param do_pickup 罠解除を試みながらの移動ならばTRUE + * @param break_trap トラップ粉砕処理を行うならばTRUE + * @return 実際に移動が行われたならばTRUEを返す。 + * @note + * This routine should (probably) always induce energy expenditure.\n + * @details + * Note that moving will *always* take a turn, and will *always* hit\n + * any monster which might be in the destination grid. Previously,\n + * moving into walls was "free" and did NOT hit invisible monsters.\n + */ +void exe_movement(player_type *creature_ptr, DIRECTION dir, bool do_pickup, bool break_trap) +{ + POSITION y = creature_ptr->y + ddy[dir]; + POSITION x = creature_ptr->x + ddx[dir]; + floor_type *floor_ptr = creature_ptr->current_floor_ptr; + grid_type *g_ptr = &floor_ptr->grid_array[y][x]; + bool p_can_enter = player_can_enter(creature_ptr, g_ptr->feat, CEM_P_CAN_ENTER_PATTERN); + bool stormbringer = FALSE; + if (!floor_ptr->dun_level && !creature_ptr->wild_mode && ((x == 0) || (x == MAX_WID - 1) || (y == 0) || (y == MAX_HGT - 1))) { + if (g_ptr->mimic && player_can_enter(creature_ptr, g_ptr->mimic, 0)) { + if ((y == 0) && (x == 0)) { + creature_ptr->wilderness_y--; + creature_ptr->wilderness_x--; + creature_ptr->oldpy = floor_ptr->height - 2; + creature_ptr->oldpx = floor_ptr->width - 2; + creature_ptr->ambush_flag = FALSE; + } else if ((y == 0) && (x == MAX_WID - 1)) { + creature_ptr->wilderness_y--; + creature_ptr->wilderness_x++; + creature_ptr->oldpy = floor_ptr->height - 2; + creature_ptr->oldpx = 1; + creature_ptr->ambush_flag = FALSE; + } else if ((y == MAX_HGT - 1) && (x == 0)) { + creature_ptr->wilderness_y++; + creature_ptr->wilderness_x--; + creature_ptr->oldpy = 1; + creature_ptr->oldpx = floor_ptr->width - 2; + creature_ptr->ambush_flag = FALSE; + } else if ((y == MAX_HGT - 1) && (x == MAX_WID - 1)) { + creature_ptr->wilderness_y++; + creature_ptr->wilderness_x++; + creature_ptr->oldpy = 1; + creature_ptr->oldpx = 1; + creature_ptr->ambush_flag = FALSE; + } else if (y == 0) { + creature_ptr->wilderness_y--; + creature_ptr->oldpy = floor_ptr->height - 2; + creature_ptr->oldpx = x; + creature_ptr->ambush_flag = FALSE; + } else if (y == MAX_HGT - 1) { + creature_ptr->wilderness_y++; + creature_ptr->oldpy = 1; + creature_ptr->oldpx = x; + creature_ptr->ambush_flag = FALSE; + } else if (x == 0) { + creature_ptr->wilderness_x--; + creature_ptr->oldpx = floor_ptr->width - 2; + creature_ptr->oldpy = y; + creature_ptr->ambush_flag = FALSE; + } else if (x == MAX_WID - 1) { + creature_ptr->wilderness_x++; + creature_ptr->oldpx = 1; + creature_ptr->oldpy = y; + creature_ptr->ambush_flag = FALSE; + } + + creature_ptr->leaving = TRUE; + take_turn(creature_ptr, 100); + return; + } + + p_can_enter = FALSE; + } + + monster_type *m_ptr; + m_ptr = &floor_ptr->m_list[g_ptr->m_idx]; + if (creature_ptr->inventory_list[INVEN_RARM].name1 == ART_STORMBRINGER) + stormbringer = TRUE; + + if (creature_ptr->inventory_list[INVEN_LARM].name1 == ART_STORMBRINGER) + stormbringer = TRUE; + + feature_type *f_ptr = &f_info[g_ptr->feat]; + bool p_can_kill_walls = creature_ptr->kill_wall && have_flag(f_ptr->flags, FF_HURT_DISI) && (!p_can_enter || !have_flag(f_ptr->flags, FF_LOS)) + && !have_flag(f_ptr->flags, FF_PERMANENT); + GAME_TEXT m_name[MAX_NLEN]; + bool can_move = TRUE; + bool do_past = FALSE; + if (g_ptr->m_idx && (m_ptr->ml || p_can_enter || p_can_kill_walls)) { + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + if (!is_hostile(m_ptr) + && !(creature_ptr->confused || creature_ptr->image || !m_ptr->ml || creature_ptr->stun + || ((creature_ptr->muta2 & MUT2_BERS_RAGE) && creature_ptr->shero)) + && pattern_seq(creature_ptr, creature_ptr->y, creature_ptr->x, y, x) && (p_can_enter || p_can_kill_walls)) { + (void)set_monster_csleep(creature_ptr, g_ptr->m_idx, 0); + monster_desc(creature_ptr, m_name, m_ptr, 0); + if (m_ptr->ml) { + if (!creature_ptr->image) + monster_race_track(creature_ptr, m_ptr->ap_r_idx); + + health_track(creature_ptr, g_ptr->m_idx); + } + + if ((stormbringer && (randint1(1000) > 666)) || (creature_ptr->pclass == CLASS_BERSERKER)) { + do_cmd_attack(creature_ptr, y, x, 0); + can_move = FALSE; + } else if (monster_can_cross_terrain(creature_ptr, floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].feat, r_ptr, 0)) { + do_past = TRUE; + } else { + msg_format(_("%^sが邪魔だ!", "%^s is in your way!"), m_name); + free_turn(creature_ptr); + can_move = FALSE; + } + } else { + do_cmd_attack(creature_ptr, y, x, 0); + can_move = FALSE; + } + } + + monster_type *riding_m_ptr = &floor_ptr->m_list[creature_ptr->riding]; + monster_race *riding_r_ptr = &r_info[creature_ptr->riding ? riding_m_ptr->r_idx : 0]; + if (can_move && creature_ptr->riding) { + if (riding_r_ptr->flags1 & RF1_NEVER_MOVE) { + msg_print(_("動けない!", "Can't move!")); + free_turn(creature_ptr); + can_move = FALSE; + disturb(creature_ptr, FALSE, TRUE); + } else if (monster_fear_remaining(riding_m_ptr)) { + GAME_TEXT steed_name[MAX_NLEN]; + monster_desc(creature_ptr, steed_name, riding_m_ptr, 0); + msg_format(_("%sが恐怖していて制御できない。", "%^s is too scared to control."), steed_name); + can_move = FALSE; + disturb(creature_ptr, FALSE, TRUE); + } else if (creature_ptr->riding_ryoute) { + can_move = FALSE; + disturb(creature_ptr, FALSE, TRUE); + } else if (have_flag(f_ptr->flags, FF_CAN_FLY) && (riding_r_ptr->flags7 & RF7_CAN_FLY)) { + /* Allow moving */ + } else if (have_flag(f_ptr->flags, FF_CAN_SWIM) && (riding_r_ptr->flags7 & RF7_CAN_SWIM)) { + /* Allow moving */ + } else if (have_flag(f_ptr->flags, FF_WATER) && !(riding_r_ptr->flags7 & RF7_AQUATIC) + && (have_flag(f_ptr->flags, FF_DEEP) || (riding_r_ptr->flags2 & RF2_AURA_FIRE))) { + msg_format(_("%sの上に行けない。", "Can't swim."), f_name + f_info[get_feat_mimic(g_ptr)].name); + free_turn(creature_ptr); + can_move = FALSE; + disturb(creature_ptr, FALSE, TRUE); + } else if (!have_flag(f_ptr->flags, FF_WATER) && (riding_r_ptr->flags7 & RF7_AQUATIC)) { + msg_format(_("%sから上がれない。", "Can't land."), f_name + f_info[get_feat_mimic(&floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name); + free_turn(creature_ptr); + can_move = FALSE; + disturb(creature_ptr, FALSE, TRUE); + } else if (have_flag(f_ptr->flags, FF_LAVA) && !(riding_r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK)) { + msg_format(_("%sの上に行けない。", "Too hot to go through."), f_name + f_info[get_feat_mimic(g_ptr)].name); + free_turn(creature_ptr); + can_move = FALSE; + disturb(creature_ptr, FALSE, TRUE); + } + + if (can_move && monster_stunned_remaining(riding_m_ptr) && one_in_(2)) { + GAME_TEXT steed_name[MAX_NLEN]; + monster_desc(creature_ptr, steed_name, riding_m_ptr, 0); + msg_format(_("%sが朦朧としていてうまく動けない!", "You cannot control stunned %s!"), steed_name); + can_move = FALSE; + disturb(creature_ptr, FALSE, TRUE); + } + } + + if (!can_move) { + } else if (!have_flag(f_ptr->flags, FF_MOVE) && have_flag(f_ptr->flags, FF_CAN_FLY) && !creature_ptr->levitation) { + msg_format(_("空を飛ばないと%sの上には行けない。", "You need to fly to go through the %s."), f_name + f_info[get_feat_mimic(g_ptr)].name); + free_turn(creature_ptr); + creature_ptr->running = 0; + can_move = FALSE; + } else if (have_flag(f_ptr->flags, FF_TREE) && !p_can_kill_walls) { + if ((creature_ptr->pclass != CLASS_RANGER) && !creature_ptr->levitation && (!creature_ptr->riding || !(riding_r_ptr->flags8 & RF8_WILD_WOOD))) + creature_ptr->energy_use *= 2; + } else if ((do_pickup != easy_disarm) && have_flag(f_ptr->flags, FF_DISARM) && !g_ptr->mimic) { + if (!trap_can_be_ignored(creature_ptr, g_ptr->feat)) { + (void)exe_disarm(creature_ptr, y, x, dir); + return; + } + } else if (!p_can_enter && !p_can_kill_walls) { + FEAT_IDX feat = get_feat_mimic(g_ptr); + feature_type *mimic_f_ptr = &f_info[feat]; + concptr name = f_name + mimic_f_ptr->name; + can_move = FALSE; + if (!(g_ptr->info & CAVE_MARK) && !player_can_see_bold(creature_ptr, y, x)) { + if (boundary_floor(g_ptr, f_ptr, mimic_f_ptr)) + msg_print(_("それ以上先には進めないようだ。", "You feel you cannot go any more.")); + else { +#ifdef JP + msg_format("%sが行く手をはばんでいるようだ。", name); +#else + msg_format("You feel %s %s blocking your way.", is_a_vowel(name[0]) ? "an" : "a", name); +#endif + g_ptr->info |= (CAVE_MARK); + lite_spot(creature_ptr, y, x); + } + } else { + if (boundary_floor(g_ptr, f_ptr, mimic_f_ptr)) { + msg_print(_("それ以上先には進めない。", "You cannot go any more.")); + if (!(creature_ptr->confused || creature_ptr->stun || creature_ptr->image)) + free_turn(creature_ptr); + } else { + if (easy_open && is_closed_door(creature_ptr, feat) && easy_open_door(creature_ptr, y, x)) + return; + +#ifdef JP + msg_format("%sが行く手をはばんでいる。", name); +#else + msg_format("There is %s %s blocking your way.", is_a_vowel(name[0]) ? "an" : "a", name); +#endif + if (!(creature_ptr->confused || creature_ptr->stun || creature_ptr->image)) + free_turn(creature_ptr); + } + } + + disturb(creature_ptr, FALSE, TRUE); + if (!boundary_floor(g_ptr, f_ptr, mimic_f_ptr)) + sound(SOUND_HITWALL); + } + + if (can_move && !pattern_seq(creature_ptr, creature_ptr->y, creature_ptr->x, y, x)) { + if (!(creature_ptr->confused || creature_ptr->stun || creature_ptr->image)) + free_turn(creature_ptr); + + disturb(creature_ptr, FALSE, TRUE); + can_move = FALSE; + } + + if (!can_move) + return; + + if (creature_ptr->warning && (!process_warning(creature_ptr, x, y))) { + creature_ptr->energy_use = 25; + return; + } + + if (do_past) + msg_format(_("%sを押し退けた。", "You push past %s."), m_name); + + if (creature_ptr->wild_mode) { + if (ddy[dir] > 0) + creature_ptr->oldpy = 1; + + if (ddy[dir] < 0) + creature_ptr->oldpy = MAX_HGT - 2; + + if (ddy[dir] == 0) + creature_ptr->oldpy = MAX_HGT / 2; + + if (ddx[dir] > 0) + creature_ptr->oldpx = 1; + + if (ddx[dir] < 0) + creature_ptr->oldpx = MAX_WID - 2; + + if (ddx[dir] == 0) + creature_ptr->oldpx = MAX_WID / 2; + } + + if (p_can_kill_walls) { + cave_alter_feat(creature_ptr, y, x, FF_HURT_DISI); + creature_ptr->update |= PU_FLOW; + } + + u32b mpe_mode = MPE_ENERGY_USE; + if (do_pickup != always_pickup) + mpe_mode |= MPE_DO_PICKUP; + + if (break_trap) + mpe_mode |= MPE_BREAK_TRAP; + + (void)move_player_effect(creature_ptr, y, x, mpe_mode); +} diff --git a/src/action/movement-execution.h b/src/action/movement-execution.h new file mode 100644 index 000000000..a7525648d --- /dev/null +++ b/src/action/movement-execution.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void exe_movement(player_type *creature_ptr, DIRECTION dir, bool do_pickup, bool break_trap); diff --git a/src/action/mutation-execution.c b/src/action/mutation-execution.c new file mode 100644 index 000000000..039c928d5 --- /dev/null +++ b/src/action/mutation-execution.c @@ -0,0 +1,282 @@ +#include "action/mutation-execution.h" +#include "cmd-item/cmd-throw.h" +#include "core/asking-player.h" +#include "effect/spells-effect-util.h" +#include "game-option/play-record-options.h" +#include "grid/grid.h" +#include "inventory/inventory-slot-types.h" +#include "io/write-diary.h" +#include "mind/mind-mage.h" +#include "mind/mind-warrior.h" +#include "monster-floor/monster-remover.h" +#include "monster-floor/monster-summon.h" +#include "monster-floor/place-monster-types.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags3.h" +#include "monster/monster-describer.h" +#include "monster/monster-description-types.h" +#include "monster/monster-flag-types.h" +#include "monster/monster-info.h" +#include "mutation/mutation-flag-types.h" +#include "mutation/mutation-techniques.h" +#include "object-enchant/item-feeling.h" +#include "object-hook/hook-checker.h" +#include "player-info/self-info.h" +#include "player/player-damage.h" +#include "racial/racial-vampire.h" +#include "spell-kind/earthquake.h" +#include "spell-kind/spells-charm.h" +#include "spell-kind/spells-detection.h" +#include "spell-kind/spells-fetcher.h" +#include "spell-kind/spells-launcher.h" +#include "spell-kind/spells-lite.h" +#include "spell-kind/spells-sight.h" +#include "spell-kind/spells-teleport.h" +#include "spell-kind/spells-world.h" +#include "spell-realm/spells-sorcery.h" +#include "spell/spell-types.h" +#include "spell/spells-status.h" +#include "spell/summon-types.h" +#include "status/element-resistance.h" +#include "status/shape-changer.h" +#include "system/floor-type-definition.h" +#include "system/object-type-definition.h" +#include "target/target-getter.h" +#include "view/display-messages.h" + +/*! + * @brief 突然変異のレイシャル効果実装 + * @param creature_ptr プレーヤーへの参照ポインタ + * @param power 発動させる突然変異レイシャルのID + * @return レイシャルを実行した場合TRUE、キャンセルした場合FALSEを返す + */ +bool exe_mutation_power(player_type *creature_ptr, int power) +{ + DIRECTION dir = 0; + PLAYER_LEVEL lvl = creature_ptr->lev; + switch (power) { + case MUT1_SPIT_ACID: + if (!get_aim_dir(creature_ptr, &dir)) + return FALSE; + + stop_mouth(creature_ptr); + msg_print(_("酸を吐きかけた...", "You spit acid...")); + fire_ball(creature_ptr, GF_ACID, dir, lvl, 1 + (lvl / 30)); + return TRUE; + case MUT1_BR_FIRE: + if (!get_aim_dir(creature_ptr, &dir)) + return FALSE; + + stop_mouth(creature_ptr); + msg_print(_("あなたは火炎のブレスを吐いた...", "You breathe fire...")); + fire_breath(creature_ptr, GF_FIRE, dir, lvl * 2, 1 + (lvl / 20)); + return TRUE; + case MUT1_HYPN_GAZE: + if (!get_aim_dir(creature_ptr, &dir)) + return FALSE; + + msg_print(_("あなたの目は幻惑的になった...", "Your eyes look mesmerizing...")); + (void)charm_monster(creature_ptr, dir, lvl); + return TRUE; + case MUT1_TELEKINES: + if (!get_aim_dir(creature_ptr, &dir)) + return FALSE; + + msg_print(_("集中している...", "You concentrate...")); + fetch_item(creature_ptr, dir, lvl * 10, TRUE); + return TRUE; + case MUT1_VTELEPORT: + msg_print(_("集中している...", "You concentrate...")); + teleport_player(creature_ptr, 10 + 4 * lvl, TELEPORT_SPONTANEOUS); + return TRUE; + case MUT1_MIND_BLST: + if (!get_aim_dir(creature_ptr, &dir)) + return FALSE; + + msg_print(_("集中している...", "You concentrate...")); + fire_bolt(creature_ptr, GF_PSI, dir, damroll(3 + ((lvl - 1) / 5), 3)); + return TRUE; + case MUT1_RADIATION: + msg_print(_("体から放射能が発生した!", "Radiation flows from your body!")); + fire_ball(creature_ptr, GF_NUKE, 0, (lvl * 2), 3 + (lvl / 20)); + return TRUE; + case MUT1_VAMPIRISM: + vampirism(creature_ptr); + return TRUE; + case MUT1_SMELL_MET: + stop_mouth(creature_ptr); + (void)detect_treasure(creature_ptr, DETECT_RAD_DEFAULT); + return TRUE; + case MUT1_SMELL_MON: + stop_mouth(creature_ptr); + (void)detect_monsters_normal(creature_ptr, DETECT_RAD_DEFAULT); + return TRUE; + case MUT1_BLINK: + teleport_player(creature_ptr, 10, TELEPORT_SPONTANEOUS); + return TRUE; + case MUT1_EAT_ROCK: + return eat_rock(creature_ptr); + case MUT1_SWAP_POS: + project_length = -1; + if (!get_aim_dir(creature_ptr, &dir)) { + project_length = 0; + return FALSE; + } + + (void)teleport_swap(creature_ptr, dir); + project_length = 0; + return TRUE; + case MUT1_SHRIEK: + stop_mouth(creature_ptr); + (void)fire_ball(creature_ptr, GF_SOUND, 0, 2 * lvl, 8); + (void)aggravate_monsters(creature_ptr, 0); + return TRUE; + case MUT1_ILLUMINE: + (void)lite_area(creature_ptr, damroll(2, (lvl / 2)), (lvl / 10) + 1); + return TRUE; + case MUT1_DET_CURSE: + for (int i = 0; i < INVEN_TOTAL; i++) { + object_type *o_ptr = &creature_ptr->inventory_list[i]; + if ((o_ptr->k_idx == 0) || !object_is_cursed(o_ptr)) + continue; + + o_ptr->feeling = FEEL_CURSED; + } + + return TRUE; + case MUT1_BERSERK: + (void)berserk(creature_ptr, randint1(25) + 25); + return TRUE; + case MUT1_POLYMORPH: + if (!get_check(_("変身します。よろしいですか?", "You will polymorph your self. Are you sure? "))) + return FALSE; + + do_poly_self(creature_ptr); + return TRUE; + case MUT1_MIDAS_TCH: + return alchemy(creature_ptr); + case MUT1_GROW_MOLD: + for (DIRECTION i = 0; i < 8; i++) + summon_specific(creature_ptr, -1, creature_ptr->y, creature_ptr->x, lvl, SUMMON_MOLD, PM_FORCE_PET); + + return TRUE; + case MUT1_RESIST: { + int num = lvl / 10; + TIME_EFFECT dur = randint1(20) + 20; + if (randint0(5) < num) { + (void)set_oppose_acid(creature_ptr, dur, FALSE); + num--; + } + + if (randint0(4) < num) { + (void)set_oppose_elec(creature_ptr, dur, FALSE); + num--; + } + + if (randint0(3) < num) { + (void)set_oppose_fire(creature_ptr, dur, FALSE); + num--; + } + + if (randint0(2) < num) { + (void)set_oppose_cold(creature_ptr, dur, FALSE); + num--; + } + + if (num != 0) { + (void)set_oppose_pois(creature_ptr, dur, FALSE); + num--; + } + + return TRUE; + } + case MUT1_EARTHQUAKE: + (void)earthquake(creature_ptr, creature_ptr->y, creature_ptr->x, 10, 0); + return TRUE; + case MUT1_EAT_MAGIC: + return eat_magic(creature_ptr, creature_ptr->lev * 2); + case MUT1_WEIGH_MAG: + report_magics(creature_ptr); + return TRUE; + case MUT1_STERILITY: + msg_print(_("突然頭が痛くなった!", "You suddenly have a headache!")); + take_hit(creature_ptr, DAMAGE_LOSELIFE, randint1(17) + 17, _("禁欲を強いた疲労", "the strain of forcing abstinence"), -1); + creature_ptr->current_floor_ptr->num_repro += MAX_REPRO; + return TRUE; + case MUT1_HIT_AND_AWAY: + return hit_and_away(creature_ptr); + case MUT1_DAZZLE: + stun_monsters(creature_ptr, lvl * 4); + confuse_monsters(creature_ptr, lvl * 4); + turn_monsters(creature_ptr, lvl * 4); + return TRUE; + case MUT1_LASER_EYE: + if (!get_aim_dir(creature_ptr, &dir)) + return FALSE; + + fire_beam(creature_ptr, GF_LITE, dir, 2 * lvl); + return TRUE; + case MUT1_RECALL: + return recall_player(creature_ptr, randint0(21) + 15); + case MUT1_BANISH: { + if (!get_direction(creature_ptr, &dir, FALSE, FALSE)) + return FALSE; + + POSITION y = creature_ptr->y + ddy[dir]; + POSITION x = creature_ptr->x + ddx[dir]; + grid_type *g_ptr; + g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + + if (!g_ptr->m_idx) { + msg_print(_("邪悪な存在を感じとれません!", "You sense no evil there!")); + return TRUE; + } + + monster_type *m_ptr; + m_ptr = &creature_ptr->current_floor_ptr->m_list[g_ptr->m_idx]; + monster_race *r_ptr; + r_ptr = &r_info[m_ptr->r_idx]; + if ((r_ptr->flags3 & RF3_EVIL) && !(r_ptr->flags1 & RF1_QUESTOR) && !(r_ptr->flags1 & RF1_UNIQUE) && !creature_ptr->current_floor_ptr->inside_arena + && !creature_ptr->current_floor_ptr->inside_quest && (r_ptr->level < randint1(creature_ptr->lev + 50)) && !(m_ptr->mflag2 & MFLAG2_NOGENO)) { + if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname) { + GAME_TEXT m_name[MAX_NLEN]; + monster_desc(creature_ptr, m_name, m_ptr, MD_INDEF_VISIBLE); + exe_write_diary(creature_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_GENOCIDE, m_name); + } + + delete_monster_idx(creature_ptr, g_ptr->m_idx); + msg_print(_("その邪悪なモンスターは硫黄臭い煙とともに消え去った!", "The evil creature vanishes in a puff of sulfurous smoke!")); + return TRUE; + } + + msg_print(_("祈りは効果がなかった!", "Your invocation is ineffectual!")); + if (one_in_(13)) + m_ptr->mflag2 |= MFLAG2_NOGENO; + + return TRUE; + } + case MUT1_COLD_TOUCH: { + if (!get_direction(creature_ptr, &dir, FALSE, FALSE)) + return FALSE; + + POSITION y = creature_ptr->y + ddy[dir]; + POSITION x = creature_ptr->x + ddx[dir]; + grid_type *g_ptr; + g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + if (!g_ptr->m_idx) { + msg_print(_("あなたは何もない場所で手を振った。", "You wave your hands in the air.")); + return TRUE; + } + + fire_bolt(creature_ptr, GF_COLD, dir, 2 * lvl); + return TRUE; + } + case 3: + return do_cmd_throw(creature_ptr, 2 + lvl / 40, FALSE, -1); + default: + free_turn(creature_ptr); + msg_format(_("能力 %s は実装されていません。", "Power %s not implemented. Oops."), power); + return TRUE; + } +} diff --git a/src/action/mutation-execution.h b/src/action/mutation-execution.h new file mode 100644 index 000000000..008ee53c5 --- /dev/null +++ b/src/action/mutation-execution.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool exe_mutation_power(player_type *creature_ptr, int power); diff --git a/src/action/open-close-execution.c b/src/action/open-close-execution.c new file mode 100644 index 000000000..1926091fd --- /dev/null +++ b/src/action/open-close-execution.c @@ -0,0 +1,333 @@ +/*! + * @brief 扉や箱を開ける処理 + * @date 2020/07/11 + * @author Hourier + */ + +#include "action/open-close-execution.h" +#include "action/movement-execution.h" +#include "combat/attack-power-table.h" +#include "game-option/disturbance-options.h" +#include "game-option/input-options.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "grid/trap.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "perception/object-perception.h" +#include "specific-object/chest.h" +#include "status/bad-status-setter.h" +#include "status/experience.h" +#include "system/floor-type-definition.h" +#include "system/object-type-definition.h" +#include "term/screen-processor.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" +#include "player/player-status-table.h" + +/*! + * @brief 「開ける」動作コマンドのサブルーチン / + * Perform the basic "open" command on doors + * @param y 対象を行うマスのY座標 + * @param x 対象を行うマスのX座標 + * @return 実際に処理が行われた場合TRUEを返す。 + * @details + * Assume destination is a closed/locked/jammed door + * Assume there is no monster blocking the destination + * Returns TRUE if repeated commands may continue + */ +bool exe_open(player_type *creature_ptr, POSITION y, POSITION x) +{ + grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + feature_type *f_ptr = &f_info[g_ptr->feat]; + bool more = FALSE; + take_turn(creature_ptr, 100); + if (!have_flag(f_ptr->flags, FF_OPEN)) { + msg_format(_("%sはがっちりと閉じられているようだ。", "The %s appears to be stuck."), f_name + f_info[get_feat_mimic(g_ptr)].name); + return more; + } + + if (!f_ptr->power) { + cave_alter_feat(creature_ptr, y, x, FF_OPEN); + sound(SOUND_OPENDOOR); + return more; + } + + int i = creature_ptr->skill_dis; + if (creature_ptr->blind || no_lite(creature_ptr)) + i = i / 10; + + if (creature_ptr->confused || creature_ptr->image) + i = i / 10; + + int j = f_ptr->power; + j = i - (j * 4); + if (j < 2) + j = 2; + + if (randint0(100) >= j) { + if (flush_failure) + flush(); + + msg_print(_("鍵をはずせなかった。", "You failed to pick the lock.")); + more = TRUE; + } + + msg_print(_("鍵をはずした。", "You have picked the lock.")); + cave_alter_feat(creature_ptr, y, x, FF_OPEN); + sound(SOUND_OPENDOOR); + gain_exp(creature_ptr, 1); + return more; +} + +/* + * todo 常にFALSEを返している + * @brief 「閉じる」動作コマンドのサブルーチン / + * Perform the basic "close" command + * @param y 対象を行うマスのY座標 + * @param x 対象を行うマスのX座標 + * @return 実際に処理が行われた場合TRUEを返す。 + * @details + * Assume destination is an open/broken door + * Assume there is no monster blocking the destination + * Returns TRUE if repeated commands may continue + */ +bool exe_close(player_type *creature_ptr, POSITION y, POSITION x) +{ + grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + FEAT_IDX old_feat = g_ptr->feat; + bool more = FALSE; + take_turn(creature_ptr, 100); + if (!have_flag(f_info[old_feat].flags, FF_CLOSE)) + return more; + + s16b closed_feat = feat_state(creature_ptr, old_feat, FF_CLOSE); + if ((g_ptr->o_idx || (g_ptr->info & CAVE_OBJECT)) && (closed_feat != old_feat) && !have_flag(f_info[closed_feat].flags, FF_DROP)) { + msg_print(_("何かがつっかえて閉まらない。", "Something prevents it from closing.")); + } else { + cave_alter_feat(creature_ptr, y, x, FF_CLOSE); + if (old_feat == g_ptr->feat) { + msg_print(_("ドアは壊れてしまっている。", "The door appears to be broken.")); + } else { + sound(SOUND_SHUTDOOR); + } + } + + return more; +} + +/*! + * @brief 移動処理による簡易な「開く」処理 / + * easy_open_door -- + * @return 開く処理が実際に試みられた場合TRUEを返す + * @details + *
+ *	If there is a jammed/closed/locked door at the given location,
+ *	then attempt to unlock/open it. Return TRUE if an attempt was
+ *	made (successful or not), otherwise return FALSE.
+ *
+ *	The code here should be nearly identical to that in
+ *	do_cmd_open_test() and exe_open().
+ * 
+ */ +bool easy_open_door(player_type *creature_ptr, POSITION y, POSITION x) +{ + int i, j; + grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + feature_type *f_ptr = &f_info[g_ptr->feat]; + if (!is_closed_door(creature_ptr, g_ptr->feat)) + return FALSE; + + if (!have_flag(f_ptr->flags, FF_OPEN)) { + msg_format(_("%sはがっちりと閉じられているようだ。", "The %s appears to be stuck."), f_name + f_info[get_feat_mimic(g_ptr)].name); + } else if (f_ptr->power) { + i = creature_ptr->skill_dis; + if (creature_ptr->blind || no_lite(creature_ptr)) + i = i / 10; + + if (creature_ptr->confused || creature_ptr->image) + i = i / 10; + + j = f_ptr->power; + j = i - (j * 4); + if (j < 2) + j = 2; + + if (randint0(100) < j) { + msg_print(_("鍵をはずした。", "You have picked the lock.")); + cave_alter_feat(creature_ptr, y, x, FF_OPEN); + sound(SOUND_OPENDOOR); + gain_exp(creature_ptr, 1); + } else { + if (flush_failure) + flush(); + + msg_print(_("鍵をはずせなかった。", "You failed to pick the lock.")); + } + } else { + cave_alter_feat(creature_ptr, y, x, FF_OPEN); + sound(SOUND_OPENDOOR); + } + + return TRUE; +} + +/*! + * @brief 箱のトラップを解除する実行処理 / + * Perform the basic "disarm" command + * @param y 解除を行うマスのY座標 + * @param x 解除を行うマスのX座標 + * @param o_idx 箱のオブジェクトID + * @return ターンを消費する処理が行われた場合TRUEを返す + * @details + *
+ * Assume destination is a visible trap
+ * Assume there is no monster blocking the destination
+ * Returns TRUE if repeated commands may continue
+ * 
+ */ +bool exe_disarm_chest(player_type *creature_ptr, POSITION y, POSITION x, OBJECT_IDX o_idx) +{ + bool more = FALSE; + object_type *o_ptr = &creature_ptr->current_floor_ptr->o_list[o_idx]; + take_turn(creature_ptr, 100); + int i = creature_ptr->skill_dis; + if (creature_ptr->blind || no_lite(creature_ptr)) + i = i / 10; + + if (creature_ptr->confused || creature_ptr->image) + i = i / 10; + + int j = i - o_ptr->pval; + if (j < 2) + j = 2; + + if (!object_is_known(o_ptr)) { + msg_print(_("トラップが見あたらない。", "I don't see any traps.")); + } else if (o_ptr->pval <= 0) { + msg_print(_("箱にはトラップが仕掛けられていない。", "The chest is not trapped.")); + } else if (!chest_traps[o_ptr->pval]) { + msg_print(_("箱にはトラップが仕掛けられていない。", "The chest is not trapped.")); + } else if (randint0(100) < j) { + msg_print(_("箱に仕掛けられていたトラップを解除した。", "You have disarmed the chest.")); + gain_exp(creature_ptr, o_ptr->pval); + o_ptr->pval = (0 - o_ptr->pval); + } else if ((i > 5) && (randint1(i) > 5)) { + more = TRUE; + if (flush_failure) + flush(); + + msg_print(_("箱のトラップ解除に失敗した。", "You failed to disarm the chest.")); + } else { + msg_print(_("トラップを作動させてしまった!", "You set off a trap!")); + sound(SOUND_FAIL); + chest_trap(creature_ptr, y, x, o_idx); + } + + return more; +} + +/*! + * @brief 箱のトラップを解除するコマンドのサブルーチン / + * Perform the basic "disarm" command + * @param y 解除を行うマスのY座標 + * @param x 解除を行うマスのX座標 + * @param dir プレイヤーからみた方向ID + * @return ターンを消費する処理が行われた場合TRUEを返す + * @details + *
+ * Assume destination is a visible trap
+ * Assume there is no monster blocking the destination
+ * Returns TRUE if repeated commands may continue
+ * 
+ */ + +bool exe_disarm(player_type *creature_ptr, POSITION y, POSITION x, DIRECTION dir) +{ + grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + feature_type *f_ptr = &f_info[g_ptr->feat]; + concptr name = (f_name + f_ptr->name); + int power = f_ptr->power; + bool more = FALSE; + int i = creature_ptr->skill_dis; + take_turn(creature_ptr, 100); + if (creature_ptr->blind || no_lite(creature_ptr)) + i = i / 10; + + if (creature_ptr->confused || creature_ptr->image) + i = i / 10; + + int j = i - power; + if (j < 2) + j = 2; + + if (randint0(100) < j) { + msg_format(_("%sを解除した。", "You have disarmed the %s."), name); + gain_exp(creature_ptr, power); + cave_alter_feat(creature_ptr, y, x, FF_DISARM); + exe_movement(creature_ptr, dir, easy_disarm, FALSE); + } else if ((i > 5) && (randint1(i) > 5)) { + if (flush_failure) + flush(); + + msg_format(_("%sの解除に失敗した。", "You failed to disarm the %s."), name); + more = TRUE; + } else { + msg_format(_("%sを作動させてしまった!", "You set off the %s!"), name); + exe_movement(creature_ptr, dir, easy_disarm, FALSE); + } + + return more; +} + +/*! + * @brief 「打ち破る」動作コマンドのサブルーチン / + * Perform the basic "bash" command + * @param y 対象を行うマスのY座標 + * @param x 対象を行うマスのX座標 + * @param dir プレイヤーから見たターゲットの方角ID + * @return 実際に処理が行われた場合TRUEを返す。 + * @details + *
+ * Assume destination is a closed/locked/jammed door
+ * Assume there is no monster blocking the destination
+ * Returns TRUE if repeated commands may continue
+ * 
+ */ +bool exe_bash(player_type *creature_ptr, POSITION y, POSITION x, DIRECTION dir) +{ + grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + feature_type *f_ptr = &f_info[g_ptr->feat]; + int bash = adj_str_blow[creature_ptr->stat_ind[A_STR]]; + int temp = f_ptr->power; + bool more = FALSE; + concptr name = f_name + f_info[get_feat_mimic(g_ptr)].name; + take_turn(creature_ptr, 100); + msg_format(_("%sに体当たりをした!", "You smash into the %s!"), name); + temp = (bash - (temp * 10)); + if (creature_ptr->pclass == CLASS_BERSERKER) + temp *= 2; + + if (temp < 1) + temp = 1; + + if (randint0(100) < temp) { + msg_format(_("%sを壊した!", "The %s crashes open!"), name); + sound(have_flag(f_ptr->flags, FF_GLASS) ? SOUND_GLASS : SOUND_OPENDOOR); + if ((randint0(100) < 50) || (feat_state(creature_ptr, g_ptr->feat, FF_OPEN) == g_ptr->feat) || have_flag(f_ptr->flags, FF_GLASS)) { + cave_alter_feat(creature_ptr, y, x, FF_BASH); + } else { + cave_alter_feat(creature_ptr, y, x, FF_OPEN); + } + + exe_movement(creature_ptr, dir, FALSE, FALSE); + } else if (randint0(100) < adj_dex_safe[creature_ptr->stat_ind[A_DEX]] + creature_ptr->lev) { + msg_format(_("この%sは頑丈だ。", "The %s holds firm."), name); + more = TRUE; + } else { + msg_print(_("体のバランスをくずしてしまった。", "You are off-balance.")); + (void)set_paralyzed(creature_ptr, creature_ptr->paralyzed + 2 + randint0(2)); + } + + return more; +} diff --git a/src/action/open-close-execution.h b/src/action/open-close-execution.h new file mode 100644 index 000000000..9c8453c50 --- /dev/null +++ b/src/action/open-close-execution.h @@ -0,0 +1,10 @@ +#pragma once + +#include "system/angband.h" + +bool exe_open(player_type *creature_ptr, POSITION y, POSITION x); +bool exe_close(player_type *creature_ptr, POSITION y, POSITION x); +bool easy_open_door(player_type *creature_ptr, POSITION y, POSITION x); +bool exe_disarm(player_type *creature_ptr, POSITION y, POSITION x, DIRECTION dir); +bool exe_disarm_chest(player_type *creature_ptr, POSITION y, POSITION x, OBJECT_IDX o_idx); +bool exe_bash(player_type *creature_ptr, POSITION y, POSITION x, DIRECTION dir); diff --git a/src/action/open-util.c b/src/action/open-util.c new file mode 100644 index 000000000..2f8994fba --- /dev/null +++ b/src/action/open-util.c @@ -0,0 +1,67 @@ +#include "action/open-util.h" +#include "floor/geometry.h" +#include "grid/grid.h" +#include "grid/trap.h" +#include "perception/object-perception.h" +#include "system/floor-type-definition.h" +#include "system/object-type-definition.h" + +/*! + * @brief 該当のマスに存在している箱のオブジェクトIDを返す。 + * @param y 走査対象にしたいマスのY座標 + * @param x 走査対象にしたいマスのX座標 + * @param trapped TRUEならばトラップが存在する箱のみ、FALSEならば空でない箱全てを対象にする + * @return 箱が存在する場合そのオブジェクトID、存在しない場合0を返す。 + */ +OBJECT_IDX chest_check(floor_type *floor_ptr, POSITION y, POSITION x, bool trapped) +{ + grid_type *g_ptr = &floor_ptr->grid_array[y][x]; + OBJECT_IDX this_o_idx, next_o_idx = 0; + for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) { + object_type *o_ptr; + o_ptr = &floor_ptr->o_list[this_o_idx]; + next_o_idx = o_ptr->next_o_idx; + if ((o_ptr->tval == TV_CHEST) + && (((!trapped) && (o_ptr->pval)) || /* non empty */ + ((trapped) && (o_ptr->pval > 0)))) /* trapped only */ + return this_o_idx; + } + + return 0; +} + +/*! + * @brief プレイヤーの周辺9マスに箱のあるマスがいくつあるかを返す / + * Return the number of chests around (or under) the character. + * @param y 該当するマスの中から1つのY座標を返す参照ポインタ + * @param x 該当するマスの中から1つのX座標を返す参照ポインタ + * @param trapped TRUEならばトラップの存在が判明している箱のみ対象にする + * @return 該当する地形の数 + * @details + * If requested, count only trapped chests. + */ +int count_chests(player_type *creature_ptr, POSITION *y, POSITION *x, bool trapped) +{ + int count = 0; + for (DIRECTION d = 0; d < 9; d++) { + POSITION yy = creature_ptr->y + ddy_ddd[d]; + POSITION xx = creature_ptr->x + ddx_ddd[d]; + OBJECT_IDX o_idx = chest_check(creature_ptr->current_floor_ptr, yy, xx, FALSE); + if (!o_idx) + continue; + + object_type *o_ptr; + o_ptr = &creature_ptr->current_floor_ptr->o_list[o_idx]; + if (o_ptr->pval == 0) + continue; + + if (trapped && (!object_is_known(o_ptr) || !chest_traps[o_ptr->pval])) + continue; + + ++count; + *y = yy; + *x = xx; + } + + return count; +} diff --git a/src/action/open-util.h b/src/action/open-util.h new file mode 100644 index 000000000..52249064c --- /dev/null +++ b/src/action/open-util.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" + +OBJECT_IDX chest_check(floor_type *floor_ptr, POSITION y, POSITION x, bool trapped); +int count_chests(player_type *creature_ptr, POSITION *y, POSITION *x, bool trapped); diff --git a/src/action/racial-execution.c b/src/action/racial-execution.c new file mode 100644 index 000000000..56b132701 --- /dev/null +++ b/src/action/racial-execution.c @@ -0,0 +1,128 @@ +#include "action/racial-execution.h" +#include "action/action-limited.h" +#include "core/asking-player.h" +#include "game-option/disturbance-options.h" +#include "racial/racial-switcher.h" +#include "racial/racial-util.h" +#include "term/screen-processor.h" +#include "view/display-messages.h" + +/*! + * @brief レイシャル・パワー発動処理 + * @param creature_ptr プレーヤーへの参照ポインタ + * @param command 発動するレイシャルのID + * @return 処理を実際に実行した場合はTRUE、キャンセルした場合FALSEを返す。 + */ +bool exe_racial_power(player_type *creature_ptr, const s32b command) +{ + if (command <= -3) + return switch_class_racial_execution(creature_ptr, command); + + if (creature_ptr->mimic_form) + return switch_mimic_racial_execution(creature_ptr); + + return switch_race_racial_execution(creature_ptr, command); +} + +/*! + * @brief レイシャル・パワーの発動成功率を計算する / Returns the chance to activate a racial power/mutation + * @param rpi_ptr 発動したいレイシャル・パワー情報の構造体参照ポインタ + * @return 成功率(%)を返す + */ +PERCENTAGE racial_chance(player_type *creature_ptr, rpi_type *rpi_ptr) +{ + if ((creature_ptr->lev < rpi_ptr->min_level) || creature_ptr->confused) + return 0; + + PERCENTAGE difficulty = rpi_ptr->fail; + if (difficulty == 0) + return 100; + + if (creature_ptr->stun) { + difficulty += (PERCENTAGE)creature_ptr->stun; + } else if (creature_ptr->lev > rpi_ptr->min_level) { + PERCENTAGE lev_adj = (PERCENTAGE)((creature_ptr->lev - rpi_ptr->min_level) / 3); + if (lev_adj > 10) + lev_adj = 10; + + difficulty -= lev_adj; + } + + if (difficulty < 5) + difficulty = 5; + + difficulty = difficulty / 2; + const BASE_STATUS stat = creature_ptr->stat_cur[rpi_ptr->stat]; + int sum = 0; + for (int i = 1; i <= stat; i++) { + int val = i - difficulty; + if (val > 0) + sum += (val <= difficulty) ? val : difficulty; + } + + if (difficulty == 0) + return 100; + else + return ((sum * 100) / difficulty) / stat; +} + +static void adjust_racial_power_difficulty(player_type *creature_ptr, rpi_type *rpi_ptr, int *difficulty) +{ + if (*difficulty == 0) + return; + + if (creature_ptr->stun) { + *difficulty += creature_ptr->stun; + } else if (creature_ptr->lev > rpi_ptr->min_level) { + int lev_adj = ((creature_ptr->lev - rpi_ptr->min_level) / 3); + if (lev_adj > 10) + lev_adj = 10; + *difficulty -= lev_adj; + } + + if (*difficulty < 5) + *difficulty = 5; +} + +/*! + * @brief レイシャル・パワーの発動の判定処理 + * @param rpi_ptr 発動したいレイシャル・パワー情報の構造体参照ポインタ + * @return racial_level_check_result + */ +racial_level_check_result check_racial_level(player_type *creature_ptr, rpi_type *rpi_ptr) +{ + PLAYER_LEVEL min_level = rpi_ptr->min_level; + int use_stat = rpi_ptr->stat; + int difficulty = rpi_ptr->fail; + int use_hp = 0; + rpi_ptr->racial_cost = rpi_ptr->cost; + if (creature_ptr->csp < rpi_ptr->racial_cost) + use_hp = rpi_ptr->racial_cost - creature_ptr->csp; + + if (creature_ptr->lev < min_level) { + msg_format(_("この能力を使用するにはレベル %d に達していなければなりません。", "You need to attain level %d to use this power."), min_level); + free_turn(creature_ptr); + return RACIAL_CANCEL; + } + + if (cmd_limit_confused(creature_ptr)) { + free_turn(creature_ptr); + return RACIAL_CANCEL; + } else if (creature_ptr->chp < use_hp) { + if (!get_check(_("本当に今の衰弱した状態でこの能力を使いますか?", "Really use the power in your weakened state? "))) { + free_turn(creature_ptr); + return RACIAL_CANCEL; + } + } + + adjust_racial_power_difficulty(creature_ptr, rpi_ptr, &difficulty); + take_turn(creature_ptr, 100); + if (randint1(creature_ptr->stat_cur[use_stat]) >= ((difficulty / 2) + randint1(difficulty / 2))) + return RACIAL_SUCCESS; + + if (flush_failure) + flush(); + + msg_print(_("充分に集中できなかった。", "You've failed to concentrate hard enough.")); + return RACIAL_FAILURE; +} diff --git a/src/action/racial-execution.h b/src/action/racial-execution.h new file mode 100644 index 000000000..90e3d4e58 --- /dev/null +++ b/src/action/racial-execution.h @@ -0,0 +1,14 @@ +#pragma once + +#include "system/angband.h" + +typedef enum racial_level_check_result { + RACIAL_SUCCESS = 1, + RACIAL_FAILURE = -1, + RACIAL_CANCEL = 0, +} racial_level_check_result; + +typedef struct rpi_type rpi_type; +PERCENTAGE racial_chance(player_type *creature_ptr, rpi_type *rpi_ptr); +racial_level_check_result check_racial_level(player_type *creature_ptr, rpi_type *rpi_ptr); +bool exe_racial_power(player_type *creature_ptr, const s32b command); diff --git a/src/action/run-execution.c b/src/action/run-execution.c new file mode 100644 index 000000000..26e226cfd --- /dev/null +++ b/src/action/run-execution.c @@ -0,0 +1,381 @@ +#include "action/run-execution.h" +#include "action/movement-execution.h" +#include "core/disturbance.h" +#include "floor/cave.h" +#include "floor/floor-util.h" +#include "game-option/disturbance-options.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "object/object-mark-types.h" +#include "system/floor-type-definition.h" +#include "system/object-type-definition.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" + +bool ignore_avoid_run; + +/* Allow quick "cycling" through the legal directions */ +byte cycle[MAX_RUN_CYCLES] = { 1, 2, 3, 6, 9, 8, 7, 4, 1, 2, 3, 6, 9, 8, 7, 4, 1 }; + +/* Map each direction into the "middle" of the "cycle[]" array */ +byte chome[MAX_RUN_CHOME] = { 0, 8, 9, 10, 7, 0, 11, 6, 5, 4 }; + +/* The direction we are running */ +static DIRECTION find_current; + +/* The direction we came from */ +static DIRECTION find_prevdir; + +static bool find_openarea; + +/* We are looking for a break */ +static bool find_breakright; +static bool find_breakleft; + +/*! + * @brief ダッシュ移動処理中、移動先のマスが既知の壁かどうかを判定する / + * Hack -- Check for a "known wall" (see below) + * @param creature_ptr プレーヤーへの参照ポインタ + * @param dir 想定する移動方向ID + * @param y 移動元のY座標 + * @param x 移動元のX座標 + * @return 移動先が既知の壁ならばTRUE + */ +static bool see_wall(player_type *creature_ptr, DIRECTION dir, POSITION y, POSITION x) +{ + y += ddy[dir]; + x += ddx[dir]; + floor_type *floor_ptr = creature_ptr->current_floor_ptr; + if (!in_bounds2(floor_ptr, y, x)) + return FALSE; + + grid_type *g_ptr; + g_ptr = &floor_ptr->grid_array[y][x]; + if (!(g_ptr->info & CAVE_MARK)) + return FALSE; + + s16b feat = get_feat_mimic(g_ptr); + feature_type *f_ptr = &f_info[feat]; + if (!player_can_enter(creature_ptr, feat, 0)) + return !have_flag(f_ptr->flags, FF_DOOR); + + if (have_flag(f_ptr->flags, FF_AVOID_RUN) && !ignore_avoid_run) + return TRUE; + + if (!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) + return !have_flag(f_ptr->flags, FF_DOOR); + + return FALSE; +} + +/*! + * @brief ダッシュ処理の導入 / + * Initialize the running algorithm for a new direction. + * @param creature_ptr プレーヤーへの参照ポインタ + * @param dir 導入の移動先 + * @details + * Diagonal Corridor -- allow diaginal entry into corridors.\n + *\n + * Blunt Corridor -- If there is a wall two spaces ahead and\n + * we seem to be in a corridor, then force a turn into the side\n + * corridor, must be moving straight into a corridor here. ???\n + *\n + * Diagonal Corridor Blunt Corridor (?)\n + * \# \# \#\n + * \#x\# \@x\#\n + * \@\@p. p\n + */ +static void run_init(player_type *creature_ptr, DIRECTION dir) +{ + find_current = dir; + find_prevdir = dir; + find_openarea = TRUE; + find_breakright = find_breakleft = FALSE; + bool deepleft = FALSE; + bool deepright = FALSE; + bool shortright = FALSE; + bool shortleft = FALSE; + creature_ptr->run_py = creature_ptr->y; + creature_ptr->run_px = creature_ptr->x; + int row = creature_ptr->y + ddy[dir]; + int col = creature_ptr->x + ddx[dir]; + ignore_avoid_run = cave_have_flag_bold(creature_ptr->current_floor_ptr, row, col, FF_AVOID_RUN); + int i = chome[dir]; + if (see_wall(creature_ptr, cycle[i + 1], creature_ptr->y, creature_ptr->x)) { + find_breakleft = TRUE; + shortleft = TRUE; + } else if (see_wall(creature_ptr, cycle[i + 1], row, col)) { + find_breakleft = TRUE; + deepleft = TRUE; + } + + if (see_wall(creature_ptr, cycle[i - 1], creature_ptr->y, creature_ptr->x)) { + find_breakright = TRUE; + shortright = TRUE; + } else if (see_wall(creature_ptr, cycle[i - 1], row, col)) { + find_breakright = TRUE; + deepright = TRUE; + } + + if (!find_breakleft || !find_breakright) + return; + + find_openarea = FALSE; + if (dir & 0x01) { + if (deepleft && !deepright) { + find_prevdir = cycle[i - 1]; + } else if (deepright && !deepleft) { + find_prevdir = cycle[i + 1]; + } + + return; + } + + if (!see_wall(creature_ptr, cycle[i], row, col)) + return; + + if (shortleft && !shortright) { + find_prevdir = cycle[i - 2]; + } else if (shortright && !shortleft) { + find_prevdir = cycle[i + 2]; + } +} + +/*! + * @brief ダッシュ移動処理中、移動先のマスか未知の地形かどうかを判定する / + * Hack -- Check for an "unknown corner" (see below) + * @param creature_ptr プレーヤーへの参照ポインタ + * @param dir 想定する移動方向ID + * @param y 移動元のY座標 + * @param x 移動元のX座標 + * @return 移動先が未知の地形ならばTRUE + */ +static bool see_nothing(player_type *creature_ptr, DIRECTION dir, POSITION y, POSITION x) +{ + y += ddy[dir]; + x += ddx[dir]; + + floor_type *floor_ptr = creature_ptr->current_floor_ptr; + if (!in_bounds2(floor_ptr, y, x)) + return TRUE; + + if (floor_ptr->grid_array[y][x].info & (CAVE_MARK)) + return FALSE; + + if (player_can_see_bold(creature_ptr, y, x)) + return FALSE; + + return TRUE; +} + +/*! + * @brief ダッシュ移動が継続できるかどうかの判定 / + * Update the current "run" path + * @param creature_ptr プレーヤーへの参照ポインタ + * @return 立ち止まるべき条件が満たされたらTRUE + * ダッシュ移動が継続できるならばTRUEを返す。 + * Return TRUE if the running should be stopped + */ +static bool run_test(player_type *creature_ptr) +{ + DIRECTION prev_dir = find_prevdir; + int max = (prev_dir & 0x01) + 1; + floor_type *floor_ptr = creature_ptr->current_floor_ptr; + if ((disturb_trap_detect || alert_trap_detect) && creature_ptr->dtrap && !(floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].info & CAVE_IN_DETECT)) { + creature_ptr->dtrap = FALSE; + if (!(floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].info & CAVE_UNSAFE)) { + if (alert_trap_detect) { + msg_print(_("* 注意:この先はトラップの感知範囲外です! *", "*Leaving trap detect region!*")); + } + + if (disturb_trap_detect) { + /* Break Run */ + return TRUE; + } + } + } + + DIRECTION check_dir = 0; + int option = 0, option2 = 0; + for (int i = -max; i <= max; i++) { + OBJECT_IDX this_o_idx, next_o_idx = 0; + DIRECTION new_dir = cycle[chome[prev_dir] + i]; + int row = creature_ptr->y + ddy[new_dir]; + int col = creature_ptr->x + ddx[new_dir]; + grid_type *g_ptr; + g_ptr = &floor_ptr->grid_array[row][col]; + FEAT_IDX feat = get_feat_mimic(g_ptr); + feature_type *f_ptr; + f_ptr = &f_info[feat]; + if (g_ptr->m_idx) { + monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx]; + if (m_ptr->ml) + return TRUE; + } + + for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) { + object_type *o_ptr; + o_ptr = &floor_ptr->o_list[this_o_idx]; + next_o_idx = o_ptr->next_o_idx; + if (o_ptr->marked & OM_FOUND) + return TRUE; + } + + bool inv = TRUE; + if (g_ptr->info & (CAVE_MARK)) { + bool notice = have_flag(f_ptr->flags, FF_NOTICE); + if (notice && have_flag(f_ptr->flags, FF_MOVE)) { + if (find_ignore_doors && have_flag(f_ptr->flags, FF_DOOR) && have_flag(f_ptr->flags, FF_CLOSE)) { + notice = FALSE; + } else if (find_ignore_stairs && have_flag(f_ptr->flags, FF_STAIRS)) { + notice = FALSE; + } else if (have_flag(f_ptr->flags, FF_LAVA) && (creature_ptr->immune_fire || is_invuln(creature_ptr))) { + notice = FALSE; + } else if (have_flag(f_ptr->flags, FF_WATER) && have_flag(f_ptr->flags, FF_DEEP) + && (creature_ptr->levitation || creature_ptr->can_swim || (creature_ptr->total_weight <= weight_limit(creature_ptr)))) { + notice = FALSE; + } + } + + if (notice) + return TRUE; + + inv = FALSE; + } + + if (!inv && see_wall(creature_ptr, 0, row, col)) { + if (find_openarea) { + if (i < 0) { + find_breakright = TRUE; + } else if (i > 0) { + find_breakleft = TRUE; + } + } + + continue; + } + + if (find_openarea) + continue; + + if (!option) { + option = new_dir; + continue; + } + + if (option2) + return TRUE; + + if (option != cycle[chome[prev_dir] + i - 1]) + return TRUE; + + if (new_dir & 0x01) { + check_dir = cycle[chome[prev_dir] + i - 2]; + option2 = new_dir; + continue; + } + + check_dir = cycle[chome[prev_dir] + i + 1]; + option2 = option; + option = new_dir; + } + + if (find_openarea) { + for (int i = -max; i < 0; i++) { + if (!see_wall(creature_ptr, cycle[chome[prev_dir] + i], creature_ptr->y, creature_ptr->x)) { + if (find_breakright) + return TRUE; + } else { + if (find_breakleft) + return TRUE; + } + } + + for (int i = max; i > 0; i--) { + if (!see_wall(creature_ptr, cycle[chome[prev_dir] + i], creature_ptr->y, creature_ptr->x)) { + if (find_breakleft) + return TRUE; + } else { + if (find_breakright) + return TRUE; + } + } + + return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x); + } + + if (!option) + return TRUE; + + if (!option2) { + find_current = option; + find_prevdir = option; + return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x); + } else if (!find_cut) { + find_current = option; + find_prevdir = option2; + return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x); + } + + int row = creature_ptr->y + ddy[option]; + int col = creature_ptr->x + ddx[option]; + if (!see_wall(creature_ptr, option, row, col) || !see_wall(creature_ptr, check_dir, row, col)) { + if (see_nothing(creature_ptr, option, row, col) && see_nothing(creature_ptr, option2, row, col)) { + find_current = option; + find_prevdir = option2; + return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x); + } + + return TRUE; + } + + if (find_cut) { + find_current = option2; + find_prevdir = option2; + return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x); + } + + find_current = option; + find_prevdir = option2; + return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x); +} + +/*! + * @brief 継続的なダッシュ処理 / + * Take one step along the current "run" path + * @param creature_ptr プレーヤーへの参照ポインタ + * @param dir 移動を試みる方向ID + * @return なし + */ +void run_step(player_type *creature_ptr, DIRECTION dir) +{ + if (dir) { + ignore_avoid_run = TRUE; + if (see_wall(creature_ptr, dir, creature_ptr->y, creature_ptr->x)) { + sound(SOUND_HITWALL); + msg_print(_("その方向には走れません。", "You cannot run in that direction.")); + disturb(creature_ptr, FALSE, FALSE); + return; + } + + run_init(creature_ptr, dir); + } else { + if (run_test(creature_ptr)) { + disturb(creature_ptr, FALSE, FALSE); + return; + } + } + + if (--creature_ptr->running <= 0) + return; + + take_turn(creature_ptr, 100); + exe_movement(creature_ptr, find_current, FALSE, FALSE); + if (player_bold(creature_ptr, creature_ptr->run_py, creature_ptr->run_px)) { + creature_ptr->run_py = 0; + creature_ptr->run_px = 0; + disturb(creature_ptr, FALSE, FALSE); + } +} diff --git a/src/action/run-execution.h b/src/action/run-execution.h new file mode 100644 index 000000000..d84cb2d0a --- /dev/null +++ b/src/action/run-execution.h @@ -0,0 +1,12 @@ +#pragma once + +#include "system/angband.h" + +#define MAX_RUN_CYCLES 17 +#define MAX_RUN_CHOME 10 + +extern bool ignore_avoid_run; +extern byte cycle[MAX_RUN_CYCLES]; +extern byte chome[MAX_RUN_CHOME]; + +void run_step(player_type *creature_ptr, DIRECTION dir); diff --git a/src/action/throw-util.c b/src/action/throw-util.c new file mode 100644 index 000000000..5ed84c12e --- /dev/null +++ b/src/action/throw-util.c @@ -0,0 +1,18 @@ +#include "action/throw-util.h" + +it_type *initialize_it_type( + it_type *item_throw_ptr, object_type *q_ptr, const int delay_factor_val, const int mult, const bool boomerang, const OBJECT_IDX shuriken) +{ + item_throw_ptr->mult = mult; + item_throw_ptr->boomerang = boomerang; + item_throw_ptr->shuriken = shuriken; + item_throw_ptr->q_ptr = q_ptr; + item_throw_ptr->hit_body = FALSE; + item_throw_ptr->hit_wall = FALSE; + item_throw_ptr->equiped_item = FALSE; + item_throw_ptr->return_when_thrown = FALSE; + item_throw_ptr->msec = delay_factor_val * delay_factor_val * delay_factor_val; + item_throw_ptr->come_back = FALSE; + item_throw_ptr->do_drop = TRUE; + return item_throw_ptr; +} diff --git a/src/action/throw-util.h b/src/action/throw-util.h new file mode 100644 index 000000000..62ea69e32 --- /dev/null +++ b/src/action/throw-util.h @@ -0,0 +1,48 @@ +#pragma once + +#include "system/angband.h" +#include "system/object-type-definition.h" + +// Item Throw. +typedef struct grid_type grid_type; +typedef struct monster_type monster_type; +typedef struct it_type { + int mult; + bool boomerang; + OBJECT_IDX shuriken; + OBJECT_IDX item; + POSITION y; + POSITION x; + POSITION ty; + POSITION tx; + POSITION prev_y; + POSITION prev_x; + POSITION ny[19]; + POSITION nx[19]; + int chance; + int tdam; + int tdis; + int cur_dis; + int visible; + PERCENTAGE corruption_possibility; + object_type *q_ptr; + object_type *o_ptr; + bool hit_body; + bool hit_wall; + bool equiped_item; + bool return_when_thrown; + GAME_TEXT o_name[MAX_NLEN]; + int msec; + BIT_FLAGS obj_flags[TR_FLAG_SIZE]; + bool come_back; + bool do_drop; + grid_type *g_ptr; + monster_type *m_ptr; + GAME_TEXT m_name[MAX_NLEN]; + int back_chance; + char o2_name[MAX_NLEN]; + bool super_boomerang; +} it_type; + +it_type *initialize_it_type( + it_type *item_throw_ptr, object_type *q_ptr, const int delay_factor_val, const int mult, const bool boomerang, const OBJECT_IDX shuriken); diff --git a/src/action/travel-execution.c b/src/action/travel-execution.c new file mode 100644 index 000000000..ea9336ebc --- /dev/null +++ b/src/action/travel-execution.c @@ -0,0 +1,121 @@ +#include "action/travel-execution.h" +#include "action/movement-execution.h" +#include "action/run-execution.h" +#include "core/disturbance.h" +#include "game-option/disturbance-options.h" +#include "game-option/input-options.h" +#include "game-option/special-options.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "player/player-move.h" +#include "system/floor-type-definition.h" +#include "view/display-messages.h" + +travel_type travel; + +/*! + * @brief トラベル機能の判定処理 / + * Test for traveling + * @param creature_ptr プレーヤーへの参照ポインタ + * @param prev_dir 前回移動を行った元の方角ID + * @return 次の方向 + */ +static DIRECTION travel_test(player_type *creature_ptr, DIRECTION prev_dir) +{ + if (creature_ptr->blind || no_lite(creature_ptr)) { + msg_print(_("目が見えない!", "You cannot see!")); + return 0; + } + + floor_type *floor_ptr = creature_ptr->current_floor_ptr; + if ((disturb_trap_detect || alert_trap_detect) && creature_ptr->dtrap && !(floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].info & CAVE_IN_DETECT)) { + creature_ptr->dtrap = FALSE; + if (!(floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].info & CAVE_UNSAFE)) { + if (alert_trap_detect) + msg_print(_("* 注意:この先はトラップの感知範囲外です! *", "*Leaving trap detect region!*")); + + if (disturb_trap_detect) + return 0; + } + } + + int max = (prev_dir & 0x01) + 1; + const grid_type *g_ptr; + for (int i = -max; i <= max; i++) { + DIRECTION dir = cycle[chome[prev_dir] + i]; + POSITION row = creature_ptr->y + ddy[dir]; + POSITION col = creature_ptr->x + ddx[dir]; + g_ptr = &floor_ptr->grid_array[row][col]; + if (g_ptr->m_idx) { + monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx]; + if (m_ptr->ml) + return 0; + } + } + + int cost = travel.cost[creature_ptr->y][creature_ptr->x]; + DIRECTION new_dir = 0; + for (int i = 0; i < 8; ++i) { + int dir_cost = travel.cost[creature_ptr->y + ddy_ddd[i]][creature_ptr->x + ddx_ddd[i]]; + if (dir_cost < cost) { + new_dir = ddd[i]; + cost = dir_cost; + } + } + + if (!new_dir) + return 0; + + g_ptr = &floor_ptr->grid_array[creature_ptr->y + ddy[new_dir]][creature_ptr->x + ddx[new_dir]]; + if (!easy_open && is_closed_door(creature_ptr, g_ptr->feat)) + return 0; + + if (!g_ptr->mimic && !trap_can_be_ignored(creature_ptr, g_ptr->feat)) + return 0; + + return new_dir; +} + +/*! + * @brief トラベル機能の実装 / + * Travel command + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void travel_step(player_type *creature_ptr) +{ + travel.dir = travel_test(creature_ptr, travel.dir); + if (!travel.dir) { + if (travel.run == 255) { + msg_print(_("道筋が見つかりません!", "No route is found!")); + travel.y = travel.x = 0; + } + + disturb(creature_ptr, FALSE, TRUE); + return; + } + + take_turn(creature_ptr, 100); + exe_movement(creature_ptr, travel.dir, always_pickup, FALSE); + if ((creature_ptr->y == travel.y) && (creature_ptr->x == travel.x)) { + travel.run = 0; + travel.y = travel.x = 0; + } else if (travel.run > 0) + travel.run--; + + term_xtra(TERM_XTRA_DELAY, delay_factor); +} + +/*! + * @brief トラベル処理の記憶配列を初期化する Hack: forget the "flow" information + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void forget_travel_flow(floor_type *floor_ptr) +{ + for (POSITION y = 0; y < floor_ptr->height; y++) + for (POSITION x = 0; x < floor_ptr->width; x++) + travel.cost[y][x] = MAX_SHORT; + + travel.y = travel.x = 0; +} diff --git a/src/action/travel-execution.h b/src/action/travel-execution.h new file mode 100644 index 000000000..0a000ef08 --- /dev/null +++ b/src/action/travel-execution.h @@ -0,0 +1,18 @@ +#pragma once + +#include "system/angband.h" +#include "floor/floor-base-definitions.h" + + /* A structure type for travel command */ +typedef struct travel_type { + int run; /* Remaining grid number */ + int cost[MAX_HGT][MAX_WID]; + POSITION x; /* Target X */ + POSITION y; /* Target Y */ + DIRECTION dir; /* Running direction */ +} travel_type; + +extern travel_type travel; + +void travel_step(player_type *creature_ptr); +void forget_travel_flow(floor_type *floor_ptr); diff --git a/src/action/tunnel-execution.c b/src/action/tunnel-execution.c new file mode 100644 index 000000000..6664b5ab6 --- /dev/null +++ b/src/action/tunnel-execution.c @@ -0,0 +1,112 @@ +#include "action/tunnel-execution.h" +#include "core/player-update-types.h" +#include "floor/cave.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "player-info/avatar.h" +#include "player/player-move.h" +#include "system/floor-type-definition.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" + +/*! + * @brief 「掘る」コマンドを該当のマスに行えるかの判定と結果メッセージの表示 / + * Determine if a given grid may be "tunneled" + * @param y 対象を行うマスのY座標 + * @param x 対象を行うマスのX座標 + * @return + */ +static bool do_cmd_tunnel_test(floor_type *floor_ptr, POSITION y, POSITION x) +{ + grid_type *g_ptr = &floor_ptr->grid_array[y][x]; + if (!(g_ptr->info & CAVE_MARK)) { + msg_print(_("そこには何も見当たらない。", "You see nothing there.")); + return FALSE; + } + + if (!cave_have_flag_grid(g_ptr, FF_TUNNEL)) { + msg_print(_("そこには掘るものが見当たらない。", "You see nothing there to tunnel.")); + return FALSE; + } + + return TRUE; +} + +/*! + * @brief 「掘る」動作コマンドのサブルーチン / + * Perform the basic "tunnel" command + * @param y 対象を行うマスのY座標 + * @param x 対象を行うマスのX座標 + * @return 実際に処理が行われた場合TRUEを返す。 + * @details + * Assumes that no monster is blocking the destination + * Do not use twall anymore + * Returns TRUE if repeated commands may continue + */ +bool exe_tunnel(player_type *creature_ptr, POSITION y, POSITION x) +{ + grid_type *g_ptr; + feature_type *f_ptr, *mimic_f_ptr; + int power; + concptr name; + bool more = FALSE; + if (!do_cmd_tunnel_test(creature_ptr->current_floor_ptr, y, x)) + return FALSE; + + take_turn(creature_ptr, 100); + g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + f_ptr = &f_info[g_ptr->feat]; + power = f_ptr->power; + mimic_f_ptr = &f_info[get_feat_mimic(g_ptr)]; + name = f_name + mimic_f_ptr->name; + sound(SOUND_DIG); + if (have_flag(f_ptr->flags, FF_PERMANENT)) { + if (have_flag(mimic_f_ptr->flags, FF_PERMANENT)) + msg_print(_("この岩は硬すぎて掘れないようだ。", "This seems to be permanent rock.")); + else + msg_print(_("そこは掘れない!", "You can't tunnel through that!")); + } else if (have_flag(f_ptr->flags, FF_CAN_DIG)) { + if (creature_ptr->skill_dig > randint0(20 * power)) { + msg_format(_("%sをくずした。", "You have removed the %s."), name); + cave_alter_feat(creature_ptr, y, x, FF_TUNNEL); + creature_ptr->update |= PU_FLOW; + } else { + msg_format(_("%sをくずしている。", "You dig into the %s."), name); + more = TRUE; + } + } else { + bool tree = have_flag(mimic_f_ptr->flags, FF_TREE); + if (creature_ptr->skill_dig > power + randint0(40 * power)) { + if (tree) + msg_format(_("%sを切り払った。", "You have cleared away the %s."), name); + else { + msg_print(_("穴を掘り終えた。", "You have finished the tunnel.")); + creature_ptr->update |= (PU_FLOW); + } + + if (have_flag(f_ptr->flags, FF_GLASS)) + sound(SOUND_GLASS); + + cave_alter_feat(creature_ptr, y, x, FF_TUNNEL); + chg_virtue(creature_ptr, V_DILIGENCE, 1); + chg_virtue(creature_ptr, V_NATURE, -1); + } else { + if (tree) { + msg_format(_("%sを切っている。", "You chop away at the %s."), name); + if (randint0(100) < 25) + search(creature_ptr); + } else { + msg_format(_("%sに穴を掘っている。", "You tunnel into the %s."), name); + } + + more = TRUE; + } + } + + if (is_hidden_door(creature_ptr, g_ptr) && (randint0(100) < 25)) + search(creature_ptr); + + return more; +} diff --git a/src/action/tunnel-execution.h b/src/action/tunnel-execution.h new file mode 100644 index 000000000..aa689e054 --- /dev/null +++ b/src/action/tunnel-execution.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool exe_tunnel(player_type *creature_ptr, POSITION y, POSITION x); diff --git a/src/action/weapon-shield.c b/src/action/weapon-shield.c new file mode 100644 index 000000000..6f2733f09 --- /dev/null +++ b/src/action/weapon-shield.c @@ -0,0 +1,71 @@ +#include "action/weapon-shield.h" +#include "flavor/flavor-describer.h" +#include "game-option/birth-options.h" +#include "inventory/inventory-object.h" +#include "inventory/inventory-slot-types.h" +#include "object-hook/hook-checker.h" +#include "object-hook/hook-weapon.h" +#include "object/object-generator.h" +#include "system/object-type-definition.h" +#include "view/display-messages.h" + +/*! + * @brief 持ち替え処理 + * @param owner_ptr プレーヤーへの参照ポインタ + * @param item 持ち替えを行いたい装備部位ID + * @return なし + */ +void verify_equip_slot(player_type *owner_ptr, INVENTORY_IDX item) +{ + object_type *o_ptr, *new_o_ptr; + GAME_TEXT o_name[MAX_NLEN]; + + if (item == INVEN_RARM) { + if (!has_melee_weapon(owner_ptr, INVEN_LARM)) + return; + + o_ptr = &owner_ptr->inventory_list[INVEN_LARM]; + describe_flavor(owner_ptr, o_name, o_ptr, 0); + + if (object_is_cursed(o_ptr)) { + if (object_allow_two_hands_wielding(o_ptr) && can_two_hands_wielding(owner_ptr)) + msg_format(_("%sを両手で構えた。", "You are wielding %s with both hands."), o_name); + return; + } + + new_o_ptr = &owner_ptr->inventory_list[INVEN_RARM]; + object_copy(new_o_ptr, o_ptr); + owner_ptr->total_weight += o_ptr->weight; + inven_item_increase(owner_ptr, INVEN_LARM, -((int)o_ptr->number)); + inven_item_optimize(owner_ptr, INVEN_LARM); + if (object_allow_two_hands_wielding(o_ptr) && can_two_hands_wielding(owner_ptr)) + msg_format(_("%sを両手で構えた。", "You are wielding %s with both hands."), o_name); + else + msg_format(_("%sを%sで構えた。", "You are wielding %s in your %s hand."), o_name, (left_hander ? _("左手", "left") : _("右手", "right"))); + return; + } + + if (item != INVEN_LARM) + return; + + o_ptr = &owner_ptr->inventory_list[INVEN_RARM]; + if (o_ptr->k_idx) + describe_flavor(owner_ptr, o_name, o_ptr, 0); + + if (has_melee_weapon(owner_ptr, INVEN_RARM)) { + if (object_allow_two_hands_wielding(o_ptr) && can_two_hands_wielding(owner_ptr)) + msg_format(_("%sを両手で構えた。", "You are wielding %s with both hands."), o_name); + + return; + } + + if ((empty_hands(owner_ptr, FALSE) & EMPTY_HAND_RARM) || object_is_cursed(o_ptr)) + return; + + new_o_ptr = &owner_ptr->inventory_list[INVEN_LARM]; + object_copy(new_o_ptr, o_ptr); + owner_ptr->total_weight += o_ptr->weight; + inven_item_increase(owner_ptr, INVEN_RARM, -((int)o_ptr->number)); + inven_item_optimize(owner_ptr, INVEN_RARM); + msg_format(_("%sを持ち替えた。", "You switched hand of %s."), o_name); +} diff --git a/src/action/weapon-shield.h b/src/action/weapon-shield.h new file mode 100644 index 000000000..00a256051 --- /dev/null +++ b/src/action/weapon-shield.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void verify_equip_slot(player_type *owner_ptr, INVENTORY_IDX item); diff --git a/src/angband.h b/src/angband.h deleted file mode 100644 index 74cd40196..000000000 --- a/src/angband.h +++ /dev/null @@ -1,103 +0,0 @@ -/*! - * @file angband.h - * @brief Angband(変愚蛮怒)メインヘッダファイル - * Main "Angband" header file - * @date 2014/08/08 - * @author - * Copyright (c) 1989 James E. Wilson - * @details * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - * This file has been modified for use with "Angband 2.8.2" - */ - - -#ifndef INCLUDED_ANGBAND_H -#define INCLUDED_ANGBAND_H - -/* - * First, include the low-level includes. Be sure to edit "h-config.h" - * to reflect any hardware, operating system, or compiler nuances. - */ -#include "h-basic.h" - - -/* - * Then, include the header files for the low-level code - */ -#include "z-util.h" -#include "z-virt.h" -#include "z-form.h" -#include "z-rand.h" -#include "z-term.h" - - -/* - * Include the "Angband" configuration header - */ -#include "z-config.h" - - -/* - * Now, include the define's, the type's, and the extern's - */ -#include "defines.h" -#include "gamevalue.h" -#include "types.h" -#include "externs.h" -#include "gameoption.h" - -/***** Some copyright messages follow below *****/ - -/* - * Note that these copyright messages apply to an ancient version - * of Angband, as in, from pre-2.4.frog-knows days, and thus the - * reference to "5.0" is rather misleading... - */ - -/* - * UNIX ANGBAND Version 5.0 - */ - - -/* Original copyright message follows. */ - -/* - * ANGBAND Version 4.8 COPYRIGHT (c) Robert Alan Koeneke - * - * I lovingly dedicate this game to hackers and adventurers - * everywhere... - * - * Designer and Programmer: - * Robert Alan Koeneke - * University of Oklahoma - * - * Assistant Programmer: - * Jimmey Wayne Todd - * University of Oklahoma - * - * Assistant Programmer: - * Gary D. McAdoo - * University of Oklahoma - * - * UNIX Port: - * James E. Wilson - * UC Berkeley - * wilson@ernie.Berkeley.EDU - * ucbvax!ucbernie!wilson - */ - - -/* - * ANGBAND may be copied and modified freely as long as the above - * credits are retained. No one who-so-ever may sell or market - * this software in any form without the expressed written consent - * of the author Robert Alan Koeneke. - */ - - -#endif - - - diff --git a/src/art-definition/art-accessory-types.h b/src/art-definition/art-accessory-types.h new file mode 100644 index 000000000..37b02de3e --- /dev/null +++ b/src/art-definition/art-accessory-types.h @@ -0,0 +1,37 @@ +#pragma once + +typedef enum art_lite_type { + ART_GALADRIEL = 1, + ART_ELENDIL = 2, + ART_JUDGE = 3, + ART_EDISON = 7, + ART_PALANTIR = 15, + ART_STONE_LORE = 17, + ART_FLY_STONE = 147, + ART_ORB_OF_FATE = 245, +} art_lite_type; + +typedef enum art_amulet_type { + ART_CARLAMMAS = 4, + ART_INGWE = 5, + ART_DWARVES = 6, + ART_FARAMIR = 18, + ART_BOROMIR = 143, + ART_MAGATAMA = 149, + ART_INROU = 166, + ART_NIGHT = 215, + ART_SACRED_KNIGHTS = 217, + ART_HELL = 218, + ART_CHARMED = 219, + ART_GOGO = 220, +} art_amulet_type; + +typedef enum art_ring_type { + ART_FRAKIR = 8, + ART_TULKAS = 9, + ART_NARYA = 10, + ART_NENYA = 11, + ART_VILYA = 12, + ART_POWER = 13, + ART_AHO = 14, +} art_ring_type; diff --git a/src/art-definition/art-armor-types.h b/src/art-definition/art-armor-types.h new file mode 100644 index 000000000..f328ce1a0 --- /dev/null +++ b/src/art-definition/art-armor-types.h @@ -0,0 +1,33 @@ +#pragma once + +typedef enum art_dragon_armor_type { + ART_RAZORBACK = 129, + ART_BLADETURNER = 130, + ART_SEIRYU = 201, +} art_dragon_type; + +typedef enum art_hard_armor_type { + ART_SOULKEEPER = 19, + ART_ISILDUR = 20, + ART_ROHIRRIM = 21, + ART_LOHENGRIN = 22, + ART_JULIAN = 23, + ART_ARVEDUI = 24, + ART_CASPANION = 25, + ART_GILES = 168, + ART_MORLOK = 203, + ART_VETERAN = 206, +} art_hard_armor_type; + +typedef enum art_soft_armor_type { + ART_SHIVA_JACKET = 26, + ART_HITHLOMIR = 27, + ART_THALKETTOTH = 28, + ART_HIMRING = 127, + ART_ICANUS = 131, + ART_NAMAKE_ARMOR = 183, + ART_GHB = 192, + ART_DASAI = 200, + ART_KESHO = 204, + ART_MILIM = 246, +} art_soft_armor_type; diff --git a/src/art-definition/art-bow-types.h b/src/art-definition/art-bow-types.h new file mode 100644 index 000000000..522651903 --- /dev/null +++ b/src/art-definition/art-bow-types.h @@ -0,0 +1,17 @@ +#pragma once + +typedef enum art_bow_type { + ART_CRIMSON = 16, + ART_BELTHRONDING = 124, + ART_BARD = 125, + ART_BRAND = 126, + ART_BUCKLAND = 134, + ART_YOICHI = 148, + ART_HARAD = 180, + ART_NAMAKE_BOW = 182, + ART_ROBIN_HOOD = 221, + ART_HELLFIRE = 222, +} art_bow_type; + +/* Arrows */ +#define ART_BARD_ARROW 153 diff --git a/src/art-definition/art-protector-types.h b/src/art-definition/art-protector-types.h new file mode 100644 index 000000000..8c605f280 --- /dev/null +++ b/src/art-definition/art-protector-types.h @@ -0,0 +1,61 @@ +#pragma once + +typedef enum art_shield_type { + ART_THORIN = 30, + ART_CELEGORM = 31, + ART_ANARION = 32, + ART_GIL_GALAD = 138, + ART_YENDOR = 141, + ART_YATA = 151, + ART_EARENDIL = 186, + ART_PERSEUS = 197, +} art_shield_type; + +typedef enum art_helm_type { + ART_INDRA = 33, + ART_CHAOS = 34, + ART_BERUTHIEL = 35, + ART_THRANDUIL = 36, + ART_THENGEL = 37, + ART_HAMMERHAND = 38, + ART_DOR = 39, + ART_HOLHENNETH = 40, + ART_TERROR = 41, + ART_AMBER = 42, + ART_NUMENOR = 132, + ART_STONEMASK = 146, +} art_helm_type; + +typedef enum art_cloak_type { + ART_JACK = 43, + ART_COLLUIN = 44, + ART_HOLCOLLETH = 45, + ART_THINGOL = 46, + ART_THORONGIL = 47, + ART_COLANNON = 48, + ART_LUTHIEN = 49, + ART_TUOR = 50, + ART_MOOK = 205, + ART_HEAVENLY_MAIDEN = 233, +} art_cloak_type; + +typedef enum art_glove_type { + ART_CAMBELEG = 52, + ART_CAMMITHRIM = 53, + ART_PAURHACH = 54, + ART_CORWIN = 55, + ART_PAURAEGEN = 56, + ART_PAURNEN = 57, + ART_THANOS = 58, + ART_FINGOLFIN = 59, + ART_PAURNIMMEN = 185, +} art_glove_type; + +typedef enum art_boots_type { + ART_FEANOR = 60, + ART_FLORA = 61, + ART_THROR = 62, + ART_SHIVA_BOOTS = 63, + ART_GLASS = 165, + ART_GETA = 210, +} art_boots_type; diff --git a/src/art-definition/art-sword-types.h b/src/art-definition/art-sword-types.h new file mode 100644 index 000000000..82515fb50 --- /dev/null +++ b/src/art-definition/art-sword-types.h @@ -0,0 +1,66 @@ +#pragma once + +typedef enum artifact_sword_type { + ART_MAEDHROS = 64, + ART_CAINE = 65, + ART_NARTHANC = 66, + ART_NIMTHANC = 67, + ART_DETHANC = 68, + ART_RILIA = 69, + ART_FIONA = 70, + ART_CALRIS = 71, + ART_GRAYSWANDIR = 72, + ART_GLAMDRING = 73, + ART_NOTHUNG = 74, + ART_ORCRIST = 75, + ART_GURTHANG = 76, + ART_ZARCUTHRA = 77, + ART_TWILIGHT = 78, + ART_GONDRICAM = 79, + ART_CRISDURIAN = 80, + ART_AGLARANG = 81, + ART_RINGIL = 82, + ART_ANDURIL = 83, + ART_WEREWINDLE = 84, + ART_CHAINSWORD = 85, + ART_FORASGIL = 86, + ART_CARETH = 87, + ART_STING = 88, + ART_SOULSWORD = 89, + ART_MERLIN = 90, + ART_DOOMCALLER = 91, + ART_VORPAL_BLADE = 92, + ART_SLAYER = 123, + ART_KUSANAGI = 128, + ART_HURIN = 133, + ART_AZAGHAL = 135, + ART_NOVA = 137, + ART_CHARIOT = 140, + ART_WORPAL_BLADE = 142, + ART_MURAMASA = 144, + ART_ZANTETSU = 150, + ART_SOULCRUSH = 154, + ART_FALIS = 155, + ART_HRUNTING = 156, + ART_ANUBIS = 158, + ART_GURENKI = 160, + ART_TAILBITER = 167, + ART_MUSASI_KATANA = 171, + ART_MUSASI_WAKIZASI = 172, + ART_QUICKTHORN = 174, + ART_TINYTHORN = 175, + ART_EXCALIBUR = 176, + ART_EXCALIPUR = 177, + ART_EXCALIBUR_J = 179, + ART_ARUNRUTH = 184, + ART_HAKABUSA = 189, + ART_STORMBRINGER = 190, + ART_NARSIL = 191, + ART_KANNU = 193, + ART_GRIMTOOTH = 196, + ART_KAMUI = 198, + ART_GOURYU = 207, + ART_EOWYN = 216, + ART_NANACHO = 248, + ART_ROBINTON = 251, +} artifact_sword_type; diff --git a/src/art-definition/art-weapon-types.h b/src/art-definition/art-weapon-types.h new file mode 100644 index 000000000..cd027c190 --- /dev/null +++ b/src/art-definition/art-weapon-types.h @@ -0,0 +1,69 @@ +#pragma once + +/* Digging */ +#define ART_NAIN 211 + +typedef enum art_polearm_type { + ART_THEODEN = 93, + ART_PAIN = 94, + ART_OSONDIR = 95, + ART_TIL = 96, + ART_RUNESPEAR = 97, + ART_DESTINY = 98, + ART_HAGEN = 99, + ART_EORLINGAS = 100, + ART_DURIN = 101, + ART_EONWE = 102, + ART_BALLI = 103, + ART_LOTHARANG = 104, + ART_DWARVES_AXE = 105, + ART_BARUKKHELED = 106, + ART_WRATH = 107, + ART_ULMO = 108, + ART_AVAVIR = 109, + ART_BENKEI = 152, + ART_TAIKOBO = 159, + ART_TONBO = 161, + ART_GAEBOLG = 163, + ART_ARRYU = 164, + ART_AEGLOS = 187, + ART_BLOOD = 199, + ART_NUMAHOKO = 202, +} art_polearm_type; + +/* The sword of the Dawn */ +#define ART_DAWN 110 + +typedef enum art_hafted_type { + ART_GROND = 111, + ART_TOTILA = 112, + ART_THUNDERFIST = 113, + ART_BLOODSPIKE = 114, + ART_FIRESTAR = 115, + ART_TARATOL = 116, + ART_AULE = 117, + ART_NAR = 118, + ART_ERIRIL = 119, + ART_GANDALF = 120, + ART_DEATHWREAKER = 121, + ART_TURMIL = 122, + ART_MJOLLNIR = 136, + ART_WINBLOWS = 139, + ART_XIAOLONG = 145, + ART_NYOIBOU = 157, + ART_JONES = 162, + ART_HYOUSIGI = 169, + ART_MATOI = 170, + ART_IRON_BALL = 173, + ART_SAMSON = 178, + ART_NAMAKE_HAMMER = 181, + ART_BOLISHOI = 188, + ART_SHUTEN_DOJI = 194, + ART_G_HAMMER = 195, + ART_AEGISFANG = 208, + ART_HERMIT = 209, + ART_GOTHMOG = 212, + ART_JIZO = 213, + ART_FUNDIN = 214, + ART_AESCULAPIUS = 225, +} art_hafted_type; diff --git a/src/art-definition/random-art-effects.h b/src/art-definition/random-art-effects.h new file mode 100644 index 000000000..ee6bc99be --- /dev/null +++ b/src/art-definition/random-art-effects.h @@ -0,0 +1,134 @@ +#pragma once + +typedef enum random_art_activation_type { + ACT_SUNLIGHT = 1, + ACT_BO_MISS_1 = 2, + ACT_BA_POIS_1 = 3, + ACT_BO_ELEC_1 = 4, + ACT_BO_ACID_1 = 5, + ACT_BO_COLD_1 = 6, + ACT_BO_FIRE_1 = 7, + ACT_BA_COLD_1 = 8, + ACT_BA_FIRE_1 = 9, + ACT_HYPODYNAMIA_1 = 10, + ACT_BA_COLD_2 = 11, + ACT_BA_ELEC_2 = 12, + ACT_HYPODYNAMIA_2 = 13, + ACT_DRAIN_1 = 14, + ACT_BO_MISS_2 = 15, + ACT_BA_FIRE_3 = 16, + ACT_BA_COLD_3 = 17, + ACT_BA_ELEC_3 = 18, + ACT_WHIRLWIND = 19, + ACT_DRAIN_2 = 20, + ACT_CALL_CHAOS = 21, + ACT_ROCKET = 22, + ACT_DISP_EVIL = 23, + ACT_BA_MISS_3 = 24, + ACT_DISP_GOOD = 25, + ACT_BO_MANA = 26, + ACT_BA_FIRE_2 = 27, + ACT_BA_WATER = 28, + ACT_BA_STAR = 29, + ACT_BA_DARK = 30, + ACT_BA_MANA = 31, + ACT_PESTICIDE = 32, + ACT_BLINDING_LIGHT = 33, + ACT_BIZARRE = 34, + ACT_CAST_BA_STAR = 35, + ACT_BLADETURNER = 36, + ACT_BA_ACID_1 = 37, + ACT_BR_FIRE = 38, + ACT_BR_COLD = 39, + ACT_BR_DRAGON = 40, + ACT_BA_FIRE_4 = 41, + ACT_BA_NUKE_1 = 42, + /* 42 - 50 unused */ + ACT_CONFUSE = 51, + ACT_SLEEP = 52, + ACT_QUAKE = 53, + ACT_TERROR = 54, + ACT_TELE_AWAY = 55, + ACT_BANISH_EVIL = 56, + ACT_GENOCIDE = 57, + ACT_MASS_GENO = 58, + ACT_SCARE_AREA = 59, + ACT_AGGRAVATE = 60, + /* 59 - 64 unused */ + ACT_CHARM_ANIMAL = 65, + ACT_CHARM_UNDEAD = 66, + ACT_CHARM_OTHER = 67, + ACT_CHARM_ANIMALS = 68, + ACT_CHARM_OTHERS = 69, + ACT_SUMMON_ANIMAL = 70, + ACT_SUMMON_PHANTOM = 71, + ACT_SUMMON_ELEMENTAL = 72, + ACT_SUMMON_DEMON = 73, + ACT_SUMMON_UNDEAD = 74, + ACT_SUMMON_HOUND = 75, + ACT_SUMMON_DAWN = 76, + ACT_SUMMON_OCTOPUS = 77, + ACT_CHOIR_SINGS = 80, + ACT_CURE_LW = 81, + ACT_CURE_MW = 82, + ACT_CURE_POISON = 83, + ACT_REST_EXP = 84, + ACT_REST_ALL = 85, + ACT_CURE_700 = 86, + ACT_CURE_1000 = 87, + ACT_CURING = 88, + ACT_CURE_MANA_FULL = 89, + ACT_ESP = 91, + ACT_BERSERK = 92, + ACT_PROT_EVIL = 93, + ACT_RESIST_ALL = 94, + ACT_SPEED = 95, + ACT_XTRA_SPEED = 96, + ACT_WRAITH = 97, + ACT_INVULN = 98, + ACT_HERO = 99, + ACT_HERO_SPEED = 100, + ACT_RESIST_ACID = 101, + ACT_RESIST_FIRE = 102, + ACT_RESIST_COLD = 103, + ACT_RESIST_ELEC = 104, + ACT_RESIST_POIS = 105, + ACT_LIGHT = 111, + ACT_MAP_LIGHT = 112, + ACT_DETECT_ALL = 113, + ACT_DETECT_XTRA = 114, + ACT_ID_FULL = 115, + ACT_ID_PLAIN = 116, + ACT_RUNE_EXPLO = 117, + ACT_RUNE_PROT = 118, + ACT_SATIATE = 119, + ACT_DEST_DOOR = 120, + ACT_STONE_MUD = 121, + ACT_RECHARGE = 122, + ACT_ALCHEMY = 123, + ACT_DIM_DOOR = 124, + ACT_TELEPORT = 125, + ACT_RECALL = 126, + ACT_JUDGE = 127, + ACT_TELEKINESIS = 128, + ACT_DETECT_UNIQUE = 129, + ACT_ESCAPE = 130, + ACT_DISP_CURSE_XTRA = 131, + ACT_BRAND_FIRE_BOLTS = 132, + ACT_RECHARGE_XTRA = 133, + ACT_LORE = 134, + ACT_SHIKOFUMI = 135, + ACT_PHASE_DOOR = 136, + ACT_DETECT_ALL_MONS = 137, + ACT_ULTIMATE_RESIST = 138, + ACT_FALLING_STAR = 246, + ACT_STRAIN_HASTE = 247, + ACT_TELEPORT_LEVEL = 248, + ACT_GRAND_CROSS = 249, + ACT_CAST_OFF = 250, + ACT_FISHING = 251, + ACT_INROU = 252, + ACT_MURAMASA = 253, + ACT_BLOODY_MOON = 254, + ACT_CRIMSON = 255, +} random_art_activation_type; diff --git a/src/artifact.c b/src/artifact.c deleted file mode 100644 index 3b4297bc4..000000000 --- a/src/artifact.c +++ /dev/null @@ -1,2329 +0,0 @@ -/*! - * @file artifact.c - * @brief アーティファクトの生成と管理 / Artifact code - * @date 2013/12/11 - * @author - * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke\n - * This software may be copied and distributed for educational, research, and\n - * not for profit purposes provided that this copyright and statement are\n - * included in all such copies.\n - * 2013 Deskull rearranged comment for Doxygen. - */ - -#include "angband.h" -#include "artifact.h" - -#include "avatar.h" -#include "cmd-activate.h" -#include "object-boost.h" -#include "object-curse.h" -#include "object-hook.h" -#include "spells-object.h" - -static bool has_extreme_damage_rate(object_type *o_ptr); -static bool weakening_artifact(object_type *o_ptr); - -#ifdef JP -/*! - * @brief ランダムアーティファクトのバイアス名称テーブル - */ -const concptr artifact_bias_name[MAX_BIAS] = -{ - "なし", - "電撃", - "毒", - "火炎", - "冷気", - "酸", - "腕力", - "知力", - "賢さ", - "器用さ", - "耐久", - "魅力", - "混沌", - "プリースト", - "死霊", - "法", - "盗賊", - "メイジ", - "戦士", - "レンジャー", -}; -#else -const concptr artifact_bias_name[MAX_BIAS] = -{ - "None", - "Elec", - "Poison", - "Fire", - "Cold", - "Acid", - "STR", - "INT", - "WIS", - "DEX", - "CON", - "CHA", - "Chaos", - "Pristly", - "Necromantic", - "Law", - "Rogue", - "Mage", - "Warrior", - "Ranger", -}; -#endif - - -/*! - * @brief ランダムアーティファクト生成中、対象のオブジェクトを呪いのアーティファクトにする経過処理。/ generation process of cursed artifact. - * @details pval、AC、命中、ダメージが正の場合、符号反転の上1d4だけ悪化させ、重い呪い、呪いフラグを必ず付加。 - * 祝福を無効。確率に応じて、永遠の呪い、太古の怨念、経験値吸収、弱い呪いの継続的付加、強い呪いの継続的付加、HP吸収の呪い、 - * MP吸収の呪い、乱テレポート、反テレポート、反魔法をつける。 - * @attention プレイヤーの職業依存処理あり。 - * @param o_ptr 対象のオブジェクト構造体ポインタ - * @return なし - */ -static void curse_artifact(object_type * o_ptr) -{ - if (o_ptr->pval > 0) o_ptr->pval = 0 - (o_ptr->pval + randint1(4)); - if (o_ptr->to_a > 0) o_ptr->to_a = 0 - (o_ptr->to_a + randint1(4)); - if (o_ptr->to_h > 0) o_ptr->to_h = 0 - (o_ptr->to_h + randint1(4)); - if (o_ptr->to_d > 0) o_ptr->to_d = 0 - (o_ptr->to_d + randint1(4)); - - o_ptr->curse_flags |= (TRC_HEAVY_CURSE | TRC_CURSED); - remove_flag(o_ptr->art_flags, TR_BLESSED); - - if (one_in_(4)) o_ptr->curse_flags |= TRC_PERMA_CURSE; - if (one_in_(3)) add_flag(o_ptr->art_flags, TR_TY_CURSE); - if (one_in_(2)) add_flag(o_ptr->art_flags, TR_AGGRAVATE); - if (one_in_(3)) add_flag(o_ptr->art_flags, TR_DRAIN_EXP); - if (one_in_(6)) add_flag(o_ptr->art_flags, TR_ADD_L_CURSE); - if (one_in_(9)) add_flag(o_ptr->art_flags, TR_ADD_H_CURSE); - if (one_in_(9)) add_flag(o_ptr->art_flags, TR_DRAIN_HP); - if (one_in_(9)) add_flag(o_ptr->art_flags, TR_DRAIN_MANA); - if (one_in_(2)) add_flag(o_ptr->art_flags, TR_TELEPORT); - else if (one_in_(3)) add_flag(o_ptr->art_flags, TR_NO_TELE); - - if ((p_ptr->pclass != CLASS_WARRIOR) && (p_ptr->pclass != CLASS_ARCHER) && (p_ptr->pclass != CLASS_CAVALRY) && (p_ptr->pclass != CLASS_BERSERKER) && (p_ptr->pclass != CLASS_SMITH) && one_in_(3)) - add_flag(o_ptr->art_flags, TR_NO_MAGIC); -} - -/*! - * @brief ランダムアーティファクト生成中、対象のオブジェクトにpval能力を付加する。/ Add one pval on generation of randam artifact. - * @details 優先的に付加されるpvalがランダムアーティファクトバイアスに依存して存在する。 - * 原則的候補は腕力、知力、賢さ、器用さ、耐久、魅力、探索、隠密、赤外線視力、加速。武器のみ採掘、追加攻撃も候補に入る。 - * @attention オブジェクトのtval、svalに依存したハードコーディング処理がある。 - * @param o_ptr 対象のオブジェクト構造体ポインタ - * @return なし - */ -static void random_plus(object_type * o_ptr) -{ - int this_type = (object_is_weapon_ammo(o_ptr) ? 23 : 19); - - switch (o_ptr->artifact_bias) - { - case BIAS_WARRIOR: - if (!(have_flag(o_ptr->art_flags, TR_STR))) - { - add_flag(o_ptr->art_flags, TR_STR); - if (one_in_(2)) return; - } - - if (!(have_flag(o_ptr->art_flags, TR_CON))) - { - add_flag(o_ptr->art_flags, TR_CON); - if (one_in_(2)) return; - } - - if (!(have_flag(o_ptr->art_flags, TR_DEX))) - { - add_flag(o_ptr->art_flags, TR_DEX); - if (one_in_(2)) return; - } - break; - - case BIAS_MAGE: - if (!(have_flag(o_ptr->art_flags, TR_INT))) - { - add_flag(o_ptr->art_flags, TR_INT); - if (one_in_(2)) return; - } - if ((o_ptr->tval == TV_GLOVES) && !(have_flag(o_ptr->art_flags, TR_MAGIC_MASTERY))) - { - add_flag(o_ptr->art_flags, TR_MAGIC_MASTERY); - if (one_in_(2)) return; - } - break; - - case BIAS_PRIESTLY: - if (!(have_flag(o_ptr->art_flags, TR_WIS))) - { - add_flag(o_ptr->art_flags, TR_WIS); - if (one_in_(2)) return; - } - break; - - case BIAS_RANGER: - if (!(have_flag(o_ptr->art_flags, TR_DEX))) - { - add_flag(o_ptr->art_flags, TR_DEX); - if (one_in_(2)) return; - } - - if (!(have_flag(o_ptr->art_flags, TR_CON))) - { - add_flag(o_ptr->art_flags, TR_CON); - if (one_in_(2)) return; - } - - if (!(have_flag(o_ptr->art_flags, TR_STR))) - { - add_flag(o_ptr->art_flags, TR_STR); - if (one_in_(2)) return; - } - break; - - case BIAS_ROGUE: - if (!(have_flag(o_ptr->art_flags, TR_STEALTH))) - { - add_flag(o_ptr->art_flags, TR_STEALTH); - if (one_in_(2)) return; - } - if (!(have_flag(o_ptr->art_flags, TR_SEARCH))) - { - add_flag(o_ptr->art_flags, TR_SEARCH); - if (one_in_(2)) return; - } - break; - - case BIAS_STR: - if (!(have_flag(o_ptr->art_flags, TR_STR))) - { - add_flag(o_ptr->art_flags, TR_STR); - if (one_in_(2)) return; - } - break; - - case BIAS_WIS: - if (!(have_flag(o_ptr->art_flags, TR_WIS))) - { - add_flag(o_ptr->art_flags, TR_WIS); - if (one_in_(2)) return; - } - break; - - case BIAS_INT: - if (!(have_flag(o_ptr->art_flags, TR_INT))) - { - add_flag(o_ptr->art_flags, TR_INT); - if (one_in_(2)) return; - } - break; - - case BIAS_DEX: - if (!(have_flag(o_ptr->art_flags, TR_DEX))) - { - add_flag(o_ptr->art_flags, TR_DEX); - if (one_in_(2)) return; - } - break; - - case BIAS_CON: - if (!(have_flag(o_ptr->art_flags, TR_CON))) - { - add_flag(o_ptr->art_flags, TR_CON); - if (one_in_(2)) return; - } - break; - - case BIAS_CHR: - if (!(have_flag(o_ptr->art_flags, TR_CHR))) - { - add_flag(o_ptr->art_flags, TR_CHR); - if (one_in_(2)) return; - } - break; - } - - if ((o_ptr->artifact_bias == BIAS_MAGE || o_ptr->artifact_bias == BIAS_PRIESTLY) && (o_ptr->tval == TV_SOFT_ARMOR) && (o_ptr->sval == SV_ROBE)) - { - if (!(have_flag(o_ptr->art_flags, TR_DEC_MANA)) && one_in_(3)) - { - add_flag(o_ptr->art_flags, TR_DEC_MANA); - if (one_in_(2)) return; - } - } - - switch (randint1(this_type)) - { - case 1: case 2: - add_flag(o_ptr->art_flags, TR_STR); - if (!o_ptr->artifact_bias && !one_in_(13)) - o_ptr->artifact_bias = BIAS_STR; - else if (!o_ptr->artifact_bias && one_in_(7)) - o_ptr->artifact_bias = BIAS_WARRIOR; - break; - case 3: case 4: - add_flag(o_ptr->art_flags, TR_INT); - if (!o_ptr->artifact_bias && !one_in_(13)) - o_ptr->artifact_bias = BIAS_INT; - else if (!o_ptr->artifact_bias && one_in_(7)) - o_ptr->artifact_bias = BIAS_MAGE; - break; - case 5: case 6: - add_flag(o_ptr->art_flags, TR_WIS); - if (!o_ptr->artifact_bias && !one_in_(13)) - o_ptr->artifact_bias = BIAS_WIS; - else if (!o_ptr->artifact_bias && one_in_(7)) - o_ptr->artifact_bias = BIAS_PRIESTLY; - break; - case 7: case 8: - add_flag(o_ptr->art_flags, TR_DEX); - if (!o_ptr->artifact_bias && !one_in_(13)) - o_ptr->artifact_bias = BIAS_DEX; - else if (!o_ptr->artifact_bias && one_in_(7)) - o_ptr->artifact_bias = BIAS_ROGUE; - break; - case 9: case 10: - add_flag(o_ptr->art_flags, TR_CON); - if (!o_ptr->artifact_bias && !one_in_(13)) - o_ptr->artifact_bias = BIAS_CON; - else if (!o_ptr->artifact_bias && one_in_(9)) - o_ptr->artifact_bias = BIAS_RANGER; - break; - case 11: case 12: - add_flag(o_ptr->art_flags, TR_CHR); - if (!o_ptr->artifact_bias && !one_in_(13)) - o_ptr->artifact_bias = BIAS_CHR; - break; - case 13: case 14: - add_flag(o_ptr->art_flags, TR_STEALTH); - if (!o_ptr->artifact_bias && one_in_(3)) - o_ptr->artifact_bias = BIAS_ROGUE; - break; - case 15: case 16: - add_flag(o_ptr->art_flags, TR_SEARCH); - if (!o_ptr->artifact_bias && one_in_(9)) - o_ptr->artifact_bias = BIAS_RANGER; - break; - case 17: case 18: - add_flag(o_ptr->art_flags, TR_INFRA); - break; - case 19: - add_flag(o_ptr->art_flags, TR_SPEED); - if (!o_ptr->artifact_bias && one_in_(11)) - o_ptr->artifact_bias = BIAS_ROGUE; - break; - case 20: case 21: - add_flag(o_ptr->art_flags, TR_TUNNEL); - break; - case 22: case 23: - if (o_ptr->tval == TV_BOW) random_plus(o_ptr); - else - { - add_flag(o_ptr->art_flags, TR_BLOWS); - if (!o_ptr->artifact_bias && one_in_(11)) - o_ptr->artifact_bias = BIAS_WARRIOR; - } - break; - } -} - -/*! - * @brief ランダムアーティファクト生成中、対象のオブジェクトに耐性を付加する。/ Add one resistance on generation of randam artifact. - * @details 優先的に付加される耐性がランダムアーティファクトバイアスに依存して存在する。 - * 原則的候補は火炎、冷気、電撃、酸(以上免疫の可能性もあり)、 - * 毒、閃光、暗黒、破片、轟音、盲目、混乱、地獄、カオス、劣化、恐怖、火オーラ、冷気オーラ、電撃オーラ、反射。 - * 戦士系バイアスのみ反魔もつく。 - * @attention オブジェクトのtval、svalに依存したハードコーディング処理がある。 - * @param o_ptr 対象のオブジェクト構造体ポインタ - * @return なし - */ -static void random_resistance(object_type * o_ptr) -{ - switch (o_ptr->artifact_bias) - { - case BIAS_ACID: - if (!(have_flag(o_ptr->art_flags, TR_RES_ACID))) - { - add_flag(o_ptr->art_flags, TR_RES_ACID); - if (one_in_(2)) return; - } - if (one_in_(BIAS_LUCK) && !(have_flag(o_ptr->art_flags, TR_IM_ACID))) - { - add_flag(o_ptr->art_flags, TR_IM_ACID); - if (!one_in_(IM_LUCK)) - { - remove_flag(o_ptr->art_flags, TR_IM_ELEC); - remove_flag(o_ptr->art_flags, TR_IM_COLD); - remove_flag(o_ptr->art_flags, TR_IM_FIRE); - } - if (one_in_(2)) return; - } - break; - - case BIAS_ELEC: - if (!(have_flag(o_ptr->art_flags, TR_RES_ELEC))) - { - add_flag(o_ptr->art_flags, TR_RES_ELEC); - if (one_in_(2)) return; - } - if ((o_ptr->tval >= TV_CLOAK) && (o_ptr->tval <= TV_HARD_ARMOR) && - !(have_flag(o_ptr->art_flags, TR_SH_ELEC))) - { - add_flag(o_ptr->art_flags, TR_SH_ELEC); - if (one_in_(2)) return; - } - if (one_in_(BIAS_LUCK) && !(have_flag(o_ptr->art_flags, TR_IM_ELEC))) - { - add_flag(o_ptr->art_flags, TR_IM_ELEC); - if (!one_in_(IM_LUCK)) - { - remove_flag(o_ptr->art_flags, TR_IM_ACID); - remove_flag(o_ptr->art_flags, TR_IM_COLD); - remove_flag(o_ptr->art_flags, TR_IM_FIRE); - } - - if (one_in_(2)) return; - } - break; - - case BIAS_FIRE: - if (!(have_flag(o_ptr->art_flags, TR_RES_FIRE))) - { - add_flag(o_ptr->art_flags, TR_RES_FIRE); - if (one_in_(2)) return; - } - if ((o_ptr->tval >= TV_CLOAK) && - (o_ptr->tval <= TV_HARD_ARMOR) && - !(have_flag(o_ptr->art_flags, TR_SH_FIRE))) - { - add_flag(o_ptr->art_flags, TR_SH_FIRE); - if (one_in_(2)) return; - } - if (one_in_(BIAS_LUCK) && - !(have_flag(o_ptr->art_flags, TR_IM_FIRE))) - { - add_flag(o_ptr->art_flags, TR_IM_FIRE); - if (!one_in_(IM_LUCK)) - { - remove_flag(o_ptr->art_flags, TR_IM_ELEC); - remove_flag(o_ptr->art_flags, TR_IM_COLD); - remove_flag(o_ptr->art_flags, TR_IM_ACID); - } - if (one_in_(2)) return; - } - break; - - case BIAS_COLD: - if (!(have_flag(o_ptr->art_flags, TR_RES_COLD))) - { - add_flag(o_ptr->art_flags, TR_RES_COLD); - if (one_in_(2)) return; - } - if ((o_ptr->tval >= TV_CLOAK) && - (o_ptr->tval <= TV_HARD_ARMOR) && - !(have_flag(o_ptr->art_flags, TR_SH_COLD))) - { - add_flag(o_ptr->art_flags, TR_SH_COLD); - if (one_in_(2)) return; - } - if (one_in_(BIAS_LUCK) && !(have_flag(o_ptr->art_flags, TR_IM_COLD))) - { - add_flag(o_ptr->art_flags, TR_IM_COLD); - if (!one_in_(IM_LUCK)) - { - remove_flag(o_ptr->art_flags, TR_IM_ELEC); - remove_flag(o_ptr->art_flags, TR_IM_ACID); - remove_flag(o_ptr->art_flags, TR_IM_FIRE); - } - if (one_in_(2)) return; - } - break; - - case BIAS_POIS: - if (!(have_flag(o_ptr->art_flags, TR_RES_POIS))) - { - add_flag(o_ptr->art_flags, TR_RES_POIS); - if (one_in_(2)) return; - } - break; - - case BIAS_WARRIOR: - if (!one_in_(3) && (!(have_flag(o_ptr->art_flags, TR_RES_FEAR)))) - { - add_flag(o_ptr->art_flags, TR_RES_FEAR); - if (one_in_(2)) return; - } - if (one_in_(3) && (!(have_flag(o_ptr->art_flags, TR_NO_MAGIC)))) - { - add_flag(o_ptr->art_flags, TR_NO_MAGIC); - if (one_in_(2)) return; - } - break; - - case BIAS_NECROMANTIC: - if (!(have_flag(o_ptr->art_flags, TR_RES_NETHER))) - { - add_flag(o_ptr->art_flags, TR_RES_NETHER); - if (one_in_(2)) return; - } - if (!(have_flag(o_ptr->art_flags, TR_RES_POIS))) - { - add_flag(o_ptr->art_flags, TR_RES_POIS); - if (one_in_(2)) return; - } - if (!(have_flag(o_ptr->art_flags, TR_RES_DARK))) - { - add_flag(o_ptr->art_flags, TR_RES_DARK); - if (one_in_(2)) return; - } - break; - - case BIAS_CHAOS: - if (!(have_flag(o_ptr->art_flags, TR_RES_CHAOS))) - { - add_flag(o_ptr->art_flags, TR_RES_CHAOS); - if (one_in_(2)) return; - } - if (!(have_flag(o_ptr->art_flags, TR_RES_CONF))) - { - add_flag(o_ptr->art_flags, TR_RES_CONF); - if (one_in_(2)) return; - } - if (!(have_flag(o_ptr->art_flags, TR_RES_DISEN))) - { - add_flag(o_ptr->art_flags, TR_RES_DISEN); - if (one_in_(2)) return; - } - break; - } - - switch (randint1(42)) - { - case 1: - if (!one_in_(WEIRD_LUCK)) - random_resistance(o_ptr); - else - { - add_flag(o_ptr->art_flags, TR_IM_ACID); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_ACID; - } - break; - case 2: - if (!one_in_(WEIRD_LUCK)) - random_resistance(o_ptr); - else - { - add_flag(o_ptr->art_flags, TR_IM_ELEC); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_ELEC; - } - break; - case 3: - if (!one_in_(WEIRD_LUCK)) - random_resistance(o_ptr); - else - { - add_flag(o_ptr->art_flags, TR_IM_COLD); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_COLD; - } - break; - case 4: - if (!one_in_(WEIRD_LUCK)) - random_resistance(o_ptr); - else - { - add_flag(o_ptr->art_flags, TR_IM_FIRE); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_FIRE; - } - break; - case 5: - case 6: - case 13: - add_flag(o_ptr->art_flags, TR_RES_ACID); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_ACID; - break; - case 7: - case 8: - case 14: - add_flag(o_ptr->art_flags, TR_RES_ELEC); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_ELEC; - break; - case 9: - case 10: - case 15: - add_flag(o_ptr->art_flags, TR_RES_FIRE); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_FIRE; - break; - case 11: - case 12: - case 16: - add_flag(o_ptr->art_flags, TR_RES_COLD); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_COLD; - break; - case 17: - case 18: - add_flag(o_ptr->art_flags, TR_RES_POIS); - if (!o_ptr->artifact_bias && !one_in_(4)) - o_ptr->artifact_bias = BIAS_POIS; - else if (!o_ptr->artifact_bias && one_in_(2)) - o_ptr->artifact_bias = BIAS_NECROMANTIC; - else if (!o_ptr->artifact_bias && one_in_(2)) - o_ptr->artifact_bias = BIAS_ROGUE; - break; - case 19: - case 20: - add_flag(o_ptr->art_flags, TR_RES_FEAR); - if (!o_ptr->artifact_bias && one_in_(3)) - o_ptr->artifact_bias = BIAS_WARRIOR; - break; - case 21: - add_flag(o_ptr->art_flags, TR_RES_LITE); - break; - case 22: - add_flag(o_ptr->art_flags, TR_RES_DARK); - break; - case 23: - case 24: - add_flag(o_ptr->art_flags, TR_RES_BLIND); - break; - case 25: - case 26: - add_flag(o_ptr->art_flags, TR_RES_CONF); - if (!o_ptr->artifact_bias && one_in_(6)) - o_ptr->artifact_bias = BIAS_CHAOS; - break; - case 27: - case 28: - add_flag(o_ptr->art_flags, TR_RES_SOUND); - break; - case 29: - case 30: - add_flag(o_ptr->art_flags, TR_RES_SHARDS); - break; - case 31: - case 32: - add_flag(o_ptr->art_flags, TR_RES_NETHER); - if (!o_ptr->artifact_bias && one_in_(3)) - o_ptr->artifact_bias = BIAS_NECROMANTIC; - break; - case 33: - case 34: - add_flag(o_ptr->art_flags, TR_RES_NEXUS); - break; - case 35: - case 36: - add_flag(o_ptr->art_flags, TR_RES_CHAOS); - if (!o_ptr->artifact_bias && one_in_(2)) - o_ptr->artifact_bias = BIAS_CHAOS; - break; - case 37: - case 38: - add_flag(o_ptr->art_flags, TR_RES_DISEN); - break; - case 39: - if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR) - add_flag(o_ptr->art_flags, TR_SH_ELEC); - else - random_resistance(o_ptr); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_ELEC; - break; - case 40: - if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR) - add_flag(o_ptr->art_flags, TR_SH_FIRE); - else - random_resistance(o_ptr); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_FIRE; - break; - case 41: - if (o_ptr->tval == TV_SHIELD || o_ptr->tval == TV_CLOAK || - o_ptr->tval == TV_HELM || o_ptr->tval == TV_HARD_ARMOR) - add_flag(o_ptr->art_flags, TR_REFLECT); - else - random_resistance(o_ptr); - break; - case 42: - if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR) - add_flag(o_ptr->art_flags, TR_SH_COLD); - else - random_resistance(o_ptr); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_COLD; - break; - } -} - - -/*! - * @brief ランダムアーティファクト生成中、対象のオブジェクトにその他特性を付加する。/ Add one misc flag on generation of randam artifact. - * @details 優先的に付加される耐性がランダムアーティファクトバイアスに依存して存在する。 - * 原則的候補は各種能力維持、永久光源+1、麻痺知らず、経験値維持、浮遊、透明視、急回復、遅消化、 - * 乱テレポート、反魔法、反テレポート、警告、テレパシー、各種ESP、一部装備に殺戮修正。 - * @attention オブジェクトのtval、svalに依存したハードコーディング処理がある。 - * @param o_ptr 対象のオブジェクト構造体ポインタ - * @return なし - */ -static void random_misc(object_type * o_ptr) -{ - switch (o_ptr->artifact_bias) - { - case BIAS_RANGER: - if (!(have_flag(o_ptr->art_flags, TR_SUST_CON))) - { - add_flag(o_ptr->art_flags, TR_SUST_CON); - if (one_in_(2)) return; - } - break; - - case BIAS_STR: - if (!(have_flag(o_ptr->art_flags, TR_SUST_STR))) - { - add_flag(o_ptr->art_flags, TR_SUST_STR); - if (one_in_(2)) return; - } - break; - - case BIAS_WIS: - if (!(have_flag(o_ptr->art_flags, TR_SUST_WIS))) - { - add_flag(o_ptr->art_flags, TR_SUST_WIS); - if (one_in_(2)) return; - } - break; - - case BIAS_INT: - if (!(have_flag(o_ptr->art_flags, TR_SUST_INT))) - { - add_flag(o_ptr->art_flags, TR_SUST_INT); - if (one_in_(2)) return; - } - break; - - case BIAS_DEX: - if (!(have_flag(o_ptr->art_flags, TR_SUST_DEX))) - { - add_flag(o_ptr->art_flags, TR_SUST_DEX); - if (one_in_(2)) return; - } - break; - - case BIAS_CON: - if (!(have_flag(o_ptr->art_flags, TR_SUST_CON))) - { - add_flag(o_ptr->art_flags, TR_SUST_CON); - if (one_in_(2)) return; - } - break; - - case BIAS_CHR: - if (!(have_flag(o_ptr->art_flags, TR_SUST_CHR))) - { - add_flag(o_ptr->art_flags, TR_SUST_CHR); - if (one_in_(2)) return; - } - break; - - case BIAS_CHAOS: - if (!(have_flag(o_ptr->art_flags, TR_TELEPORT))) - { - add_flag(o_ptr->art_flags, TR_TELEPORT); - if (one_in_(2)) return; - } - break; - - case BIAS_FIRE: - if (!(have_flag(o_ptr->art_flags, TR_LITE_1))) - { - add_flag(o_ptr->art_flags, TR_LITE_1); /* Freebie */ - } - break; - } - - switch (randint1(33)) - { - case 1: - add_flag(o_ptr->art_flags, TR_SUST_STR); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_STR; - break; - case 2: - add_flag(o_ptr->art_flags, TR_SUST_INT); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_INT; - break; - case 3: - add_flag(o_ptr->art_flags, TR_SUST_WIS); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_WIS; - break; - case 4: - add_flag(o_ptr->art_flags, TR_SUST_DEX); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_DEX; - break; - case 5: - add_flag(o_ptr->art_flags, TR_SUST_CON); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_CON; - break; - case 6: - add_flag(o_ptr->art_flags, TR_SUST_CHR); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_CHR; - break; - case 7: - case 8: - case 14: - add_flag(o_ptr->art_flags, TR_FREE_ACT); - break; - case 9: - add_flag(o_ptr->art_flags, TR_HOLD_EXP); - if (!o_ptr->artifact_bias && one_in_(5)) - o_ptr->artifact_bias = BIAS_PRIESTLY; - else if (!o_ptr->artifact_bias && one_in_(6)) - o_ptr->artifact_bias = BIAS_NECROMANTIC; - break; - case 10: - case 11: - add_flag(o_ptr->art_flags, TR_LITE_1); - break; - case 12: - case 13: - add_flag(o_ptr->art_flags, TR_LEVITATION); - break; - case 15: - case 16: - case 17: - add_flag(o_ptr->art_flags, TR_SEE_INVIS); - break; - case 19: - case 20: - add_flag(o_ptr->art_flags, TR_SLOW_DIGEST); - break; - case 21: - case 22: - add_flag(o_ptr->art_flags, TR_REGEN); - break; - case 23: - add_flag(o_ptr->art_flags, TR_TELEPORT); - break; - case 24: - case 25: - case 26: - if (object_is_armour(o_ptr)) - random_misc(o_ptr); - else - { - o_ptr->to_a = 4 + randint1(11); - } - break; - case 27: - case 28: - case 29: - { - HIT_PROB bonus_h; - HIT_POINT bonus_d; - add_flag(o_ptr->art_flags, TR_SHOW_MODS); - bonus_h = 4 + (HIT_PROB)(randint1(11)); - bonus_d = 4 + (HIT_POINT)(randint1(11)); - if ((o_ptr->tval != TV_SWORD) && (o_ptr->tval != TV_POLEARM) && (o_ptr->tval != TV_HAFTED) && (o_ptr->tval != TV_DIGGING) && (o_ptr->tval != TV_GLOVES) && (o_ptr->tval != TV_RING)) - { - bonus_h /= 2; - bonus_d /= 2; - } - o_ptr->to_h += bonus_h; - o_ptr->to_d += bonus_d; - break; - } - case 30: - add_flag(o_ptr->art_flags, TR_NO_MAGIC); - break; - case 31: - add_flag(o_ptr->art_flags, TR_NO_TELE); - break; - case 32: - add_flag(o_ptr->art_flags, TR_WARNING); - break; - - case 18: - switch (randint1(3)) - { - case 1: - add_flag(o_ptr->art_flags, TR_ESP_EVIL); - if (!o_ptr->artifact_bias && one_in_(3)) - o_ptr->artifact_bias = BIAS_LAW; - break; - case 2: - add_flag(o_ptr->art_flags, TR_ESP_NONLIVING); - if (!o_ptr->artifact_bias && one_in_(3)) - o_ptr->artifact_bias = BIAS_MAGE; - break; - case 3: - add_flag(o_ptr->art_flags, TR_TELEPATHY); - if (!o_ptr->artifact_bias && one_in_(9)) - o_ptr->artifact_bias = BIAS_MAGE; - break; - } - break; - - case 33: - { - int idx[3]; - int n = randint1(3); - - idx[0] = randint1(10); - - idx[1] = randint1(9); - if (idx[1] >= idx[0]) idx[1]++; - - idx[2] = randint1(8); - if (idx[2] >= idx[0]) idx[2]++; - if (idx[2] >= idx[1]) idx[2]++; - - while (n--) switch (idx[n]) - { - case 1: - add_flag(o_ptr->art_flags, TR_ESP_ANIMAL); - if (!o_ptr->artifact_bias && one_in_(4)) - o_ptr->artifact_bias = BIAS_RANGER; - break; - case 2: - add_flag(o_ptr->art_flags, TR_ESP_UNDEAD); - if (!o_ptr->artifact_bias && one_in_(3)) - o_ptr->artifact_bias = BIAS_PRIESTLY; - else if (!o_ptr->artifact_bias && one_in_(6)) - o_ptr->artifact_bias = BIAS_NECROMANTIC; - break; - case 3: - add_flag(o_ptr->art_flags, TR_ESP_DEMON); - break; - case 4: - add_flag(o_ptr->art_flags, TR_ESP_ORC); - break; - case 5: - add_flag(o_ptr->art_flags, TR_ESP_TROLL); - break; - case 6: - add_flag(o_ptr->art_flags, TR_ESP_GIANT); - break; - case 7: - add_flag(o_ptr->art_flags, TR_ESP_DRAGON); - break; - case 8: - add_flag(o_ptr->art_flags, TR_ESP_HUMAN); - if (!o_ptr->artifact_bias && one_in_(6)) - o_ptr->artifact_bias = BIAS_ROGUE; - break; - case 9: - add_flag(o_ptr->art_flags, TR_ESP_GOOD); - if (!o_ptr->artifact_bias && one_in_(3)) - o_ptr->artifact_bias = BIAS_LAW; - break; - case 10: - add_flag(o_ptr->art_flags, TR_ESP_UNIQUE); - if (!o_ptr->artifact_bias && one_in_(3)) - o_ptr->artifact_bias = BIAS_LAW; - break; - } - break; - } - } -} - -/*! - * @brief ランダムアーティファクト生成中、対象のオブジェクトにスレイ効果を付加する。/ Add one slaying on generation of randam artifact. - * @details 優先的に付加される耐性がランダムアーティファクトバイアスに依存して存在する。 - * 原則的候補は強力射、高速射、混沌効果、吸血効果、祝福、投擲しやすい、焼棄、凍結、電撃、溶解、毒殺、 - * 動物スレイ、邪悪スレイ、悪魔スレイ、不死スレイ、オークスレイ、トロルスレイ、巨人スレイ、ドラゴンスレイ、 - * *ドラゴンスレイ*、人間スレイ、切れ味、地震、理力。 - * @attention オブジェクトのtval、svalに依存したハードコーディング処理がある。 - * @param o_ptr 対象のオブジェクト構造体ポインタ - * @return なし - */ -static void random_slay(object_type *o_ptr) -{ - if (o_ptr->tval == TV_BOW) - { - switch (randint1(6)) - { - case 1: - case 2: - case 3: - add_flag(o_ptr->art_flags, TR_XTRA_MIGHT); - if (!one_in_(7)) remove_flag(o_ptr->art_flags, TR_XTRA_SHOTS); - if (!o_ptr->artifact_bias && one_in_(9)) - o_ptr->artifact_bias = BIAS_RANGER; - break; - default: - add_flag(o_ptr->art_flags, TR_XTRA_SHOTS); - if (!one_in_(7)) remove_flag(o_ptr->art_flags, TR_XTRA_MIGHT); - if (!o_ptr->artifact_bias && one_in_(9)) - o_ptr->artifact_bias = BIAS_RANGER; - break; - } - - return; - } - - switch (o_ptr->artifact_bias) - { - case BIAS_CHAOS: - if (!(have_flag(o_ptr->art_flags, TR_CHAOTIC))) - { - add_flag(o_ptr->art_flags, TR_CHAOTIC); - if (one_in_(2)) return; - } - break; - - case BIAS_PRIESTLY: - if((o_ptr->tval == TV_SWORD || o_ptr->tval == TV_POLEARM) && - !(have_flag(o_ptr->art_flags, TR_BLESSED))) - { - /* A free power for "priestly" random artifacts */ - add_flag(o_ptr->art_flags, TR_BLESSED); - } - break; - - case BIAS_NECROMANTIC: - if (!(have_flag(o_ptr->art_flags, TR_VAMPIRIC))) - { - add_flag(o_ptr->art_flags, TR_VAMPIRIC); - if (one_in_(2)) return; - } - if (!(have_flag(o_ptr->art_flags, TR_BRAND_POIS)) && one_in_(2)) - { - add_flag(o_ptr->art_flags, TR_BRAND_POIS); - if (one_in_(2)) return; - } - break; - - case BIAS_RANGER: - if (!(have_flag(o_ptr->art_flags, TR_SLAY_ANIMAL))) - { - add_flag(o_ptr->art_flags, TR_SLAY_ANIMAL); - if (one_in_(2)) return; - } - break; - - case BIAS_ROGUE: - if ((((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_DAGGER)) || - ((o_ptr->tval == TV_POLEARM) && (o_ptr->sval == SV_SPEAR))) && - !(have_flag(o_ptr->art_flags, TR_THROW))) - { - /* Free power for rogues... */ - add_flag(o_ptr->art_flags, TR_THROW); - } - if (!(have_flag(o_ptr->art_flags, TR_BRAND_POIS))) - { - add_flag(o_ptr->art_flags, TR_BRAND_POIS); - if (one_in_(2)) return; - } - break; - - case BIAS_POIS: - if (!(have_flag(o_ptr->art_flags, TR_BRAND_POIS))) - { - add_flag(o_ptr->art_flags, TR_BRAND_POIS); - if (one_in_(2)) return; - } - break; - - case BIAS_FIRE: - if (!(have_flag(o_ptr->art_flags, TR_BRAND_FIRE))) - { - add_flag(o_ptr->art_flags, TR_BRAND_FIRE); - if (one_in_(2)) return; - } - break; - - case BIAS_COLD: - if (!(have_flag(o_ptr->art_flags, TR_BRAND_COLD))) - { - add_flag(o_ptr->art_flags, TR_BRAND_COLD); - if (one_in_(2)) return; - } - break; - - case BIAS_ELEC: - if (!(have_flag(o_ptr->art_flags, TR_BRAND_ELEC))) - { - add_flag(o_ptr->art_flags, TR_BRAND_ELEC); - if (one_in_(2)) return; - } - break; - - case BIAS_ACID: - if (!(have_flag(o_ptr->art_flags, TR_BRAND_ACID))) - { - add_flag(o_ptr->art_flags, TR_BRAND_ACID); - if (one_in_(2)) return; - } - break; - - case BIAS_LAW: - if (!(have_flag(o_ptr->art_flags, TR_SLAY_EVIL))) - { - add_flag(o_ptr->art_flags, TR_SLAY_EVIL); - if (one_in_(2)) return; - } - if (!(have_flag(o_ptr->art_flags, TR_SLAY_UNDEAD))) - { - add_flag(o_ptr->art_flags, TR_SLAY_UNDEAD); - if (one_in_(2)) return; - } - if (!(have_flag(o_ptr->art_flags, TR_SLAY_DEMON))) - { - add_flag(o_ptr->art_flags, TR_SLAY_DEMON); - if (one_in_(2)) return; - } - break; - } - - switch (randint1(36)) - { - case 1: - case 2: - if (one_in_(4)) - { - add_flag(o_ptr->art_flags, TR_KILL_ANIMAL); - } - else - { - add_flag(o_ptr->art_flags, TR_SLAY_ANIMAL); - } - break; - case 3: - case 4: - if (one_in_(8)) - { - add_flag(o_ptr->art_flags, TR_KILL_EVIL); - } - else - { - add_flag(o_ptr->art_flags, TR_SLAY_EVIL); - } - if (!o_ptr->artifact_bias && one_in_(2)) - o_ptr->artifact_bias = BIAS_LAW; - else if (!o_ptr->artifact_bias && one_in_(9)) - o_ptr->artifact_bias = BIAS_PRIESTLY; - break; - case 5: - case 6: - if (one_in_(4)) - { - add_flag(o_ptr->art_flags, TR_KILL_UNDEAD); - } - else - { - add_flag(o_ptr->art_flags, TR_SLAY_UNDEAD); - } - if (!o_ptr->artifact_bias && one_in_(9)) - o_ptr->artifact_bias = BIAS_PRIESTLY; - break; - case 7: - case 8: - if (one_in_(4)) - { - add_flag(o_ptr->art_flags, TR_KILL_DEMON); - } - else - { - add_flag(o_ptr->art_flags, TR_SLAY_DEMON); - } - if (!o_ptr->artifact_bias && one_in_(9)) - o_ptr->artifact_bias = BIAS_PRIESTLY; - break; - case 9: - case 10: - if (one_in_(4)) - { - add_flag(o_ptr->art_flags, TR_KILL_ORC); - } - else - { - add_flag(o_ptr->art_flags, TR_SLAY_ORC); - } - break; - case 11: - case 12: - if (one_in_(4)) - { - add_flag(o_ptr->art_flags, TR_KILL_TROLL); - } - else - { - add_flag(o_ptr->art_flags, TR_SLAY_TROLL); - } - break; - case 13: - case 14: - if (one_in_(4)) - { - add_flag(o_ptr->art_flags, TR_KILL_GIANT); - } - else - { - add_flag(o_ptr->art_flags, TR_SLAY_GIANT); - } - break; - case 15: - case 16: - add_flag(o_ptr->art_flags, TR_SLAY_DRAGON); - break; - case 17: - add_flag(o_ptr->art_flags, TR_KILL_DRAGON); - break; - case 18: - case 19: - if (o_ptr->tval == TV_SWORD) - { - add_flag(o_ptr->art_flags, TR_VORPAL); - if (!o_ptr->artifact_bias && one_in_(9)) - o_ptr->artifact_bias = BIAS_WARRIOR; - } - else - random_slay(o_ptr); - break; - case 20: - add_flag(o_ptr->art_flags, TR_IMPACT); - break; - case 21: - case 22: - add_flag(o_ptr->art_flags, TR_BRAND_FIRE); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_FIRE; - break; - case 23: - case 24: - add_flag(o_ptr->art_flags, TR_BRAND_COLD); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_COLD; - break; - case 25: - case 26: - add_flag(o_ptr->art_flags, TR_BRAND_ELEC); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_ELEC; - break; - case 27: - case 28: - add_flag(o_ptr->art_flags, TR_BRAND_ACID); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_ACID; - break; - case 29: - case 30: - add_flag(o_ptr->art_flags, TR_BRAND_POIS); - if (!o_ptr->artifact_bias && !one_in_(3)) - o_ptr->artifact_bias = BIAS_POIS; - else if (!o_ptr->artifact_bias && one_in_(6)) - o_ptr->artifact_bias = BIAS_NECROMANTIC; - else if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_ROGUE; - break; - case 31: - add_flag(o_ptr->art_flags, TR_VAMPIRIC); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_NECROMANTIC; - break; - case 32: - add_flag(o_ptr->art_flags, TR_FORCE_WEAPON); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = (one_in_(2) ? BIAS_MAGE : BIAS_PRIESTLY); - break; - case 33: - case 34: - if (one_in_(4)) - { - add_flag(o_ptr->art_flags, TR_KILL_HUMAN); - } - else - { - add_flag(o_ptr->art_flags, TR_SLAY_HUMAN); - } - break; - default: - add_flag(o_ptr->art_flags, TR_CHAOTIC); - if (!o_ptr->artifact_bias) - o_ptr->artifact_bias = BIAS_CHAOS; - break; - } -} - -/*! - * @brief ランダムアーティファクト生成中、対象のオブジェクトにバイアスに依存した発動を与える。/ Add one activaton of randam artifact depend on bias. - * @details バイアスが無い場合、一部のバイアスの確率によっては one_ability() に処理が移行する。 - * @param o_ptr 対象のオブジェクト構造体ポインタ - * @return なし - */ -static void give_activation_power(object_type *o_ptr) -{ - int type = 0, chance = 0; - - switch (o_ptr->artifact_bias) - { - case BIAS_ELEC: - if (!one_in_(3)) - { - type = ACT_BO_ELEC_1; - } - else if (!one_in_(5)) - { - type = ACT_BA_ELEC_2; - } - else - { - type = ACT_BA_ELEC_3; - } - chance = 101; - break; - - case BIAS_POIS: - type = ACT_BA_POIS_1; - chance = 101; - break; - - case BIAS_FIRE: - if (!one_in_(3)) - { - type = ACT_BO_FIRE_1; - } - else if (!one_in_(5)) - { - type = ACT_BA_FIRE_1; - } - else - { - type = ACT_BA_FIRE_2; - } - chance = 101; - break; - - case BIAS_COLD: - chance = 101; - if (!one_in_(3)) - type = ACT_BO_COLD_1; - else if (!one_in_(3)) - type = ACT_BA_COLD_1; - else if (!one_in_(3)) - type = ACT_BA_COLD_2; - else - type = ACT_BA_COLD_3; - break; - - case BIAS_CHAOS: - chance = 50; - if (one_in_(6)) - type = ACT_SUMMON_DEMON; - else - type = ACT_CALL_CHAOS; - break; - - case BIAS_PRIESTLY: - chance = 101; - - if (one_in_(13)) - type = ACT_CHARM_UNDEAD; - else if (one_in_(12)) - type = ACT_BANISH_EVIL; - else if (one_in_(11)) - type = ACT_DISP_EVIL; - else if (one_in_(10)) - type = ACT_PROT_EVIL; - else if (one_in_(9)) - type = ACT_CURE_1000; - else if (one_in_(8)) - type = ACT_CURE_700; - else if (one_in_(7)) - type = ACT_REST_ALL; - else if (one_in_(6)) - type = ACT_REST_EXP; - else - type = ACT_CURE_MW; - break; - - case BIAS_NECROMANTIC: - chance = 101; - if (one_in_(66)) - type = ACT_WRAITH; - else if (one_in_(13)) - type = ACT_DISP_GOOD; - else if (one_in_(9)) - type = ACT_MASS_GENO; - else if (one_in_(8)) - type = ACT_GENOCIDE; - else if (one_in_(13)) - type = ACT_SUMMON_UNDEAD; - else if (one_in_(9)) - type = ACT_DRAIN_2; - else if (one_in_(6)) - type = ACT_CHARM_UNDEAD; - else - type = ACT_DRAIN_1; - break; - - case BIAS_LAW: - chance = 101; - if (one_in_(8)) - type = ACT_BANISH_EVIL; - else if (one_in_(4)) - type = ACT_DISP_EVIL; - else - type = ACT_PROT_EVIL; - break; - - case BIAS_ROGUE: - chance = 101; - if (one_in_(50)) - type = ACT_SPEED; - else if (one_in_(4)) - type = ACT_SLEEP; - else if (one_in_(3)) - type = ACT_DETECT_ALL; - else if (one_in_(8)) - type = ACT_ID_FULL; - else - type = ACT_ID_PLAIN; - break; - - case BIAS_MAGE: - chance = 66; - if (one_in_(20)) - type = ACT_SUMMON_ELEMENTAL; - else if (one_in_(10)) - type = ACT_SUMMON_PHANTOM; - else if (one_in_(5)) - type = ACT_RUNE_EXPLO; - else - type = ACT_ESP; - break; - - case BIAS_WARRIOR: - chance = 80; - if (one_in_(100)) - type = ACT_INVULN; - else - type = ACT_BERSERK; - break; - - case BIAS_RANGER: - chance = 101; - if (one_in_(20)) - type = ACT_CHARM_ANIMALS; - else if (one_in_(7)) - type = ACT_SUMMON_ANIMAL; - else if (one_in_(6)) - type = ACT_CHARM_ANIMAL; - else if (one_in_(4)) - type = ACT_RESIST_ALL; - else if (one_in_(3)) - type = ACT_SATIATE; - else - type = ACT_CURE_POISON; - break; - } - - if (!type || (randint1(100) >= chance)) - { - one_activation(o_ptr); - return; - } - - /* A type was chosen... */ - o_ptr->xtra2 = (byte_hack)type; - add_flag(o_ptr->art_flags, TR_ACTIVATE); - o_ptr->timeout = 0; -} - -/*! - * @brief ランダムアーティファクト生成中、対象のオブジェクトに名前を与える。/ Set name of randomartifact. - * @details 確率によって、シンダリン銘、漢字銘、固定名のいずれか一つが与えられる。 - * @param o_ptr 処理中のアイテム参照ポインタ - * @param return_name 名前を返すための文字列参照ポインタ - * @param armour 対象のオブジェクトが防具が否か - * @param power 銘の基準となるオブジェクトの価値レベル(0=呪い、1=低位、2=中位、3以上=高位) - * @return なし - */ -static void get_random_name(object_type *o_ptr, char *return_name, bool armour, int power) -{ - PERCENTAGE prob = randint1(100); - - if (prob <= SINDARIN_NAME) - { - get_table_sindarin(return_name); - } - else if (prob <= TABLE_NAME) - { - get_table_name(return_name); - } - else - { - concptr filename; - - switch (armour) - { - case 1: - switch (power) - { - case 0: - filename = _("a_cursed_j.txt", "a_cursed.txt"); - break; - case 1: - filename = _("a_low_j.txt", "a_low.txt"); - break; - case 2: - filename = _("a_med_j.txt", "a_med.txt"); - break; - default: - filename = _("a_high_j.txt", "a_high.txt"); - } - break; - default: - switch (power) - { - case 0: - filename = _("w_cursed_j.txt", "w_cursed.txt"); - break; - case 1: - filename = _("w_low_j.txt", "w_low.txt"); - break; - case 2: - filename = _("w_med_j.txt", "w_med.txt"); - break; - default: - filename = _("w_high_j.txt", "w_high.txt"); - } - } - - (void)get_rnd_line(filename, o_ptr->artifact_bias, return_name); -#ifdef JP - if (return_name[0] == 0) get_table_name(return_name); -#endif - } -} - -/*! - * @brief ランダムアーティファクト生成のメインルーチン - * @details 既に生成が済んでいるオブジェクトの構造体を、アーティファクトとして強化する。 - * @param o_ptr 対象のオブジェクト構造体ポインタ - * @param a_scroll アーティファクト生成の巻物上の処理。呪いのアーティファクトが生成対象外となる。 - * @return 常にTRUE(1)を返す - */ -bool create_artifact(object_type *o_ptr, bool a_scroll) -{ - GAME_TEXT new_name[1024]; - PARAMETER_VALUE has_pval = 0; - int powers = randint1(5) + 1; - int max_powers; - int max_type = (object_is_weapon_ammo(o_ptr) ? 7 : 5); - int power_level; - s32b total_flags; - bool a_cursed = FALSE; - int warrior_artifact_bias = 0; - int i; - - /* Reset artifact bias */ - o_ptr->artifact_bias = 0; - - /* Nuke enchantments */ - o_ptr->name1 = 0; - o_ptr->name2 = 0; - - for (i = 0; i < TR_FLAG_SIZE; i++) - o_ptr->art_flags[i] |= k_info[o_ptr->k_idx].flags[i]; - - if (o_ptr->pval) has_pval = TRUE; - - if (a_scroll && one_in_(4)) - { - switch (p_ptr->pclass) - { - case CLASS_WARRIOR: - case CLASS_BERSERKER: - case CLASS_ARCHER: - case CLASS_SAMURAI: - case CLASS_CAVALRY: - case CLASS_SMITH: - o_ptr->artifact_bias = BIAS_WARRIOR; - break; - case CLASS_MAGE: - case CLASS_HIGH_MAGE: - case CLASS_SORCERER: - case CLASS_MAGIC_EATER: - case CLASS_BLUE_MAGE: - o_ptr->artifact_bias = BIAS_MAGE; - break; - case CLASS_PRIEST: - o_ptr->artifact_bias = BIAS_PRIESTLY; - break; - case CLASS_ROGUE: - case CLASS_NINJA: - o_ptr->artifact_bias = BIAS_ROGUE; - warrior_artifact_bias = 25; - break; - case CLASS_RANGER: - case CLASS_SNIPER: - o_ptr->artifact_bias = BIAS_RANGER; - warrior_artifact_bias = 30; - break; - case CLASS_PALADIN: - o_ptr->artifact_bias = BIAS_PRIESTLY; - warrior_artifact_bias = 40; - break; - case CLASS_WARRIOR_MAGE: - case CLASS_RED_MAGE: - o_ptr->artifact_bias = BIAS_MAGE; - warrior_artifact_bias = 40; - break; - case CLASS_CHAOS_WARRIOR: - o_ptr->artifact_bias = BIAS_CHAOS; - warrior_artifact_bias = 40; - break; - case CLASS_MONK: - case CLASS_FORCETRAINER: - o_ptr->artifact_bias = BIAS_PRIESTLY; - break; - case CLASS_MINDCRAFTER: - case CLASS_BARD: - if (randint1(5) > 2) o_ptr->artifact_bias = BIAS_PRIESTLY; - break; - case CLASS_TOURIST: - if (randint1(5) > 2) o_ptr->artifact_bias = BIAS_WARRIOR; - break; - case CLASS_IMITATOR: - if (randint1(2) > 1) o_ptr->artifact_bias = BIAS_RANGER; - break; - case CLASS_BEASTMASTER: - o_ptr->artifact_bias = BIAS_CHR; - warrior_artifact_bias = 50; - break; - case CLASS_MIRROR_MASTER: - if (randint1(4) > 1) - { - o_ptr->artifact_bias = BIAS_MAGE; - } - else - { - o_ptr->artifact_bias = BIAS_ROGUE; - } - break; - } - } - - if (a_scroll && (randint1(100) <= warrior_artifact_bias)) - o_ptr->artifact_bias = BIAS_WARRIOR; - - strcpy(new_name, ""); - - if (!a_scroll && one_in_(A_CURSED)) - a_cursed = TRUE; - if (((o_ptr->tval == TV_AMULET) || (o_ptr->tval == TV_RING)) && object_is_cursed(o_ptr)) - a_cursed = TRUE; - - while (one_in_(powers) || one_in_(7) || one_in_(10)) - powers++; - - if (!a_cursed && one_in_(WEIRD_LUCK)) - powers *= 2; - - if (a_cursed) powers /= 2; - - max_powers = powers; - /* Main loop */ - while (powers--) - { - switch (randint1(max_type)) - { - case 1: case 2: - random_plus(o_ptr); - has_pval = TRUE; - break; - case 3: case 4: - if (one_in_(2) && object_is_weapon_ammo(o_ptr) && (o_ptr->tval != TV_BOW)) - { - if (a_cursed && !one_in_(13)) break; - if (one_in_(13)) - { - if (one_in_(o_ptr->ds+4)) o_ptr->ds++; - } - else - { - if (one_in_(o_ptr->dd+1)) o_ptr->dd++; - } - } - else - random_resistance(o_ptr); - break; - case 5: - random_misc(o_ptr); - break; - case 6: case 7: - random_slay(o_ptr); - break; - default: - if (p_ptr->wizard) msg_print("Switch error in create_artifact!"); - powers++; - } - }; - - if (has_pval) - { - if (have_flag(o_ptr->art_flags, TR_BLOWS)) - { - o_ptr->pval = randint1(2); - if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_HAYABUSA)) - o_ptr->pval++; - } - else - { - do - { - o_ptr->pval++; - } - while (o_ptr->pval < randint1(5) || one_in_(o_ptr->pval)); - } - - if ((o_ptr->pval > 4) && !one_in_(WEIRD_LUCK)) - o_ptr->pval = 4; - } - - - /* give it some plusses... */ - if (object_is_armour(o_ptr)) - o_ptr->to_a += randint1(o_ptr->to_a > 19 ? 1 : 20 - o_ptr->to_a); - else if (object_is_weapon_ammo(o_ptr)) - { - o_ptr->to_h += randint1(o_ptr->to_h > 19 ? 1 : 20 - o_ptr->to_h); - o_ptr->to_d += randint1(o_ptr->to_d > 19 ? 1 : 20 - o_ptr->to_d); - if ((have_flag(o_ptr->art_flags, TR_WIS)) && (o_ptr->pval > 0)) add_flag(o_ptr->art_flags, TR_BLESSED); - } - - /* Just to be sure */ - add_flag(o_ptr->art_flags, TR_IGNORE_ACID); - add_flag(o_ptr->art_flags, TR_IGNORE_ELEC); - add_flag(o_ptr->art_flags, TR_IGNORE_FIRE); - add_flag(o_ptr->art_flags, TR_IGNORE_COLD); - - total_flags = flag_cost(o_ptr, o_ptr->pval); - - if (a_cursed) curse_artifact(o_ptr); - - if (!a_cursed && - one_in_(object_is_armour(o_ptr) ? ACTIVATION_CHANCE * 2 : ACTIVATION_CHANCE)) - { - o_ptr->xtra2 = 0; - give_activation_power(o_ptr); - } - - if (object_is_armour(o_ptr)) - { - while ((o_ptr->to_d+o_ptr->to_h) > 20) - { - if (one_in_(o_ptr->to_d) && one_in_(o_ptr->to_h)) break; - o_ptr->to_d -= (HIT_POINT)randint0(3); - o_ptr->to_h -= (HIT_PROB)randint0(3); - } - while ((o_ptr->to_d+o_ptr->to_h) > 10) - { - if (one_in_(o_ptr->to_d) || one_in_(o_ptr->to_h)) break; - o_ptr->to_d -= (HIT_POINT)randint0(3); - o_ptr->to_h -= (HIT_PROB)randint0(3); - } - } - - if (((o_ptr->artifact_bias == BIAS_MAGE) || (o_ptr->artifact_bias == BIAS_INT)) && (o_ptr->tval == TV_GLOVES)) add_flag(o_ptr->art_flags, TR_FREE_ACT); - - if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_DOKUBARI)) - { - o_ptr->to_h = 0; - o_ptr->to_d = 0; - remove_flag(o_ptr->art_flags, TR_BLOWS); - remove_flag(o_ptr->art_flags, TR_FORCE_WEAPON); - remove_flag(o_ptr->art_flags, TR_SLAY_ANIMAL); - remove_flag(o_ptr->art_flags, TR_SLAY_EVIL); - remove_flag(o_ptr->art_flags, TR_SLAY_UNDEAD); - remove_flag(o_ptr->art_flags, TR_SLAY_DEMON); - remove_flag(o_ptr->art_flags, TR_SLAY_ORC); - remove_flag(o_ptr->art_flags, TR_SLAY_TROLL); - remove_flag(o_ptr->art_flags, TR_SLAY_GIANT); - remove_flag(o_ptr->art_flags, TR_SLAY_DRAGON); - remove_flag(o_ptr->art_flags, TR_KILL_DRAGON); - remove_flag(o_ptr->art_flags, TR_SLAY_HUMAN); - remove_flag(o_ptr->art_flags, TR_VORPAL); - remove_flag(o_ptr->art_flags, TR_BRAND_POIS); - remove_flag(o_ptr->art_flags, TR_BRAND_ACID); - remove_flag(o_ptr->art_flags, TR_BRAND_ELEC); - remove_flag(o_ptr->art_flags, TR_BRAND_FIRE); - remove_flag(o_ptr->art_flags, TR_BRAND_COLD); - } - - if (!object_is_weapon_ammo(o_ptr)) - { - /* For armors */ - if (a_cursed) power_level = 0; - else if (total_flags < 15000) power_level = 1; - else if (total_flags < 35000) power_level = 2; - else power_level = 3; - } - - else - { - /* For weapons */ - if (a_cursed) power_level = 0; - else if (total_flags < 20000) power_level = 1; - else if (total_flags < 45000) power_level = 2; - else power_level = 3; - } - - /* ダメージ抑制処理を行う */ - while (has_extreme_damage_rate(o_ptr) && !one_in_(SWORDFISH_LUCK)) - { - weakening_artifact(o_ptr); - } - - if (a_scroll) - { - GAME_TEXT dummy_name[MAX_NLEN] = ""; - concptr ask_msg = _("このアーティファクトを何と名付けますか?", "What do you want to call the artifact? "); - - object_aware(o_ptr); - object_known(o_ptr); - - /* Mark the item as fully known */ - o_ptr->ident |= (IDENT_MENTAL); - - /* For being treated as random artifact in screen_object() */ - o_ptr->art_name = quark_add(""); - - (void)screen_object(o_ptr, 0L); - - if (!get_string(ask_msg, dummy_name, sizeof dummy_name) - || !dummy_name[0]) - { - /* Cancelled */ - if (one_in_(2)) - { - get_table_sindarin_aux(dummy_name); - } - else - { - get_table_name_aux(dummy_name); - } - } - sprintf(new_name, _("《%s》", "'%s'"), dummy_name); - chg_virtue(V_INDIVIDUALISM, 2); - chg_virtue(V_ENCHANT, 5); - } - else - { - get_random_name(o_ptr, new_name, object_is_armour(o_ptr), power_level); - } - - /* Save the inscription */ - o_ptr->art_name = quark_add(new_name); - - msg_format_wizard(CHEAT_OBJECT, _("パワー %d で 価値%ld のランダムアーティファクト生成 バイアスは「%s」", - "Random artifact generated - Power:%d Value:%d Bias:%s."), max_powers, total_flags, artifact_bias_name[o_ptr->artifact_bias]); - - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - return TRUE; -} - -/*! - * @brief オブジェクトから能力発動IDを取得する。 - * @details いくつかのケースで定義されている発動効果から、 - * 鍛冶師による付与>固定アーティファクト>エゴ>ランダムアーティファクト>ベースアイテムの優先順位で走査していく。 - * @param o_ptr 対象のオブジェクト構造体ポインタ - * @return 発動効果のIDを返す - */ -int activation_index(object_type *o_ptr) -{ - /* Give priority to weaponsmith's essential activations */ - if (object_is_smith(o_ptr)) - { - switch (o_ptr->xtra3 - 1) - { - case ESSENCE_TMP_RES_ACID: return ACT_RESIST_ACID; - case ESSENCE_TMP_RES_ELEC: return ACT_RESIST_ELEC; - case ESSENCE_TMP_RES_FIRE: return ACT_RESIST_FIRE; - case ESSENCE_TMP_RES_COLD: return ACT_RESIST_COLD; - case TR_IMPACT: return ACT_QUAKE; - } - } - - if (object_is_fixed_artifact(o_ptr)) - { - if (have_flag(a_info[o_ptr->name1].flags, TR_ACTIVATE)) - { - return a_info[o_ptr->name1].act_idx; - } - } - if (object_is_ego(o_ptr)) - { - if (have_flag(e_info[o_ptr->name2].flags, TR_ACTIVATE)) - { - return e_info[o_ptr->name2].act_idx; - } - } - if (!object_is_random_artifact(o_ptr)) - { - if (have_flag(k_info[o_ptr->k_idx].flags, TR_ACTIVATE)) - { - return k_info[o_ptr->k_idx].act_idx; - } - } - - return o_ptr->xtra2; -} - -/*! - * @brief オブジェクトから発動効果構造体のポインタを取得する。 - * @details activation_index() 関数の結果から参照する。 - * @param o_ptr 対象のオブジェクト構造体ポインタ - * @return 発動効果構造体のポインタを返す - */ -const activation_type* find_activation_info(object_type *o_ptr) -{ - const int index = activation_index(o_ptr); - const activation_type* p; - - for (p = activation_info; p->flag != NULL; ++ p) { - if (p->index == index) - { - return p; - } - } - - return NULL; -} - -/*! - * @brief 固定アーティファクト生成時の特別なハードコーディング処理を行う。. - * @details random_artifact_resistance()とあるが実際は固定アーティファクトである。 - * 対象は恐怖の仮面、村正、ロビントンのハープ、龍争虎鬪、ブラッディムーン、羽衣、天女の羽衣、ミリム、 - * その他追加耐性、特性追加処理。 - * @attention プレイヤーの各種ステータスに依存した処理がある。 - * @todo 折を見て関数名を変更すること。 - * @param o_ptr 対象のオブジェクト構造体ポインタ - * @param a_ptr 生成する固定アーティファクト構造体ポインタ - * @return なし - */ -void random_artifact_resistance(object_type * o_ptr, artifact_type *a_ptr) -{ - bool give_resistance = FALSE, give_power = FALSE; - - if (o_ptr->name1 == ART_TERROR) /* Terror Mask is for warriors... */ - { - if (p_ptr->pclass == CLASS_WARRIOR || p_ptr->pclass == CLASS_ARCHER || p_ptr->pclass == CLASS_CAVALRY || p_ptr->pclass == CLASS_BERSERKER) - { - give_power = TRUE; - give_resistance = TRUE; - } - else - { - add_flag(o_ptr->art_flags, TR_AGGRAVATE); - add_flag(o_ptr->art_flags, TR_TY_CURSE); - o_ptr->curse_flags |= - (TRC_CURSED | TRC_HEAVY_CURSE); - o_ptr->curse_flags |= get_curse(2, o_ptr); - return; - } - } - - if (o_ptr->name1 == ART_MURAMASA) - { - if (p_ptr->pclass != CLASS_SAMURAI) - { - add_flag(o_ptr->art_flags, TR_NO_MAGIC); - o_ptr->curse_flags |= (TRC_HEAVY_CURSE); - } - } - - if (o_ptr->name1 == ART_ROBINTON) - { - if (p_ptr->pclass == CLASS_BARD) - { - add_flag(o_ptr->art_flags, TR_DEC_MANA); - } - } - - if (o_ptr->name1 == ART_XIAOLONG) - { - if (p_ptr->pclass == CLASS_MONK) - add_flag(o_ptr->art_flags, TR_BLOWS); - } - - if (o_ptr->name1 == ART_BLOOD) - { - get_bloody_moon_flags(o_ptr); - } - - if (o_ptr->name1 == ART_HEAVENLY_MAIDEN) - { - if (p_ptr->psex != SEX_FEMALE) - { - add_flag(o_ptr->art_flags, TR_AGGRAVATE); - } - } - - if (o_ptr->name1 == ART_MILIM) - { - if (p_ptr->pseikaku == SEIKAKU_SEXY) - { - o_ptr->pval = 3; - add_flag(o_ptr->art_flags, TR_STR); - add_flag(o_ptr->art_flags, TR_INT); - add_flag(o_ptr->art_flags, TR_WIS); - add_flag(o_ptr->art_flags, TR_DEX); - add_flag(o_ptr->art_flags, TR_CON); - add_flag(o_ptr->art_flags, TR_CHR); - } - } - - if (a_ptr->gen_flags & (TRG_XTRA_POWER)) give_power = TRUE; - if (a_ptr->gen_flags & (TRG_XTRA_H_RES)) give_resistance = TRUE; - if (a_ptr->gen_flags & (TRG_XTRA_RES_OR_POWER)) - { - /* Give a resistance OR a power */ - if (one_in_(2)) give_resistance = TRUE; - else give_power = TRUE; - } - - if (give_power) - { - one_ability(o_ptr); - } - - if (give_resistance) - { - one_high_resistance(o_ptr); - } -} - - -/*! - * @brief フロアの指定された位置に固定アーティファクトを生成する。 / Create the artifact of the specified number - * @details 固定アーティファクト構造体から基本ステータスをコピーした後、所定の座標でdrop_item()で落とす。 - * @param a_idx 生成する固定アーティファクト構造体のID - * @param y アイテムを落とす地点のy座標 - * @param x アイテムを落とす地点のx座標 - * @return 生成が成功したか否か、失敗はIDの不全、ベースアイテムの不全、drop_item()の失敗時に起こる。 - * @attention この処理はdrop_near()内で普通の固定アーティファクトが重ならない性質に依存する. - * 仮に2個以上存在可能かつ装備品以外の固定アーティファクトが作成されれば - * drop_near()関数の返り値は信用できなくなる. - */ -bool create_named_art(ARTIFACT_IDX a_idx, POSITION y, POSITION x) -{ - object_type forge; - object_type *q_ptr; - KIND_OBJECT_IDX i; - - artifact_type *a_ptr = &a_info[a_idx]; - q_ptr = &forge; - - /* Ignore "empty" artifacts */ - if (!a_ptr->name) return FALSE; - - /* Acquire the "kind" index */ - i = lookup_kind(a_ptr->tval, a_ptr->sval); - - if (!i) return FALSE; - - /* Create the artifact */ - object_prep(q_ptr, i); - - /* Save the name */ - q_ptr->name1 = a_idx; - - /* Extract the fields */ - q_ptr->pval = a_ptr->pval; - q_ptr->ac = a_ptr->ac; - q_ptr->dd = a_ptr->dd; - q_ptr->ds = a_ptr->ds; - q_ptr->to_a = a_ptr->to_a; - q_ptr->to_h = a_ptr->to_h; - q_ptr->to_d = a_ptr->to_d; - q_ptr->weight = a_ptr->weight; - - /* Hack -- extract the "cursed" flag */ - if (a_ptr->gen_flags & TRG_CURSED) q_ptr->curse_flags |= (TRC_CURSED); - if (a_ptr->gen_flags & TRG_HEAVY_CURSE) q_ptr->curse_flags |= (TRC_HEAVY_CURSE); - if (a_ptr->gen_flags & TRG_PERMA_CURSE) q_ptr->curse_flags |= (TRC_PERMA_CURSE); - if (a_ptr->gen_flags & (TRG_RANDOM_CURSE0)) q_ptr->curse_flags |= get_curse(0, q_ptr); - if (a_ptr->gen_flags & (TRG_RANDOM_CURSE1)) q_ptr->curse_flags |= get_curse(1, q_ptr); - if (a_ptr->gen_flags & (TRG_RANDOM_CURSE2)) q_ptr->curse_flags |= get_curse(2, q_ptr); - - random_artifact_resistance(q_ptr, a_ptr); - - /* Drop the artifact from heaven */ - return drop_near(q_ptr, -1, y, x) ? TRUE : FALSE; -} - -/*対邪平均ダメージの計算処理*/ -HIT_POINT calc_arm_avgdamage(object_type *o_ptr) -{ - BIT_FLAGS flgs[TR_FLAG_SIZE]; - object_flags(o_ptr, flgs); - - HIT_POINT dam, base, s_evil, forced, vorpal; - s_evil = forced = vorpal = 0; - dam = base = (o_ptr->dd * o_ptr->ds + o_ptr->dd) / 2; - - if(have_flag(flgs, TR_KILL_EVIL)) - { - dam = s_evil = dam * 7 / 2; - } - else if(!have_flag(flgs, TR_KILL_EVIL) && have_flag(flgs, TR_SLAY_EVIL)) - { - dam = s_evil = dam * 2; - } - else s_evil = dam; - - if (have_flag(flgs, TR_FORCE_WEAPON)) - { - dam = forced = dam * 3 / 2 + (o_ptr->dd * o_ptr->ds + o_ptr->dd); - } - else forced = dam; - - if(have_flag(flgs, TR_VORPAL)) - { - dam = vorpal = dam * 11 / 9; - } - else vorpal = dam; - - dam = dam + o_ptr->to_d; - - msg_format_wizard(CHEAT_OBJECT,"ç´ :%d> 対邪:%d> 理力:%d> 切:%d> 最終:%d", base, s_evil, forced, vorpal, dam); - - return dam; -} - -static bool has_extreme_damage_rate(object_type *o_ptr) -{ - BIT_FLAGS flgs[TR_FLAG_SIZE]; - object_flags(o_ptr, flgs); - - if (have_flag(flgs, TR_VAMPIRIC)) - { - if(have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 1) && (calc_arm_avgdamage(o_ptr) > 52)) - { - return TRUE; - } - else if(have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 2) && (calc_arm_avgdamage(o_ptr) > 43)) - { - return TRUE; - } - else if( have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 3) && (calc_arm_avgdamage(o_ptr) > 33)) - { - return TRUE; - } - else if (calc_arm_avgdamage(o_ptr) > 63) - { - return TRUE; - } - } - else - { - if (have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 1) && (calc_arm_avgdamage(o_ptr) > 65)) - { - return TRUE; - } - else if (have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 2) && (calc_arm_avgdamage(o_ptr) > 52)) - { - return TRUE; - } - else if (have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 3) && (calc_arm_avgdamage(o_ptr) > 40)) - { - return TRUE; - } - else if (calc_arm_avgdamage(o_ptr) > 75) - { - return TRUE; - } - } - return FALSE; -} - -static bool weakening_artifact(object_type *o_ptr) -{ - KIND_OBJECT_IDX k_idx = lookup_kind(o_ptr->tval, o_ptr->sval); - object_kind *k_ptr = &k_info[k_idx]; - BIT_FLAGS flgs[TR_FLAG_SIZE]; - object_flags(o_ptr, flgs); - - if (have_flag(flgs, TR_KILL_EVIL)) - { - remove_flag(o_ptr->art_flags, TR_KILL_EVIL); - add_flag(o_ptr->art_flags, TR_SLAY_EVIL); - return TRUE; - } - else if (k_ptr->dd < o_ptr->dd) - { - o_ptr->dd--; - return TRUE; - } - else if (k_ptr->ds < o_ptr->ds) - { - o_ptr->ds--; - return TRUE; - } - else if (o_ptr->to_d > 10) - { - o_ptr->to_d = o_ptr->to_d - damroll(1, 6); - if (o_ptr->to_d < 10) - { - o_ptr->to_d = 10; - } - return TRUE; - } - return FALSE; -} - -/*! - * @brief 非INSTA_ART型の固定アーティファクトの生成を確率に応じて試行する。 - * Mega-Hack -- Attempt to create one of the "Special Objects" - * @param o_ptr 生成に割り当てたいオブジェクトの構造体参照ポインタ - * @return 生成に成功したらTRUEを返す。 - * @details - * Attempt to change an object into an artifact\n - * This routine should only be called by "apply_magic()"\n - * Note -- see "make_artifact_special()" and "apply_magic()"\n - */ -bool make_artifact(object_type *o_ptr) -{ - ARTIFACT_IDX i; - - /* No artifacts in the town */ - if (!current_floor_ptr->dun_level) return (FALSE); - - /* Paranoia -- no "plural" artifacts */ - if (o_ptr->number != 1) return (FALSE); - - /* Check the artifact list (skip the "specials") */ - for (i = 0; i < max_a_idx; i++) - { - artifact_type *a_ptr = &a_info[i]; - - /* Skip "empty" items */ - if (!a_ptr->name) continue; - - /* Cannot make an artifact twice */ - if (a_ptr->cur_num) continue; - - if (a_ptr->gen_flags & TRG_QUESTITEM) continue; - - if (a_ptr->gen_flags & TRG_INSTA_ART) continue; - - /* Must have the correct fields */ - if (a_ptr->tval != o_ptr->tval) continue; - if (a_ptr->sval != o_ptr->sval) continue; - - /* XXX XXX Enforce minimum "depth" (loosely) */ - if (a_ptr->level > current_floor_ptr->dun_level) - { - /* Acquire the "out-of-depth factor" */ - int d = (a_ptr->level - current_floor_ptr->dun_level) * 2; - - /* Roll for out-of-depth creation */ - if (!one_in_(d)) continue; - } - - /* We must make the "rarity roll" */ - if (!one_in_(a_ptr->rarity)) continue; - - /* Hack -- mark the item as an artifact */ - o_ptr->name1 = i; - - /* Hack: Some artifacts get random extra powers */ - random_artifact_resistance(o_ptr, a_ptr); - - /* Success */ - return (TRUE); - } - - /* Failure */ - return (FALSE); -} - -/*! - * @brief INSTA_ART型の固定アーティファクトの生成を確率に応じて試行する。 - * Mega-Hack -- Attempt to create one of the "Special Objects" - * @param o_ptr 生成に割り当てたいオブジェクトの構造体参照ポインタ - * @return 生成に成功したらTRUEを返す。 - * @details - * We are only called from "make_object()", and we assume that\n - * "apply_magic()" is called immediately after we return.\n - *\n - * Note -- see "make_artifact()" and "apply_magic()"\n - */ -bool make_artifact_special(object_type *o_ptr) -{ - IDX i; - KIND_OBJECT_IDX k_idx = 0; - - /*! @note 地上ではキャンセルする / No artifacts in the town */ - if (!current_floor_ptr->dun_level) return (FALSE); - - /*! @note get_obj_num_hookによる指定がある場合は生成をキャンセルする / Themed object */ - if (get_obj_num_hook) return (FALSE); - - /*! @note 全固定アーティファクト中からIDの若い順に生成対象とその確率を走査する / Check the artifact list (just the "specials") */ - for (i = 0; i < max_a_idx; i++) - { - artifact_type *a_ptr = &a_info[i]; - - /*! @note アーティファクト名が空の不正なデータは除外する / Skip "empty" artifacts */ - if (!a_ptr->name) continue; - - /*! @note 既に生成回数がカウントされたアーティファクト、QUESTITEMと非INSTA_ARTは除外 / Cannot make an artifact twice */ - if (a_ptr->cur_num) continue; - if (a_ptr->gen_flags & TRG_QUESTITEM) continue; - if (!(a_ptr->gen_flags & TRG_INSTA_ART)) continue; - - /*! @note アーティファクト生成階が現在に対して足りない場合は高確率で1/(不足階層*2)を満たさないと生成リストに加えられない / - * XXX XXX Enforce minimum "depth" (loosely) */ - if (a_ptr->level > current_floor_ptr->object_level) - { - /* @note / Acquire the "out-of-depth factor". Roll for out-of-depth creation. */ - int d = (a_ptr->level - current_floor_ptr->object_level) * 2; - if (!one_in_(d)) continue; - } - - /*! @note 1/(レア度)の確率を満たさないと除外される / Artifact "rarity roll" */ - if (!one_in_(a_ptr->rarity)) continue; - - /*! @note INSTA_ART型固定アーティファクトのベースアイテムもチェック対象とする。ベースアイテムの生成階層が足りない場合1/(不足階層*5) を満たさないと除外される。 / - * Find the base object. XXX XXX Enforce minimum "object" level (loosely). Acquire the "out-of-depth factor". Roll for out-of-depth creation. */ - k_idx = lookup_kind(a_ptr->tval, a_ptr->sval); - if (k_info[k_idx].level > current_floor_ptr->object_level) - { - int d = (k_info[k_idx].level - current_floor_ptr->object_level) * 5; - if (!one_in_(d)) continue; - } - - /*! @note 前述の条件を満たしたら、後のIDのアーティファクトはチェックせずすぐ確定し生成処理に移す / - * Assign the template. Mega-Hack -- mark the item as an artifact. Hack: Some artifacts get random extra powers. Success. */ - object_prep(o_ptr, k_idx); - - o_ptr->name1 = i; - random_artifact_resistance(o_ptr, a_ptr); - return (TRUE); - } - - /*! @note 全INSTA_ART固定アーティファクトを試行しても決まらなかった場合 FALSEを返す / Failure */ - return (FALSE); -} diff --git a/src/artifact.h b/src/artifact.h deleted file mode 100644 index 3bdcd8855..000000000 --- a/src/artifact.h +++ /dev/null @@ -1,294 +0,0 @@ -/* artifact.c */ -extern bool create_artifact(object_type *o_ptr, bool a_scroll); -extern int activation_index(object_type *o_ptr); -extern const activation_type* find_activation_info(object_type *o_ptr); -extern void random_artifact_resistance(object_type * o_ptr, artifact_type *a_ptr); -extern bool create_named_art(ARTIFACT_IDX a_idx, POSITION y, POSITION x); -extern bool make_artifact(object_type *o_ptr); -extern bool make_artifact_special(object_type *o_ptr); - -/*** Artifact indexes (see "lib/edit/a_info.txt") ***/ - -/* Lites */ -#define ART_GALADRIEL 1 -#define ART_ELENDIL 2 -#define ART_JUDGE 3 -#define ART_EDISON 7 -#define ART_PALANTIR 15 -#define ART_STONE_LORE 17 -#define ART_FLY_STONE 147 -#define ART_ORB_OF_FATE 245 -/* Amulets */ -#define ART_CARLAMMAS 4 -#define ART_INGWE 5 -#define ART_DWARVES 6 -#define ART_FARAMIR 18 -#define ART_BOROMIR 143 -#define ART_MAGATAMA 149 -#define ART_INROU 166 -#define ART_NIGHT 215 -#define ART_SACRED_KNIGHTS 217 -#define ART_HELL 218 -#define ART_CHARMED 219 -#define ART_GOGO 220 - -/* Rings */ -#define ART_FRAKIR 8 -#define ART_TULKAS 9 -#define ART_NARYA 10 -#define ART_NENYA 11 -#define ART_VILYA 12 -#define ART_POWER 13 -#define ART_AHO 14 - -/* Dragon Scale */ -#define ART_RAZORBACK 129 -#define ART_BLADETURNER 130 -#define ART_SEIRYU 201 - -/* Hard Armour */ -#define ART_SOULKEEPER 19 -#define ART_ISILDUR 20 -#define ART_ROHIRRIM 21 -#define ART_LOHENGRIN 22 -#define ART_JULIAN 23 -#define ART_ARVEDUI 24 -#define ART_CASPANION 25 -#define ART_GILES 168 -#define ART_MORLOK 203 -#define ART_VETERAN 206 - -/* Soft Armour */ -#define ART_SHIVA_JACKET 26 -#define ART_HITHLOMIR 27 -#define ART_THALKETTOTH 28 -#define ART_HIMRING 127 -#define ART_ICANUS 131 -#define ART_NAMAKE_ARMOR 183 -#define ART_GHB 192 -#define ART_DASAI 200 -#define ART_KESHO 204 -#define ART_MILIM 246 - -/* Shields */ -#define ART_THORIN 30 -#define ART_CELEGORM 31 -#define ART_ANARION 32 -#define ART_GIL_GALAD 138 -#define ART_YENDOR 141 -#define ART_YATA 151 -#define ART_EARENDIL 186 -#define ART_PERSEUS 197 - -/* Helms and Crowns */ -#define ART_INDRA 33 -#define ART_CHAOS 34 -#define ART_BERUTHIEL 35 -#define ART_THRANDUIL 36 -#define ART_THENGEL 37 -#define ART_HAMMERHAND 38 -#define ART_DOR 39 -#define ART_HOLHENNETH 40 -#define ART_TERROR 41 -#define ART_AMBER 42 -#define ART_NUMENOR 132 -#define ART_STONEMASK 146 - -/* Cloaks */ -#define ART_JACK 43 -#define ART_COLLUIN 44 -#define ART_HOLCOLLETH 45 -#define ART_THINGOL 46 -#define ART_THORONGIL 47 -#define ART_COLANNON 48 -#define ART_LUTHIEN 49 -#define ART_TUOR 50 -#define ART_MOOK 205 -#define ART_HEAVENLY_MAIDEN 233 - -/* Gloves */ -#define ART_CAMBELEG 52 -#define ART_CAMMITHRIM 53 -#define ART_PAURHACH 54 -#define ART_CORWIN 55 -#define ART_PAURAEGEN 56 -#define ART_PAURNEN 57 -#define ART_THANOS 58 -#define ART_FINGOLFIN 59 -#define ART_PAURNIMMEN 185 - -/* Boots */ -#define ART_FEANOR 60 -#define ART_FLORA 61 -#define ART_THROR 62 -#define ART_SHIVA_BOOTS 63 -#define ART_GLASS 165 -#define ART_GETA 210 - -/* Digging */ -#define ART_NAIN 211 - -/* Swords */ -#define ART_MAEDHROS 64 -#define ART_CAINE 65 -#define ART_NARTHANC 66 -#define ART_NIMTHANC 67 -#define ART_DETHANC 68 -#define ART_RILIA 69 -#define ART_FIONA 70 -#define ART_CALRIS 71 -#define ART_GRAYSWANDIR 72 -#define ART_GLAMDRING 73 -#define ART_NOTHUNG 74 -#define ART_ORCRIST 75 -#define ART_GURTHANG 76 -#define ART_ZARCUTHRA 77 -#define ART_TWILIGHT 78 -#define ART_GONDRICAM 79 -#define ART_CRISDURIAN 80 -#define ART_AGLARANG 81 -#define ART_RINGIL 82 -#define ART_ANDURIL 83 -#define ART_WEREWINDLE 84 -#define ART_CHAINSWORD 85 -#define ART_FORASGIL 86 -#define ART_CARETH 87 -#define ART_STING 88 -#define ART_SOULSWORD 89 -#define ART_MERLIN 90 -#define ART_DOOMCALLER 91 -#define ART_VORPAL_BLADE 92 -#define ART_SLAYER 123 -#define ART_KUSANAGI 128 -#define ART_HURIN 133 -#define ART_AZAGHAL 135 -#define ART_NOVA 137 -#define ART_CHARIOT 140 -#define ART_WORPAL_BLADE 142 -#define ART_MURAMASA 144 -#define ART_ZANTETSU 150 -#define ART_SOULCRUSH 154 -#define ART_FALIS 155 -#define ART_HRUNTING 156 -#define ART_ANUBIS 158 -#define ART_GURENKI 160 -#define ART_TAILBITER 167 -#define ART_MUSASI_KATANA 171 -#define ART_MUSASI_WAKIZASI 172 -#define ART_QUICKTHORN 174 -#define ART_TINYTHORN 175 -#define ART_EXCALIBUR 176 -#define ART_EXCALIPUR 177 -#define ART_EXCALIBUR_J 179 -#define ART_ARUNRUTH 184 -#define ART_HAKABUSA 189 -#define ART_STORMBRINGER 190 -#define ART_NARSIL 191 -#define ART_KANNU 193 -#define ART_GRIMTOOTH 196 -#define ART_KAMUI 198 -#define ART_GOURYU 207 -#define ART_EOWYN 216 -#define ART_NANACHO 248 -#define ART_ROBINTON 251 - -/* Polearms */ -#define ART_THEODEN 93 -#define ART_PAIN 94 -#define ART_OSONDIR 95 -#define ART_TIL 96 -#define ART_RUNESPEAR 97 -#define ART_DESTINY 98 -#define ART_HAGEN 99 -#define ART_EORLINGAS 100 -#define ART_DURIN 101 -#define ART_EONWE 102 -#define ART_BALLI 103 -#define ART_LOTHARANG 104 -#define ART_DWARVES_AXE 105 -#define ART_BARUKKHELED 106 -#define ART_WRATH 107 -#define ART_ULMO 108 -#define ART_AVAVIR 109 -#define ART_BENKEI 152 -#define ART_TAIKOBO 159 -#define ART_TONBO 161 -#define ART_GAEBOLG 163 -#define ART_ARRYU 164 -#define ART_AEGLOS 187 -#define ART_BLOOD 199 -#define ART_NUMAHOKO 202 - -/* The sword of the Dawn */ -#define ART_DAWN 110 - -/* Hafted */ -#define ART_GROND 111 -#define ART_TOTILA 112 -#define ART_THUNDERFIST 113 -#define ART_BLOODSPIKE 114 -#define ART_FIRESTAR 115 -#define ART_TARATOL 116 -#define ART_AULE 117 -#define ART_NAR 118 -#define ART_ERIRIL 119 -#define ART_GANDALF 120 -#define ART_DEATHWREAKER 121 -#define ART_TURMIL 122 -#define ART_MJOLLNIR 136 -#define ART_WINBLOWS 139 -#define ART_XIAOLONG 145 -#define ART_NYOIBOU 157 -#define ART_JONES 162 -#define ART_HYOUSIGI 169 -#define ART_MATOI 170 -#define ART_IRON_BALL 173 -#define ART_SAMSON 178 -#define ART_NAMAKE_HAMMER 181 -#define ART_BOLISHOI 188 -#define ART_SHUTEN_DOJI 194 -#define ART_G_HAMMER 195 -#define ART_AEGISFANG 208 -#define ART_HERMIT 209 -#define ART_GOTHMOG 212 -#define ART_JIZO 213 -#define ART_FUNDIN 214 -#define ART_AESCULAPIUS 225 - -/* Bows */ -#define ART_BELTHRONDING 124 -#define ART_BARD 125 -#define ART_BRAND 126 -#define ART_CRIMSON 16 -#define ART_BUCKLAND 134 -#define ART_YOICHI 148 -#define ART_HARAD 180 -#define ART_NAMAKE_BOW 182 -#define ART_ROBIN_HOOD 221 -#define ART_HELLFIRE 222 - -/* Arrows */ -#define ART_BARD_ARROW 153 - - -/* "Biases" for random artifact gen */ -#define BIAS_ELEC 1 /*!< ランダムアーティファクトバイアス:電撃 */ -#define BIAS_POIS 2 /*!< ランダムアーティファクトバイアス:毒 */ -#define BIAS_FIRE 3 /*!< ランダムアーティファクトバイアス:火炎 */ -#define BIAS_COLD 4 /*!< ランダムアーティファクトバイアス:冷気 */ -#define BIAS_ACID 5 /*!< ランダムアーティファクトバイアス:酸 */ -#define BIAS_STR 6 /*!< ランダムアーティファクトバイアス:腕力 */ -#define BIAS_INT 7 /*!< ランダムアーティファクトバイアス:知力 */ -#define BIAS_WIS 8 /*!< ランダムアーティファクトバイアス:賢さ */ -#define BIAS_DEX 9 /*!< ランダムアーティファクトバイアス:器用さ */ -#define BIAS_CON 10 /*!< ランダムアーティファクトバイアス:耐久 */ -#define BIAS_CHR 11 /*!< ランダムアーティファクトバイアス:魅力 */ -#define BIAS_CHAOS 12 /*!< ランダムアーティファクトバイアス:混沌 */ -#define BIAS_PRIESTLY 13 /*!< ランダムアーティファクトバイアス:プリースト系 */ -#define BIAS_NECROMANTIC 14 /*!< ランダムアーティファクトバイアス:死霊 */ -#define BIAS_LAW 15 /*!< ランダムアーティファクトバイアス:法 */ -#define BIAS_ROGUE 16 /*!< ランダムアーティファクトバイアス:盗賊系 */ -#define BIAS_MAGE 17 /*!< ランダムアーティファクトバイアス:メイジ系 */ -#define BIAS_WARRIOR 18 /*!< ランダムアーティファクトバイアス:戦士系 */ -#define BIAS_RANGER 19 /*!< ランダムアーティファクトバイアス:レンジャー系 */ -#define MAX_BIAS 20 /*!< ランダムアーティファクトバイアス:最大数 */ diff --git a/src/artifact/artifact-info.c b/src/artifact/artifact-info.c new file mode 100644 index 000000000..635d84f7e --- /dev/null +++ b/src/artifact/artifact-info.c @@ -0,0 +1,64 @@ +#include "artifact/artifact-info.h" +#include "art-definition/random-art-effects.h" +#include "cmd-item/cmd-smith.h" +#include "mind/mind-weaponsmith.h" +#include "object-enchant/object-ego.h" +#include "object-enchant/tr-types.h" +#include "object-hook/hook-enchant.h" +#include "object/object-kind.h" +#include "system/artifact-type-definition.h" +#include "system/object-type-definition.h" +#include "util/bit-flags-calculator.h" + +/*! + * @brief オブジェクトから能力発動IDを取得する。 + * @details いくつかのケースで定義されている発動効果から、 + * 鍛冶師による付与>固定アーティファクト>エゴ>ランダムアーティファクト>ベースアイテムの優先順位で走査していく。 + * @param o_ptr 対象のオブジェクト構造体ポインタ + * @return 発動効果のIDを返す + */ +int activation_index(player_type *player_ptr, object_type *o_ptr) +{ + if (object_is_smith(player_ptr, o_ptr)) { + switch (o_ptr->xtra3 - 1) { + case ESSENCE_TMP_RES_ACID: + return ACT_RESIST_ACID; + case ESSENCE_TMP_RES_ELEC: + return ACT_RESIST_ELEC; + case ESSENCE_TMP_RES_FIRE: + return ACT_RESIST_FIRE; + case ESSENCE_TMP_RES_COLD: + return ACT_RESIST_COLD; + case TR_IMPACT: + return ACT_QUAKE; + } + } + + if (object_is_fixed_artifact(o_ptr) && have_flag(a_info[o_ptr->name1].flags, TR_ACTIVATE)) + return a_info[o_ptr->name1].act_idx; + + if (object_is_ego(o_ptr) && have_flag(e_info[o_ptr->name2].flags, TR_ACTIVATE)) + return e_info[o_ptr->name2].act_idx; + + if (!object_is_random_artifact(o_ptr) && have_flag(k_info[o_ptr->k_idx].flags, TR_ACTIVATE)) + return k_info[o_ptr->k_idx].act_idx; + + return o_ptr->xtra2; +} + +/*! + * @brief オブジェクトから発動効果構造体のポインタを取得する。 + * @details activation_index() 関数の結果から参照する。 + * @param o_ptr 対象のオブジェクト構造体ポインタ + * @return 発動効果構造体のポインタを返す + */ +const activation_type *find_activation_info(player_type *player_ptr, object_type *o_ptr) +{ + const int index = activation_index(player_ptr, o_ptr); + const activation_type *p; + for (p = activation_info; p->flag != NULL; ++p) + if (p->index == index) + return p; + + return NULL; +} diff --git a/src/artifact/artifact-info.h b/src/artifact/artifact-info.h new file mode 100644 index 000000000..0c4d141f7 --- /dev/null +++ b/src/artifact/artifact-info.h @@ -0,0 +1,7 @@ +#pragma once + +#include "object-enchant/activation-info-table.h" +#include "system/angband.h" + +int activation_index(player_type *player_ptr, object_type *o_ptr); +const activation_type *find_activation_info(player_type *player_ptr, object_type *o_ptr); diff --git a/src/artifact/fixed-art-generator.c b/src/artifact/fixed-art-generator.c new file mode 100644 index 000000000..3364ded88 --- /dev/null +++ b/src/artifact/fixed-art-generator.c @@ -0,0 +1,332 @@ +/*! + * @brief 固定アーティファクトの生成 / Artifact code + * @date 2020/07/14 + * @author + * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + * 2013 Deskull rearranged comment for Doxygen. + * 2020 Hourier rearranged + */ + +#include "artifact/fixed-art-generator.h" +#include "art-definition/art-armor-types.h" +#include "art-definition/art-protector-types.h" +#include "art-definition/art-sword-types.h" +#include "art-definition/art-weapon-types.h" +#include "floor/floor-object.h" +#include "object-enchant/object-boost.h" +#include "object-enchant/object-curse.h" +#include "object-enchant/tr-types.h" +#include "object-enchant/trc-types.h" +#include "object-enchant/trg-types.h" +#include "object/object-generator.h" +#include "object/object-kind-hook.h" +#include "object/object-kind.h" +#include "specific-object/bloody-moon.h" +#include "system/artifact-type-definition.h" +#include "system/floor-type-definition.h" +#include "system/system-variables.h" +#include "util/bit-flags-calculator.h" + +/*! + * @brief 恐怖の仮面への特殊処理 (一部職業のみ追加能力&耐性、それ以外は反感&太古の怨念) + * @param player_ptr プレーヤーへの参照ポインタ + * @param o_ptr 対象のオブジェクト構造体への参照ポインタ + * @param give_power 追加能力の有無 + * @param give_resistance 追加耐性の有無 + * @return そもそも対象のオブジェクトが恐怖の仮面ではないか、「その他の職業」であればTRUE + */ +static bool invest_terror_mask(player_type *player_ptr, object_type *o_ptr, bool *give_power, bool *give_resistance) +{ + if (o_ptr->name1 != ART_TERROR) + return FALSE; + + bool is_special_class = player_ptr->pclass == CLASS_WARRIOR; + is_special_class |= player_ptr->pclass == CLASS_ARCHER; + is_special_class |= player_ptr->pclass == CLASS_CAVALRY; + is_special_class |= player_ptr->pclass == CLASS_BERSERKER; + if (is_special_class) { + *give_power = TRUE; + *give_resistance = TRUE; + return FALSE; + } + + add_flag(o_ptr->art_flags, TR_AGGRAVATE); + add_flag(o_ptr->art_flags, TR_TY_CURSE); + o_ptr->curse_flags |= (TRC_CURSED | TRC_HEAVY_CURSE); + o_ptr->curse_flags |= get_curse(player_ptr, 2, o_ptr); + return TRUE; +} + +/*! + * @brief 戦乙女ミリムの危ない水着への特殊処理 (セクシーギャルのみpval追加) + * @param player_ptr プレーヤーへの参照ポインタ + * @param o_ptr 対象のオブジェクト構造体への参照ポインタ + * @return なし + */ +static void milim_swimsuit(player_type *player_ptr, object_type *o_ptr) +{ + if ((o_ptr->name1 != ART_MILIM) || (player_ptr->pseikaku != PERSONALITY_SEXY)) + return; + + o_ptr->pval = 3; + add_flag(o_ptr->art_flags, TR_STR); + add_flag(o_ptr->art_flags, TR_INT); + add_flag(o_ptr->art_flags, TR_WIS); + add_flag(o_ptr->art_flags, TR_DEX); + add_flag(o_ptr->art_flags, TR_CON); + add_flag(o_ptr->art_flags, TR_CHR); +} + +/*! + * @brief 固定アーティファクト生成時の特別なハードコーディング処理を行う。. + * @details random_artifact_resistance()とあるが実際は固定アーティファクトである。 + * 対象は恐怖の仮面、村正、ロビントンのハープ、龍争虎鬪、ブラッディムーン、羽衣、天女の羽衣、ミリム、 + * その他追加耐性、特性追加処理。 + * @attention プレイヤーの各種ステータスに依存した処理がある。 + * @todo 折を見て関数名を変更すること。 + * @param player_ptr プレーヤーへの参照ポインタ + * @param o_ptr 対象のオブジェクト構造体ポインタ + * @param a_ptr 生成する固定アーティファクト構造体ポインタ + * @return なし + */ +static void random_artifact_resistance(player_type *player_ptr, object_type *o_ptr, artifact_type *a_ptr) +{ + bool give_power = FALSE; + bool give_resistance = FALSE; + if (invest_terror_mask(player_ptr, o_ptr, &give_power, &give_resistance)) + return; + + if ((o_ptr->name1 == ART_MURAMASA) && (player_ptr->pclass != CLASS_SAMURAI)) { + add_flag(o_ptr->art_flags, TR_NO_MAGIC); + o_ptr->curse_flags |= (TRC_HEAVY_CURSE); + } + + if ((o_ptr->name1 == ART_ROBINTON) && (player_ptr->pclass == CLASS_BARD)) + add_flag(o_ptr->art_flags, TR_DEC_MANA); + + if ((o_ptr->name1 == ART_XIAOLONG) && (player_ptr->pclass == CLASS_MONK)) + add_flag(o_ptr->art_flags, TR_BLOWS); + + if (o_ptr->name1 == ART_BLOOD) + get_bloody_moon_flags(o_ptr); + + if ((o_ptr->name1 == ART_HEAVENLY_MAIDEN) && (player_ptr->psex != SEX_FEMALE)) + add_flag(o_ptr->art_flags, TR_AGGRAVATE); + + milim_swimsuit(player_ptr, o_ptr); + if (a_ptr->gen_flags & TRG_XTRA_POWER) + give_power = TRUE; + + if (a_ptr->gen_flags & TRG_XTRA_H_RES) + give_resistance = TRUE; + + if (a_ptr->gen_flags & TRG_XTRA_RES_OR_POWER) + if (one_in_(2)) + give_resistance = TRUE; + else + give_power = TRUE; + + if (give_power) + one_ability(o_ptr); + + if (give_resistance) + one_high_resistance(o_ptr); +} + +static void invest_curse_to_fixed_artifact(player_type *player_ptr, artifact_type *a_ptr, object_type *q_ptr) +{ + if (a_ptr->gen_flags & TRG_CURSED) + q_ptr->curse_flags |= TRC_CURSED; + + if (a_ptr->gen_flags & TRG_HEAVY_CURSE) + q_ptr->curse_flags |= TRC_HEAVY_CURSE; + + if (a_ptr->gen_flags & TRG_PERMA_CURSE) + q_ptr->curse_flags |= TRC_PERMA_CURSE; + + if (a_ptr->gen_flags & TRG_RANDOM_CURSE0) + q_ptr->curse_flags |= get_curse(player_ptr, 0, q_ptr); + + if (a_ptr->gen_flags & TRG_RANDOM_CURSE1) + q_ptr->curse_flags |= get_curse(player_ptr, 1, q_ptr); + + if (a_ptr->gen_flags & TRG_RANDOM_CURSE2) + q_ptr->curse_flags |= get_curse(player_ptr, 2, q_ptr); +} + +/*! + * @brief フロアの指定された位置に固定アーティファクトを生成する。 / Create the artifact of the specified number + * @details 固定アーティファクト構造体から基本ステータスをコピーした後、所定の座標でdrop_item()で落とす。 + * @param player_ptr プレーヤーへの参照ポインタ + * @param a_idx 生成する固定アーティファクト構造体のID + * @param y アイテムを落とす地点のy座標 + * @param x アイテムを落とす地点のx座標 + * @return 生成が成功したか否か、失敗はIDの不全、ベースアイテムの不全、drop_item()の失敗時に起こる。 + * @attention この処理はdrop_near()内で普通の固定アーティファクトが重ならない性質に依存する. + * 仮に2個以上存在可能かつ装備品以外の固定アーティファクトが作成されれば + * drop_near()関数の返り値は信用できなくなる. + */ +bool create_named_art(player_type *player_ptr, ARTIFACT_IDX a_idx, POSITION y, POSITION x) +{ + artifact_type *a_ptr = &a_info[a_idx]; + if (!a_ptr->name) + return FALSE; + + KIND_OBJECT_IDX i = lookup_kind(a_ptr->tval, a_ptr->sval); + if (i == 0) + return FALSE; + + object_type forge; + object_type *q_ptr; + q_ptr = &forge; + object_prep(player_ptr, q_ptr, i); + q_ptr->name1 = a_idx; + q_ptr->pval = a_ptr->pval; + q_ptr->ac = a_ptr->ac; + q_ptr->dd = a_ptr->dd; + q_ptr->ds = a_ptr->ds; + q_ptr->to_a = a_ptr->to_a; + q_ptr->to_h = a_ptr->to_h; + q_ptr->to_d = a_ptr->to_d; + q_ptr->weight = a_ptr->weight; + invest_curse_to_fixed_artifact(player_ptr, a_ptr, q_ptr); + random_artifact_resistance(player_ptr, q_ptr, a_ptr); + return drop_near(player_ptr, q_ptr, -1, y, x) ? TRUE : FALSE; +} + +/*! + * @brief 非INSTA_ART型の固定アーティファクトの生成を確率に応じて試行する。 + * Mega-Hack -- Attempt to create one of the "Special Objects" + * @param player_ptr プレーヤーへの参照ポインタ + * @param o_ptr 生成に割り当てたいオブジェクトの構造体参照ポインタ + * @return 生成に成功したらTRUEを返す。 + * @details + * Attempt to change an object into an artifact\n + * This routine should only be called by "apply_magic()"\n + * Note -- see "make_artifact_special()" and "apply_magic()"\n + */ +bool make_artifact(player_type *player_ptr, object_type *o_ptr) +{ + floor_type *floor_ptr = player_ptr->current_floor_ptr; + if (floor_ptr->dun_level == 0) + return FALSE; + + if (o_ptr->number != 1) + return FALSE; + + for (ARTIFACT_IDX i = 0; i < max_a_idx; i++) { + artifact_type *a_ptr = &a_info[i]; + if (!a_ptr->name) + continue; + + if (a_ptr->cur_num) + continue; + + if (a_ptr->gen_flags & TRG_QUESTITEM) + continue; + + if (a_ptr->gen_flags & TRG_INSTA_ART) + continue; + + if (a_ptr->tval != o_ptr->tval) + continue; + + if (a_ptr->sval != o_ptr->sval) + continue; + + if (a_ptr->level > floor_ptr->dun_level) { + int d = (a_ptr->level - floor_ptr->dun_level) * 2; + if (!one_in_(d)) + continue; + } + + if (!one_in_(a_ptr->rarity)) + continue; + + o_ptr->name1 = i; + random_artifact_resistance(player_ptr, o_ptr, a_ptr); + return TRUE; + } + + return FALSE; +} + +/*! + * @brief INSTA_ART型の固定アーティファクトの生成を確率に応じて試行する。 + * Mega-Hack -- Attempt to create one of the "Special Objects" + * @param player_ptr プレーヤーへの参照ポインタ + * @param o_ptr 生成に割り当てたいオブジェクトの構造体参照ポインタ + * @return 生成に成功したらTRUEを返す。 + * @details + * We are only called from "make_object()", and we assume that\n + * "apply_magic()" is called immediately after we return.\n + *\n + * Note -- see "make_artifact()" and "apply_magic()"\n + */ +bool make_artifact_special(player_type *player_ptr, object_type *o_ptr) +{ + KIND_OBJECT_IDX k_idx = 0; + + /*! @note 地上ではキャンセルする / No artifacts in the town */ + floor_type *floor_ptr = player_ptr->current_floor_ptr; + if (floor_ptr->dun_level == 0) + return FALSE; + + /*! @note get_obj_num_hookによる指定がある場合は生成をキャンセルする / Themed object */ + if (get_obj_num_hook) + return FALSE; + + /*! @note 全固定アーティファクト中からIDの若い順に生成対象とその確率を走査する / Check the artifact list (just the "specials") */ + for (ARTIFACT_IDX i = 0; i < max_a_idx; i++) { + artifact_type *a_ptr = &a_info[i]; + + /*! @note アーティファクト名が空の不正なデータは除外する / Skip "empty" artifacts */ + if (!a_ptr->name) + continue; + + /*! @note 既に生成回数がカウントされたアーティファクト、QUESTITEMと非INSTA_ARTは除外 / Cannot make an artifact twice */ + if (a_ptr->cur_num) + continue; + if (a_ptr->gen_flags & TRG_QUESTITEM) + continue; + if (!(a_ptr->gen_flags & TRG_INSTA_ART)) + continue; + + /*! @note アーティファクト生成階が現在に対して足りない場合は高確率で1/(不足階層*2)を満たさないと生成リストに加えられない / + * XXX XXX Enforce minimum "depth" (loosely) */ + if (a_ptr->level > floor_ptr->object_level) { + /* @note / Acquire the "out-of-depth factor". Roll for out-of-depth creation. */ + int d = (a_ptr->level - floor_ptr->object_level) * 2; + if (!one_in_(d)) + continue; + } + + /*! @note 1/(レア度)の確率を満たさないと除外される / Artifact "rarity roll" */ + if (!one_in_(a_ptr->rarity)) + continue; + + /*! @note INSTA_ART型固定アーティファクトのベースアイテムもチェック対象とする。ベースアイテムの生成階層が足りない場合1/(不足階層*5) + * を満たさないと除外される。 / Find the base object. XXX XXX Enforce minimum "object" level (loosely). Acquire the "out-of-depth factor". Roll for + * out-of-depth creation. */ + k_idx = lookup_kind(a_ptr->tval, a_ptr->sval); + if (k_info[k_idx].level > floor_ptr->object_level) { + int d = (k_info[k_idx].level - floor_ptr->object_level) * 5; + if (!one_in_(d)) + continue; + } + + /*! @note 前述の条件を満たしたら、後のIDのアーティファクトはチェックせずすぐ確定し生成処理に移す / + * Assign the template. Mega-Hack -- mark the item as an artifact. Hack: Some artifacts get random extra powers. Success. */ + object_prep(player_ptr, o_ptr, k_idx); + + o_ptr->name1 = i; + random_artifact_resistance(player_ptr, o_ptr, a_ptr); + return TRUE; + } + + /*! @note 全INSTA_ART固定アーティファクトを試行しても決まらなかった場合 FALSEを返す / Failure */ + return FALSE; +} diff --git a/src/artifact/fixed-art-generator.h b/src/artifact/fixed-art-generator.h new file mode 100644 index 000000000..b439d3dd2 --- /dev/null +++ b/src/artifact/fixed-art-generator.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +bool create_named_art(player_type *player_ptr, ARTIFACT_IDX a_idx, POSITION y, POSITION x); +bool make_artifact(player_type *player_ptr, object_type *o_ptr); +bool make_artifact_special(player_type *player_ptr, object_type *o_ptr); diff --git a/src/artifact/random-art-activation.c b/src/artifact/random-art-activation.c new file mode 100644 index 000000000..0403ced59 --- /dev/null +++ b/src/artifact/random-art-activation.c @@ -0,0 +1,235 @@ +#include "artifact/random-art-activation.h" +#include "art-definition/random-art-effects.h" +#include "artifact/random-art-bias-types.h" +#include "object-enchant/object-boost.h" +#include "object-enchant/tr-types.h" +#include "system/object-type-definition.h" +#include "util/bit-flags-calculator.h" + +static int invest_activation_elec(void) +{ + if (!one_in_(3)) + return ACT_BO_ELEC_1; + + if (!one_in_(5)) + return ACT_BA_ELEC_2; + + return ACT_BA_ELEC_3; +} + +static int invest_activation_fire(void) +{ + if (!one_in_(3)) + return ACT_BO_FIRE_1; + + if (!one_in_(5)) + return ACT_BA_FIRE_1; + + return ACT_BA_FIRE_2; +} + +static int invest_activation_cold(void) +{ + if (!one_in_(3)) + return ACT_BO_COLD_1; + + if (!one_in_(3)) + return ACT_BA_COLD_1; + + if (!one_in_(3)) + return ACT_BA_COLD_2; + + return ACT_BA_COLD_3; +} + +static int invest_activation_chaos(void) { return one_in_(6) ? ACT_SUMMON_DEMON : ACT_CALL_CHAOS; } + +static int invest_activation_priest(void) +{ + if (one_in_(13)) + return ACT_CHARM_UNDEAD; + + if (one_in_(12)) + return ACT_BANISH_EVIL; + + if (one_in_(11)) + return ACT_DISP_EVIL; + + if (one_in_(10)) + return ACT_PROT_EVIL; + + if (one_in_(9)) + return ACT_CURE_1000; + + if (one_in_(8)) + return ACT_CURE_700; + + if (one_in_(7)) + return ACT_REST_ALL; + + if (one_in_(6)) + return ACT_REST_EXP; + + return ACT_CURE_MW; +} + +static int invest_activation_necromancy(void) +{ + if (one_in_(66)) + return ACT_WRAITH; + + if (one_in_(13)) + return ACT_DISP_GOOD; + + if (one_in_(9)) + return ACT_MASS_GENO; + + if (one_in_(8)) + return ACT_GENOCIDE; + + if (one_in_(13)) + return ACT_SUMMON_UNDEAD; + + if (one_in_(9)) + return ACT_DRAIN_2; + + if (one_in_(6)) + return ACT_CHARM_UNDEAD; + + return ACT_DRAIN_1; +} + +static int invest_activation_law(void) +{ + if (one_in_(8)) + return ACT_BANISH_EVIL; + + if (one_in_(4)) + return ACT_DISP_EVIL; + + return ACT_PROT_EVIL; +} + +static int invest_activation_rogue(void) +{ + if (one_in_(50)) + return ACT_SPEED; + + if (one_in_(4)) + return ACT_SLEEP; + + if (one_in_(3)) + return ACT_DETECT_ALL; + + if (one_in_(8)) + return ACT_ID_FULL; + + return ACT_ID_PLAIN; +} + +static int invest_activation_mage(void) +{ + if (one_in_(20)) + return ACT_SUMMON_ELEMENTAL; + + if (one_in_(10)) + return ACT_SUMMON_PHANTOM; + + if (one_in_(5)) + return ACT_RUNE_EXPLO; + + return ACT_ESP; +} + +static int invest_activation_warrior(void) { return one_in_(100) ? ACT_INVULN : ACT_BERSERK; } + +static int invest_activation_ranger(void) +{ + if (one_in_(20)) + return ACT_CHARM_ANIMALS; + + if (one_in_(7)) + return ACT_SUMMON_ANIMAL; + + if (one_in_(6)) + return ACT_CHARM_ANIMAL; + + if (one_in_(4)) + return ACT_RESIST_ALL; + + if (one_in_(3)) + return ACT_SATIATE; + + return ACT_CURE_POISON; +} + +/*! + * @brief ランダムアーティファクト生成中、対象のオブジェクトにバイアスに依存した発動を与える。/ Add one activaton of randam artifact depend on bias. + * @details バイアスが無い場合、一部のバイアスの確率によっては one_ability() に処理が移行する。 + * @param o_ptr 対象のオブジェクト構造体ポインタ + * @return なし + */ +void give_activation_power(object_type *o_ptr) +{ + int type = 0; + int chance = 0; + switch (o_ptr->artifact_bias) { + case BIAS_ELEC: + type = invest_activation_elec(); + chance = 101; + break; + case BIAS_POIS: + type = ACT_BA_POIS_1; + chance = 101; + break; + case BIAS_FIRE: + type = invest_activation_fire(); + chance = 101; + break; + case BIAS_COLD: + type = invest_activation_cold(); + chance = 101; + break; + case BIAS_CHAOS: + type = invest_activation_chaos(); + chance = 50; + break; + case BIAS_PRIESTLY: + type = invest_activation_priest(); + chance = 101; + break; + case BIAS_NECROMANTIC: + type = invest_activation_necromancy(); + chance = 101; + break; + case BIAS_LAW: + type = invest_activation_law(); + chance = 101; + break; + case BIAS_ROGUE: + type = invest_activation_rogue(); + chance = 101; + break; + case BIAS_MAGE: + type = invest_activation_mage(); + chance = 66; + break; + case BIAS_WARRIOR: + type = invest_activation_warrior(); + chance = 80; + break; + case BIAS_RANGER: + type = invest_activation_ranger(); + chance = 101; + break; + } + + if (!type || (randint1(100) >= chance)) { + one_activation(o_ptr); + return; + } + + o_ptr->xtra2 = (byte)type; + add_flag(o_ptr->art_flags, TR_ACTIVATE); + o_ptr->timeout = 0; +} diff --git a/src/artifact/random-art-activation.h b/src/artifact/random-art-activation.h new file mode 100644 index 000000000..6fd292688 --- /dev/null +++ b/src/artifact/random-art-activation.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void give_activation_power(object_type *o_ptr); diff --git a/src/artifact/random-art-bias-types.h b/src/artifact/random-art-bias-types.h new file mode 100644 index 000000000..8943a3c5c --- /dev/null +++ b/src/artifact/random-art-bias-types.h @@ -0,0 +1,25 @@ +#pragma once + +typedef enum random_art_bias_type { + BIAS_NONE = 0, + BIAS_ELEC = 1, /*!< ランダムアーティファクトバイアス:電撃 */ + BIAS_POIS = 2, /*!< ランダムアーティファクトバイアス:毒 */ + BIAS_FIRE = 3, /*!< ランダムアーティファクトバイアス:火炎 */ + BIAS_COLD = 4, /*!< ランダムアーティファクトバイアス:冷気 */ + BIAS_ACID = 5, /*!< ランダムアーティファクトバイアス:酸 */ + BIAS_STR = 6, /*!< ランダムアーティファクトバイアス:腕力 */ + BIAS_INT = 7, /*!< ランダムアーティファクトバイアス:知力 */ + BIAS_WIS = 8, /*!< ランダムアーティファクトバイアス:賢さ */ + BIAS_DEX = 9, /*!< ランダムアーティファクトバイアス:器用さ */ + BIAS_CON = 10, /*!< ランダムアーティファクトバイアス:耐久 */ + BIAS_CHR = 11, /*!< ランダムアーティファクトバイアス:魅力 */ + BIAS_CHAOS = 12, /*!< ランダムアーティファクトバイアス:混沌 */ + BIAS_PRIESTLY = 13, /*!< ランダムアーティファクトバイアス:プリースト系 */ + BIAS_NECROMANTIC = 14, /*!< ランダムアーティファクトバイアス:死霊 */ + BIAS_LAW = 15, /*!< ランダムアーティファクトバイアス:法 */ + BIAS_ROGUE = 16, /*!< ランダムアーティファクトバイアス:盗賊系 */ + BIAS_MAGE = 17, /*!< ランダムアーティファクトバイアス:メイジ系 */ + BIAS_WARRIOR = 18, /*!< ランダムアーティファクトバイアス:戦士系 */ + BIAS_RANGER = 19, /*!< ランダムアーティファクトバイアス:レンジャー系 */ + MAX_BIAS = 20, /*!< ランダムアーティファクトバイアス:最大数 */ +} random_art_bias_type; diff --git a/src/artifact/random-art-characteristics.c b/src/artifact/random-art-characteristics.c new file mode 100644 index 000000000..84921274f --- /dev/null +++ b/src/artifact/random-art-characteristics.c @@ -0,0 +1,226 @@ +#include "artifact/random-art-characteristics.h" +#include "flavor/object-flavor.h" +#include "game-option/cheat-types.h" +#include "io/files-util.h" +#include "object-enchant/tr-types.h" +#include "object-enchant/trc-types.h" +#include "object/object-flags.h" +#include "system/object-type-definition.h" +#include "util/bit-flags-calculator.h" +#include "wizard/wizard-messages.h" + +static void pval_subtraction(object_type *o_ptr) +{ + if (o_ptr->pval > 0) + o_ptr->pval = 0 - (o_ptr->pval + randint1(4)); + + if (o_ptr->to_a > 0) + o_ptr->to_a = 0 - (o_ptr->to_a + randint1(4)); + + if (o_ptr->to_h > 0) + o_ptr->to_h = 0 - (o_ptr->to_h + randint1(4)); + + if (o_ptr->to_d > 0) + o_ptr->to_d = 0 - (o_ptr->to_d + randint1(4)); +} + +static void add_negative_flags(object_type *o_ptr) +{ + if (one_in_(4)) + o_ptr->curse_flags |= TRC_PERMA_CURSE; + + if (one_in_(3)) + add_flag(o_ptr->art_flags, TR_TY_CURSE); + + if (one_in_(2)) + add_flag(o_ptr->art_flags, TR_AGGRAVATE); + + if (one_in_(3)) + add_flag(o_ptr->art_flags, TR_DRAIN_EXP); + + if (one_in_(6)) + add_flag(o_ptr->art_flags, TR_ADD_L_CURSE); + + if (one_in_(9)) + add_flag(o_ptr->art_flags, TR_ADD_H_CURSE); + + if (one_in_(9)) + add_flag(o_ptr->art_flags, TR_DRAIN_HP); + + if (one_in_(9)) + add_flag(o_ptr->art_flags, TR_DRAIN_MANA); + + if (one_in_(2)) + add_flag(o_ptr->art_flags, TR_TELEPORT); + else if (one_in_(3)) + add_flag(o_ptr->art_flags, TR_NO_TELE); +} + +/*! + * @brief ランダムアーティファクト生成中、対象のオブジェクトを呪いのアーティファクトにする経過処理。/ generation process of cursed artifact. + * @details pval、AC、命中、ダメージが正の場合、符号反転の上1d4だけ悪化させ、重い呪い、呪いフラグを必ず付加。 + * 祝福を無効。確率に応じて、永遠の呪い、太古の怨念、経験値吸収、弱い呪いの継続的付加、強い呪いの継続的付加、HP吸収の呪い、 + * MP吸収の呪い、乱テレポート、反テレポート、反魔法をつける。 + * @attention プレイヤーの職業依存処理あり。 + * @param player_ptr プレーヤーへの参照ポインタ + * @param o_ptr 対象のオブジェクト構造体ポインタ + * @return なし + */ +void curse_artifact(player_type *player_ptr, object_type *o_ptr) +{ + pval_subtraction(o_ptr); + o_ptr->curse_flags |= (TRC_HEAVY_CURSE | TRC_CURSED); + remove_flag(o_ptr->art_flags, TR_BLESSED); + add_negative_flags(o_ptr); + if ((player_ptr->pclass != CLASS_WARRIOR) && (player_ptr->pclass != CLASS_ARCHER) && (player_ptr->pclass != CLASS_CAVALRY) + && (player_ptr->pclass != CLASS_BERSERKER) && (player_ptr->pclass != CLASS_SMITH) && one_in_(3)) + add_flag(o_ptr->art_flags, TR_NO_MAGIC); +} + +/*! + * @brief ランダムアーティファクトの名前リストをオブジェクト種別と生成パワーに応じて選択する + * @param armour 防具かどうか + * @param power 生成パワー + * @return ファイル名 + * @details 二重switch文だが短いので執行猶予とする + */ +static concptr get_random_art_filename(const bool armour, const int power) +{ + concptr filename; + switch (armour) { + case 1: + switch (power) { + case 0: + filename = _("a_cursed_j.txt", "a_cursed.txt"); + break; + case 1: + filename = _("a_low_j.txt", "a_low.txt"); + break; + case 2: + filename = _("a_med_j.txt", "a_med.txt"); + break; + default: + filename = _("a_high_j.txt", "a_high.txt"); + } + break; + default: + switch (power) { + case 0: + filename = _("w_cursed_j.txt", "w_cursed.txt"); + break; + case 1: + filename = _("w_low_j.txt", "w_low.txt"); + break; + case 2: + filename = _("w_med_j.txt", "w_med.txt"); + break; + default: + filename = _("w_high_j.txt", "w_high.txt"); + } + } + + return filename; +} + +/*! + * @brief ランダムアーティファクト生成中、対象のオブジェクトに名前を与える。/ Set name of randomartifact. + * @details 確率によって、シンダリン銘、漢字銘、固定名のいずれか一つが与えられる。 + * @param o_ptr 処理中のアイテム参照ポインタ + * @param return_name 名前を返すための文字列参照ポインタ + * @param armour 対象のオブジェクトが防具が否か + * @param power 銘の基準となるオブジェクトの価値レベル(0=呪い、1=低位、2=中位、3以上=高位) + * @return なし + */ +void get_random_name(object_type *o_ptr, char *return_name, bool armour, int power) +{ + PERCENTAGE prob = randint1(100); + if (prob <= SINDARIN_NAME) { + get_table_sindarin(return_name); + return; + } + + if (prob <= TABLE_NAME) { + get_table_name(return_name); + return; + } + + concptr filename = get_random_art_filename(armour, power); + (void)get_rnd_line(filename, o_ptr->artifact_bias, return_name); +#ifdef JP + if (return_name[0] == 0) + get_table_name(return_name); +#endif +} + +/*対邪平均ダメージの計算処理*/ +static HIT_POINT calc_arm_avgdamage(player_type *player_ptr, object_type *o_ptr) +{ + BIT_FLAGS flgs[TR_FLAG_SIZE]; + object_flags(player_ptr, o_ptr, flgs); + HIT_POINT base, forced, vorpal; + HIT_POINT s_evil = forced = vorpal = 0; + HIT_POINT dam = base = (o_ptr->dd * o_ptr->ds + o_ptr->dd) / 2; + if (have_flag(flgs, TR_KILL_EVIL)) { + dam = s_evil = dam * 7 / 2; + } else if (!have_flag(flgs, TR_KILL_EVIL) && have_flag(flgs, TR_SLAY_EVIL)) { + dam = s_evil = dam * 2; + } else + s_evil = dam; + + if (have_flag(flgs, TR_FORCE_WEAPON)) { + dam = forced = dam * 3 / 2 + (o_ptr->dd * o_ptr->ds + o_ptr->dd); + } else + forced = dam; + + if (have_flag(flgs, TR_VORPAL)) { + dam = vorpal = dam * 11 / 9; + } else + vorpal = dam; + + dam = dam + o_ptr->to_d; + msg_format_wizard(player_ptr, CHEAT_OBJECT, "ç´ :%d> 対邪:%d> 理力:%d> 切:%d> 最終:%d", base, s_evil, forced, vorpal, dam); + return dam; +} + +bool has_extreme_damage_rate(player_type *player_ptr, object_type *o_ptr) +{ + BIT_FLAGS flgs[TR_FLAG_SIZE]; + object_flags(player_ptr, o_ptr, flgs); + if (have_flag(flgs, TR_VAMPIRIC)) { + if (have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 1) && (calc_arm_avgdamage(player_ptr, o_ptr) > 52)) { + return TRUE; + } + + if (have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 2) && (calc_arm_avgdamage(player_ptr, o_ptr) > 43)) { + return TRUE; + } + + if (have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 3) && (calc_arm_avgdamage(player_ptr, o_ptr) > 33)) { + return TRUE; + } + + if (calc_arm_avgdamage(player_ptr, o_ptr) > 63) { + return TRUE; + } + + return FALSE; + } + + if (have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 1) && (calc_arm_avgdamage(player_ptr, o_ptr) > 65)) { + return TRUE; + } + + if (have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 2) && (calc_arm_avgdamage(player_ptr, o_ptr) > 52)) { + return TRUE; + } + + if (have_flag(flgs, TR_BLOWS) && (o_ptr->pval == 3) && (calc_arm_avgdamage(player_ptr, o_ptr) > 40)) { + return TRUE; + } + + if (calc_arm_avgdamage(player_ptr, o_ptr) > 75) { + return TRUE; + } + + return FALSE; +} diff --git a/src/artifact/random-art-characteristics.h b/src/artifact/random-art-characteristics.h new file mode 100644 index 000000000..ee6f1b502 --- /dev/null +++ b/src/artifact/random-art-characteristics.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +void curse_artifact(player_type *player_ptr, object_type *o_ptr); +void get_random_name(object_type *o_ptr, char *return_name, bool armour, int power); +bool has_extreme_damage_rate(player_type *player_ptr, object_type *o_ptr); diff --git a/src/artifact/random-art-generator.c b/src/artifact/random-art-generator.c new file mode 100644 index 000000000..a17423b70 --- /dev/null +++ b/src/artifact/random-art-generator.c @@ -0,0 +1,438 @@ +/*! + * @brief ランダムアーティファクトの生成 / Artifact code + * @date 2020/07/14 + * @author Hourier + */ + +#include "artifact/random-art-generator.h" +#include "artifact/random-art-activation.h" +#include "artifact/random-art-bias-types.h" +#include "artifact/random-art-characteristics.h" +#include "artifact/random-art-misc.h" +#include "artifact/random-art-pval-investor.h" +#include "artifact/random-art-resistance.h" +#include "artifact/random-art-slay.h" +#include "core/asking-player.h" +#include "core/window-redrawer.h" +#include "flavor/object-flavor.h" +#include "game-option/cheat-types.h" +#include "object-enchant/special-object-flags.h" +#include "object-enchant/tr-types.h" +#include "object-hook/hook-armor.h" +#include "object-hook/hook-checker.h" +#include "object-hook/hook-weapon.h" +#include "object/object-flags.h" +#include "object/object-kind-hook.h" +#include "object/object-kind.h" +#include "object/object-value-calc.h" +#include "perception/identification.h" +#include "perception/object-perception.h" +#include "player-info/avatar.h" +#include "sv-definition/sv-weapon-types.h" +#include "util/bit-flags-calculator.h" +#include "util/quarks.h" +#include "view/display-messages.h" +#include "wizard/artifact-bias-table.h" +#include "wizard/wizard-messages.h" +#include "world/world.h" + +static bool weakening_artifact(player_type *player_ptr, object_type *o_ptr) +{ + KIND_OBJECT_IDX k_idx = lookup_kind(o_ptr->tval, o_ptr->sval); + object_kind *k_ptr = &k_info[k_idx]; + BIT_FLAGS flgs[TR_FLAG_SIZE]; + object_flags(player_ptr, o_ptr, flgs); + + if (have_flag(flgs, TR_KILL_EVIL)) { + remove_flag(o_ptr->art_flags, TR_KILL_EVIL); + add_flag(o_ptr->art_flags, TR_SLAY_EVIL); + return TRUE; + } + + if (k_ptr->dd < o_ptr->dd) { + o_ptr->dd--; + return TRUE; + } + + if (k_ptr->ds < o_ptr->ds) { + o_ptr->ds--; + return TRUE; + } + + if (o_ptr->to_d > 10) { + o_ptr->to_d = o_ptr->to_d - damroll(1, 6); + if (o_ptr->to_d < 10) { + o_ptr->to_d = 10; + } + + return TRUE; + } + + return FALSE; +} + +static void set_artifact_bias(player_type *player_ptr, object_type *o_ptr, int *warrior_artifact_bias) +{ + switch (player_ptr->pclass) { + case CLASS_WARRIOR: + case CLASS_BERSERKER: + case CLASS_ARCHER: + case CLASS_SAMURAI: + case CLASS_CAVALRY: + case CLASS_SMITH: + o_ptr->artifact_bias = BIAS_WARRIOR; + break; + case CLASS_MAGE: + case CLASS_HIGH_MAGE: + case CLASS_SORCERER: + case CLASS_MAGIC_EATER: + case CLASS_BLUE_MAGE: + o_ptr->artifact_bias = BIAS_MAGE; + break; + case CLASS_PRIEST: + o_ptr->artifact_bias = BIAS_PRIESTLY; + break; + case CLASS_ROGUE: + case CLASS_NINJA: + o_ptr->artifact_bias = BIAS_ROGUE; + *warrior_artifact_bias = 25; + break; + case CLASS_RANGER: + case CLASS_SNIPER: + o_ptr->artifact_bias = BIAS_RANGER; + *warrior_artifact_bias = 30; + break; + case CLASS_PALADIN: + o_ptr->artifact_bias = BIAS_PRIESTLY; + *warrior_artifact_bias = 40; + break; + case CLASS_WARRIOR_MAGE: + case CLASS_RED_MAGE: + o_ptr->artifact_bias = BIAS_MAGE; + *warrior_artifact_bias = 40; + break; + case CLASS_CHAOS_WARRIOR: + o_ptr->artifact_bias = BIAS_CHAOS; + *warrior_artifact_bias = 40; + break; + case CLASS_MONK: + case CLASS_FORCETRAINER: + o_ptr->artifact_bias = BIAS_PRIESTLY; + break; + case CLASS_MINDCRAFTER: + case CLASS_BARD: + if (randint1(5) > 2) + o_ptr->artifact_bias = BIAS_PRIESTLY; + break; + case CLASS_TOURIST: + if (randint1(5) > 2) + o_ptr->artifact_bias = BIAS_WARRIOR; + break; + case CLASS_IMITATOR: + if (randint1(2) > 1) + o_ptr->artifact_bias = BIAS_RANGER; + break; + case CLASS_BEASTMASTER: + o_ptr->artifact_bias = BIAS_CHR; + *warrior_artifact_bias = 50; + break; + case CLASS_MIRROR_MASTER: + if (randint1(4) > 1) + o_ptr->artifact_bias = BIAS_MAGE; + else + o_ptr->artifact_bias = BIAS_ROGUE; + + break; + } +} + +static void decide_warrior_bias(player_type *player_ptr, object_type *o_ptr, const bool a_scroll) +{ + int warrior_artifact_bias = 0; + if (a_scroll && one_in_(4)) + set_artifact_bias(player_ptr, o_ptr, &warrior_artifact_bias); + + if (a_scroll && (randint1(100) <= warrior_artifact_bias)) + o_ptr->artifact_bias = BIAS_WARRIOR; +} + +static bool decide_random_art_cursed(const bool a_scroll, object_type *o_ptr) +{ + if (!a_scroll && one_in_(A_CURSED)) + return TRUE; + + if (((o_ptr->tval == TV_AMULET) || (o_ptr->tval == TV_RING)) && object_is_cursed(o_ptr)) + return TRUE; + + return FALSE; +} + +static int decide_random_art_power(const bool a_cursed) +{ + int powers = randint1(5) + 1; + while (one_in_(powers) || one_in_(7) || one_in_(10)) + powers++; + + if (!a_cursed && one_in_(WEIRD_LUCK)) + powers *= 2; + + if (a_cursed) + powers /= 2; + + return powers; +} + +static void invest_powers(player_type *player_ptr, object_type *o_ptr, int *powers, bool *has_pval, const bool a_cursed) +{ + int max_type = object_is_weapon_ammo(o_ptr) ? 7 : 5; + while ((*powers)--) { + switch (randint1(max_type)) { + case 1: + case 2: + random_plus(o_ptr); + *has_pval = TRUE; + break; + case 3: + case 4: + if (one_in_(2) && object_is_weapon_ammo(o_ptr) && (o_ptr->tval != TV_BOW)) { + if (a_cursed && !one_in_(13)) + break; + if (one_in_(13)) { + if (one_in_(o_ptr->ds + 4)) + o_ptr->ds++; + } else { + if (one_in_(o_ptr->dd + 1)) + o_ptr->dd++; + } + } else + random_resistance(o_ptr); + + break; + case 5: + random_misc(player_ptr, o_ptr); + break; + case 6: + case 7: + random_slay(o_ptr); + break; + default: + if (current_world_ptr->wizard) + msg_print("Switch error in become_random_artifact!"); + + (*powers)++; + } + }; +} + +static void strengthen_pval(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_BLOWS)) { + o_ptr->pval = randint1(2); + if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_HAYABUSA)) + o_ptr->pval++; + } else { + do { + o_ptr->pval++; + } while (o_ptr->pval < randint1(5) || one_in_(o_ptr->pval)); + } + + if ((o_ptr->pval > 4) && !one_in_(WEIRD_LUCK)) + o_ptr->pval = 4; +} + +/*! + * @brief 防具ならばAC修正、武具なら殺戮修正を付与する + * @param player_ptr プレーヤーへの参照ポインタ + * @param o_ptr ランダムアーティファクトを示すアイテムへの参照ポインタ + * @return なし + */ +static void invest_positive_modified_value(player_type *player_ptr, object_type *o_ptr) +{ + if (object_is_armour(player_ptr, o_ptr)) { + o_ptr->to_a += randint1(o_ptr->to_a > 19 ? 1 : 20 - o_ptr->to_a); + return; + } + + if (!object_is_weapon_ammo(o_ptr)) + return; + + o_ptr->to_h += randint1(o_ptr->to_h > 19 ? 1 : 20 - o_ptr->to_h); + o_ptr->to_d += randint1(o_ptr->to_d > 19 ? 1 : 20 - o_ptr->to_d); + if ((have_flag(o_ptr->art_flags, TR_WIS)) && (o_ptr->pval > 0)) + add_flag(o_ptr->art_flags, TR_BLESSED); +} + +/*! + * @brief 防具のAC修正が高すぎた場合に弱化させる + * @param player_ptr プレーヤーへの参照ポインタ + * @param o_ptr ランダムアーティファクトを示すアイテムへの参照ポインタ + * @return なし + */ +static void invest_negative_modified_value(player_type *player_ptr, object_type *o_ptr) +{ + if (!object_is_armour(player_ptr, o_ptr)) + return; + + while ((o_ptr->to_d + o_ptr->to_h) > 20) { + if (one_in_(o_ptr->to_d) && one_in_(o_ptr->to_h)) + break; + + o_ptr->to_d -= (HIT_POINT)randint0(3); + o_ptr->to_h -= (HIT_PROB)randint0(3); + } + + while ((o_ptr->to_d + o_ptr->to_h) > 10) { + if (one_in_(o_ptr->to_d) || one_in_(o_ptr->to_h)) + break; + + o_ptr->to_d -= (HIT_POINT)randint0(3); + o_ptr->to_h -= (HIT_PROB)randint0(3); + } +} + +static void reset_flags_poison_needle(object_type *o_ptr) +{ + if ((o_ptr->tval != TV_SWORD) || (o_ptr->sval != SV_POISON_NEEDLE)) + return; + + o_ptr->to_h = 0; + o_ptr->to_d = 0; + remove_flag(o_ptr->art_flags, TR_BLOWS); + remove_flag(o_ptr->art_flags, TR_FORCE_WEAPON); + remove_flag(o_ptr->art_flags, TR_SLAY_ANIMAL); + remove_flag(o_ptr->art_flags, TR_SLAY_EVIL); + remove_flag(o_ptr->art_flags, TR_SLAY_UNDEAD); + remove_flag(o_ptr->art_flags, TR_SLAY_DEMON); + remove_flag(o_ptr->art_flags, TR_SLAY_ORC); + remove_flag(o_ptr->art_flags, TR_SLAY_TROLL); + remove_flag(o_ptr->art_flags, TR_SLAY_GIANT); + remove_flag(o_ptr->art_flags, TR_SLAY_DRAGON); + remove_flag(o_ptr->art_flags, TR_KILL_DRAGON); + remove_flag(o_ptr->art_flags, TR_SLAY_HUMAN); + remove_flag(o_ptr->art_flags, TR_VORPAL); + remove_flag(o_ptr->art_flags, TR_BRAND_POIS); + remove_flag(o_ptr->art_flags, TR_BRAND_ACID); + remove_flag(o_ptr->art_flags, TR_BRAND_ELEC); + remove_flag(o_ptr->art_flags, TR_BRAND_FIRE); + remove_flag(o_ptr->art_flags, TR_BRAND_COLD); +} + +static int decide_random_art_power_level(object_type *o_ptr, const bool a_cursed, const int total_flags) +{ + if (object_is_weapon_ammo(o_ptr)) { + if (a_cursed) + return 0; + + if (total_flags < 20000) + return 1; + + if (total_flags < 45000) + return 2; + + return 3; + } + + if (a_cursed) + return 0; + + if (total_flags < 15000) + return 1; + + if (total_flags < 35000) + return 2; + + return 3; +} + +static void name_unnatural_random_artifact(player_type *player_ptr, object_type *o_ptr, const bool a_scroll, const int power_level, GAME_TEXT *new_name) +{ + if (!a_scroll) { + get_random_name(o_ptr, new_name, object_is_armour(player_ptr, o_ptr), power_level); + return; + } + + GAME_TEXT dummy_name[MAX_NLEN] = ""; + concptr ask_msg = _("このアーティファクトを何と名付けますか?", "What do you want to call the artifact? "); + object_aware(player_ptr, o_ptr); + object_known(o_ptr); + o_ptr->ident |= IDENT_FULL_KNOWN; + o_ptr->art_name = quark_add(""); + (void)screen_object(player_ptr, o_ptr, 0L); + if (!get_string(ask_msg, dummy_name, sizeof dummy_name) || !dummy_name[0]) { + if (one_in_(2)) { + get_table_sindarin_aux(dummy_name); + } else { + get_table_name_aux(dummy_name); + } + } + + sprintf(new_name, _("《%s》", "'%s'"), dummy_name); + chg_virtue(player_ptr, V_INDIVIDUALISM, 2); + chg_virtue(player_ptr, V_ENCHANT, 5); +} + +static void generate_unnatural_random_artifact(player_type *player_ptr, object_type *o_ptr, const bool a_scroll, const int power_level, const int max_powers, const int total_flags) +{ + GAME_TEXT new_name[1024]; + strcpy(new_name, ""); + name_unnatural_random_artifact(player_ptr, o_ptr, a_scroll, power_level, new_name); + o_ptr->art_name = quark_add(new_name); + msg_format_wizard(player_ptr, CHEAT_OBJECT, + _("パワー %d で 価値%ld のランダムアーティファクト生成 バイアスは「%s」", "Random artifact generated - Power:%d Value:%d Bias:%s."), max_powers, + total_flags, artifact_bias_name[o_ptr->artifact_bias]); + player_ptr->window |= PW_INVEN | PW_EQUIP; +} + +/*! + * @brief ランダムアーティファクト生成のメインルーチン + * @details 既に生成が済んでいるオブジェクトの構造体を、アーティファクトとして強化する。 + * @param player_ptr プレーヤーへの参照ポインタ + * @param o_ptr 対象のオブジェクト構造体ポインタ + * @param a_scroll アーティファクト生成の巻物上の処理。呪いのアーティファクトが生成対象外となる。 + * @return 常にTRUE(1)を返す + */ +bool become_random_artifact(player_type *player_ptr, object_type *o_ptr, bool a_scroll) +{ + o_ptr->artifact_bias = 0; + o_ptr->name1 = 0; + o_ptr->name2 = 0; + for (int i = 0; i < TR_FLAG_SIZE; i++) + o_ptr->art_flags[i] |= k_info[o_ptr->k_idx].flags[i]; + + bool has_pval = o_ptr->pval != 0; + decide_warrior_bias(player_ptr, o_ptr, a_scroll); + + bool a_cursed = decide_random_art_cursed(a_scroll, o_ptr); + int powers = decide_random_art_power(a_cursed); + int max_powers = powers; + invest_powers(player_ptr, o_ptr, &powers, &has_pval, a_cursed); + if (has_pval) + strengthen_pval(o_ptr); + + invest_positive_modified_value(player_ptr, o_ptr); + add_flag(o_ptr->art_flags, TR_IGNORE_ACID); + add_flag(o_ptr->art_flags, TR_IGNORE_ELEC); + add_flag(o_ptr->art_flags, TR_IGNORE_FIRE); + add_flag(o_ptr->art_flags, TR_IGNORE_COLD); + + s32b total_flags = flag_cost(player_ptr, o_ptr, o_ptr->pval); + if (a_cursed) + curse_artifact(player_ptr, o_ptr); + + if (!a_cursed && one_in_(object_is_armour(player_ptr, o_ptr) ? ACTIVATION_CHANCE * 2 : ACTIVATION_CHANCE)) { + o_ptr->xtra2 = 0; + give_activation_power(o_ptr); + } + + invest_negative_modified_value(player_ptr, o_ptr); + if (((o_ptr->artifact_bias == BIAS_MAGE) || (o_ptr->artifact_bias == BIAS_INT)) && (o_ptr->tval == TV_GLOVES)) + add_flag(o_ptr->art_flags, TR_FREE_ACT); + + reset_flags_poison_needle(o_ptr); + int power_level = decide_random_art_power_level(o_ptr, a_cursed, total_flags); + while (has_extreme_damage_rate(player_ptr, o_ptr) && !one_in_(SWORDFISH_LUCK)) + weakening_artifact(player_ptr, o_ptr); + + generate_unnatural_random_artifact(player_ptr, o_ptr, a_scroll, power_level, max_powers, total_flags); + return TRUE; +} diff --git a/src/artifact/random-art-generator.h b/src/artifact/random-art-generator.h new file mode 100644 index 000000000..8508d6bac --- /dev/null +++ b/src/artifact/random-art-generator.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool become_random_artifact(player_type *player_ptr, object_type *o_ptr, bool a_scroll); diff --git a/src/artifact/random-art-misc.c b/src/artifact/random-art-misc.c new file mode 100644 index 000000000..ee35cb1d5 --- /dev/null +++ b/src/artifact/random-art-misc.c @@ -0,0 +1,344 @@ +#include "artifact/random-art-misc.h" +#include "artifact/random-art-bias-types.h" +#include "object-enchant/tr-types.h" +#include "object-hook/hook-armor.h" +#include "system/object-type-definition.h" +#include "util/bit-flags-calculator.h" + +static bool invest_misc_ranger(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SUST_CON)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SUST_CON); + return one_in_(2); +} + +static bool invest_misc_strength(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SUST_STR)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SUST_STR); + return one_in_(2); +} + +static bool invest_misc_wisdom(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SUST_WIS)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SUST_WIS); + return one_in_(2); +} + +static bool invest_misc_intelligence(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SUST_INT)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SUST_INT); + return one_in_(2); +} + +static bool invest_misc_dexterity(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SUST_DEX)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SUST_DEX); + return one_in_(2); +} + +static bool invest_misc_constitution(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SUST_CON)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SUST_CON); + return one_in_(2); +} + +static bool invest_misc_charisma(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SUST_CHR)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SUST_CHR); + return one_in_(2); +} + +static bool invest_misc_chaos(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_TELEPORT)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_TELEPORT); + return one_in_(2); +} + +/*! + * @brief アーティファクトのバイアス値に基づいて特性を付与する + * @param o_ptr 対象のオブジェクト構造体への参照ポインタ + * @return 処理続行ならFALSE、打ち切るならTRUE + */ +static bool switch_misc_bias(object_type *o_ptr) +{ + switch (o_ptr->artifact_bias) { + case BIAS_RANGER: + return invest_misc_ranger(o_ptr); + case BIAS_STR: + return invest_misc_strength(o_ptr); + case BIAS_INT: + return invest_misc_intelligence(o_ptr); + case BIAS_WIS: + return invest_misc_wisdom(o_ptr); + case BIAS_DEX: + return invest_misc_dexterity(o_ptr); + case BIAS_CON: + return invest_misc_constitution(o_ptr); + case BIAS_CHR: + return invest_misc_charisma(o_ptr); + case BIAS_CHAOS: + return invest_misc_chaos(o_ptr); + case BIAS_FIRE: + if (!(have_flag(o_ptr->art_flags, TR_LITE_1))) + add_flag(o_ptr->art_flags, TR_LITE_1); + + return FALSE; + default: + return FALSE; + } +} + +static void invest_misc_hit_dice(object_type *o_ptr) +{ + add_flag(o_ptr->art_flags, TR_SHOW_MODS); + HIT_PROB bonus_h = 4 + (HIT_PROB)randint1(11); + HIT_POINT bonus_d = 4 + (HIT_POINT)randint1(11); + if ((o_ptr->tval != TV_SWORD) && (o_ptr->tval != TV_POLEARM) && (o_ptr->tval != TV_HAFTED) && (o_ptr->tval != TV_DIGGING) && (o_ptr->tval != TV_GLOVES) + && (o_ptr->tval != TV_RING)) { + bonus_h /= 2; + bonus_d /= 2; + } + + o_ptr->to_h += bonus_h; + o_ptr->to_d += bonus_d; +} + +static void invest_misc_string_esp(object_type *o_ptr) +{ + switch (randint1(3)) { + case 1: + add_flag(o_ptr->art_flags, TR_ESP_EVIL); + if (!o_ptr->artifact_bias && one_in_(3)) + o_ptr->artifact_bias = BIAS_LAW; + + return; + case 2: + add_flag(o_ptr->art_flags, TR_ESP_NONLIVING); + if (!o_ptr->artifact_bias && one_in_(3)) + o_ptr->artifact_bias = BIAS_MAGE; + + return; + case 3: + add_flag(o_ptr->art_flags, TR_TELEPATHY); + if (!o_ptr->artifact_bias && one_in_(9)) + o_ptr->artifact_bias = BIAS_MAGE; + + return; + } +} + +static void switch_investment_weak_esps(object_type *o_ptr, const int *idx, const int n) +{ + switch (idx[n]) { + case 1: + add_flag(o_ptr->art_flags, TR_ESP_ANIMAL); + if (!o_ptr->artifact_bias && one_in_(4)) + o_ptr->artifact_bias = BIAS_RANGER; + + break; + case 2: + add_flag(o_ptr->art_flags, TR_ESP_UNDEAD); + if (!o_ptr->artifact_bias && one_in_(3)) + o_ptr->artifact_bias = BIAS_PRIESTLY; + else if (!o_ptr->artifact_bias && one_in_(6)) + o_ptr->artifact_bias = BIAS_NECROMANTIC; + + break; + case 3: + add_flag(o_ptr->art_flags, TR_ESP_DEMON); + break; + case 4: + add_flag(o_ptr->art_flags, TR_ESP_ORC); + break; + case 5: + add_flag(o_ptr->art_flags, TR_ESP_TROLL); + break; + case 6: + add_flag(o_ptr->art_flags, TR_ESP_GIANT); + break; + case 7: + add_flag(o_ptr->art_flags, TR_ESP_DRAGON); + break; + case 8: + add_flag(o_ptr->art_flags, TR_ESP_HUMAN); + if (!o_ptr->artifact_bias && one_in_(6)) + o_ptr->artifact_bias = BIAS_ROGUE; + + break; + case 9: + add_flag(o_ptr->art_flags, TR_ESP_GOOD); + if (!o_ptr->artifact_bias && one_in_(3)) + o_ptr->artifact_bias = BIAS_LAW; + + break; + case 10: + add_flag(o_ptr->art_flags, TR_ESP_UNIQUE); + if (!o_ptr->artifact_bias && one_in_(3)) + o_ptr->artifact_bias = BIAS_LAW; + + break; + } +} + +static void invest_misc_weak_esps(object_type *o_ptr) +{ + int idx[3]; + idx[0] = randint1(10); + idx[1] = randint1(9); + if (idx[1] >= idx[0]) + idx[1]++; + + idx[2] = randint1(8); + if (idx[2] >= idx[0]) + idx[2]++; + + if (idx[2] >= idx[1]) + idx[2]++; + + int n = randint1(3); + while (n--) + switch_investment_weak_esps(o_ptr, idx, n); +} + +/*! + * @brief ランダムアーティファクト生成中、対象のオブジェクトにその他特性を付加する。/ Add one misc flag on generation of randam artifact. + * @details 優先的に付加される耐性がランダムアーティファクトバイアスに依存して存在する。 + * 原則的候補は各種能力維持、永久光源+1、麻痺知らず、経験値維持、浮遊、透明視、急回復、遅消化、 + * 乱テレポート、反魔法、反テレポート、警告、テレパシー、各種ESP、一部装備に殺戮修正。 + * @attention オブジェクトのtval、svalに依存したハードコーディング処理がある。 + * @param o_ptr 対象のオブジェクト構造体ポインタ + * @return なし + */ +void random_misc(player_type *player_ptr, object_type *o_ptr) +{ + if (switch_misc_bias(o_ptr)) + return; + + switch (randint1(33)) { + case 1: + add_flag(o_ptr->art_flags, TR_SUST_STR); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_STR; + + break; + case 2: + add_flag(o_ptr->art_flags, TR_SUST_INT); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_INT; + + break; + case 3: + add_flag(o_ptr->art_flags, TR_SUST_WIS); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_WIS; + + break; + case 4: + add_flag(o_ptr->art_flags, TR_SUST_DEX); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_DEX; + + break; + case 5: + add_flag(o_ptr->art_flags, TR_SUST_CON); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_CON; + + break; + case 6: + add_flag(o_ptr->art_flags, TR_SUST_CHR); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_CHR; + + break; + case 7: + case 8: + case 14: + add_flag(o_ptr->art_flags, TR_FREE_ACT); + break; + case 9: + add_flag(o_ptr->art_flags, TR_HOLD_EXP); + if (!o_ptr->artifact_bias && one_in_(5)) + o_ptr->artifact_bias = BIAS_PRIESTLY; + else if (!o_ptr->artifact_bias && one_in_(6)) + o_ptr->artifact_bias = BIAS_NECROMANTIC; + + break; + case 10: + case 11: + add_flag(o_ptr->art_flags, TR_LITE_1); + break; + case 12: + case 13: + add_flag(o_ptr->art_flags, TR_LEVITATION); + break; + case 15: + case 16: + case 17: + add_flag(o_ptr->art_flags, TR_SEE_INVIS); + break; + case 19: + case 20: + add_flag(o_ptr->art_flags, TR_SLOW_DIGEST); + break; + case 21: + case 22: + add_flag(o_ptr->art_flags, TR_REGEN); + break; + case 23: + add_flag(o_ptr->art_flags, TR_TELEPORT); + break; + case 24: + case 25: + case 26: + if (object_is_armour(player_ptr, o_ptr)) + random_misc(player_ptr, o_ptr); + else + o_ptr->to_a = 4 + randint1(11); + + break; + case 27: + case 28: + case 29: + invest_misc_hit_dice(o_ptr); + break; + case 30: + add_flag(o_ptr->art_flags, TR_NO_MAGIC); + break; + case 31: + add_flag(o_ptr->art_flags, TR_NO_TELE); + break; + case 32: + add_flag(o_ptr->art_flags, TR_WARNING); + break; + case 18: + invest_misc_string_esp(o_ptr); + break; + case 33: + invest_misc_weak_esps(o_ptr); + break; + } +} diff --git a/src/artifact/random-art-misc.h b/src/artifact/random-art-misc.h new file mode 100644 index 000000000..174495a16 --- /dev/null +++ b/src/artifact/random-art-misc.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void random_misc(player_type *player_ptr, object_type *o_ptr); diff --git a/src/artifact/random-art-pval-investor.c b/src/artifact/random-art-pval-investor.c new file mode 100644 index 000000000..113be3d53 --- /dev/null +++ b/src/artifact/random-art-pval-investor.c @@ -0,0 +1,243 @@ +/*! + * @brief ランダムアーティファクトにpvalを追加する処理 + * @date 2020/07/14 + * @author Hourier + */ + +#include "artifact/random-art-pval-investor.h" +#include "artifact/random-art-bias-types.h" +#include "object-enchant/tr-types.h" +#include "object-hook/hook-weapon.h" +#include "sv-definition/sv-armor-types.h" +#include "system/object-type-definition.h" +#include "util/bit-flags-calculator.h" + +static bool random_art_bias_strength(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_STR)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_STR); + return one_in_(2); +} + +static bool random_art_bias_intelligence(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_INT)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_INT); + return one_in_(2); +} + +static bool random_art_bias_wisdom(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_WIS)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_WIS); + return one_in_(2); +} + +static bool random_art_bias_dexterity(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_DEX)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_DEX); + return one_in_(2); +} + +static bool random_art_bias_constitution(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_CON)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_CON); + return one_in_(2); +} + +static bool random_art_bias_charisma(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_CHR)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_CHR); + return one_in_(2); +} + +static bool random_art_bias_magic_mastery(object_type *o_ptr) +{ + if ((o_ptr->tval != TV_GLOVES) || have_flag(o_ptr->art_flags, TR_MAGIC_MASTERY)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_MAGIC_MASTERY); + return one_in_(2); +} + +static bool random_art_bias_stealth(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_STEALTH)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_STEALTH); + return one_in_(2); +} + +static bool random_art_bias_search(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SEARCH)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SEARCH); + return one_in_(2); +} + +static bool switch_random_art_bias(object_type *o_ptr) +{ + switch (o_ptr->artifact_bias) { + case BIAS_WARRIOR: + return random_art_bias_strength(o_ptr) || random_art_bias_constitution(o_ptr) || random_art_bias_dexterity(o_ptr); + case BIAS_MAGE: + return random_art_bias_intelligence(o_ptr) || random_art_bias_magic_mastery(o_ptr); + case BIAS_RANGER: + return random_art_bias_dexterity(o_ptr) || random_art_bias_constitution(o_ptr) || random_art_bias_strength(o_ptr); + case BIAS_ROGUE: + return random_art_bias_stealth(o_ptr) || random_art_bias_search(o_ptr); + case BIAS_STR: + return random_art_bias_strength(o_ptr); + case BIAS_INT: + return random_art_bias_intelligence(o_ptr); + case BIAS_PRIESTLY: + case BIAS_WIS: + return random_art_bias_wisdom(o_ptr); + case BIAS_DEX: + return random_art_bias_dexterity(o_ptr); + case BIAS_CON: + return random_art_bias_constitution(o_ptr); + case BIAS_CHR: + return random_art_bias_charisma(o_ptr); + default: + return FALSE; + } +} + +static bool random_art_bias_decrease_mana(object_type *o_ptr) +{ + if (((o_ptr->artifact_bias != BIAS_MAGE) && (o_ptr->artifact_bias != BIAS_PRIESTLY)) || (o_ptr->tval != TV_SOFT_ARMOR) || (o_ptr->sval != SV_ROBE) + || have_flag(o_ptr->art_flags, TR_DEC_MANA) || !one_in_(3)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_DEC_MANA); + return one_in_(2); +} + +/*! + * @brief ランダムアーティファクト生成中、対象のオブジェクトにpval能力を付加する。/ Add one pval on generation of randam artifact. + * @details 優先的に付加されるpvalがランダムアーティファクトバイアスに依存して存在する。 + * 原則的候補は腕力、知力、賢さ、器用さ、耐久、魅力、探索、隠密、赤外線視力、加速。武器のみ採掘、追加攻撃も候補に入る。 + * @attention オブジェクトのtval、svalに依存したハードコーディング処理がある。 + * @param o_ptr 対象のオブジェクト構造体ポインタ + * @return なし + */ +void random_plus(object_type *o_ptr) +{ + if (switch_random_art_bias(o_ptr) || random_art_bias_decrease_mana(o_ptr)) + return; + + int this_type = object_is_weapon_ammo(o_ptr) ? 23 : 19; + switch (randint1(this_type)) { + case 1: + case 2: + add_flag(o_ptr->art_flags, TR_STR); + if (!o_ptr->artifact_bias && !one_in_(13)) + o_ptr->artifact_bias = BIAS_STR; + else if (!o_ptr->artifact_bias && one_in_(7)) + o_ptr->artifact_bias = BIAS_WARRIOR; + + break; + case 3: + case 4: + add_flag(o_ptr->art_flags, TR_INT); + if (!o_ptr->artifact_bias && !one_in_(13)) + o_ptr->artifact_bias = BIAS_INT; + else if (!o_ptr->artifact_bias && one_in_(7)) + o_ptr->artifact_bias = BIAS_MAGE; + + break; + case 5: + case 6: + add_flag(o_ptr->art_flags, TR_WIS); + if (!o_ptr->artifact_bias && !one_in_(13)) + o_ptr->artifact_bias = BIAS_WIS; + else if (!o_ptr->artifact_bias && one_in_(7)) + o_ptr->artifact_bias = BIAS_PRIESTLY; + + break; + case 7: + case 8: + add_flag(o_ptr->art_flags, TR_DEX); + if (!o_ptr->artifact_bias && !one_in_(13)) + o_ptr->artifact_bias = BIAS_DEX; + else if (!o_ptr->artifact_bias && one_in_(7)) + o_ptr->artifact_bias = BIAS_ROGUE; + + break; + case 9: + case 10: + add_flag(o_ptr->art_flags, TR_CON); + if (!o_ptr->artifact_bias && !one_in_(13)) + o_ptr->artifact_bias = BIAS_CON; + else if (!o_ptr->artifact_bias && one_in_(9)) + o_ptr->artifact_bias = BIAS_RANGER; + + break; + case 11: + case 12: + add_flag(o_ptr->art_flags, TR_CHR); + if (!o_ptr->artifact_bias && !one_in_(13)) + o_ptr->artifact_bias = BIAS_CHR; + + break; + case 13: + case 14: + add_flag(o_ptr->art_flags, TR_STEALTH); + if (!o_ptr->artifact_bias && one_in_(3)) + o_ptr->artifact_bias = BIAS_ROGUE; + + break; + case 15: + case 16: + add_flag(o_ptr->art_flags, TR_SEARCH); + if (!o_ptr->artifact_bias && one_in_(9)) + o_ptr->artifact_bias = BIAS_RANGER; + + break; + case 17: + case 18: + add_flag(o_ptr->art_flags, TR_INFRA); + break; + case 19: + add_flag(o_ptr->art_flags, TR_SPEED); + if (!o_ptr->artifact_bias && one_in_(11)) + o_ptr->artifact_bias = BIAS_ROGUE; + + break; + case 20: + case 21: + add_flag(o_ptr->art_flags, TR_TUNNEL); + break; + case 22: + case 23: + if (o_ptr->tval == TV_BOW) { + random_plus(o_ptr); + break; + } + + add_flag(o_ptr->art_flags, TR_BLOWS); + if (!o_ptr->artifact_bias && one_in_(11)) + o_ptr->artifact_bias = BIAS_WARRIOR; + + break; + } +} diff --git a/src/artifact/random-art-pval-investor.h b/src/artifact/random-art-pval-investor.h new file mode 100644 index 000000000..98db36043 --- /dev/null +++ b/src/artifact/random-art-pval-investor.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" + +typedef struct object_type object_type; +void random_plus(object_type *o_ptr); diff --git a/src/artifact/random-art-resistance.c b/src/artifact/random-art-resistance.c new file mode 100644 index 000000000..503adae28 --- /dev/null +++ b/src/artifact/random-art-resistance.c @@ -0,0 +1,473 @@ +#include "artifact/random-art-resistance.h" +#include "artifact/random-art-bias-types.h" +#include "object-enchant/tr-types.h" +#include "system/object-type-definition.h" +#include "util/bit-flags-calculator.h" + +static bool random_art_resistance_acid(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_RES_ACID)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_RES_ACID); + return one_in_(2); +} + +static bool random_art_immunity_acid(object_type *o_ptr) +{ + if (!one_in_(BIAS_LUCK) || have_flag(o_ptr->art_flags, TR_IM_ACID)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_IM_ACID); + if (one_in_(IM_LUCK)) + return one_in_(2); + + remove_flag(o_ptr->art_flags, TR_IM_ELEC); + remove_flag(o_ptr->art_flags, TR_IM_COLD); + remove_flag(o_ptr->art_flags, TR_IM_FIRE); + return one_in_(2); +} + +static bool random_art_resistance_elec(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_RES_ELEC)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_RES_ELEC); + return one_in_(2); +} + +static bool random_art_aura_elec(object_type *o_ptr) +{ + if ((o_ptr->tval < TV_CLOAK) || (o_ptr->tval > TV_HARD_ARMOR) || have_flag(o_ptr->art_flags, TR_SH_ELEC)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SH_ELEC); + return one_in_(2); +} + +static bool random_art_immunity_elec(object_type *o_ptr) +{ + if (!one_in_(BIAS_LUCK) || have_flag(o_ptr->art_flags, TR_IM_ELEC)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_IM_ELEC); + if (one_in_(IM_LUCK)) + return one_in_(2); + + remove_flag(o_ptr->art_flags, TR_IM_ACID); + remove_flag(o_ptr->art_flags, TR_IM_COLD); + remove_flag(o_ptr->art_flags, TR_IM_FIRE); + return one_in_(2); +} + +static bool random_art_resistance_fire(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_RES_FIRE)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_RES_FIRE); + return one_in_(2); +} + +static bool random_art_aura_fire(object_type *o_ptr) +{ + if ((o_ptr->tval < TV_CLOAK) || (o_ptr->tval > TV_HARD_ARMOR) || have_flag(o_ptr->art_flags, TR_SH_FIRE)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SH_FIRE); + return one_in_(2); +} + +static bool random_art_immunity_fire(object_type *o_ptr) +{ + if (!one_in_(BIAS_LUCK) || have_flag(o_ptr->art_flags, TR_IM_FIRE)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_IM_FIRE); + if (one_in_(IM_LUCK)) + return one_in_(2); + + remove_flag(o_ptr->art_flags, TR_IM_ELEC); + remove_flag(o_ptr->art_flags, TR_IM_COLD); + remove_flag(o_ptr->art_flags, TR_IM_ACID); + return one_in_(2); +} + +static bool random_art_resistance_cold(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_RES_COLD)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_RES_COLD); + return one_in_(2); +} + +static bool random_art_aura_cold(object_type *o_ptr) +{ + if ((o_ptr->tval < TV_CLOAK) || (o_ptr->tval > TV_HARD_ARMOR) || have_flag(o_ptr->art_flags, TR_SH_COLD)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SH_COLD); + return one_in_(2); +} + +static bool random_art_immunity_cold(object_type *o_ptr) +{ + if (!one_in_(BIAS_LUCK) || have_flag(o_ptr->art_flags, TR_IM_COLD)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_IM_COLD); + if (one_in_(IM_LUCK)) + return one_in_(2); + + remove_flag(o_ptr->art_flags, TR_IM_ELEC); + remove_flag(o_ptr->art_flags, TR_IM_COLD); + remove_flag(o_ptr->art_flags, TR_IM_ACID); + return one_in_(2); +} + +static bool random_art_resistance_pois(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_RES_POIS)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_RES_POIS); + return one_in_(2); +} + +static bool random_art_resistance_fear(object_type *o_ptr) +{ + if (one_in_(3) || have_flag(o_ptr->art_flags, TR_RES_FEAR)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_RES_FEAR); + return one_in_(2); +} + +static bool random_art_resistance_no_magic(object_type *o_ptr) +{ + if (!one_in_(3) || have_flag(o_ptr->art_flags, TR_NO_MAGIC)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_NO_MAGIC); + return one_in_(2); +} + +static bool random_art_resistance_nether(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_RES_NETHER)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_RES_NETHER); + return one_in_(2); +} + +static bool random_art_resistance_dark(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_RES_DARK)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_RES_DARK); + return one_in_(2); +} + +static bool random_art_resistance_chaos(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_RES_CHAOS)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_RES_CHAOS); + return one_in_(2); +} + +static bool random_art_resistance_confusion(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_RES_CONF)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_RES_CONF); + return one_in_(2); +} + +static bool random_art_resistance_disenchant(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_RES_DISEN)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_RES_DISEN); + return one_in_(2); +} + +static bool switch_random_art_resistance(object_type *o_ptr) +{ + switch (o_ptr->artifact_bias) { + case BIAS_ACID: + return random_art_resistance_acid(o_ptr) || random_art_immunity_acid(o_ptr); + case BIAS_ELEC: + return random_art_resistance_elec(o_ptr) || random_art_aura_elec(o_ptr) || random_art_immunity_elec(o_ptr); + case BIAS_FIRE: + return random_art_resistance_fire(o_ptr) || random_art_aura_fire(o_ptr) || random_art_immunity_fire(o_ptr); + case BIAS_COLD: + return random_art_resistance_cold(o_ptr) || random_art_aura_cold(o_ptr) || random_art_immunity_cold(o_ptr); + case BIAS_POIS: + return random_art_resistance_pois(o_ptr); + case BIAS_WARRIOR: + return random_art_resistance_fear(o_ptr) || random_art_resistance_no_magic(o_ptr); + case BIAS_NECROMANTIC: + return random_art_resistance_nether(o_ptr) || random_art_resistance_pois(o_ptr) || random_art_resistance_dark(o_ptr); + case BIAS_CHAOS: + return random_art_resistance_chaos(o_ptr) || random_art_resistance_confusion(o_ptr) || random_art_resistance_disenchant(o_ptr); + default: + return FALSE; + } +} + +/* 一定確率で再試行する */ +static void set_weird_bias_acid(object_type *o_ptr) +{ + if (!one_in_(WEIRD_LUCK)) { + random_resistance(o_ptr); + return; + } + + add_flag(o_ptr->art_flags, TR_IM_ACID); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_ACID; +} + +/* 一定確率で再試行する */ +static void set_weird_bias_elec(object_type *o_ptr) +{ + if (!one_in_(WEIRD_LUCK)) { + random_resistance(o_ptr); + return; + } + + add_flag(o_ptr->art_flags, TR_IM_ELEC); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_ELEC; +} + +/* 一定確率で再試行する */ +static void set_weird_bias_cold(object_type *o_ptr) +{ + if (!one_in_(WEIRD_LUCK)) { + random_resistance(o_ptr); + return; + } + + add_flag(o_ptr->art_flags, TR_IM_COLD); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_COLD; +} + +/* 一定確率で再試行する */ +static void set_weird_bias_fire(object_type *o_ptr) +{ + if (!one_in_(WEIRD_LUCK)) { + random_resistance(o_ptr); + return; + } + + add_flag(o_ptr->art_flags, TR_IM_FIRE); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_FIRE; +} + +static void set_bias_pois(object_type *o_ptr) +{ + add_flag(o_ptr->art_flags, TR_RES_POIS); + if (!o_ptr->artifact_bias && !one_in_(4)) { + o_ptr->artifact_bias = BIAS_POIS; + return; + } + + if (!o_ptr->artifact_bias && one_in_(2)) { + o_ptr->artifact_bias = BIAS_NECROMANTIC; + return; + } + + if (!o_ptr->artifact_bias && one_in_(2)) + o_ptr->artifact_bias = BIAS_ROGUE; +} + +/* 一定確率で再試行する */ +static void set_weird_bias_aura_elec(object_type *o_ptr) +{ + if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR) + add_flag(o_ptr->art_flags, TR_SH_ELEC); + else + random_resistance(o_ptr); + + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_ELEC; +} + +/* 一定確率で再試行する */ +static void set_weird_bias_aura_fire(object_type *o_ptr) +{ + if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR) + add_flag(o_ptr->art_flags, TR_SH_FIRE); + else + random_resistance(o_ptr); + + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_FIRE; +} + +/* 一定確率で再試行する */ +static void set_weird_bias_reflection(object_type *o_ptr) +{ + if (o_ptr->tval == TV_SHIELD || o_ptr->tval == TV_CLOAK || o_ptr->tval == TV_HELM || o_ptr->tval == TV_HARD_ARMOR) { + add_flag(o_ptr->art_flags, TR_REFLECT); + return; + } + + random_resistance(o_ptr); +} + +/* 一定確率で再試行する */ +static void set_weird_bias_aura_cold(object_type *o_ptr) +{ + if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR) + add_flag(o_ptr->art_flags, TR_SH_COLD); + else + random_resistance(o_ptr); + + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_COLD; +} + +/*! + * @brief ランダムアーティファクト生成中、対象のオブジェクトに耐性を付加する。/ Add one resistance on generation of randam artifact. + * @details 優先的に付加される耐性がランダムアーティファクトバイアスに依存して存在する。 + * 原則的候補は火炎、冷気、電撃、酸(以上免疫の可能性もあり)、 + * 毒、閃光、暗黒、破片、轟音、盲目、混乱、地獄、カオス、劣化、恐怖、火オーラ、冷気オーラ、電撃オーラ、反射。 + * 戦士系バイアスのみ反魔もつく。 + * @attention オブジェクトのtval、svalに依存したハードコーディング処理がある。 + * @param o_ptr 対象のオブジェクト構造体ポインタ + * @return なし + */ +void random_resistance(object_type *o_ptr) +{ + if (switch_random_art_resistance(o_ptr)) + return; + + switch (randint1(42)) { + case 1: + set_weird_bias_acid(o_ptr); + break; + case 2: + set_weird_bias_elec(o_ptr); + break; + case 3: + set_weird_bias_cold(o_ptr); + break; + case 4: + set_weird_bias_fire(o_ptr); + break; + case 5: + case 6: + case 13: + add_flag(o_ptr->art_flags, TR_RES_ACID); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_ACID; + + break; + case 7: + case 8: + case 14: + add_flag(o_ptr->art_flags, TR_RES_ELEC); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_ELEC; + + break; + case 9: + case 10: + case 15: + add_flag(o_ptr->art_flags, TR_RES_FIRE); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_FIRE; + + break; + case 11: + case 12: + case 16: + add_flag(o_ptr->art_flags, TR_RES_COLD); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_COLD; + + break; + case 17: + case 18: + set_bias_pois(o_ptr); + break; + case 19: + case 20: + add_flag(o_ptr->art_flags, TR_RES_FEAR); + if (!o_ptr->artifact_bias && one_in_(3)) + o_ptr->artifact_bias = BIAS_WARRIOR; + + break; + case 21: + add_flag(o_ptr->art_flags, TR_RES_LITE); + break; + case 22: + add_flag(o_ptr->art_flags, TR_RES_DARK); + break; + case 23: + case 24: + add_flag(o_ptr->art_flags, TR_RES_BLIND); + break; + case 25: + case 26: + add_flag(o_ptr->art_flags, TR_RES_CONF); + if (!o_ptr->artifact_bias && one_in_(6)) + o_ptr->artifact_bias = BIAS_CHAOS; + + break; + case 27: + case 28: + add_flag(o_ptr->art_flags, TR_RES_SOUND); + break; + case 29: + case 30: + add_flag(o_ptr->art_flags, TR_RES_SHARDS); + break; + case 31: + case 32: + add_flag(o_ptr->art_flags, TR_RES_NETHER); + if (!o_ptr->artifact_bias && one_in_(3)) + o_ptr->artifact_bias = BIAS_NECROMANTIC; + + break; + case 33: + case 34: + add_flag(o_ptr->art_flags, TR_RES_NEXUS); + break; + case 35: + case 36: + add_flag(o_ptr->art_flags, TR_RES_CHAOS); + if (!o_ptr->artifact_bias && one_in_(2)) + o_ptr->artifact_bias = BIAS_CHAOS; + + break; + case 37: + case 38: + add_flag(o_ptr->art_flags, TR_RES_DISEN); + break; + case 39: + set_weird_bias_aura_elec(o_ptr); + break; + case 40: + set_weird_bias_aura_fire(o_ptr); + break; + case 41: + set_weird_bias_reflection(o_ptr); + break; + case 42: + set_weird_bias_aura_cold(o_ptr); + break; + } +} diff --git a/src/artifact/random-art-resistance.h b/src/artifact/random-art-resistance.h new file mode 100644 index 000000000..a6d787565 --- /dev/null +++ b/src/artifact/random-art-resistance.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void random_resistance(object_type *o_ptr); diff --git a/src/artifact/random-art-slay.c b/src/artifact/random-art-slay.c new file mode 100644 index 000000000..efbc49f48 --- /dev/null +++ b/src/artifact/random-art-slay.c @@ -0,0 +1,354 @@ +#include "artifact/random-art-slay.h" +#include "artifact/random-art-bias-types.h" +#include "object-enchant/tr-types.h" +#include "sv-definition/sv-weapon-types.h" +#include "system/object-type-definition.h" +#include "util/bit-flags-calculator.h" + +static bool random_art_slay_bow(object_type *o_ptr) +{ + if (o_ptr->tval != TV_BOW) + return FALSE; + + switch (randint1(6)) { + case 1: + case 2: + case 3: + add_flag(o_ptr->art_flags, TR_XTRA_MIGHT); + if (!one_in_(7)) + remove_flag(o_ptr->art_flags, TR_XTRA_SHOTS); + + if ((o_ptr->artifact_bias == BIAS_NONE) && one_in_(9)) + o_ptr->artifact_bias = BIAS_RANGER; + + return TRUE; + default: + add_flag(o_ptr->art_flags, TR_XTRA_SHOTS); + if (!one_in_(7)) + remove_flag(o_ptr->art_flags, TR_XTRA_MIGHT); + + if ((o_ptr->artifact_bias == BIAS_NONE) && one_in_(9)) + o_ptr->artifact_bias = BIAS_RANGER; + + return TRUE; + } +} + +static bool random_art_slay_chaos(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_CHAOTIC)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_CHAOTIC); + return one_in_(2); +} + +static bool random_art_slay_vampiric(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_VAMPIRIC)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_VAMPIRIC); + return one_in_(2); +} + +static bool random_art_slay_brand_acid(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_BRAND_ACID)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_BRAND_ACID); + return one_in_(2); +} + +static bool random_art_slay_brand_elec(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_BRAND_ELEC)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_BRAND_ELEC); + return one_in_(2); +} + +static bool random_art_slay_brand_fire(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_BRAND_FIRE)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_BRAND_FIRE); + return one_in_(2); +} + +static bool random_art_slay_brand_cold(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_BRAND_COLD)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_BRAND_COLD); + return one_in_(2); +} + +static bool random_art_slay_brand_pois(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_BRAND_POIS) || one_in_(2)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_BRAND_POIS); + return one_in_(2); +} + +static bool random_art_slay_animal(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SLAY_ANIMAL)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SLAY_ANIMAL); + return one_in_(2); +} + +static bool random_art_slay_evil(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SLAY_EVIL)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SLAY_EVIL); + return one_in_(2); +} + +static bool random_art_slay_undead(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SLAY_UNDEAD)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SLAY_UNDEAD); + return one_in_(2); +} + +static bool random_art_slay_demon(object_type *o_ptr) +{ + if (have_flag(o_ptr->art_flags, TR_SLAY_DEMON)) + return FALSE; + + add_flag(o_ptr->art_flags, TR_SLAY_DEMON); + return one_in_(2); +} + +static bool switch_random_art_slay(object_type *o_ptr) +{ + switch (o_ptr->artifact_bias) { + case BIAS_CHAOS: + return random_art_slay_chaos(o_ptr); + case BIAS_PRIESTLY: + if (((o_ptr->tval == TV_SWORD) || (o_ptr->tval == TV_POLEARM)) && !have_flag(o_ptr->art_flags, TR_BLESSED)) + add_flag(o_ptr->art_flags, TR_BLESSED); + + return FALSE; + case BIAS_NECROMANTIC: + return random_art_slay_vampiric(o_ptr) || random_art_slay_brand_pois(o_ptr); + case BIAS_RANGER: + return random_art_slay_animal(o_ptr); + case BIAS_ROGUE: + if ((((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_DAGGER)) || ((o_ptr->tval == TV_POLEARM) && (o_ptr->sval == SV_SPEAR))) + && !(have_flag(o_ptr->art_flags, TR_THROW))) { + add_flag(o_ptr->art_flags, TR_THROW); + } + + return random_art_slay_brand_pois(o_ptr); + case BIAS_POIS: + return random_art_slay_brand_pois(o_ptr); + case BIAS_ACID: + return random_art_slay_brand_acid(o_ptr); + case BIAS_ELEC: + return random_art_slay_brand_elec(o_ptr); + case BIAS_FIRE: + return random_art_slay_brand_fire(o_ptr); + case BIAS_COLD: + return random_art_slay_brand_cold(o_ptr); + case BIAS_LAW: + return random_art_slay_evil(o_ptr) || random_art_slay_undead(o_ptr) || random_art_slay_demon(o_ptr); + default: + return FALSE; + } +} + +/*! + * @brief ランダムアーティファクト生成中、対象のオブジェクトにスレイ効果を付加する。/ Add one slaying on generation of randam artifact. + * @details 優先的に付加される耐性がランダムアーティファクトバイアスに依存して存在する。 + * 原則的候補は強力射、高速射、混沌効果、吸血効果、祝福、投擲しやすい、焼棄、凍結、電撃、溶解、毒殺、 + * 動物スレイ、邪悪スレイ、悪魔スレイ、不死スレイ、オークスレイ、トロルスレイ、巨人スレイ、ドラゴンスレイ、 + * *ドラゴンスレイ*、人間スレイ、切れ味、地震、理力。 + * @attention オブジェクトのtval、svalに依存したハードコーディング処理がある。 + * @param o_ptr 対象のオブジェクト構造体ポインタ + * @return なし + */ +void random_slay(object_type *o_ptr) +{ + if (random_art_slay_bow(o_ptr) || switch_random_art_slay(o_ptr)) + return; + + switch (randint1(36)) { + case 1: + case 2: + if (one_in_(4)) + add_flag(o_ptr->art_flags, TR_KILL_ANIMAL); + else + add_flag(o_ptr->art_flags, TR_SLAY_ANIMAL); + + break; + case 3: + case 4: + if (one_in_(8)) + add_flag(o_ptr->art_flags, TR_KILL_EVIL); + else + add_flag(o_ptr->art_flags, TR_SLAY_EVIL); + + if ((o_ptr->artifact_bias == BIAS_NONE) && one_in_(2)) { + o_ptr->artifact_bias = BIAS_LAW; + break; + } + + if ((o_ptr->artifact_bias == BIAS_NONE) && one_in_(9)) + o_ptr->artifact_bias = BIAS_PRIESTLY; + + break; + case 5: + case 6: + if (one_in_(4)) + add_flag(o_ptr->art_flags, TR_KILL_UNDEAD); + else + add_flag(o_ptr->art_flags, TR_SLAY_UNDEAD); + + if ((o_ptr->artifact_bias == BIAS_NONE) && one_in_(9)) + o_ptr->artifact_bias = BIAS_PRIESTLY; + + break; + case 7: + case 8: + if (one_in_(4)) + add_flag(o_ptr->art_flags, TR_KILL_DEMON); + else + add_flag(o_ptr->art_flags, TR_SLAY_DEMON); + + if ((o_ptr->artifact_bias == BIAS_NONE) && one_in_(9)) + o_ptr->artifact_bias = BIAS_PRIESTLY; + + break; + case 9: + case 10: + if (one_in_(4)) + add_flag(o_ptr->art_flags, TR_KILL_ORC); + else + add_flag(o_ptr->art_flags, TR_SLAY_ORC); + + break; + case 11: + case 12: + if (one_in_(4)) + add_flag(o_ptr->art_flags, TR_KILL_TROLL); + else + add_flag(o_ptr->art_flags, TR_SLAY_TROLL); + + break; + case 13: + case 14: + if (one_in_(4)) + add_flag(o_ptr->art_flags, TR_KILL_GIANT); + else + add_flag(o_ptr->art_flags, TR_SLAY_GIANT); + + break; + case 15: + case 16: + add_flag(o_ptr->art_flags, TR_SLAY_DRAGON); + break; + case 17: + add_flag(o_ptr->art_flags, TR_KILL_DRAGON); + break; + case 18: + case 19: + if (o_ptr->tval != TV_SWORD) { + random_slay(o_ptr); + break; + } + + add_flag(o_ptr->art_flags, TR_VORPAL); + if ((o_ptr->artifact_bias == BIAS_NONE) && one_in_(9)) + o_ptr->artifact_bias = BIAS_WARRIOR; + + break; + case 20: + add_flag(o_ptr->art_flags, TR_IMPACT); + break; + case 21: + case 22: + add_flag(o_ptr->art_flags, TR_BRAND_FIRE); + if (o_ptr->artifact_bias == BIAS_NONE) + o_ptr->artifact_bias = BIAS_FIRE; + + break; + case 23: + case 24: + add_flag(o_ptr->art_flags, TR_BRAND_COLD); + if (o_ptr->artifact_bias == BIAS_NONE) + o_ptr->artifact_bias = BIAS_COLD; + + break; + case 25: + case 26: + add_flag(o_ptr->art_flags, TR_BRAND_ELEC); + if (o_ptr->artifact_bias == BIAS_NONE) + o_ptr->artifact_bias = BIAS_ELEC; + + break; + case 27: + case 28: + add_flag(o_ptr->art_flags, TR_BRAND_ACID); + if (!o_ptr->artifact_bias) + o_ptr->artifact_bias = BIAS_ACID; + + break; + case 29: + case 30: + add_flag(o_ptr->art_flags, TR_BRAND_POIS); + if ((o_ptr->artifact_bias == BIAS_NONE) && !one_in_(3)) { + o_ptr->artifact_bias = BIAS_POIS; + break; + } + + if ((o_ptr->artifact_bias == BIAS_NONE) && one_in_(6)) { + o_ptr->artifact_bias = BIAS_NECROMANTIC; + break; + } + + if (o_ptr->artifact_bias == BIAS_NONE) + o_ptr->artifact_bias = BIAS_ROGUE; + + break; + case 31: + add_flag(o_ptr->art_flags, TR_VAMPIRIC); + if (o_ptr->artifact_bias == BIAS_NONE) + o_ptr->artifact_bias = BIAS_NECROMANTIC; + + break; + case 32: + add_flag(o_ptr->art_flags, TR_FORCE_WEAPON); + if (o_ptr->artifact_bias == BIAS_NONE) + o_ptr->artifact_bias = (one_in_(2) ? BIAS_MAGE : BIAS_PRIESTLY); + + break; + case 33: + case 34: + if (one_in_(4)) + add_flag(o_ptr->art_flags, TR_KILL_HUMAN); + else + add_flag(o_ptr->art_flags, TR_SLAY_HUMAN); + + break; + default: + add_flag(o_ptr->art_flags, TR_CHAOTIC); + if (o_ptr->artifact_bias == BIAS_NONE) + o_ptr->artifact_bias = BIAS_CHAOS; + + break; + } +} diff --git a/src/artifact/random-art-slay.h b/src/artifact/random-art-slay.h new file mode 100644 index 000000000..0f377c856 --- /dev/null +++ b/src/artifact/random-art-slay.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void random_slay(object_type *o_ptr); diff --git a/src/autopick.c b/src/autopick.c deleted file mode 100644 index c74136acc..000000000 --- a/src/autopick.c +++ /dev/null @@ -1,6140 +0,0 @@ -/*! - * @file autopick.c - * @brief 自動拾い機能の実装 / Object Auto-picker/Destroyer - * @date 2014/01/02 - * @author - * Copyright (c) 2002 Mogami\n - *\n - * This software may be copied and distributed for educational, research, and\n - * not for profit purposes provided that this copyright and statement are\n - * included in all such copies.\n - * 2014 Deskull rearranged comment for Doxygen.\n - */ - -#include "angband.h" -#include "store.h" -#include "player-status.h" -#include "player-move.h" -#include "object-hook.h" - -#define MAX_LINELEN 1024 - -/* - * Macros for Keywords - */ -#define FLG_ALL 0 -#define FLG_UNAWARE 1 -#define FLG_UNIDENTIFIED 2 -#define FLG_IDENTIFIED 3 -#define FLG_STAR_IDENTIFIED 4 -#define FLG_COLLECTING 5 -#define FLG_ARTIFACT 6 -#define FLG_EGO 7 -#define FLG_GOOD 10 -#define FLG_NAMELESS 11 -#define FLG_AVERAGE 12 -#define FLG_WORTHLESS 13 -#define FLG_RARE 14 -#define FLG_COMMON 15 -#define FLG_BOOSTED 16 -#define FLG_MORE_DICE 17 -#define FLG_MORE_BONUS 18 -#define FLG_WANTED 19 -#define FLG_UNIQUE 20 -#define FLG_HUMAN 21 -#define FLG_UNREADABLE 22 -#define FLG_REALM1 23 -#define FLG_REALM2 24 -#define FLG_FIRST 25 -#define FLG_SECOND 26 -#define FLG_THIRD 27 -#define FLG_FOURTH 28 - -#define FLG_ITEMS 30 -#define FLG_WEAPONS 31 -#define FLG_FAVORITE_WEAPONS 32 -#define FLG_ARMORS 33 -#define FLG_MISSILES 34 -#define FLG_DEVICES 35 -#define FLG_LIGHTS 36 -#define FLG_JUNKS 37 -#define FLG_CORPSES 38 -#define FLG_SPELLBOOKS 39 -#define FLG_HAFTED 40 -#define FLG_SHIELDS 41 -#define FLG_BOWS 42 -#define FLG_RINGS 43 -#define FLG_AMULETS 44 -#define FLG_SUITS 45 -#define FLG_CLOAKS 46 -#define FLG_HELMS 47 -#define FLG_GLOVES 48 -#define FLG_BOOTS 49 - -#define FLG_NOUN_BEGIN FLG_ITEMS -#define FLG_NOUN_END FLG_BOOTS - -#ifdef JP - -static GAME_TEXT KEY_ALL[] = "すべての"; -static GAME_TEXT KEY_UNAWARE[] = "未判明の"; -static GAME_TEXT KEY_UNIDENTIFIED[] = "未鑑定の"; -static GAME_TEXT KEY_IDENTIFIED[] = "鑑定済みの"; -static GAME_TEXT KEY_STAR_IDENTIFIED[] = "*鑑定*済みの"; -static GAME_TEXT KEY_COLLECTING[] = "収集中の"; -static GAME_TEXT KEY_ARTIFACT[] = "アーティファクト"; -static GAME_TEXT KEY_EGO[] = "エゴ"; -static GAME_TEXT KEY_GOOD[] = "上質の"; -static GAME_TEXT KEY_NAMELESS[] = "無銘の"; -static GAME_TEXT KEY_AVERAGE[] = "並の"; -static GAME_TEXT KEY_WORTHLESS[] = "無価値の"; -static GAME_TEXT KEY_RARE[] = "レアな"; -static GAME_TEXT KEY_COMMON[] = "ありふれた"; -static GAME_TEXT KEY_BOOSTED[] = "ダイス目の違う"; -static GAME_TEXT KEY_MORE_THAN[] = "ダイス目"; -static GAME_TEXT KEY_DICE[] = "以上の"; -static GAME_TEXT KEY_MORE_BONUS[] = "修正値"; -static GAME_TEXT KEY_MORE_BONUS2[] = "以上の"; -static GAME_TEXT KEY_WANTED[] = "賞金首の"; -static GAME_TEXT KEY_UNIQUE[] = "ユニーク・モンスターの"; -static GAME_TEXT KEY_HUMAN[] = "人間の"; -static GAME_TEXT KEY_UNREADABLE[] = "読めない"; -static GAME_TEXT KEY_REALM1[] = "第一領域の"; -static GAME_TEXT KEY_REALM2[] = "第二領域の"; -static GAME_TEXT KEY_FIRST[] = "1冊目の"; -static GAME_TEXT KEY_SECOND[] = "2冊目の"; -static GAME_TEXT KEY_THIRD[] = "3冊目の"; -static GAME_TEXT KEY_FOURTH[] = "4冊目の"; -static GAME_TEXT KEY_ITEMS[] = "アイテム"; -static GAME_TEXT KEY_WEAPONS[] = "武器"; -static GAME_TEXT KEY_FAVORITE_WEAPONS[] = "得意武器"; -static GAME_TEXT KEY_ARMORS[] = "防具"; -static GAME_TEXT KEY_MISSILES[] = "矢"; -static GAME_TEXT KEY_DEVICES[] = "魔法アイテム"; -static GAME_TEXT KEY_LIGHTS[] = "光源"; -static GAME_TEXT KEY_JUNKS[] = "がらくた"; -static GAME_TEXT KEY_CORPSES[] = "死体や骨"; -static GAME_TEXT KEY_SPELLBOOKS[] = "魔法書"; -static GAME_TEXT KEY_HAFTED[] = "鈍器"; -static GAME_TEXT KEY_SHIELDS[] = "盾"; -static GAME_TEXT KEY_BOWS[] = "弓"; -static GAME_TEXT KEY_RINGS[] = "指輪"; -static GAME_TEXT KEY_AMULETS[] = "アミュレット"; -static GAME_TEXT KEY_SUITS[] = "鎧"; -static GAME_TEXT KEY_CLOAKS[] = "クローク"; -static GAME_TEXT KEY_HELMS[] = "兜"; -static GAME_TEXT KEY_GLOVES[] = "籠手"; -static GAME_TEXT KEY_BOOTS[] = "靴"; - -#else - -static GAME_TEXT KEY_ALL[] = "all"; -static GAME_TEXT KEY_UNAWARE[] = "unaware"; -static GAME_TEXT KEY_UNIDENTIFIED[] = "unidentified"; -static GAME_TEXT KEY_IDENTIFIED[] = "identified"; -static GAME_TEXT KEY_STAR_IDENTIFIED[] = "*identified*"; -static GAME_TEXT KEY_COLLECTING[] = "collecting"; -static GAME_TEXT KEY_ARTIFACT[] = "artifact"; -static GAME_TEXT KEY_EGO[] = "ego"; -static GAME_TEXT KEY_GOOD[] = "good"; -static GAME_TEXT KEY_NAMELESS[] = "nameless"; -static GAME_TEXT KEY_AVERAGE[] = "average"; -static GAME_TEXT KEY_WORTHLESS[] = "worthless"; -static GAME_TEXT KEY_RARE[] = "rare"; -static GAME_TEXT KEY_COMMON[] = "common"; -static GAME_TEXT KEY_BOOSTED[] = "dice boosted"; -static GAME_TEXT KEY_MORE_THAN[] = "more than"; -static GAME_TEXT KEY_DICE[] = " dice"; -static GAME_TEXT KEY_MORE_BONUS[] = "more bonus than"; -static GAME_TEXT KEY_MORE_BONUS2[] = ""; -static GAME_TEXT KEY_WANTED[] = "wanted"; -static GAME_TEXT KEY_UNIQUE[] = "unique monster's"; -static GAME_TEXT KEY_HUMAN[] = "human"; -static GAME_TEXT KEY_UNREADABLE[] = "unreadable"; -static GAME_TEXT KEY_REALM1[] = "first realm's"; -static GAME_TEXT KEY_REALM2[] = "second realm's"; -static GAME_TEXT KEY_FIRST[] = "first"; -static GAME_TEXT KEY_SECOND[] = "second"; -static GAME_TEXT KEY_THIRD[] = "third"; -static GAME_TEXT KEY_FOURTH[] = "fourth"; -static GAME_TEXT KEY_ITEMS[] = "items"; -static GAME_TEXT KEY_WEAPONS[] = "weapons"; -static GAME_TEXT KEY_FAVORITE_WEAPONS[] = "favorite weapons"; -static GAME_TEXT KEY_ARMORS[] = "armors"; -static GAME_TEXT KEY_MISSILES[] = "missiles"; -static GAME_TEXT KEY_DEVICES[] = "magical devices"; -static GAME_TEXT KEY_LIGHTS[] = "lights"; -static GAME_TEXT KEY_JUNKS[] = "junks"; -static GAME_TEXT KEY_CORPSES[] = "corpses or skeletons"; -static GAME_TEXT KEY_SPELLBOOKS[] = "spellbooks"; -static GAME_TEXT KEY_HAFTED[] = "hafted weapons"; -static GAME_TEXT KEY_SHIELDS[] = "shields"; -static GAME_TEXT KEY_BOWS[] = "bows"; -static GAME_TEXT KEY_RINGS[] = "rings"; -static GAME_TEXT KEY_AMULETS[] = "amulets"; -static GAME_TEXT KEY_SUITS[] = "suits"; -static GAME_TEXT KEY_CLOAKS[] = "cloaks"; -static GAME_TEXT KEY_HELMS[] = "helms"; -static GAME_TEXT KEY_GLOVES[] = "gloves"; -static GAME_TEXT KEY_BOOTS[] = "boots"; - -#endif /* JP */ - -#define MATCH_KEY(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\ - ? (ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE) -#define MATCH_KEY2(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\ - ? (prev_ptr = ptr, ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE) - -#ifdef JP -#define ADD_KEY(KEY) strcat(ptr, KEY) -#else -#define ADD_KEY(KEY) (strcat(ptr, KEY), strcat(ptr, " ")) -#endif -#define ADD_KEY2(KEY) strcat(ptr, KEY) - -#define ADD_FLG(FLG) (entry->flag[FLG / 32] |= (1L << (FLG % 32))) -#define REM_FLG(FLG) (entry->flag[FLG / 32] &= ~(1L << (FLG % 32))) -#define ADD_FLG_NOUN(FLG) (ADD_FLG(FLG), prev_flg = FLG) -#define IS_FLG(FLG) (entry->flag[FLG / 32] & (1L << (FLG % 32))) - -#ifdef JP - static char kanji_colon[] = ":"; -#endif - - -/* - * A function to create new entry - */ -static bool autopick_new_entry(autopick_type *entry, concptr str, bool allow_default) -{ - concptr insc; - int i; - byte act = 0; - char buf[MAX_LINELEN]; - concptr prev_ptr, ptr, old_ptr; - int prev_flg; - - if (str[0] && str[1] == ':') switch (str[0]) - { - case '?': case '%': - case 'A': case 'P': case 'C': - return FALSE; - } - - entry->flag[0] = entry->flag[1] = 0L; - entry->dice = 0; - entry->bonus = 0; - - act = DO_AUTOPICK | DO_DISPLAY; - while (TRUE) - { - if ((act & DO_AUTOPICK) && *str == '!') - { - act &= ~DO_AUTOPICK; - act |= DO_AUTODESTROY; - str++; - } - else if ((act & DO_AUTOPICK) && *str == '~') - { - act &= ~DO_AUTOPICK; - act |= DONT_AUTOPICK; - str++; - } - else if ((act & DO_AUTOPICK) && *str == ';') - { - act &= ~DO_AUTOPICK; - act |= DO_QUERY_AUTOPICK; - str++; - } - else if ((act & DO_DISPLAY) && *str == '(') - { - act &= ~DO_DISPLAY; - str++; - } - else - break; - } - - /* don't mind upper or lower case */ - insc = NULL; - for (i = 0; *str; i++) - { - char c = *str++; -#ifdef JP - if (iskanji(c)) - { - buf[i++] = c; - buf[i] = *str++; - continue; - } -#endif - /* Auto-inscription? */ - if (c == '#') - { - buf[i] = '\0'; - insc = str; - break; - } - - if (isupper(c)) c = (char)tolower(c); - - buf[i] = c; - } - buf[i] = '\0'; - - /* Skip empty line unless allow_default */ - if (!allow_default && *buf == 0) return FALSE; - - /* Skip comment line */ - if (*buf == 0 && insc) return FALSE; - - ptr = prev_ptr = buf; - old_ptr = NULL; - - while (old_ptr != ptr) - { - /* Save current location */ - old_ptr = ptr; - - if (MATCH_KEY(KEY_ALL)) ADD_FLG(FLG_ALL); - if (MATCH_KEY(KEY_COLLECTING)) ADD_FLG(FLG_COLLECTING); - if (MATCH_KEY(KEY_UNAWARE)) ADD_FLG(FLG_UNAWARE); - if (MATCH_KEY(KEY_UNIDENTIFIED)) ADD_FLG(FLG_UNIDENTIFIED); - if (MATCH_KEY(KEY_IDENTIFIED)) ADD_FLG(FLG_IDENTIFIED); - if (MATCH_KEY(KEY_STAR_IDENTIFIED)) ADD_FLG(FLG_STAR_IDENTIFIED); - if (MATCH_KEY(KEY_BOOSTED)) ADD_FLG(FLG_BOOSTED); - - /*** Weapons whose dd*ds is more than nn ***/ - if (MATCH_KEY2(KEY_MORE_THAN)) - { - int k = 0; - entry->dice = 0; - - /* Drop leading spaces */ - while (' ' == *ptr) ptr++; - - /* Read number */ - while ('0' <= *ptr && *ptr <= '9') - { - entry->dice = 10 * entry->dice + (*ptr - '0'); - ptr++; - k++; - } - - if (k > 0 && k <= 2) - { - (void)MATCH_KEY(KEY_DICE); - ADD_FLG(FLG_MORE_DICE); - } - else - ptr = prev_ptr; - } - - /*** Items whose magical bonus is more than n ***/ - if (MATCH_KEY2(KEY_MORE_BONUS)) - { - int k = 0; - entry->bonus = 0; - - /* Drop leading spaces */ - while (' ' == *ptr) ptr++; - - /* Read number */ - while ('0' <= *ptr && *ptr <= '9') - { - entry->bonus = 10 * entry->bonus + (*ptr - '0'); - ptr++; - k++; - } - - if (k > 0 && k <= 2) - { -#ifdef JP - (void)MATCH_KEY(KEY_MORE_BONUS2); -#else - if (' ' == *ptr) ptr++; -#endif - ADD_FLG(FLG_MORE_BONUS); - } - else - ptr = prev_ptr; - } - - if (MATCH_KEY(KEY_WORTHLESS)) ADD_FLG(FLG_WORTHLESS); - if (MATCH_KEY(KEY_EGO)) ADD_FLG(FLG_EGO); - if (MATCH_KEY(KEY_GOOD)) ADD_FLG(FLG_GOOD); - if (MATCH_KEY(KEY_NAMELESS)) ADD_FLG(FLG_NAMELESS); - if (MATCH_KEY(KEY_AVERAGE)) ADD_FLG(FLG_AVERAGE); - if (MATCH_KEY(KEY_RARE)) ADD_FLG(FLG_RARE); - if (MATCH_KEY(KEY_COMMON)) ADD_FLG(FLG_COMMON); - if (MATCH_KEY(KEY_WANTED)) ADD_FLG(FLG_WANTED); - if (MATCH_KEY(KEY_UNIQUE)) ADD_FLG(FLG_UNIQUE); - if (MATCH_KEY(KEY_HUMAN)) ADD_FLG(FLG_HUMAN); - if (MATCH_KEY(KEY_UNREADABLE)) ADD_FLG(FLG_UNREADABLE); - if (MATCH_KEY(KEY_REALM1)) ADD_FLG(FLG_REALM1); - if (MATCH_KEY(KEY_REALM2)) ADD_FLG(FLG_REALM2); - if (MATCH_KEY(KEY_FIRST)) ADD_FLG(FLG_FIRST); - if (MATCH_KEY(KEY_SECOND)) ADD_FLG(FLG_SECOND); - if (MATCH_KEY(KEY_THIRD)) ADD_FLG(FLG_THIRD); - if (MATCH_KEY(KEY_FOURTH)) ADD_FLG(FLG_FOURTH); - } - - /* Not yet found any noun */ - prev_flg = -1; - - if (MATCH_KEY2(KEY_ARTIFACT)) ADD_FLG_NOUN(FLG_ARTIFACT); - - if (MATCH_KEY2(KEY_ITEMS)) ADD_FLG_NOUN(FLG_ITEMS); - else if (MATCH_KEY2(KEY_WEAPONS)) ADD_FLG_NOUN(FLG_WEAPONS); - else if (MATCH_KEY2(KEY_FAVORITE_WEAPONS)) ADD_FLG_NOUN(FLG_FAVORITE_WEAPONS); - else if (MATCH_KEY2(KEY_ARMORS)) ADD_FLG_NOUN(FLG_ARMORS); - else if (MATCH_KEY2(KEY_MISSILES)) ADD_FLG_NOUN(FLG_MISSILES); - else if (MATCH_KEY2(KEY_DEVICES)) ADD_FLG_NOUN(FLG_DEVICES); - else if (MATCH_KEY2(KEY_LIGHTS)) ADD_FLG_NOUN(FLG_LIGHTS); - else if (MATCH_KEY2(KEY_JUNKS)) ADD_FLG_NOUN(FLG_JUNKS); - else if (MATCH_KEY2(KEY_CORPSES)) ADD_FLG_NOUN(FLG_CORPSES); - else if (MATCH_KEY2(KEY_SPELLBOOKS)) ADD_FLG_NOUN(FLG_SPELLBOOKS); - else if (MATCH_KEY2(KEY_HAFTED)) ADD_FLG_NOUN(FLG_HAFTED); - else if (MATCH_KEY2(KEY_SHIELDS)) ADD_FLG_NOUN(FLG_SHIELDS); - else if (MATCH_KEY2(KEY_BOWS)) ADD_FLG_NOUN(FLG_BOWS); - else if (MATCH_KEY2(KEY_RINGS)) ADD_FLG_NOUN(FLG_RINGS); - else if (MATCH_KEY2(KEY_AMULETS)) ADD_FLG_NOUN(FLG_AMULETS); - else if (MATCH_KEY2(KEY_SUITS)) ADD_FLG_NOUN(FLG_SUITS); - else if (MATCH_KEY2(KEY_CLOAKS)) ADD_FLG_NOUN(FLG_CLOAKS); - else if (MATCH_KEY2(KEY_HELMS)) ADD_FLG_NOUN(FLG_HELMS); - else if (MATCH_KEY2(KEY_GLOVES)) ADD_FLG_NOUN(FLG_GLOVES); - else if (MATCH_KEY2(KEY_BOOTS)) ADD_FLG_NOUN(FLG_BOOTS); - - /* Last 'keyword' must be at the correct location */ - if (*ptr == ':') - ptr++; -#ifdef JP - else if (ptr[0] == kanji_colon[0] && ptr[1] == kanji_colon[1]) - ptr += 2; -#endif - else if (*ptr == '\0') - { - /* There was no noun */ - if (prev_flg == -1) - - /* Add extra word "items" */ - ADD_FLG_NOUN(FLG_ITEMS); - } - else - { - /* Noun type? */ - if (prev_flg != -1) - { - /* A noun type keyword didn't end correctly */ - entry->flag[prev_flg/32] &= ~(1L<< (prev_flg%32)); - ptr = prev_ptr; - } - } - - /* Save this auto-picker entry line */ - entry->name = string_make(ptr); - entry->action = act; - entry->insc = string_make(insc); - - return TRUE; -} - - -/* - * Get auto-picker entry from o_ptr. - */ -static void autopick_entry_from_object(autopick_type *entry, object_type *o_ptr) -{ - /* Assume that object name is to be added */ - bool name = TRUE; - -#ifdef JP - /* エゴ銘が邪魔かもしれないので、デフォルトで「^」は付けない */ - bool bol_mark = FALSE; -#else - /* We can always use the ^ mark in English */ - bool bol_mark = TRUE; -#endif - - GAME_TEXT name_str[MAX_NLEN]; - - /* Initialize name string */ - name_str[0] = '\0'; - - entry->insc = string_make(quark_str(o_ptr->inscription)); - entry->action = DO_AUTOPICK | DO_DISPLAY; - entry->flag[0] = entry->flag[1] = 0L; - entry->dice = 0; - - /* Unaware */ - if (!object_is_aware(o_ptr)) - { - ADD_FLG(FLG_UNAWARE); - bol_mark = TRUE; - } - - /* Not really identified */ - else if (!object_is_known(o_ptr)) - { - if (!(o_ptr->ident & IDENT_SENSE)) - { - ADD_FLG(FLG_UNIDENTIFIED); - bol_mark = TRUE; - } - else - { - /* Pseudo-identified */ - switch (o_ptr->feeling) - { - case FEEL_AVERAGE: - case FEEL_GOOD: - ADD_FLG(FLG_NAMELESS); - bol_mark = TRUE; - break; - - case FEEL_BROKEN: - case FEEL_CURSED: - ADD_FLG(FLG_NAMELESS); - ADD_FLG(FLG_WORTHLESS); - bol_mark = TRUE; - break; - - case FEEL_TERRIBLE: - case FEEL_WORTHLESS: - ADD_FLG(FLG_WORTHLESS); - break; - - case FEEL_EXCELLENT: - ADD_FLG(FLG_EGO); - break; - - case FEEL_UNCURSED: - /* XXX No appropriate flag */ - /* ADD_FLG(); */ - break; - - default: - /* Never reach here */ - break; - } - } - } - - /* Identified */ - else - { - /* Ego objects */ - if (object_is_ego(o_ptr)) - { - if (object_is_weapon_armour_ammo(o_ptr)) - { - /* - * Base name of ego weapons and armors - * are almost meaningless. - * Register the ego type only. - */ - ego_item_type *e_ptr = &e_info[o_ptr->name2]; -#ifdef JP - /* エゴ銘には「^」マークが使える */ - sprintf(name_str, "^%s", e_name + e_ptr->name); -#else - /* We ommit the basename and cannot use the ^ mark */ - strcpy(name_str, e_name + e_ptr->name); -#endif - - /* Don't use the object description */ - name = FALSE; - - /* Restrict to 'common' equipments */ - if (!object_is_rare(o_ptr)) ADD_FLG(FLG_COMMON); - } - - ADD_FLG(FLG_EGO); - } - - /* Artifact */ - else if (object_is_artifact(o_ptr)) - ADD_FLG(FLG_ARTIFACT); - - /* Non-ego, non-artifact */ - else - { - /* Wearable nameless object */ - if (object_is_equipment(o_ptr)) - ADD_FLG(FLG_NAMELESS); - - bol_mark = TRUE; - } - - } - - /* Melee weapon with boosted dice */ - if (object_is_melee_weapon(o_ptr)) - { - object_kind *k_ptr = &k_info[o_ptr->k_idx]; - - if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds)) - ADD_FLG(FLG_BOOSTED); - } - - /* Wanted monster's corpse */ - if (object_is_shoukinkubi(o_ptr)) - { - REM_FLG(FLG_WORTHLESS); - ADD_FLG(FLG_WANTED); - } - - if ((o_ptr->tval == TV_CORPSE || o_ptr->tval == TV_STATUE) - && (r_info[o_ptr->pval].flags1 & RF1_UNIQUE)) - { - ADD_FLG(FLG_UNIQUE); - } - - if (o_ptr->tval == TV_CORPSE && my_strchr("pht", r_info[o_ptr->pval].d_char)) - { - ADD_FLG(FLG_HUMAN); - } - - if (o_ptr->tval >= TV_LIFE_BOOK && - !check_book_realm(o_ptr->tval, o_ptr->sval)) - { - ADD_FLG(FLG_UNREADABLE); - if (o_ptr->tval != TV_ARCANE_BOOK) name = FALSE; - } - - if (REALM1_BOOK == o_ptr->tval && - p_ptr->pclass != CLASS_SORCERER && - p_ptr->pclass != CLASS_RED_MAGE) - { - ADD_FLG(FLG_REALM1); - name = FALSE; - } - - if (REALM2_BOOK == o_ptr->tval && - p_ptr->pclass != CLASS_SORCERER && - p_ptr->pclass != CLASS_RED_MAGE) - { - ADD_FLG(FLG_REALM2); - name = FALSE; - } - - if (o_ptr->tval >= TV_LIFE_BOOK && 0 == o_ptr->sval) - ADD_FLG(FLG_FIRST); - if (o_ptr->tval >= TV_LIFE_BOOK && 1 == o_ptr->sval) - ADD_FLG(FLG_SECOND); - if (o_ptr->tval >= TV_LIFE_BOOK && 2 == o_ptr->sval) - ADD_FLG(FLG_THIRD); - if (o_ptr->tval >= TV_LIFE_BOOK && 3 == o_ptr->sval) - ADD_FLG(FLG_FOURTH); - - if (object_is_ammo(o_ptr)) - ADD_FLG(FLG_MISSILES); - else if (o_ptr->tval == TV_SCROLL || o_ptr->tval == TV_STAFF - || o_ptr->tval == TV_WAND || o_ptr->tval == TV_ROD) - ADD_FLG(FLG_DEVICES); - else if (o_ptr->tval == TV_LITE) - ADD_FLG(FLG_LIGHTS); - else if (o_ptr->tval == TV_SKELETON || o_ptr->tval == TV_BOTTLE - || o_ptr->tval == TV_JUNK || o_ptr->tval == TV_STATUE) - ADD_FLG(FLG_JUNKS); - else if (o_ptr->tval == TV_CORPSE) - ADD_FLG(FLG_CORPSES); - else if (o_ptr->tval >= TV_LIFE_BOOK) - ADD_FLG(FLG_SPELLBOOKS); - else if (o_ptr->tval == TV_POLEARM || o_ptr->tval == TV_SWORD - || o_ptr->tval == TV_DIGGING || o_ptr->tval == TV_HAFTED) - ADD_FLG(FLG_WEAPONS); - else if (o_ptr->tval == TV_SHIELD) - ADD_FLG(FLG_SHIELDS); - else if (o_ptr->tval == TV_BOW) - ADD_FLG(FLG_BOWS); - else if (o_ptr->tval == TV_RING) - ADD_FLG(FLG_RINGS); - else if (o_ptr->tval == TV_AMULET) - ADD_FLG(FLG_AMULETS); - else if (o_ptr->tval == TV_DRAG_ARMOR || o_ptr->tval == TV_HARD_ARMOR || - o_ptr->tval == TV_SOFT_ARMOR) - ADD_FLG(FLG_SUITS); - else if (o_ptr->tval == TV_CLOAK) - ADD_FLG(FLG_CLOAKS); - else if (o_ptr->tval == TV_HELM) - ADD_FLG(FLG_HELMS); - else if (o_ptr->tval == TV_GLOVES) - ADD_FLG(FLG_GLOVES); - else if (o_ptr->tval == TV_BOOTS) - ADD_FLG(FLG_BOOTS); - - /* Prepare the object description */ - if (name) - { - GAME_TEXT o_name[MAX_NLEN]; - - object_desc(o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL | OD_NAME_ONLY)); - - /* - * If necessary, add a '^' which indicates the - * beginning of line. - */ - sprintf(name_str, "%s%s", bol_mark ? "^" : "", o_name); - } - - /* Register the name in lowercase */ - str_tolower(name_str); - entry->name = string_make(name_str); - - return; -} - - -/* - * A function to delete entry - */ -static void autopick_free_entry(autopick_type *entry) -{ - string_free(entry->name); - string_free(entry->insc); - entry->name = NULL; - entry->insc = NULL; -} - - -#define MAX_AUTOPICK_DEFAULT 200 - -/* - * Initialize the autopick - */ -static void init_autopick(void) -{ - static const char easy_autopick_inscription[] = "(:=g"; - autopick_type entry; - int i; - - if (!autopick_list) - { - max_max_autopick = MAX_AUTOPICK_DEFAULT; - C_MAKE(autopick_list, max_max_autopick, autopick_type); - max_autopick = 0; - } - - /* Clear old entries */ - for( i = 0; i < max_autopick; i++) - autopick_free_entry(&autopick_list[i]); - - max_autopick = 0; - - /* There is always one entry "=g" */ - autopick_new_entry(&entry, easy_autopick_inscription, TRUE); - autopick_list[max_autopick++] = entry; -} - - -#define PT_DEFAULT 0 -#define PT_WITH_PNAME 1 - -/* - * Get file name for autopick preference - */ -static concptr pickpref_filename(int filename_mode) -{ - static const char namebase[] = _("picktype", "pickpref"); - - switch (filename_mode) - { - case PT_DEFAULT: - return format("%s.prf", namebase); - - case PT_WITH_PNAME: - return format("%s-%s.prf", namebase, player_base); - - default: - return NULL; - } -} - - -/* - * Load an autopick preference file - */ -void autopick_load_pref(bool disp_mes) -{ - GAME_TEXT buf[80]; - errr err; - - /* Free old entries */ - init_autopick(); - - /* Try a filename with player name */ - my_strcpy(buf, pickpref_filename(PT_WITH_PNAME), sizeof(buf)); - - /* Load the file */ - err = process_autopick_file(buf); - - if (err == 0 && disp_mes) - { - /* Success */ - msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf); - } - - /* No file found */ - if (0 > err) - { - /* Use default name */ - my_strcpy(buf, pickpref_filename(PT_DEFAULT), sizeof(buf)); - - /* Load the file */ - err = process_autopick_file(buf); - - if (err == 0 && disp_mes) - { - /* Success */ - msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf); - } - } - - if (err && disp_mes) - { - /* Failed */ - msg_print(_("自動拾い設定ファイルの読み込みに失敗しました。", "Failed to reload autopick preference.")); - } -} - - -/* - * Add one line to autopick_list[] - */ -static void add_autopick_list(autopick_type *entry) -{ - /* There is no enough space to add one line */ - if (max_autopick >= max_max_autopick) - { - int old_max_max_autopick = max_max_autopick; - autopick_type *old_autopick_list = autopick_list; - - /* Increase size of list */ - max_max_autopick += MAX_AUTOPICK_DEFAULT; - - /* Allocate */ - C_MAKE(autopick_list, max_max_autopick, autopick_type); - - /* Copy from old list to new list */ - (void)C_COPY(autopick_list, old_autopick_list, old_max_max_autopick, autopick_type); - - /* Kill old list */ - C_KILL(old_autopick_list, old_max_max_autopick, autopick_type); - } - - /* Add one line */ - autopick_list[max_autopick] = *entry; - - max_autopick++; -} - - -/* - * Process line for auto picker/destroyer. - */ -errr process_autopick_file_command(char *buf) -{ - autopick_type an_entry, *entry = &an_entry; - int i; - - /* Nuke illegal char */ - for(i = 0; buf[i]; i++) - { -#ifdef JP - if (iskanji(buf[i])) - { - i++; - continue; - } -#endif - if (iswspace(buf[i]) && buf[i] != ' ') - break; - } - buf[i] = 0; - - if (!autopick_new_entry(entry, buf, FALSE)) return 0; - - /* Already has the same entry? */ - for(i = 0; i < max_autopick; i++) - if(!strcmp(entry->name, autopick_list[i].name) - && entry->flag[0] == autopick_list[i].flag[0] - && entry->flag[1] == autopick_list[i].flag[1] - && entry->dice == autopick_list[i].dice - && entry->bonus == autopick_list[i].bonus) - { - autopick_free_entry(entry); - return 0; - } - - add_autopick_list(entry); - return 0; -} - - -/* - * Reconstruct preference line from entry - */ -concptr autopick_line_from_entry(autopick_type *entry) -{ - char buf[MAX_LINELEN]; - char *ptr; - bool sepa_flag = TRUE; - - *buf = '\0'; - if (!(entry->action & DO_DISPLAY)) strcat(buf, "("); - if (entry->action & DO_QUERY_AUTOPICK) strcat(buf, ";"); - if (entry->action & DO_AUTODESTROY) strcat(buf, "!"); - if (entry->action & DONT_AUTOPICK) strcat(buf, "~"); - - ptr = buf; - - if (IS_FLG(FLG_ALL)) ADD_KEY(KEY_ALL); - if (IS_FLG(FLG_COLLECTING)) ADD_KEY(KEY_COLLECTING); - if (IS_FLG(FLG_UNAWARE)) ADD_KEY(KEY_UNAWARE); - if (IS_FLG(FLG_UNIDENTIFIED)) ADD_KEY(KEY_UNIDENTIFIED); - if (IS_FLG(FLG_IDENTIFIED)) ADD_KEY(KEY_IDENTIFIED); - if (IS_FLG(FLG_STAR_IDENTIFIED)) ADD_KEY(KEY_STAR_IDENTIFIED); - if (IS_FLG(FLG_BOOSTED)) ADD_KEY(KEY_BOOSTED); - - if (IS_FLG(FLG_MORE_DICE)) - { - ADD_KEY(KEY_MORE_THAN); - strcat(ptr, format("%d", entry->dice)); - ADD_KEY(KEY_DICE); - } - - if (IS_FLG(FLG_MORE_BONUS)) - { - ADD_KEY(KEY_MORE_BONUS); - strcat(ptr, format("%d", entry->bonus)); - ADD_KEY(KEY_MORE_BONUS2); - } - - if (IS_FLG(FLG_UNREADABLE)) ADD_KEY(KEY_UNREADABLE); - if (IS_FLG(FLG_REALM1)) ADD_KEY(KEY_REALM1); - if (IS_FLG(FLG_REALM2)) ADD_KEY(KEY_REALM2); - if (IS_FLG(FLG_FIRST)) ADD_KEY(KEY_FIRST); - if (IS_FLG(FLG_SECOND)) ADD_KEY(KEY_SECOND); - if (IS_FLG(FLG_THIRD)) ADD_KEY(KEY_THIRD); - if (IS_FLG(FLG_FOURTH)) ADD_KEY(KEY_FOURTH); - if (IS_FLG(FLG_WANTED)) ADD_KEY(KEY_WANTED); - if (IS_FLG(FLG_UNIQUE)) ADD_KEY(KEY_UNIQUE); - if (IS_FLG(FLG_HUMAN)) ADD_KEY(KEY_HUMAN); - if (IS_FLG(FLG_WORTHLESS)) ADD_KEY(KEY_WORTHLESS); - if (IS_FLG(FLG_GOOD)) ADD_KEY(KEY_GOOD); - if (IS_FLG(FLG_NAMELESS)) ADD_KEY(KEY_NAMELESS); - if (IS_FLG(FLG_AVERAGE)) ADD_KEY(KEY_AVERAGE); - if (IS_FLG(FLG_RARE)) ADD_KEY(KEY_RARE); - if (IS_FLG(FLG_COMMON)) ADD_KEY(KEY_COMMON); - if (IS_FLG(FLG_EGO)) ADD_KEY(KEY_EGO); - - if (IS_FLG(FLG_ARTIFACT)) ADD_KEY(KEY_ARTIFACT); - - if (IS_FLG(FLG_ITEMS)) ADD_KEY2(KEY_ITEMS); - else if (IS_FLG(FLG_WEAPONS)) ADD_KEY2(KEY_WEAPONS); - else if (IS_FLG(FLG_FAVORITE_WEAPONS)) ADD_KEY2(KEY_FAVORITE_WEAPONS); - else if (IS_FLG(FLG_ARMORS)) ADD_KEY2(KEY_ARMORS); - else if (IS_FLG(FLG_MISSILES)) ADD_KEY2(KEY_MISSILES); - else if (IS_FLG(FLG_DEVICES)) ADD_KEY2(KEY_DEVICES); - else if (IS_FLG(FLG_LIGHTS)) ADD_KEY2(KEY_LIGHTS); - else if (IS_FLG(FLG_JUNKS)) ADD_KEY2(KEY_JUNKS); - else if (IS_FLG(FLG_CORPSES)) ADD_KEY2(KEY_CORPSES); - else if (IS_FLG(FLG_SPELLBOOKS)) ADD_KEY2(KEY_SPELLBOOKS); - else if (IS_FLG(FLG_HAFTED)) ADD_KEY2(KEY_HAFTED); - else if (IS_FLG(FLG_SHIELDS)) ADD_KEY2(KEY_SHIELDS); - else if (IS_FLG(FLG_BOWS)) ADD_KEY2(KEY_BOWS); - else if (IS_FLG(FLG_RINGS)) ADD_KEY2(KEY_RINGS); - else if (IS_FLG(FLG_AMULETS)) ADD_KEY2(KEY_AMULETS); - else if (IS_FLG(FLG_SUITS)) ADD_KEY2(KEY_SUITS); - else if (IS_FLG(FLG_CLOAKS)) ADD_KEY2(KEY_CLOAKS); - else if (IS_FLG(FLG_HELMS)) ADD_KEY2(KEY_HELMS); - else if (IS_FLG(FLG_GLOVES)) ADD_KEY2(KEY_GLOVES); - else if (IS_FLG(FLG_BOOTS)) ADD_KEY2(KEY_BOOTS); - - /* You don't need sepalator after adjective */ - /* 'artifact' is not true adjective */ - else if (!IS_FLG(FLG_ARTIFACT)) - sepa_flag = FALSE; - - if (entry->name && entry->name[0]) - { - int i, j = 0; - - if (sepa_flag) strcat(buf, ":"); - - i = strlen(buf); - while (entry->name[j] && i < MAX_LINELEN - 2 - 1) - { -#ifdef JP - if (iskanji(entry->name[j])) - buf[i++] = entry->name[j++]; -#endif - buf[i++] = entry->name[j++]; - } - buf[i] = '\0'; - } - - if (entry->insc) - { - int i, j = 0; - strcat(buf, "#"); - i = strlen(buf); - - while (entry->insc[j] && i < MAX_LINELEN - 2) - { -#ifdef JP - if (iskanji(entry->insc[j])) - buf[i++] = entry->insc[j++]; -#endif - buf[i++] = entry->insc[j++]; - } - buf[i] = '\0'; - } - - return string_make(buf); -} - - -/* - * Reconstruct preference line from entry and kill entry - */ -static concptr autopick_line_from_entry_kill(autopick_type *entry) -{ - concptr ptr = autopick_line_from_entry(entry); - - /* Free memory for original entry */ - autopick_free_entry(entry); - - return ptr; -} - - -/* - * A function for Auto-picker/destroyer - * Examine whether the object matches to the entry - */ -static bool is_autopick_aux(object_type *o_ptr, autopick_type *entry, concptr o_name) -{ - int j; - concptr ptr = entry->name; - - /*** Unaware items ***/ - if (IS_FLG(FLG_UNAWARE) && object_is_aware(o_ptr)) - return FALSE; - - /*** Unidentified ***/ - if (IS_FLG(FLG_UNIDENTIFIED) - && (object_is_known(o_ptr) || (o_ptr->ident & IDENT_SENSE))) - return FALSE; - - /*** Identified ***/ - if (IS_FLG(FLG_IDENTIFIED) && !object_is_known(o_ptr)) - return FALSE; - - /*** *Identified* ***/ - if (IS_FLG(FLG_STAR_IDENTIFIED) && - (!object_is_known(o_ptr) || !(o_ptr->ident & IDENT_MENTAL))) - return FALSE; - - /*** Dice boosted (weapon of slaying) ***/ - if (IS_FLG(FLG_BOOSTED)) - { - object_kind *k_ptr = &k_info[o_ptr->k_idx]; - - /* Require melee weapon */ - if (!object_is_melee_weapon(o_ptr)) - return FALSE; - - /* Require boosted dice */ - if ((o_ptr->dd == k_ptr->dd) && (o_ptr->ds == k_ptr->ds)) - return FALSE; - - /* In Vault Quest, Dice must be hide.*/ - if(!object_is_known(o_ptr) && object_is_quest_target(o_ptr)) - { - return FALSE; - } - } - - /*** Weapons which dd*ds is more than nn ***/ - if (IS_FLG(FLG_MORE_DICE)) - { - if (o_ptr->dd * o_ptr->ds < entry->dice) - return FALSE; - } - - /*** Weapons whic dd*ds is more than nn ***/ - if (IS_FLG(FLG_MORE_BONUS)) - { - if (!object_is_known(o_ptr)) return FALSE; - - if (o_ptr->pval) - { - if (o_ptr->pval < entry->bonus) return FALSE; - } - else - { - if (o_ptr->to_h < entry->bonus && - o_ptr->to_d < entry->bonus && - o_ptr->to_a < entry->bonus && - o_ptr->pval < entry->bonus) - return FALSE; - } - } - - /*** Worthless items ***/ - if (IS_FLG(FLG_WORTHLESS) && object_value(o_ptr) > 0) - return FALSE; - - /*** Artifact object ***/ - if (IS_FLG(FLG_ARTIFACT)) - { - if (!object_is_known(o_ptr) || !object_is_artifact(o_ptr)) - return FALSE; - } - - /*** Ego object ***/ - if (IS_FLG(FLG_EGO)) - { - /* Need to be an ego item */ - if (!object_is_ego(o_ptr)) return FALSE; - - /* Need to be known to be an ego */ - if (!object_is_known(o_ptr) && - !((o_ptr->ident & IDENT_SENSE) && o_ptr->feeling == FEEL_EXCELLENT)) - return FALSE; - } - - /*** Good ***/ - if (IS_FLG(FLG_GOOD)) - { - if (!object_is_equipment(o_ptr)) return FALSE; - - /* Identified */ - if (object_is_known(o_ptr)) - { - /* Artifacts and Ego objects are not okay */ - if (!object_is_nameless(o_ptr)) - return FALSE; - - /* Average are not okay */ - if (o_ptr->to_a <= 0 && (o_ptr->to_h + o_ptr->to_d) <= 0) - return FALSE; - } - - /* Pseudo-identified */ - else if (o_ptr->ident & IDENT_SENSE) - { - switch (o_ptr->feeling) - { - case FEEL_GOOD: - /* It's good */ - break; - - default: - /* It's not good */ - return FALSE; - } - } - - /* Unidentified */ - else - { - /* Not known to be good */ - return FALSE; - } - } - - /*** Nameless ***/ - if (IS_FLG(FLG_NAMELESS)) - { - if (!object_is_equipment(o_ptr)) return FALSE; - - /* Identified */ - if (object_is_known(o_ptr)) - { - /* Artifacts and Ego objects are not okay */ - if (!object_is_nameless(o_ptr)) - return FALSE; - } - - /* Pseudo-identified */ - else if (o_ptr->ident & IDENT_SENSE) - { - switch (o_ptr->feeling) - { - case FEEL_AVERAGE: - case FEEL_GOOD: - case FEEL_BROKEN: - case FEEL_CURSED: - /* It's nameless */ - break; - - default: - /* It's not nameless */ - return FALSE; - } - } - - /* Unidentified */ - else - { - /* Not known to be nameless */ - return FALSE; - } - } - - /*** Average ***/ - if (IS_FLG(FLG_AVERAGE)) - { - if (!object_is_equipment(o_ptr)) return FALSE; - - /* Identified */ - if (object_is_known(o_ptr)) - { - /* Artifacts and Ego objects are not okay */ - if (!object_is_nameless(o_ptr)) - return FALSE; - - /* Cursed or broken objects are not okay */ - if (object_is_cursed(o_ptr) || object_is_broken(o_ptr)) - return FALSE; - - /* Good are not okay */ - if (o_ptr->to_a > 0 || (o_ptr->to_h + o_ptr->to_d) > 0) - return FALSE; - } - - /* Pseudo-identified */ - else if (o_ptr->ident & IDENT_SENSE) - { - switch (o_ptr->feeling) - { - case FEEL_AVERAGE: - /* It's average */ - break; - - default: - /* It's not average */ - return FALSE; - } - } - - /* Unidentified */ - else - { - /* Not known to be average */ - return FALSE; - } - } - - /*** Rere equipments ***/ - if (IS_FLG(FLG_RARE) && !object_is_rare(o_ptr)) - return FALSE; - - /*** Common equipments ***/ - if (IS_FLG(FLG_COMMON) && object_is_rare(o_ptr)) - return FALSE; - - /*** Wanted monster's corpse/skeletons ***/ - if (IS_FLG(FLG_WANTED) && !object_is_shoukinkubi(o_ptr)) - return FALSE; - - /*** Unique monster's corpse/skeletons/statues ***/ - if (IS_FLG(FLG_UNIQUE) && - ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) || - !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE))) - return FALSE; - - /*** Human corpse/skeletons (for Daemon magic) ***/ - if (IS_FLG(FLG_HUMAN) && - (o_ptr->tval != TV_CORPSE || - !my_strchr("pht", r_info[o_ptr->pval].d_char))) - return FALSE; - - /*** Unreadable spellbooks ***/ - if (IS_FLG(FLG_UNREADABLE) && - (o_ptr->tval < TV_LIFE_BOOK || - check_book_realm(o_ptr->tval, o_ptr->sval))) - return FALSE; - - /*** First realm spellbooks ***/ - if (IS_FLG(FLG_REALM1) && - (REALM1_BOOK != o_ptr->tval || - p_ptr->pclass == CLASS_SORCERER || - p_ptr->pclass == CLASS_RED_MAGE)) - return FALSE; - - /*** Second realm spellbooks ***/ - if (IS_FLG(FLG_REALM2) && - (REALM2_BOOK != o_ptr->tval || - p_ptr->pclass == CLASS_SORCERER || - p_ptr->pclass == CLASS_RED_MAGE)) - return FALSE; - - /*** First rank spellbooks ***/ - if (IS_FLG(FLG_FIRST) && - (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval)) - return FALSE; - - /*** Second rank spellbooks ***/ - if (IS_FLG(FLG_SECOND) && - (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval)) - return FALSE; - - /*** Third rank spellbooks ***/ - if (IS_FLG(FLG_THIRD) && - (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval)) - return FALSE; - - /*** Fourth rank spellbooks ***/ - if (IS_FLG(FLG_FOURTH) && - (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval)) - return FALSE; - - /*** Items ***/ - if (IS_FLG(FLG_WEAPONS)) - { - if (!object_is_weapon(o_ptr)) - return FALSE; - } - else if (IS_FLG(FLG_FAVORITE_WEAPONS)) - { - if (!object_is_favorite(o_ptr)) - return FALSE; - } - else if (IS_FLG(FLG_ARMORS)) - { - if (!object_is_armour(o_ptr)) - return FALSE; - } - else if (IS_FLG(FLG_MISSILES)) - { - if (!object_is_ammo(o_ptr)) return FALSE; - } - else if (IS_FLG(FLG_DEVICES)) - { - switch(o_ptr->tval) - { - case TV_SCROLL: case TV_STAFF: case TV_WAND: case TV_ROD: - break; - default: return FALSE; - } - } - else if (IS_FLG(FLG_LIGHTS)) - { - if (!(o_ptr->tval == TV_LITE)) - return FALSE; - } - else if (IS_FLG(FLG_JUNKS)) - { - switch(o_ptr->tval) - { - case TV_SKELETON: case TV_BOTTLE: - case TV_JUNK: case TV_STATUE: - break; - default: return FALSE; - } - } - else if (IS_FLG(FLG_CORPSES)) - { - if (o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_SKELETON) - return FALSE; - } - else if (IS_FLG(FLG_SPELLBOOKS)) - { - if (!(o_ptr->tval >= TV_LIFE_BOOK)) - return FALSE; - } - else if (IS_FLG(FLG_HAFTED)) - { - if (!(o_ptr->tval == TV_HAFTED)) - return FALSE; - } - else if (IS_FLG(FLG_SHIELDS)) - { - if (!(o_ptr->tval == TV_SHIELD)) - return FALSE; - } - else if (IS_FLG(FLG_BOWS)) - { - if (!(o_ptr->tval == TV_BOW)) - return FALSE; - } - else if (IS_FLG(FLG_RINGS)) - { - if (!(o_ptr->tval == TV_RING)) - return FALSE; - } - else if (IS_FLG(FLG_AMULETS)) - { - if (!(o_ptr->tval == TV_AMULET)) - return FALSE; - } - else if (IS_FLG(FLG_SUITS)) - { - if (!(o_ptr->tval == TV_DRAG_ARMOR || - o_ptr->tval == TV_HARD_ARMOR || - o_ptr->tval == TV_SOFT_ARMOR)) - return FALSE; - } - else if (IS_FLG(FLG_CLOAKS)) - { - if (!(o_ptr->tval == TV_CLOAK)) - return FALSE; - } - else if (IS_FLG(FLG_HELMS)) - { - if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM)) - return FALSE; - } - else if (IS_FLG(FLG_GLOVES)) - { - if (!(o_ptr->tval == TV_GLOVES)) - return FALSE; - } - else if (IS_FLG(FLG_BOOTS)) - { - if (!(o_ptr->tval == TV_BOOTS)) - return FALSE; - } - - /* Keyword don't match */ - if (*ptr == '^') - { - ptr++; - if (strncmp(o_name, ptr, strlen(ptr))) return FALSE; - } - else - { - if (!my_strstr(o_name, ptr)) return FALSE; - } - - /* TRUE when it need not to be 'collecting' */ - if (!IS_FLG(FLG_COLLECTING)) return TRUE; - - /* Check if there is a same item */ - for (j = 0; j < INVEN_PACK; j++) - { - /* - * 'Collecting' means the item must be absorbed - * into an inventory slot. - * But an item can not be absorbed into itself! - */ - if ((&inventory[j] != o_ptr) && - object_similar(&inventory[j], o_ptr)) - return TRUE; - } - - /* Not collecting */ - return FALSE; -} - - -/* - * A function for Auto-picker/destroyer - * Examine whether the object matches to the list of keywords or not. - */ -int is_autopick(object_type *o_ptr) -{ - int i; - GAME_TEXT o_name[MAX_NLEN]; - - if (o_ptr->tval == TV_GOLD) return -1; - - /* Prepare object name string first */ - object_desc(o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL)); - - /* Convert the string to lower case */ - str_tolower(o_name); - - /* Look for a matching entry in the list */ - for (i=0; i < max_autopick; i++) - { - autopick_type *entry = &autopick_list[i]; - - if (is_autopick_aux(o_ptr, entry, o_name)) return i; - } - - /* No matching entry */ - return -1; -} - - -/* - * Auto inscription - */ -static void auto_inscribe_item(object_type *o_ptr, int idx) -{ - /* Are there auto-inscription? */ - if (idx < 0 || !autopick_list[idx].insc) return; - - if (!o_ptr->inscription) - o_ptr->inscription = quark_add(autopick_list[idx].insc); - - /* Redraw inscription */ - p_ptr->window |= (PW_EQUIP | PW_INVEN); - - /* {.} and {$} effect p_ptr->warning and TRC_TELEPORT_SELF */ - p_ptr->update |= (PU_BONUS); -} - - -/* - * Automatically destroy items in this grid. - */ -static bool is_opt_confirm_destroy(object_type *o_ptr) -{ - if (!destroy_items) return FALSE; - - /* Known to be worthless? */ - if (leave_worth) - if (object_value(o_ptr) > 0) return FALSE; - - if (leave_equip) - if (object_is_weapon_armour_ammo(o_ptr)) return FALSE; - - if (leave_chest) - if ((o_ptr->tval == TV_CHEST) && o_ptr->pval) return FALSE; - - if (leave_wanted) - { - if (object_is_shoukinkubi(o_ptr)) return FALSE; - } - - if (leave_corpse) - if (o_ptr->tval == TV_CORPSE) return FALSE; - - if (leave_junk) - if ((o_ptr->tval == TV_SKELETON) || (o_ptr->tval == TV_BOTTLE) || (o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_STATUE)) return FALSE; - - if (leave_special) - { - if (p_ptr->prace == RACE_DEMON) - { - if (o_ptr->tval == TV_CORPSE && - o_ptr->sval == SV_CORPSE && - my_strchr("pht", r_info[o_ptr->pval].d_char)) - return FALSE; - } - - if (p_ptr->pclass == CLASS_ARCHER) - { - if (o_ptr->tval == TV_SKELETON || - (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON)) - return FALSE; - } - else if (p_ptr->pclass == CLASS_NINJA) - { - if (o_ptr->tval == TV_LITE && - o_ptr->name2 == EGO_LITE_DARKNESS && object_is_known(o_ptr)) - return FALSE; - } - else if (p_ptr->pclass == CLASS_BEASTMASTER || - p_ptr->pclass == CLASS_CAVALRY) - { - if (o_ptr->tval == TV_WAND && - o_ptr->sval == SV_WAND_HEAL_MONSTER && object_is_aware(o_ptr)) - return FALSE; - } - } - - if (o_ptr->tval == TV_GOLD) return FALSE; - - return TRUE; -} - - -/* - * Automatically destroy an item if it is to be destroyed - * - * When always_pickup is 'yes', we disable auto-destroyer function of - * auto-picker/destroyer, and do only easy-auto-destroyer. - */ -static object_type autopick_last_destroyed_object; - -static void auto_destroy_item(object_type *o_ptr, int autopick_idx) -{ - bool destroy = FALSE; - - /* Easy-Auto-Destroyer (3rd priority) */ - if (is_opt_confirm_destroy(o_ptr)) destroy = TRUE; - - /* Protected by auto-picker (2nd priotity) */ - if (autopick_idx >= 0 && - !(autopick_list[autopick_idx].action & DO_AUTODESTROY)) - destroy = FALSE; - - /* Auto-destroyer works only when !always_pickup */ - if (!always_pickup) - { - /* Auto-picker/destroyer (1st priority) */ - if (autopick_idx >= 0 && - (autopick_list[autopick_idx].action & DO_AUTODESTROY)) - destroy = TRUE; - } - - /* Not to be destroyed */ - if (!destroy) return; - - /* Now decided to destroy */ - - disturb(FALSE, FALSE); - - /* Artifact? */ - if (!can_player_destroy_object(o_ptr)) - { - GAME_TEXT o_name[MAX_NLEN]; - - /* Describe the object (with {terrible/special}) */ - object_desc(o_name, o_ptr, 0); - - msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name); - - return; - } - - /* Record name of destroyed item */ - (void)COPY(&autopick_last_destroyed_object, o_ptr, object_type); - - /* Destroy Later */ - o_ptr->marked |= OM_AUTODESTROY; - p_ptr->update |= PU_AUTODESTROY; - - return; -} - - -/* - * Auto-destroy marked item - */ -static void autopick_delayed_alter_aux(INVENTORY_IDX item) -{ - object_type *o_ptr; - - /* Get the item (in the pack) */ - if (item >= 0) o_ptr = &inventory[item]; - - /* Get the item (on the floor) */ - else o_ptr = ¤t_floor_ptr->o_list[0 - item]; - - if (o_ptr->k_idx && (o_ptr->marked & OM_AUTODESTROY)) - { - GAME_TEXT o_name[MAX_NLEN]; - - /* Describe the object (with {terrible/special}) */ - object_desc(o_name, o_ptr, 0); - - /* Eliminate the item (from the pack) */ - if (item >= 0) - { - inven_item_increase(item, -(o_ptr->number)); - inven_item_optimize(item); - } - - /* Eliminate the item (from the floor) */ - else - { - delete_object_idx(0 - item); - } - - msg_format(_("%sを自動破壊します。", "Auto-destroying %s."), o_name); - } -} - - -/* - * Auto-destroy marked items in inventry and on floor - */ -void autopick_delayed_alter(void) -{ - INVENTORY_IDX item; - - /* - * Scan inventry in reverse order to prevent - * skipping after inven_item_optimize() - */ - for (item = INVEN_TOTAL - 1; item >= 0 ; item--) - autopick_delayed_alter_aux(item); - - /* Scan the pile of objects */ - item = current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].o_idx; - while (item) - { - OBJECT_IDX next = current_floor_ptr->o_list[item].next_o_idx; - autopick_delayed_alter_aux(-item); - item = next; - } -} - - -/* - * Auto-inscription and/or destroy - * - * Auto-destroyer works only on inventory or on floor stack only when - * requested. - */ -void autopick_alter_item(INVENTORY_IDX item, bool destroy) -{ - object_type *o_ptr; - int idx; - - /* Get the item (in the pack) */ - if (item >= 0) o_ptr = &inventory[item]; - - /* Get the item (on the floor) */ - else o_ptr = ¤t_floor_ptr->o_list[0 - item]; - - /* Get the index in the auto-pick/destroy list */ - idx = is_autopick(o_ptr); - - /* Do auto-inscription */ - auto_inscribe_item(o_ptr, idx); - - /* Do auto-destroy if needed */ - if (destroy && item <= INVEN_PACK) - auto_destroy_item(o_ptr, idx); -} - - -/* - * Automatically pickup/destroy items in this grid. - */ -void autopick_pickup_items(grid_type *g_ptr) -{ - OBJECT_IDX this_o_idx, next_o_idx = 0; - - /* Scan the pile of objects */ - for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) - { - int idx; - object_type *o_ptr = ¤t_floor_ptr->o_list[this_o_idx]; - next_o_idx = o_ptr->next_o_idx; - - idx = is_autopick(o_ptr); - - /* Item index for floor -1,-2,-3,... */ - auto_inscribe_item(o_ptr, idx); - - if (idx >= 0 && - (autopick_list[idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK))) - { - disturb(FALSE, FALSE); - - if (!inven_carry_okay(o_ptr)) - { - GAME_TEXT o_name[MAX_NLEN]; - - object_desc(o_name, o_ptr, 0); - - msg_format(_("ザックには%sを入れる隙間がない。", "You have no room for %s."), o_name); - /* Hack - remember that the item has given a message here. */ - o_ptr->marked |= OM_NOMSG; - - continue; - } - else if (autopick_list[idx].action & DO_QUERY_AUTOPICK) - { - char out_val[MAX_NLEN+20]; - GAME_TEXT o_name[MAX_NLEN]; - - if (o_ptr->marked & OM_NO_QUERY) - { - /* Already answered as 'No' */ - continue; - } - - object_desc(o_name, o_ptr, 0); - - sprintf(out_val, _("%sを拾いますか? ", "Pick up %s? "), o_name); - - if (!get_check(out_val)) - { - /* Hack - remember that the item has given a message here. */ - o_ptr->marked |= (OM_NOMSG | OM_NO_QUERY); - continue; - } - - } - py_pickup_aux(this_o_idx); - } - - /* - * Do auto-destroy; - * When always_pickup is 'yes', we disable - * auto-destroyer from autopick function, and do only - * easy-auto-destroyer. - */ - else - { - auto_destroy_item(o_ptr, idx); - } - } /* for () */ -} - - -static const char autoregister_header[] = "?:$AUTOREGISTER"; - -/* - * Clear auto registered lines in the picktype.prf . - */ -static bool clear_auto_register(void) -{ - char tmp_file[1024]; - char pref_file[1024]; - char buf[1024]; - FILE *pref_fff; - FILE *tmp_fff; - int num = 0; - bool autoregister = FALSE; - bool okay = TRUE; - - path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_WITH_PNAME)); - pref_fff = my_fopen(pref_file, "r"); - - if (!pref_fff) - { - path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_DEFAULT)); - pref_fff = my_fopen(pref_file, "r"); - } - - if (!pref_fff) - { - /* No file yet */ - return TRUE; - } - - /* Open a new (temporary) file */ - tmp_fff = my_fopen_temp(tmp_file, sizeof(tmp_file)); - - if (!tmp_fff) - { - /* Close the preference file */ - fclose(pref_fff); - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file); - msg_print(NULL); - return FALSE; - } - - - /* Loop for every line */ - while (TRUE) - { - /* Read a line */ - if (my_fgets(pref_fff, buf, sizeof(buf))) break; - - if (autoregister) - { - /* Delete auto-registered line */ - - /* Count auto-destroy preference lines */ - if (buf[0] != '#' && buf[0] != '?') num++; - } - - /* We are looking for auto-registered line */ - else - { - if (streq(buf, autoregister_header)) - { - /* Delete all further lines */ - autoregister = TRUE; - } - else - { - /* Copy orginally lines */ - fprintf(tmp_fff, "%s\n", buf); - } - } - } - - /* Close files */ - my_fclose(pref_fff); - my_fclose(tmp_fff); - - if (num) - { - msg_format(_("以前のキャラクター用の自動設定(%d行)が残っています。", - "Auto registered lines (%d lines) for previous character are remaining."), num); - strcpy(buf, _("古い設定行は削除します。よろしいですか?", "These lines will be deleted. Are you sure? ")); - - /* You can cancel it */ - if (!get_check(buf)) - { - okay = FALSE; - autoregister = FALSE; - - msg_print(_("エディタのカット&ペースト等を使って必要な行を避難してください。", - "Use cut & paste of auto picker editor (_) to keep old prefs.")); - } - } - - - /* If there are some changes, overwrite the original file with new one */ - if (autoregister) - { - /* Copy contents of temporary file */ - - tmp_fff = my_fopen(tmp_file, "r"); - pref_fff = my_fopen(pref_file, "w"); - - while (!my_fgets(tmp_fff, buf, sizeof(buf))) - fprintf(pref_fff, "%s\n", buf); - - my_fclose(pref_fff); - my_fclose(tmp_fff); - } - - /* Kill the temporary file */ - fd_kill(tmp_file); - - return okay; -} - - -/* - * Automatically register an auto-destroy preference line - */ -bool autopick_autoregister(object_type *o_ptr) -{ - char buf[1024]; - char pref_file[1024]; - FILE *pref_fff; - autopick_type an_entry, *entry = &an_entry; - - int match_autopick = is_autopick(o_ptr); - - /* Already registered */ - if (match_autopick != -1) - { - concptr what; - byte act = autopick_list[match_autopick].action; - - if (act & DO_AUTOPICK) what = _("自動で拾う", "auto-pickup"); - else if (act & DO_AUTODESTROY) what = _("自動破壊する", "auto-destroy"); - else if (act & DONT_AUTOPICK) what = _("放置する", "leave on floor"); - else /* if (act & DO_QUERY_AUTOPICK) */ what = _("確認して拾う", "query auto-pickup"); - - msg_format(_("そのアイテムは既に%sように設定されています。", "The object is already registered to %s."), what); - return FALSE; - } - - /* Known to be an artifact? */ - if ((object_is_known(o_ptr) && object_is_artifact(o_ptr)) || - ((o_ptr->ident & IDENT_SENSE) && - (o_ptr->feeling == FEEL_TERRIBLE || o_ptr->feeling == FEEL_SPECIAL))) - { - GAME_TEXT o_name[MAX_NLEN]; - - /* Describe the object (with {terrible/special}) */ - object_desc(o_name, o_ptr, 0); - - msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name); - - return FALSE; - } - - - if (!p_ptr->autopick_autoregister) - { - /* Clear old auto registered lines */ - if (!clear_auto_register()) return FALSE; - } - - /* Try a filename with player name */ - path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_WITH_PNAME)); - pref_fff = my_fopen(pref_file, "r"); - - if (!pref_fff) - { - /* Use default name */ - path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_DEFAULT)); - pref_fff = my_fopen(pref_file, "r"); - } - - /* Check the header */ - while (TRUE) - { - /* Read a line */ - if (my_fgets(pref_fff, buf, sizeof(buf))) - { - /* No header found */ - p_ptr->autopick_autoregister = FALSE; - - break; - } - - if (streq(buf, autoregister_header)) - { - /* Found the header */ - p_ptr->autopick_autoregister = TRUE; - - break; - } - } - - /* Close read only FILE* */ - fclose(pref_fff); - - /* Open for append */ - pref_fff = my_fopen(pref_file, "a"); - - /* Failure */ - if (!pref_fff) { - msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), pref_file); - msg_print(NULL); - - /* Failed */ - return FALSE; - } - - if (!p_ptr->autopick_autoregister) - { - /* Add the header */ - fprintf(pref_fff, "%s\n", autoregister_header); - - fprintf(pref_fff, "%s\n", _("# *警告!!* 以降の行は自動登録されたものです。", - "# *Waring!* The lines below will be deleated later.")); - fprintf(pref_fff, "%s\n", _("# 後で自動的に削除されますので、必要な行は上の方へ移動しておいてください。", - "# Keep it by cut & paste if you need these lines for future characters.")); - - /* Now auto register is in-use */ - p_ptr->autopick_autoregister = TRUE; - } - - /* Get a preference entry */ - autopick_entry_from_object(entry, o_ptr); - - /* Set to auto-destroy (with no-display) */ - entry->action = DO_AUTODESTROY; - - /* Load the new line as preference */ - add_autopick_list(entry); - - /* Add a line to the file */ - /* Don't kill "entry" */ - fprintf(pref_fff, "%s\n", autopick_line_from_entry(entry)); - fclose(pref_fff); - - return TRUE; -} - - -/******** Auto-picker/destroyer editor **********/ - -#define MAX_YANK MAX_LINELEN -#define MAX_LINES 3000 - -#define MARK_MARK 0x01 -#define MARK_BY_SHIFT 0x02 - -#define LSTAT_BYPASS 0x01 -#define LSTAT_EXPRESSION 0x02 -#define LSTAT_AUTOREGISTER 0x04 - -#define QUIT_WITHOUT_SAVE 1 -#define QUIT_AND_SAVE 2 - -/* - * Struct for yank buffer - */ -typedef struct chain_str { - struct chain_str *next; - char s[1]; -} chain_str_type; - - -/* - * Data struct for text editor - */ -typedef struct { - int wid, hgt; - int cx, cy; - int upper, left; - int old_wid, old_hgt; - int old_cy; - int old_upper, old_left; - int mx, my; - byte mark; - - object_type *search_o_ptr; - concptr search_str; - concptr last_destroyed; - - chain_str_type *yank; - bool yank_eol; - - concptr *lines_list; - byte states[MAX_LINES]; - - u16b dirty_flags; - int dirty_line; - int filename_mode; - int old_com_id; - - bool changed; -} text_body_type; - - -/* - * Dirty flag for text editor - */ -#define DIRTY_ALL 0x0001 -#define DIRTY_MODE 0x0004 -#define DIRTY_SCREEN 0x0008 -#define DIRTY_NOT_FOUND 0x0010 -#define DIRTY_NO_SEARCH 0x0020 -#define DIRTY_EXPRESSION 0x0040 -#define DIRTY_SKIP_INACTIVE 0x0080 -#define DIRTY_INACTIVE 0x0100 - -/* - * Describe which kind of object is Auto-picked/destroyed - */ -static void describe_autopick(char *buff, autopick_type *entry) -{ - concptr str = entry->name; - byte act = entry->action; - concptr insc = entry->insc; - int i; - - bool top = FALSE; - -#ifdef JP - concptr before_str[100], body_str; - int before_n = 0; - - body_str = "アイテム"; - - /*** Collecting items ***/ - /*** Which can be absorbed into a slot as a bundle ***/ - if (IS_FLG(FLG_COLLECTING)) - before_str[before_n++] = "収集中で既に持っているスロットにまとめられる"; - - /*** Unaware items ***/ - if (IS_FLG(FLG_UNAWARE)) - before_str[before_n++] = "未鑑定でその効果も判明していない"; - - /*** Unidentified ***/ - if (IS_FLG(FLG_UNIDENTIFIED)) - before_str[before_n++] = "未鑑定の"; - - /*** Identified ***/ - if (IS_FLG(FLG_IDENTIFIED)) - before_str[before_n++] = "鑑定済みの"; - - /*** *Identified* ***/ - if (IS_FLG(FLG_STAR_IDENTIFIED)) - before_str[before_n++] = "完全に鑑定済みの"; - - /*** Dice boosted (weapon of slaying) ***/ - if (IS_FLG(FLG_BOOSTED)) - { - before_str[before_n++] = "ダメージダイスが通常より大きい"; - body_str = "武器"; - } - - /*** Weapons whose dd*ds is more than nn ***/ - if (IS_FLG(FLG_MORE_DICE)) - { - static char more_than_desc_str[] = "___"; - before_str[before_n++] = "ダメージダイスの最大値が"; - body_str = "武器"; - - sprintf(more_than_desc_str,"%d", entry->dice); - before_str[before_n++] = more_than_desc_str; - before_str[before_n++] = "以上の"; - } - - /*** Items whose magical bonus is more than nn ***/ - if (IS_FLG(FLG_MORE_BONUS)) - { - static char more_bonus_desc_str[] = "___"; - before_str[before_n++] = "修正値が(+"; - - sprintf(more_bonus_desc_str,"%d", entry->bonus); - before_str[before_n++] = more_bonus_desc_str; - before_str[before_n++] = ")以上の"; - } - - /*** Worthless items ***/ - if (IS_FLG(FLG_WORTHLESS)) - before_str[before_n++] = "店で無価値と判定される"; - - /*** Artifact ***/ - if (IS_FLG(FLG_ARTIFACT)) - { - before_str[before_n++] = "アーティファクトの"; - body_str = "装備"; - } - - /*** Ego ***/ - if (IS_FLG(FLG_EGO)) - { - before_str[before_n++] = "エゴアイテムの"; - body_str = "装備"; - } - - /*** Good ***/ - if (IS_FLG(FLG_GOOD)) - { - before_str[before_n++] = "上質の"; - body_str = "装備"; - } - - /*** Nameless ***/ - if (IS_FLG(FLG_NAMELESS)) - { - before_str[before_n++] = "エゴでもアーティファクトでもない"; - body_str = "装備"; - } - - /*** Average ***/ - if (IS_FLG(FLG_AVERAGE)) - { - before_str[before_n++] = "並の"; - body_str = "装備"; - } - - /*** Rare equipments ***/ - if (IS_FLG(FLG_RARE)) - { - before_str[before_n++] = "ドラゴン装備やカオス・ブレード等を含む珍しい"; - body_str = "装備"; - } - - /*** Common equipments ***/ - if (IS_FLG(FLG_COMMON)) - { - before_str[before_n++] = "ありふれた(ドラゴン装備やカオス・ブレード等の珍しい物ではない)"; - body_str = "装備"; - } - - /*** Wanted monster's corpse/skeletons ***/ - if (IS_FLG(FLG_WANTED)) - { - before_str[before_n++] = "ハンター事務所で賞金首とされている"; - body_str = "死体や骨"; - } - - /*** Human corpse/skeletons (for Daemon magic) ***/ - if (IS_FLG(FLG_HUMAN)) - { - before_str[before_n++] = "悪魔魔法で使うための人間やヒューマノイドの"; - body_str = "死体や骨"; - } - - /*** Unique monster's corpse/skeletons/statues ***/ - if (IS_FLG(FLG_UNIQUE)) - { - before_str[before_n++] = "ユニークモンスターの"; - body_str = "死体や骨"; - } - - /*** Unreadable spellbooks ***/ - if (IS_FLG(FLG_UNREADABLE)) - { - before_str[before_n++] = "あなたが読めない領域の"; - body_str = "魔法書"; - } - - /*** First realm spellbooks ***/ - if (IS_FLG(FLG_REALM1)) - { - before_str[before_n++] = "第一領域の"; - body_str = "魔法書"; - } - - /*** Second realm spellbooks ***/ - if (IS_FLG(FLG_REALM2)) - { - before_str[before_n++] = "第二領域の"; - body_str = "魔法書"; - } - - /*** First rank spellbooks ***/ - if (IS_FLG(FLG_FIRST)) - { - before_str[before_n++] = "全4冊の内の1冊目の"; - body_str = "魔法書"; - } - - /*** Second rank spellbooks ***/ - if (IS_FLG(FLG_SECOND)) - { - before_str[before_n++] = "全4冊の内の2冊目の"; - body_str = "魔法書"; - } - - /*** Third rank spellbooks ***/ - if (IS_FLG(FLG_THIRD)) - { - before_str[before_n++] = "全4冊の内の3冊目の"; - body_str = "魔法書"; - } - - /*** Fourth rank spellbooks ***/ - if (IS_FLG(FLG_FOURTH)) - { - before_str[before_n++] = "全4冊の内の4冊目の"; - body_str = "魔法書"; - } - - /*** Items ***/ - if (IS_FLG(FLG_ITEMS)) - ; /* Nothing to do */ - else if (IS_FLG(FLG_WEAPONS)) - body_str = "武器"; - else if (IS_FLG(FLG_FAVORITE_WEAPONS)) - body_str = "得意武器"; - else if (IS_FLG(FLG_ARMORS)) - body_str = "防具"; - else if (IS_FLG(FLG_MISSILES)) - body_str = "弾や矢やクロスボウの矢"; - else if (IS_FLG(FLG_DEVICES)) - body_str = "巻物や魔法棒や杖やロッド"; - else if (IS_FLG(FLG_LIGHTS)) - body_str = "光源用のアイテム"; - else if (IS_FLG(FLG_JUNKS)) - body_str = "折れた棒等のガラクタ"; - else if (IS_FLG(FLG_CORPSES)) - body_str = "死体や骨"; - else if (IS_FLG(FLG_SPELLBOOKS)) - body_str = "魔法書"; - else if (IS_FLG(FLG_HAFTED)) - body_str = "鈍器"; - else if (IS_FLG(FLG_SHIELDS)) - body_str = "盾"; - else if (IS_FLG(FLG_BOWS)) - body_str = "スリングや弓やクロスボウ"; - else if (IS_FLG(FLG_RINGS)) - body_str = "指輪"; - else if (IS_FLG(FLG_AMULETS)) - body_str = "アミュレット"; - else if (IS_FLG(FLG_SUITS)) - body_str = "鎧"; - else if (IS_FLG(FLG_CLOAKS)) - body_str = "クローク"; - else if (IS_FLG(FLG_HELMS)) - body_str = "ヘルメットや冠"; - else if (IS_FLG(FLG_GLOVES)) - body_str = "籠手"; - else if (IS_FLG(FLG_BOOTS)) - body_str = "ブーツ"; - - *buff = '\0'; - if (!before_n) - strcat(buff, "全ての"); - else for (i = 0; i < before_n && before_str[i]; i++) - strcat(buff, before_str[i]); - - strcat(buff, body_str); - - if (*str) - { - if (*str == '^') - { - str++; - top = TRUE; - } - - strcat(buff, "で、名前が「"); - strncat(buff, str, 80); - if (top) - strcat(buff, "」で始まるもの"); - else - strcat(buff, "」を含むもの"); - } - - if (insc) - { - strncat(buff, format("に「%s」", insc), 80); - - if (my_strstr(insc, "%%all")) - strcat(buff, "(%%allは全能力を表す英字の記号で置換)"); - else if (my_strstr(insc, "%all")) - strcat(buff, "(%allは全能力を表す記号で置換)"); - else if (my_strstr(insc, "%%")) - strcat(buff, "(%%は追加能力を表す英字の記号で置換)"); - else if (my_strstr(insc, "%")) - strcat(buff, "(%は追加能力を表す記号で置換)"); - - strcat(buff, "と刻んで"); - } - else - strcat(buff, "を"); - - if (act & DONT_AUTOPICK) - strcat(buff, "放置する。"); - else if (act & DO_AUTODESTROY) - strcat(buff, "破壊する。"); - else if (act & DO_QUERY_AUTOPICK) - strcat(buff, "確認の後に拾う。"); - else - strcat(buff, "拾う。"); - - if (act & DO_DISPLAY) - { - if (act & DONT_AUTOPICK) - strcat(buff, "全体マップ('M')で'N'を押したときに表示する。"); - else if (act & DO_AUTODESTROY) - strcat(buff, "全体マップ('M')で'K'を押したときに表示する。"); - else - strcat(buff, "全体マップ('M')で'M'を押したときに表示する。"); - } - else - strcat(buff, "全体マップには表示しない。"); - -#else /* JP */ - - concptr before_str[20], after_str[20], which_str[20], whose_str[20], body_str; - int before_n = 0, after_n = 0, which_n = 0, whose_n = 0; - - body_str = "items"; - - /*** Collecting items ***/ - /*** Which can be absorbed into a slot as a bundle ***/ - if (IS_FLG(FLG_COLLECTING)) - which_str[which_n++] = "can be absorbed into an existing inventory slot"; - - /*** Unaware items ***/ - if (IS_FLG(FLG_UNAWARE)) - { - before_str[before_n++] = "unidentified"; - whose_str[whose_n++] = "basic abilities are not known"; - } - - /*** Unidentified ***/ - if (IS_FLG(FLG_UNIDENTIFIED)) - before_str[before_n++] = "unidentified"; - - /*** Identified ***/ - if (IS_FLG(FLG_IDENTIFIED)) - before_str[before_n++] = "identified"; - - /*** *Identified* ***/ - if (IS_FLG(FLG_STAR_IDENTIFIED)) - before_str[before_n++] = "fully identified"; - - /*** Rare equipments ***/ - if (IS_FLG(FLG_RARE)) - { - before_str[before_n++] = "very rare"; - body_str = "equipments"; - after_str[after_n++] = "such like Dragon armors, Blades of Chaos, etc."; - } - - /*** Common equipments ***/ - if (IS_FLG(FLG_COMMON)) - { - before_str[before_n++] = "relatively common"; - body_str = "equipments"; - after_str[after_n++] = "compared to very rare Dragon armors, Blades of Chaos, etc."; - } - - /*** Worthless items ***/ - if (IS_FLG(FLG_WORTHLESS)) - { - before_str[before_n++] = "worthless"; - which_str[which_n++] = "can not be sold at stores"; - } - - /*** Artifacto ***/ - if (IS_FLG(FLG_ARTIFACT)) - { - before_str[before_n++] = "artifact"; - } - - /*** Ego ***/ - if (IS_FLG(FLG_EGO)) - { - before_str[before_n++] = "ego"; - } - - /*** Good ***/ - if (IS_FLG(FLG_GOOD)) - { - body_str = "equipment"; - which_str[which_n++] = "have good quality"; - } - - /*** Nameless ***/ - if (IS_FLG(FLG_NAMELESS)) - { - body_str = "equipment"; - which_str[which_n++] = "is neither ego-item nor artifact"; - } - - /*** Average ***/ - if (IS_FLG(FLG_AVERAGE)) - { - body_str = "equipment"; - which_str[which_n++] = "have average quality"; - } - - /*** Dice boosted (weapon of slaying) ***/ - if (IS_FLG(FLG_BOOSTED)) - { - body_str = "weapons"; - whose_str[whose_n++] = "damage dice is bigger than normal"; - } - - /*** Weapons whose dd*ds is more than nn ***/ - if (IS_FLG(FLG_MORE_DICE)) - { - static char more_than_desc_str[] = - "maximum damage from dice is bigger than __"; - body_str = "weapons"; - - sprintf(more_than_desc_str + sizeof(more_than_desc_str) - 3, - "%d", entry->dice); - whose_str[whose_n++] = more_than_desc_str; - } - - /*** Items whose magical bonus is more than nn ***/ - if (IS_FLG(FLG_MORE_BONUS)) - { - static char more_bonus_desc_str[] = - "magical bonus is bigger than (+__)"; - - sprintf(more_bonus_desc_str + sizeof(more_bonus_desc_str) - 4, - "%d)", entry->bonus); - whose_str[whose_n++] = more_bonus_desc_str; - } - - /*** Wanted monster's corpse/skeletons ***/ - if (IS_FLG(FLG_WANTED)) - { - body_str = "corpse or skeletons"; - which_str[which_n++] = "is wanted at the Hunter's Office"; - } - - /*** Human corpse/skeletons (for Daemon magic) ***/ - if (IS_FLG(FLG_HUMAN)) - { - before_str[before_n++] = "humanoid"; - body_str = "corpse or skeletons"; - which_str[which_n++] = "can be used for Daemon magic"; - } - - /*** Unique monster's corpse/skeletons/statues ***/ - if (IS_FLG(FLG_UNIQUE)) - { - before_str[before_n++] = "unique monster's"; - body_str = "corpse or skeletons"; - } - - /*** Unreadable spellbooks ***/ - if (IS_FLG(FLG_UNREADABLE)) - { - body_str = "spellbooks"; - after_str[after_n++] = "of different realms from yours"; - } - - /*** First realm spellbooks ***/ - if (IS_FLG(FLG_REALM1)) - { - body_str = "spellbooks"; - after_str[after_n++] = "of your first realm"; - } - - /*** Second realm spellbooks ***/ - if (IS_FLG(FLG_REALM2)) - { - body_str = "spellbooks"; - after_str[after_n++] = "of your second realm"; - } - - /*** First rank spellbooks ***/ - if (IS_FLG(FLG_FIRST)) - { - before_str[before_n++] = "first one of four"; - body_str = "spellbooks"; - } - - /*** Second rank spellbooks ***/ - if (IS_FLG(FLG_SECOND)) - { - before_str[before_n++] = "second one of four"; - body_str = "spellbooks"; - } - - /*** Third rank spellbooks ***/ - if (IS_FLG(FLG_THIRD)) - { - before_str[before_n++] = "third one of four"; - body_str = "spellbooks"; - } - - /*** Fourth rank spellbooks ***/ - if (IS_FLG(FLG_FOURTH)) - { - before_str[before_n++] = "fourth one of four"; - body_str = "spellbooks"; - } - - /*** Items ***/ - if (IS_FLG(FLG_ITEMS)) - ; /* Nothing to do */ - else if (IS_FLG(FLG_WEAPONS)) - body_str = "weapons"; - else if (IS_FLG(FLG_FAVORITE_WEAPONS)) - body_str = "favorite weapons"; - else if (IS_FLG(FLG_ARMORS)) - body_str = "armors"; - else if (IS_FLG(FLG_MISSILES)) - body_str = "shots, arrows or crossbow bolts"; - else if (IS_FLG(FLG_DEVICES)) - body_str = "scrolls, wands, staves or rods"; - else if (IS_FLG(FLG_LIGHTS)) - body_str = "light sources"; - else if (IS_FLG(FLG_JUNKS)) - body_str = "junk such as broken sticks"; - else if (IS_FLG(FLG_CORPSES)) - body_str = "corpses or skeletons"; - else if (IS_FLG(FLG_SPELLBOOKS)) - body_str = "spellbooks"; - else if (IS_FLG(FLG_HAFTED)) - body_str = "hafted weapons"; - else if (IS_FLG(FLG_SHIELDS)) - body_str = "shields"; - else if (IS_FLG(FLG_BOWS)) - body_str = "slings, bows or crossbows"; - else if (IS_FLG(FLG_RINGS)) - body_str = "rings"; - else if (IS_FLG(FLG_AMULETS)) - body_str = "amulets"; - else if (IS_FLG(FLG_SUITS)) - body_str = "body armors"; - else if (IS_FLG(FLG_CLOAKS)) - body_str = "cloaks"; - else if (IS_FLG(FLG_HELMS)) - body_str = "helms or crowns"; - else if (IS_FLG(FLG_GLOVES)) - body_str = "gloves"; - else if (IS_FLG(FLG_BOOTS)) - body_str = "boots"; - - /* Prepare a string for item name */ - if (*str) - { - if (*str == '^') - { - str++; - top = TRUE; - whose_str[whose_n++] = "name is beginning with \""; - } - else - which_str[which_n++] = "have \""; - } - - - /* Describe action flag */ - if (act & DONT_AUTOPICK) - strcpy(buff, "Leave on floor "); - else if (act & DO_AUTODESTROY) - strcpy(buff, "Destroy "); - else if (act & DO_QUERY_AUTOPICK) - strcpy(buff, "Ask to pick up "); - else - strcpy(buff, "Pickup "); - - /* Auto-insctiption */ - if (insc) - { - strncat(buff, format("and inscribe \"%s\"", insc), 80); - - if (my_strstr(insc, "%all")) - strcat(buff, ", replacing %all with code string representing all abilities,"); - else if (my_strstr(insc, "%")) - strcat(buff, ", replacing % with code string representing extra random abilities,"); - - strcat(buff, " on "); - } - - /* Adjective */ - if (!before_n) - strcat(buff, "all "); - else for (i = 0; i < before_n && before_str[i]; i++) - { - strcat(buff, before_str[i]); - strcat(buff, " "); - } - - /* Item class */ - strcat(buff, body_str); - - /* of ... */ - for (i = 0; i < after_n && after_str[i]; i++) - { - strcat(buff, " "); - strcat(buff, after_str[i]); - } - - /* which ... */ - for (i = 0; i < whose_n && whose_str[i]; i++) - { - if (i == 0) - strcat(buff, " whose "); - else - strcat(buff, ", and "); - - strcat(buff, whose_str[i]); - } - - /* Item name ; whose name is beginning with "str" */ - if (*str && top) - { - strcat(buff, str); - strcat(buff, "\""); - } - - /* whose ..., and which .... */ - if (whose_n && which_n) - strcat(buff, ", and "); - - /* which ... */ - for (i = 0; i < which_n && which_str[i]; i++) - { - if (i == 0) - strcat(buff, " which "); - else - strcat(buff, ", and "); - - strcat(buff, which_str[i]); - } - - /* Item name ; which have "str" as part of its name */ - if (*str && !top) - { - strncat(buff, str, 80); - strcat(buff, "\" as part of its name"); - } - strcat(buff, "."); - - /* Describe whether it will be displayed on the full map or not */ - if (act & DO_DISPLAY) - { - if (act & DONT_AUTOPICK) - strcat(buff, " Display these items when you press the N key in the full 'M'ap."); - else if (act & DO_AUTODESTROY) - strcat(buff, " Display these items when you press the K key in the full 'M'ap."); - else - strcat(buff, " Display these items when you press the M key in the full 'M'ap."); - } - else - strcat(buff, " Not displayed in the full map."); -#endif /* JP */ - -} - - -/* - * Read whole lines of a file to memory - */ -static concptr *read_text_lines(concptr filename) -{ - concptr *lines_list = NULL; - FILE *fff; - - int lines = 0; - char buf[1024]; - - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename); - - /* Open the file */ - fff = my_fopen(buf, "r"); - - if (fff) - { - /* Allocate list of pointers */ - C_MAKE(lines_list, MAX_LINES, concptr); - - /* Parse it */ - while (0 == my_fgets(fff, buf, sizeof(buf))) - { - lines_list[lines++] = string_make(buf); - if (lines >= MAX_LINES - 1) break; - } - if (lines == 0) - lines_list[0] = string_make(""); - - my_fclose(fff); - } - - if (!fff) return NULL; - return lines_list; -} - - -/* - * Copy the default autopick file to the user directory - */ -static void prepare_default_pickpref(void) -{ - const concptr messages[] = { - _("あなたは「自動拾いエディタ」を初めて起動しました。", "You have activated the Auto-Picker Editor for the first time."), - _("自動拾いのユーザー設定ファイルがまだ書かれていないので、", "Since user pref file for autopick is not yet created,"), - _("基本的な自動拾い設定ファイルをlib/pref/picktype.prfからコピーします。", "the default setting is loaded from lib/pref/pickpref.prf ."), - NULL - }; - - char buf[1024]; - FILE *pref_fp; - FILE *user_fp; - int i; - concptr filename = pickpref_filename(PT_DEFAULT); - - /* Display messages */ - for (i = 0; messages[i]; i++) msg_print(messages[i]); - msg_print(NULL); - - - /* Open new file */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename); - user_fp = my_fopen(buf, "w"); - - /* Failed */ - if (!user_fp) return; - - /* Write header messages for a notification */ - fprintf(user_fp, "#***\n"); - for (i = 0; messages[i]; i++) - { - fprintf(user_fp, "#*** %s\n", messages[i]); - } - fprintf(user_fp, "#***\n\n\n"); - - - /* Open the default file */ - path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, filename); - pref_fp = my_fopen(buf, "r"); - - /* Failed */ - if (!pref_fp) - { - my_fclose(user_fp); - return; - } - - /* Copy the contents of default file */ - while (!my_fgets(pref_fp, buf, sizeof(buf))) - fprintf(user_fp, "%s\n", buf); - - my_fclose(user_fp); - my_fclose(pref_fp); -} - -/* - * Read an autopick prefence file to memory - * Prepare default if no user file is found - */ -static concptr *read_pickpref_text_lines(int *filename_mode_p) -{ - char buf[1024]; - concptr *lines_list; - - /* Try a filename with player name */ - *filename_mode_p = PT_WITH_PNAME; - strcpy(buf, pickpref_filename(*filename_mode_p)); - lines_list = read_text_lines(buf); - - if (!lines_list) - { - /* Use default name */ - *filename_mode_p = PT_DEFAULT; - strcpy(buf, pickpref_filename(*filename_mode_p)); - lines_list = read_text_lines(buf); - } - - if (!lines_list) - { - /* There is no preference file in the user directory */ - - /* Copy the default autopick file to the user directory */ - prepare_default_pickpref(); - - /* Use default name again */ - lines_list = read_text_lines(buf); - } - - if (!lines_list) - { - /* Allocate list of pointers */ - C_MAKE(lines_list, MAX_LINES, concptr); - lines_list[0] = string_make(""); - } - return lines_list; -} - - -/* - * Write whole lines of memory to a file. - */ -static bool write_text_lines(concptr filename, concptr *lines_list) -{ - FILE *fff; - - int lines = 0; - char buf[1024]; - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename); - - /* Open the file */ - fff = my_fopen(buf, "w"); - if (fff) - { - for (lines = 0; lines_list[lines]; lines++) - my_fputs(fff, lines_list[lines], 1024); - - my_fclose(fff); - } - - if (!fff) return FALSE; - return TRUE; -} - - -/* - * Free memory of lines_list. - */ -static void free_text_lines(concptr *lines_list) -{ - int lines; - - for (lines = 0; lines_list[lines]; lines++) - string_free(lines_list[lines]); - - /* free list of pointers */ - C_KILL(lines_list, MAX_LINES, concptr); -} - - -/* - * Delete or insert string - */ -static void toggle_keyword(text_body_type *tb, BIT_FLAGS flg) -{ - int by1, by2, y; - bool add = TRUE; - bool fixed = FALSE; - - /* Some lines are selected */ - if (tb->mark) - { - by1 = MIN(tb->my, tb->cy); - by2 = MAX(tb->my, tb->cy); - } - - /* No mark -- Select current line */ - else /* if (!tb->mark) */ - { - by1 = by2 = tb->cy; - } - - - /* Set/Reset flag of each line */ - for (y = by1; y <= by2; y++) - { - autopick_type an_entry, *entry = &an_entry; - - if (!autopick_new_entry(entry, tb->lines_list[y], !fixed)) continue; - - string_free(tb->lines_list[y]); - - if (!fixed) - { - /* Add? or Remove? */ - if (!IS_FLG(flg)) add = TRUE; - else add = FALSE; - - /* No more change */ - fixed = TRUE; - } - - /* You can use only one noun flag */ - if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END) - { - int i; - for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++) - REM_FLG(i); - } - - /* You can use only one identify state flag */ - else if (FLG_UNAWARE <= flg && flg <= FLG_STAR_IDENTIFIED) - { - int i; - for (i = FLG_UNAWARE; i <= FLG_STAR_IDENTIFIED; i++) - REM_FLG(i); - } - - /* You can use only one flag in artifact/ego/nameless */ - else if (FLG_ARTIFACT <= flg && flg <= FLG_AVERAGE) - { - int i; - for (i = FLG_ARTIFACT; i <= FLG_AVERAGE; i++) - REM_FLG(i); - } - - /* You can use only one flag in rare/common */ - else if (FLG_RARE <= flg && flg <= FLG_COMMON) - { - int i; - for (i = FLG_RARE; i <= FLG_COMMON; i++) - REM_FLG(i); - } - - if (add) ADD_FLG(flg); - else REM_FLG(flg); - - tb->lines_list[y] = autopick_line_from_entry_kill(entry); - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - - /* Text is changed */ - tb->changed = TRUE; - } -} - - -/* - * Change command letter - */ -static void toggle_command_letter(text_body_type *tb, byte flg) -{ - autopick_type an_entry, *entry = &an_entry; - int by1, by2, y; - bool add = TRUE; - bool fixed = FALSE; - - /* Some lines are selected */ - if (tb->mark) - { - by1 = MIN(tb->my, tb->cy); - by2 = MAX(tb->my, tb->cy); - } - - /* No mark -- Select current line */ - else /* if (!tb->mark) */ - { - by1 = by2 = tb->cy; - } - - - /* Set/Reset flag of each line */ - for (y = by1; y <= by2; y++) - { - int wid = 0; - - if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue; - - string_free(tb->lines_list[y]); - - if (!fixed) - { - /* Add? or Remove? */ - if (!(entry->action & flg)) add = TRUE; - else add = FALSE; - - /* No more change */ - fixed = TRUE; - } - - /* Count number of letter (by negative number) */ - if (entry->action & DONT_AUTOPICK) wid--; - else if (entry->action & DO_AUTODESTROY) wid--; - else if (entry->action & DO_QUERY_AUTOPICK) wid--; - if (!(entry->action & DO_DISPLAY)) wid--; - - /* Set/Reset the flag */ - if (flg != DO_DISPLAY) - { - entry->action &= ~(DO_AUTOPICK | DONT_AUTOPICK | DO_AUTODESTROY | DO_QUERY_AUTOPICK); - if (add) entry->action |= flg; - else entry->action |= DO_AUTOPICK; - } - else - { - entry->action &= ~(DO_DISPLAY); - if (add) entry->action |= flg; - } - - /* Correct cursor location */ - if (tb->cy == y) - { - if (entry->action & DONT_AUTOPICK) wid++; - else if (entry->action & DO_AUTODESTROY) wid++; - else if (entry->action & DO_QUERY_AUTOPICK) wid++; - if (!(entry->action & DO_DISPLAY)) wid++; - - if (wid > 0) tb->cx++; - if (wid < 0 && tb->cx > 0) tb->cx--; - } - - tb->lines_list[y] = autopick_line_from_entry_kill(entry); - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - - /* Text is changed */ - tb->changed = TRUE; - } -} - -/* - * Delete or insert string - */ -static void add_keyword(text_body_type *tb, BIT_FLAGS flg) -{ - int by1, by2, y; - - /* Some lines are selected */ - if (tb->mark) - { - by1 = MIN(tb->my, tb->cy); - by2 = MAX(tb->my, tb->cy); - } - - /* No mark -- Select current line */ - else /* if (!tb->mark) */ - { - by1 = by2 = tb->cy; - } - - - /* Set/Reset flag of each line */ - for (y = by1; y <= by2; y++) - { - autopick_type an_entry, *entry = &an_entry; - - if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue; - - /* There is the flag already */ - if (IS_FLG(flg)) - { - /* Free memory for the entry */ - autopick_free_entry(entry); - - continue; - } - - string_free(tb->lines_list[y]); - - /* Remove all noun flag */ - if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END) - { - int i; - for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++) - REM_FLG(i); - } - - ADD_FLG(flg); - - tb->lines_list[y] = autopick_line_from_entry_kill(entry); - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - - /* Text is changed */ - tb->changed = TRUE; - } -} - - -/* - * Check if this line is expression or not. - * And update it if it is. - */ -static void check_expression_line(text_body_type *tb, int y) -{ - concptr s = tb->lines_list[y]; - - if ((s[0] == '?' && s[1] == ':') || - (tb->states[y] & LSTAT_BYPASS)) - { - /* Expressions need re-evaluation */ - tb->dirty_flags |= DIRTY_EXPRESSION; - } -} - - -/* - * Add an empty line at the last of the file - */ -static bool add_empty_line(text_body_type *tb) -{ - int k; - - for (k = 0; tb->lines_list[k]; k++) - /* count number of lines */ ; - - /* Too many lines! */ - if (k >= MAX_LINES - 2) return FALSE; - - /* The last line is already empty */ - if (!tb->lines_list[k-1][0]) return FALSE; - - /* Create new empty line */ - tb->lines_list[k] = string_make(""); - - /* Expressions need re-evaluation */ - tb->dirty_flags |= DIRTY_EXPRESSION; - - /* Text is changed */ - tb->changed = TRUE; - - /* A line is added */ - return TRUE; -} - - -/* - * Insert return code and split the line - */ -static bool insert_return_code(text_body_type *tb) -{ - char buf[MAX_LINELEN]; - int i, j, k; - - for (k = 0; tb->lines_list[k]; k++) - /* count number of lines */ ; - - if (k >= MAX_LINES - 2) return FALSE; - k--; - - /* Move down lines */ - for (; tb->cy < k; k--) - { - tb->lines_list[k+1] = tb->lines_list[k]; - tb->states[k+1] = tb->states[k]; - } - - /* Split current line */ - for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++) - { -#ifdef JP - if (iskanji(tb->lines_list[tb->cy][i])) - buf[j++] = tb->lines_list[tb->cy][i++]; -#endif - buf[j++] = tb->lines_list[tb->cy][i]; - } - buf[j] = '\0'; - tb->lines_list[tb->cy+1] = string_make(&tb->lines_list[tb->cy][i]); - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make(buf); - - /* Expressions need re-evaluation */ - tb->dirty_flags |= DIRTY_EXPRESSION; - - /* Text is changed */ - tb->changed = TRUE; - - return TRUE; -} - - -/* - * Choose an item and get auto-picker entry from it. - */ -static bool entry_from_choosed_object(autopick_type *entry) -{ - object_type *o_ptr; - concptr q, s; - - q = _("どのアイテムを登録しますか? ", "Enter which item? "); - s = _("アイテムを持っていない。", "You have nothing to enter."); - o_ptr = choose_object(NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP); - if (!o_ptr) return FALSE; - - autopick_entry_from_object(entry, o_ptr); - return TRUE; -} - - -/* - * Choose an item for search - */ -static byte get_object_for_search(object_type **o_handle, concptr *search_strp) -{ - char buf[MAX_NLEN+20]; - object_type *o_ptr; - concptr q, s; - - q = _("どのアイテムを検索しますか? ", "Enter which item? "); - s = _("アイテムを持っていない。", "You have nothing to enter."); - o_ptr = choose_object(NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP); - if (!o_ptr) return 0; - - *o_handle = o_ptr; - - string_free(*search_strp); - object_desc(buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL)); - *search_strp = string_make(format("<%s>", buf)); - return 1; -} - - -/* - * Prepare for search by destroyed object - */ -static byte get_destroyed_object_for_search(object_type **o_handle, concptr *search_strp) -{ - char buf[MAX_NLEN+20]; - - if (!autopick_last_destroyed_object.k_idx) return 0; - - *o_handle = &autopick_last_destroyed_object; - - string_free(*search_strp); - object_desc(buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL)); - *search_strp = string_make(format("<%s>", buf)); - return 1; -} - - -/* - * Choose an item or string for search - */ -static byte get_string_for_search(object_type **o_handle, concptr *search_strp) -{ - int pos = 0; - - /* - * Text color - * TERM_YELLOW : Overwrite mode - * TERM_WHITE : Insert mode - */ - byte color = TERM_YELLOW; - char buf[MAX_NLEN+20]; - const int len = 80; - - char prompt[] = _("検索(^I:持ち物 ^L:破壊された物): ", "Search key(^I:inven ^L:destroyed): "); - int col = sizeof(prompt) - 1; - - /* Prepare string buffer for edit */ - if (*search_strp) strcpy(buf, *search_strp); - else buf[0] = '\0'; - - /* Object searching mode */ - if (*o_handle) - { - color = TERM_L_GREEN; - } - - /* Display prompt */ - prt(prompt, 0, 0); - - - /* Process input */ - while (TRUE) - { - bool back = FALSE; - int skey; - - /* Display the string */ - Term_erase(col, 0, 255); - Term_putstr(col, 0, -1, color, buf); - - /* Place cursor */ - Term_gotoxy(col + pos, 0); - - /* Get a special key code */ - skey = inkey_special(TRUE); - - /* Analyze the key */ - switch (skey) - { - case SKEY_LEFT: - case KTRL('b'): - { - int i = 0; - - /* Now on insert mode */ - color = TERM_WHITE; - - /* No move at beginning of line */ - if (0 == pos) break; - - while (TRUE) - { - int next_pos = i + 1; - -#ifdef JP - if (iskanji(buf[i])) next_pos++; -#endif - - /* Is there the cursor at next position? */ - if (next_pos >= pos) break; - - /* Move to next */ - i = next_pos; - } - - /* Get previous position */ - pos = i; - - break; - } - - case SKEY_RIGHT: - case KTRL('f'): - /* Now on insert mode */ - color = TERM_WHITE; - - /* No move at end of line */ - if ('\0' == buf[pos]) break; - -#ifdef JP - /* Move right */ - if (iskanji(buf[pos])) pos += 2; - else pos++; -#else - pos++; -#endif - - break; - - case ESCAPE: - return 0; - - case KTRL('r'): - back = TRUE; - /* Fall through */ - - case '\n': - case '\r': - case KTRL('s'): - if (*o_handle) return (back ? -1 : 1); - string_free(*search_strp); - *search_strp = string_make(buf); - *o_handle = NULL; - return (back ? -1 : 1); - - case KTRL('i'): - return get_object_for_search(o_handle, search_strp); - - case KTRL('l'): - /* Prepare string for destroyed object if there is one. */ - if (get_destroyed_object_for_search(o_handle, search_strp)) - return 1; - break; - - case '\010': - { - /* Backspace */ - - int i = 0; - - /* Now on insert mode */ - color = TERM_WHITE; - - /* No move at beginning of line */ - if (0 == pos) break; - - while (TRUE) - { - int next_pos = i + 1; - -#ifdef JP - if (iskanji(buf[i])) next_pos++; -#endif - - /* Is there the cursor at next position? */ - if (next_pos >= pos) break; - - /* Move to next */ - i = next_pos; - } - - /* Get previous position */ - pos = i; - - /* Fall through to 'Delete key' */ - } - - case 0x7F: - case KTRL('d'): - /* Delete key */ - { - int dst, src; - - /* Now on insert mode */ - color = TERM_WHITE; - - /* No move at end of line */ - if ('\0' == buf[pos]) break; - - /* Position of next character */ - src = pos + 1; - -#ifdef JP - /* Next character is one more byte away */ - if (iskanji(buf[pos])) src++; -#endif - - dst = pos; - - /* Move characters at src to dst */ - while ('\0' != (buf[dst++] = buf[src++])) - /* loop */; - - break; - } - - default: - { - /* Insert a character */ - - char tmp[100]; - char c; - - /* Ignore special keys */ - if (skey & SKEY_MASK) break; - - /* Get a character code */ - c = (char)skey; - - /* Was non insert mode? */ - if (color != TERM_WHITE) - { - /* Was object searching mode */ - if (color == TERM_L_GREEN) - { - /* Cancel the mode */ - *o_handle = NULL; - - /* Remove indicating string */ - string_free(*search_strp); - *search_strp = NULL; - } - - /* Overwrite default string */ - buf[0] = '\0'; - - /* Go to insert mode */ - color = TERM_WHITE; - } - - /* Save right part of string */ - strcpy(tmp, buf + pos); -#ifdef JP - if (iskanji(c)) - { - char next; - - /* Bypass macro processing */ - inkey_base = TRUE; - next = inkey(); - - if (pos + 1 < len) - { - buf[pos++] = c; - buf[pos++] = next; - } - else - { - bell(); - } - } - else -#endif - { -#ifdef JP - if (pos < len && (isprint(c) || iskana(c))) -#else - if (pos < len && isprint(c)) -#endif - { - buf[pos++] = c; - } - else - { - bell(); - } - } - - /* Terminate */ - buf[pos] = '\0'; - - /* Write back the left part of string */ - my_strcat(buf, tmp, len + 1); - - break; - } /* default: */ - - } - - /* Object searching mode was cancelled? */ - if (*o_handle && color != TERM_L_GREEN) - { - /* Cancel the mode */ - *o_handle = NULL; - - /* Remove indicating string */ - buf[0] = '\0'; - string_free(*search_strp); - *search_strp = NULL; - - } - - - } /* while (TRUE) */ -} - - -/* - * Search next line matches for o_ptr - */ -static void search_for_object(text_body_type *tb, object_type *o_ptr, bool forward) -{ - autopick_type an_entry, *entry = &an_entry; - GAME_TEXT o_name[MAX_NLEN]; - int bypassed_cy = -1; - - /* Start searching from current cursor position */ - int i = tb->cy; - - /* Prepare object name string first */ - object_desc(o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL)); - - /* Convert the string to lower case */ - str_tolower(o_name); - - while (TRUE) - { - bool match; - - /* End of list? */ - if (forward) - { - if (!tb->lines_list[++i]) break; - } - else - { - if (--i < 0) break; - } - - /* Is this line is a correct entry? */ - if (!autopick_new_entry(entry, tb->lines_list[i], FALSE)) continue; - - /* Does this line match to the object? */ - match = is_autopick_aux(o_ptr, entry, o_name); - autopick_free_entry(entry); - if (!match) continue; - - /* Found a line but it's inactive */ - if (tb->states[i] & LSTAT_BYPASS) - { - /* If it is first found, remember it */ - if (bypassed_cy == -1) bypassed_cy = i; - } - - /* Found an active line! */ - else - { - /* Move to this line */ - tb->cx = 0; - tb->cy = i; - - if (bypassed_cy != -1) - { - /* Mark as some lines are skipped */ - tb->dirty_flags |= DIRTY_SKIP_INACTIVE; - } - - /* Found it! */ - return; - } - } - - if (bypassed_cy != -1) - { - /* Move to the remembered line */ - tb->cx = 0; - tb->cy = bypassed_cy; - - /* Mark as this line is inactive */ - tb->dirty_flags |= DIRTY_INACTIVE; - } - - else - { - /* Mark as NOT FOUND */ - tb->dirty_flags |= DIRTY_NOT_FOUND; - } - - return; -} - - -/* - * Search next line matches to the string - */ -static void search_for_string(text_body_type *tb, concptr search_str, bool forward) -{ - int bypassed_cy = -1; - int bypassed_cx = 0; - - /* Start searching from current cursor position */ - int i = tb->cy; - - while (TRUE) - { - concptr pos; - - /* End of list? */ - if (forward) - { - if (!tb->lines_list[++i]) break; - } - else - { - if (--i < 0) break; - } - - /* Look for the string pattern */ - pos = my_strstr(tb->lines_list[i], search_str); - - /* Not found! */ - if (!pos) continue; - - /* Found a line but it's inactive */ - if ((tb->states[i] & LSTAT_BYPASS) && - !(tb->states[i] & LSTAT_EXPRESSION)) - { - /* If it is first found, remember it */ - if (bypassed_cy == -1) - { - bypassed_cy = i; - bypassed_cx = (int)(pos - tb->lines_list[i]); - } - } - - /* Found an active line! */ - else - { - /* Move to this location */ - tb->cx = (int)(pos - tb->lines_list[i]); - tb->cy = i; - - if (bypassed_cy != -1) - { - /* Mark as some lines are skipped */ - tb->dirty_flags |= DIRTY_SKIP_INACTIVE; - } - - /* Found it! */ - return; - } - } - - if (bypassed_cy != -1) - { - /* Move to the remembered line */ - tb->cx = bypassed_cx; - tb->cy = bypassed_cy; - - /* Mark as this line is inactive */ - tb->dirty_flags |= DIRTY_INACTIVE; - } - - else - { - /* Mark as NOT FOUND */ - tb->dirty_flags |= DIRTY_NOT_FOUND; - } - - return; -} - - - - -/* - * Editor command id's - */ -#define EC_QUIT 1 -#define EC_SAVEQUIT 2 -#define EC_REVERT 3 -#define EC_HELP 4 -#define EC_RETURN 5 -#define EC_LEFT 6 -#define EC_DOWN 7 -#define EC_UP 8 -#define EC_RIGHT 9 -#define EC_BOL 10 -#define EC_EOL 11 -#define EC_PGUP 12 -#define EC_PGDOWN 13 -#define EC_TOP 14 -#define EC_BOTTOM 15 -#define EC_CUT 16 -#define EC_COPY 17 -#define EC_PASTE 18 -#define EC_BLOCK 19 -#define EC_KILL_LINE 20 -#define EC_DELETE_CHAR 21 -#define EC_BACKSPACE 22 -#define EC_SEARCH_STR 23 -#define EC_SEARCH_FORW 24 -#define EC_SEARCH_BACK 25 -#define EC_SEARCH_OBJ 26 -#define EC_SEARCH_DESTROYED 27 -#define EC_INSERT_OBJECT 28 -#define EC_INSERT_DESTROYED 29 -#define EC_INSERT_BLOCK 30 -#define EC_INSERT_MACRO 31 -#define EC_INSERT_KEYMAP 32 -#define EC_CL_AUTOPICK 33 -#define EC_CL_DESTROY 34 -#define EC_CL_LEAVE 35 -#define EC_CL_QUERY 36 -#define EC_CL_NO_DISP 37 -#define EC_OK_COLLECTING 38 -#define EC_IK_UNAWARE 39 -#define EC_IK_UNIDENTIFIED 40 -#define EC_IK_IDENTIFIED 41 -#define EC_IK_STAR_IDENTIFIED 42 -#define EC_OK_BOOSTED 43 -#define EC_OK_MORE_DICE 44 -#define EC_OK_MORE_BONUS 45 -#define EC_OK_WORTHLESS 46 -#define EC_OK_ARTIFACT 47 -#define EC_OK_EGO 48 -#define EC_OK_GOOD 49 -#define EC_OK_NAMELESS 50 -#define EC_OK_AVERAGE 51 -#define EC_OK_RARE 52 -#define EC_OK_COMMON 53 -#define EC_OK_WANTED 54 -#define EC_OK_UNIQUE 55 -#define EC_OK_HUMAN 56 -#define EC_OK_UNREADABLE 57 -#define EC_OK_REALM1 58 -#define EC_OK_REALM2 59 -#define EC_OK_FIRST 60 -#define EC_OK_SECOND 61 -#define EC_OK_THIRD 62 -#define EC_OK_FOURTH 63 -#define EC_KK_WEAPONS 64 -#define EC_KK_FAVORITE_WEAPONS 65 -#define EC_KK_ARMORS 66 -#define EC_KK_MISSILES 67 -#define EC_KK_DEVICES 68 -#define EC_KK_LIGHTS 69 -#define EC_KK_JUNKS 70 -#define EC_KK_CORPSES 71 -#define EC_KK_SPELLBOOKS 72 -#define EC_KK_SHIELDS 73 -#define EC_KK_BOWS 74 -#define EC_KK_RINGS 75 -#define EC_KK_AMULETS 76 -#define EC_KK_SUITS 77 -#define EC_KK_CLOAKS 78 -#define EC_KK_HELMS 79 -#define EC_KK_GLOVES 80 -#define EC_KK_BOOTS 81 - - -/* Manu names */ -#ifdef JP - -static GAME_TEXT MN_QUIT[] = "セーブ無しで終了"; -static GAME_TEXT MN_SAVEQUIT[] = "セーブして終了"; -static GAME_TEXT MN_REVERT[] = "全ての変更を破棄"; -static GAME_TEXT MN_HELP[] = "ヘルプ"; - -static GAME_TEXT MN_MOVE[] = "カーソル移動"; -static GAME_TEXT MN_LEFT[] = "å·¦ (←矢印キー)"; -static GAME_TEXT MN_DOWN[] = "下 (↓矢印キー)"; -static GAME_TEXT MN_UP[] = "上 (↑矢印キー)"; -static GAME_TEXT MN_RIGHT[] = "右 (→矢印キー)"; -static GAME_TEXT MN_BOL[] = "行の先頭"; -static GAME_TEXT MN_EOL[] = "行の終端"; -static GAME_TEXT MN_PGUP[] = "上のページ (PageUpキー)"; -static GAME_TEXT MN_PGDOWN[] = "下のページ (PageDownキー)"; -static GAME_TEXT MN_TOP[] = "1行目へ移動 (Homeキー)"; -static GAME_TEXT MN_BOTTOM[] = "最下行へ移動(Endキー)"; - -static GAME_TEXT MN_EDIT[] = "編集"; -static GAME_TEXT MN_CUT[] = "カット"; -static GAME_TEXT MN_COPY[] = "コピー"; -static GAME_TEXT MN_PASTE[] = "ペースト"; -static GAME_TEXT MN_BLOCK[] = "選択範囲の指定"; -static GAME_TEXT MN_KILL_LINE[] = "行の残りを削除"; -static GAME_TEXT MN_DELETE_CHAR[] = "1文字削除"; -static GAME_TEXT MN_BACKSPACE[] = "バックスペース"; -static GAME_TEXT MN_RETURN[] = "改行"; - -static GAME_TEXT MN_SEARCH[] = "検索"; -static GAME_TEXT MN_SEARCH_STR[] = "文字列で検索"; -static GAME_TEXT MN_SEARCH_FORW[] = "前方へ再検索"; -static GAME_TEXT MN_SEARCH_BACK[] = "後方へ再検索"; -static GAME_TEXT MN_SEARCH_OBJ[] = "アイテムを選択して検索"; -static GAME_TEXT MN_SEARCH_DESTROYED[] = "自動破壊されたアイテムで検索"; - -static GAME_TEXT MN_INSERT[] = "色々挿入"; -static GAME_TEXT MN_INSERT_OBJECT[] = "選択したアイテムの名前を挿入"; -static GAME_TEXT MN_INSERT_DESTROYED[] = "自動破壊されたアイテムの名前を挿入"; -static GAME_TEXT MN_INSERT_BLOCK[] = "条件分岐ブロックの例を挿入"; -static GAME_TEXT MN_INSERT_MACRO[] = "マクロ定義を挿入"; -static GAME_TEXT MN_INSERT_KEYMAP[] = "キーマップ定義を挿入"; - -static GAME_TEXT MN_COMMAND_LETTER[] = "拾い/破壊/放置の選択"; -static GAME_TEXT MN_CL_AUTOPICK[] = "「 」 (自動拾い)"; -static GAME_TEXT MN_CL_DESTROY[] = "「!」 (自動破壊)"; -static GAME_TEXT MN_CL_LEAVE[] = "「~」 (放置)"; -static GAME_TEXT MN_CL_QUERY[] = "「;」 (確認して拾う)"; -static GAME_TEXT MN_CL_NO_DISP[] = "「(」 (マップコマンドで表示しない)"; - -static GAME_TEXT MN_ADJECTIVE_GEN[] = "形容詞(一般)の選択"; -static GAME_TEXT MN_RARE[] = "レアな (装備)"; -static GAME_TEXT MN_COMMON[] = "ありふれた (装備)"; - -static GAME_TEXT MN_ADJECTIVE_SPECIAL[] = "形容詞(特殊)の選択"; -static GAME_TEXT MN_BOOSTED[] = "ダイス目の違う (武器)"; -static GAME_TEXT MN_MORE_DICE[] = "ダイス目 # 以上の (武器)"; -static GAME_TEXT MN_MORE_BONUS[] = "修正値 # 以上の (指輪等)"; -static GAME_TEXT MN_WANTED[] = "賞金首の (死体)"; -static GAME_TEXT MN_UNIQUE[] = "ユニーク・モンスターの (死体)"; -static GAME_TEXT MN_HUMAN[] = "人間の (死体)"; -static GAME_TEXT MN_UNREADABLE[] = "読めない (魔法書)"; -static GAME_TEXT MN_REALM1[] = "第一領域の (魔法書)"; -static GAME_TEXT MN_REALM2[] = "第二領域の (魔法書)"; -static GAME_TEXT MN_FIRST[] = "1冊目の (魔法書)"; -static GAME_TEXT MN_SECOND[] = "2冊目の (魔法書)"; -static GAME_TEXT MN_THIRD[] = "3冊目の (魔法書)"; -static GAME_TEXT MN_FOURTH[] = "4冊目の (魔法書)"; - -static GAME_TEXT MN_NOUN[] = "名詞の選択"; - -#else - -static GAME_TEXT MN_QUIT[] = "Quit without save"; -static GAME_TEXT MN_SAVEQUIT[] = "Save & Quit"; -static GAME_TEXT MN_REVERT[] = "Revert all changes"; -static GAME_TEXT MN_HELP[] = "Help"; - -static GAME_TEXT MN_MOVE[] = "Move cursor"; -static GAME_TEXT MN_LEFT[] = "Left (Left Arrow key)"; -static GAME_TEXT MN_DOWN[] = "Down (Down Arrow key)"; -static GAME_TEXT MN_UP[] = "Up (Up Arrow key)"; -static GAME_TEXT MN_RIGHT[] = "Right (Right Arrow key)"; -static GAME_TEXT MN_BOL[] = "Beggining of line"; -static GAME_TEXT MN_EOL[] = "End of line"; -static GAME_TEXT MN_PGUP[] = "Page up (PageUp key)"; -static GAME_TEXT MN_PGDOWN[] = "Page down(PageDown key)"; -static GAME_TEXT MN_TOP[] = "Top (Home key)"; -static GAME_TEXT MN_BOTTOM[] = "Bottom (End key)"; - -static GAME_TEXT MN_EDIT[] = "Edit"; -static GAME_TEXT MN_CUT[] = "Cut"; -static GAME_TEXT MN_COPY[] = "Copy"; -static GAME_TEXT MN_PASTE[] = "Paste"; -static GAME_TEXT MN_BLOCK[] = "Select block"; -static GAME_TEXT MN_KILL_LINE[] = "Kill rest of line"; -static GAME_TEXT MN_DELETE_CHAR[] = "Delete character"; -static GAME_TEXT MN_BACKSPACE[] = "Backspace"; -static GAME_TEXT MN_RETURN[] = "Return"; - -static GAME_TEXT MN_SEARCH[] = "Search"; -static GAME_TEXT MN_SEARCH_STR[] = "Search by string"; -static GAME_TEXT MN_SEARCH_FORW[] = "Search forward"; -static GAME_TEXT MN_SEARCH_BACK[] = "Search backward"; -static GAME_TEXT MN_SEARCH_OBJ[] = "Search by inventory object"; -static GAME_TEXT MN_SEARCH_DESTROYED[] = "Search by destroyed object"; - -static GAME_TEXT MN_INSERT[] = "Insert..."; -static GAME_TEXT MN_INSERT_OBJECT[] = "Insert name of choosen object"; -static GAME_TEXT MN_INSERT_DESTROYED[] = "Insert name of destroyed object"; -static GAME_TEXT MN_INSERT_BLOCK[] = "Insert conditional block"; -static GAME_TEXT MN_INSERT_MACRO[] = "Insert a macro definition"; -static GAME_TEXT MN_INSERT_KEYMAP[] = "Insert a keymap definition"; - -static GAME_TEXT MN_COMMAND_LETTER[] = "Command letter"; -static GAME_TEXT MN_CL_AUTOPICK[] = "' ' (Auto pick)"; -static GAME_TEXT MN_CL_DESTROY[] = "'!' (Auto destroy)"; -static GAME_TEXT MN_CL_LEAVE[] = "'~' (Leave it on the floor)"; -static GAME_TEXT MN_CL_QUERY[] = "';' (Query to pick up)"; -static GAME_TEXT MN_CL_NO_DISP[] = "'(' (No display on the large map)"; - -static GAME_TEXT MN_ADJECTIVE_GEN[] = "Adjective (general)"; -static GAME_TEXT MN_RARE[] = "rare (equipments)"; -static GAME_TEXT MN_COMMON[] = "common (equipments)"; - -static GAME_TEXT MN_ADJECTIVE_SPECIAL[] = "Adjective (special)"; -static GAME_TEXT MN_BOOSTED[] = "dice boosted (weapons)"; -static GAME_TEXT MN_MORE_DICE[] = "more than # dice (weapons)"; -static GAME_TEXT MN_MORE_BONUS[] = "more bonus than # (rings etc.)"; -static GAME_TEXT MN_WANTED[] = "wanted (corpse)"; -static GAME_TEXT MN_UNIQUE[] = "unique (corpse)"; -static GAME_TEXT MN_HUMAN[] = "human (corpse)"; -static GAME_TEXT MN_UNREADABLE[] = "unreadable (spellbooks)"; -static GAME_TEXT MN_REALM1[] = "realm1 (spellbooks)"; -static GAME_TEXT MN_REALM2[] = "realm2 (spellbooks)"; -static GAME_TEXT MN_FIRST[] = "first (spellbooks)"; -static GAME_TEXT MN_SECOND[] = "second (spellbooks)"; -static GAME_TEXT MN_THIRD[] = "third (spellbooks)"; -static GAME_TEXT MN_FOURTH[] = "fourth (spellbooks)"; - -static GAME_TEXT MN_NOUN[] = "Keywords (noun)"; - -#endif - - -typedef struct { - concptr name; - int level; - int key; - int com_id; -} command_menu_type; - - -command_menu_type menu_data[] = -{ - {MN_HELP, 0, -1, EC_HELP}, - {MN_QUIT, 0, KTRL('q'), EC_QUIT}, - {MN_SAVEQUIT, 0, KTRL('w'), EC_SAVEQUIT}, - {MN_REVERT, 0, KTRL('z'), EC_REVERT}, - - {MN_EDIT, 0, -1, -1}, - {MN_CUT, 1, KTRL('x'), EC_CUT}, - {MN_COPY, 1, KTRL('c'), EC_COPY}, - {MN_PASTE, 1, KTRL('v'), EC_PASTE}, - {MN_BLOCK, 1, KTRL('g'), EC_BLOCK}, - {MN_KILL_LINE, 1, KTRL('k'), EC_KILL_LINE}, - {MN_DELETE_CHAR, 1, KTRL('d'), EC_DELETE_CHAR}, - {MN_BACKSPACE, 1, KTRL('h'), EC_BACKSPACE}, - {MN_RETURN, 1, KTRL('j'), EC_RETURN}, - {MN_RETURN, 1, KTRL('m'), EC_RETURN}, - - {MN_SEARCH, 0, -1, -1}, - {MN_SEARCH_STR, 1, KTRL('s'), EC_SEARCH_STR}, - {MN_SEARCH_FORW, 1, -1, EC_SEARCH_FORW}, - {MN_SEARCH_BACK, 1, KTRL('r'), EC_SEARCH_BACK}, - {MN_SEARCH_OBJ, 1, KTRL('y'), EC_SEARCH_OBJ}, - {MN_SEARCH_DESTROYED, 1, -1, EC_SEARCH_DESTROYED}, - - {MN_MOVE, 0, -1, -1}, - {MN_LEFT, 1, KTRL('b'), EC_LEFT}, - {MN_DOWN, 1, KTRL('n'), EC_DOWN}, - {MN_UP, 1, KTRL('p'), EC_UP}, - {MN_RIGHT, 1, KTRL('f'), EC_RIGHT}, - {MN_BOL, 1, KTRL('a'), EC_BOL}, - {MN_EOL, 1, KTRL('e'), EC_EOL}, - {MN_PGUP, 1, KTRL('o'), EC_PGUP}, - {MN_PGDOWN, 1, KTRL('l'), EC_PGDOWN}, - {MN_TOP, 1, KTRL('t'), EC_TOP}, - {MN_BOTTOM, 1, KTRL('u'), EC_BOTTOM}, - - {MN_INSERT, 0, -1, -1}, - {MN_INSERT_OBJECT, 1, KTRL('i'), EC_INSERT_OBJECT}, - {MN_INSERT_DESTROYED, 1, -1, EC_INSERT_DESTROYED}, - {MN_INSERT_BLOCK, 1, -1, EC_INSERT_BLOCK}, - {MN_INSERT_MACRO, 1, -1, EC_INSERT_MACRO}, - {MN_INSERT_KEYMAP, 1, -1, EC_INSERT_KEYMAP}, - - {MN_ADJECTIVE_GEN, 0, -1, -1}, - {KEY_UNAWARE, 1, -1, EC_IK_UNAWARE}, - {KEY_UNIDENTIFIED, 1, -1, EC_IK_UNIDENTIFIED}, - {KEY_IDENTIFIED, 1, -1, EC_IK_IDENTIFIED}, - {KEY_STAR_IDENTIFIED, 1, -1, EC_IK_STAR_IDENTIFIED}, - {KEY_COLLECTING, 1, -1, EC_OK_COLLECTING}, - {KEY_ARTIFACT, 1, -1, EC_OK_ARTIFACT}, - {KEY_EGO, 1, -1, EC_OK_EGO}, - {KEY_GOOD, 1, -1, EC_OK_GOOD}, - {KEY_NAMELESS, 1, -1, EC_OK_NAMELESS}, - {KEY_AVERAGE, 1, -1, EC_OK_AVERAGE}, - {KEY_WORTHLESS, 1, -1, EC_OK_WORTHLESS}, - {MN_RARE, 1, -1, EC_OK_RARE}, - {MN_COMMON, 1, -1, EC_OK_COMMON}, - - {MN_ADJECTIVE_SPECIAL, 0, -1, -1}, - {MN_BOOSTED, 1, -1, EC_OK_BOOSTED}, - {MN_MORE_DICE, 1, -1, EC_OK_MORE_DICE}, - {MN_MORE_BONUS, 1, -1, EC_OK_MORE_BONUS}, - {MN_WANTED, 1, -1, EC_OK_WANTED}, - {MN_UNIQUE, 1, -1, EC_OK_UNIQUE}, - {MN_HUMAN, 1, -1, EC_OK_HUMAN}, - {MN_UNREADABLE, 1, -1, EC_OK_UNREADABLE}, - {MN_REALM1, 1, -1, EC_OK_REALM1}, - {MN_REALM2, 1, -1, EC_OK_REALM2}, - {MN_FIRST, 1, -1, EC_OK_FIRST}, - {MN_SECOND, 1, -1, EC_OK_SECOND}, - {MN_THIRD, 1, -1, EC_OK_THIRD}, - {MN_FOURTH, 1, -1, EC_OK_FOURTH}, - - {MN_NOUN, 0, -1, -1}, - {KEY_WEAPONS, 1, -1, EC_KK_WEAPONS}, - {KEY_FAVORITE_WEAPONS, 1, -1, EC_KK_FAVORITE_WEAPONS}, - {KEY_ARMORS, 1, -1, EC_KK_ARMORS}, - {KEY_MISSILES, 1, -1, EC_KK_MISSILES}, - {KEY_DEVICES, 1, -1, EC_KK_DEVICES}, - {KEY_LIGHTS, 1, -1, EC_KK_LIGHTS}, - {KEY_JUNKS, 1, -1, EC_KK_JUNKS}, - {KEY_CORPSES, 1, -1, EC_KK_CORPSES}, - {KEY_SPELLBOOKS, 1, -1, EC_KK_SPELLBOOKS}, - {KEY_SHIELDS, 1, -1, EC_KK_SHIELDS}, - {KEY_BOWS, 1, -1, EC_KK_BOWS}, - {KEY_RINGS, 1, -1, EC_KK_RINGS}, - {KEY_AMULETS, 1, -1, EC_KK_AMULETS}, - {KEY_SUITS, 1, -1, EC_KK_SUITS}, - {KEY_CLOAKS, 1, -1, EC_KK_CLOAKS}, - {KEY_HELMS, 1, -1, EC_KK_HELMS}, - {KEY_GLOVES, 1, -1, EC_KK_GLOVES}, - {KEY_BOOTS, 1, -1, EC_KK_BOOTS}, - - {MN_COMMAND_LETTER, 0, -1, -1}, - {MN_CL_AUTOPICK, 1, -1, EC_CL_AUTOPICK}, - {MN_CL_DESTROY, 1, -1, EC_CL_DESTROY}, - {MN_CL_LEAVE, 1, -1, EC_CL_LEAVE}, - {MN_CL_QUERY, 1, -1, EC_CL_QUERY}, - {MN_CL_NO_DISP, 1, -1, EC_CL_NO_DISP}, - - {MN_DELETE_CHAR, -1, 0x7F, EC_DELETE_CHAR}, - - {NULL, -1, -1, 0} -}; - - -/* - * Find a command by 'key'. - */ -static int get_com_id(char key) -{ - int i; - - for (i = 0; menu_data[i].name; i++) - { - if (menu_data[i].key == key) - { - return menu_data[i].com_id; - } - } - - return 0; -} - - -/* - * Display the menu, and get a command - */ -static int do_command_menu(int level, int start) -{ - int i; - int max_len = 0; - int max_menu_wid; - int col0 = 5 + level*7; - int row0 = 1 + level*3; - byte menu_key = 0; - int menu_id_list[26]; - bool redraw = TRUE; - char linestr[MAX_LINELEN]; - - /* Get max length */ - menu_key = 0; - for (i = start; menu_data[i].level >= level; i++) - { - int len; - - /* Ignore lower level sub menus */ - if (menu_data[i].level > level) continue; - - len = strlen(menu_data[i].name); - if (len > max_len) max_len = len; - - menu_id_list[menu_key] = i; - menu_key++; - } - - while (menu_key < 26) - { - menu_id_list[menu_key] = -1; - menu_key++; - } - - /* Extra space for displaying menu key and command key */ - max_menu_wid = max_len + 3 + 3; - - /* Prepare box line */ - linestr[0] = '\0'; - strcat(linestr, "+"); - for (i = 0; i < max_menu_wid + 2; i++) - { - strcat(linestr, "-"); - } - strcat(linestr, "+"); - - while (TRUE) - { - int com_id; - char key; - int menu_id; - - if (redraw) - { - int row1 = row0 + 1; - - /* Draw top line */ - Term_putstr(col0, row0, -1, TERM_WHITE, linestr); - - /* Draw menu items */ - menu_key = 0; - for (i = start; menu_data[i].level >= level; i++) - { - char com_key_str[3]; - concptr str; - - /* Ignore lower level sub menus */ - if (menu_data[i].level > level) continue; - - if (menu_data[i].com_id == -1) - { - strcpy(com_key_str, _("▼", ">")); - } - else if (menu_data[i].key != -1) - { - com_key_str[0] = '^'; - com_key_str[1] = menu_data[i].key + '@'; - com_key_str[2] = '\0'; - } - else - { - com_key_str[0] = '\0'; - } - - str = format("| %c) %-*s %2s | ", menu_key + 'a', max_len, menu_data[i].name, com_key_str); - - Term_putstr(col0, row1++, -1, TERM_WHITE, str); - - menu_key++; - } - - /* Draw bottom line */ - Term_putstr(col0, row1, -1, TERM_WHITE, linestr); - - /* The menu was shown */ - redraw = FALSE; - } - prt(format(_("(a-%c) コマンド:", "(a-%c) Command:"), menu_key + 'a' - 1), 0, 0); - key = inkey(); - - if (key == ESCAPE) return 0; - - if ('a' <= key && key <= 'z') - { - menu_id = menu_id_list[key - 'a']; - - if (menu_id >= 0) - { - com_id = menu_data[menu_id].com_id; - - if (com_id == -1) - { - com_id = do_command_menu(level + 1, menu_id + 1); - - if (com_id) return com_id; - else redraw = TRUE; - } - else if (com_id) - { - return com_id; - } - } - } - - else - { - com_id = get_com_id(key); - if (com_id) return com_id; - else continue; - } - } -} - - -static chain_str_type *new_chain_str(concptr str) -{ - chain_str_type *chain; - - size_t len = strlen(str); - - chain = (chain_str_type *)ralloc(sizeof(chain_str_type) + len * sizeof(char)); - - strcpy(chain->s, str); - chain->next = NULL; - - return chain; -} - - -static void kill_yank_chain(text_body_type *tb) -{ - chain_str_type *chain = tb->yank; - tb->yank = NULL; - tb->yank_eol = TRUE; - - while (chain) - { - chain_str_type *next = chain->next; - size_t len = strlen(chain->s); - - rnfree(chain, sizeof(chain_str_type) + len * sizeof(char)); - - chain = next; - } -} - - -static void add_str_to_yank(text_body_type *tb, concptr str) -{ - chain_str_type *chain; - - tb->yank_eol = FALSE; - - if (NULL == tb->yank) - { - tb->yank = new_chain_str(str); - return; - } - - chain = tb->yank; - - while (TRUE) - { - if (!chain->next) - { - chain->next = new_chain_str(str); - return; - } - - /* Go to next */ - chain = chain->next; - } -} - - -/* - * Do work for the copy editor-command - */ -static void copy_text_to_yank(text_body_type *tb) -{ - int len = strlen(tb->lines_list[tb->cy]); - - /* Correct cursor location */ - if (tb->cx > len) tb->cx = len; - - /* Use single line? */ - if (!tb->mark) - { - /* Select a single line */ - tb->cx = 0; - tb->my = tb->cy; - tb->mx = len; - } - - /* Kill old yank buffer */ - kill_yank_chain(tb); - - - /* Single line case */ - if (tb->my == tb->cy) - { - int i; - char buf[MAX_LINELEN]; - int bx1 = MIN(tb->mx, tb->cx); - int bx2 = MAX(tb->mx, tb->cx); - - /* Correct fake cursor position */ - if (bx2 > len) bx2 = len; - - /* Whole part of this line is selected */ - if (bx1 == 0 && bx2 == len) - { - /* Copy this line */ - add_str_to_yank(tb, tb->lines_list[tb->cy]); - - /* Add end of line to the buffer */ - add_str_to_yank(tb, ""); - } - - /* Segment of this line is selected */ - else - { - for (i = 0; i < bx2 - bx1; i++) - { - buf[i] = tb->lines_list[tb->cy][bx1 + i]; - } - buf[i] = '\0'; - - /* Copy this segment of line */ - add_str_to_yank(tb, buf); - } - } - - /* Multiple lines case */ - else /* if (tb->my != tb->cy) */ - { - int y; - - int by1 = MIN(tb->my, tb->cy); - int by2 = MAX(tb->my, tb->cy); - - /* Copy lines */ - for (y = by1; y <= by2; y++) - { - /* Copy this line */ - add_str_to_yank(tb, tb->lines_list[y]); - } - - /* Add final end of line to the buffer */ - add_str_to_yank(tb, ""); - } - - /* Disable selection */ - tb->mark = 0; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; -} - - -#define DESCRIPT_HGT 3 - -/* - * Draw text - */ -static void draw_text_editor(text_body_type *tb) -{ - int i; - int by1 = 0, by2 = 0; - - Term_get_size(&tb->wid, &tb->hgt); - - /* - * Top line (-1), description line (-3), separator (-1) - * == -5 - */ - tb->hgt -= 2 + DESCRIPT_HGT; - -#ifdef JP - /* Don't let cursor at second byte of kanji */ - for (i = 0; tb->lines_list[tb->cy][i]; i++) - if (iskanji(tb->lines_list[tb->cy][i])) - { - i++; - if (i == tb->cx) - { - /* - * Move to a correct position in the - * left or right - */ - if (i & 1) tb->cx--; - else tb->cx++; - break; - } - } -#endif - - /* Scroll if necessary */ - if (tb->cy < tb->upper || tb->upper + tb->hgt <= tb->cy) - tb->upper = tb->cy - (tb->hgt)/2; - if (tb->upper < 0) - tb->upper = 0; - if ((tb->cx < tb->left + 10 && tb->left > 0) || tb->left + tb->wid - 5 <= tb->cx) - tb->left = tb->cx - (tb->wid)*2/3; - if (tb->left < 0) - tb->left = 0; - - /* Redraw whole window after resize */ - if (tb->old_wid != tb->wid || tb->old_hgt != tb->hgt) - tb->dirty_flags |= DIRTY_SCREEN; - - /* Redraw all text after scroll */ - else if (tb->old_upper != tb->upper || tb->old_left != tb->left) - tb->dirty_flags |= DIRTY_ALL; - - - if (tb->dirty_flags & DIRTY_SCREEN) - { - tb->dirty_flags |= (DIRTY_ALL | DIRTY_MODE); - Term_clear(); - } - - /* Redraw mode line */ - if (tb->dirty_flags & DIRTY_MODE) - { - char buf[MAX_LINELEN]; - - int sepa_length = tb->wid; - - /* Separator */ - for (i = 0; i < sepa_length; i++) - buf[i] = '-'; - buf[i] = '\0'; - - Term_putstr(0, tb->hgt + 1, sepa_length, TERM_WHITE, buf); - } - - if (tb->dirty_flags & DIRTY_EXPRESSION) - { - int y; - byte state = 0; - - for (y = 0; tb->lines_list[y]; y++) - { - char f; - concptr v; - concptr s = tb->lines_list[y]; - char *ss, *s_keep; - int s_len; - - /* Update this line's state */ - tb->states[y] = state; - - if (*s++ != '?') continue; - if (*s++ != ':') continue; - - /* Lines below this line are auto-registered */ - if (streq(s, "$AUTOREGISTER")) - state |= LSTAT_AUTOREGISTER; - - s_len = strlen(s); - ss = (char *)string_make(s); - s_keep = ss; - - /* Parse the expr */ - v = process_pref_file_expr(&ss, &f); - - /* Set flag */ - if (streq(v, "0")) state |= LSTAT_BYPASS; - else state &= ~LSTAT_BYPASS; - - /* Cannot use string_free() because the string was "destroyed" */ - C_KILL(s_keep, s_len + 1, char); - - /* Re-update this line's state */ - tb->states[y] = state | LSTAT_EXPRESSION; - } - - tb->dirty_flags |= DIRTY_ALL; - } - - if (tb->mark) - { - tb->dirty_flags |= DIRTY_ALL; - - by1 = MIN(tb->my, tb->cy); - by2 = MAX(tb->my, tb->cy); - } - - /* Dump up to tb->hgt lines of messages */ - for (i = 0; i < tb->hgt; i++) - { - int j; - int leftcol = 0; - concptr msg; - byte color; - int y = tb->upper+i; - - /* clean or dirty? */ - if (!(tb->dirty_flags & DIRTY_ALL) && (tb->dirty_line != y)) - continue; - - msg = tb->lines_list[y]; - if (!msg) break; - - /* Apply horizontal scroll */ - for (j = 0; *msg; msg++, j++) - { - if (j == tb->left) break; -#ifdef JP - if (j > tb->left) - { - leftcol = 1; - break; - } - if (iskanji(*msg)) - { - msg++; - j++; - } -#endif - } - - /* Erase line */ - Term_erase(0, i + 1, tb->wid); - - if (tb->states[y] & LSTAT_AUTOREGISTER) - { - /* Warning color -- These lines will be deleted later */ - color = TERM_L_RED; - } - else - { - /* Bypassed line will be displayed by darker color */ - if (tb->states[y] & LSTAT_BYPASS) color = TERM_SLATE; - else color = TERM_WHITE; - } - - /* No mark or Out of mark */ - if (!tb->mark || (y < by1 || by2 < y)) - { - /* Dump the messages, bottom to top */ - Term_putstr(leftcol, i + 1, tb->wid - 1, color, msg); - } - - /* Multiple lines selected */ - else if (by1 != by2) - { - /* Dump the messages, bottom to top */ - Term_putstr(leftcol, i + 1, tb->wid - 1, TERM_YELLOW, msg); - } - - /* Single line selected */ - else - { - int x0 = leftcol + tb->left; - int len = strlen(tb->lines_list[tb->cy]); - int bx1 = MIN(tb->mx, tb->cx); - int bx2 = MAX(tb->mx, tb->cx); - - /* Correct cursor location */ - if (bx2 > len) bx2 = len; - - Term_gotoxy(leftcol, i + 1); - if (x0 < bx1) Term_addstr(bx1 - x0, color, msg); - if (x0 < bx2) Term_addstr(bx2 - bx1, TERM_YELLOW, msg + (bx1 - x0)); - Term_addstr(-1, color, msg + (bx2 - x0)); - } - } - - for (; i < tb->hgt; i++) - { - /* Erase line */ - Term_erase(0, i + 1, tb->wid); - } - - /* Display information when updated */ - if (tb->old_cy != tb->cy || (tb->dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND | DIRTY_NO_SEARCH)) || tb->dirty_line == tb->cy) - { - autopick_type an_entry, *entry = &an_entry; - concptr str1 = NULL, str2 = NULL; - - - /* Clear information line */ - for (i = 0; i < DESCRIPT_HGT; i++) - { - /* Erase line */ - Term_erase(0, tb->hgt + 2 + i, tb->wid); - } - - /* Display information */ - if (tb->dirty_flags & DIRTY_NOT_FOUND) - { - str1 = format(_("パターンが見つかりません: %s", "Pattern not found: %s"), tb->search_str); - } - else if (tb->dirty_flags & DIRTY_SKIP_INACTIVE) - { - str1 = format(_("無効状態の行をスキップしました。(%sを検索中)", - "Some inactive lines are skipped. (Searching %s)"), tb->search_str); - } - else if (tb->dirty_flags & DIRTY_INACTIVE) - { - str1 = format(_("無効状態の行だけが見付かりました。(%sを検索中)", - "Found only an inactive line. (Searching %s)"), tb->search_str); - } - else if (tb->dirty_flags & DIRTY_NO_SEARCH) - { - str1 = _("検索するパターンがありません(^S で検索)。", "No pattern to search. (Press ^S to search.)"); - } - else if (tb->lines_list[tb->cy][0] == '#') - { - str1 = _("この行はコメントです。", "This line is a comment."); - } - else if (tb->lines_list[tb->cy][0] && tb->lines_list[tb->cy][1] == ':') - { - switch(tb->lines_list[tb->cy][0]) - { - case '?': - str1 = _("この行は条件分岐式です。", "This line is a Conditional Expression."); - break; - case 'A': - str1 = _("この行はマクロの実行内容を定義します。", "This line defines a Macro action."); - break; - case 'P': - str1 = _("この行はマクロのトリガー・キーを定義します。", "This line defines a Macro trigger key."); - break; - case 'C': - str1 = _("この行はキー配置を定義します。", "This line defines a Keymap."); - break; - } - - switch(tb->lines_list[tb->cy][0]) - { - case '?': - if (tb->states[tb->cy] & LSTAT_BYPASS) - { - str2 = _("現在の式の値は「偽(=0)」です。", "The expression is 'False'(=0) currently."); - } - else - { - str2 = _("現在の式の値は「真(=1)」です。", "The expression is 'True'(=1) currently."); - } - break; - - default: - if (tb->states[tb->cy] & LSTAT_AUTOREGISTER) - { - str2 = _("この行は後で削除されます。", "This line will be delete later."); - } - - else if (tb->states[tb->cy] & LSTAT_BYPASS) - { - str2 = _("この行は現在は無効な状態です。", "This line is bypassed currently."); - } - break; - } - } - - /* Get description of an autopicker preference line */ - else if (autopick_new_entry(entry, tb->lines_list[tb->cy], FALSE)) - { - char buf[MAX_LINELEN]; - char temp[MAX_LINELEN]; - concptr t; - - describe_autopick(buf, entry); - - if (tb->states[tb->cy] & LSTAT_AUTOREGISTER) - { - strcat(buf, _("この行は後で削除されます。", " This line will be delete later.")); - } - - if (tb->states[tb->cy] & LSTAT_BYPASS) - { - strcat(buf, _("この行は現在は無効な状態です。", " This line is bypassed currently.")); - } - - roff_to_buf(buf, 81, temp, sizeof(temp)); - t = temp; - for (i = 0; i < 3; i++) - { - if(t[0] == 0) - break; - else - { - prt(t, tb->hgt +1 + 1 + i, 0); - t += strlen(t) + 1; - } - } - autopick_free_entry(entry); - } - - /* Draw the first line */ - if (str1) prt(str1, tb->hgt +1 + 1, 0); - - /* Draw the second line */ - if (str2) prt(str2, tb->hgt +1 + 2, 0); - } -} - - -/* - * Kill segment of a line - */ -static void kill_line_segment(text_body_type *tb, int y, int x0, int x1, bool whole) -{ - char buf[MAX_LINELEN]; - concptr s = tb->lines_list[y]; - char *d = buf; - int x; - - /* Kill whole line? */ - if (whole && x0 == 0 && s[x1] == '\0' && tb->lines_list[y+1]) - { - int i; - - string_free(tb->lines_list[y]); - - /* Shift lines up */ - for (i = y; tb->lines_list[i+1]; i++) - tb->lines_list[i] = tb->lines_list[i+1]; - tb->lines_list[i] = NULL; - - /* Expressions need re-evaluation */ - tb->dirty_flags |= DIRTY_EXPRESSION; - - return; - } - - /* No segment? */ - if (x0 == x1) return; - - /* Before the segment */ - for (x = 0; x < x0; x++) - *(d++) = s[x]; - - /* After the segment */ - for (x = x1; s[x]; x++) - *(d++) = s[x]; - - *d = '\0'; - - /* Replace */ - string_free(tb->lines_list[y]); - tb->lines_list[y] = string_make(buf); - - /* Expressions may need re-evaluation */ - check_expression_line(tb, y); - - /* Text is changed */ - tb->changed = TRUE; -} - - -/* - * Get a trigger key and insert ASCII string for the trigger - */ -static bool insert_macro_line(text_body_type *tb) -{ - char tmp[1024]; - char buf[1024]; - int i, n = 0; - - /* Flush */ - flush(); - - /* Do not process macros */ - inkey_base = TRUE; - - /* First key */ - i = inkey(); - - /* Read the pattern */ - while (i) - { - /* Save the key */ - buf[n++] = (char)i; - - /* Do not process macros */ - inkey_base = TRUE; - - /* Do not wait for keys */ - inkey_scan = TRUE; - - /* Attempt to read a key */ - i = inkey(); - } - - /* Terminate */ - buf[n] = '\0'; - - flush(); - - /* Convert the trigger */ - ascii_to_text(tmp, buf); - - /* Null */ - if(!tmp[0]) return FALSE; - - tb->cx = 0; - - /* Insert preference string */ - insert_return_code(tb); - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make(format("P:%s", tmp)); - - /* Acquire action */ - i = macro_find_exact(buf); - - if (i == -1) - { - /* Nothing defined */ - tmp[0] = '\0'; - } - else - { - /* Analyze the current action */ - ascii_to_text(tmp, macro__act[i]); - } - - /* Insert blank action preference line */ - insert_return_code(tb); - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make(format("A:%s", tmp)); - - return TRUE; -} - - -/* - * Get a command key and insert ASCII string for the key - */ -static bool insert_keymap_line(text_body_type *tb) -{ - char tmp[1024]; - char buf[2]; - BIT_FLAGS mode; - concptr act; - - /* Roguelike */ - if (rogue_like_commands) - { - mode = KEYMAP_MODE_ROGUE; - } - - /* Original */ - else - { - mode = KEYMAP_MODE_ORIG; - } - - flush(); - - /* Get a key */ - buf[0] = inkey(); - buf[1] = '\0'; - - flush(); - - /* Convert the trigger */ - ascii_to_text(tmp, buf); - - /* Null */ - if(!tmp[0]) return FALSE; - - tb->cx = 0; - - /* Insert preference string */ - insert_return_code(tb); - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make(format("C:%d:%s", mode, tmp)); - - /* Look up the keymap */ - act = keymap_act[mode][(byte)(buf[0])]; - - if (act) - { - /* Analyze the current action */ - ascii_to_text(tmp, act); - } - else - { - /* No keymap defined -- Use trigger key itself as a default */ - - /* Nothing to do (use tmp) */ - } - - /* Insert blank action preference line */ - insert_return_code(tb); - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make(format("A:%s", tmp)); - - return TRUE; -} - - -/* - * Execute a single editor command - */ -static bool do_editor_command(text_body_type *tb, int com_id) -{ - switch(com_id) - { - case EC_QUIT: - if (tb->changed) - { - if (!get_check(_("全ての変更を破棄してから終了します。よろしいですか? ", - "Discard all changes and quit. Are you sure? "))) break; - } - return QUIT_WITHOUT_SAVE; - - case EC_SAVEQUIT: - return QUIT_AND_SAVE; - - case EC_REVERT: - /* Revert to original */ - if (!get_check(_("全ての変更を破棄して元の状態に戻します。よろしいですか? ", - "Discard all changes and revert to original file. Are you sure? "))) break; - - free_text_lines(tb->lines_list); - tb->lines_list = read_pickpref_text_lines(&tb->filename_mode); - tb->dirty_flags |= DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION; - tb->cx = tb->cy = 0; - tb->mark = 0; - - /* Text is not changed */ - tb->changed = FALSE; - break; - - case EC_HELP: - /* Peruse the main help file */ - (void)show_file(TRUE, _("jeditor.txt", "editor.txt"), NULL, 0, 0); - /* Redraw all */ - tb->dirty_flags |= DIRTY_SCREEN; - - break; - - case EC_RETURN: - /* Split a line or insert end of line */ - - /* Ignore selection */ - if (tb->mark) - { - tb->mark = 0; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - } - - insert_return_code(tb); - tb->cy++; - tb->cx = 0; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - break; - - case EC_LEFT: - /* Back */ - if (0 < tb->cx) - { - int len; -#ifdef JP - int i; -#endif - - tb->cx--; - len = strlen(tb->lines_list[tb->cy]); - if (len < tb->cx) tb->cx = len; - -#ifdef JP - /* Don't let cursor at second byte of kanji */ - for (i = 0; tb->lines_list[tb->cy][i]; i++) - { - if (iskanji(tb->lines_list[tb->cy][i])) - { - i++; - if (i == tb->cx) - { - /* Move to the left */ - tb->cx--; - break; - } - } - } -#endif - } - else if (tb->cy > 0) - { - tb->cy--; - tb->cx = strlen(tb->lines_list[tb->cy]); - } - break; - - case EC_DOWN: - /* Next line */ - - /* Is this the last line? */ - if (!tb->lines_list[tb->cy + 1]) - { - /* Add one more empty line if possible */ - if (!add_empty_line(tb)) break; - } - - /* Go down */ - tb->cy++; - - break; - - case EC_UP: - /* Previous line */ - if (tb->cy > 0) tb->cy--; - break; - - case EC_RIGHT: - { - /* Forward */ - - int len; -#ifdef JP - if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++; -#endif - tb->cx++; - len = strlen(tb->lines_list[tb->cy]); - if (len < tb->cx) - { - /* Correct the cursor position */ - tb->cx = len; - - /* Is this the last line? */ - if (!tb->lines_list[tb->cy + 1]) - { - /* Add one more empty line if possible */ - if (!add_empty_line(tb)) break; - } - - /* Move to the beginning of next line */ - tb->cy++; - tb->cx = 0; - } - break; - } - - case EC_BOL: - /* Beginning of line */ - tb->cx = 0; - break; - - case EC_EOL: - /* End of line */ - tb->cx = strlen(tb->lines_list[tb->cy]); - break; - - case EC_PGUP: - while (0 < tb->cy && tb->upper <= tb->cy) - tb->cy--; - while (0 < tb->upper && tb->cy + 1 < tb->upper + tb->hgt) - tb->upper--; - break; - - case EC_PGDOWN: - /* Page down */ - while (tb->cy < tb->upper + tb->hgt) - { - /* Is this the last line? */ - if (!tb->lines_list[tb->cy + 1]) - { - /* Add one more empty line if possible */ - if (!add_empty_line(tb)) break; - } - - tb->cy++; - } - - tb->upper = tb->cy; - break; - - case EC_TOP: - tb->cy = 0; - break; - - case EC_BOTTOM: - while (TRUE) - { - /* Is this the last line? */ - if (!tb->lines_list[tb->cy + 1]) - { - /* Add one more empty line if possible */ - if (!add_empty_line(tb)) break; - } - - tb->cy++; - } - - /* Always at the biginning of the last line */ - tb->cx = 0; - - break; - - case EC_CUT: - { - /* Copy the text first */ - copy_text_to_yank(tb); - - /* Single line case */ - if (tb->my == tb->cy) - { - int bx1 = MIN(tb->mx, tb->cx); - int bx2 = MAX(tb->mx, tb->cx); - int len = strlen(tb->lines_list[tb->cy]); - - /* Correct fake cursor position */ - if (bx2 > len) bx2 = len; - - kill_line_segment(tb, tb->cy, bx1, bx2, TRUE); - - /* New cursor position */ - tb->cx = bx1; - } - - /* Multiple lines case */ - else /* if (tb->my != tb->cy) */ - { - int y; - - int by1 = MIN(tb->my, tb->cy); - int by2 = MAX(tb->my, tb->cy); - - /* Kill lines in reverse order */ - for (y = by2; y >= by1; y--) - { - int len = strlen(tb->lines_list[y]); - - kill_line_segment(tb, y, 0, len, TRUE); - } - - /* New cursor position */ - tb->cy = by1; - tb->cx = 0; - } - - - /* Disable selection */ - tb->mark = 0; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - - /* Text is changed */ - tb->changed = TRUE; - - break; - } - - case EC_COPY: - copy_text_to_yank(tb); - - /* - * Move cursor position to the end of the selection - * - * Pressing ^C ^V correctly duplicates the selection. - */ - if (tb->my == tb->cy) - { - tb->cx = MAX(tb->cx, tb->mx); - - /* - * When whole line is selected, the end of - * line code is also copyed. - */ - if (!tb->lines_list[tb->cy][tb->cx]) - { - /* Is this the last line? */ - if (!tb->lines_list[tb->cy + 1]) - { - /* Add one more empty line if possible */ - if (!add_empty_line(tb)) break; - } - - /* Go to the beginning of next line */ - tb->cy++; - tb->cx = 0; - } - } - else - { - tb->cy = MAX(tb->cy, tb->my); - - /* Is this the last line? */ - if (!tb->lines_list[tb->cy + 1]) - { - /* Add one more empty line if possible */ - if (!add_empty_line(tb)) break; - } - - /* Go down */ - tb->cy++; - } - - break; - - case EC_PASTE: - { - /* Paste killed text */ - - chain_str_type *chain = tb->yank; - int len = strlen(tb->lines_list[tb->cy]); - - /* Nothing to do? */ - if (!chain) break; - - /* Correct cursor location */ - if (tb->cx > len) tb->cx = len; - - /* Ignore selection */ - if (tb->mark) - { - tb->mark = 0; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - } - - /* Paste text */ - while (chain) - { - concptr yank_str = chain->s; - - char buf[MAX_LINELEN]; - int i; - char rest[MAX_LINELEN], *rest_ptr = rest; - - /* Save preceding string */ - for(i = 0; i < tb->cx; i++) - buf[i] = tb->lines_list[tb->cy][i]; - - strcpy(rest, &(tb->lines_list[tb->cy][i])); - - /* Paste yank buffer */ - while (*yank_str && i < MAX_LINELEN-1) - { - buf[i++] = *yank_str++; - } - - /* Terminate */ - buf[i] = '\0'; - - chain = chain->next; - - if (chain || tb->yank_eol) - { - /* There is an end of line between chain nodes */ - - insert_return_code(tb); - - /* Replace this line with new one */ - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make(buf); - - /* Move to next line */ - tb->cx = 0; - tb->cy++; - - continue; - } - - /* Final line doesn't have end of line */ - - tb->cx = strlen(buf); - - /* Rest of original line */ - while (*rest_ptr && i < MAX_LINELEN-1) - { - buf[i++] = *rest_ptr++; - } - - /* Terminate */ - buf[i] = '\0'; - - /* Replace this line with new one */ - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make(buf); - - /* Finish */ - break; - } - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - - /* Expressions need re-evaluation */ - tb->dirty_flags |= DIRTY_EXPRESSION; - - /* Text is changed */ - tb->changed = TRUE; - - break; - } - - case EC_BLOCK: - if (tb->mark) - { - /* Disable the selection */ - tb->mark = 0; - - /* Redraw text */ - tb->dirty_flags |= DIRTY_ALL; - } - else - { - tb->mark = MARK_MARK; - - /* Repeating this command swaps cursor position */ - if (com_id == tb->old_com_id) - { - int tmp; - - tmp = tb->cy; - tb->cy = tb->my; - tb->my = tmp; - tmp = tb->cx; - tb->cx = tb->mx; - tb->mx = tmp; - - /* Redraw text */ - tb->dirty_flags |= DIRTY_ALL; - } - else - { - int len = strlen(tb->lines_list[tb->cy]); - - /* Mark the point 1 */ - tb->my = tb->cy; - tb->mx = tb->cx; - - /* Correct cursor location */ - if (tb->cx > len) tb->mx = len; - } - } - break; - - case EC_KILL_LINE: - { - /* Kill rest of line */ - - int len = strlen(tb->lines_list[tb->cy]); - - /* Correct cursor location */ - if (tb->cx > len) tb->cx = len; - - /* Ignore selection */ - if (tb->mark) - { - tb->mark = 0; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - } - - /* Append only if this command is repeated. */ - if (tb->old_com_id != com_id) - { - kill_yank_chain(tb); - tb->yank = NULL; - } - - /* Really deleted some text */ - if (tb->cx < len) - { - /* Add deleted string to yank buffer */ - add_str_to_yank(tb, &(tb->lines_list[tb->cy][tb->cx])); - - kill_line_segment(tb, tb->cy, tb->cx, len, FALSE); - - /* Now dirty */ - tb->dirty_line = tb->cy; - - /* Leave end of line character */ - break; - } - - /* Cut the end of line character only */ - if (tb->yank_eol) add_str_to_yank(tb, ""); - - /* Cut end of line */ - tb->yank_eol = TRUE; - - do_editor_command(tb, EC_DELETE_CHAR); - break; - } - - case EC_DELETE_CHAR: - { - /* DELETE == go forward + BACK SPACE */ - - int len; - - /* Ignore selection */ - if (tb->mark) - { - tb->mark = 0; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - } - -#ifdef JP - if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++; -#endif - tb->cx++; - - /* Pass through the end of line to next line */ - len = strlen(tb->lines_list[tb->cy]); - if (len < tb->cx) - { - if (tb->lines_list[tb->cy + 1]) - { - tb->cy++; - tb->cx = 0; - } - else - { - tb->cx = len; - break; - } - } - - do_editor_command(tb, EC_BACKSPACE); - break; - } - - case EC_BACKSPACE: - { - /* BACK SPACE */ - - int len, i, j, k; - char buf[MAX_LINELEN]; - - /* Ignore selection */ - if (tb->mark) - { - tb->mark = 0; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - } - - /* Move to correct collumn */ - len = strlen(tb->lines_list[tb->cy]); - if (len < tb->cx) tb->cx = len; - - if (tb->cx == 0) - { - /* delete a return code and union two lines */ - if (tb->cy == 0) break; - tb->cx = strlen(tb->lines_list[tb->cy-1]); - strcpy(buf, tb->lines_list[tb->cy-1]); - strcat(buf, tb->lines_list[tb->cy]); - string_free(tb->lines_list[tb->cy-1]); - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy-1] = string_make(buf); - - for (i = tb->cy; tb->lines_list[i+1]; i++) - tb->lines_list[i] = tb->lines_list[i+1]; - - tb->lines_list[i] = NULL; - tb->cy--; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - - /* Expressions need re-evaluation */ - tb->dirty_flags |= DIRTY_EXPRESSION; - - /* Text is changed */ - tb->changed = TRUE; - - break; - } - - for (i = j = k = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++) - { - k = j; -#ifdef JP - if (iskanji(tb->lines_list[tb->cy][i])) - buf[j++] = tb->lines_list[tb->cy][i++]; -#endif - buf[j++] = tb->lines_list[tb->cy][i]; - } - while (j > k) - { - tb->cx--; - j--; - } - for (; tb->lines_list[tb->cy][i]; i++) - buf[j++] = tb->lines_list[tb->cy][i]; - buf[j] = '\0'; - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make(buf); - - /* Now dirty */ - tb->dirty_line = tb->cy; - - /* Expressions may need re-evaluation */ - check_expression_line(tb, tb->cy); - - /* Text is changed */ - tb->changed = TRUE; - - break; - } - - case EC_SEARCH_STR: - { - byte search_dir; - - /* Become dirty because of item/equip menu */ - tb->dirty_flags |= DIRTY_SCREEN; - - search_dir = get_string_for_search(&tb->search_o_ptr, &tb->search_str); - - if (!search_dir) break; - - if (search_dir == 1) do_editor_command(tb, EC_SEARCH_FORW); - else do_editor_command(tb, EC_SEARCH_BACK); - break; - } - - case EC_SEARCH_FORW: - if (tb->search_o_ptr) - { - search_for_object(tb, tb->search_o_ptr, TRUE); - } - else if (tb->search_str && tb->search_str[0]) - { - search_for_string(tb, tb->search_str, TRUE); - } - else - { - tb->dirty_flags |= DIRTY_NO_SEARCH; - } - break; - - case EC_SEARCH_BACK: - if (tb->search_o_ptr) - { - search_for_object(tb, tb->search_o_ptr, FALSE); - } - else if (tb->search_str && tb->search_str[0]) - { - search_for_string(tb, tb->search_str, FALSE); - } - else - { - tb->dirty_flags |= DIRTY_NO_SEARCH; - } - break; - - case EC_SEARCH_OBJ: - /* Become dirty because of item/equip menu */ - tb->dirty_flags |= DIRTY_SCREEN; - - if (!get_object_for_search(&tb->search_o_ptr, &tb->search_str)) break; - - do_editor_command(tb, EC_SEARCH_FORW); - break; - - case EC_SEARCH_DESTROYED: - if (!get_destroyed_object_for_search(&tb->search_o_ptr, &tb->search_str)) - { - /* There is no object to search */ - tb->dirty_flags |= DIRTY_NO_SEARCH; - - break; - } - - do_editor_command(tb, EC_SEARCH_FORW); - break; - - case EC_INSERT_OBJECT: - { - /* Insert choosen item name */ - - autopick_type an_entry, *entry = &an_entry; - - if (!entry_from_choosed_object(entry)) - { - /* Now dirty because of item/equip menu */ - tb->dirty_flags |= DIRTY_SCREEN; - break; - } - - tb->cx = 0; - insert_return_code(tb); - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = autopick_line_from_entry_kill(entry); - - /* Now dirty because of item/equip menu */ - tb->dirty_flags |= DIRTY_SCREEN; - - break; - } - - case EC_INSERT_DESTROYED: - /* Insert a name of last destroyed item */ - if (tb->last_destroyed) - { - tb->cx = 0; - insert_return_code(tb); - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make(tb->last_destroyed); - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - - /* Text is changed */ - tb->changed = TRUE; - } - break; - - case EC_INSERT_BLOCK: - { - /* Insert a conditinal expression line */ - char expression[80]; - - /* Conditional Expression for Class and Race */ - sprintf(expression, "?:[AND [EQU $RACE %s] [EQU $CLASS %s] [GEQ $LEVEL %02d]]", -#ifdef JP - rp_ptr->E_title, cp_ptr->E_title, -#else - rp_ptr->title, cp_ptr->title, -#endif - p_ptr->lev - ); - - tb->cx = 0; - insert_return_code(tb); - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make(expression); - tb->cy++; - insert_return_code(tb); - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make("?:1"); - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - - /* Text is changed */ - tb->changed = TRUE; - - break; - } - - case EC_INSERT_MACRO: - /* Draw_everythig (delete menu) */ - draw_text_editor(tb); - - /* Erase line */ - Term_erase(0, tb->cy - tb->upper + 1, tb->wid); - - /* Prompt */ - Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, _("P:<トリガーキー>: ", "P:: ")); - if (insert_macro_line(tb)) - { - /* Prepare to input action */ - tb->cx = 2; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - - /* Text is changed */ - tb->changed = TRUE; - } - - break; - - case EC_INSERT_KEYMAP: - /* Draw_everythig (delete menu) */ - draw_text_editor(tb); - - /* Erase line */ - Term_erase(0, tb->cy - tb->upper + 1, tb->wid); - - /* Prompt */ - Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, - format(_("C:%d:<コマンドキー>: ", "C:%d:: "), (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG))); - - if (insert_keymap_line(tb)) - { - /* Prepare to input action */ - tb->cx = 2; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - - /* Text is changed */ - tb->changed = TRUE; - } - break; - - case EC_CL_AUTOPICK: toggle_command_letter(tb, DO_AUTOPICK); break; - case EC_CL_DESTROY: toggle_command_letter(tb, DO_AUTODESTROY); break; - case EC_CL_LEAVE: toggle_command_letter(tb, DONT_AUTOPICK); break; - case EC_CL_QUERY: toggle_command_letter(tb, DO_QUERY_AUTOPICK); break; - case EC_CL_NO_DISP: toggle_command_letter(tb, DO_DISPLAY); break; - - case EC_IK_UNAWARE: toggle_keyword(tb, FLG_UNAWARE); break; - case EC_IK_UNIDENTIFIED: toggle_keyword(tb, FLG_UNIDENTIFIED); break; - case EC_IK_IDENTIFIED: toggle_keyword(tb, FLG_IDENTIFIED); break; - case EC_IK_STAR_IDENTIFIED: toggle_keyword(tb, FLG_STAR_IDENTIFIED); break; - case EC_KK_WEAPONS: toggle_keyword(tb, FLG_WEAPONS); break; - case EC_KK_FAVORITE_WEAPONS: toggle_keyword(tb, FLG_FAVORITE_WEAPONS); break; - case EC_KK_ARMORS: toggle_keyword(tb, FLG_ARMORS); break; - case EC_KK_MISSILES: toggle_keyword(tb, FLG_MISSILES); break; - case EC_KK_DEVICES: toggle_keyword(tb, FLG_DEVICES); break; - case EC_KK_LIGHTS: toggle_keyword(tb, FLG_LIGHTS); break; - case EC_KK_JUNKS: toggle_keyword(tb, FLG_JUNKS); break; - case EC_KK_CORPSES: toggle_keyword(tb, FLG_CORPSES); break; - case EC_KK_SPELLBOOKS: toggle_keyword(tb, FLG_SPELLBOOKS); break; - case EC_KK_SHIELDS: toggle_keyword(tb, FLG_SHIELDS); break; - case EC_KK_BOWS: toggle_keyword(tb, FLG_BOWS); break; - case EC_KK_RINGS: toggle_keyword(tb, FLG_RINGS); break; - case EC_KK_AMULETS: toggle_keyword(tb, FLG_AMULETS); break; - case EC_KK_SUITS: toggle_keyword(tb, FLG_SUITS); break; - case EC_KK_CLOAKS: toggle_keyword(tb, FLG_CLOAKS); break; - case EC_KK_HELMS: toggle_keyword(tb, FLG_HELMS); break; - case EC_KK_GLOVES: toggle_keyword(tb, FLG_GLOVES); break; - case EC_KK_BOOTS: toggle_keyword(tb, FLG_BOOTS); break; - case EC_OK_COLLECTING: toggle_keyword(tb, FLG_COLLECTING); break; - case EC_OK_BOOSTED: toggle_keyword(tb, FLG_BOOSTED); break; - case EC_OK_MORE_DICE: toggle_keyword(tb, FLG_MORE_DICE); break; - case EC_OK_MORE_BONUS: toggle_keyword(tb, FLG_MORE_BONUS); break; - case EC_OK_WORTHLESS: toggle_keyword(tb, FLG_WORTHLESS); break; - case EC_OK_ARTIFACT: toggle_keyword(tb, FLG_ARTIFACT); break; - case EC_OK_EGO: toggle_keyword(tb, FLG_EGO); break; - case EC_OK_GOOD: toggle_keyword(tb, FLG_GOOD); break; - case EC_OK_NAMELESS: toggle_keyword(tb, FLG_NAMELESS); break; - case EC_OK_AVERAGE: toggle_keyword(tb, FLG_AVERAGE); break; - case EC_OK_RARE: toggle_keyword(tb, FLG_RARE); break; - case EC_OK_COMMON: toggle_keyword(tb, FLG_COMMON); break; - case EC_OK_WANTED: toggle_keyword(tb, FLG_WANTED); break; - case EC_OK_UNIQUE: toggle_keyword(tb, FLG_UNIQUE); break; - case EC_OK_HUMAN: toggle_keyword(tb, FLG_HUMAN); break; - case EC_OK_UNREADABLE: - toggle_keyword(tb, FLG_UNREADABLE); - add_keyword(tb, FLG_SPELLBOOKS); - break; - case EC_OK_REALM1: - toggle_keyword(tb, FLG_REALM1); - add_keyword(tb, FLG_SPELLBOOKS); - break; - case EC_OK_REALM2: - toggle_keyword(tb, FLG_REALM2); - add_keyword(tb, FLG_SPELLBOOKS); - break; - case EC_OK_FIRST: - toggle_keyword(tb, FLG_FIRST); - add_keyword(tb, FLG_SPELLBOOKS); - break; - case EC_OK_SECOND: - toggle_keyword(tb, FLG_SECOND); - add_keyword(tb, FLG_SPELLBOOKS); - break; - case EC_OK_THIRD: - toggle_keyword(tb, FLG_THIRD); - add_keyword(tb, FLG_SPELLBOOKS); - break; - case EC_OK_FOURTH: - toggle_keyword(tb, FLG_FOURTH); - add_keyword(tb, FLG_SPELLBOOKS); - break; - } - - /* Save old command */ - tb->old_com_id = com_id; - - return FALSE; -} - - -/* - * Insert single letter at cursor position. - */ -static void insert_single_letter(text_body_type *tb, int key) -{ - int i, j, len; - char buf[MAX_LINELEN]; - - /* Save preceding string */ - for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++) - buf[j++] = tb->lines_list[tb->cy][i]; - - /* Add a character */ -#ifdef JP - if (iskanji(key)) - { - int next; - - inkey_base = TRUE; - next = inkey(); - if (j+2 < MAX_LINELEN) - { - buf[j++] = (char)key; - buf[j++] = (char)next; - tb->cx += 2; - } - else - bell(); - } - else -#endif - { - if (j+1 < MAX_LINELEN) - buf[j++] = (char)key; - tb->cx++; - } - - /* Add following */ - for (; tb->lines_list[tb->cy][i] && j + 1 < MAX_LINELEN; i++) - buf[j++] = tb->lines_list[tb->cy][i]; - buf[j] = '\0'; - - /* Replace current line with new line */ - string_free(tb->lines_list[tb->cy]); - tb->lines_list[tb->cy] = string_make(buf); - - /* Move to correct collumn */ - len = strlen(tb->lines_list[tb->cy]); - if (len < tb->cx) tb->cx = len; - - /* Now dirty */ - tb->dirty_line = tb->cy; - - /* Expressions may need re-evaluation */ - check_expression_line(tb, tb->cy); - - /* Text is changed */ - tb->changed = TRUE; -} - - -/* - * Check special key code and get a movement command id - */ -static int analyze_move_key(text_body_type *tb, int skey) -{ - int com_id; - - /* Not a special key */ - if (!(skey & SKEY_MASK)) return 0; - - /* Convert from a special key code to an editor command */ - switch(skey & ~SKEY_MOD_MASK) - { - case SKEY_DOWN: com_id = EC_DOWN; break; - case SKEY_LEFT: com_id = EC_LEFT; break; - case SKEY_RIGHT: com_id = EC_RIGHT; break; - case SKEY_UP: com_id = EC_UP; break; - case SKEY_PGUP: com_id = EC_PGUP; break; - case SKEY_PGDOWN: com_id = EC_PGDOWN; break; - case SKEY_TOP: com_id = EC_TOP; break; - case SKEY_BOTTOM: com_id = EC_BOTTOM; break; - - default: - /* Not a special movement key */ - return 0; - } - - /* Without shift modifier */ - if (!(skey & SKEY_MOD_SHIFT)) - { - /* - * Un-shifted cursor keys cancells - * selection created by shift+cursor. - */ - if (tb->mark & MARK_BY_SHIFT) - { - tb->mark = 0; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - } - } - - /* With shift modifier */ - else - { - /* Start selection by shift + cursor keys */ - if (!tb->mark) - { - int len = strlen(tb->lines_list[tb->cy]); - - tb->mark = MARK_MARK | MARK_BY_SHIFT; - tb->my = tb->cy; - tb->mx = tb->cx; - - /* Correct cursor location */ - if (tb->cx > len) tb->mx = len; - - /* Need to redraw text */ - if (com_id == EC_UP || com_id == EC_DOWN) - { - /* Redraw all text */ - tb->dirty_flags |= DIRTY_ALL; - } - else - { - tb->dirty_line = tb->cy; - } - } - } - - return com_id; -} - -/* - * In-game editor of Object Auto-picker/Destoryer - */ -void do_cmd_edit_autopick(void) -{ - static int cx_save = 0; - static int cy_save = 0; - - text_body_type text_body, *tb = &text_body; - - autopick_type an_entry, *entry = &an_entry; - char buf[MAX_LINELEN]; - - int i; - int key = -1; - - static s32b old_autosave_turn = 0L; - byte quit = 0; - - tb->changed = FALSE; - tb->cx = cx_save; - tb->cy = cy_save; - tb->upper = tb->left = 0; - tb->mark = 0; - tb->mx = tb->my = 0; - tb->old_cy = tb->old_upper = tb->old_left = -1; - tb->old_wid = tb->old_hgt = -1; - tb->old_com_id = 0; - - tb->yank = NULL; - tb->search_o_ptr = NULL; - tb->search_str = NULL; - tb->last_destroyed = NULL; - tb->dirty_flags = DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION; - tb->dirty_line = -1; - tb->filename_mode = PT_DEFAULT; - - if (current_world_ptr->game_turn < old_autosave_turn) - { - while (old_autosave_turn > current_world_ptr->game_turn) old_autosave_turn -= TURNS_PER_TICK * TOWN_DAWN; - } - - /* Autosave */ - if (current_world_ptr->game_turn > old_autosave_turn + 100L) - { - do_cmd_save_game(TRUE); - old_autosave_turn = current_world_ptr->game_turn; - } - - /* HACK -- Reset start_time to stop counting current_world_ptr->play_time while edit */ - update_playtime(); - - /* Free old entries */ - init_autopick(); - - /* Command Description of the 'Last Destroyed Item' */ - if (autopick_last_destroyed_object.k_idx) - { - autopick_entry_from_object(entry, &autopick_last_destroyed_object); - tb->last_destroyed = autopick_line_from_entry_kill(entry); - } - - /* Read or initialize whole text */ - tb->lines_list = read_pickpref_text_lines(&tb->filename_mode); - - /* Reset cursor position if needed */ - for (i = 0; i < tb->cy; i++) - { - if (!tb->lines_list[i]) - { - tb->cy = tb->cx = 0; - break; - } - } - screen_save(); - - /* Process requests until done */ - while (!quit) - { - int com_id = 0; - - /* Draw_everythig */ - draw_text_editor(tb); - - /* Display header line */ - prt(_("(^Q:終了 ^W:セーブして終了, ESC:メニュー, その他:入力)", - "(^Q:Quit, ^W:Save&Quit, ESC:Menu, Other:Input text)"), 0, 0); - if (!tb->mark) - { - /* Display current position */ - prt (format("(%d,%d)", tb->cx, tb->cy), 0, 60); - } - else - { - /* Display current position and mark position */ - prt (format("(%d,%d)-(%d,%d)", tb->mx, tb->my, tb->cx, tb->cy), 0, 60); - } - - /* Place cursor */ - Term_gotoxy(tb->cx - tb->left, tb->cy - tb->upper + 1); - - /* Now clean */ - tb->dirty_flags = 0; - tb->dirty_line = -1; - - /* Save old key and location */ - tb->old_cy = tb->cy; - tb->old_upper = tb->upper; - tb->old_left = tb->left; - tb->old_wid = tb->wid; - tb->old_hgt = tb->hgt; - - key = inkey_special(TRUE); - - /* Special keys */ - if (key & SKEY_MASK) - { - /* Get a movement command */ - com_id = analyze_move_key(tb, key); - } - - /* Open the menu */ - else if (key == ESCAPE) - { - com_id = do_command_menu(0, 0); - - /* Redraw all text later */ - tb->dirty_flags |= DIRTY_SCREEN; - } - - /* Insert a character */ - else if (!iscntrl((unsigned char)key)) - { - /* Ignore selection */ - if (tb->mark) - { - tb->mark = 0; - - /* Now dirty */ - tb->dirty_flags |= DIRTY_ALL; - } - - insert_single_letter(tb, key); - - /* Next loop */ - continue; - } - - /* Other commands */ - else - { - com_id = get_com_id((char)key); - } - - if (com_id) quit = do_editor_command(tb, com_id); - } /* while (TRUE) */ - screen_load(); - - /* Get the filename of preference */ - strcpy(buf, pickpref_filename(tb->filename_mode)); - - if (quit == QUIT_AND_SAVE) - write_text_lines(buf, tb->lines_list); - - free_text_lines(tb->lines_list); - - string_free(tb->search_str); - string_free(tb->last_destroyed); - - /* Destroy string chain */ - kill_yank_chain(tb); - - /* Reload autopick pref */ - process_autopick_file(buf); - - /* HACK -- reset start_time so that current_world_ptr->play_time is not increase while edit */ - start_time = (u32b)time(NULL); - - /* Save cursor location */ - cx_save = tb->cx; - cy_save = tb->cy; -} diff --git a/src/autopick/autopick-command-menu.c b/src/autopick/autopick-command-menu.c new file mode 100644 index 000000000..658656d64 --- /dev/null +++ b/src/autopick/autopick-command-menu.c @@ -0,0 +1,143 @@ +/*! + * todo 1関数100行以上ある、後で関数を分割すること + * @brief 自動拾いエディタのコマンドを受け付ける + * @date 2020/04/26 + * @author Hourier + */ + +#include "autopick/autopick-command-menu.h" +#include "autopick/autopick-menu-data-table.h" +#include "autopick/autopick-util.h" +#include "io/input-key-acceptor.h" +#include "system/angband.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/int-char-converter.h" + +/*! + * @brief 自動拾いエディタの画面を再描画する + * @param redraw 再描画が必要ならTRUE + * @param level command_menu_type 構造体におけるメニュー (詳細不明) + * @param start + * @param linestr + * @param menu_key 自動拾いエディタのメニューで入力したキー + * @param max_len + * @return なし + */ +static void redraw_edit_command_menu(bool *redraw, int level, int start, char *linestr, byte *menu_key, int max_len) +{ + if (!*redraw) return; + + int col0 = 5 + level * 7; + int row0 = 1 + level * 3; + int row1 = row0 + 1; + term_putstr(col0, row0, -1, TERM_WHITE, linestr); + + *menu_key = 0; + for (int i = start; menu_data[i].level >= level; i++) + { + char com_key_str[3]; + concptr str; + if (menu_data[i].level > level) continue; + + if (menu_data[i].com_id == -1) + { + strcpy(com_key_str, _("▼", ">")); + } + else if (menu_data[i].key != -1) + { + com_key_str[0] = '^'; + com_key_str[1] = menu_data[i].key + '@'; + com_key_str[2] = '\0'; + } + else + { + com_key_str[0] = '\0'; + } + + str = format("| %c) %-*s %2s | ", *menu_key + 'a', max_len, menu_data[i].name, com_key_str); + + term_putstr(col0, row1++, -1, TERM_WHITE, str); + + (*menu_key)++; + } + + term_putstr(col0, row1, -1, TERM_WHITE, linestr); + *redraw = FALSE; +} + + +/* + * Display the menu, and get a command + */ +int do_command_menu(int level, int start) +{ + int max_len = 0; + int menu_id_list[26]; + byte menu_key = 0; + for (int i = start; menu_data[i].level >= level; i++) + { + /* Ignore lower level sub menus */ + if (menu_data[i].level > level) continue; + + int len = strlen(menu_data[i].name); + if (len > max_len) max_len = len; + + menu_id_list[menu_key] = i; + menu_key++; + } + + while (menu_key < 26) + { + menu_id_list[menu_key] = -1; + menu_key++; + } + + int max_menu_wid = max_len + 3 + 3; + + char linestr[MAX_LINELEN]; + linestr[0] = '\0'; + strcat(linestr, "+"); + for (int i = 0; i < max_menu_wid + 2; i++) + { + strcat(linestr, "-"); + } + + strcat(linestr, "+"); + bool redraw = TRUE; + while (TRUE) + { + redraw_edit_command_menu(&redraw, level, start, linestr, &menu_key, max_len); + prt(format(_("(a-%c) コマンド:", "(a-%c) Command:"), menu_key + 'a' - 1), 0, 0); + char key = inkey(); + if (key == ESCAPE) return 0; + + int com_id; + bool is_alphabet = key >= 'a' && key <= 'z'; + if (!is_alphabet) + { + com_id = get_com_id(key); + if (com_id) + { + return com_id; + } + + continue; + } + + int menu_id = menu_id_list[key - 'a']; + if (menu_id < 0) continue; + + com_id = menu_data[menu_id].com_id; + if (com_id == -1) + { + com_id = do_command_menu(level + 1, menu_id + 1); + if (com_id) return com_id; + else redraw = TRUE; + } + else if (com_id) + { + return com_id; + } + } +} diff --git a/src/autopick/autopick-command-menu.h b/src/autopick/autopick-command-menu.h new file mode 100644 index 000000000..429eda205 --- /dev/null +++ b/src/autopick/autopick-command-menu.h @@ -0,0 +1,3 @@ +#pragma once + +int do_command_menu(int level, int start); diff --git a/src/autopick/autopick-commands-table.h b/src/autopick/autopick-commands-table.h new file mode 100644 index 000000000..9f7fd1609 --- /dev/null +++ b/src/autopick/autopick-commands-table.h @@ -0,0 +1,86 @@ +#pragma once + +/* + * Editor command id's + */ +#define EC_QUIT 1 +#define EC_SAVEQUIT 2 +#define EC_REVERT 3 +#define EC_HELP 4 +#define EC_RETURN 5 +#define EC_LEFT 6 +#define EC_DOWN 7 +#define EC_UP 8 +#define EC_RIGHT 9 +#define EC_BOL 10 +#define EC_EOL 11 +#define EC_PGUP 12 +#define EC_PGDOWN 13 +#define EC_TOP 14 +#define EC_BOTTOM 15 +#define EC_CUT 16 +#define EC_COPY 17 +#define EC_PASTE 18 +#define EC_BLOCK 19 +#define EC_KILL_LINE 20 +#define EC_DELETE_CHAR 21 +#define EC_BACKSPACE 22 +#define EC_SEARCH_STR 23 +#define EC_SEARCH_FORW 24 +#define EC_SEARCH_BACK 25 +#define EC_SEARCH_OBJ 26 +#define EC_SEARCH_DESTROYED 27 +#define EC_INSERT_OBJECT 28 +#define EC_INSERT_DESTROYED 29 +#define EC_INSERT_BLOCK 30 +#define EC_INSERT_MACRO 31 +#define EC_INSERT_KEYMAP 32 +#define EC_CL_AUTOPICK 33 +#define EC_CL_DESTROY 34 +#define EC_CL_LEAVE 35 +#define EC_CL_QUERY 36 +#define EC_CL_NO_DISP 37 +#define EC_OK_COLLECTING 38 +#define EC_IK_UNAWARE 39 +#define EC_IK_UNIDENTIFIED 40 +#define EC_IK_IDENTIFIED 41 +#define EC_IK_STAR_IDENTIFIED 42 +#define EC_OK_BOOSTED 43 +#define EC_OK_MORE_DICE 44 +#define EC_OK_MORE_BONUS 45 +#define EC_OK_WORTHLESS 46 +#define EC_OK_ARTIFACT 47 +#define EC_OK_EGO 48 +#define EC_OK_GOOD 49 +#define EC_OK_NAMELESS 50 +#define EC_OK_AVERAGE 51 +#define EC_OK_RARE 52 +#define EC_OK_COMMON 53 +#define EC_OK_WANTED 54 +#define EC_OK_UNIQUE 55 +#define EC_OK_HUMAN 56 +#define EC_OK_UNREADABLE 57 +#define EC_OK_REALM1 58 +#define EC_OK_REALM2 59 +#define EC_OK_FIRST 60 +#define EC_OK_SECOND 61 +#define EC_OK_THIRD 62 +#define EC_OK_FOURTH 63 +#define EC_KK_WEAPONS 64 +#define EC_KK_FAVORITE_WEAPONS 65 +#define EC_KK_ARMORS 66 +#define EC_KK_MISSILES 67 +#define EC_KK_DEVICES 68 +#define EC_KK_LIGHTS 69 +#define EC_KK_JUNKS 70 +#define EC_KK_CORPSES 71 +#define EC_KK_SPELLBOOKS 72 +#define EC_KK_SHIELDS 73 +#define EC_KK_BOWS 74 +#define EC_KK_RINGS 75 +#define EC_KK_AMULETS 76 +#define EC_KK_SUITS 77 +#define EC_KK_CLOAKS 78 +#define EC_KK_HELMS 79 +#define EC_KK_GLOVES 80 +#define EC_KK_BOOTS 81 diff --git a/src/autopick/autopick-describer.c b/src/autopick/autopick-describer.c new file mode 100644 index 000000000..ae3fd21bd --- /dev/null +++ b/src/autopick/autopick-describer.c @@ -0,0 +1,596 @@ +/*! + * todo 1つ300行近い関数なので後ほど要分割 + * @brief 自動拾いの記述 + * @date 2020/04/25 + * @author Hourier + */ + +#include "autopick/autopick-describer.h" +#include "autopick/autopick-flags-table.h" +#include "autopick/autopick-key-flag-process.h" +#include "autopick/autopick-methods-table.h" +#include "system/angband.h" +#include "util/string-processor.h" + +typedef struct +{ + concptr str; + byte act; + concptr insc; + bool top; + int before_n; + concptr body_str; +} autopick_describer; + +#if JP +static void describe_autpick_jp(char *buff, autopick_type *entry, autopick_describer *describer) +{ + concptr before_str[100]; + if (IS_FLG(FLG_COLLECTING)) + before_str[describer->before_n++] = "収集中で既に持っているスロットにまとめられる"; + + if (IS_FLG(FLG_UNAWARE)) + before_str[describer->before_n++] = "未鑑定でその効果も判明していない"; + + if (IS_FLG(FLG_UNIDENTIFIED)) + before_str[describer->before_n++] = "未鑑定の"; + + if (IS_FLG(FLG_IDENTIFIED)) + before_str[describer->before_n++] = "鑑定済みの"; + + if (IS_FLG(FLG_STAR_IDENTIFIED)) + before_str[describer->before_n++] = "完全に鑑定済みの"; + + if (IS_FLG(FLG_BOOSTED)) + { + before_str[describer->before_n++] = "ダメージダイスが通常より大きい"; + describer->body_str = "武器"; + } + + if (IS_FLG(FLG_MORE_DICE)) + { + static char more_than_desc_str[] = "___"; + before_str[describer->before_n++] = "ダメージダイスの最大値が"; + describer->body_str = "武器"; + + sprintf(more_than_desc_str, "%d", entry->dice); + before_str[describer->before_n++] = more_than_desc_str; + before_str[describer->before_n++] = "以上の"; + } + + if (IS_FLG(FLG_MORE_BONUS)) + { + static char more_bonus_desc_str[] = "___"; + before_str[describer->before_n++] = "修正値が(+"; + + sprintf(more_bonus_desc_str, "%d", entry->bonus); + before_str[describer->before_n++] = more_bonus_desc_str; + before_str[describer->before_n++] = ")以上の"; + } + + if (IS_FLG(FLG_WORTHLESS)) + before_str[describer->before_n++] = "店で無価値と判定される"; + + if (IS_FLG(FLG_ARTIFACT)) + { + before_str[describer->before_n++] = "アーティファクトの"; + describer->body_str = "装備"; + } + + if (IS_FLG(FLG_EGO)) + { + before_str[describer->before_n++] = "エゴアイテムの"; + describer->body_str = "装備"; + } + + if (IS_FLG(FLG_GOOD)) + { + before_str[describer->before_n++] = "上質の"; + describer->body_str = "装備"; + } + + if (IS_FLG(FLG_NAMELESS)) + { + before_str[describer->before_n++] = "エゴでもアーティファクトでもない"; + describer->body_str = "装備"; + } + + if (IS_FLG(FLG_AVERAGE)) + { + before_str[describer->before_n++] = "並の"; + describer->body_str = "装備"; + } + + if (IS_FLG(FLG_RARE)) + { + before_str[describer->before_n++] = "ドラゴン装備やカオス・ブレード等を含む珍しい"; + describer->body_str = "装備"; + } + + if (IS_FLG(FLG_COMMON)) + { + before_str[describer->before_n++] = "ありふれた(ドラゴン装備やカオス・ブレード等の珍しい物ではない)"; + describer->body_str = "装備"; + } + + if (IS_FLG(FLG_WANTED)) + { + before_str[describer->before_n++] = "ハンター事務所で賞金首とされている"; + describer->body_str = "死体や骨"; + } + + if (IS_FLG(FLG_HUMAN)) + { + before_str[describer->before_n++] = "悪魔魔法で使うための人間やヒューマノイドの"; + describer->body_str = "死体や骨"; + } + + if (IS_FLG(FLG_UNIQUE)) + { + before_str[describer->before_n++] = "ユニークモンスターの"; + describer->body_str = "死体や骨"; + } + + if (IS_FLG(FLG_UNREADABLE)) + { + before_str[describer->before_n++] = "あなたが読めない領域の"; + describer->body_str = "魔法書"; + } + + if (IS_FLG(FLG_REALM1)) + { + before_str[describer->before_n++] = "第一領域の"; + describer->body_str = "魔法書"; + } + + if (IS_FLG(FLG_REALM2)) + { + before_str[describer->before_n++] = "第二領域の"; + describer->body_str = "魔法書"; + } + + if (IS_FLG(FLG_FIRST)) + { + before_str[describer->before_n++] = "全4冊の内の1冊目の"; + describer->body_str = "魔法書"; + } + + if (IS_FLG(FLG_SECOND)) + { + before_str[describer->before_n++] = "全4冊の内の2冊目の"; + describer->body_str = "魔法書"; + } + + if (IS_FLG(FLG_THIRD)) + { + before_str[describer->before_n++] = "全4冊の内の3冊目の"; + describer->body_str = "魔法書"; + } + + if (IS_FLG(FLG_FOURTH)) + { + before_str[describer->before_n++] = "全4冊の内の4冊目の"; + describer->body_str = "魔法書"; + } + + if (IS_FLG(FLG_ITEMS)) + ; /* Nothing to do */ + else if (IS_FLG(FLG_WEAPONS)) + describer->body_str = "武器"; + else if (IS_FLG(FLG_FAVORITE_WEAPONS)) + describer->body_str = "得意武器"; + else if (IS_FLG(FLG_ARMORS)) + describer->body_str = "防具"; + else if (IS_FLG(FLG_MISSILES)) + describer->body_str = "弾や矢やクロスボウの矢"; + else if (IS_FLG(FLG_DEVICES)) + describer->body_str = "巻物や魔法棒や杖やロッド"; + else if (IS_FLG(FLG_LIGHTS)) + describer->body_str = "光源用のアイテム"; + else if (IS_FLG(FLG_JUNKS)) + describer->body_str = "折れた棒等のガラクタ"; + else if (IS_FLG(FLG_CORPSES)) + describer->body_str = "死体や骨"; + else if (IS_FLG(FLG_SPELLBOOKS)) + describer->body_str = "魔法書"; + else if (IS_FLG(FLG_HAFTED)) + describer->body_str = "鈍器"; + else if (IS_FLG(FLG_SHIELDS)) + describer->body_str = "盾"; + else if (IS_FLG(FLG_BOWS)) + describer->body_str = "スリングや弓やクロスボウ"; + else if (IS_FLG(FLG_RINGS)) + describer->body_str = "指輪"; + else if (IS_FLG(FLG_AMULETS)) + describer->body_str = "アミュレット"; + else if (IS_FLG(FLG_SUITS)) + describer->body_str = "鎧"; + else if (IS_FLG(FLG_CLOAKS)) + describer->body_str = "クローク"; + else if (IS_FLG(FLG_HELMS)) + describer->body_str = "ヘルメットや冠"; + else if (IS_FLG(FLG_GLOVES)) + describer->body_str = "籠手"; + else if (IS_FLG(FLG_BOOTS)) + describer->body_str = "ブーツ"; + + *buff = '\0'; + if (!describer->before_n) + strcat(buff, "全ての"); + else for (int i = 0; i < describer->before_n && before_str[i]; i++) + strcat(buff, before_str[i]); + + strcat(buff, describer->body_str); + + if (*describer->str) + { + if (*describer->str == '^') + { + describer->str++; + describer->top = TRUE; + } + + strcat(buff, "で、名前が「"); + strncat(buff, describer->str, 80); + if (describer->top) + strcat(buff, "」で始まるもの"); + else + strcat(buff, "」を含むもの"); + } + + if (describer->insc) + { + strncat(buff, format("に「%s」", describer->insc), 80); + + if (angband_strstr(describer->insc, "%%all")) + strcat(buff, "(%%allは全能力を表す英字の記号で置換)"); + else if (angband_strstr(describer->insc, "%all")) + strcat(buff, "(%allは全能力を表す記号で置換)"); + else if (angband_strstr(describer->insc, "%%")) + strcat(buff, "(%%は追加能力を表す英字の記号で置換)"); + else if (angband_strstr(describer->insc, "%")) + strcat(buff, "(%は追加能力を表す記号で置換)"); + + strcat(buff, "と刻んで"); + } + else + strcat(buff, "を"); + + if (describer->act & DONT_AUTOPICK) + strcat(buff, "放置する。"); + else if (describer->act & DO_AUTODESTROY) + strcat(buff, "破壊する。"); + else if (describer->act & DO_QUERY_AUTOPICK) + strcat(buff, "確認の後に拾う。"); + else + strcat(buff, "拾う。"); + + if (describer->act & DO_DISPLAY) + { + if (describer->act & DONT_AUTOPICK) + strcat(buff, "全体マップ('M')で'N'を押したときに表示する。"); + else if (describer->act & DO_AUTODESTROY) + strcat(buff, "全体マップ('M')で'K'を押したときに表示する。"); + else + strcat(buff, "全体マップ('M')で'M'を押したときに表示する。"); + } + else + strcat(buff, "全体マップには表示しない。"); +} +#else + + +void describe_autopick_en(char *buff, autopick_type *entry, autopick_describer *describer) +{ + concptr before_str[20], after_str[20], which_str[20], whose_str[20]; + int after_n = 0, which_n = 0, whose_n = 0; + if (IS_FLG(FLG_COLLECTING)) + which_str[which_n++] = "can be absorbed into an existing inventory list slot"; + + if (IS_FLG(FLG_UNAWARE)) + { + before_str[describer->before_n++] = "unidentified"; + whose_str[whose_n++] = "basic abilities are not known"; + } + + if (IS_FLG(FLG_UNIDENTIFIED)) + before_str[describer->before_n++] = "unidentified"; + + if (IS_FLG(FLG_IDENTIFIED)) + before_str[describer->before_n++] = "identified"; + + if (IS_FLG(FLG_STAR_IDENTIFIED)) + before_str[describer->before_n++] = "fully identified"; + + if (IS_FLG(FLG_RARE)) + { + before_str[describer->before_n++] = "very rare"; + describer->body_str = "equipments"; + after_str[after_n++] = "such as Dragon armor, Blades of Chaos, etc."; + } + + if (IS_FLG(FLG_COMMON)) + { + before_str[describer->before_n++] = "relatively common"; + describer->body_str = "equipments"; + after_str[after_n++] = "compared to very rare Dragon armor, Blades of Chaos, etc."; + } + + if (IS_FLG(FLG_WORTHLESS)) + { + before_str[describer->before_n++] = "worthless"; + which_str[which_n++] = "can not be sold at stores"; + } + + if (IS_FLG(FLG_ARTIFACT)) + before_str[describer->before_n++] = "artifact"; + + if (IS_FLG(FLG_EGO)) + before_str[describer->before_n++] = "ego"; + + if (IS_FLG(FLG_GOOD)) + { + describer->body_str = "equipment"; + which_str[which_n++] = "have good quality"; + } + + if (IS_FLG(FLG_NAMELESS)) + { + describer->body_str = "equipment"; + which_str[which_n++] = "is neither ego-item nor artifact"; + } + + if (IS_FLG(FLG_AVERAGE)) + { + describer->body_str = "equipment"; + which_str[which_n++] = "have average quality"; + } + + if (IS_FLG(FLG_BOOSTED)) + { + describer->body_str = "weapons"; + whose_str[whose_n++] = "damage dice is bigger than normal"; + } + + if (IS_FLG(FLG_MORE_DICE)) + { + static char more_than_desc_str[] = + "maximum damage from dice is bigger than __"; + describer->body_str = "weapons"; + + sprintf(more_than_desc_str + sizeof(more_than_desc_str) - 3, + "%d", entry->dice); + whose_str[whose_n++] = more_than_desc_str; + } + + if (IS_FLG(FLG_MORE_BONUS)) + { + static char more_bonus_desc_str[] = + "magical bonus is bigger than (+__)"; + + sprintf(more_bonus_desc_str + sizeof(more_bonus_desc_str) - 4, + "%d)", entry->bonus); + whose_str[whose_n++] = more_bonus_desc_str; + } + + if (IS_FLG(FLG_WANTED)) + { + describer->body_str = "corpse or skeletons"; + which_str[which_n++] = "is wanted at the Hunter's Office"; + } + + if (IS_FLG(FLG_HUMAN)) + { + before_str[describer->before_n++] = "humanoid"; + describer->body_str = "corpse or skeletons"; + which_str[which_n++] = "can be used for Daemon magic"; + } + + if (IS_FLG(FLG_UNIQUE)) + { + before_str[describer->before_n++] = "unique monster's"; + describer->body_str = "corpse or skeletons"; + } + + if (IS_FLG(FLG_UNREADABLE)) + { + describer->body_str = "spellbooks"; + after_str[after_n++] = "of different realms from yours"; + } + + if (IS_FLG(FLG_REALM1)) + { + describer->body_str = "spellbooks"; + after_str[after_n++] = "of your first realm"; + } + + if (IS_FLG(FLG_REALM2)) + { + describer->body_str = "spellbooks"; + after_str[after_n++] = "of your second realm"; + } + + if (IS_FLG(FLG_FIRST)) + { + before_str[describer->before_n++] = "first one of four"; + describer->body_str = "spellbooks"; + } + + if (IS_FLG(FLG_SECOND)) + { + before_str[describer->before_n++] = "second one of four"; + describer->body_str = "spellbooks"; + } + + if (IS_FLG(FLG_THIRD)) + { + before_str[describer->before_n++] = "third one of four"; + describer->body_str = "spellbooks"; + } + + if (IS_FLG(FLG_FOURTH)) + { + before_str[describer->before_n++] = "fourth one of four"; + describer->body_str = "spellbooks"; + } + + if (IS_FLG(FLG_ITEMS)) + ; /* Nothing to do */ + else if (IS_FLG(FLG_WEAPONS)) + describer->body_str = "weapons"; + else if (IS_FLG(FLG_FAVORITE_WEAPONS)) + describer->body_str = "favorite weapons"; + else if (IS_FLG(FLG_ARMORS)) + describer->body_str = "armors"; + else if (IS_FLG(FLG_MISSILES)) + describer->body_str = "shots, arrows or crossbow bolts"; + else if (IS_FLG(FLG_DEVICES)) + describer->body_str = "scrolls, wands, staffs or rods"; + else if (IS_FLG(FLG_LIGHTS)) + describer->body_str = "light sources"; + else if (IS_FLG(FLG_JUNKS)) + describer->body_str = "junk such as broken sticks"; + else if (IS_FLG(FLG_CORPSES)) + describer->body_str = "corpses or skeletons"; + else if (IS_FLG(FLG_SPELLBOOKS)) + describer->body_str = "spellbooks"; + else if (IS_FLG(FLG_HAFTED)) + describer->body_str = "hafted weapons"; + else if (IS_FLG(FLG_SHIELDS)) + describer->body_str = "shields"; + else if (IS_FLG(FLG_BOWS)) + describer->body_str = "slings, bows or crossbows"; + else if (IS_FLG(FLG_RINGS)) + describer->body_str = "rings"; + else if (IS_FLG(FLG_AMULETS)) + describer->body_str = "amulets"; + else if (IS_FLG(FLG_SUITS)) + describer->body_str = "body armors"; + else if (IS_FLG(FLG_CLOAKS)) + describer->body_str = "cloaks"; + else if (IS_FLG(FLG_HELMS)) + describer->body_str = "helms or crowns"; + else if (IS_FLG(FLG_GLOVES)) + describer->body_str = "gloves"; + else if (IS_FLG(FLG_BOOTS)) + describer->body_str = "boots"; + + if (*describer->str) + { + if (*describer->str == '^') + { + describer->str++; + describer->top = TRUE; + whose_str[whose_n++] = "name begins with \""; + } + else + which_str[which_n++] = "have \""; + } + + if (describer->act & DONT_AUTOPICK) + strcpy(buff, "Leave on floor "); + else if (describer->act & DO_AUTODESTROY) + strcpy(buff, "Destroy "); + else if (describer->act & DO_QUERY_AUTOPICK) + strcpy(buff, "Ask to pick up "); + else + strcpy(buff, "Pickup "); + + if (describer->insc) + { + strncat(buff, format("and inscribe \"%s\"", describer->insc), 80); + + if (angband_strstr(describer->insc, "%all")) + strcat(buff, ", replacing %all with code string representing all abilities,"); + else if (angband_strstr(describer->insc, "%")) + strcat(buff, ", replacing % with code string representing extra random abilities,"); + + strcat(buff, " on "); + } + + if (!describer->before_n) + strcat(buff, "all "); + else + for (int i = 0; i < describer->before_n && before_str[i]; i++) + { + strcat(buff, before_str[i]); + strcat(buff, " "); + } + + strcat(buff, describer->body_str); + for (int i = 0; i < after_n && after_str[i]; i++) + { + strcat(buff, " "); + strcat(buff, after_str[i]); + } + + for (int i = 0; i < whose_n && whose_str[i]; i++) + { + if (i == 0) + strcat(buff, " whose "); + else + strcat(buff, ", and "); + + strcat(buff, whose_str[i]); + } + + if (*describer->str && describer->top) + { + strcat(buff, describer->str); + strcat(buff, "\""); + } + + if (whose_n && which_n) + strcat(buff, ", and "); + + for (int i = 0; i < which_n && which_str[i]; i++) + { + if (i == 0) + strcat(buff, " which "); + else + strcat(buff, ", and "); + + strcat(buff, which_str[i]); + } + + if (*describer->str && !describer->top) + { + strncat(buff, describer->str, 80); + strcat(buff, "\" as part of its name"); + } + + strcat(buff, "."); + + if (describer->act & DO_DISPLAY) + { + if (describer->act & DONT_AUTOPICK) + strcat(buff, " Display these items when you press the N key in the full 'M'ap."); + else if (describer->act & DO_AUTODESTROY) + strcat(buff, " Display these items when you press the K key in the full 'M'ap."); + else + strcat(buff, " Display these items when you press the M key in the full 'M'ap."); + } + else + strcat(buff, " Not displayed in the full map."); +} +#endif + + +/* + * Describe which kind of object is Auto-picked/destroyed + */ +void describe_autopick(char *buff, autopick_type *entry) +{ + autopick_describer describer; + describer.str = entry->name; + describer.act = entry->action; + describer.insc = entry->insc; + describer.top = FALSE; + describer.before_n = 0; + describer.body_str = _("アイテム", "items"); +#ifdef JP + describe_autpick_jp(buff, entry, &describer); +#else + describe_autopick_en(buff, entry, &describer); +#endif +} diff --git a/src/autopick/autopick-describer.h b/src/autopick/autopick-describer.h new file mode 100644 index 000000000..a8069ad35 --- /dev/null +++ b/src/autopick/autopick-describer.h @@ -0,0 +1,5 @@ +#pragma once + +#include "autopick/autopick-util.h" + +void describe_autopick(char *buff, autopick_type *entry); diff --git a/src/autopick/autopick-destroyer.c b/src/autopick/autopick-destroyer.c new file mode 100644 index 000000000..bec6a4572 --- /dev/null +++ b/src/autopick/autopick-destroyer.c @@ -0,0 +1,127 @@ +/*! + * @brief 自動破壊の実行 + * @date 2020/04/25 + * @author Hourier + */ + +#include "autopick/autopick-destroyer.h" +#include "autopick-methods-table.h" +#include "autopick/autopick-util.h" +#include "core/disturbance.h" +#include "core/player-update-types.h" +#include "flavor/flavor-describer.h" +#include "game-option/auto-destruction-options.h" +#include "game-option/input-options.h" +#include "monster-race/monster-race.h" +#include "object-enchant/object-ego.h" +#include "object-enchant/special-object-flags.h" +#include "object-hook/hook-expendable.h" +#include "object-hook/hook-quest.h" +#include "object-hook/hook-weapon.h" +#include "object/object-mark-types.h" +#include "object/object-value.h" +#include "perception/object-perception.h" +#include "player/player-race-types.h" +#include "sv-definition/sv-other-types.h" +#include "sv-definition/sv-wand-types.h" +#include "util/string-processor.h" +#include "view/display-messages.h" + +/*! + * @brief クラス依存のアイテム破壊を調べる + * @param player_ptr プレーヤーへの参照ポインタ + * @param o_ptr アイテムへの参照ポインタ + * @return 特別なクラス、かつそのクラス特有のアイテムであればFALSE、それ以外はTRUE + */ +static bool is_leave_special_item(player_type *player_ptr, object_type *o_ptr) +{ + if (!leave_special) + return TRUE; + + if (player_ptr->prace == RACE_BALROG) { + if (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_CORPSE && angband_strchr("pht", r_info[o_ptr->pval].d_char)) + return FALSE; + } else if (player_ptr->pclass == CLASS_ARCHER) { + if (o_ptr->tval == TV_SKELETON || (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON)) + return FALSE; + } else if (player_ptr->pclass == CLASS_NINJA) { + if (o_ptr->tval == TV_LITE && o_ptr->name2 == EGO_LITE_DARKNESS && object_is_known(o_ptr)) + return FALSE; + } else if (player_ptr->pclass == CLASS_BEASTMASTER || player_ptr->pclass == CLASS_CAVALRY) { + if (o_ptr->tval == TV_WAND && o_ptr->sval == SV_WAND_HEAL_MONSTER && object_is_aware(o_ptr)) + return FALSE; + } + + return TRUE; +} + +/* + * Automatically destroy items in this grid. + */ +static bool is_opt_confirm_destroy(player_type *player_ptr, object_type *o_ptr) +{ + if (!destroy_items) + return FALSE; + + if (leave_worth) + if (object_value(player_ptr, o_ptr) > 0) + return FALSE; + + if (leave_equip) + if (object_is_weapon_armour_ammo(player_ptr, o_ptr)) + return FALSE; + + if (leave_chest) + if ((o_ptr->tval == TV_CHEST) && o_ptr->pval) + return FALSE; + + if (leave_wanted) + if (object_is_bounty(player_ptr, o_ptr)) + return FALSE; + + if (leave_corpse) + if (o_ptr->tval == TV_CORPSE) + return FALSE; + + if (leave_junk) + if ((o_ptr->tval == TV_SKELETON) || (o_ptr->tval == TV_BOTTLE) || (o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_STATUE)) + return FALSE; + + if (!is_leave_special_item(player_ptr, o_ptr)) + return FALSE; + + if (o_ptr->tval == TV_GOLD) + return FALSE; + + return TRUE; +} + +void auto_destroy_item(player_type *player_ptr, object_type *o_ptr, int autopick_idx) +{ + bool destroy = FALSE; + if (is_opt_confirm_destroy(player_ptr, o_ptr)) + destroy = TRUE; + + if (autopick_idx >= 0 && !(autopick_list[autopick_idx].action & DO_AUTODESTROY)) + destroy = FALSE; + + if (!always_pickup) { + if (autopick_idx >= 0 && (autopick_list[autopick_idx].action & DO_AUTODESTROY)) + destroy = TRUE; + } + + if (!destroy) + return; + + disturb(player_ptr, FALSE, FALSE); + if (!can_player_destroy_object(player_ptr, o_ptr)) { + GAME_TEXT o_name[MAX_NLEN]; + describe_flavor(player_ptr, o_name, o_ptr, 0); + msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name); + return; + } + + (void)COPY(&autopick_last_destroyed_object, o_ptr, object_type); + o_ptr->marked |= OM_AUTODESTROY; + player_ptr->update |= PU_AUTODESTROY; +} diff --git a/src/autopick/autopick-destroyer.h b/src/autopick/autopick-destroyer.h new file mode 100644 index 000000000..38aa0bd11 --- /dev/null +++ b/src/autopick/autopick-destroyer.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void auto_destroy_item(player_type *player_ptr, object_type *o_ptr, int autopick_idx); diff --git a/src/autopick/autopick-dirty-flags.h b/src/autopick/autopick-dirty-flags.h new file mode 100644 index 000000000..b285e8834 --- /dev/null +++ b/src/autopick/autopick-dirty-flags.h @@ -0,0 +1,13 @@ +#pragma once + +/* + * Dirty flag for text editor + */ +#define DIRTY_ALL 0x0001 +#define DIRTY_MODE 0x0004 +#define DIRTY_SCREEN 0x0008 +#define DIRTY_NOT_FOUND 0x0010 +#define DIRTY_NO_SEARCH 0x0020 +#define DIRTY_EXPRESSION 0x0040 +#define DIRTY_SKIP_INACTIVE 0x0080 +#define DIRTY_INACTIVE 0x0100 diff --git a/src/autopick/autopick-drawer.c b/src/autopick/autopick-drawer.c new file mode 100644 index 000000000..616e97601 --- /dev/null +++ b/src/autopick/autopick-drawer.c @@ -0,0 +1,309 @@ +/*! + * @brief 自動拾いエディタを表示させる + * @date 2020/04/26 + * @author Hourier + */ + +#include "autopick/autopick-drawer.h" +#include "autopick/autopick-describer.h" +#include "autopick/autopick-dirty-flags.h" +#include "autopick/autopick-entry.h" +#include "io/pref-file-expressor.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/buffer-shaper.h" + +#define DESCRIPT_HGT 3 + +static void process_dirty_expression(player_type *player_ptr, text_body_type *tb) +{ + if ((tb->dirty_flags & DIRTY_EXPRESSION) == 0) return; + + byte state = 0; + for (int y = 0; tb->lines_list[y]; y++) + { + concptr s = tb->lines_list[y]; + char *ss, *s_keep; + tb->states[y] = state; + + if (*s++ != '?') continue; + if (*s++ != ':') continue; + + if (streq(s, "$AUTOREGISTER")) + state |= LSTAT_AUTOREGISTER; + + int s_len = strlen(s); + ss = (char *)string_make(s); + s_keep = ss; + + char f; + concptr v = process_pref_file_expr(player_ptr, &ss, &f); + if (streq(v, "0")) state |= LSTAT_BYPASS; + else state &= ~LSTAT_BYPASS; + + C_KILL(s_keep, s_len + 1, char); + tb->states[y] = state | LSTAT_EXPRESSION; + } + + tb->dirty_flags |= DIRTY_ALL; +} + + +/* + * Draw text + */ +void draw_text_editor(player_type *player_ptr, text_body_type *tb) +{ + int by1 = 0, by2 = 0; + + term_get_size(&tb->wid, &tb->hgt); + + /* + * Top line (-1), description line (-3), separator (-1) + * == -5 + */ + tb->hgt -= 2 + DESCRIPT_HGT; + +#ifdef JP + /* Don't let cursor at second byte of kanji */ + for (int i = 0; tb->lines_list[tb->cy][i]; i++) + if (iskanji(tb->lines_list[tb->cy][i])) + { + i++; + if (i == tb->cx) + { + /* + * Move to a correct position in the + * left or right + */ + if (i & 1) tb->cx--; + else tb->cx++; + break; + } + } +#endif + if (tb->cy < tb->upper || tb->upper + tb->hgt <= tb->cy) + tb->upper = tb->cy - (tb->hgt) / 2; + if (tb->upper < 0) + tb->upper = 0; + if ((tb->cx < tb->left + 10 && tb->left > 0) || tb->left + tb->wid - 5 <= tb->cx) + tb->left = tb->cx - (tb->wid) * 2 / 3; + if (tb->left < 0) + tb->left = 0; + + if (tb->old_wid != tb->wid || tb->old_hgt != tb->hgt) + tb->dirty_flags |= DIRTY_SCREEN; + else if (tb->old_upper != tb->upper || tb->old_left != tb->left) + tb->dirty_flags |= DIRTY_ALL; + + if (tb->dirty_flags & DIRTY_SCREEN) + { + tb->dirty_flags |= (DIRTY_ALL | DIRTY_MODE); + term_clear(); + } + + if (tb->dirty_flags & DIRTY_MODE) + { + char buf[MAX_LINELEN]; + int sepa_length = tb->wid; + int j = 0; + for (; j < sepa_length; j++) + buf[j] = '-'; + buf[j] = '\0'; + term_putstr(0, tb->hgt + 1, sepa_length, TERM_WHITE, buf); + } + + process_dirty_expression(player_ptr, tb); + if (tb->mark) + { + tb->dirty_flags |= DIRTY_ALL; + + by1 = MIN(tb->my, tb->cy); + by2 = MAX(tb->my, tb->cy); + } + + int i; + for (i = 0; i < tb->hgt; i++) + { + int leftcol = 0; + concptr msg; + byte color; + int y = tb->upper + i; + + if (!(tb->dirty_flags & DIRTY_ALL) && (tb->dirty_line != y)) + continue; + + msg = tb->lines_list[y]; + if (!msg) break; + + for (int j = 0; *msg; msg++, j++) + { + if (j == tb->left) break; +#ifdef JP + if (j > tb->left) + { + leftcol = 1; + break; + } + if (iskanji(*msg)) + { + msg++; + j++; + } +#endif + } + + term_erase(0, i + 1, tb->wid); + if (tb->states[y] & LSTAT_AUTOREGISTER) + { + color = TERM_L_RED; + } + else + { + if (tb->states[y] & LSTAT_BYPASS) color = TERM_SLATE; + else color = TERM_WHITE; + } + + if (!tb->mark || (y < by1 || by2 < y)) + { + term_putstr(leftcol, i + 1, tb->wid - 1, color, msg); + } + else if (by1 != by2) + { + term_putstr(leftcol, i + 1, tb->wid - 1, TERM_YELLOW, msg); + } + else + { + int x0 = leftcol + tb->left; + int len = strlen(tb->lines_list[tb->cy]); + int bx1 = MIN(tb->mx, tb->cx); + int bx2 = MAX(tb->mx, tb->cx); + + if (bx2 > len) bx2 = len; + + term_gotoxy(leftcol, i + 1); + if (x0 < bx1) term_addstr(bx1 - x0, color, msg); + if (x0 < bx2) term_addstr(bx2 - bx1, TERM_YELLOW, msg + (bx1 - x0)); + term_addstr(-1, color, msg + (bx2 - x0)); + } + } + + for (; i < tb->hgt; i++) + { + term_erase(0, i + 1, tb->wid); + } + + bool is_dirty_diary = (tb->dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND | DIRTY_NO_SEARCH)) != 0; + bool is_updated = tb->old_cy != tb->cy || is_dirty_diary || tb->dirty_line == tb->cy; + if (!is_updated) return; + + autopick_type an_entry, *entry = &an_entry; + concptr str1 = NULL, str2 = NULL; + for (int j = 0; j < DESCRIPT_HGT; j++) + { + term_erase(0, tb->hgt + 2 + j, tb->wid); + } + + if (tb->dirty_flags & DIRTY_NOT_FOUND) + { + str1 = format(_("パターンが見つかりません: %s", "Pattern not found: %s"), tb->search_str); + } + else if (tb->dirty_flags & DIRTY_SKIP_INACTIVE) + { + str1 = format(_("無効状態の行をスキップしました。(%sを検索中)", + "Some inactive lines are skipped. (Searching %s)"), tb->search_str); + } + else if (tb->dirty_flags & DIRTY_INACTIVE) + { + str1 = format(_("無効状態の行だけが見付かりました。(%sを検索中)", + "Found only an inactive line. (Searching %s)"), tb->search_str); + } + else if (tb->dirty_flags & DIRTY_NO_SEARCH) + { + str1 = _("検索するパターンがありません(^S で検索)。", "No pattern to search. (Press ^S to search.)"); + } + else if (tb->lines_list[tb->cy][0] == '#') + { + str1 = _("この行はコメントです。", "This line is a comment."); + } + else if (tb->lines_list[tb->cy][0] && tb->lines_list[tb->cy][1] == ':') + { + switch (tb->lines_list[tb->cy][0]) + { + case '?': + str1 = _("この行は条件分岐式です。", "This line is a Conditional Expression."); + break; + case 'A': + str1 = _("この行はマクロの実行内容を定義します。", "This line defines a Macro action."); + break; + case 'P': + str1 = _("この行はマクロのトリガー・キーを定義します。", "This line defines a Macro trigger key."); + break; + case 'C': + str1 = _("この行はキー配置を定義します。", "This line defines a Keymap."); + break; + } + + switch (tb->lines_list[tb->cy][0]) + { + case '?': + if (tb->states[tb->cy] & LSTAT_BYPASS) + { + str2 = _("現在の式の値は「偽(=0)」です。", "The expression is 'False'(=0) currently."); + } + else + { + str2 = _("現在の式の値は「真(=1)」です。", "The expression is 'True'(=1) currently."); + } + break; + + default: + if (tb->states[tb->cy] & LSTAT_AUTOREGISTER) + { + str2 = _("この行は後で削除されます。", "This line will be delete later."); + } + + else if (tb->states[tb->cy] & LSTAT_BYPASS) + { + str2 = _("この行は現在は無効な状態です。", "This line is bypassed currently."); + } + break; + } + } + else if (autopick_new_entry(entry, tb->lines_list[tb->cy], FALSE)) + { + char buf[MAX_LINELEN]; + char temp[MAX_LINELEN]; + concptr t; + + describe_autopick(buf, entry); + + if (tb->states[tb->cy] & LSTAT_AUTOREGISTER) + { + strcat(buf, _("この行は後で削除されます。", " This line will be delete later.")); + } + + if (tb->states[tb->cy] & LSTAT_BYPASS) + { + strcat(buf, _("この行は現在は無効な状態です。", " This line is bypassed currently.")); + } + + shape_buffer(buf, 81, temp, sizeof(temp)); + t = temp; + for (int j = 0; j < 3; j++) + { + if (t[0] == 0) + break; + else + { + prt(t, tb->hgt + 1 + 1 + j, 0); + t += strlen(t) + 1; + } + } + + autopick_free_entry(entry); + } + + if (str1) prt(str1, tb->hgt + 1 + 1, 0); + if (str2) prt(str2, tb->hgt + 1 + 2, 0); +} diff --git a/src/autopick/autopick-drawer.h b/src/autopick/autopick-drawer.h new file mode 100644 index 000000000..21528de40 --- /dev/null +++ b/src/autopick/autopick-drawer.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" +#include "autopick/autopick-util.h" + +void draw_text_editor(player_type *player_ptr, text_body_type *tb); diff --git a/src/autopick/autopick-editor-command.c b/src/autopick/autopick-editor-command.c new file mode 100644 index 000000000..57a5383c2 --- /dev/null +++ b/src/autopick/autopick-editor-command.c @@ -0,0 +1,778 @@ +/*! + * todo これ単体で750行を超えているので要分割 + * @brief 自動拾いエディタ画面でキーを押した時の挙動一式 + * @date 2020/04/26 + * @author Hourier + */ + +#include "autopick/autopick-editor-command.h" +#include "autopick/autopick-commands-table.h" +#include "autopick/autopick-dirty-flags.h" +#include "autopick/autopick-drawer.h" +#include "autopick/autopick-editor-util.h" +#include "autopick/autopick-entry.h" +#include "autopick/autopick-finder.h" +#include "autopick/autopick-flags-table.h" +#include "autopick/autopick-inserter-killer.h" +#include "autopick/autopick-methods-table.h" +#include "autopick/autopick-reader-writer.h" +#include "core/asking-player.h" +#include "core/show-file.h" +#include "game-option/input-options.h" +#include "game-option/keymap-directory-getter.h" +#include "player/player-class.h" +#include "player/player-race.h" +#include "term/term-color-types.h" + +/* + * @brief + * @param player_ptr プレーヤーへの参照ポインタ + * @param tb 自動拾いの構文 + * @param com_id エディタ内で打ったコマンド + * @return + * @details Execute a single editor command + */ +ape_quittance do_editor_command(player_type *player_ptr, text_body_type *tb, int com_id) +{ + switch (com_id) + { + case EC_QUIT: + { + if (tb->changed) + { + if (!get_check(_("全ての変更を破棄してから終了します。よろしいですか? ", + "Discard all changes and quit. Are you sure? "))) break; + } + + return APE_QUIT_WITHOUT_SAVE; + } + case EC_SAVEQUIT: + return APE_QUIT_AND_SAVE; + case EC_REVERT: + { + if (!get_check(_("全ての変更を破棄して元の状態に戻します。よろしいですか? ", + "Discard all changes and revert to original file. Are you sure? "))) break; + + free_text_lines(tb->lines_list); + tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode); + tb->dirty_flags |= DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION; + tb->cx = tb->cy = 0; + tb->mark = 0; + tb->changed = FALSE; + break; + } + case EC_HELP: + { + (void)show_file(player_ptr, TRUE, _("jeditor.txt", "editor.txt"), NULL, 0, 0); + tb->dirty_flags |= DIRTY_SCREEN; + break; + } + case EC_RETURN: + { + if (tb->mark) + { + tb->mark = 0; + tb->dirty_flags |= DIRTY_ALL; + } + + insert_return_code(tb); + tb->cy++; + tb->cx = 0; + tb->dirty_flags |= DIRTY_ALL; + break; + } + case EC_LEFT: + { + if (0 < tb->cx) + { + int len; +#ifdef JP + int i; +#endif + tb->cx--; + len = strlen(tb->lines_list[tb->cy]); + if (len < tb->cx) tb->cx = len; +#ifdef JP + for (i = 0; tb->lines_list[tb->cy][i]; i++) + { + if (iskanji(tb->lines_list[tb->cy][i])) + { + i++; + if (i == tb->cx) + { + tb->cx--; + break; + } + } + } +#endif + } + else if (tb->cy > 0) + { + tb->cy--; + tb->cx = strlen(tb->lines_list[tb->cy]); + } + + break; + } + case EC_DOWN: + { + if (!tb->lines_list[tb->cy + 1]) + { + if (!add_empty_line(tb)) break; + } + + tb->cy++; + break; + } + case EC_UP: + if (tb->cy > 0) tb->cy--; + break; + case EC_RIGHT: + { +#ifdef JP + if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++; +#endif + tb->cx++; + int len = strlen(tb->lines_list[tb->cy]); + if (len < tb->cx) + { + tb->cx = len; + if (!tb->lines_list[tb->cy + 1]) + { + if (!add_empty_line(tb)) break; + } + + tb->cy++; + tb->cx = 0; + } + + break; + } + case EC_BOL: + tb->cx = 0; + break; + case EC_EOL: + tb->cx = strlen(tb->lines_list[tb->cy]); + break; + case EC_PGUP: + while (0 < tb->cy && tb->upper <= tb->cy) + tb->cy--; + + while (0 < tb->upper && tb->cy + 1 < tb->upper + tb->hgt) + tb->upper--; + + break; + case EC_PGDOWN: + while (tb->cy < tb->upper + tb->hgt) + { + if (!tb->lines_list[tb->cy + 1]) + { + if (!add_empty_line(tb)) break; + } + + tb->cy++; + } + + tb->upper = tb->cy; + break; + case EC_TOP: + tb->cy = 0; + break; + case EC_BOTTOM: + while (TRUE) + { + if (!tb->lines_list[tb->cy + 1]) + { + if (!add_empty_line(tb)) break; + } + + tb->cy++; + } + + tb->cx = 0; + break; + case EC_CUT: + { + copy_text_to_yank(tb); + if (tb->my == tb->cy) + { + int bx1 = MIN(tb->mx, tb->cx); + int bx2 = MAX(tb->mx, tb->cx); + int len = strlen(tb->lines_list[tb->cy]); + if (bx2 > len) bx2 = len; + + kill_line_segment(tb, tb->cy, bx1, bx2, TRUE); + tb->cx = bx1; + } + else + { + int by1 = MIN(tb->my, tb->cy); + int by2 = MAX(tb->my, tb->cy); + + for (int y = by2; y >= by1; y--) + { + int len = strlen(tb->lines_list[y]); + + kill_line_segment(tb, y, 0, len, TRUE); + } + + tb->cy = by1; + tb->cx = 0; + } + + tb->mark = 0; + tb->dirty_flags |= DIRTY_ALL; + tb->changed = TRUE; + break; + } + case EC_COPY: + { + copy_text_to_yank(tb); + + /* + * Move cursor position to the end of the selection + * + * Pressing ^C ^V correctly duplicates the selection. + */ + if (tb->my != tb->cy) + { + tb->cy = MAX(tb->cy, tb->my); + if (!tb->lines_list[tb->cy + 1]) + { + if (!add_empty_line(tb)) break; + } + + tb->cy++; + break; + } + + tb->cx = MAX(tb->cx, tb->mx); + if (!tb->lines_list[tb->cy][tb->cx]) + { + if (!tb->lines_list[tb->cy + 1]) + { + if (!add_empty_line(tb)) break; + } + + tb->cy++; + tb->cx = 0; + } + + break; + } + case EC_PASTE: + { + chain_str_type *chain = tb->yank; + int len = strlen(tb->lines_list[tb->cy]); + if (!chain) break; + if (tb->cx > len) tb->cx = len; + + if (tb->mark) + { + tb->mark = 0; + tb->dirty_flags |= DIRTY_ALL; + } + + while (chain) + { + concptr yank_str = chain->s; + char buf[MAX_LINELEN]; + int i; + char rest[MAX_LINELEN], *rest_ptr = rest; + for (i = 0; i < tb->cx; i++) + buf[i] = tb->lines_list[tb->cy][i]; + + strcpy(rest, &(tb->lines_list[tb->cy][i])); + while (*yank_str && i < MAX_LINELEN - 1) + { + buf[i++] = *yank_str++; + } + + buf[i] = '\0'; + chain = chain->next; + if (chain || tb->yank_eol) + { + insert_return_code(tb); + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make(buf); + tb->cx = 0; + tb->cy++; + + continue; + } + + tb->cx = strlen(buf); + while (*rest_ptr && i < MAX_LINELEN - 1) + { + buf[i++] = *rest_ptr++; + } + + buf[i] = '\0'; + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make(buf); + break; + } + + tb->dirty_flags |= DIRTY_ALL; + tb->dirty_flags |= DIRTY_EXPRESSION; + tb->changed = TRUE; + break; + } + case EC_BLOCK: + { + if (tb->mark) + { + tb->mark = 0; + tb->dirty_flags |= DIRTY_ALL; + break; + } + + tb->mark = MARK_MARK; + if (com_id == tb->old_com_id) + { + int tmp = tb->cy; + tb->cy = tb->my; + tb->my = tmp; + tmp = tb->cx; + tb->cx = tb->mx; + tb->mx = tmp; + tb->dirty_flags |= DIRTY_ALL; + break; + } + + int len = strlen(tb->lines_list[tb->cy]); + + tb->my = tb->cy; + tb->mx = tb->cx; + if (tb->cx > len) tb->mx = len; + break; + } + case EC_KILL_LINE: + { + int len = strlen(tb->lines_list[tb->cy]); + if (tb->cx > len) tb->cx = len; + + if (tb->mark) + { + tb->mark = 0; + tb->dirty_flags |= DIRTY_ALL; + } + + if (tb->old_com_id != com_id) + { + kill_yank_chain(tb); + tb->yank = NULL; + } + + if (tb->cx < len) + { + add_str_to_yank(tb, &(tb->lines_list[tb->cy][tb->cx])); + kill_line_segment(tb, tb->cy, tb->cx, len, FALSE); + tb->dirty_line = tb->cy; + break; + } + + if (tb->yank_eol) add_str_to_yank(tb, ""); + + tb->yank_eol = TRUE; + do_editor_command(player_ptr, tb, EC_DELETE_CHAR); + break; + } + case EC_DELETE_CHAR: + { + if (tb->mark) + { + tb->mark = 0; + tb->dirty_flags |= DIRTY_ALL; + } + +#ifdef JP + if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++; +#endif + tb->cx++; + int len = strlen(tb->lines_list[tb->cy]); + if (len >= tb->cx) + { + do_editor_command(player_ptr, tb, EC_BACKSPACE); + break; + } + + if (tb->lines_list[tb->cy + 1]) + { + tb->cy++; + tb->cx = 0; + } + else + { + tb->cx = len; + break; + } + + do_editor_command(player_ptr, tb, EC_BACKSPACE); + break; + } + case EC_BACKSPACE: + { + int len, i, j, k; + char buf[MAX_LINELEN]; + if (tb->mark) + { + tb->mark = 0; + tb->dirty_flags |= DIRTY_ALL; + } + + len = strlen(tb->lines_list[tb->cy]); + if (len < tb->cx) tb->cx = len; + + if (tb->cx == 0) + { + if (tb->cy == 0) break; + tb->cx = strlen(tb->lines_list[tb->cy - 1]); + strcpy(buf, tb->lines_list[tb->cy - 1]); + strcat(buf, tb->lines_list[tb->cy]); + string_free(tb->lines_list[tb->cy - 1]); + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy - 1] = string_make(buf); + + for (i = tb->cy; tb->lines_list[i + 1]; i++) + tb->lines_list[i] = tb->lines_list[i + 1]; + + tb->lines_list[i] = NULL; + tb->cy--; + tb->dirty_flags |= DIRTY_ALL; + tb->dirty_flags |= DIRTY_EXPRESSION; + tb->changed = TRUE; + break; + } + + for (i = j = k = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++) + { + k = j; +#ifdef JP + if (iskanji(tb->lines_list[tb->cy][i])) + buf[j++] = tb->lines_list[tb->cy][i++]; +#endif + buf[j++] = tb->lines_list[tb->cy][i]; + } + + while (j > k) + { + tb->cx--; + j--; + } + + for (; tb->lines_list[tb->cy][i]; i++) + { + buf[j++] = tb->lines_list[tb->cy][i]; + } + + buf[j] = '\0'; + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make(buf); + tb->dirty_line = tb->cy; + check_expression_line(tb, tb->cy); + tb->changed = TRUE; + break; + } + case EC_SEARCH_STR: + { + byte search_dir; + tb->dirty_flags |= DIRTY_SCREEN; + search_dir = get_string_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str); + + if (!search_dir) break; + + if (search_dir == 1) do_editor_command(player_ptr, tb, EC_SEARCH_FORW); + else do_editor_command(player_ptr, tb, EC_SEARCH_BACK); + + break; + } + case EC_SEARCH_FORW: + if (tb->search_o_ptr) + { + search_for_object(player_ptr, tb, tb->search_o_ptr, TRUE); + break; + } + + if (tb->search_str && tb->search_str[0]) + { + search_for_string(tb, tb->search_str, TRUE); + break; + } + + tb->dirty_flags |= DIRTY_NO_SEARCH; + break; + + case EC_SEARCH_BACK: + { + if (tb->search_o_ptr) + { + search_for_object(player_ptr, tb, tb->search_o_ptr, FALSE); + break; + } + + if (tb->search_str && tb->search_str[0]) + { + search_for_string(tb, tb->search_str, FALSE); + break; + } + + tb->dirty_flags |= DIRTY_NO_SEARCH; + break; + } + case EC_SEARCH_OBJ: + { + tb->dirty_flags |= DIRTY_SCREEN; + + if (!get_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str)) break; + + do_editor_command(player_ptr, tb, EC_SEARCH_FORW); + break; + } + case EC_SEARCH_DESTROYED: + { + if (!get_destroyed_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str)) + { + tb->dirty_flags |= DIRTY_NO_SEARCH; + break; + } + + do_editor_command(player_ptr, tb, EC_SEARCH_FORW); + break; + } + case EC_INSERT_OBJECT: + { + autopick_type an_entry, *entry = &an_entry; + if (!entry_from_choosed_object(player_ptr, entry)) + { + tb->dirty_flags |= DIRTY_SCREEN; + break; + } + + tb->cx = 0; + insert_return_code(tb); + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = autopick_line_from_entry_kill(entry); + tb->dirty_flags |= DIRTY_SCREEN; + break; + } + case EC_INSERT_DESTROYED: + { + if (!tb->last_destroyed) break; + + tb->cx = 0; + insert_return_code(tb); + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make(tb->last_destroyed); + tb->dirty_flags |= DIRTY_ALL; + tb->changed = TRUE; + break; + } + case EC_INSERT_BLOCK: + { + char expression[80]; + sprintf(expression, "?:[AND [EQU $RACE %s] [EQU $CLASS %s] [GEQ $LEVEL %02d]]", +#ifdef JP + rp_ptr->E_title, cp_ptr->E_title, +#else + rp_ptr->title, cp_ptr->title, +#endif + player_ptr->lev); + tb->cx = 0; + insert_return_code(tb); + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make(expression); + tb->cy++; + insert_return_code(tb); + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make("?:1"); + tb->dirty_flags |= DIRTY_ALL; + tb->changed = TRUE; + break; + } + case EC_INSERT_MACRO: + { + draw_text_editor(player_ptr, tb); + term_erase(0, tb->cy - tb->upper + 1, tb->wid); + term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, _("P:<トリガーキー>: ", "P:: ")); + if (!insert_macro_line(tb)) break; + + tb->cx = 2; + tb->dirty_flags |= DIRTY_ALL; + tb->changed = TRUE; + break; + } + case EC_INSERT_KEYMAP: + { + draw_text_editor(player_ptr, tb); + term_erase(0, tb->cy - tb->upper + 1, tb->wid); + term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, + format(_("C:%d:<コマンドキー>: ", "C:%d:: "), (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG))); + + if (!insert_keymap_line(tb)) break; + + tb->cx = 2; + tb->dirty_flags |= DIRTY_ALL; + tb->changed = TRUE; + break; + } + case EC_CL_AUTOPICK: + toggle_command_letter(tb, DO_AUTOPICK); + break; + case EC_CL_DESTROY: + toggle_command_letter(tb, DO_AUTODESTROY); + break; + case EC_CL_LEAVE: + toggle_command_letter(tb, DONT_AUTOPICK); + break; + case EC_CL_QUERY: + toggle_command_letter(tb, DO_QUERY_AUTOPICK); + break; + case EC_CL_NO_DISP: + toggle_command_letter(tb, DO_DISPLAY); + break; + case EC_IK_UNAWARE: + toggle_keyword(tb, FLG_UNAWARE); + break; + case EC_IK_UNIDENTIFIED: + toggle_keyword(tb, FLG_UNIDENTIFIED); + break; + case EC_IK_IDENTIFIED: + toggle_keyword(tb, FLG_IDENTIFIED); + break; + case EC_IK_STAR_IDENTIFIED: + toggle_keyword(tb, FLG_STAR_IDENTIFIED); + break; + case EC_KK_WEAPONS: + toggle_keyword(tb, FLG_WEAPONS); + break; + case EC_KK_FAVORITE_WEAPONS: + toggle_keyword(tb, FLG_FAVORITE_WEAPONS); + break; + case EC_KK_ARMORS: + toggle_keyword(tb, FLG_ARMORS); + break; + case EC_KK_MISSILES: + toggle_keyword(tb, FLG_MISSILES); + break; + case EC_KK_DEVICES: + toggle_keyword(tb, FLG_DEVICES); + break; + case EC_KK_LIGHTS: + toggle_keyword(tb, FLG_LIGHTS); + break; + case EC_KK_JUNKS: + toggle_keyword(tb, FLG_JUNKS); + break; + case EC_KK_CORPSES: + toggle_keyword(tb, FLG_CORPSES); + break; + case EC_KK_SPELLBOOKS: + toggle_keyword(tb, FLG_SPELLBOOKS); + break; + case EC_KK_SHIELDS: + toggle_keyword(tb, FLG_SHIELDS); + break; + case EC_KK_BOWS: + toggle_keyword(tb, FLG_BOWS); + break; + case EC_KK_RINGS: + toggle_keyword(tb, FLG_RINGS); + break; + case EC_KK_AMULETS: + toggle_keyword(tb, FLG_AMULETS); + break; + case EC_KK_SUITS: + toggle_keyword(tb, FLG_SUITS); + break; + case EC_KK_CLOAKS: + toggle_keyword(tb, FLG_CLOAKS); + break; + case EC_KK_HELMS: + toggle_keyword(tb, FLG_HELMS); + break; + case EC_KK_GLOVES: + toggle_keyword(tb, FLG_GLOVES); + break; + case EC_KK_BOOTS: + toggle_keyword(tb, FLG_BOOTS); + break; + case EC_OK_COLLECTING: + toggle_keyword(tb, FLG_COLLECTING); + break; + case EC_OK_BOOSTED: + toggle_keyword(tb, FLG_BOOSTED); + break; + case EC_OK_MORE_DICE: + toggle_keyword(tb, FLG_MORE_DICE); + break; + case EC_OK_MORE_BONUS: + toggle_keyword(tb, FLG_MORE_BONUS); + break; + case EC_OK_WORTHLESS: + toggle_keyword(tb, FLG_WORTHLESS); + break; + case EC_OK_ARTIFACT: + toggle_keyword(tb, FLG_ARTIFACT); + break; + case EC_OK_EGO: + toggle_keyword(tb, FLG_EGO); + break; + case EC_OK_GOOD: + toggle_keyword(tb, FLG_GOOD); + break; + case EC_OK_NAMELESS: + toggle_keyword(tb, FLG_NAMELESS); + break; + case EC_OK_AVERAGE: + toggle_keyword(tb, FLG_AVERAGE); + break; + case EC_OK_RARE: + toggle_keyword(tb, FLG_RARE); + break; + case EC_OK_COMMON: + toggle_keyword(tb, FLG_COMMON); + break; + case EC_OK_WANTED: + toggle_keyword(tb, FLG_WANTED); + break; + case EC_OK_UNIQUE: + toggle_keyword(tb, FLG_UNIQUE); + break; + case EC_OK_HUMAN: + toggle_keyword(tb, FLG_HUMAN); + break; + case EC_OK_UNREADABLE: + toggle_keyword(tb, FLG_UNREADABLE); + add_keyword(tb, FLG_SPELLBOOKS); + break; + case EC_OK_REALM1: + toggle_keyword(tb, FLG_REALM1); + add_keyword(tb, FLG_SPELLBOOKS); + break; + case EC_OK_REALM2: + toggle_keyword(tb, FLG_REALM2); + add_keyword(tb, FLG_SPELLBOOKS); + break; + case EC_OK_FIRST: + toggle_keyword(tb, FLG_FIRST); + add_keyword(tb, FLG_SPELLBOOKS); + break; + case EC_OK_SECOND: + toggle_keyword(tb, FLG_SECOND); + add_keyword(tb, FLG_SPELLBOOKS); + break; + case EC_OK_THIRD: + toggle_keyword(tb, FLG_THIRD); + add_keyword(tb, FLG_SPELLBOOKS); + break; + case EC_OK_FOURTH: + toggle_keyword(tb, FLG_FOURTH); + add_keyword(tb, FLG_SPELLBOOKS); + break; + } + + tb->old_com_id = com_id; + return APE_QUIT; +} diff --git a/src/autopick/autopick-editor-command.h b/src/autopick/autopick-editor-command.h new file mode 100644 index 000000000..def634790 --- /dev/null +++ b/src/autopick/autopick-editor-command.h @@ -0,0 +1,13 @@ +#pragma once + +#include "system/angband.h" +#include "autopick/autopick-util.h" + +/*! APE means AutoPickEditor*/ +typedef enum ape_quittance { + APE_QUIT = 0, + APE_QUIT_WITHOUT_SAVE = 1, + APE_QUIT_AND_SAVE = 2 +} ape_quittance; + +ape_quittance do_editor_command(player_type *player_ptr, text_body_type *tb, int com_id); diff --git a/src/autopick/autopick-editor-table.h b/src/autopick/autopick-editor-table.h new file mode 100644 index 000000000..e73addc5a --- /dev/null +++ b/src/autopick/autopick-editor-table.h @@ -0,0 +1,76 @@ +#pragma once + +/*! + * todo GAME_TEXT[] かconcptrを使いたかった + * しかしコンパイルエラーで通らなかったので暫定的にdefineにした + * 上手いことコンパイルできる方法があれば求む + * @brief コマンド説明 + */ +#define MN_QUIT _("セーブ無しで終了", "Quit without save") +#define MN_SAVEQUIT _("セーブして終了", "Save & Quit") +#define MN_REVERT _("全ての変更を破棄", "Revert all changes") +#define MN_HELP _("ヘルプ", "Help") + +#define MN_MOVE _("カーソル移動", "Move cursor") +#define MN_LEFT _("å·¦ (←矢印キー)", "Left (Left Arrow key)") +#define MN_DOWN _("下 (↓矢印キー)", "Down (Down Arrow key)") +#define MN_UP _("上 (↑矢印キー)", "Up (Up Arrow key)") +#define MN_RIGHT _("右 (→矢印キー)", "Right (Right Arrow key)") +#define MN_BOL _("行の先頭", "Beggining of line") +#define MN_EOL _("行の終端", "End of line") +#define MN_PGUP _("上のページ (PageUpキー)", "Page up (PageUp key)") +#define MN_PGDOWN _("下のページ (PageDownキー)", "Page down(PageDown key)") +#define MN_TOP _("1行目へ移動 (Homeキー)", "Top (Home key)") +#define MN_BOTTOM _("最下行へ移動(Endキー)", "Bottom (End key)") + +#define MN_EDIT _("編集", "Edit") +#define MN_CUT _("カット", "Cut") +#define MN_COPY _("コピー", "Copy") +#define MN_PASTE _("ペースト", "Paste") +#define MN_BLOCK _("選択範囲の指定", "Select block") +#define MN_KILL_LINE _("行の残りを削除", "Kill rest of line") +#define MN_DELETE_CHAR _("1文字削除", "Delete character") +#define MN_BACKSPACE _("バックスペース", "Backspace") +#define MN_RETURN _("改行", "Return") + +#define MN_SEARCH _("検索", "Search") +#define MN_SEARCH_STR _("文字列で検索", "Search by string") +#define MN_SEARCH_FORW _("前方へ再検索", "Search foward") +#define MN_SEARCH_BACK _("後方へ再検索", "Search backward") +#define MN_SEARCH_OBJ _("アイテムを選択して検索", "Search by inventory object") +#define MN_SEARCH_DESTROYED _("自動破壊されたアイテムで検索", "Search by destroyed object") + +#define MN_INSERT _("色々挿入", "Insert...") +#define MN_INSERT_OBJECT _("選択したアイテムの名前を挿入", "Insert name of choosen object") +#define MN_INSERT_DESTROYED _("自動破壊されたアイテムの名前を挿入", "Insert name of destroyed object") +#define MN_INSERT_BLOCK _("条件分岐ブロックの例を挿入", "Insert conditional block") +#define MN_INSERT_MACRO _("マクロ定義を挿入", "Insert a macro definition") +#define MN_INSERT_KEYMAP _("キーマップ定義を挿入", "Insert a keymap definition") + +#define MN_COMMAND_LETTER _("拾い/破壊/放置の選択", "Command letter") +#define MN_CL_AUTOPICK _("「 」 (自動拾い)", "' ' (Auto pick)") +#define MN_CL_DESTROY _("「!」 (自動破壊)", "'!' (Auto destroy)") +#define MN_CL_LEAVE _("「~」 (放置)", "'~' (Leave it on the floor)") +#define MN_CL_QUERY _("「;」 (確認して拾う)", "';' (Query to pick up)") +#define MN_CL_NO_DISP _("「(」 (マップコマンドで表示しない)", "'(' (No display on the large map)") + +#define MN_ADJECTIVE_GEN _("形容詞(一般)の選択", "Adjective (general)") +#define MN_RARE _("レアな (装備)", "rare (equipment)") +#define MN_COMMON _("ありふれた (装備)", "common (equipment)") + +#define MN_ADJECTIVE_SPECIAL _("形容詞(特殊)の選択", "Adjective (special)") +#define MN_BOOSTED _("ダイス目の違う (武器)", "dice boosted (weapons)") +#define MN_MORE_DICE _("ダイス目 # 以上の (武器)", "more than # dice (weapons)") +#define MN_MORE_BONUS _("修正値 # 以上の (指輪等)", "more bonus than # (rings etc.)") +#define MN_WANTED _("賞金首の (死体)", "wanted (corpse)") +#define MN_UNIQUE _("ユニーク・モンスターの (死体)", "unique (corpse)") +#define MN_HUMAN _("人間の (死体)", "human (corpse)") +#define MN_UNREADABLE _("読めない (魔法書)", "unreadable (spellbooks)") +#define MN_REALM1 _("第一領域の (魔法書)", "realm1 (spellbooks)") +#define MN_REALM2 _("第二領域の (魔法書)", "realm2 (spellbooks)") +#define MN_FIRST _("1冊目の (魔法書)", "first (spellbooks)") +#define MN_SECOND _("2冊目の (魔法書)", "second (spellbooks)") +#define MN_THIRD _("3冊目の (魔法書)", "third (spellbooks)") +#define MN_FOURTH _("4冊目の (魔法書)", "fourth (spellbooks)") + +#define MN_NOUN _("名詞の選択", "Keywords (noun)") diff --git a/src/autopick/autopick-editor-util.c b/src/autopick/autopick-editor-util.c new file mode 100644 index 000000000..5ae984ef8 --- /dev/null +++ b/src/autopick/autopick-editor-util.c @@ -0,0 +1,318 @@ +#include "autopick/autopick-editor-util.h" +#include "autopick/autopick-flags-table.h" +#include "autopick/autopick-methods-table.h" +#include "autopick/autopick-dirty-flags.h" +#include "autopick/autopick-entry.h" +#include "autopick/autopick-key-flag-process.h" + +/* + * Delete or insert string + */ +void toggle_keyword(text_body_type *tb, BIT_FLAGS flg) +{ + int by1, by2; + bool add = TRUE; + bool fixed = FALSE; + if (tb->mark) + { + by1 = MIN(tb->my, tb->cy); + by2 = MAX(tb->my, tb->cy); + } + else /* if (!tb->mark) */ + { + by1 = by2 = tb->cy; + } + + for (int y = by1; y <= by2; y++) + { + autopick_type an_entry, *entry = &an_entry; + if (!autopick_new_entry(entry, tb->lines_list[y], !fixed)) continue; + + string_free(tb->lines_list[y]); + if (!fixed) + { + if (!IS_FLG(flg)) add = TRUE; + else add = FALSE; + + fixed = TRUE; + } + + if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END) + { + int i; + for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++) + REM_FLG(i); + } + else if (FLG_UNAWARE <= flg && flg <= FLG_STAR_IDENTIFIED) + { + int i; + for (i = FLG_UNAWARE; i <= FLG_STAR_IDENTIFIED; i++) + REM_FLG(i); + } + else if (FLG_ARTIFACT <= flg && flg <= FLG_AVERAGE) + { + int i; + for (i = FLG_ARTIFACT; i <= FLG_AVERAGE; i++) + REM_FLG(i); + } + else if (FLG_RARE <= flg && flg <= FLG_COMMON) + { + int i; + for (i = FLG_RARE; i <= FLG_COMMON; i++) + REM_FLG(i); + } + + if (add) ADD_FLG(flg); + else REM_FLG(flg); + + tb->lines_list[y] = autopick_line_from_entry_kill(entry); + tb->dirty_flags |= DIRTY_ALL; + tb->changed = TRUE; + } +} + + +/* + * Change command letter + */ +void toggle_command_letter(text_body_type *tb, byte flg) +{ + autopick_type an_entry; + autopick_type *entry = &an_entry; + int by1, by2; + bool add = TRUE; + bool fixed = FALSE; + if (tb->mark) + { + by1 = MIN(tb->my, tb->cy); + by2 = MAX(tb->my, tb->cy); + } + else /* if (!tb->mark) */ + { + by1 = by2 = tb->cy; + } + + for (int y = by1; y <= by2; y++) + { + int wid = 0; + + if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue; + + string_free(tb->lines_list[y]); + + if (!fixed) + { + if (!(entry->action & flg)) add = TRUE; + else add = FALSE; + + fixed = TRUE; + } + + if (entry->action & DONT_AUTOPICK) wid--; + else if (entry->action & DO_AUTODESTROY) wid--; + else if (entry->action & DO_QUERY_AUTOPICK) wid--; + if (!(entry->action & DO_DISPLAY)) wid--; + + if (flg != DO_DISPLAY) + { + entry->action &= ~(DO_AUTOPICK | DONT_AUTOPICK | DO_AUTODESTROY | DO_QUERY_AUTOPICK); + if (add) entry->action |= flg; + else entry->action |= DO_AUTOPICK; + } + else + { + entry->action &= ~(DO_DISPLAY); + if (add) entry->action |= flg; + } + + if (tb->cy == y) + { + if (entry->action & DONT_AUTOPICK) wid++; + else if (entry->action & DO_AUTODESTROY) wid++; + else if (entry->action & DO_QUERY_AUTOPICK) wid++; + if (!(entry->action & DO_DISPLAY)) wid++; + + if (wid > 0) tb->cx++; + if (wid < 0 && tb->cx > 0) tb->cx--; + } + + tb->lines_list[y] = autopick_line_from_entry_kill(entry); + tb->dirty_flags |= DIRTY_ALL; + tb->changed = TRUE; + } +} + + +/* + * Delete or insert string + */ +void add_keyword(text_body_type *tb, BIT_FLAGS flg) +{ + int by1, by2; + if (tb->mark) + { + by1 = MIN(tb->my, tb->cy); + by2 = MAX(tb->my, tb->cy); + } + else + { + by1 = by2 = tb->cy; + } + + for (int y = by1; y <= by2; y++) + { + autopick_type an_entry, *entry = &an_entry; + if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue; + + if (IS_FLG(flg)) + { + autopick_free_entry(entry); + continue; + } + + string_free(tb->lines_list[y]); + if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END) + { + int i; + for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++) + REM_FLG(i); + } + + ADD_FLG(flg); + tb->lines_list[y] = autopick_line_from_entry_kill(entry); + tb->dirty_flags |= DIRTY_ALL; + tb->changed = TRUE; + } +} + + +/* + * Add an empty line at the last of the file + */ +bool add_empty_line(text_body_type *tb) +{ + int num_lines; + for (num_lines = 0; tb->lines_list[num_lines]; num_lines++); + + if (num_lines >= MAX_LINES - 2) return FALSE; + if (!tb->lines_list[num_lines - 1][0]) return FALSE; + + tb->lines_list[num_lines] = string_make(""); + tb->dirty_flags |= DIRTY_EXPRESSION; + tb->changed = TRUE; + return TRUE; +} + + +static chain_str_type *new_chain_str(concptr str) +{ + chain_str_type *chain; + size_t len = strlen(str); + chain = (chain_str_type *)ralloc(sizeof(chain_str_type) + len * sizeof(char)); + strcpy(chain->s, str); + chain->next = NULL; + return chain; +} + + +void kill_yank_chain(text_body_type *tb) +{ + chain_str_type *chain = tb->yank; + tb->yank = NULL; + tb->yank_eol = TRUE; + + while (chain) + { + chain_str_type *next = chain->next; + size_t len = strlen(chain->s); + + rnfree(chain, sizeof(chain_str_type) + len * sizeof(char)); + + chain = next; + } +} + + +void add_str_to_yank(text_body_type *tb, concptr str) +{ + tb->yank_eol = FALSE; + if (NULL == tb->yank) + { + tb->yank = new_chain_str(str); + return; + } + + chain_str_type *chain; + chain = tb->yank; + + while (TRUE) + { + if (!chain->next) + { + chain->next = new_chain_str(str); + return; + } + + /* Go to next */ + chain = chain->next; + } +} + + +/* + * Do work for the copy editor-command + */ +void copy_text_to_yank(text_body_type *tb) +{ + int len = strlen(tb->lines_list[tb->cy]); + if (tb->cx > len) tb->cx = len; + + if (!tb->mark) + { + tb->cx = 0; + tb->my = tb->cy; + tb->mx = len; + } + + kill_yank_chain(tb); + if (tb->my != tb->cy) + { + int by1 = MIN(tb->my, tb->cy); + int by2 = MAX(tb->my, tb->cy); + + for (int y = by1; y <= by2; y++) + { + add_str_to_yank(tb, tb->lines_list[y]); + } + + add_str_to_yank(tb, ""); + tb->mark = 0; + tb->dirty_flags |= DIRTY_ALL; + return; + } + + char buf[MAX_LINELEN]; + int bx1 = MIN(tb->mx, tb->cx); + int bx2 = MAX(tb->mx, tb->cx); + if (bx2 > len) bx2 = len; + + if (bx1 == 0 && bx2 == len) + { + add_str_to_yank(tb, tb->lines_list[tb->cy]); + add_str_to_yank(tb, ""); + } + else + { + int end = bx2 - bx1; + for (int i = 0; i < bx2 - bx1; i++) + { + buf[i] = tb->lines_list[tb->cy][bx1 + i]; + } + + buf[end] = '\0'; + add_str_to_yank(tb, buf); + } + + tb->mark = 0; + tb->dirty_flags |= DIRTY_ALL; +} diff --git a/src/autopick/autopick-editor-util.h b/src/autopick/autopick-editor-util.h new file mode 100644 index 000000000..bc30b61fd --- /dev/null +++ b/src/autopick/autopick-editor-util.h @@ -0,0 +1,12 @@ +#pragma once + +#include "autopick/autopick-util.h" +#include "system/angband.h" + +void toggle_keyword(text_body_type *tb, BIT_FLAGS flg); +void toggle_command_letter(text_body_type *tb, byte flg); +void add_keyword(text_body_type *tb, BIT_FLAGS flg); +bool add_empty_line(text_body_type *tb); +void kill_yank_chain(text_body_type *tb); +void add_str_to_yank(text_body_type *tb, concptr str); +void copy_text_to_yank(text_body_type *tb); diff --git a/src/autopick/autopick-entry.c b/src/autopick/autopick-entry.c new file mode 100644 index 000000000..b2b98c9b7 --- /dev/null +++ b/src/autopick/autopick-entry.c @@ -0,0 +1,652 @@ +#include "autopick/autopick-entry.h" +#include "autopick/autopick-flags-table.h" +#include "autopick/autopick-key-flag-process.h" +#include "autopick/autopick-keys-table.h" +#include "autopick/autopick-methods-table.h" +#include "core/show-file.h" +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "floor/floor-object.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "object-enchant/item-feeling.h" +#include "object-enchant/object-ego.h" +#include "object-enchant/special-object-flags.h" +#include "object-hook/hook-bow.h" +#include "object-hook/hook-enchant.h" +#include "object-hook/hook-quest.h" +#include "object-hook/hook-weapon.h" +#include "object/item-use-flags.h" +#include "object/object-info.h" +#include "object/object-kind.h" +#include "perception/object-perception.h" +#include "player/player-realm.h" +#include "util/quarks.h" +#include "util/string-processor.h" + +#ifdef JP +static char kanji_colon[] = ":"; +#endif + +/* + * A function to create new entry + */ +bool autopick_new_entry(autopick_type *entry, concptr str, bool allow_default) +{ + if (str[0] && str[1] == ':') + switch (str[0]) { + case '?': + case '%': + case 'A': + case 'P': + case 'C': + return FALSE; + } + + entry->flag[0] = entry->flag[1] = 0L; + entry->dice = 0; + entry->bonus = 0; + + byte act = DO_AUTOPICK | DO_DISPLAY; + while (TRUE) { + if ((act & DO_AUTOPICK) && *str == '!') { + act &= ~DO_AUTOPICK; + act |= DO_AUTODESTROY; + str++; + continue; + } + + if ((act & DO_AUTOPICK) && *str == '~') { + act &= ~DO_AUTOPICK; + act |= DONT_AUTOPICK; + str++; + continue; + } + + if ((act & DO_AUTOPICK) && *str == ';') { + act &= ~DO_AUTOPICK; + act |= DO_QUERY_AUTOPICK; + str++; + continue; + } + + if ((act & DO_DISPLAY) && *str == '(') { + act &= ~DO_DISPLAY; + str++; + continue; + } + + break; + } + + concptr insc = NULL; + char buf[MAX_LINELEN]; + int i; + for (i = 0; *str; i++) { + char c = *str++; +#ifdef JP + if (iskanji(c)) { + buf[i++] = c; + buf[i] = *str++; + continue; + } +#endif + if (c == '#') { + buf[i] = '\0'; + insc = str; + break; + } + + if (isupper(c)) + c = (char)tolower(c); + + buf[i] = c; + } + + buf[i] = '\0'; + if (!allow_default && *buf == 0) + return FALSE; + if (*buf == 0 && insc) + return FALSE; + + concptr prev_ptr, ptr; + ptr = prev_ptr = buf; + concptr old_ptr = NULL; + while (old_ptr != ptr) { + old_ptr = ptr; + if (MATCH_KEY(KEY_ALL)) + ADD_FLG(FLG_ALL); + if (MATCH_KEY(KEY_COLLECTING)) + ADD_FLG(FLG_COLLECTING); + if (MATCH_KEY(KEY_UNAWARE)) + ADD_FLG(FLG_UNAWARE); + if (MATCH_KEY(KEY_UNIDENTIFIED)) + ADD_FLG(FLG_UNIDENTIFIED); + if (MATCH_KEY(KEY_IDENTIFIED)) + ADD_FLG(FLG_IDENTIFIED); + if (MATCH_KEY(KEY_STAR_IDENTIFIED)) + ADD_FLG(FLG_STAR_IDENTIFIED); + if (MATCH_KEY(KEY_BOOSTED)) + ADD_FLG(FLG_BOOSTED); + + /*** Weapons whose dd*ds is more than nn ***/ + if (MATCH_KEY2(KEY_MORE_THAN)) { + int k = 0; + entry->dice = 0; + + while (' ' == *ptr) + ptr++; + + while ('0' <= *ptr && *ptr <= '9') { + entry->dice = 10 * entry->dice + (*ptr - '0'); + ptr++; + k++; + } + + if (k > 0 && k <= 2) { + (void)MATCH_KEY(KEY_DICE); + ADD_FLG(FLG_MORE_DICE); + } else + ptr = prev_ptr; + } + + /*** Items whose magical bonus is more than n ***/ + if (MATCH_KEY2(KEY_MORE_BONUS)) { + int k = 0; + entry->bonus = 0; + + while (' ' == *ptr) + ptr++; + + while ('0' <= *ptr && *ptr <= '9') { + entry->bonus = 10 * entry->bonus + (*ptr - '0'); + ptr++; + k++; + } + + if (k > 0 && k <= 2) { +#ifdef JP + (void)MATCH_KEY(KEY_MORE_BONUS2); +#else + if (' ' == *ptr) + ptr++; +#endif + ADD_FLG(FLG_MORE_BONUS); + } else + ptr = prev_ptr; + } + + if (MATCH_KEY(KEY_WORTHLESS)) + ADD_FLG(FLG_WORTHLESS); + if (MATCH_KEY(KEY_EGO)) + ADD_FLG(FLG_EGO); + if (MATCH_KEY(KEY_GOOD)) + ADD_FLG(FLG_GOOD); + if (MATCH_KEY(KEY_NAMELESS)) + ADD_FLG(FLG_NAMELESS); + if (MATCH_KEY(KEY_AVERAGE)) + ADD_FLG(FLG_AVERAGE); + if (MATCH_KEY(KEY_RARE)) + ADD_FLG(FLG_RARE); + if (MATCH_KEY(KEY_COMMON)) + ADD_FLG(FLG_COMMON); + if (MATCH_KEY(KEY_WANTED)) + ADD_FLG(FLG_WANTED); + if (MATCH_KEY(KEY_UNIQUE)) + ADD_FLG(FLG_UNIQUE); + if (MATCH_KEY(KEY_HUMAN)) + ADD_FLG(FLG_HUMAN); + if (MATCH_KEY(KEY_UNREADABLE)) + ADD_FLG(FLG_UNREADABLE); + if (MATCH_KEY(KEY_REALM1)) + ADD_FLG(FLG_REALM1); + if (MATCH_KEY(KEY_REALM2)) + ADD_FLG(FLG_REALM2); + if (MATCH_KEY(KEY_FIRST)) + ADD_FLG(FLG_FIRST); + if (MATCH_KEY(KEY_SECOND)) + ADD_FLG(FLG_SECOND); + if (MATCH_KEY(KEY_THIRD)) + ADD_FLG(FLG_THIRD); + if (MATCH_KEY(KEY_FOURTH)) + ADD_FLG(FLG_FOURTH); + } + + int prev_flg = -1; + if (MATCH_KEY2(KEY_ARTIFACT)) + ADD_FLG_NOUN(FLG_ARTIFACT); + + if (MATCH_KEY2(KEY_ITEMS)) + ADD_FLG_NOUN(FLG_ITEMS); + else if (MATCH_KEY2(KEY_WEAPONS)) + ADD_FLG_NOUN(FLG_WEAPONS); + else if (MATCH_KEY2(KEY_FAVORITE_WEAPONS)) + ADD_FLG_NOUN(FLG_FAVORITE_WEAPONS); + else if (MATCH_KEY2(KEY_ARMORS)) + ADD_FLG_NOUN(FLG_ARMORS); + else if (MATCH_KEY2(KEY_MISSILES)) + ADD_FLG_NOUN(FLG_MISSILES); + else if (MATCH_KEY2(KEY_DEVICES)) + ADD_FLG_NOUN(FLG_DEVICES); + else if (MATCH_KEY2(KEY_LIGHTS)) + ADD_FLG_NOUN(FLG_LIGHTS); + else if (MATCH_KEY2(KEY_JUNKS)) + ADD_FLG_NOUN(FLG_JUNKS); + else if (MATCH_KEY2(KEY_CORPSES)) + ADD_FLG_NOUN(FLG_CORPSES); + else if (MATCH_KEY2(KEY_SPELLBOOKS)) + ADD_FLG_NOUN(FLG_SPELLBOOKS); + else if (MATCH_KEY2(KEY_HAFTED)) + ADD_FLG_NOUN(FLG_HAFTED); + else if (MATCH_KEY2(KEY_SHIELDS)) + ADD_FLG_NOUN(FLG_SHIELDS); + else if (MATCH_KEY2(KEY_BOWS)) + ADD_FLG_NOUN(FLG_BOWS); + else if (MATCH_KEY2(KEY_RINGS)) + ADD_FLG_NOUN(FLG_RINGS); + else if (MATCH_KEY2(KEY_AMULETS)) + ADD_FLG_NOUN(FLG_AMULETS); + else if (MATCH_KEY2(KEY_SUITS)) + ADD_FLG_NOUN(FLG_SUITS); + else if (MATCH_KEY2(KEY_CLOAKS)) + ADD_FLG_NOUN(FLG_CLOAKS); + else if (MATCH_KEY2(KEY_HELMS)) + ADD_FLG_NOUN(FLG_HELMS); + else if (MATCH_KEY2(KEY_GLOVES)) + ADD_FLG_NOUN(FLG_GLOVES); + else if (MATCH_KEY2(KEY_BOOTS)) + ADD_FLG_NOUN(FLG_BOOTS); + + if (*ptr == ':') + ptr++; +#ifdef JP + else if (ptr[0] == kanji_colon[0] && ptr[1] == kanji_colon[1]) + ptr += 2; +#endif + else if (*ptr == '\0') { + if (prev_flg == -1) + ADD_FLG_NOUN(FLG_ITEMS); + } else { + if (prev_flg != -1) { + entry->flag[prev_flg / 32] &= ~(1L << (prev_flg % 32)); + ptr = prev_ptr; + } + } + + entry->name = string_make(ptr); + entry->action = act; + entry->insc = string_make(insc); + + return TRUE; +} + +/* + * Get auto-picker entry from o_ptr. + */ +void autopick_entry_from_object(player_type *player_ptr, autopick_type *entry, object_type *o_ptr) +{ + /* Assume that object name is to be added */ + bool name = TRUE; + GAME_TEXT name_str[MAX_NLEN]; + name_str[0] = '\0'; + entry->insc = string_make(quark_str(o_ptr->inscription)); + entry->action = DO_AUTOPICK | DO_DISPLAY; + entry->flag[0] = entry->flag[1] = 0L; + entry->dice = 0; + + // エゴ銘が邪魔かもしれないので、デフォルトで「^」は付けない. + // We can always use the ^ mark in English. + bool is_hat_added = _(FALSE, TRUE); + if (!object_is_aware(o_ptr)) { + ADD_FLG(FLG_UNAWARE); + is_hat_added = TRUE; + } else if (!object_is_known(o_ptr)) { + if (!(o_ptr->ident & IDENT_SENSE)) { + ADD_FLG(FLG_UNIDENTIFIED); + is_hat_added = TRUE; + } else { + switch (o_ptr->feeling) { + case FEEL_AVERAGE: + case FEEL_GOOD: + ADD_FLG(FLG_NAMELESS); + is_hat_added = TRUE; + break; + + case FEEL_BROKEN: + case FEEL_CURSED: + ADD_FLG(FLG_NAMELESS); + ADD_FLG(FLG_WORTHLESS); + is_hat_added = TRUE; + break; + + case FEEL_TERRIBLE: + case FEEL_WORTHLESS: + ADD_FLG(FLG_WORTHLESS); + break; + + case FEEL_EXCELLENT: + ADD_FLG(FLG_EGO); + break; + + case FEEL_UNCURSED: + break; + + default: + break; + } + } + } else { + if (object_is_ego(o_ptr)) { + if (object_is_weapon_armour_ammo(player_ptr, o_ptr)) { + /* + * Base name of ego weapons and armors + * are almost meaningless. + * Register the ego type only. + */ + ego_item_type *e_ptr = &e_info[o_ptr->name2]; +#ifdef JP + /* エゴ銘には「^」マークが使える */ + sprintf(name_str, "^%s", e_name + e_ptr->name); +#else + /* We ommit the basename and cannot use the ^ mark */ + strcpy(name_str, e_name + e_ptr->name); +#endif + name = FALSE; + if (!object_is_rare(o_ptr)) + ADD_FLG(FLG_COMMON); + } + + ADD_FLG(FLG_EGO); + } else if (object_is_artifact(o_ptr)) + ADD_FLG(FLG_ARTIFACT); + else { + if (object_is_equipment(o_ptr)) + ADD_FLG(FLG_NAMELESS); + + is_hat_added = TRUE; + } + } + + if (object_is_melee_weapon(o_ptr)) { + object_kind *k_ptr = &k_info[o_ptr->k_idx]; + + if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds)) + ADD_FLG(FLG_BOOSTED); + } + + if (object_is_bounty(player_ptr, o_ptr)) { + REM_FLG(FLG_WORTHLESS); + ADD_FLG(FLG_WANTED); + } + + if ((o_ptr->tval == TV_CORPSE || o_ptr->tval == TV_STATUE) && (r_info[o_ptr->pval].flags1 & RF1_UNIQUE)) { + ADD_FLG(FLG_UNIQUE); + } + + if (o_ptr->tval == TV_CORPSE && angband_strchr("pht", r_info[o_ptr->pval].d_char)) { + ADD_FLG(FLG_HUMAN); + } + + if (o_ptr->tval >= TV_LIFE_BOOK && !check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval)) { + ADD_FLG(FLG_UNREADABLE); + if (o_ptr->tval != TV_ARCANE_BOOK) + name = FALSE; + } + + if (get_realm1_book(player_ptr) == o_ptr->tval && player_ptr->pclass != CLASS_SORCERER && player_ptr->pclass != CLASS_RED_MAGE) { + ADD_FLG(FLG_REALM1); + name = FALSE; + } + + if (get_realm2_book(player_ptr) == o_ptr->tval && player_ptr->pclass != CLASS_SORCERER && player_ptr->pclass != CLASS_RED_MAGE) { + ADD_FLG(FLG_REALM2); + name = FALSE; + } + + if (o_ptr->tval >= TV_LIFE_BOOK && 0 == o_ptr->sval) + ADD_FLG(FLG_FIRST); + if (o_ptr->tval >= TV_LIFE_BOOK && 1 == o_ptr->sval) + ADD_FLG(FLG_SECOND); + if (o_ptr->tval >= TV_LIFE_BOOK && 2 == o_ptr->sval) + ADD_FLG(FLG_THIRD); + if (o_ptr->tval >= TV_LIFE_BOOK && 3 == o_ptr->sval) + ADD_FLG(FLG_FOURTH); + + if (object_is_ammo(o_ptr)) + ADD_FLG(FLG_MISSILES); + else if (o_ptr->tval == TV_SCROLL || o_ptr->tval == TV_STAFF || o_ptr->tval == TV_WAND || o_ptr->tval == TV_ROD) + ADD_FLG(FLG_DEVICES); + else if (o_ptr->tval == TV_LITE) + ADD_FLG(FLG_LIGHTS); + else if (o_ptr->tval == TV_SKELETON || o_ptr->tval == TV_BOTTLE || o_ptr->tval == TV_JUNK || o_ptr->tval == TV_STATUE) + ADD_FLG(FLG_JUNKS); + else if (o_ptr->tval == TV_CORPSE) + ADD_FLG(FLG_CORPSES); + else if (o_ptr->tval >= TV_LIFE_BOOK) + ADD_FLG(FLG_SPELLBOOKS); + else if (o_ptr->tval == TV_POLEARM || o_ptr->tval == TV_SWORD || o_ptr->tval == TV_DIGGING || o_ptr->tval == TV_HAFTED) + ADD_FLG(FLG_WEAPONS); + else if (o_ptr->tval == TV_SHIELD) + ADD_FLG(FLG_SHIELDS); + else if (o_ptr->tval == TV_BOW) + ADD_FLG(FLG_BOWS); + else if (o_ptr->tval == TV_RING) + ADD_FLG(FLG_RINGS); + else if (o_ptr->tval == TV_AMULET) + ADD_FLG(FLG_AMULETS); + else if (o_ptr->tval == TV_DRAG_ARMOR || o_ptr->tval == TV_HARD_ARMOR || o_ptr->tval == TV_SOFT_ARMOR) + ADD_FLG(FLG_SUITS); + else if (o_ptr->tval == TV_CLOAK) + ADD_FLG(FLG_CLOAKS); + else if (o_ptr->tval == TV_HELM) + ADD_FLG(FLG_HELMS); + else if (o_ptr->tval == TV_GLOVES) + ADD_FLG(FLG_GLOVES); + else if (o_ptr->tval == TV_BOOTS) + ADD_FLG(FLG_BOOTS); + + if (!name) { + str_tolower(name_str); + entry->name = string_make(name_str); + return; + } + + GAME_TEXT o_name[MAX_NLEN]; + describe_flavor(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL | OD_NAME_ONLY)); + + /* + * If necessary, add a '^' which indicates the + * beginning of line. + */ + sprintf(name_str, "%s%s", is_hat_added ? "^" : "", o_name); + str_tolower(name_str); + entry->name = string_make(name_str); +} + +/* + * Reconstruct preference line from entry + */ +concptr autopick_line_from_entry(autopick_type *entry) +{ + char buf[MAX_LINELEN]; + *buf = '\0'; + if (!(entry->action & DO_DISPLAY)) + strcat(buf, "("); + if (entry->action & DO_QUERY_AUTOPICK) + strcat(buf, ";"); + if (entry->action & DO_AUTODESTROY) + strcat(buf, "!"); + if (entry->action & DONT_AUTOPICK) + strcat(buf, "~"); + + char *ptr; + ptr = buf; + if (IS_FLG(FLG_ALL)) + ADD_KEY(KEY_ALL); + if (IS_FLG(FLG_COLLECTING)) + ADD_KEY(KEY_COLLECTING); + if (IS_FLG(FLG_UNAWARE)) + ADD_KEY(KEY_UNAWARE); + if (IS_FLG(FLG_UNIDENTIFIED)) + ADD_KEY(KEY_UNIDENTIFIED); + if (IS_FLG(FLG_IDENTIFIED)) + ADD_KEY(KEY_IDENTIFIED); + if (IS_FLG(FLG_STAR_IDENTIFIED)) + ADD_KEY(KEY_STAR_IDENTIFIED); + if (IS_FLG(FLG_BOOSTED)) + ADD_KEY(KEY_BOOSTED); + + if (IS_FLG(FLG_MORE_DICE)) { + ADD_KEY(KEY_MORE_THAN); + strcat(ptr, format("%d", entry->dice)); + ADD_KEY(KEY_DICE); + } + + if (IS_FLG(FLG_MORE_BONUS)) { + ADD_KEY(KEY_MORE_BONUS); + strcat(ptr, format("%d", entry->bonus)); + ADD_KEY(KEY_MORE_BONUS2); + } + + if (IS_FLG(FLG_UNREADABLE)) + ADD_KEY(KEY_UNREADABLE); + if (IS_FLG(FLG_REALM1)) + ADD_KEY(KEY_REALM1); + if (IS_FLG(FLG_REALM2)) + ADD_KEY(KEY_REALM2); + if (IS_FLG(FLG_FIRST)) + ADD_KEY(KEY_FIRST); + if (IS_FLG(FLG_SECOND)) + ADD_KEY(KEY_SECOND); + if (IS_FLG(FLG_THIRD)) + ADD_KEY(KEY_THIRD); + if (IS_FLG(FLG_FOURTH)) + ADD_KEY(KEY_FOURTH); + if (IS_FLG(FLG_WANTED)) + ADD_KEY(KEY_WANTED); + if (IS_FLG(FLG_UNIQUE)) + ADD_KEY(KEY_UNIQUE); + if (IS_FLG(FLG_HUMAN)) + ADD_KEY(KEY_HUMAN); + if (IS_FLG(FLG_WORTHLESS)) + ADD_KEY(KEY_WORTHLESS); + if (IS_FLG(FLG_GOOD)) + ADD_KEY(KEY_GOOD); + if (IS_FLG(FLG_NAMELESS)) + ADD_KEY(KEY_NAMELESS); + if (IS_FLG(FLG_AVERAGE)) + ADD_KEY(KEY_AVERAGE); + if (IS_FLG(FLG_RARE)) + ADD_KEY(KEY_RARE); + if (IS_FLG(FLG_COMMON)) + ADD_KEY(KEY_COMMON); + if (IS_FLG(FLG_EGO)) + ADD_KEY(KEY_EGO); + + if (IS_FLG(FLG_ARTIFACT)) + ADD_KEY(KEY_ARTIFACT); + + bool sepa_flag = TRUE; + if (IS_FLG(FLG_ITEMS)) + ADD_KEY2(KEY_ITEMS); + else if (IS_FLG(FLG_WEAPONS)) + ADD_KEY2(KEY_WEAPONS); + else if (IS_FLG(FLG_FAVORITE_WEAPONS)) + ADD_KEY2(KEY_FAVORITE_WEAPONS); + else if (IS_FLG(FLG_ARMORS)) + ADD_KEY2(KEY_ARMORS); + else if (IS_FLG(FLG_MISSILES)) + ADD_KEY2(KEY_MISSILES); + else if (IS_FLG(FLG_DEVICES)) + ADD_KEY2(KEY_DEVICES); + else if (IS_FLG(FLG_LIGHTS)) + ADD_KEY2(KEY_LIGHTS); + else if (IS_FLG(FLG_JUNKS)) + ADD_KEY2(KEY_JUNKS); + else if (IS_FLG(FLG_CORPSES)) + ADD_KEY2(KEY_CORPSES); + else if (IS_FLG(FLG_SPELLBOOKS)) + ADD_KEY2(KEY_SPELLBOOKS); + else if (IS_FLG(FLG_HAFTED)) + ADD_KEY2(KEY_HAFTED); + else if (IS_FLG(FLG_SHIELDS)) + ADD_KEY2(KEY_SHIELDS); + else if (IS_FLG(FLG_BOWS)) + ADD_KEY2(KEY_BOWS); + else if (IS_FLG(FLG_RINGS)) + ADD_KEY2(KEY_RINGS); + else if (IS_FLG(FLG_AMULETS)) + ADD_KEY2(KEY_AMULETS); + else if (IS_FLG(FLG_SUITS)) + ADD_KEY2(KEY_SUITS); + else if (IS_FLG(FLG_CLOAKS)) + ADD_KEY2(KEY_CLOAKS); + else if (IS_FLG(FLG_HELMS)) + ADD_KEY2(KEY_HELMS); + else if (IS_FLG(FLG_GLOVES)) + ADD_KEY2(KEY_GLOVES); + else if (IS_FLG(FLG_BOOTS)) + ADD_KEY2(KEY_BOOTS); + else if (!IS_FLG(FLG_ARTIFACT)) + sepa_flag = FALSE; + + if (entry->name && entry->name[0]) { + if (sepa_flag) + strcat(buf, ":"); + + int i = strlen(buf); + int j = 0; + while (entry->name[j] && i < MAX_LINELEN - 2 - 1) { +#ifdef JP + if (iskanji(entry->name[j])) + buf[i++] = entry->name[j++]; +#endif + buf[i++] = entry->name[j++]; + } + buf[i] = '\0'; + } + + if (!entry->insc) + return string_make(buf); + + int i, j = 0; + strcat(buf, "#"); + i = strlen(buf); + + while (entry->insc[j] && i < MAX_LINELEN - 2) { +#ifdef JP + if (iskanji(entry->insc[j])) + buf[i++] = entry->insc[j++]; +#endif + buf[i++] = entry->insc[j++]; + } + + buf[i] = '\0'; + return string_make(buf); +} + +/* + * Reconstruct preference line from entry and kill entry + */ +concptr autopick_line_from_entry_kill(autopick_type *entry) +{ + concptr ptr = autopick_line_from_entry(entry); + autopick_free_entry(entry); + return ptr; +} + +/* + * Choose an item and get auto-picker entry from it. + */ +bool entry_from_choosed_object(player_type *player_ptr, autopick_type *entry) +{ + concptr q = _("どのアイテムを登録しますか? ", "Enter which item? "); + concptr s = _("アイテムを持っていない。", "You have nothing to enter."); + object_type *o_ptr; + o_ptr = choose_object(player_ptr, NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP, 0); + if (!o_ptr) + return FALSE; + + autopick_entry_from_object(player_ptr, entry, o_ptr); + return TRUE; +} diff --git a/src/autopick/autopick-entry.h b/src/autopick/autopick-entry.h new file mode 100644 index 000000000..4b0bf904b --- /dev/null +++ b/src/autopick/autopick-entry.h @@ -0,0 +1,10 @@ +#pragma once + +#include "system/angband.h" +#include "autopick/autopick-util.h" + +bool autopick_new_entry(autopick_type *entry, concptr str, bool allow_default); +void autopick_entry_from_object(player_type *player_ptr, autopick_type *entry, object_type *o_ptr); +concptr autopick_line_from_entry(autopick_type *entry); +concptr autopick_line_from_entry_kill(autopick_type *entry); +bool entry_from_choosed_object(player_type *player_ptr, autopick_type *entry); diff --git a/src/autopick/autopick-finder.c b/src/autopick/autopick-finder.c new file mode 100644 index 000000000..49a222868 --- /dev/null +++ b/src/autopick/autopick-finder.c @@ -0,0 +1,391 @@ +/*! + * todo get_string_for_search() ‚Í’·‚¢A—v•ªŠ„ + * @brief Ž©“®E‚¢‚ÌŒŸõ + * @date 2020/04/26 + * @author Hourier + */ + +#include "autopick/autopick-finder.h" +#include "autopick/autopick-dirty-flags.h" +#include "autopick/autopick-entry.h" +#include "autopick/autopick-matcher.h" +#include "core/show-file.h" +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "floor/floor-object.h" +#include "io/input-key-acceptor.h" +#include "main/sound-of-music.h" +#include "object/item-use-flags.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/int-char-converter.h" +#include "util/string-processor.h" + +/* + * @brief —^‚¦‚ç‚ꂽƒAƒCƒeƒ€‚ªŽ©“®E‚¢‚̃ŠƒXƒg‚É“o˜^‚³‚ê‚Ä‚¢‚é‚©‚Ç‚¤‚©‚ðŒŸõ‚·‚é + * @param player_ptr ƒvƒŒ[ƒ„[‚Ö‚ÌŽQÆƒ|ƒCƒ“ƒ^ + * @o_ptr ƒAƒCƒeƒ€‚Ö‚ÌŽQÆƒ|ƒCƒ“ƒ^ + * @return Ž©“®E‚¢‚̃ŠƒXƒg‚É“o˜^‚³‚ê‚Ä‚¢‚½‚ç‚»‚Ì“o˜^”ԍ†A‚È‚©‚Á‚½‚ç-1 + * @details + * A function for Auto-picker/destroyer + * Examine whether the object matches to the list of keywords or not. + */ +int find_autopick_list(player_type *player_ptr, object_type *o_ptr) +{ + GAME_TEXT o_name[MAX_NLEN]; + if (o_ptr->tval == TV_GOLD) + return -1; + + describe_flavor(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL)); + str_tolower(o_name); + for (int i = 0; i < max_autopick; i++) { + autopick_type *entry = &autopick_list[i]; + if (is_autopick_match(player_ptr, o_ptr, entry, o_name)) + return i; + } + + return -1; +} + +/* + * Choose an item for search + */ +bool get_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp) +{ + concptr q = _("‚ǂ̃AƒCƒeƒ€‚ðŒŸõ‚µ‚Ü‚·‚©? ", "Enter which item? "); + concptr s = _("ƒAƒCƒeƒ€‚ðŽ‚Á‚Ä‚¢‚È‚¢B", "You have nothing to enter."); + object_type *o_ptr; + o_ptr = choose_object(player_ptr, NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP, 0); + if (!o_ptr) + return FALSE; + + *o_handle = o_ptr; + string_free(*search_strp); + char buf[MAX_NLEN + 20]; + describe_flavor(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL)); + *search_strp = string_make(format("<%s>", buf)); + return TRUE; +} + +/* + * Prepare for search by destroyed object + */ +bool get_destroyed_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp) +{ + if (!autopick_last_destroyed_object.k_idx) + return FALSE; + + *o_handle = &autopick_last_destroyed_object; + string_free(*search_strp); + char buf[MAX_NLEN + 20]; + describe_flavor(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL)); + *search_strp = string_make(format("<%s>", buf)); + return TRUE; +} + +/* + * Choose an item or string for search + */ +byte get_string_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp) +{ + /* + * Text color + * TERM_YELLOW : Overwrite mode + * TERM_WHITE : Insert mode + */ + byte color = TERM_YELLOW; + char buf[MAX_NLEN + 20]; + const int len = 80; + char prompt[] = _("ŒŸõ(^I:Ž‚¿•¨ ^L:”j‰ó‚³‚ꂽ•¨): ", "Search key(^I:inven ^L:destroyed): "); + int col = sizeof(prompt) - 1; + if (*search_strp) + strcpy(buf, *search_strp); + else + buf[0] = '\0'; + + if (*o_handle) + color = TERM_L_GREEN; + + prt(prompt, 0, 0); + int pos = 0; + while (TRUE) { + bool back = FALSE; + term_erase(col, 0, 255); + term_putstr(col, 0, -1, color, buf); + term_gotoxy(col + pos, 0); + + int skey = inkey_special(TRUE); + switch (skey) { + case SKEY_LEFT: + case KTRL('b'): { + int i = 0; + color = TERM_WHITE; + if (pos == 0) + break; + + while (TRUE) { + int next_pos = i + 1; + +#ifdef JP + if (iskanji(buf[i])) + next_pos++; +#endif + if (next_pos >= pos) + break; + + i = next_pos; + } + + pos = i; + break; + } + + case SKEY_RIGHT: + case KTRL('f'): + color = TERM_WHITE; + if ('\0' == buf[pos]) + break; + +#ifdef JP + if (iskanji(buf[pos])) + pos += 2; + else + pos++; +#else + pos++; +#endif + break; + + case ESCAPE: + return 0; + + case KTRL('r'): + back = TRUE; + /* Fall through */ + + case '\n': + case '\r': + case KTRL('s'): + if (*o_handle) + return (back ? -1 : 1); + string_free(*search_strp); + *search_strp = string_make(buf); + *o_handle = NULL; + return (back ? -1 : 1); + + case KTRL('i'): + return get_object_for_search(player_ptr, o_handle, search_strp); + + case KTRL('l'): + if (get_destroyed_object_for_search(player_ptr, o_handle, search_strp)) + return 1; + break; + + case '\010': { + int i = 0; + color = TERM_WHITE; + if (pos == 0) + break; + + while (TRUE) { + int next_pos = i + 1; +#ifdef JP + if (iskanji(buf[i])) + next_pos++; +#endif + if (next_pos >= pos) + break; + + i = next_pos; + } + + pos = i; + } + /* Fall through */ + + case 0x7F: + case KTRL('d'): { + int dst, src; + color = TERM_WHITE; + if (buf[pos] == '\0') + break; + + src = pos + 1; +#ifdef JP + if (iskanji(buf[pos])) + src++; +#endif + dst = pos; + while ('\0' != (buf[dst++] = buf[src++])) + ; + + break; + } + + default: { + char tmp[100]; + char c; + if (skey & SKEY_MASK) + break; + + c = (char)skey; + if (color != TERM_WHITE) { + if (color == TERM_L_GREEN) { + *o_handle = NULL; + string_free(*search_strp); + *search_strp = NULL; + } + + buf[0] = '\0'; + color = TERM_WHITE; + } + + strcpy(tmp, buf + pos); +#ifdef JP + if (iskanji(c)) { + char next; + inkey_base = TRUE; + next = inkey(); + + if (pos + 1 < len) { + buf[pos++] = c; + buf[pos++] = next; + } else { + bell(); + } + } else +#endif +#ifdef JP + if (pos < len && (isprint(c) || iskana(c))) +#else + if (pos < len && isprint(c)) +#endif + { + buf[pos++] = c; + } else { + bell(); + } + + buf[pos] = '\0'; + angband_strcat(buf, tmp, len + 1); + + break; + } + } + + if (*o_handle == NULL || color == TERM_L_GREEN) + continue; + + *o_handle = NULL; + buf[0] = '\0'; + string_free(*search_strp); + *search_strp = NULL; + } +} + +/* + * Search next line matches for o_ptr + */ +void search_for_object(player_type *player_ptr, text_body_type *tb, object_type *o_ptr, bool forward) +{ + autopick_type an_entry, *entry = &an_entry; + GAME_TEXT o_name[MAX_NLEN]; + int bypassed_cy = -1; + int i = tb->cy; + describe_flavor(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL)); + str_tolower(o_name); + + while (TRUE) { + bool match; + if (forward) { + if (!tb->lines_list[++i]) + break; + } else { + if (--i < 0) + break; + } + + if (!autopick_new_entry(entry, tb->lines_list[i], FALSE)) + continue; + + match = is_autopick_match(player_ptr, o_ptr, entry, o_name); + autopick_free_entry(entry); + if (!match) + continue; + + if (tb->states[i] & LSTAT_BYPASS) { + if (bypassed_cy == -1) + bypassed_cy = i; + continue; + } + + tb->cx = 0; + tb->cy = i; + if (bypassed_cy != -1) { + tb->dirty_flags |= DIRTY_SKIP_INACTIVE; + } + + return; + } + + if (bypassed_cy == -1) { + tb->dirty_flags |= DIRTY_NOT_FOUND; + return; + } + + tb->cx = 0; + tb->cy = bypassed_cy; + tb->dirty_flags |= DIRTY_INACTIVE; +} + +/* + * Search next line matches to the string + */ +void search_for_string(text_body_type *tb, concptr search_str, bool forward) +{ + int bypassed_cy = -1; + int bypassed_cx = 0; + + int i = tb->cy; + while (TRUE) { + concptr pos; + if (forward) { + if (!tb->lines_list[++i]) + break; + } else { + if (--i < 0) + break; + } + + pos = angband_strstr(tb->lines_list[i], search_str); + if (!pos) + continue; + + if ((tb->states[i] & LSTAT_BYPASS) && !(tb->states[i] & LSTAT_EXPRESSION)) { + if (bypassed_cy == -1) { + bypassed_cy = i; + bypassed_cx = (int)(pos - tb->lines_list[i]); + } + + continue; + } + + tb->cx = (int)(pos - tb->lines_list[i]); + tb->cy = i; + + if (bypassed_cy != -1) { + tb->dirty_flags |= DIRTY_SKIP_INACTIVE; + } + + return; + } + + if (bypassed_cy == -1) { + tb->dirty_flags |= DIRTY_NOT_FOUND; + return; + } + + tb->cx = bypassed_cx; + tb->cy = bypassed_cy; + tb->dirty_flags |= DIRTY_INACTIVE; +} diff --git a/src/autopick/autopick-finder.h b/src/autopick/autopick-finder.h new file mode 100644 index 000000000..8306e98c9 --- /dev/null +++ b/src/autopick/autopick-finder.h @@ -0,0 +1,12 @@ +#pragma once + +#include "system/angband.h" +#include "autopick/autopick-util.h" +#include "system/object-type-definition.h" + +int find_autopick_list(player_type *player_ptr, object_type *o_ptr); +bool get_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp); +bool get_destroyed_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp); +byte get_string_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp); +void search_for_object(player_type *player_ptr, text_body_type *tb, object_type *o_ptr, bool forward); +void search_for_string(text_body_type *tb, concptr search_str, bool forward); diff --git a/src/autopick/autopick-flags-table.h b/src/autopick/autopick-flags-table.h new file mode 100644 index 000000000..1e710af33 --- /dev/null +++ b/src/autopick/autopick-flags-table.h @@ -0,0 +1,56 @@ +#pragma once + +/* + * Macros for Keywords + */ +#define FLG_ALL 0 +#define FLG_UNAWARE 1 +#define FLG_UNIDENTIFIED 2 +#define FLG_IDENTIFIED 3 +#define FLG_STAR_IDENTIFIED 4 +#define FLG_COLLECTING 5 +#define FLG_ARTIFACT 6 +#define FLG_EGO 7 +#define FLG_GOOD 10 +#define FLG_NAMELESS 11 +#define FLG_AVERAGE 12 +#define FLG_WORTHLESS 13 +#define FLG_RARE 14 +#define FLG_COMMON 15 +#define FLG_BOOSTED 16 +#define FLG_MORE_DICE 17 +#define FLG_MORE_BONUS 18 +#define FLG_WANTED 19 +#define FLG_UNIQUE 20 +#define FLG_HUMAN 21 +#define FLG_UNREADABLE 22 +#define FLG_REALM1 23 +#define FLG_REALM2 24 +#define FLG_FIRST 25 +#define FLG_SECOND 26 +#define FLG_THIRD 27 +#define FLG_FOURTH 28 + +#define FLG_ITEMS 30 +#define FLG_WEAPONS 31 +#define FLG_FAVORITE_WEAPONS 32 +#define FLG_ARMORS 33 +#define FLG_MISSILES 34 +#define FLG_DEVICES 35 +#define FLG_LIGHTS 36 +#define FLG_JUNKS 37 +#define FLG_CORPSES 38 +#define FLG_SPELLBOOKS 39 +#define FLG_HAFTED 40 +#define FLG_SHIELDS 41 +#define FLG_BOWS 42 +#define FLG_RINGS 43 +#define FLG_AMULETS 44 +#define FLG_SUITS 45 +#define FLG_CLOAKS 46 +#define FLG_HELMS 47 +#define FLG_GLOVES 48 +#define FLG_BOOTS 49 + +#define FLG_NOUN_BEGIN FLG_ITEMS +#define FLG_NOUN_END FLG_BOOTS diff --git a/src/autopick/autopick-initializer.c b/src/autopick/autopick-initializer.c new file mode 100644 index 000000000..8be480b70 --- /dev/null +++ b/src/autopick/autopick-initializer.c @@ -0,0 +1,28 @@ +#include "autopick/autopick-initializer.h" +#include "autopick/autopick-entry.h" +#include "autopick/autopick-util.h" +#include "system/angband.h" + +/* + * Initialize the autopick + */ +void init_autopick(void) +{ + static const char easy_autopick_inscription[] = "(:=g"; + autopick_type entry; + int i; + + if (!autopick_list) + { + max_max_autopick = MAX_AUTOPICK_DEFAULT; + C_MAKE(autopick_list, max_max_autopick, autopick_type); + max_autopick = 0; + } + + for (i = 0; i < max_autopick; i++) + autopick_free_entry(&autopick_list[i]); + + max_autopick = 0; + autopick_new_entry(&entry, easy_autopick_inscription, TRUE); + autopick_list[max_autopick++] = entry; +} diff --git a/src/autopick/autopick-initializer.h b/src/autopick/autopick-initializer.h new file mode 100644 index 000000000..572f79995 --- /dev/null +++ b/src/autopick/autopick-initializer.h @@ -0,0 +1,3 @@ +#pragma once + +void init_autopick(void); diff --git a/src/autopick/autopick-inserter-killer.c b/src/autopick/autopick-inserter-killer.c new file mode 100644 index 000000000..7ce348fc0 --- /dev/null +++ b/src/autopick/autopick-inserter-killer.c @@ -0,0 +1,244 @@ +#include "autopick/autopick-inserter-killer.h" +#include "autopick/autopick-dirty-flags.h" +#include "cmd-io/macro-util.h" +#include "game-option/input-options.h" +#include "game-option/keymap-directory-getter.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "main/sound-of-music.h" +#include "term/screen-processor.h" +#include "util/string-processor.h" + +/* + * Check if this line is expression or not. + * And update it if it is. + */ +void check_expression_line(text_body_type *tb, int y) +{ + concptr s = tb->lines_list[y]; + + if ((s[0] == '?' && s[1] == ':') || + (tb->states[y] & LSTAT_BYPASS)) + { + tb->dirty_flags |= DIRTY_EXPRESSION; + } +} + +/* + * Insert return code and split the line + */ +bool insert_return_code(text_body_type *tb) +{ + char buf[MAX_LINELEN]; + int i, j, num_lines; + + for (num_lines = 0; tb->lines_list[num_lines]; num_lines++); + + if (num_lines >= MAX_LINES - 2) return FALSE; + num_lines--; + + for (; tb->cy < num_lines; num_lines--) + { + tb->lines_list[num_lines + 1] = tb->lines_list[num_lines]; + tb->states[num_lines + 1] = tb->states[num_lines]; + } + + for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++) + { +#ifdef JP + if (iskanji(tb->lines_list[tb->cy][i])) + buf[j++] = tb->lines_list[tb->cy][i++]; +#endif + buf[j++] = tb->lines_list[tb->cy][i]; + } + + buf[j] = '\0'; + tb->lines_list[tb->cy + 1] = string_make(&tb->lines_list[tb->cy][i]); + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make(buf); + tb->dirty_flags |= DIRTY_EXPRESSION; + tb->changed = TRUE; + return TRUE; +} + + +/* + * Get a trigger key and insert ASCII string for the trigger + */ +bool insert_macro_line(text_body_type *tb) +{ + int i, n = 0; + flush(); + inkey_base = TRUE; + i = inkey(); + char buf[1024]; + while (i) + { + buf[n++] = (char)i; + inkey_base = TRUE; + inkey_scan = TRUE; + i = inkey(); + } + + buf[n] = '\0'; + flush(); + + char tmp[1024]; + ascii_to_text(tmp, buf); + if (!tmp[0]) return FALSE; + + tb->cx = 0; + insert_return_code(tb); + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make(format("P:%s", tmp)); + + i = macro_find_exact(buf); + if (i == -1) + { + tmp[0] = '\0'; + } + else + { + ascii_to_text(tmp, macro__act[i]); + } + + insert_return_code(tb); + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make(format("A:%s", tmp)); + + return TRUE; +} + + +/* + * Get a command key and insert ASCII string for the key + */ +bool insert_keymap_line(text_body_type *tb) +{ + BIT_FLAGS mode; + if (rogue_like_commands) + { + mode = KEYMAP_MODE_ROGUE; + } + else + { + mode = KEYMAP_MODE_ORIG; + } + + flush(); + char buf[2]; + buf[0] = inkey(); + buf[1] = '\0'; + + flush(); + char tmp[1024]; + ascii_to_text(tmp, buf); + if (!tmp[0]) return FALSE; + + tb->cx = 0; + insert_return_code(tb); + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make(format("C:%d:%s", mode, tmp)); + + concptr act = keymap_act[mode][(byte)(buf[0])]; + if (act) + { + ascii_to_text(tmp, act); + } + + insert_return_code(tb); + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make(format("A:%s", tmp)); + + return TRUE; +} + + +/* + * Insert single letter at cursor position. + */ +void insert_single_letter(text_body_type *tb, int key) +{ + int i, j, len; + char buf[MAX_LINELEN]; + + for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++) + { + buf[j++] = tb->lines_list[tb->cy][i]; + } + +#ifdef JP + if (iskanji(key)) + { + int next; + + inkey_base = TRUE; + next = inkey(); + if (j + 2 < MAX_LINELEN) + { + buf[j++] = (char)key; + buf[j++] = (char)next; + tb->cx += 2; + } + else + bell(); + } + else +#endif + { + if (j + 1 < MAX_LINELEN) + buf[j++] = (char)key; + tb->cx++; + } + + for (; tb->lines_list[tb->cy][i] && j + 1 < MAX_LINELEN; i++) + buf[j++] = tb->lines_list[tb->cy][i]; + buf[j] = '\0'; + + string_free(tb->lines_list[tb->cy]); + tb->lines_list[tb->cy] = string_make(buf); + len = strlen(tb->lines_list[tb->cy]); + if (len < tb->cx) tb->cx = len; + + tb->dirty_line = tb->cy; + check_expression_line(tb, tb->cy); + tb->changed = TRUE; +} + + +/* + * Kill segment of a line + */ +void kill_line_segment(text_body_type *tb, int y, int x0, int x1, bool whole) +{ + concptr s = tb->lines_list[y]; + if (whole && x0 == 0 && s[x1] == '\0' && tb->lines_list[y + 1]) + { + string_free(tb->lines_list[y]); + + int i; + for (i = y; tb->lines_list[i + 1]; i++) + tb->lines_list[i] = tb->lines_list[i + 1]; + tb->lines_list[i] = NULL; + + tb->dirty_flags |= DIRTY_EXPRESSION; + + return; + } + + if (x0 == x1) return; + + char buf[MAX_LINELEN]; + char *d = buf; + for (int x = 0; x < x0; x++) + *(d++) = s[x]; + + for (int x = x1; s[x]; x++) + *(d++) = s[x]; + + *d = '\0'; + string_free(tb->lines_list[y]); + tb->lines_list[y] = string_make(buf); + check_expression_line(tb, y); + tb->changed = TRUE; +} diff --git a/src/autopick/autopick-inserter-killer.h b/src/autopick/autopick-inserter-killer.h new file mode 100644 index 000000000..bd8d9f7e7 --- /dev/null +++ b/src/autopick/autopick-inserter-killer.h @@ -0,0 +1,11 @@ +#pragma once + +#include "autopick/autopick-util.h" +#include "system/angband.h" + +void check_expression_line(text_body_type *tb, int y); +bool insert_return_code(text_body_type *tb); +bool insert_macro_line(text_body_type *tb); +bool insert_keymap_line(text_body_type *tb); +void insert_single_letter(text_body_type *tb, int key); +void kill_line_segment(text_body_type *tb, int y, int x0, int x1, bool whole); diff --git a/src/autopick/autopick-key-flag-process.h b/src/autopick/autopick-key-flag-process.h new file mode 100644 index 000000000..94a417dc8 --- /dev/null +++ b/src/autopick/autopick-key-flag-process.h @@ -0,0 +1,18 @@ +#pragma once + +#define MATCH_KEY(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\ + ? (ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE) +#define MATCH_KEY2(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\ + ? (prev_ptr = ptr, ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE) + +#ifdef JP +#define ADD_KEY(KEY) strcat(ptr, KEY) +#else +#define ADD_KEY(KEY) (strcat(ptr, KEY), strcat(ptr, " ")) +#endif +#define ADD_KEY2(KEY) strcat(ptr, KEY) + +#define ADD_FLG(FLG) (entry->flag[FLG / 32] |= (1L << (FLG % 32))) +#define REM_FLG(FLG) (entry->flag[FLG / 32] &= ~(1L << (FLG % 32))) +#define ADD_FLG_NOUN(FLG) (ADD_FLG(FLG), prev_flg = FLG) +#define IS_FLG(FLG) (entry->flag[FLG / 32] & (1L << (FLG % 32))) diff --git a/src/autopick/autopick-keys-table.h b/src/autopick/autopick-keys-table.h new file mode 100644 index 000000000..8e634775b --- /dev/null +++ b/src/autopick/autopick-keys-table.h @@ -0,0 +1,57 @@ +#pragma once + +/*! + * todo GAME_TEXT[] かconcptrを使いたかった + * しかしコンパイルエラーで通らなかったので暫定的にdefineにした + * 上手いことコンパイルできる方法があれば求む + * @brief アイテム種別及び各種形容詞 + */ +#define KEY_ALL _("すべての", "all") +#define KEY_UNAWARE _("未判明の", "unaware") +#define KEY_UNIDENTIFIED _("未鑑定の", "unidentified") +#define KEY_IDENTIFIED _("鑑定済みの", "identified") +#define KEY_STAR_IDENTIFIED _("*鑑定*済みの", "*identified*") +#define KEY_COLLECTING _("収集中の", "collecting") +#define KEY_ARTIFACT _("アーティファクト", "artifact") +#define KEY_EGO _("エゴ", "ego") +#define KEY_GOOD _("上質の", "good") +#define KEY_NAMELESS _("無銘の", "nameless") +#define KEY_AVERAGE _("並の", "average") +#define KEY_WORTHLESS _("無価値の", "worthless") +#define KEY_RARE _("レアな", "rare") +#define KEY_COMMON _("ありふれた", "common") +#define KEY_BOOSTED _("ダイス目の違う", "dice boosted") +#define KEY_MORE_THAN _("ダイス目", "more than") +#define KEY_DICE _("以上の", "dice") +#define KEY_MORE_BONUS _("修正値", "more bonus than") +#define KEY_MORE_BONUS2 _("以上の", "") +#define KEY_WANTED _("賞金首の", "wanted") +#define KEY_UNIQUE _("ユニーク・モンスターの", "unique monster's") +#define KEY_HUMAN _("人間の", "human") +#define KEY_UNREADABLE _("読めない", "unreadable") +#define KEY_REALM1 _("第一領域の", "first realm's") +#define KEY_REALM2 _("第二領域の", "second realm's") +#define KEY_FIRST _("1冊目の", "first") +#define KEY_SECOND _("2冊目の", "second") +#define KEY_THIRD _("3冊目の", "third") +#define KEY_FOURTH _("4冊目の", "fourth") +#define KEY_ITEMS _("アイテム", "items") +#define KEY_WEAPONS _("武器", "weapons") +#define KEY_FAVORITE_WEAPONS _("得意武器", "favorite weapons") +#define KEY_ARMORS _("防具", "armors") +#define KEY_MISSILES _("矢", "missiles") +#define KEY_DEVICES _("魔法アイテム", "magical devices") +#define KEY_LIGHTS _("光源", "lights") +#define KEY_JUNKS _("がらくた", "junks") +#define KEY_CORPSES _("死体や骨", "corpses or skeletons") +#define KEY_SPELLBOOKS _("魔法書", "spellbooks") +#define KEY_HAFTED _("鈍器", "hafted weapons") +#define KEY_SHIELDS _("盾", "shields") +#define KEY_BOWS _("弓", "bows") +#define KEY_RINGS _("指輪", "rings") +#define KEY_AMULETS _("アミュレット", "amulets") +#define KEY_SUITS _("鎧", "suits") +#define KEY_CLOAKS _("クローク", "cloaks") +#define KEY_HELMS _("兜", "helms") +#define KEY_GLOVES _("籠手", "gloves") +#define KEY_BOOTS _("靴", "boots") diff --git a/src/autopick/autopick-matcher.c b/src/autopick/autopick-matcher.c new file mode 100644 index 000000000..c958e461a --- /dev/null +++ b/src/autopick/autopick-matcher.c @@ -0,0 +1,375 @@ +/*! + * todo 300行以上の凶悪関数なので後で分割しておく + * @brief 床のアイテムが自動拾いに一致するかどうかを調べる関数だけを格納したファイル + * @date 2020/04/25 + * @author Hourier + */ + +#include "autopick/autopick-matcher.h" +#include "autopick/autopick-flags-table.h" +#include "autopick/autopick-key-flag-process.h" +#include "inventory/inventory-slot-types.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "perception/object-perception.h" +#include "object-enchant/item-feeling.h" +#include "object-hook/hook-armor.h" +#include "object-hook/hook-bow.h" +#include "object-hook/hook-checker.h" +#include "object-hook/hook-enchant.h" +#include "object-hook/hook-quest.h" +#include "object-hook/hook-weapon.h" +#include "object/object-kind.h" +#include "object/object-stack.h" +#include "object/object-value.h" +#include "object/object-info.h" +#include "object-enchant/special-object-flags.h" +#include "player/player-realm.h" +#include "util/string-processor.h" + +/* + * A function for Auto-picker/destroyer + * Examine whether the object matches to the entry + */ +bool is_autopick_match(player_type *player_ptr, object_type *o_ptr, autopick_type *entry, concptr o_name) +{ + concptr ptr = entry->name; + if (IS_FLG(FLG_UNAWARE) && object_is_aware(o_ptr)) + return FALSE; + + if (IS_FLG(FLG_UNIDENTIFIED) + && (object_is_known(o_ptr) || (o_ptr->ident & IDENT_SENSE))) + return FALSE; + + if (IS_FLG(FLG_IDENTIFIED) && !object_is_known(o_ptr)) + return FALSE; + + if (IS_FLG(FLG_STAR_IDENTIFIED) && + (!object_is_known(o_ptr) || !object_is_fully_known(o_ptr))) + return FALSE; + + if (IS_FLG(FLG_BOOSTED)) + { + object_kind *k_ptr = &k_info[o_ptr->k_idx]; + if (!object_is_melee_weapon(o_ptr)) + return FALSE; + + if ((o_ptr->dd == k_ptr->dd) && (o_ptr->ds == k_ptr->ds)) + return FALSE; + + if (!object_is_known(o_ptr) && object_is_quest_target(player_ptr, o_ptr)) + { + return FALSE; + } + } + + if (IS_FLG(FLG_MORE_DICE)) + { + if (o_ptr->dd * o_ptr->ds < entry->dice) + return FALSE; + } + + if (IS_FLG(FLG_MORE_BONUS)) + { + if (!object_is_known(o_ptr)) return FALSE; + + if (o_ptr->pval) + { + if (o_ptr->pval < entry->bonus) return FALSE; + } + else + { + if (o_ptr->to_h < entry->bonus && + o_ptr->to_d < entry->bonus && + o_ptr->to_a < entry->bonus && + o_ptr->pval < entry->bonus) + return FALSE; + } + } + + if (IS_FLG(FLG_WORTHLESS) && object_value(player_ptr, o_ptr) > 0) + return FALSE; + + if (IS_FLG(FLG_ARTIFACT)) + { + if (!object_is_known(o_ptr) || !object_is_artifact(o_ptr)) + return FALSE; + } + + if (IS_FLG(FLG_EGO)) + { + if (!object_is_ego(o_ptr)) return FALSE; + if (!object_is_known(o_ptr) && + !((o_ptr->ident & IDENT_SENSE) && o_ptr->feeling == FEEL_EXCELLENT)) + return FALSE; + } + + if (IS_FLG(FLG_GOOD)) + { + if (!object_is_equipment(o_ptr)) return FALSE; + if (object_is_known(o_ptr)) + { + if (!object_is_nameless(player_ptr, o_ptr)) + return FALSE; + + if (o_ptr->to_a <= 0 && (o_ptr->to_h + o_ptr->to_d) <= 0) + return FALSE; + } + else if (o_ptr->ident & IDENT_SENSE) + { + switch (o_ptr->feeling) + { + case FEEL_GOOD: + break; + + default: + return FALSE; + } + } + else + { + return FALSE; + } + } + + if (IS_FLG(FLG_NAMELESS)) + { + if (!object_is_equipment(o_ptr)) return FALSE; + if (object_is_known(o_ptr)) + { + if (!object_is_nameless(player_ptr, o_ptr)) + return FALSE; + } + else if (o_ptr->ident & IDENT_SENSE) + { + switch (o_ptr->feeling) + { + case FEEL_AVERAGE: + case FEEL_GOOD: + case FEEL_BROKEN: + case FEEL_CURSED: + break; + + default: + return FALSE; + } + } + else + { + return FALSE; + } + } + + if (IS_FLG(FLG_AVERAGE)) + { + if (!object_is_equipment(o_ptr)) return FALSE; + if (object_is_known(o_ptr)) + { + if (!object_is_nameless(player_ptr, o_ptr)) + return FALSE; + + if (object_is_cursed(o_ptr) || object_is_broken(o_ptr)) + return FALSE; + + if (o_ptr->to_a > 0 || (o_ptr->to_h + o_ptr->to_d) > 0) + return FALSE; + } + else if (o_ptr->ident & IDENT_SENSE) + { + switch (o_ptr->feeling) + { + case FEEL_AVERAGE: + break; + + default: + return FALSE; + } + } + else + { + return FALSE; + } + } + + if (IS_FLG(FLG_RARE) && !object_is_rare(o_ptr)) + return FALSE; + + if (IS_FLG(FLG_COMMON) && object_is_rare(o_ptr)) + return FALSE; + + if (IS_FLG(FLG_WANTED) && !object_is_bounty(player_ptr, o_ptr)) + return FALSE; + + if (IS_FLG(FLG_UNIQUE) && + ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) || + !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE))) + return FALSE; + + if (IS_FLG(FLG_HUMAN) && + (o_ptr->tval != TV_CORPSE || + !angband_strchr("pht", r_info[o_ptr->pval].d_char))) + return FALSE; + + if (IS_FLG(FLG_UNREADABLE) && + (o_ptr->tval < TV_LIFE_BOOK || + check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval))) + return FALSE; + + if (IS_FLG(FLG_REALM1) && (get_realm1_book(player_ptr) != o_ptr->tval || + player_ptr->pclass == CLASS_SORCERER || + player_ptr->pclass == CLASS_RED_MAGE)) + return FALSE; + + if (IS_FLG(FLG_REALM2) && (get_realm2_book(player_ptr) != o_ptr->tval || + player_ptr->pclass == CLASS_SORCERER || + player_ptr->pclass == CLASS_RED_MAGE)) + return FALSE; + + if (IS_FLG(FLG_FIRST) && + (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval)) + return FALSE; + + if (IS_FLG(FLG_SECOND) && + (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval)) + return FALSE; + + if (IS_FLG(FLG_THIRD) && + (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval)) + return FALSE; + + if (IS_FLG(FLG_FOURTH) && + (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval)) + return FALSE; + + if (IS_FLG(FLG_WEAPONS)) + { + if (!object_is_weapon(player_ptr, o_ptr)) + return FALSE; + } + else if (IS_FLG(FLG_FAVORITE_WEAPONS)) + { + if (!object_is_favorite(player_ptr, o_ptr)) + return FALSE; + } + else if (IS_FLG(FLG_ARMORS)) + { + if (!object_is_armour(player_ptr, o_ptr)) + return FALSE; + } + else if (IS_FLG(FLG_MISSILES)) + { + if (!object_is_ammo(o_ptr)) return FALSE; + } + else if (IS_FLG(FLG_DEVICES)) + { + switch (o_ptr->tval) + { + case TV_SCROLL: case TV_STAFF: case TV_WAND: case TV_ROD: + break; + default: return FALSE; + } + } + else if (IS_FLG(FLG_LIGHTS)) + { + if (!(o_ptr->tval == TV_LITE)) + return FALSE; + } + else if (IS_FLG(FLG_JUNKS)) + { + switch (o_ptr->tval) + { + case TV_SKELETON: case TV_BOTTLE: + case TV_JUNK: case TV_STATUE: + break; + default: return FALSE; + } + } + else if (IS_FLG(FLG_CORPSES)) + { + if (o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_SKELETON) + return FALSE; + } + else if (IS_FLG(FLG_SPELLBOOKS)) + { + if (!(o_ptr->tval >= TV_LIFE_BOOK)) + return FALSE; + } + else if (IS_FLG(FLG_HAFTED)) + { + if (!(o_ptr->tval == TV_HAFTED)) + return FALSE; + } + else if (IS_FLG(FLG_SHIELDS)) + { + if (!(o_ptr->tval == TV_SHIELD)) + return FALSE; + } + else if (IS_FLG(FLG_BOWS)) + { + if (!(o_ptr->tval == TV_BOW)) + return FALSE; + } + else if (IS_FLG(FLG_RINGS)) + { + if (!(o_ptr->tval == TV_RING)) + return FALSE; + } + else if (IS_FLG(FLG_AMULETS)) + { + if (!(o_ptr->tval == TV_AMULET)) + return FALSE; + } + else if (IS_FLG(FLG_SUITS)) + { + if (!(o_ptr->tval == TV_DRAG_ARMOR || + o_ptr->tval == TV_HARD_ARMOR || + o_ptr->tval == TV_SOFT_ARMOR)) + return FALSE; + } + else if (IS_FLG(FLG_CLOAKS)) + { + if (!(o_ptr->tval == TV_CLOAK)) + return FALSE; + } + else if (IS_FLG(FLG_HELMS)) + { + if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM)) + return FALSE; + } + else if (IS_FLG(FLG_GLOVES)) + { + if (!(o_ptr->tval == TV_GLOVES)) + return FALSE; + } + else if (IS_FLG(FLG_BOOTS)) + { + if (!(o_ptr->tval == TV_BOOTS)) + return FALSE; + } + + if (*ptr == '^') + { + ptr++; + if (strncmp(o_name, ptr, strlen(ptr))) return FALSE; + } + else + { + if (!angband_strstr(o_name, ptr)) return FALSE; + } + + if (!IS_FLG(FLG_COLLECTING)) return TRUE; + + for (int j = 0; j < INVEN_PACK; j++) + { + /* + * 'Collecting' means the item must be absorbed + * into an inventory slot. + * But an item can not be absorbed into itself! + */ + if ((&player_ptr->inventory_list[j] != o_ptr) && + object_similar(&player_ptr->inventory_list[j], o_ptr)) + return TRUE; + } + + return FALSE; +} diff --git a/src/autopick/autopick-matcher.h b/src/autopick/autopick-matcher.h new file mode 100644 index 000000000..ae7eb5777 --- /dev/null +++ b/src/autopick/autopick-matcher.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" +#include "autopick/autopick-util.h" + +bool is_autopick_match(player_type *player_ptr, object_type *o_ptr, autopick_type *entry, concptr o_name); diff --git a/src/autopick/autopick-menu-data-table.c b/src/autopick/autopick-menu-data-table.c new file mode 100644 index 000000000..452fc161e --- /dev/null +++ b/src/autopick/autopick-menu-data-table.c @@ -0,0 +1,117 @@ +/*! + * @brief 自動拾いのユーティリティ + * @date 2020/04/25 + * @author Hourier + */ + +#include "autopick/autopick-menu-data-table.h" +#include "autopick/autopick-commands-table.h" +#include "autopick/autopick-editor-table.h" +#include "autopick/autopick-keys-table.h" +#include "util/int-char-converter.h" + +command_menu_type menu_data[MENU_DATA_NUM] = +{ + {MN_HELP, 0, -1, EC_HELP}, + {MN_QUIT, 0, KTRL('q'), EC_QUIT}, + {MN_SAVEQUIT, 0, KTRL('w'), EC_SAVEQUIT}, + {MN_REVERT, 0, KTRL('z'), EC_REVERT}, + + {MN_EDIT, 0, -1, -1}, + {MN_CUT, 1, KTRL('x'), EC_CUT}, + {MN_COPY, 1, KTRL('c'), EC_COPY}, + {MN_PASTE, 1, KTRL('v'), EC_PASTE}, + {MN_BLOCK, 1, KTRL('g'), EC_BLOCK}, + {MN_KILL_LINE, 1, KTRL('k'), EC_KILL_LINE}, + {MN_DELETE_CHAR, 1, KTRL('d'), EC_DELETE_CHAR}, + {MN_BACKSPACE, 1, KTRL('h'), EC_BACKSPACE}, + {MN_RETURN, 1, KTRL('j'), EC_RETURN}, + {MN_RETURN, 1, KTRL('m'), EC_RETURN}, + + {MN_SEARCH, 0, -1, -1}, + {MN_SEARCH_STR, 1, KTRL('s'), EC_SEARCH_STR}, + {MN_SEARCH_FORW, 1, -1, EC_SEARCH_FORW}, + {MN_SEARCH_BACK, 1, KTRL('r'), EC_SEARCH_BACK}, + {MN_SEARCH_OBJ, 1, KTRL('y'), EC_SEARCH_OBJ}, + {MN_SEARCH_DESTROYED, 1, -1, EC_SEARCH_DESTROYED}, + + {MN_MOVE, 0, -1, -1}, + {MN_LEFT, 1, KTRL('b'), EC_LEFT}, + {MN_DOWN, 1, KTRL('n'), EC_DOWN}, + {MN_UP, 1, KTRL('p'), EC_UP}, + {MN_RIGHT, 1, KTRL('f'), EC_RIGHT}, + {MN_BOL, 1, KTRL('a'), EC_BOL}, + {MN_EOL, 1, KTRL('e'), EC_EOL}, + {MN_PGUP, 1, KTRL('o'), EC_PGUP}, + {MN_PGDOWN, 1, KTRL('l'), EC_PGDOWN}, + {MN_TOP, 1, KTRL('t'), EC_TOP}, + {MN_BOTTOM, 1, KTRL('u'), EC_BOTTOM}, + + {MN_INSERT, 0, -1, -1}, + {MN_INSERT_OBJECT, 1, KTRL('i'), EC_INSERT_OBJECT}, + {MN_INSERT_DESTROYED, 1, -1, EC_INSERT_DESTROYED}, + {MN_INSERT_BLOCK, 1, -1, EC_INSERT_BLOCK}, + {MN_INSERT_MACRO, 1, -1, EC_INSERT_MACRO}, + {MN_INSERT_KEYMAP, 1, -1, EC_INSERT_KEYMAP}, + + {MN_ADJECTIVE_GEN, 0, -1, -1}, + {KEY_UNAWARE, 1, -1, EC_IK_UNAWARE}, + {KEY_UNIDENTIFIED, 1, -1, EC_IK_UNIDENTIFIED}, + {KEY_IDENTIFIED, 1, -1, EC_IK_IDENTIFIED}, + {KEY_STAR_IDENTIFIED, 1, -1, EC_IK_STAR_IDENTIFIED}, + {KEY_COLLECTING, 1, -1, EC_OK_COLLECTING}, + {KEY_ARTIFACT, 1, -1, EC_OK_ARTIFACT}, + {KEY_EGO, 1, -1, EC_OK_EGO}, + {KEY_GOOD, 1, -1, EC_OK_GOOD}, + {KEY_NAMELESS, 1, -1, EC_OK_NAMELESS}, + {KEY_AVERAGE, 1, -1, EC_OK_AVERAGE}, + {KEY_WORTHLESS, 1, -1, EC_OK_WORTHLESS}, + {MN_RARE, 1, -1, EC_OK_RARE}, + {MN_COMMON, 1, -1, EC_OK_COMMON}, + + {MN_ADJECTIVE_SPECIAL, 0, -1, -1}, + {MN_BOOSTED, 1, -1, EC_OK_BOOSTED}, + {MN_MORE_DICE, 1, -1, EC_OK_MORE_DICE}, + {MN_MORE_BONUS, 1, -1, EC_OK_MORE_BONUS}, + {MN_WANTED, 1, -1, EC_OK_WANTED}, + {MN_UNIQUE, 1, -1, EC_OK_UNIQUE}, + {MN_HUMAN, 1, -1, EC_OK_HUMAN}, + {MN_UNREADABLE, 1, -1, EC_OK_UNREADABLE}, + {MN_REALM1, 1, -1, EC_OK_REALM1}, + {MN_REALM2, 1, -1, EC_OK_REALM2}, + {MN_FIRST, 1, -1, EC_OK_FIRST}, + {MN_SECOND, 1, -1, EC_OK_SECOND}, + {MN_THIRD, 1, -1, EC_OK_THIRD}, + {MN_FOURTH, 1, -1, EC_OK_FOURTH}, + + {MN_NOUN, 0, -1, -1}, + {KEY_WEAPONS, 1, -1, EC_KK_WEAPONS}, + {KEY_FAVORITE_WEAPONS, 1, -1, EC_KK_FAVORITE_WEAPONS}, + {KEY_ARMORS, 1, -1, EC_KK_ARMORS}, + {KEY_MISSILES, 1, -1, EC_KK_MISSILES}, + {KEY_DEVICES, 1, -1, EC_KK_DEVICES}, + {KEY_LIGHTS, 1, -1, EC_KK_LIGHTS}, + {KEY_JUNKS, 1, -1, EC_KK_JUNKS}, + {KEY_CORPSES, 1, -1, EC_KK_CORPSES}, + {KEY_SPELLBOOKS, 1, -1, EC_KK_SPELLBOOKS}, + {KEY_SHIELDS, 1, -1, EC_KK_SHIELDS}, + {KEY_BOWS, 1, -1, EC_KK_BOWS}, + {KEY_RINGS, 1, -1, EC_KK_RINGS}, + {KEY_AMULETS, 1, -1, EC_KK_AMULETS}, + {KEY_SUITS, 1, -1, EC_KK_SUITS}, + {KEY_CLOAKS, 1, -1, EC_KK_CLOAKS}, + {KEY_HELMS, 1, -1, EC_KK_HELMS}, + {KEY_GLOVES, 1, -1, EC_KK_GLOVES}, + {KEY_BOOTS, 1, -1, EC_KK_BOOTS}, + + {MN_COMMAND_LETTER, 0, -1, -1}, + {MN_CL_AUTOPICK, 1, -1, EC_CL_AUTOPICK}, + {MN_CL_DESTROY, 1, -1, EC_CL_DESTROY}, + {MN_CL_LEAVE, 1, -1, EC_CL_LEAVE}, + {MN_CL_QUERY, 1, -1, EC_CL_QUERY}, + {MN_CL_NO_DISP, 1, -1, EC_CL_NO_DISP}, + + {MN_DELETE_CHAR, -1, 0x7F, EC_DELETE_CHAR}, + + {NULL, -1, -1, 0} +}; diff --git a/src/autopick/autopick-menu-data-table.h b/src/autopick/autopick-menu-data-table.h new file mode 100644 index 000000000..faf5a9824 --- /dev/null +++ b/src/autopick/autopick-menu-data-table.h @@ -0,0 +1,14 @@ +#pragma once + +#include "system/angband.h" + +#define MENU_DATA_NUM 92 + +typedef struct command_menu_type { + concptr name; + int level; + int key; + int com_id; +} command_menu_type; + +extern command_menu_type menu_data[MENU_DATA_NUM]; diff --git a/src/autopick/autopick-methods-table.h b/src/autopick/autopick-methods-table.h new file mode 100644 index 000000000..e612e5252 --- /dev/null +++ b/src/autopick/autopick-methods-table.h @@ -0,0 +1,8 @@ +#pragma once + +#define DO_AUTOPICK 0x01 +#define DO_AUTODESTROY 0x02 +#define DO_DISPLAY 0x04 +#define DONT_AUTOPICK 0x08 +#define ITEM_DISPLAY 0x10 +#define DO_QUERY_AUTOPICK 0x20 diff --git a/src/autopick/autopick-pref-processor.c b/src/autopick/autopick-pref-processor.c new file mode 100644 index 000000000..0ce94846c --- /dev/null +++ b/src/autopick/autopick-pref-processor.c @@ -0,0 +1,43 @@ +#include "autopick/autopick-pref-processor.h" +#include "autopick/autopick-entry.h" +#include "autopick/autopick-util.h" +#include "system/angband.h" + +/* + * Process line for auto picker/destroyer. + */ +void process_autopick_file_command(char *buf) +{ + autopick_type an_entry, *entry = &an_entry; + int i; + for (i = 0; buf[i]; i++) + { +#ifdef JP + if (iskanji(buf[i])) + { + i++; + continue; + } +#endif + if (iswspace(buf[i]) && buf[i] != ' ') + break; + } + + buf[i] = 0; + if (!autopick_new_entry(entry, buf, FALSE)) return; + + for (i = 0; i < max_autopick; i++) + { + if (!strcmp(entry->name, autopick_list[i].name) + && entry->flag[0] == autopick_list[i].flag[0] + && entry->flag[1] == autopick_list[i].flag[1] + && entry->dice == autopick_list[i].dice + && entry->bonus == autopick_list[i].bonus) + { + autopick_free_entry(entry); + return; + } + } + + add_autopick_list(entry); +} diff --git a/src/autopick/autopick-pref-processor.h b/src/autopick/autopick-pref-processor.h new file mode 100644 index 000000000..14c4482da --- /dev/null +++ b/src/autopick/autopick-pref-processor.h @@ -0,0 +1,3 @@ +#pragma once + +void process_autopick_file_command(char *buf); diff --git a/src/autopick/autopick-reader-writer.c b/src/autopick/autopick-reader-writer.c new file mode 100644 index 000000000..6dd8e4709 --- /dev/null +++ b/src/autopick/autopick-reader-writer.c @@ -0,0 +1,197 @@ +#include "autopick/autopick-reader-writer.h" +#include "autopick/autopick-initializer.h" +#include "autopick/autopick-pref-processor.h" +#include "io/files-util.h" +#include "io/read-pref-file.h" +#include "util/angband-files.h" +#include "util/string-processor.h" +#include "view/display-messages.h" + +/* + * Load an autopick preference file + */ +void autopick_load_pref(player_type *player_ptr, bool disp_mes) +{ + GAME_TEXT buf[80]; + init_autopick(); + angband_strcpy(buf, pickpref_filename(player_ptr, PT_WITH_PNAME), sizeof(buf)); + errr err = process_autopick_file(player_ptr, buf, process_autopick_file_command); + if (err == 0 && disp_mes) + { + msg_format(_("%s‚ð“ǂݍž‚Ý‚Ü‚µ‚½B", "Loaded '%s'."), buf); + } + + if (err < 0) + { + angband_strcpy(buf, pickpref_filename(player_ptr, PT_DEFAULT), sizeof(buf)); + err = process_autopick_file(player_ptr, buf, process_autopick_file_command); + if (err == 0 && disp_mes) + { + msg_format(_("%s‚ð“ǂݍž‚Ý‚Ü‚µ‚½B", "Loaded '%s'."), buf); + } + } + + if (err && disp_mes) + { + msg_print(_("Ž©“®E‚¢Ý’èƒtƒ@ƒCƒ‹‚̓ǂݍž‚Ý‚ÉŽ¸”s‚µ‚Ü‚µ‚½B", "Failed to reload autopick preference.")); + } +} + + +/* + * Get file name for autopick preference + */ +concptr pickpref_filename(player_type *player_ptr, int filename_mode) +{ + static const char namebase[] = _("picktype", "pickpref"); + + switch (filename_mode) + { + case PT_DEFAULT: + return format("%s.prf", namebase); + + case PT_WITH_PNAME: + return format("%s-%s.prf", namebase, player_ptr->base_name); + + default: + return NULL; + } +} + + +/* + * Read whole lines of a file to memory + */ +static concptr *read_text_lines(concptr filename) +{ + concptr *lines_list = NULL; + FILE *fff; + + int lines = 0; + char buf[1024]; + + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename); + fff = angband_fopen(buf, "r"); + if (!fff) return NULL; + + C_MAKE(lines_list, MAX_LINES, concptr); + while (angband_fgets(fff, buf, sizeof(buf)) == 0) + { + lines_list[lines++] = string_make(buf); + if (lines >= MAX_LINES - 1) break; + } + + if (lines == 0) + lines_list[0] = string_make(""); + + angband_fclose(fff); + return lines_list; +} + + +/* + * Copy the default autopick file to the user directory + */ +static void prepare_default_pickpref(player_type *player_ptr) +{ + const concptr messages[] = { + _("‚ ‚È‚½‚́uŽ©“®E‚¢ƒGƒfƒBƒ^v‚ð‰‚ß‚Ä‹N“®‚µ‚Ü‚µ‚½B", "You have activated the Auto-Picker Editor for the first time."), + _("Ž©“®E‚¢‚̃†[ƒU[Ý’èƒtƒ@ƒCƒ‹‚ª‚Ü‚¾‘‚©‚ê‚Ä‚¢‚È‚¢‚̂ŁA", "Since user pref file for autopick is not yet created,"), + _("Šî–{“I‚ÈŽ©“®E‚¢Ý’èƒtƒ@ƒCƒ‹‚ðlib/pref/picktype.prf‚©‚çƒRƒs[‚µ‚Ü‚·B", "the default setting is loaded from lib/pref/pickpref.prf ."), + NULL + }; + + concptr filename = pickpref_filename(player_ptr, PT_DEFAULT); + for (int i = 0; messages[i]; i++) + { + msg_print(messages[i]); + } + + msg_print(NULL); + char buf[1024]; + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename); + FILE *user_fp; + user_fp = angband_fopen(buf, "w"); + if (!user_fp) return; + + fprintf(user_fp, "#***\n"); + for (int i = 0; messages[i]; i++) + { + fprintf(user_fp, "#*** %s\n", messages[i]); + } + + fprintf(user_fp, "#***\n\n\n"); + path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, filename); + FILE *pref_fp; + pref_fp = angband_fopen(buf, "r"); + + if (!pref_fp) + { + angband_fclose(user_fp); + return; + } + + while (!angband_fgets(pref_fp, buf, sizeof(buf))) + { + fprintf(user_fp, "%s\n", buf); + } + + angband_fclose(user_fp); + angband_fclose(pref_fp); +} + +/* + * Read an autopick prefence file to memory + * Prepare default if no user file is found + */ +concptr *read_pickpref_text_lines(player_type *player_ptr, int *filename_mode_p) +{ + /* Try a filename with player name */ + *filename_mode_p = PT_WITH_PNAME; + char buf[1024]; + strcpy(buf, pickpref_filename(player_ptr, *filename_mode_p)); + concptr *lines_list; + lines_list = read_text_lines(buf); + + if (!lines_list) + { + *filename_mode_p = PT_DEFAULT; + strcpy(buf, pickpref_filename(player_ptr, *filename_mode_p)); + lines_list = read_text_lines(buf); + } + + if (!lines_list) + { + prepare_default_pickpref(player_ptr); + lines_list = read_text_lines(buf); + } + + if (!lines_list) + { + C_MAKE(lines_list, MAX_LINES, concptr); + lines_list[0] = string_make(""); + } + + return lines_list; +} + + +/* + * Write whole lines of memory to a file. + */ +bool write_text_lines(concptr filename, concptr *lines_list) +{ + char buf[1024]; + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename); + FILE *fff; + fff = angband_fopen(buf, "w"); + if (!fff) return FALSE; + + for (int lines = 0; lines_list[lines]; lines++) + { + angband_fputs(fff, lines_list[lines], 1024); + } + + angband_fclose(fff); + return TRUE; +} diff --git a/src/autopick/autopick-reader-writer.h b/src/autopick/autopick-reader-writer.h new file mode 100644 index 000000000..275160dfc --- /dev/null +++ b/src/autopick/autopick-reader-writer.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" +#include "autopick/autopick-util.h" + +void autopick_load_pref(player_type *player_ptr, bool disp_mes); +concptr *read_pickpref_text_lines(player_type *player_ptr, int *filename_mode_p); +bool write_text_lines(concptr filename, concptr *lines_list); +concptr pickpref_filename(player_type *player_ptr, int filename_mode); diff --git a/src/autopick/autopick-registry.c b/src/autopick/autopick-registry.c new file mode 100644 index 000000000..cfbeb34de --- /dev/null +++ b/src/autopick/autopick-registry.c @@ -0,0 +1,199 @@ +/*! + * @brief 自動拾いにアイテムを登録する + * @date 2020/04/26 + * @author Hourier + */ + +#include "autopick/autopick-registry.h" +#include "autopick/autopick-entry.h" +#include "autopick/autopick-finder.h" +#include "autopick/autopick-methods-table.h" +#include "autopick/autopick-reader-writer.h" +#include "core/asking-player.h" +#include "flavor/flavor-describer.h" +#include "io/files-util.h" +#include "object-enchant/item-feeling.h" +#include "object-enchant/special-object-flags.h" +#include "object-hook/hook-enchant.h" +#include "perception/object-perception.h" +#include "util/angband-files.h" +#include "view/display-messages.h" + +static const char autoregister_header[] = "?:$AUTOREGISTER"; + +/* + * Clear auto registered lines in the picktype.prf . + */ +static bool clear_auto_register(player_type *player_ptr) +{ + char pref_file[1024]; + path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME)); + FILE *pref_fff; + pref_fff = angband_fopen(pref_file, "r"); + + if (!pref_fff) { + path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT)); + pref_fff = angband_fopen(pref_file, "r"); + } + + if (!pref_fff) { + return TRUE; + } + + char tmp_file[1024]; + FILE *tmp_fff; + tmp_fff = angband_fopen_temp(tmp_file, sizeof(tmp_file)); + if (!tmp_fff) { + fclose(pref_fff); + msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file); + msg_print(NULL); + return FALSE; + } + + bool autoregister = FALSE; + int num = 0; + char buf[1024]; + while (TRUE) { + if (angband_fgets(pref_fff, buf, sizeof(buf))) + break; + + if (autoregister) { + if (buf[0] != '#' && buf[0] != '?') + num++; + continue; + } + + if (streq(buf, autoregister_header)) { + autoregister = TRUE; + } else { + fprintf(tmp_fff, "%s\n", buf); + } + } + + angband_fclose(pref_fff); + angband_fclose(tmp_fff); + + bool okay = TRUE; + if (num) { + msg_format(_("以前のキャラクター用の自動設定(%d行)が残っています。", "Auto registered lines (%d lines) for previous character are remaining."), num); + strcpy(buf, _("古い設定行は削除します。よろしいですか?", "These lines will be deleted. Are you sure? ")); + + if (!get_check(buf)) { + okay = FALSE; + autoregister = FALSE; + + msg_print(_("エディタのカット&ペースト等を使って必要な行を避難してください。", "Use cut & paste of auto picker editor (_) to keep old prefs.")); + } + } + + if (autoregister) { + tmp_fff = angband_fopen(tmp_file, "r"); + pref_fff = angband_fopen(pref_file, "w"); + + while (!angband_fgets(tmp_fff, buf, sizeof(buf))) + fprintf(pref_fff, "%s\n", buf); + + angband_fclose(pref_fff); + angband_fclose(tmp_fff); + } + + fd_kill(tmp_file); + return okay; +} + +/* + * Automatically register an auto-destroy preference line + */ +bool autopick_autoregister(player_type *player_ptr, object_type *o_ptr) +{ + autopick_type an_entry, *entry = &an_entry; + int autopick_registered = find_autopick_list(player_ptr, o_ptr); + if (autopick_registered != -1) { + concptr what; + byte act = autopick_list[autopick_registered].action; + if (act & DO_AUTOPICK) + what = _("自動で拾う", "auto-pickup"); + else if (act & DO_AUTODESTROY) + what = _("自動破壊する", "auto-destroy"); + else if (act & DONT_AUTOPICK) + what = _("放置する", "leave on floor"); + else + what = _("確認して拾う", "query auto-pickup"); + + msg_format(_("そのアイテムは既に%sように設定されています。", "The object is already registered to %s."), what); + return FALSE; + } + + if ((object_is_known(o_ptr) && object_is_artifact(o_ptr)) + || ((o_ptr->ident & IDENT_SENSE) && (o_ptr->feeling == FEEL_TERRIBLE || o_ptr->feeling == FEEL_SPECIAL))) { + GAME_TEXT o_name[MAX_NLEN]; + describe_flavor(player_ptr, o_name, o_ptr, 0); + msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name); + return FALSE; + } + + if (!player_ptr->autopick_autoregister) { + if (!clear_auto_register(player_ptr)) + return FALSE; + } + + char buf[1024]; + char pref_file[1024]; + FILE *pref_fff; + path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME)); + pref_fff = angband_fopen(pref_file, "r"); + + if (!pref_fff) { + path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT)); + pref_fff = angband_fopen(pref_file, "r"); + } + + if (pref_fff) { + while (TRUE) { + if (angband_fgets(pref_fff, buf, sizeof(buf))) { + player_ptr->autopick_autoregister = FALSE; + break; + } + + if (streq(buf, autoregister_header)) { + player_ptr->autopick_autoregister = TRUE; + break; + } + } + + fclose(pref_fff); + } else { + /* + * File could not be opened for reading. Assume header not + * present. + */ + player_ptr->autopick_autoregister = FALSE; + } + + pref_fff = angband_fopen(pref_file, "a"); + if (!pref_fff) { + msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), pref_file); + msg_print(NULL); + return FALSE; + } + + if (!player_ptr->autopick_autoregister) { + fprintf(pref_fff, "%s\n", autoregister_header); + + fprintf(pref_fff, "%s\n", _("# *警告!!* 以降の行は自動登録されたものです。", "# *Warning!* The lines below will be deleted later.")); + fprintf(pref_fff, "%s\n", + _("# 後で自動的に削除されますので、必要な行は上の方へ移動しておいてください。", + "# Keep it by cut & paste if you need these lines for future characters.")); + player_ptr->autopick_autoregister = TRUE; + } + + autopick_entry_from_object(player_ptr, entry, o_ptr); + entry->action = DO_AUTODESTROY; + add_autopick_list(entry); + + concptr tmp = autopick_line_from_entry(entry); + fprintf(pref_fff, "%s\n", tmp); + string_free(tmp); + fclose(pref_fff); + return TRUE; +} diff --git a/src/autopick/autopick-registry.h b/src/autopick/autopick-registry.h new file mode 100644 index 000000000..713efdefc --- /dev/null +++ b/src/autopick/autopick-registry.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" +#include "autopick/autopick-util.h" +#include "system/object-type-definition.h" + +bool autopick_autoregister(player_type *player_ptr, object_type *o_ptr); diff --git a/src/autopick/autopick-util.c b/src/autopick/autopick-util.c new file mode 100644 index 000000000..59e3955c0 --- /dev/null +++ b/src/autopick/autopick-util.c @@ -0,0 +1,102 @@ +#include "autopick/autopick-util.h" +#include "autopick/autopick-menu-data-table.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" +#include "game-option/input-options.h" +#include "main/sound-of-music.h" +#include "monster-race/race-indice-types.h" +#include "object-enchant/item-feeling.h" +#include "util/quarks.h" + +/* + * 自動拾い/破壊設定のリストに関する変数 / List for auto-picker/destroyer entries + */ +int max_autopick = 0; /*!< 現在登録している自動拾い/破壊設定の数 */ +int max_max_autopick = 0; /*!< 自動拾い/破壊設定の限界数 */ +autopick_type *autopick_list = NULL; /*!< 自動拾い/破壊設定構造体のポインタ配列 */ + +/* + * Automatically destroy an item if it is to be destroyed + * + * When always_pickup is 'yes', we disable auto-destroyer function of + * auto-picker/destroyer, and do only easy-auto-destroyer. + */ +object_type autopick_last_destroyed_object; + +/* + * A function to delete entry + */ +void autopick_free_entry(autopick_type *entry) +{ + string_free(entry->name); + string_free(entry->insc); + entry->name = NULL; + entry->insc = NULL; +} + + +/* + * Free memory of lines_list. + */ +void free_text_lines(concptr *lines_list) +{ + for (int lines = 0; lines_list[lines]; lines++) + { + string_free(lines_list[lines]); + } + + /* free list of pointers */ + C_KILL(lines_list, MAX_LINES, concptr); +} + + +/* + * Find a command by 'key'. + */ +int get_com_id(char key) +{ + for (int i = 0; menu_data[i].name; i++) + { + if (menu_data[i].key == key) + { + return menu_data[i].com_id; + } + } + + return 0; +} + + +/* + * Auto inscription + */ +void auto_inscribe_item(player_type *player_ptr, object_type *o_ptr, int idx) +{ + if (idx < 0 || !autopick_list[idx].insc) return; + + if (!o_ptr->inscription) + o_ptr->inscription = quark_add(autopick_list[idx].insc); + + player_ptr->window |= (PW_EQUIP | PW_INVEN); + player_ptr->update |= (PU_BONUS); +} + + +/* + * Add one line to autopick_list[] + */ +void add_autopick_list(autopick_type *entry) +{ + if (max_autopick >= max_max_autopick) + { + int old_max_max_autopick = max_max_autopick; + autopick_type *old_autopick_list = autopick_list; + max_max_autopick += MAX_AUTOPICK_DEFAULT; + C_MAKE(autopick_list, max_max_autopick, autopick_type); + (void)C_COPY(autopick_list, old_autopick_list, old_max_max_autopick, autopick_type); + C_KILL(old_autopick_list, old_max_max_autopick, autopick_type); + } + + autopick_list[max_autopick] = *entry; + max_autopick++; +} diff --git a/src/autopick/autopick-util.h b/src/autopick/autopick-util.h new file mode 100644 index 000000000..f0b4bbcd1 --- /dev/null +++ b/src/autopick/autopick-util.h @@ -0,0 +1,85 @@ +#pragma once + +#include "system/angband.h" +#include "system/object-type-definition.h" + +#define MAX_LINELEN 1024 +#define MAX_AUTOPICK_DEFAULT 200 +#define MAX_YANK MAX_LINELEN +#define MAX_LINES 3000 + +#define PT_DEFAULT 0 +#define PT_WITH_PNAME 1 + +#define MARK_MARK 0x01 +#define MARK_BY_SHIFT 0x02 + +#define LSTAT_BYPASS 0x01 +#define LSTAT_EXPRESSION 0x02 +#define LSTAT_AUTOREGISTER 0x04 + +/*! + * @struct autopick_type + * @brief 自動拾い/破壊設定データの構造体 / A structure type for entry of auto-picker/destroyer + */ +typedef struct { + concptr name; /*!< 自動拾い/破壊定義の名称一致基準 / Items which have 'name' as part of its name match */ + concptr insc; /*!< 対象となったアイテムに自動で刻む内容 / Items will be auto-inscribed as 'insc' */ + BIT_FLAGS flag[2]; /*!< キーワードに関する汎用的な条件フラグ / Misc. keyword to be matched */ + byte action; /*!< 対象のアイテムを拾う/破壊/放置するかの指定フラグ / Auto-pickup or Destroy or Leave items */ + byte dice; /*!< 武器のダイス値基準値 / Weapons which have more than 'dice' dice match */ + byte bonus; /*!< アイテムのボーナス基準値 / Items which have more than 'bonus' magical bonus match */ +} autopick_type; + +/* + * Struct for yank buffer + */ +typedef struct chain_str { + struct chain_str *next; + char s[1]; +} chain_str_type; + +/* + * Data struct for text editor + */ +typedef struct { + int wid, hgt; + int cx, cy; + int upper, left; + int old_wid, old_hgt; + int old_cy; + int old_upper, old_left; + int mx, my; + byte mark; + + object_type *search_o_ptr; + concptr search_str; + concptr last_destroyed; + + chain_str_type *yank; + bool yank_eol; + + concptr *lines_list; + byte states[MAX_LINES]; + + u16b dirty_flags; + int dirty_line; + int filename_mode; + int old_com_id; + + bool changed; +} text_body_type; + +/* + * List for auto-picker/destroyer entries + */ +extern int max_autopick; +extern int max_max_autopick; +extern autopick_type *autopick_list; +extern object_type autopick_last_destroyed_object; + +void autopick_free_entry(autopick_type *entry); +void free_text_lines(concptr *lines_list); +int get_com_id(char key); +void auto_inscribe_item(player_type *player_ptr, object_type *o_ptr, int idx); +void add_autopick_list(autopick_type *entry); diff --git a/src/autopick/autopick.c b/src/autopick/autopick.c new file mode 100644 index 000000000..d4c69b8f9 --- /dev/null +++ b/src/autopick/autopick.c @@ -0,0 +1,153 @@ +/*! + * @file autopick.c + * @brief 自動拾い機能の実装 / Object Auto-picker/Destroyer + * @date 2014/01/02 + * @author + * Copyright (c) 2002 Mogami\n + *\n + * This software may be copied and distributed for educational, research, and\n + * not for profit purposes provided that this copyright and statement are\n + * included in all such copies.\n + * 2014 Deskull rearranged comment for Doxygen.\n + */ + +#include "autopick/autopick.h" +#include "autopick/autopick-destroyer.h" +#include "autopick/autopick-finder.h" +#include "autopick/autopick-menu-data-table.h" +#include "autopick/autopick-methods-table.h" +#include "core/asking-player.h" +#include "core/disturbance.h" +#include "flavor/flavor-describer.h" +#include "floor/floor-object.h" +#include "inventory/inventory-object.h" +#include "inventory/inventory-slot-types.h" +#include "inventory/player-inventory.h" +#include "object/object-mark-types.h" +#include "object/object-info.h" +#include "system/floor-type-definition.h" +#include "term/screen-processor.h" +#include "view/display-messages.h" + +/* + * Auto-destroy marked item + */ +static void autopick_delayed_alter_aux(player_type *player_ptr, INVENTORY_IDX item) +{ + object_type *o_ptr; + o_ptr = ref_item(player_ptr, item); + + if (o_ptr->k_idx == 0 || !(o_ptr->marked & OM_AUTODESTROY)) return; + + GAME_TEXT o_name[MAX_NLEN]; + describe_flavor(player_ptr, o_name, o_ptr, 0); + if (item >= 0) + { + inven_item_increase(player_ptr, item, -(o_ptr->number)); + inven_item_optimize(player_ptr, item); + } + else + { + delete_object_idx(player_ptr, 0 - item); + } + + msg_format(_("%sを自動破壊します。", "Auto-destroying %s."), o_name); +} + + +/* + * Auto-destroy marked items in inventry and on floor + */ +void autopick_delayed_alter(player_type *owner_ptr) +{ + INVENTORY_IDX item; + + /* + * Scan inventry in reverse order to prevent + * skipping after inven_item_optimize() + */ + for (item = INVEN_TOTAL - 1; item >= 0; item--) + autopick_delayed_alter_aux(owner_ptr, item); + + floor_type *floor_ptr = owner_ptr->current_floor_ptr; + item = floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx; + while (item) + { + OBJECT_IDX next = floor_ptr->o_list[item].next_o_idx; + autopick_delayed_alter_aux(owner_ptr, -item); + item = next; + } +} + + +/* + * Auto-inscription and/or destroy + * + * Auto-destroyer works only on inventory or on floor stack only when + * requested. + */ +void autopick_alter_item(player_type *player_ptr, INVENTORY_IDX item, bool destroy) +{ + object_type *o_ptr; + o_ptr = ref_item(player_ptr, item); + int idx = find_autopick_list(player_ptr, o_ptr); + auto_inscribe_item(player_ptr, o_ptr, idx); + if (destroy && item <= INVEN_PACK) + auto_destroy_item(player_ptr, o_ptr, idx); +} + + +/* + * Automatically pickup/destroy items in this grid. + */ +void autopick_pickup_items(player_type* player_ptr, grid_type *g_ptr) +{ + OBJECT_IDX this_o_idx, next_o_idx = 0; + for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) + { + object_type *o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx]; + next_o_idx = o_ptr->next_o_idx; + int idx = find_autopick_list(player_ptr, o_ptr); + auto_inscribe_item(player_ptr, o_ptr, idx); + bool is_auto_pickup = idx >= 0; + is_auto_pickup &= (autopick_list[idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK)) != 0; + if (!is_auto_pickup) + { + auto_destroy_item(player_ptr, o_ptr, idx); + continue; + } + + disturb(player_ptr, FALSE, FALSE); + if (!check_store_item_to_inventory(player_ptr, o_ptr)) + { + GAME_TEXT o_name[MAX_NLEN]; + describe_flavor(player_ptr, o_name, o_ptr, 0); + msg_format(_("ザックには%sを入れる隙間がない。", "You have no room for %s."), o_name); + o_ptr->marked |= OM_NOMSG; + continue; + } + + if (!(autopick_list[idx].action & DO_QUERY_AUTOPICK)) + { + describe_pickup_item(player_ptr, this_o_idx); + continue; + } + + char out_val[MAX_NLEN + 20]; + GAME_TEXT o_name[MAX_NLEN]; + if (o_ptr->marked & OM_NO_QUERY) + { + continue; + } + + describe_flavor(player_ptr, o_name, o_ptr, 0); + sprintf(out_val, _("%sを拾いますか? ", "Pick up %s? "), o_name); + if (!get_check(out_val)) + { + o_ptr->marked |= OM_NOMSG | OM_NO_QUERY; + continue; + } + + describe_pickup_item(player_ptr, this_o_idx); + } +} diff --git a/src/autopick/autopick.h b/src/autopick/autopick.h new file mode 100644 index 000000000..501517edd --- /dev/null +++ b/src/autopick/autopick.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" +#include "autopick/autopick-util.h" +#include "grid/grid.h" + +extern void autopick_alter_item(player_type *player_ptr, INVENTORY_IDX item, bool destroy); +extern void autopick_delayed_alter(player_type *player_ptr); +extern void autopick_pickup_items(player_type *player_ptr, grid_type *g_ptr); diff --git a/src/avatar.c b/src/avatar.c deleted file mode 100644 index 83b62a91e..000000000 --- a/src/avatar.c +++ /dev/null @@ -1,530 +0,0 @@ -/*! - @file avatar.c - @brief ウルティマ4を参考にした徳のシステムの実装 / Enable an Ultima IV style "avatar" game where you try to achieve perfection in various virtues. - @date 2013/12/23 - @author - Topi Ylinen 1998\n - f1toyl@uta.fi\n - topi.ylinen@noodi.fi\n - \n - Copyright (c) 1989 James E. Wilson, Christopher J. Stuart - This software may be copied and distributed for educational, research, and - not for profit purposes provided that this copyright and statement are - included in all such copies. -*/ - -#include "angband.h" -#include "avatar.h" - -/*! - * 徳の名称 / The names of the virtues - */ -concptr virtue[MAX_VIRTUE] = -{ - _("情", "Compassion"), - _("誉", "Honour"), - _("æ­£", "Justice"), - _("犠", "Sacrifice"), - _("識", "Knowledge"), - _("誠", "Faith"), - _("啓", "Enlightenment"), - _("秘", "Mysticism"), - _("運", "Chance"), - _("然", "Nature"), - _("調", "Harmony"), - _("æ´»", "Vitality"), - _("æ­»", "Unlife"), - _("忍", "Patience"), - _("節", "Temperance"), - _("勤", "Diligence"), - _("勇", "Valour"), - _("個", "Individualism"), -}; - -/*! - * @brief 該当の徳がプレイヤーに指定されているか否かに応じつつ、大小を比較する。 - * @details 徳がない場合は値0として比較する。 - * @param type 比較したい徳のID - * @param num 比較基準値 - * @param tekitou VIRTUE_LARGE = 基準値より大きいか / VIRTUE_SMALL = 基準値より小さいか - * @return 比較の真偽値を返す - * @todo 引数名を直しておく - */ -bool compare_virtue(int type, int num, int tekitou) -{ - int vir; - if (virtue_number(type)) - vir = p_ptr->virtues[virtue_number(type) - 1]; - else - vir = 0; - - switch (tekitou) - { - case VIRTUE_LARGE: - if (vir > num) return TRUE; - else return FALSE; - case VIRTUE_SMALL: - if (vir < num) return TRUE; - else return FALSE; - } - - return FALSE; -} - -/*! - * @brief プレイヤーの指定の徳が何番目のスロットに登録されているかを返す。 / Aux function - * @param type 確認したい徳のID - * @return スロットがあるならばスロットのID(0~7)+1、ない場合は0を返す。 - */ -int virtue_number(int type) -{ - int i; - - /* Search */ - for (i = 0; i < 8; i++) - { - if (p_ptr->vir_types[i] == type) return i + 1; - } - - /* No match */ - return 0; -} - -/*! - * @brief プレイヤーの職業や種族に依存しないランダムな徳を取得する / Aux function - * @param which 確認したい徳のID - * @return なし - */ -static void get_random_virtue(int which) -{ - int type = 0; - - /* Randomly choose a type */ - while (!(type) || virtue_number(type)) - { - switch (randint1(29)) - { - case 1: case 2: case 3: - type = V_SACRIFICE; - break; - case 4: case 5: case 6: - type = V_COMPASSION; - break; - case 7: case 8: case 9: case 10: case 11: case 12: - type = V_VALOUR; - break; - case 13: case 14: case 15: case 16: case 17: - type = V_HONOUR; - break; - case 18: case 19: case 20: case 21: - type = V_JUSTICE; - break; - case 22: case 23: - type = V_TEMPERANCE; - break; - case 24: case 25: - type = V_HARMONY; - break; - case 26: case 27: case 28: - type = V_PATIENCE; - break; - default: - type = V_DILIGENCE; - break; - } - } - - /* Chosen */ - p_ptr->vir_types[which] = (s16b)type; -} - -/*! - * @brief プレイヤーの選んだ魔法領域に応じて対応する徳を返す。 - * @param realm 魔法領域のID - * @return 対応する徳のID - */ -static VIRTUES_IDX get_realm_virtues(REALM_IDX realm) -{ - switch (realm) - { - case REALM_LIFE: - if (virtue_number(V_VITALITY)) return V_TEMPERANCE; - else return V_VITALITY; - case REALM_SORCERY: - if (virtue_number(V_KNOWLEDGE)) return V_ENCHANT; - else return V_KNOWLEDGE; - case REALM_NATURE: - if (virtue_number(V_NATURE)) return V_HARMONY; - else return V_NATURE; - case REALM_CHAOS: - if (virtue_number(V_CHANCE)) return V_INDIVIDUALISM; - else return V_CHANCE; - case REALM_DEATH: - return V_UNLIFE; - case REALM_TRUMP: - return V_KNOWLEDGE; - case REALM_ARCANE: - return 0; - case REALM_CRAFT: - if (virtue_number(V_ENCHANT)) return V_INDIVIDUALISM; - else return V_ENCHANT; - case REALM_DAEMON: - if (virtue_number(V_JUSTICE)) return V_FAITH; - else return V_JUSTICE; - case REALM_CRUSADE: - if (virtue_number(V_JUSTICE)) return V_HONOUR; - else return V_JUSTICE; - case REALM_HEX: - if (virtue_number(V_COMPASSION)) return V_JUSTICE; - else return V_COMPASSION; - }; - - return 0; -} - - -/*! - * @brief 作成中のプレイヤーキャラクターに徳8種類を与える。 / Select virtues & reset values for a new character - * @details 職業に応じて1~4種が固定、種族に応じて1種類が与えられ、後は重複なくランダムに選択される。 - * @return なし - */ -void get_virtues(void) -{ - int i = 0, j = 0; - s16b tmp_vir; - - /* Reset */ - for (i = 0; i < 8; i++) - { - p_ptr->virtues[i] = 0; - p_ptr->vir_types[i] = 0; - } - - i = 0; - - /* Get pre-defined types */ - /* 1 or more virtues based on class */ - switch (p_ptr->pclass) - { - case CLASS_WARRIOR: - case CLASS_SAMURAI: - p_ptr->vir_types[i++] = V_VALOUR; - p_ptr->vir_types[i++] = V_HONOUR; - break; - case CLASS_MAGE: - p_ptr->vir_types[i++] = V_KNOWLEDGE; - p_ptr->vir_types[i++] = V_ENCHANT; - break; - case CLASS_PRIEST: - p_ptr->vir_types[i++] = V_FAITH; - p_ptr->vir_types[i++] = V_TEMPERANCE; - break; - case CLASS_ROGUE: - case CLASS_SNIPER: - p_ptr->vir_types[i++] = V_HONOUR; - break; - case CLASS_RANGER: - case CLASS_ARCHER: - p_ptr->vir_types[i++] = V_NATURE; - p_ptr->vir_types[i++] = V_TEMPERANCE; - break; - case CLASS_PALADIN: - p_ptr->vir_types[i++] = V_JUSTICE; - p_ptr->vir_types[i++] = V_VALOUR; - p_ptr->vir_types[i++] = V_HONOUR; - p_ptr->vir_types[i++] = V_FAITH; - break; - case CLASS_WARRIOR_MAGE: - case CLASS_RED_MAGE: - p_ptr->vir_types[i++] = V_ENCHANT; - p_ptr->vir_types[i++] = V_VALOUR; - break; - case CLASS_CHAOS_WARRIOR: - p_ptr->vir_types[i++] = V_CHANCE; - p_ptr->vir_types[i++] = V_INDIVIDUALISM; - break; - case CLASS_MONK: - case CLASS_FORCETRAINER: - p_ptr->vir_types[i++] = V_FAITH; - p_ptr->vir_types[i++] = V_HARMONY; - p_ptr->vir_types[i++] = V_TEMPERANCE; - p_ptr->vir_types[i++] = V_PATIENCE; - break; - case CLASS_MINDCRAFTER: - case CLASS_MIRROR_MASTER: - p_ptr->vir_types[i++] = V_HARMONY; - p_ptr->vir_types[i++] = V_ENLIGHTEN; - p_ptr->vir_types[i++] = V_PATIENCE; - break; - case CLASS_HIGH_MAGE: - case CLASS_SORCERER: - p_ptr->vir_types[i++] = V_ENLIGHTEN; - p_ptr->vir_types[i++] = V_ENCHANT; - p_ptr->vir_types[i++] = V_KNOWLEDGE; - break; - case CLASS_TOURIST: - p_ptr->vir_types[i++] = V_ENLIGHTEN; - p_ptr->vir_types[i++] = V_CHANCE; - break; - case CLASS_IMITATOR: - p_ptr->vir_types[i++] = V_CHANCE; - break; - case CLASS_BLUE_MAGE: - p_ptr->vir_types[i++] = V_CHANCE; - p_ptr->vir_types[i++] = V_KNOWLEDGE; - break; - case CLASS_BEASTMASTER: - p_ptr->vir_types[i++] = V_NATURE; - p_ptr->vir_types[i++] = V_CHANCE; - p_ptr->vir_types[i++] = V_VITALITY; - break; - case CLASS_MAGIC_EATER: - p_ptr->vir_types[i++] = V_ENCHANT; - p_ptr->vir_types[i++] = V_KNOWLEDGE; - break; - case CLASS_BARD: - p_ptr->vir_types[i++] = V_HARMONY; - p_ptr->vir_types[i++] = V_COMPASSION; - break; - case CLASS_CAVALRY: - p_ptr->vir_types[i++] = V_VALOUR; - p_ptr->vir_types[i++] = V_HARMONY; - break; - case CLASS_BERSERKER: - p_ptr->vir_types[i++] = V_VALOUR; - p_ptr->vir_types[i++] = V_INDIVIDUALISM; - break; - case CLASS_SMITH: - p_ptr->vir_types[i++] = V_HONOUR; - p_ptr->vir_types[i++] = V_KNOWLEDGE; - break; - case CLASS_NINJA: - p_ptr->vir_types[i++] = V_PATIENCE; - p_ptr->vir_types[i++] = V_KNOWLEDGE; - p_ptr->vir_types[i++] = V_FAITH; - p_ptr->vir_types[i++] = V_UNLIFE; - break; - }; - - /* Get one virtue based on race */ - switch (p_ptr->prace) - { - case RACE_HUMAN: case RACE_HALF_ELF: case RACE_DUNADAN: - p_ptr->vir_types[i++] = V_INDIVIDUALISM; - break; - case RACE_ELF: case RACE_SPRITE: case RACE_ENT: - p_ptr->vir_types[i++] = V_NATURE; - break; - case RACE_HOBBIT: case RACE_HALF_OGRE: - p_ptr->vir_types[i++] = V_TEMPERANCE; - break; - case RACE_DWARF: case RACE_KLACKON: case RACE_ANDROID: - p_ptr->vir_types[i++] = V_DILIGENCE; - break; - case RACE_GNOME: case RACE_CYCLOPS: - p_ptr->vir_types[i++] = V_KNOWLEDGE; - break; - case RACE_HALF_ORC: case RACE_AMBERITE: case RACE_KOBOLD: - p_ptr->vir_types[i++] = V_HONOUR; - break; - case RACE_HALF_TROLL: case RACE_BARBARIAN: - p_ptr->vir_types[i++] = V_VALOUR; - break; - case RACE_HIGH_ELF: case RACE_KUTAR: - p_ptr->vir_types[i++] = V_VITALITY; - break; - case RACE_HALF_GIANT: case RACE_GOLEM: case RACE_ANGEL: case RACE_DEMON: - p_ptr->vir_types[i++] = V_JUSTICE; - break; - case RACE_HALF_TITAN: - p_ptr->vir_types[i++] = V_HARMONY; - break; - case RACE_YEEK: - p_ptr->vir_types[i++] = V_SACRIFICE; - break; - case RACE_MIND_FLAYER: - p_ptr->vir_types[i++] = V_ENLIGHTEN; - break; - case RACE_DARK_ELF: case RACE_DRACONIAN: case RACE_S_FAIRY: - p_ptr->vir_types[i++] = V_ENCHANT; - break; - case RACE_NIBELUNG: - p_ptr->vir_types[i++] = V_PATIENCE; - break; - case RACE_IMP: - p_ptr->vir_types[i++] = V_FAITH; - break; - case RACE_ZOMBIE: case RACE_SKELETON: - case RACE_VAMPIRE: case RACE_SPECTRE: - p_ptr->vir_types[i++] = V_UNLIFE; - break; - case RACE_BEASTMAN: - p_ptr->vir_types[i++] = V_CHANCE; - break; - } - - /* Get a virtue for realms */ - if (p_ptr->realm1) - { - tmp_vir = get_realm_virtues(p_ptr->realm1); - if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir; - } - if (p_ptr->realm2) - { - tmp_vir = get_realm_virtues(p_ptr->realm2); - if (tmp_vir) p_ptr->vir_types[i++] = tmp_vir; - } - - /* Eliminate doubles */ - for (i = 0; i < 8; i++) - { - for (j = i + 1; j < 8; j++) - { - if ((p_ptr->vir_types[j] != 0) && (p_ptr->vir_types[j] == p_ptr->vir_types[i])) - p_ptr->vir_types[j] = 0; - } - } - - /* Fill in the blanks */ - for (i = 0; i < 8; i++) - { - if (p_ptr->vir_types[i] == 0) get_random_virtue(i); - } -} - -/*! - * @brief 対応する徳をプレイヤーがスロットに登録している場合に加減を行う。 - * @details 範囲は-125~125、基本的に絶対値が大きいほど絶対値が上がり辛くなる。 - * @param virtue 徳のID - * @param amount 加減量 - * @return なし - */ -void chg_virtue(int virtue_id, int amount) -{ - int i = 0; - - for (i = 0; i < 8; i++) - { - if (p_ptr->vir_types[i] == virtue_id) - { - if (amount > 0) - { - if ((amount + p_ptr->virtues[i] > 50) && one_in_(2)) - { - p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 50); - return; - } - if ((amount + p_ptr->virtues[i] > 80) && one_in_(2)) - { - p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 80); - return; - } - if ((amount + p_ptr->virtues[i] > 100) && one_in_(2)) - { - p_ptr->virtues[i] = MAX(p_ptr->virtues[i], 100); - return; - } - if (amount + p_ptr->virtues[i] > 125) - p_ptr->virtues[i] = 125; - else - p_ptr->virtues[i] = p_ptr->virtues[i] + amount; - } - else - { - if ((amount + p_ptr->virtues[i] < -50) && one_in_(2)) - { - p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -50); - return; - } - if ((amount + p_ptr->virtues[i] < -80) && one_in_(2)) - { - p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -80); - return; - } - if ((amount + p_ptr->virtues[i] < -100) && one_in_(2)) - { - p_ptr->virtues[i] = MIN(p_ptr->virtues[i], -100); - return; - } - if (amount + p_ptr->virtues[i] < -125) - p_ptr->virtues[i] = -125; - else - p_ptr->virtues[i] = p_ptr->virtues[i] + amount; - } - p_ptr->update |= (PU_BONUS); - return; - } - } -} - -/*! - * @brief 対応する徳をプレイヤーがスロットに登録している場合に固定値をセットする。 - * @param virtue 徳のID - * @param amount セットしたい値。 - * @return なし - */ -void set_virtue(int virtue_id, int amount) -{ - int i = 0; - - for (i = 0; i < 8; i++) - { - if (p_ptr->vir_types[i] == virtue_id) - { - p_ptr->virtues[i] = (s16b)amount; - return; - } - } -} - -/*! - * @brief 徳のダンプ表示を行う。 - * @param OutFile ファイルポインタ。 - * @return なし - */ -void dump_virtues(FILE *OutFile) -{ - int v_nr = 0; - - if (!OutFile) return; - - for (v_nr = 0; v_nr < 8; v_nr++) - { - GAME_TEXT vir_name [20]; - int tester = p_ptr->virtues[v_nr]; - - strcpy(vir_name, virtue[(p_ptr->vir_types[v_nr])-1]); - - if (p_ptr->vir_types[v_nr] == 0 || p_ptr->vir_types[v_nr] > MAX_VIRTUE) - fprintf(OutFile, _("おっと。%sの情報なし。", "Oops. No info about %s."), vir_name); - - else if (tester < -100) - fprintf(OutFile, _("[%s]の対極", "You are the polar opposite of %s."), vir_name); - else if (tester < -80) - fprintf(OutFile, _("[%s]の大敵", "You are an arch-enemy of %s."), vir_name); - else if (tester < -60) - fprintf(OutFile, _("[%s]の強敵", "You are a bitter enemy of %s."), vir_name); - else if (tester < -40) - fprintf(OutFile, _("[%s]の敵", "You are an enemy of %s."), vir_name); - else if (tester < -20) - fprintf(OutFile, _("[%s]の罪者", "You have sinned against %s."), vir_name); - else if (tester < 0) - fprintf(OutFile, _("[%s]の迷道者", "You have strayed from the path of %s."), vir_name); - else if (tester == 0) - fprintf(OutFile,_("[%s]の中立者", "You are neutral to %s."), vir_name); - else if (tester < 20) - fprintf(OutFile,_("[%s]の小徳者", "You are somewhat virtuous in %s."), vir_name); - else if (tester < 40) - fprintf(OutFile,_("[%s]の中徳者", "You are virtuous in %s."), vir_name); - else if (tester < 60) - fprintf(OutFile,_("[%s]の高徳者", "You are very virtuous in %s."), vir_name); - else if (tester < 80) - fprintf(OutFile,_("[%s]の覇者", "You are a champion of %s."), vir_name); - else if (tester < 100) - fprintf(OutFile,_("[%s]の偉大な覇者", "You are a great champion of %s."), vir_name); - else - fprintf(OutFile,_("[%s]の具現者", "You are the living embodiment of %s."), vir_name); - - fprintf(OutFile, "\n"); - } -} diff --git a/src/avatar.h b/src/avatar.h deleted file mode 100644 index bbba82443..000000000 --- a/src/avatar.h +++ /dev/null @@ -1,8 +0,0 @@ -/* avatar.c */ -extern bool compare_virtue(int type, int num, int tekitou); -extern int virtue_number(int type); -extern concptr virtue[MAX_VIRTUE]; -extern void get_virtues(void); -extern void chg_virtue(int virtue, int amount); -extern void set_virtue(int virtue, int amount); -extern void dump_virtues(FILE * OutFile); diff --git a/src/birth.c b/src/birth.c deleted file mode 100644 index 445d8a69f..000000000 --- a/src/birth.c +++ /dev/null @@ -1,4709 +0,0 @@ -/*! - * @file birth.c - * @brief プレイヤーの作成を行う / Create a player character - * @date 2013/12/28 - * @author - * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n - *\n - * This software may be copied and distributed for educational, research,\n - * and not for profit purposes provided that this copyright and statement\n - * are included in all such copies. Other copyrights may also apply.\n - * 2013 Deskull Doxygen向けのコメント整理\n - */ - -#include "angband.h" -#include "avatar.h" -#include "history.h" -#include "monsterrace-hook.h" -#include "store.h" -#include "patron.h" -#include "quest.h" -#include "player-status.h" -#include "spells.h" -#include "spells-status.h" -#include "wild.h" - -/*! - * オートローラーの内容を描画する間隔 / - * How often the autoroller will update the display and pause - * to check for user interuptions. - * Bigger values will make the autoroller faster, but slower - * system may have problems because the user can't stop the - * autoroller for this number of rolls. - */ -#define AUTOROLLER_STEP 5431L - -#if 0 -/*! - * オートローラを1回まわすごとに1/10秒のウェイトをかけるマクロ定義 / Define this to cut down processor use while autorolling - */ -#define AUTOROLLER_DELAY -#endif - -/*! - * ランダムクエストのモンスターを確定するために試行する回数 / Maximum number of tries for selection of a proper quest monster - */ -#define MAX_TRIES 100 - -/* 選択可能な職業の最大数 */ -#define MAX_CLASS_CHOICE MAX_CLASS - - - -/*! 種族の解説メッセージテーブル */ -static concptr race_jouhou[MAX_RACES] = -{ -#ifdef JP -"人間は基本となるキャラクタです。他の全ての種族は人間と比較されます。人間はどんな職業に就くこともでき、どの職業でも平均的にこなせます。人間は寿命が短いため、レベル上昇が他のどんな種族よりも早くなる傾向があります。また、特別な修正や特性は持っていません。", - -"ハーフエルフは人間より賢いですが、強くはありません。彼らは探索, 解除, 魔法防御, 隠密行動, 射撃, そして魔法道具使用でわずかに優れています。しかし武器の取り扱いはそう得意ではありません。ハーフエルフはどの職業に就くこともでき、生まれつきの特性はありません。", - -"エルフは人間より良い魔法使いになれますが、戦闘は苦手です。彼らは人間やハーフエルフよりも頭が良く、高い賢さを持っています。エルフは探索, 解除, 知覚, 隠密行動, 射撃, そして魔法道具使用で優れていますが、武器の扱いは得意ではありません。彼らは生まれつき光に対する耐性を持っています。", - -"ホビット、またはハーフリングは弓や投擲に長け、魔法防御も優れています。また、探索, 解除, 知覚, そして隠密行動でもとても良い能力を示します。そのため、彼らは優れた盗賊となることができます(しかし、「忍びの者」と呼ばれることを好みます)。ホビットは人間より遥かに貧弱で、戦士としてはてんでダメです。彼らはかなり良い赤外線視力を持っており、温血動物を離れた場所から見つけることができます。彼らは経験値を保持する力が強く、経験値吸収攻撃に対して耐性を持っています。", - -"ノームはドワーフより小さいですが、ホビットよりは大きい種族です。彼らはホビット同様地表の洞穴のような家に住んでいます。ノームはとても良い魔法防御を持ち、探索, 解除, 知覚, 隠密行動でも優れています。彼らは人間より低い腕力を持ち、武器を持っての戦闘は苦手です。ノームはかなり良い赤外線視力を持っており、温血動物を離れた場所から見つけることができます。ノームは生まれつき麻痺に対する耐性を持っています。", - -"ドワーフは頑固な坑夫であり、伝説の戦士です。彼らは人間にくらべ強くタフですが、知能は劣ります。しかし、長命ゆえに彼らは非常に賢いです。彼らは良い魔法防御を持ち、探索, 知覚, 戦闘, 射撃では優れています。彼らは一つ大きな欠点を持っています。ドワーフの隠密行動は絶望的に悪いです。彼らは決して盲目にはなりません。", - -"ハーフオークはよい戦士になれますが、魔法は期待できません。彼らはドワーフと同じくらい隠密行動が悪く、また探索や解除, 知覚もひどいです。ハーフオークは醜く、店での買い物ではより高い金額を要求されがちです。彼らは地下に住むことを好むため、ハーフオークは暗闇に対する耐性を備えています。", - -"ハーフトロルは信じられないほど強く、他の大部分の種族より大きなHPを持ちます。彼らは不運にもとても愚かです。彼らの探索, 解除, 知覚, 隠密行動は悪く、その外見はハーフオークがしかめっ面をするほど醜悪です。ハーフトロルは腕力が下がることがありません。レベルが上がると、彼らは再生能力を手にいれ、戦士ならばさらに遅消化能力も獲得します。", - -"アンバライトは多くのアドバンテージを授けられた、うわさによれば不死の種族です。彼らは知覚, 戦闘, 射撃に優れており、他の面でもかなり熟練しています。事実上あらゆるものを見てきており、新鮮なものはほとんどないため、彼らの成長は他のどの種族より遅いものです。彼らはとてもタフで頑強であり、彼らの耐久力が下がることはありません。また、怪我をすぐに治す再生能力があります。", - -"ハイエルフは世界の始まりから存在する不死の種族です。彼らは全てのスキルに熟達しており、強く、知的で非常に人気があります - 誰もが彼らのことを好いています。ハイエルフは見えないものを見ることができ、普通のエルフ同様光に対する耐性を持っています。しかし、彼らにとって未知のものはほとんどなく、経験を得ることは大変に困難です。", - -"野蛮人は北方から来た頑強な種族です。彼らは激しく戦い、彼らの激怒は世界中で恐れられています。戦闘が彼らの人生です。彼らは恐れを知らず、ハーフトロルよりもすぐに狂暴に戦闘に入ってしまうことを学びます。しかし、野蛮人は魔法を疑っており、そのため魔法の道具を使うことはかなり大変なこととなっています。", - -"ハーフオーガはハーフオークに似ていますが、それだけではありません。彼らは大きく、邪悪で愚かです。戦士としては彼らは必要な資質を全て持っており、また魔法使いになることさえできます。結局、彼らはオーガ・メイジに関係があり、レベルが十分に上がったら彼らから罠のルーンをセットするスキルを学ぶのです。ハーフオークのように、彼らは暗闇に対する耐性を持ち、ハーフトロル同様に腕力が下がることはありません。", - -"半巨人は大変力強いのですが、呪文を唱えられるほど利口ではありません。彼らはよい戦闘能力を持ちますが、それ以外のことは苦手です。彼らの厚い皮膚は破片に対する耐性を持ちます。また、ハーフオーガやハーフトロル同様腕力を下げられることがありません。", - -"巨大なタイタンと人間の子孫であり、この強大な生物は他のほぼ全ての種族よりはるかに勝っています。彼らは多種族にみられるような魅力的な特殊能力は持っていませんが、その大変大きなHPはそれを補ってあまりあります。半タイタンはそこそこのスキルを持っていますが、その巨大さゆえに罠の解除やこっそり歩くことは困難です。法と秩序を愛する彼らは、カオスに対する耐性を持っています。", - -"一つ目ではありますが、サイクロプスは多くの二つの目を持つ生物以上に見ることができます。サイクロプスは非常に力強いのですが、知的であるとはちょっと言えません。彼らに比べれば、ハーフトロルの方がハンサムに見えるということは言うまでもありません。サイクロプスは戦闘, 射撃に優れていますが、その他の大部分のスキルは苦手です。サイクロプスは音に対する耐性を持っています。", - -"イークは最も哀れな生物の一つであり、並のモンスターであっても不注意なイークならば徹底的に打ちのめせるほど肉体的には強くありませんが、彼らはかなり知的でいくらか賢い生物です。イークは戦闘スキルは苦手ですが、他の分野では優れています。彼らの皮膚は、時間とともに酸への耐性を増していき、レベルが十分に上がれば完全に免疫を持つようになります。", - -"クラッコンは奇怪な半知的の昆虫型生物です。彼らはすばらしい戦士になれますが、精神的な能力はひどく制限されています。彼らは探索を除けば大部分のスキルをそこそこにこなします。クラッコンは決して混乱させられることがなく、レベルが上がるごとに速くなります。", - -"コボルドは弱いゴブリンの種族です。彼らは毒を持った武器を好み、毒矢(無制限に供給されます)を投げる能力を身につけることができます。コボルドはそこそこの戦士になれますが、その他のスキルは軒並み悪いです。彼らは生まれつき毒に対する耐性を持っています。", - -"嫌われ、迫害されてきた小人族です。彼らは大抵のスキルをそつなくこなします。洞穴居住者である彼らは、暗闇に悩まされることはありませんし、生まれつき持っている魔法のアイテムに対する嗜好のため、彼らは装備による魔法のボーナスを奪う効果に耐性を持っています。", - -"闇の、洞穴に住む種族であるダークエルフは魔法の知識に対する長い伝統を持っています。ダークエルフは魔法の道具をうまく使うことができ、他の多くの種族より簡単に呪文を唱えられるだけの知能を持っています。その鋭い視覚によって、彼らはハイエルフ同様見えないものをみる能力を学びますが、それはある程度レベルが上がったときです。ダークエルフは暗闇に対する耐性を持っています。", - -"ドラゴンのような特性を持った人間型種族です。彼らはレベルが上がるにつれ、新しい元素への耐性を手にいれます。ドラコニアンは優れた能力値を持ってゲームを開始でき、大抵のスキルをうまくこなせます。その翼で、彼らは簡単に落とし穴や溶岩、水を無傷で飛び越えることができます。", - -"秘密主義の神秘的な古代種族です。彼らの文明はこの惑星上の何よりも古いかもしれません。その肉体的資質は決して誉められたものではありませんが、彼らの知能と賢さはマインドフレアを他のどんな種族よりも強力な魔法使いにします。マインドフレアの知能と賢さは下がることがなく、レベルが上がれば見えないものをみる能力、テレパシー能力を獲得します。", - -"地獄からやってきた悪魔的な生物です。彼らは他の種族から毛嫌いされていますが、大抵の職業をかなりうまくこなすことができます。インプは生まれつき火に耐性を持っており、レベルが上がれば見えないものを見る能力を獲得します。", - -"ゴーレムは泥のような生命のない材料からつくられ、生命を吹き込まれた人工的な生物です。彼らには思考というものがほとんどなく、そのため魔法に依存する職業では役立たずです。しかし戦士としては大変にタフです。彼らは毒に耐性を持ち、見えないものを見ることができ、さらに麻痺知らずです。レベルが上がれば、彼らは生命力吸収攻撃に耐性を持つようになります。ゴーレムは通常の食物からはほとんど栄養を摂取できませんが、代わりに魔法棒や杖から魔力を吸収して動力源にする事ができます。また、その頑丈な身体のため、ACにボーナスを得ることができ、さらに決して気絶させられることがありません。", - -"スケルトンには2つのタイプが存在します。普通の戦士タイプと、リッチと呼ばれる呪文を使うスケルトンです。アンデッドである彼らは、毒や生命力吸収攻撃を心配する必要はありません。彼らは物体を知覚するのに眼を利用していないため、見えない物に騙されません。彼らの骨はとがった破片のようなものに耐性を持ち、レベルが上がれば冷気に対する耐性を獲得します。薬や食物の持つ効果はスケルトンの胃(存在しませんが)を通過することなくその力を発揮しますが、薬や食物自体は彼の顎を通り抜けて落ちてしまい、栄養を吸収することはできません。その代わりに魔法棒や杖から魔力を吸収してエネルギー源にする事ができます。", - -"ゾンビはアンデッドであり、生命力吸収攻撃に耐性を持ち、スケルトンのようにレベルが上がれば冷気の耐性を獲得します。また、毒に耐性を持ち見えないものを見ることができます。(スケルトンとは違い)切る攻撃には弱いですが、地獄に対する耐性を持っています。ゴーレムのように、彼らは食物からほとんど栄養を摂取できませんが、代わりに魔法棒や杖から魔力を吸収してエネルギー源にする事ができます。", - -"強力なアンデッドの一種である吸血鬼は、畏敬の念を呼び起こす外見をしています。アンデッドの例にもれず、彼らも生命力を吸収されることがなく、地獄に対する耐性を持っています。また、冷気と毒に対する耐性も備えています。しかし、新鮮な血液に常に飢えており、それは近くにいる生物から血液を吸うことによってのみ満たされます。この強力な生物は深刻な弱点を持っています。太陽光線(や光源)は彼らの破滅を意味します。幸運にも、吸血鬼はその身体から「暗黒の光」のオーラを放出しています。一方、暗闇は彼らをより強力にするものです。", - -"幽霊は強力なアンデッドの一種です。彼らは不気味な緑色の光に包まれています。半物質的な存在である彼らは、壁を通り抜けることができますが、そのときには壁の密度によって傷つけられてしまいます。他のアンデッド同様、彼らも生命力を吸収されることがなく、見えないものを見ることができ、毒と冷気に対して耐性を備え、さらに地獄に対する耐性も持っています。レベルが十分に上がると彼らはテレパシーを獲得します。幽霊は卓越した魔法使いになることができますが、その身体的特性は非常に貧弱です。彼らは食物からほとんど栄養を摂取できませんが、代わりに魔法棒や杖から魔力を吸収してエネルギー源にする事ができます。", - -"妖精は非常に小さいです。彼らは小さな翼を持ち、罠や危険な地形を飛び越えることができます。彼らは日光を大変好み、光に対する耐性を持っています。身体的にはもっとも貧弱な種族の一つですが、妖精は魔法の面で大変な才能を持っており、非常に熟練した魔法使いになることができます。高レベルではより速く飛ぶことができるようになります。", - -"この種族はカオスによってつくられた冒涜的で嫌悪される存在です。彼らは独立した種族ではなく、人間型種族、大抵は人間がカオスによって歪められた存在、もしくは人間と獣の悪夢のような交配種です。全ての獣人はカオスに盲従しており、そのため混乱と音に対して耐性を備えていますが、純粋なログルスはまだ彼らに対し効果を持っています。獣人は混沌を好み、それは彼らをさらに歪めます。獣人は突然変異を起こしやすい性質を持っています。彼らがつくられたとき、ランダムな変異を受けます。その後、レベルが上がるごとに違う変異を受ける可能性があります。", - -"エントは非常に強く、賢いですが、その巨大さゆえに罠の解除やこっそりと歩くことは苦手です。成長するにつれて腕力や耐久力が上がりますが、器用さは下がっていきます。彼らには大きな欠点があり、炎によって通常よりも大きなダメージを受けてしまいます。彼らは食物からほとんど栄養を摂取できませんが、代わりに薬等から水分を摂取する事で活動できます。", - -"天使の上位種であるアルコンは、全てのスキルに熟達しており、強くて賢く、非常に人気があります。彼らは目に見えないものを見ることができ、その翼で罠や危険な地形を飛び越えることができます。しかし、非常に成長が遅いという欠点もあります。", - -"悪魔の上位種であるバルログは、強く、知的で、またタフでもあります。しかし、彼らは神を信じようとはせず、プリーストには全く向いていません。炎と地獄、経験値吸収への耐性を持っており、レベルが上がれば見えないものを見る能力を獲得します。また、地獄や火炎のブレスを吐くこともできます。彼等はほとんどの技能で優れていますが、静かに歩くことは苦手です。彼らは食物からほとんど栄養を摂取できませんが、人間タイプを生贄にする事で精力を回復する事ができます。", - -"ドゥナダンは西方から来た屈強な種族です。このいにしえの種族は全ての領域において人間の能力を凌駕し、特に耐久力に関してはそれが顕著です。しかしながらこの種族は全てに卓越していることが災いして、この世界には新しい経験といったものがほとんどなく、レベルを上げることが非常に困難です。彼らはとてもタフで頑強であり、彼らの耐久力が下がることはありません。", - -"影フェアリーは人間よりやや大きい妖精族で、翼を持ち、罠や危険な地形を飛び越えることができます。しかし、彼らは日光を嫌い、閃光によって通常よりも大きなダメージを受けてしまいます。肉体的には非常に貧弱ですが、魔法の面では優れた能力を持っています。彼らにはすばらしい長所が一つあり、モンスターの反感をかうような強力なアイテムを装備してもモンスターを怒らせることがありません。ただしその場合でも隠密行動能力が下がり、また、自分自身の性格によって反感をかっている場合には効果がありません。", - -"クターとしている無表情の謎の生物です。彼らは外見がかわいらしいため、魅力が高いです。彼らは混乱しません。なぜなら、混乱してもクターとしているため変わりないからです。しかも、そのクターとしている外見から敵に見つかりにくいです。しかし、彼らは注意力が少ないため探索や知覚能力は悪いです。彼らはレベルが上がると横に伸びてACを上げる技を覚えますが、伸びている間は魔法防御能力は低くなってしまいます。", - -"アンドロイドは機械の身体を持つ人工的な存在です。魔法をうまく使うことはできませんが、戦士としては非常に優れています。彼らは他の種族のように経験値を得て成長するということはありません。身体に身につける装備によって成長します。ただし、指輪、アミュレット、光源は成長に影響しません。彼らは毒の耐性を持ち、麻痺知らずで、生命力を吸収されることがありません。また、身体が頑丈なのでACにボーナスを得ます。しかし身体のいたるところに電子回路が組み込まれているため、電撃によって通常よりも大きなダメージを受けてしまいます。彼らは食物からほとんど動力を得られませんが、油を補給する事で動力源を得る事ができます。", - -"マーフォーク実装中", - -#else - -"The human is the base character. All other races are compared to them. Humans can choose any class and are average at everything. Humans tend to go up levels faster than most other races because of their shorter life spans. No racial adjustments or intrinsics occur to characters choosing human.", - -"Half-elves tend to be smarter and faster than humans, but not as strong. Half-elves are slightly better at searching, disarming, saving throws, stealth, bows, and magic, but they are not as good at hand weapons. Half-elves may choose any class and do not receive any intrinsic abilities.", - -"Elves are better magicians then humans, but not as good at fighting. They tend to be smarter and faster than either humans or half-elves and also have better wisdom. Elves are better at searching, disarming, perception, stealth, bows, and magic, but they are not as good at hand weapons. They resist light effects intrinsically.", - -"Hobbits, or Halflings, are very good at bows, throwing, and have good saving throws. They also are very good at searching, disarming, perception, and stealth; so they make excellent rogues, but prefer to be called burglars. They are much weaker than humans, and no good at melee fighting. Halflings have fair infravision, so they can detect warm creatures at a distance. They have a strong hold on their life force, and are thus intrinsically resistant to life draining.", - -"Gnomes are smaller than dwarves but larger than Halflings. They, like the hobbits, live in the earth in burrow-like homes. Gnomes make excellent mages, and have very good saving throws. They are good at searching, disarming, perception, and stealth. They have lower strength than humans so they are not very good at fighting with hand weapons. Gnomes have fair infra-vision, so they can detect warm-blooded creatures at a distance. Gnomes are intrinsically protected against paralysis.", - -"Dwarves are the headstrong miners and fighters of legend. Dwarves tend to be stronger and tougher but slower and less intelligent than humans. Because they are so headstrong and are somewhat wise, they resist spells which are cast on them. They are very good at searching, perception, fighting, and bows. Dwarves have a miserable stealth. They can never be blinded.", - -"Half-orcs make excellent warriors, but are terrible at magic. They are as bad as dwarves at stealth, and horrible at searching, disarming, and perception. Half-orcs are quite ugly, and tend to pay more for goods in town. Because of their preference to living underground to on the surface, half-orcs resist darkness attacks.", - -"Half-Trolls are incredibly strong, and have more hit points than most other races. They are also very stupid and slow. They are bad at searching, disarming, perception, and stealth. They are so ugly that a Half-Orc grimaces in their presence. They also happen to be fun to run... Half-trolls always have their strength sustained. At higher levels, Half-Trolls regenerate wounds automatically, and if he or her is warrior slowly.", - -"The Amberites are a reputedly immortal race, who are endowed with numerous advantages in addition to their longevity. They are very tough and their constitution cannot be reduced, and their ability to heal wounds far surpasses that of any other race. Having seen virtually everything, very little is new to them, and they gain levels much slower than the other races.", - -"High-elves are a race of immortal beings dating from the beginning of time. They are masters of all skills, and are strong and intelligent, although their wisdom is sometimes suspect. High-elves begin their lives able to see the unseen, and resist light effects just like regular elves. However, there are few things that they have not seen already, and experience is very hard for them to gain.", - -"Barbarians are hardy men of the north. They are fierce in combat, and their wrath is feared throughout the world. Combat is their life: they feel no fear, and they learn to enter battle frenzy at will even sooner than half-trolls. Barbarians are, however, suspicious of magic, which makes magic devices fairly hard for them to use. ", - -"Half-Ogres are like Half-Orcs, only more so. They are big, bad, and stupid. For warriors, they have all the necessary attributes, and they can even become wizards: after all, they are related to Ogre Magi, from whom they have learned the skill of setting trapped runes once their level is high enough. Like Half-Orcs, they resist darkness, and like Half-Trolls, they have their strength sustained.", - -"Half-Giants limited intelligence makes it difficult for them to become full spellcasters, but with their huge strength they make excellent warriors. Their thick skin makes them resistant to shards, and like Half-Ogres and Half-Trolls, they have their strength sustained.", - -"Half-mortal descendants of the mighty titans, these immensely powerful creatures put almost any other race to shame. They may lack the fascinating special powers of certain other races, but their enhanced attributes more than make up for that. They learn to estimate the strengths of their foes, and their love for law and order makes them resistant to the effects of Chaos.", - -"With but one eye, a Cyclops can see more than many with two eyes. They are headstrong, and loud noises bother them very little. They are not quite qualified for the magic using professions, but as a certain Mr. Ulysses can testify, their accuracy with thrown rocks can be deadly...", - -"Yeeks are among the most pathetic creatures. Fortunately, their horrible screams can scare away less confident foes, and their skin becomes more and more resistant to acid, as they gain experience. But having said that, even a mediocre monster can wipe the proverbial floor with an unwary Yeek.", - -"Klackons are bizarre semi-intelligent ant-like insectoid creatures. They make great fighters, but their mental abilities are severely limited. Obedient and well-ordered, they can never be confused. They are also very nimble, and become faster as they advance levels. They are also very acidic, inherently resisting acid, and capable of spitting acid at higher levels. ", - -"Kobolds are a weak goblin race. They love poisoned weapons, and can learn to throw poisoned darts (of which they carry an unlimited supply). They are also inherently resistant to poison, although they are not one of the more powerful races.", - -"The hated and persecuted race of nocturnal dwarves, these cavedwellers are not much bothered by darkness. Their natural inclination to magical items has made them immune to effects which could drain away magical energy.", - -"Another dark, cavedwelling race, likewise unhampered by darkness attacks, the Dark Elves have a long tradition and knowledge of magic. They have an inherent magic missile attack available to them at a low level. With their keen sight, they also learn to see invisible things as their relatives High-Elves do, but at a higher level.", - -"A humanoid race with dragon-like attributes. As they advance levels, they gain new elemental resistances (up to Poison Resistance), and they also have a breath weapon, which becomes more powerful with experience. The exact type of the breath weapon depends on the Draconian's class and level. With their wings, they can easily escape any pit trap unharmed.", - -"A secretive and mysterious ancient race. Their civilization may well be older than any other on our planet, and their intelligence and wisdom are naturally sustained, and are so great that they enable Mind Flayers to become more powerful spellcasters than any other race, even if their physical attributes are a good deal less admirable. As they advance levels, they gain the powers of See Invisible and Telepathy.", - -"A demon-creature from the nether-world, naturally resistant to fire attacks, and capable of learning fire bolt and fire ball attacks. They are little loved by other races, but can perform fairly well in most professions. As they advance levels, they gain the powers of See Invisible.", - -"A Golem is an artificial creature, built from a lifeless raw material like clay, and awakened to life. They are nearly mindless, making them useless for professions which rely on magic, but as warriors they are very tough. They are resistant to poison, they can see invisible things, and move freely. At higher levels, they also become resistant to attacks which threaten to drain away their experience. Golems gain very little nutrition from ordinary food, but can absorb mana from staves and wands as their power source. Golems also gain a natural armor class bonus from their tough body.", - -"There are two types of skeletons: the ordinary, warrior-like skeletons, and the spell-using skeletons, which are also called liches. As undead beings, skeletons need to worry very little about poison or attacks that can drain life. They do not really use eyes for perceiving things, and are thus not fooled by invisibility. Their bones are resistant to sharp shrapnel, and they will quickly become resistant to cold. Although the magical effects of these will affect the skeleton even without entering the skeleton's (non-existent) belly, the potion or food itself will fall through the skeleton's jaws, giving no nutritional benefit. They can absorb mana from staves and wands as their energy source.", - -"Much like Skeletons, Zombies too are undead horrors: they are resistant to exp-draining attacks, and can learn to restore their experience. Like skeletons, they become resistant to cold-based attacks (actually earlier than skeletons), resist poison and can see invisible. While still vulnerable to cuts (unlike skeletons), Zombies are resistant to Nether. Like Golems, they gain very little nutrition from the food of mortals, but can absorb mana from staves and wands as their energy source.", - -"One of the mightier undead creatures, the Vampire is an awe-inspiring sight. Yet this dread creature has a serious weakness: the bright rays of sun are its bane, and it will need to flee the surface to the deep recesses of earth until the sun finally sets. Darkness, on the other hand, only makes the Vampire stronger. As undead, the Vampire has a firm hold on its experience, and resists nether attacks. The Vampire also resists cold and poison based attacks. It is, however, susceptible to its perpetual hunger for fresh blood, which can only be satiated by sucking the blood from a nearby monster.", - -"Another powerful undead creature: the Spectre is a ghastly apparition, surrounded by an unearthly green glow. They exist only partially on our plane of existence: half-corporeal, they can pass through walls, although the density of the wall will hurt them in the process of doing this. As undead, they have a firm hold on their experience, see invisible, and resist poison and cold. They also resist nether. At higher levels they develop telepathic abilities. Spectres make superb spellcasters, but their physical form is very weak. They gain very little nutrition from the food of mortals, but can absorb mana from staves and wands as their energy source.", - -"One of the several fairy races, Sprites are very small. They have tiny wings and can fly over traps that may open up beneath them. They enjoy sunlight intensely, and need worry little about light based attacks. Although physically among the weakest races, Sprites are very talented in magic, and can become highly skilled wizards. Sprites have the special power of spraying Sleeping Dust, and at higher levels they learn to fly faster.", - -"This race is a blasphemous abomination produced by Chaos. It is not an independent race but rather a humanoid creature, most often a human, twisted by the Chaos, or a nightmarish crossbreed of a human and a beast. All Beastmen are accustomed to Chaos so much that they are untroubled by confusion and sound, although raw logrus can still have effects on them. Beastmen revel in chaos, as it twists them more and more. Beastmen are subject to mutations: when they have been created, they receive a random mutation. After that, every time they advance a level they have a small chance of gaining yet another mutation.", - -"The Ents are a powerful race dating from the beginning of the world, oldest of all animals or plants who inhabit Arda. Spirits of the land, they were summoned to guard the forests of Middle-earth. Being much like trees they are very clumsy but strong, and very susceptible to fire. They gain very little nutrition from the food of mortals, but they can absorb water from potions as their nutrition.", - -"Archons are a higher class of angels. They are good at all skills, and are strong, wise, and are a favorite with any people. They are able to see the unseen, and their wings allow them to safely fly over traps and other dangerous places. However, belonging to a higher plane as they do, the experiences of this world do not leave a strong impression on them and they gain levels slowly.", - -"Balrogs are a higher class of demons. They are strong, intelligent and tough. They do not believe in gods, and are not suitable for priest at all. Balrog are resistant to fire and nether, and have a firm hold on their experience. They also eventually learn to see invisible things. They are good at almost all skills except stealth. They gain very little nutrition from the food of mortals, and need human corpses as sacrifices to regain their vitality.", - -"Dunedain are a race of hardy men from the West. This elder race surpasses human abilities in every field, especially constitution. However, being men of the world, very little is new to them, and levels are very hard for them to gain. Their constitution cannot be reduced. ", - -"Shadow Fairies are one of the several fairy races. They have wings, and can fly over traps that may open up beneath them. Shadow Fairies must beware of sunlight, as they are vulnerable to bright light. They are physically weak, but have advantages in using magic and are amazingly stealthy. Shadow Fairies have a wonderful advantage in that they never aggravate monsters (If their equipment normally aggravates monsters, they only suffer a penalty to stealth, but if they aggravate by their personality itself, the advantage will be lost).", - -"A Kutar is an expressionless animal-like living creature. The word 'kuta' means 'absentmindedly' or 'vacantly'. Their absentmindedness hurts their searching and perception skills, but renders them incapable of being confused. Their unearthly calmness and serenity make them among the most stealthy of any race. Kutars, although expressionless, are beautiful and so have a high charisma. Members of this race can learn to expand their body horizontally. This increases armour class, but renders them vulnerable to magical attacks.", - -"An android is a artificial creation with a body of machinery. They are poor at spell casting, but they make excellent warriors. They don't acquire experience like other races, but rather gain in power as they attach new equipment to their frame. Rings, amulets, and lights do not influence growth. Androids are resistant to poison, can move freely, and are immune to exp-draining attacks. Moreover, because of their hard metallic bodies, they get a bonus to AC. Androids have electronic circuits throughout their body and must beware of electric shocks. They gain very little nutrition from the food of mortals, but they can use flasks of oil as their energy source." - -"Merfolk implementing.", - -#endif -}; - -/*! 職業の解説メッセージテーブル */ -static concptr class_jouhou[MAX_CLASS] = -{ -#ifdef JP -"戦士は、直面する問題のほとんどを細切れに叩き切ることで解決するキャラクタです。が、時折退却して魔法の道具の世話になることもあります。不運にも、高レベルなアイテムの多くは彼らが扱える範囲を越えています。", - -"メイジは魔法使いであり、その機知によって生き延びなければなりません。戦士のように、単純に切りまくることで道を開くことは望めません。呪文書に加えて、メイジは助けになる魔法の道具を持ち運ぶべきです。これは他の何よりも遥かに簡単にマスターできます。魔法に必要な能力値は知能です。", - -"プリーストは高貴な力を使うことに専念したキャラクタです。彼らは自身の神のためにダンジョンを探索し、もし宝を手にいれたなら、それは彼が信仰する宗教の栄光となります。プリーストは新しい祈りを神からの贈り物という形で受け取るため、どれを学ぶのか自分で選ぶことはできません。プリーストは魔法の道具の使い方をよく知っていますが、メイジほどうまくは使えません。刃のついた武器より鈍器を好み、祝福されていない刃のついた武器を装備すると不愉快な感覚に襲われ、戦闘能力が落ちてしまいます。魔法に必要な能力値は賢さです。", - -"盗賊はその狡猾さで生き抜くことを好むキャラクタですが、肝心なときには戦闘で道を切り開くことができます、盗賊は罠やドアを見つける能力に優れ、罠の解除や鍵開けに熟達しています。盗賊は高い隠密行動を持ち、たくさんのモンスターの群れのそばを起こすことなく通り抜けたり、忍び寄って先制攻撃することができます。魔法に必要な能力値は知能です。", - -"レンジャーは戦士とメイジを合わせたような職業で、身の回りの自然と特別な関係を作り上げています。彼はより戦士であり、弓のような遠距離武器を巧く使える職業です。レンジャーはよい隠密行動、よい知覚、よい探索、よい魔法防御を持ち、魔法の道具の使用にも長けています。魔法に必要な能力値は知能です。", - -"パラディンは戦士とプリーストを合わせた職業です。パラディンはとてもよい戦士ですが、遠距離武器を扱うのは得意ではありません。パラディンには多くの能力が欠けています。隠密行動, 知覚, 探索, そして魔法道具使用が苦手ですが、その神との提携によって魔法防御はそこそこです。魔法に必要な能力値は賢さです。", - -"魔法戦士はその名称が意味する通りの職業であり、戦士とメイジの資質をあわせ持ちます。彼らの同業者であるレンジャーが自然の魔法と生き抜くためのスキルに特化している一方、本当の魔法剣士はどちらの世界でも一番になろうとしています。戦士としては普通のメイジとは比べ物にならないほど優れています。しかし、実際には魔法でも戦闘でも専門の職業には及ばず、戦士とメイジの中間に位置するような職業です。魔法に必要な能力値は知能です。", - -"混沌の戦士は恐るべきカオスの魔王の使いとして恐れられる存在です。混沌の戦士はパトロンとなる悪魔を持ち、レベルが上がる度に報酬を得ることがあります。彼は治療してくれたり、こちらを変化させたり、能力値を上げてくれるかもしれませんし、回りに怪物達を出現させたり、能力値や装備を奪うかも知れません。もしくは単にこちらを無視するだけかもしれません。カオスの魔王は無秩序で予測のつかない存在です。報酬の種類はパトロンとなる悪魔と偶然に依存します(違う悪魔は異なる報酬を与えます)。魔法に必要な能力値は知能です。", - -"修行僧は他の職業とは著しく異なる職業です。彼らは他の職業同様武器と防具を使えますが、マーシャルアーツの訓練を積んでいるため、武器、防具なしでより強力な存在となります。高レベルでは、必要な耐性を身につけるためある種の防具を装備する必要がありますが、もしあまりに重すぎる防具を装備してしまうと、その体術に深刻な妨げとなります。レベルが上がると、彼らは新しい強力な攻撃法を学び、防御能力も上昇します。魔法に必要な能力値は賢さです。", - -"超能力者は魔法のかわりにその精神の力を使う唯一の職業です。この力は超能力者独特のもので、単に超感覚的なものから他人の精神を支配するものまで様々です。彼らの力はある種の訓練によって開発されるものなので、超能力者は力を使うのに呪文書を必要としません。使える力は単純にキャラクタのレベルによって決まります。超能力に必要な能力値は賢さです。", - -"ハイメイジは一つの領域に特化し、その領域を通常のメイジよりはるかに深く学んだメイジです。1つの領域に特化したおかげで、彼らは自らが選択した領域の呪文を唱える際の消費MP、最低レベル、失敗率で相当な恩恵を受けます。しかし、生命の領域ではプリーストほどうまくはなれないことには注意すべきです。魔法に必要な能力値は知能です。", - -"観光客は観光のためにこの世界にやってきました。戦闘力が低く、強力な呪文を使うこともできないため、最も生きぬいていくのが厳しい職業と言えます。魔法に必要な能力値は知能です。", - -"ものまね師は戦闘力はそこそこありますが、自分から特殊な能力を使うことは全くできません。しかし、自分の目の前にいる相手が特殊能力を使った場合、その能力と全く同じ能力をそっくりそのまま使うことができます。ものまねに必要な能力は基本的に器用さですが、まねる特殊能力に関係ある他の能力も必要です。", - -"魔獣使いは変愚蛮怒世界のダンジョンに住む生物と心を通い合わせられます。彼らは最もうまくモンスターを乗りこなすことができ、召喚したり手なづけたりしたモンスターを自分の手足のように使います。魔法に必要な能力は魅力です。", - -"スペルマスターは全ての魔法を極める者です。彼らは全分野において非常に優れた魔法使いであり、あらゆる魔法書のすべての呪文を学習の手間なく使いこなすことができます。その反面、彼らは戦士としては最低で、どんな武器も満足に扱えません。魔術師の杖だけは例外ですが、武器としては使い物にならないでしょう。すべての魔法をうまく生かさなければならないため、非常に上級者向けな職業と言えます。魔法に必要な能力は知能です。", - -"アーチャーは魔法を使うことはできませんが、どんな職業よりも巧みに弓やスリングを使いこなします。大量の矢や弾を必要とするのは確かですが、岩石からスリング用の弾を作ったり、レベルが上がるとモンスターの骨やがらくたから矢を作ったりする技術を身につけます。また、戦士と比べて隠密行動、知覚、探索、魔法道具の使用などにも優れており、いざというときには魔法の道具に頼ることもできます。", - -"魔道具術師は杖、魔法棒、ロッドといった魔法のアイテムから魔力を取り込むことによって魔法を使います。魔法のアイテムを発見することが他の職業よりもはるかに重要になります。戦闘力は高くはないですが、そこそこの強さがあります。魔法に必要な能力は知能です。", - -"吟遊詩人は魔力を帯びた歌を歌うことができます。多くの歌は普通の魔法と異なり、歌を歌っている間継続して効果を発揮します。しかし、同時に2つの歌を歌うことができない、という欠点もあります。視界内全体に影響を及ぼす歌が多い、という特徴もあります。肉体的な能力は貧弱で、単純に切りまくることで道を開くことはできません。魔法に必要な能力は魅力です。", - -"赤魔道師は下級魔法のほとんどを使うことができ、戦闘力も十分にあります。レベルが上がると強力な能力「連続魔」を身につけることができます。しかし、魔法を覚えるスピードは遅く、上級魔法を使えないので、メイジほどには魔法を頼りにすることができません。魔法道具使用と魔法防御はそこそこですが、それ以外の技能は苦手です。魔法に必要な能力は知能です。", - -"剣術家は戦士に次ぐ戦闘力があり、様々な技を使うことができます。彼らのMPはレベルに依存せず、賢さだけで決まり、気合いをためることにより、最大値を越えてMPを増やすことができます。しかし、戦士と同様、高レベルの魔法のアイテムは彼らの扱える範囲を越えており、罠の解除や探索の能力も高いとはいえません。必殺技の使用に必要な能力は賢さです。", - -"練気術師は「気」を使う達人です。修行僧と同様、武器や防具を持たずに戦うことを好み、武器・防具なしでより強力な存在となります。修行僧ほどの戦闘能力はありませんが、修行僧と同様の魔法が使え、さらに「気」の力を操ります。武器を持つことや、重すぎる防具を装備することは、「気」の力の使用を妨げます。魔法と練気術に必要な能力は賢さです。", - -"青魔道師は優れた魔法使いであり、その機知によって生き延びなければなりません。メイジ等の他の魔法使いとの違いは魔法の覚え方で、青魔道師はモンスターの魔法の効果を受けることでその魔法を覚えます。覚えるためには「ラーニング」の状態になっていないといけません。魔法に必要な能力は知能です。", - -"騎兵は馬に乗り戦場を駆け抜けるエリート戦士です。魔法は使えませんが、馬上からの圧倒的な攻撃力を誇る上に、高い機動力を生かした射撃をも得意としています。レベルが上がれば、野生のモンスターにまたがり無理矢理手なずけることができます。彼らは己の肉体と精神に誇りを持ち、魔法道具にはあまり頼ろうとはしません。", - -"狂戦士は怒り狂って武器を振るう恐るべき戦士です。全職業中最高の肉体能力を誇り、恐怖と麻痺に対する耐性を持ち、レベルが上がればその強靭な肉体で矢の呪文を跳ね返すことができます。さらに武器なしで戦うことや、呪いのかけられた装備を力づくで剥がすことができ、いくつかの技を(反魔法状態でも)使うことができます。しかし、巻物や魔法道具は全く使うことができず、罠の解除や隠密行動、探索、魔法防御、飛び道具の技能に関しては絶望的です。ひたすら殴って道を開くしかありません。幽霊は非常に勝利しやすいですがスコアがかなり低く修正されます。", - -"鍛冶師は武器や防具を自分で強化することができます。特殊効果を持つ武器や防具から特殊効果の元となるエッセンスを取り出し、別の武器や防具にエッセンスを付加することによってその特殊効果を付加できます。ある程度の戦闘能力も持ちますが、魔法は一切使用できず、隠密や魔法防御の技能も低くなります。", - -"鏡使いは、魔力の込められた鏡を作り出して、それを触媒として攻撃を行なうことができる鏡魔法を使います。鏡使いは鏡の上で実力を発揮し、鏡の上では素早いテレポートが可能となります。魔法の鏡は、レベルによって一度に制御できる数が制限されます。鏡魔法に必要な能力は知能です。", - -"忍者は暗闇に潜む恐るべき暗殺者であり、光源を持たずに行動し、相手の不意をつき一撃で息の根を止めます。また、相手を惑わすための忍術も身につけます。罠やドアを見つける能力に優れ、罠の解除や鍵開けに熟達しています。軽装を好み、重い鎧や武器を装備すると著しく動きが制限され、また、盾を装備しようとはしません。軽装ならば、レベルが上がるにつれより速くより静かに行動できます。さらに忍者は恐怖せず、成長すれば毒がほとんど効かなくなり、透明なものを見ることができるようになります。忍術に必要な能力は器用さです。", - -"スナイパーは一撃必殺を狙う恐るべき射手です。精神を高めることにより、射撃の威力と精度を高めます。また、魔法を使うことはできませんが、研ぎ澄まされた精神から繰り出される射撃術はさらなる威力をもたらすことでしょう。テクニックが必要とされる職業です。" - -#else - -"A Warrior is a hack-and-slash character, who solves most of his problems by cutting them to pieces, but will occasionally fall back on the help of a magical device. Unfortunately, many high-level devices may be forever beyond their use.", - -"A Mage is a spell caster that must live by his wits as he cannot hope to simply hack his way through the dungeon like a warrior. In addition to his spellbooks, a mage should carry a range of magical devices to help him in his endeavors which he can master far more easily than anyone else. A mage's prime statistic is Intelligence as this determines his spell casting ability. ", - -"A Priest is a character devoted to serving a higher power. They explore the dungeon in the service of their God. Since Priests receive new prayers as gifts from their patron deity, they cannot choose which ones they will learn. Priests are familiar with magical devices which they believe act as foci for divine intervention in the natural order of things. A priest wielding an edged weapon will be so uncomfortable with it that his fighting ability. A Priest's primary stat is Wisdom since this determine his success at praying to his deity. ", - -"A Rogue is a character that prefers to live by his cunning, but is capable of fighting his way out of a tight spot. Rogues are good at locating hidden traps and doors and are the masters of disarming traps and picking locks. A rogue has a high stealth allowing him to sneak around many creatures without having to fight, or to get in a telling first blow. A rogue may also backstab a fleeing monster. Intelligence determines a Rogue's spell casting ability.", - -"A Ranger is a combination of a warrior and a mage who has developed a special affinity for the natural world around him. He is a good fighter and also good about a missile weapon such as a bow. A ranger has a good stealth, good perception, good searching, a good saving throw and is good with magical devices. Intelligence determines a Ranger's spell casting ability.", - -"A Paladin is a combination of a warrior and a priest. Paladins are very good fighters, but not very good at missile weapons. A paladin lacks much in the way of abilities. He is poor at stealth, perception, searching, and magical devices but has a decent saving throw due to his divine alliance. Wisdom determines a Paladin's success at praying to his deity.", - -"A Warrior-Mage is precisely what the name suggests: a cross between the warrior and mage classes. While their brothers, the rangers, specialize in Nature magic and survival skills, true Warrior-Mages attempt to reach the best of both worlds. As warriors they are much superior to the usual Mage class. Intelligence determines a Warrior-Mage's spell casting ability.", - -"Chaos Warriors are the feared servants of the terrible Demon Lords of Chaos. Every Chaos Warrior has a Patron Demon and, when gaining a level, may receive a reward from his Patron. He might be healed or polymorphed, his stats could be increased, or he might be rewarded with an awesome weapon. On the other hand, the Patrons might surround him with monsters, drain his stats or wreck his equipment or they might simply ignore him. The Demon Lords of Chaos are chaotic and unpredictable indeed. The exact type of reward depends on both the Patron Demon (different Demons give different rewards) and chance.", - -"The Monk character class is very different from all other classes. Their training in martial arts makes them much more powerful with no armor or weapons. To gain the resistances necessary for survival a monk may need to wear some kind of armor, but if the armor he wears is too heavy, it will severely disturb his martial arts maneuvers. As the monk advances levels, new, powerful forms of attack become available. Their defensive capabilities increase likewise, but if armour is being worn, this effect decreases. Wisdom determines a Monk's spell casting ability.", - -"The Mindcrafter is a unique class that uses the powers of the mind instead of magic. These powers are unique to Mindcrafters, and vary from simple extrasensory powers to mental domination of others. Since these powers are developed by the practice of certain disciplines, a Mindcrafter requires no spellbooks to use them. The available powers are simply determined by the character's level. Wisdom determines a Mindcrafter's ability to use mind powers.", - -"High-mages are mages who specialize in one particular field of magic and learn it very well - much better than the ordinary mage. For the price of giving up a second realm of magic, they gain substantial benefits in the mana costs, minimum levels, and failure rates in the spells of the realm of their specialty. A high mage's prime statistic is intelligence as this determines his spell casting ability. ", - -"Tourists have visited this world for the purpose of sightseeing. Their fighting skills is bad, and they cannot cast powerful spells. They are the most difficult class to win the game with. Intelligence determines a tourist's spell casting ability.", - -"Imitators have enough fighting skills to survive, but rely on their ability to imitate monster spells. When monsters in line of sight use spells, they are added to a temporary spell list which the imitator can choose among. Spells should be imitated quickly, because timing and situation are everything. An imitator can only repeat a spell once each time he observes it. Dexterity determines general imitation ability, but a stat related to the specific action is often also taken into account.", - -"Beastmasters are in tune with the minds of the creatures of the world of Hengband. They are very good at riding, and have enough fighting ability. They use monsters which summoned or dominated by him as his hands and feet. Beastmasters can cast trump magic, and very good at summoning spell, but they can not summon non-living creatures. Charisma determines a Beastmaster's spell casting ability.", - -"Sorcerers are the all-around best magicians, being able to cast any spell from most magic realms without having to learn it. On the downside, they are the worst fighters in the dungeon, being unable to use any weapon but a Wizardstaff.", - -"Archers are to bows what warriors are to melee. They are the best class around with any bow, crossbow, or sling. They need a lot of ammunition, but will learn how to make it from junk found in the dungeon. An archer is better than a warrior at stealth, perception, searching and magical devices.", - -"Magic-Eaters can absorb the energy of wands, staffs, and rods, and can then use these magics as if they were carrying all of these absorbed devices. They are middling-poor at fighting. A Magic-Eater's prime statistic is intelligence.", - -"Bards are something like traditional musicians. Their magical attacks are sound-based, and last as long as the Bard has mana. Although a bard cannot sing two or more songs at the same time, he or she does have the advantage that many songs affect all areas in sight. A bard's prime statistic is charisma.", - -"Red-Mages can use almost all spells from lower rank spellbooks of most realms without having to learn it. At higher level, they develop the powerful ability \"Double Magic\". However, they have large penalties in the mana costs, minimum levels, and failure rates of spells, and they cannot use any spells from higher rank spellbooks. They are not bad at using magical devices and magic resistance, and are decent fighter, but are bad at other skills. A red-mage's prime statistic is intelligence.", - -"Samurai, masters of the art of the blade, are the next strongest fighters after Warriors. Their spellpoints do not depend on level, but depend solely on wisdom, and they can use the technique Concentration to temporarily increase SP beyond its usual maximum value. Samurai are not good at most other skills, and many magical devices may be too difficult for them to use. Wisdom determines a Samurai's ability to use the special combat techniques available to him.", - -"A ForceTrainer is a master of the spiritual Force. They prefer fighting with neither weapon nor armor. They are not as good fighters as are Monks, but they can use both magic and the spiritual Force. Wielding weapons or wearing heavy armor disturbs use of the Force. Wisdom is a ForceTrainer's primary stat.", - -"A Blue-Mage is a spell caster that must live by his wits, as he cannot hope to simply hack his way through the dungeon like a warrior. A major difference between the Mage and the Blue-Mage is the method of learning spells: Blue-Mages may learn spells from monsters by activating his Learning ability. A Blue-Mage's prime statistic is Intelligence as this determines his spell casting ability. ", - -"Cavalry ride on horses into battle. Although they cannot cast spells, they are proud of their overwhelming offensive strength on horseback. They are good at shooting. At high levels, they learn to forcibly saddle and tame wild monsters. Since they take pride in the body and the soul, they don't use magical devices well.", - -"A Berserker is a fearful fighter indeed, immune to fear and paralysis. At high levels, Berserkers can reflect bolt spells with their tough flesh. Furthermore, they can fight without weapons, can remove cursed equipment by force, and can even use their special combat techniques when surrounded by an anti-magic barrier. Berserkers, however, cannot use any magical devices or read any scrolls, and are hopeless at all non-combat skills. Since Berserker Spectres are quite easy to *win* with, their scores are lowered.", - -"A Weaponsmith can improve weapons and armors for him or herself. They can extract the essences of special effects from weapons or armors which have various special abilities, and can add these essences to another weapon or armor. They are good at fighting, but cannot cast spells, and are poor at skills such as stealth or magic defense.", - -"Mirror-Masters are spell casters; like other mages, they must live by their wits. They can create magical mirrors, and employ them in the casting of Mirror-Magic spells. A Mirror-Master standing on a mirror has greater ability and, for example, can perform quick teleports. The maximum number of Magical Mirrors which can be controlled simultaneously depends on the level. Intelligence determines a Mirror-Master's spell casting ability.", - -"A Ninja is a fearful assassin lurking in darkness. He or she can navigate effectively with no light source, catch enemies unawares, and kill with a single blow. Ninjas can use Ninjutsu, and are good at locating hidden traps and doors, disarming traps and picking locks. Since heavy armors, heavy weapons, or shields will restrict their motion greatly, they prefer light clothes, and become faster and more stealthy as they gain levels. A Ninja knows no fear and, at high level, becomes almost immune to poison and able to see invisible things. Dexterity determines a Ninja's ability to use Ninjutsu.", - -"Snipers are good at shooting, and they can kill targets by a few shots. After they concentrate deeply, they can demonstrate their shooting talents. You can see incredibly firepower of their shots." -#endif -}; - -/*! 性格の解説メッセージテーブル */ -static concptr seikaku_jouhou[MAX_SEIKAKU] = -{ -#ifdef JP -"ふつうは、特に特筆するべき部分がない性格です。あらゆる技能を平均的にこなします。", - -"ちからじまんは、肉体的な能力や技能が上昇します。しかし、魔法に関係する能力や技能は劣り、戦士よりのステータスを持ちます。", - -"きれものは、肉体的な能力は下がりますが、知能や魔法に関係する技能は上昇し、メイジよりのステータスを持ちます。", - -"しあわせものは、神を信仰する能力が高くなります。肉体的には平均的な能力を持ち、プリーストに近いステータスとなります。", - -"すばしっこいは、どのスキルも比較的うまくこなしますが、肉体的な能力は低くなります。", - -"いのちしらずは、戦闘力、魔法能力の両方が上昇しますが、魔法防御、HPといった能力は悪くなります。", - -"好きな食べ物は焼きビーフン。抑えてはいるが、冒険心旺盛な一匹狼。正義感、勇気とも平均以上だがカッとしやすい所もある。計画的人生より行き当たりばったりの人生を選んでしまうタイプで、異性の扱いは苦手。", - -"なまけものは、あらゆるスキルが低く、何をやってもうまくいきません。", - -"セクシーギャルは、あらゆるスキルをうまくこなすことができます。しかし、その人をなめた性格は全てのモンスターを怒らせることになるでしょう。この性格は女性しか選ぶことができません。", - -"ラッキーマンは、能力値はなまけものに匹敵するくらい低いにもかかわらず、どんなことをしてもなぜかうまくいってしまいます。この性格は男性しか選ぶことができません。", - -"がまんづよいは、じっくりと物事にとりくむ慎重な性格で、他の性格に比べて高い耐久力を得ることができます。しかし、自分から行動するのは苦手で、多くの技能は低くなってしまいます。", - -"いかさまは、初心者の練習用の性格です。あらゆる能力が高くなっています。この性格を使えば勝利者になることは容易ですが、勝利しても全く自慢になりません。", - -"チャージマンは「こんなところ」に連れて行かれても仕方のない可愛そうなお友達なんDA。腕っ節やタフさはマンモス並みに強いのだけれど知能面はまるで駄目なのが分かるだろう?この性格は最初から気が狂っているので、混乱したり幻覚を見る心配がないのです。", - -#else - -"\"Ordinary\" is a personality with no special skills or talents, with unmodified stats and skills.", - -"\"Mighty\" raises your physical stats and skills, but reduces stats and skills which influence magic. It makes your stats suitable for a warrior. Also it directly influences your hit-points and spell fail rate.", - -"\"Shrewd\" reduces your physical stats, and raises your intelligence and magical skills. It makes your stats suitable for a mage. Also it directly influences your hit-points and spell fail rate.", - -"\"Pious\" deepens your faith in your God. It makes your physical ability average, and your stats suitable for priest. ", - -"\"Nimble\" renders you highly skilled comparatively well, but reduces your physical ability. ", - -"\"Fearless\" raises both your melee and magical ability. Stats such as magic defense and constitution are reduced. Also it has a direct bad influence on your hit-points.", - -"\"Combat\" gives you comparatively high melee and shooting abilities, and average constitution. Other skills such as stealth, magic defence, and magical devices are weakened. All \"Combat\" people have great respect for the legendary \"Combat Echizen\".\n\ -(See \"Death Crimson\" / Ecole Software Corp.)", - -"A \"Lazy\" person has no good stats and can do no action well. Also it has a direct bad influence on your spell fail rate.", - -"\"Sexy\" rises all of your abilities, but your haughty attitude will aggravate all monsters. Only females can choose this personality.", - -"A \"Lucky\" man has poor stats, equivalent to a \"Lazy\" person. Mysteriously, however, he can do all things well. Only males can choose this personality.", - -"A \"Patient\" person does things carefully. Patient people have high constitution, and high resilience, but poor abilities in most other skills. Also it directly influences your hit-points.", - -"\"munchkin\" is a personality for beginners. It raises all your stats and skills. With this personality, you can win the game easily, but gain little honor in doing so.", - -"\ChargeMan\" is crazy killer. It render you powerfull strength and constitution, but poor intelligence.you are not confused and seen the illusion because this you go mad from the beginning.", - -#endif -}; - -/*! 魔法領域の詳細解説メッセージテーブル */ -static concptr realm_jouhou[VALID_REALM] = -{ -#ifdef JP -"生命は回復能力に優れた魔法です。治療や防御、感知魔法が多く含まれていますが、攻撃呪文もわずかに持っています。特に高レベルの呪文にはアンデッドを塵に帰す力をあると言われています。", - -"仙術は「meta」領域であり、感知や鑑定、さらに退却用の呪文や自身の能力を高める呪文などの便利な呪文が含まれています。しかし、直接攻撃用の呪文は持っていません。", - -"自然の魔法は使用者を元素のマスターにします。これには防御、探知、治療と攻撃呪文が含まれています。また、生命以外の領域で最高の治療呪文もこの領域にあります。", - -"カオスの魔法は制御が困難で、予測のできない魔法もあります。カオスは非常に非元素的であり、カオスの呪文は想像できる最も恐るべき破壊兵器です。この呪文を唱えるものはカオスの尖兵に対し、敵や自分自身さえも変異させるよう要求します。", - -"黒魔術である暗黒の魔法ほど邪悪なカテゴリーはありません。これらの呪文は比較的学ぶのが困難ですが、高レベルになると術者に生物とアンデッドを自由に操る能力を与えます。残念なことに、もっとも強力な呪文はその触媒として術者自身の血を必要とし、詠唱中にしばしば術者を傷つけます。", - -"トランプの魔法はテレポート系の呪文で精選されたものを持っており、その出入り口は他の生物を召喚するためにも使えるため、召喚呪文から選りすぐられたものも同様に持っています。しかし、この魔法によって全ての怪物が別の場所へ呼ばれるのを理解するわけではなく、もし召喚呪文に失敗するとその生物は敵となります。", - -"秘術の魔法は、全ての領域から有用な呪文だけを取り入れようとした多用途領域です。必要な「道具」的呪文を持っていても高レベルの強力な呪文は持っていません。結果として、全ての呪文書は街で買い求めることができます。また、他の領域に存在する同様な呪文の方がより低レベル、低コストで唱えることができます。", - -"匠の魔法は、自分や道具を強化するための魔法が含まれています。魔法によって自分自身の戦闘力を非常に高めることができますが、相手を直接攻撃するような呪文は含まれていません。", - -"悪魔の魔法は暗黒と同様非常に邪悪なカテゴリーです。様々な攻撃魔法に優れ、また悪魔のごとき知覚能力を得ることができます。高レベルの呪文は悪魔を自在に操り、自分自身の肉体をも悪魔化させることができます。", - -"破邪は「正義」の魔法です。直接敵を傷つける魔法が多く含まれ、特に邪悪な敵に対する力は恐るべきものがあります。しかし、善良な敵にはあまり効果がありません。", - -"歌集は、歌によって効果を発揮する魔法です。魔法と同様、使った時に効果のあるものと、歌い続けることによって持続して効果を発揮するものがあります。後者の場合は、MPの続く限り効果を発揮することができますが、同時に歌える歌は1つだけという制限もあります。", - -"武芸の書は、様々な戦闘の技について書かれています。この本は技を覚えるときに読む必要がありますが、一度覚えた技は使うのに本を持つ必要はありません。技を使うときには必ず武器を装備していなければいけません。", - -"呪術は忌むべき領域です。複数の呪いの言葉を歌のように紡ぎながら詠唱します。多くの呪文は詠唱し続けることによって効果が持続されます。呪文には相手の行動を束縛するもの、ダメージを与えるもの、攻撃に対して反撃するものが多くあります。" -#else - -"Life magic is very good for healing; it relies mostly on healing, protection and detection spells. Also life magic have a few attack spells as well. It said that some high level spell of life magic can disintegrate Undead monsters into ash.", - -"Sorcery is a `meta` realm, including enchantment and general spells. It provides superb protection spells, spells to enhance your odds in combat and, most importantly, a vast selection of spells for gathering information. However, Sorcery has one weakness: it has no spells to deal direct damage to your enemies.", - -"Nature magic makes you master of elements; it provides protection, detection, curing and attack spells. Nature also has a spell of Herbal Healing, which is the only powerful healing spell outside the realm of Life magic.", - -"There are few types of magic more unpredictable and difficult to control than Chaos magic. Chaos is the very element of unmaking, and the Chaos spells are the most terrible weapons of destruction imaginable. The caster can also call on the primal forces of Chaos to induce mutations in his/her opponents and even him/herself.", - -"There is no fouler nor more evil category of spells than the necromantic spells of Death Magic. These spells are relatively hard to learn, but at higher levels the spells give the caster power over living and the (un)dead, but the most powerful spells need his / her own blood as the focus, often hurting the caster in the process of casting.", - -"Trump magic has, indeed, an admirable selection of teleportation spells. Since the Trump gateways can also be used to summon other creatures, Trump magic has an equally impressive selection of summoning spells. However, not all monsters appreciate being drawn to another place by Trump user.", - -"Arcane magic is a general purpose realm of magic. It attempts to encompass all 'useful' spells from all realms. This is the downside of Arcane magic: while Arcane does have all the necessary 'tool' spells for a dungeon delver, it has no ultra-powerful high level spells. As a consequence, all Arcane spellbooks can be bought in town. It should also be noted that the 'specialized' realms usually offer the same spell at a lower level and cost. ", - -"Craft magic can strengthen the caster or the equipments. These spells can greatly improve the caster's fighting ability. Using them against opponents directly is not possible.", - -"Demon is a very evil realm, same as Death. It provides various attack spells and devilish detection spells. at higher levels, Demon magic provides ability to dominate demons, and to polymorph yourself into a demon.", - -"Crusade is a magic of 'Justice'. It includes damage spells, which are greatly effective against foul and evil monsters, but have poor effects against good monsters.", - -"Music magic shows various effects as sing song. There is two type of song; the one which shows effects instantly and the other one shows effect continuously until SP runs out. But the latter type has a limit; only one song can be sing at the same time.", - -"The books of Kendo describe about various combat techniques. When learning new techniques, you are required to carry the books, but once you memorizes them, you don't have to carry them. When using a technique, wielding a weapon is required.", - -"Hex is a very terrible realm. Spells gives continual effects when they are spelled continually like songs. Spells may obstract monsters' actions, may deal damages in sight, may revenge against enemies." -#endif -}; - -/*! 魔法領域の簡易解説メッセージテーブル */ -static concptr realm_subinfo[VALID_REALM] = -{ -#ifdef JP -"感知と防御と回復に優れています", -"攻撃はできませんが非常に便利です", -"感知と防御に優れています", -"破壊的な攻撃に優れています", -"生命のある敵への攻撃に優れています", -"召喚とテレポートに優れています", -"やや弱いながらも非常に便利です", -"直接戦闘の補助に優れています", -"攻撃と防御の両面に優れています", -"邪悪な怪物に対する攻撃に優れています", -"様々な魔法効果を持った歌を歌います", -"打撃攻撃に特殊能力を付加します", -"敵を邪魔しつつ復讐を狙います" -#else -"Good at detection and healing.", -"Utility and protective spells.", -"Good at detection and defence.", -"Offensive and destructive.", -"Ruins living creatures.", -"Good at summoning, teleportation.", -"Very useful but poor a bit.", -"Support for melee fighting.", -"Good at both offence and defence.", -"Destroys evil creatures.", -"Song with magical effects.", -"Special attacks on melee.", -"Good at obstacle and revenge." -#endif -}; - - -/*! オートローラの能力値的要求水準 / Autoroll limit */ -static s16b stat_limit[6]; - -/*! オートローラの年齢、身長、体重、社会的地位の要求水準 */ -static struct { - s16b agemin, agemax; - s16b htmin, htmax; - s16b wtmin, wtmax; - s16b scmin, scmax; -} chara_limit; - -/*! オートローラ中、各能力値が水準を超えた回数 / Autoroll matches */ -static s32b stat_match[6]; - -/*! オートローラの試行回数 / Autoroll round */ -static s32b auto_round; - -/*! - * @brief プレイヤー作成を中断して変愚蛮怒を終了する - * @return なし - */ -static void birth_quit(void) -{ - remove_loc(); - quit(NULL); -} - -/*! - * @brief 指定されたヘルプファイルを表示する / Show specific help file - * @param helpfile ファイル名 - * @return なし - */ -static void show_help(concptr helpfile) -{ - screen_save(); - (void)show_file(TRUE, helpfile, NULL, 0, 0); - screen_load(); -} - - -/*! - * @brief プレイヤーの魔法領域を選択する / Choose from one of the available magical realms - * @param choices 選択可能な魔法領域のビット配列 - * @param count 選択可能な魔法領域を返すポインタ群。 - * @return 選択した魔法領域のID - */ -static byte choose_realm(s32b choices, int *count) -{ - int picks[VALID_REALM] = {0}; - int k, i, cs, os; - byte auto_select = REALM_NONE; - int n = 0; - char c; - char sym[VALID_REALM]; - char p2 = ')'; - char buf[80], cur[80]; - - /* Count the choices */ - if (choices & CH_LIFE) - { - (*count)++; - auto_select = REALM_LIFE; - } - if (choices & CH_SORCERY) - { - (*count)++; - auto_select = REALM_SORCERY; - } - if (choices & CH_NATURE) - { - (*count)++; - auto_select = REALM_NATURE; - } - if (choices & CH_CHAOS) - { - (*count)++; - auto_select = REALM_CHAOS; - } - if (choices & CH_DEATH) - { - (*count)++; - auto_select = REALM_DEATH; - } - if (choices & CH_TRUMP) - { - (*count)++; - auto_select = REALM_TRUMP; - } - if (choices & CH_ARCANE) - { - (*count)++; - auto_select = REALM_ARCANE; - } - if (choices & CH_ENCHANT) - { - (*count)++; - auto_select = REALM_CRAFT; - } - if (choices & CH_DAEMON) - { - (*count)++; - auto_select = REALM_DAEMON; - } - if (choices & CH_CRUSADE) - { - (*count)++; - auto_select = REALM_CRUSADE; - } - if (choices & CH_MUSIC) - { - (*count)++; - auto_select = REALM_MUSIC; - } - if (choices & CH_HISSATSU) - { - (*count)++; - auto_select = REALM_HISSATSU; - } - if (choices & CH_HEX) - { - (*count)++; - auto_select = REALM_HEX; - } - - clear_from(10); - - /* Auto-select the realm */ - if ((*count) < 2) return auto_select; - - /* Constraint to the 1st realm */ - if (p_ptr->realm2 != 255) - { - if (p_ptr->pclass == CLASS_PRIEST) - { - if (is_good_realm(p_ptr->realm1)) - { - choices &= ~(CH_DEATH | CH_DAEMON); - } - else - { - choices &= ~(CH_LIFE | CH_CRUSADE); - } - } - } - - /* Extra info */ - put_str (_("注意:魔法の領域の選択によりあなたが習得する呪文のタイプが決まります。", "Note: The realm of magic will determine which spells you can learn."), 23, 5); - - cs = 0; - for (i = 0; i < 32; i++) - { - /* Analize realms */ - if (choices & (1L << i)) - { - if (p_ptr->realm1 == i+1) - { - if (p_ptr->realm2 == 255) - cs = n; - else - continue; - } - if (p_ptr->realm2 == i+1) - cs = n; - - sym[n] = I2A(n); - - sprintf(buf, "%c%c %s", sym[n], p2, realm_names[i+1]); - put_str(buf, 12 + (n/5), 2 + 15 * (n%5)); - picks[n++] = i+1; - } - } - sprintf(cur, "%c%c %s", '*', p2, _("ランダム", "Random")); - - /* Get a realm */ - k = -1; - os = n; - while (1) { - /* Move Cursol */ - if (cs != os) - { - c_put_str(TERM_WHITE, cur, 12 + (os/5), 2 + 15 * (os%5)); - put_str(" ", 3, 40); - put_str(" ", 4, 40); - - if(cs == n) - { - sprintf(cur, "%c%c %s", '*', p2, _("ランダム", "Random")); - } - else - { - sprintf(cur, "%c%c %s", sym[cs], p2, realm_names[picks[cs]]); - sprintf(buf, "%s", realm_names[picks[cs]]); -#ifdef JP - c_put_str(TERM_L_BLUE, buf, 3, 40); - put_str("の特徴", 3, 40+strlen(buf)); -#else - c_put_str(TERM_L_BLUE, realm_names[picks[cs]], 3, 40); - put_str(": Characteristic", 3, 40+strlen(realm_names[picks[cs]])); -#endif - put_str(realm_subinfo[technic2magic(picks[cs])-1], 4, 40); - } - c_put_str(TERM_YELLOW, cur, 12 + (cs/5), 2 + 15 * (cs%5)); - os = cs; - } - - if (k >= 0) break; - - sprintf(buf, _("領域を選んで下さい(%c-%c) ('='初期オプション設定): ", "Choose a realm (%c-%c) ('=' for options): "), sym[0], sym[n-1]); - - put_str(buf, 10, 10); - c = inkey(); - if (c == 'Q') birth_quit(); - if (c == 'S') return 255; - if (c == ' ' || c == '\r' || c == '\n') - { - if(cs == n) - { - k = randint0(n); - break; - } - else - { - k = cs; - break; - } - } - if (c == '*') - { - k = randint0(n); - break; - } - if (c == '8') - { - if (cs >= 5) cs -= 5; - } - if (c == '4') - { - if (cs > 0) cs--; - } - if (c == '6') - { - if (cs < n) cs++; - } - if (c == '2') - { - if ((cs + 5) <= n) cs += 5; - } - k = (islower(c) ? A2I(c) : -1); - if ((k >= 0) && (k < n)) - { - cs = k; - continue; - } - k = (isupper(c) ? (26 + c - 'A') : -1); - if ((k >= 26) && (k < n)) - { - cs = k; - continue; - } - else k = -1; - if (c == '?') - { - show_help(_("jmagic.txt#MagicRealms", "magic.txt#MagicRealms")); - } - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth option((*)s effect score)")); - - screen_load(); - } - else if (c !='2' && c !='4' && c !='6' && c !='8') bell(); - } - - /* Clean up */ - clear_from(10); - - return (byte_hack)(picks[k]); -} - - -/*! - * @brief 選択した魔法領域の解説を表示する / Choose the magical realms - * @return ユーザが魔法領域の確定を選んだらTRUEを返す。 - */ -static bool get_player_realms(void) -{ - int i, count; - - /* Clean up infomation of modifications */ - put_str(" ", 3, 40); - put_str(" ", 4, 40); - put_str(" ", 5, 40); - - /* Select the first realm */ - p_ptr->realm1 = REALM_NONE; - p_ptr->realm2 = 255; - while (1) - { - char temp[80*10]; - concptr t; - count = 0; - p_ptr->realm1 = choose_realm(realm_choices1[p_ptr->pclass], &count); - - if (255 == p_ptr->realm1) return FALSE; - if (!p_ptr->realm1) break; - - /* Clean up*/ - clear_from(10); - put_str(" ", 3, 40); - put_str(" ", 4, 40); - put_str(" ", 5, 40); - - roff_to_buf(realm_jouhou[technic2magic(p_ptr->realm1)-1], 74, temp, sizeof(temp)); - t = temp; - for (i = 0; i < 10; i++) - { - if(t[0] == 0) - break; - else - { - prt(t, 12+i, 3); - t += strlen(t) + 1; - } - } - - if (count < 2) - { - prt(_("何かキーを押してください", "Hit any key."), 0, 0); - (void)inkey(); - prt("", 0, 0); - break; - } - else if (get_check_strict(_("よろしいですか?", "Are you sure? "), CHECK_DEFAULT_Y)) break; - } - - /* Select the second realm */ - p_ptr->realm2 = REALM_NONE; - if (p_ptr->realm1) - { - /* Print the realm */ - put_str(_("魔法 :", "Magic :"), 6, 1); - c_put_str(TERM_L_BLUE, realm_names[p_ptr->realm1], 6, 15); - - /* Select the second realm */ - while (1) - { - char temp[80*8]; - concptr t; - - count = 0; - p_ptr->realm2 = choose_realm(realm_choices2[p_ptr->pclass], &count); - - if (255 == p_ptr->realm2) return FALSE; - if (!p_ptr->realm2) break; - - /* Clean up*/ - clear_from(10); - put_str(" ", 3, 40); - put_str(" ", 4, 40); - put_str(" ", 5, 40); - - roff_to_buf(realm_jouhou[technic2magic(p_ptr->realm2)-1], 74, temp, sizeof(temp)); - t = temp; - for (i = 0; i < A_MAX; i++) - { - if(t[0] == 0) - break; - else - { - prt(t, 12+i, 3); - t += strlen(t) + 1; - } - } - - if (count < 2) - { - prt(_("何かキーを押してください", "Hit any key."), 0, 0); - (void)inkey(); - prt("", 0, 0); - break; - } - else if (get_check_strict(_("よろしいですか?", "Are you sure? "), CHECK_DEFAULT_Y)) break; - } - if (p_ptr->realm2) - { - /* Print the realm */ - c_put_str(TERM_L_BLUE, format("%s, %s", realm_names[p_ptr->realm1], realm_names[p_ptr->realm2]), 6, 15); - } - } - - return (TRUE); -} - - -/*! - * @brief プレイヤーのクイックスタート情報をプレイヤー構造体から保存する / Save the current data for later - * @param birther_ptr クイックスタート構造体の参照ポインタ - * @return なし。 - */ -static void save_prev_data(birther *birther_ptr) -{ - int i; - - /* Save the data */ - birther_ptr->psex = p_ptr->psex; - birther_ptr->prace = p_ptr->prace; - birther_ptr->pclass = p_ptr->pclass; - birther_ptr->pseikaku = p_ptr->pseikaku; - birther_ptr->realm1 = p_ptr->realm1; - birther_ptr->realm2 = p_ptr->realm2; - birther_ptr->age = p_ptr->age; - birther_ptr->ht = p_ptr->ht; - birther_ptr->wt = p_ptr->wt; - birther_ptr->sc = p_ptr->sc; - birther_ptr->au = p_ptr->au; - - /* Save the stats */ - for (i = 0; i < A_MAX; i++) - { - birther_ptr->stat_max[i] = p_ptr->stat_max[i]; - birther_ptr->stat_max_max[i] = p_ptr->stat_max_max[i]; - } - - /* Save the hp */ - for (i = 0; i < PY_MAX_LEVEL; i++) - { - birther_ptr->player_hp[i] = p_ptr->player_hp[i]; - } - - birther_ptr->chaos_patron = p_ptr->chaos_patron; - - /* Save the virtues */ - for (i = 0; i < 8; i++) - { - birther_ptr->vir_types[i] = p_ptr->vir_types[i]; - } - - /* Save the history */ - for (i = 0; i < 4; i++) - { - strcpy(birther_ptr->history[i], p_ptr->history[i]); - } -} - - -/*! - * @brief プレイヤーのクイックスタート情報をプレイヤー構造体へ読み込む / Load the previous data - * @param swap TRUEならば現在のプレイヤー構造体上との内容をスワップする形で読み込む。 - * @return なし。 - */ -static void load_prev_data(bool swap) -{ - int i; - - birther temp; - - /*** Save the current data ***/ - if (swap) save_prev_data(&temp); - - - /*** Load the previous data ***/ - - /* Load the data */ - p_ptr->psex = previous_char.psex; - p_ptr->prace = previous_char.prace; - p_ptr->pclass = previous_char.pclass; - p_ptr->pseikaku = previous_char.pseikaku; - p_ptr->realm1 = previous_char.realm1; - p_ptr->realm2 = previous_char.realm2; - p_ptr->age = previous_char.age; - p_ptr->ht = previous_char.ht; - p_ptr->wt = previous_char.wt; - p_ptr->sc = previous_char.sc; - p_ptr->au = previous_char.au; - - /* Load the stats */ - for (i = 0; i < A_MAX; i++) - { - p_ptr->stat_cur[i] = p_ptr->stat_max[i] = previous_char.stat_max[i]; - p_ptr->stat_max_max[i] = previous_char.stat_max_max[i]; - } - - /* Load the hp */ - for (i = 0; i < PY_MAX_LEVEL; i++) - { - p_ptr->player_hp[i] = previous_char.player_hp[i]; - } - p_ptr->mhp = p_ptr->player_hp[0]; - p_ptr->chp = p_ptr->player_hp[0]; - - p_ptr->chaos_patron = previous_char.chaos_patron; - - for (i = 0; i < 8; i++) - { - p_ptr->vir_types[i] = previous_char.vir_types[i]; - } - - /* Load the history */ - for (i = 0; i < 4; i++) - { - strcpy(p_ptr->history[i], previous_char.history[i]); - } - - /*** Save the previous data ***/ - if (swap) - { - (void)COPY(&previous_char, &temp, birther); - } -} - - - - -/*! - * @brief プレイヤーの能力値表現に基づいて加減算を行う。 - * @param value 現在の能力値 - * @param amount 加減算する値 - * @return 加減算の結果 - */ -static int adjust_stat(int value, int amount) -{ - int i; - - /* Negative amounts */ - if (amount < 0) - { - /* Apply penalty */ - for (i = 0; i < (0 - amount); i++) - { - if (value >= 18+10) - { - value -= 10; - } - else if (value > 18) - { - value = 18; - } - else if (value > 3) - { - value--; - } - } - } - - /* Positive amounts */ - else if (amount > 0) - { - /* Apply reward */ - for (i = 0; i < amount; i++) - { - if (value < 18) - { - value++; - } - else - { - value += 10; - } - } - } - - /* Return the result */ - return (value); -} - - - - -/*! - * @brief プレイヤーの能力値を一通りロールする。 / Roll for a characters stats - * @details - * calc_bonuses()による、独立ステータスからの副次ステータス算出も行っている。 - * For efficiency, we include a chunk of "calc_bonuses()".\n - * @return なし - */ -static void get_stats(void) -{ - /* Roll and verify some stats */ - while (TRUE) - { - int i; - int sum = 0; - - /* Roll some dice */ - for (i = 0; i < 2; i++) - { - s32b tmp = randint0(60*60*60); - BASE_STATUS val; - - /* Extract 5 + 1d3 + 1d4 + 1d5 */ - val = 5 + 3; - val += tmp % 3; tmp /= 3; - val += tmp % 4; tmp /= 4; - val += tmp % 5; tmp /= 5; - - /* Save that value */ - sum += val; - p_ptr->stat_cur[3*i] = p_ptr->stat_max[3*i] = val; - - /* Extract 5 + 1d3 + 1d4 + 1d5 */ - val = 5 + 3; - val += tmp % 3; tmp /= 3; - val += tmp % 4; tmp /= 4; - val += tmp % 5; tmp /= 5; - - /* Save that value */ - sum += val; - p_ptr->stat_cur[3*i+1] = p_ptr->stat_max[3*i+1] = val; - - /* Extract 5 + 1d3 + 1d4 + 1d5 */ - val = 5 + 3; - val += tmp % 3; tmp /= 3; - val += tmp % 4; tmp /= 4; - val += (BASE_STATUS)tmp; - - /* Save that value */ - sum += val; - p_ptr->stat_cur[3*i+2] = p_ptr->stat_max[3*i+2] = val; - } - - /* Verify totals */ - if ((sum > 42+5*6) && (sum < 57+5*6)) break; - /* 57 was 54... I hate 'magic numbers' :< TY */ - } -} - -/*! - * @brief プレイヤーの限界ステータスを決める。 - * @return なし - */ -void get_max_stats(void) -{ - int i, j; - int dice[6]; - - /* Roll and verify some stats */ - while (TRUE) - { - /* Roll some dice */ - for (j = i = 0; i < A_MAX; i++) - { - /* Roll the dice */ - dice[i] = randint1(7); - - /* Collect the maximum */ - j += dice[i]; - } - - /* Verify totals */ - if (j == 24) break; - } - - /* Acquire the stats */ - for (i = 0; i < A_MAX; i++) - { - BASE_STATUS max_max = 18 + 60 + dice[i]*10; - - /* Save that value */ - p_ptr->stat_max_max[i] = max_max; - if (p_ptr->stat_max[i] > max_max) - p_ptr->stat_max[i] = max_max; - if (p_ptr->stat_cur[i] > max_max) - p_ptr->stat_cur[i] = max_max; - } - p_ptr->knowledge &= ~(KNOW_STAT); - p_ptr->redraw |= (PR_STATS); -} - - -/*! - * @brief その他「オートローラ中は算出の対象にしない」副次ステータスを処理する / Roll for some info that the auto-roller ignores - * @return なし - */ -static void get_extra(bool roll_hitdie) -{ - int i, j; - - /* Experience factor */ - if (p_ptr->prace == RACE_ANDROID) p_ptr->expfact = rp_ptr->r_exp; - else p_ptr->expfact = rp_ptr->r_exp + cp_ptr->c_exp; - - if (((p_ptr->pclass == CLASS_MONK) || (p_ptr->pclass == CLASS_FORCETRAINER) || (p_ptr->pclass == CLASS_NINJA)) && ((p_ptr->prace == RACE_KLACKON) || (p_ptr->prace == RACE_SPRITE))) - p_ptr->expfact -= 15; - - /* Reset record of race/realm changes */ - p_ptr->start_race = p_ptr->prace; - p_ptr->old_race1 = 0L; - p_ptr->old_race2 = 0L; - p_ptr->old_realm = 0; - - for (i = 0; i < 64; i++) - { - if (p_ptr->pclass == CLASS_SORCERER) p_ptr->spell_exp[i] = SPELL_EXP_MASTER; - else if (p_ptr->pclass == CLASS_RED_MAGE) p_ptr->spell_exp[i] = SPELL_EXP_SKILLED; - else p_ptr->spell_exp[i] = SPELL_EXP_UNSKILLED; - } - - for (i = 0; i < 5; i++) - for (j = 0; j < 64; j++) - p_ptr->weapon_exp[i][j] = s_info[p_ptr->pclass].w_start[i][j]; - if ((p_ptr->pseikaku == SEIKAKU_SEXY) && (p_ptr->weapon_exp[TV_HAFTED-TV_WEAPON_BEGIN][SV_WHIP] < WEAPON_EXP_BEGINNER)) - { - p_ptr->weapon_exp[TV_HAFTED-TV_WEAPON_BEGIN][SV_WHIP] = WEAPON_EXP_BEGINNER; - } - - for (i = 0; i < GINOU_MAX; i++) - p_ptr->skill_exp[i] = s_info[p_ptr->pclass].s_start[i]; - - /* Hitdice */ - if (p_ptr->pclass == CLASS_SORCERER) - p_ptr->hitdie = rp_ptr->r_mhp/2 + cp_ptr->c_mhp + ap_ptr->a_mhp; - else - p_ptr->hitdie = rp_ptr->r_mhp + cp_ptr->c_mhp + ap_ptr->a_mhp; - - /* Roll for hit point unless quick-start */ - if (roll_hitdie) roll_hitdice(p_ptr, SPOP_NO_UPDATE); - - /* Initial hitpoints */ - p_ptr->mhp = p_ptr->player_hp[0]; -} - - -/*! - * @brief プレイヤーの生い立ちの自動生成を行う。 / Get the racial history, and social class, using the "history charts". - * @return なし - */ -static void get_history(void) -{ - int i, n, chart, roll, social_class; - - char *s, *t; - - char buf[240]; - - /* Clear the previous history strings */ - for (i = 0; i < 4; i++) p_ptr->history[i][0] = '\0'; - - /* Clear the history text */ - buf[0] = '\0'; - - /* Initial social class */ - social_class = randint1(4); - - /* Starting place */ - switch (p_ptr->prace) - { - case RACE_AMBERITE: - { - chart = 67; - break; - } - case RACE_HUMAN: - case RACE_BARBARIAN: - case RACE_DUNADAN: - case RACE_MERFOLK: - { - chart = 1; - break; - } - case RACE_HALF_ELF: - { - chart = 4; - break; - } - case RACE_ELF: - case RACE_HIGH_ELF: - { - chart = 7; - break; - } - case RACE_HOBBIT: - { - chart = 10; - break; - } - case RACE_GNOME: - { - chart = 13; - break; - } - case RACE_DWARF: - { - chart = 16; - break; - } - case RACE_HALF_ORC: - { - chart = 19; - break; - } - case RACE_HALF_TROLL: - { - chart = 22; - break; - } - case RACE_DARK_ELF: - { - chart = 69; - break; - } - case RACE_HALF_OGRE: - { - chart = 74; - break; - } - case RACE_HALF_GIANT: - { - chart = 75; - break; - } - case RACE_HALF_TITAN: - { - chart = 76; - break; - } - case RACE_CYCLOPS: - { - chart = 77; - break; - } - case RACE_YEEK: - { - chart = 78; - break; - } - case RACE_KOBOLD: - { - chart = 82; - break; - } - case RACE_KLACKON: - { - chart = 84; - break; - } - case RACE_NIBELUNG: - { - chart = 87; - break; - } - case RACE_DRACONIAN: - { - chart = 89; - break; - } - case RACE_MIND_FLAYER: - { - chart = 92; - break; - } - case RACE_IMP: - { - chart = 94; - break; - } - case RACE_GOLEM: - { - chart = 98; - break; - } - case RACE_SKELETON: - { - chart = 102; - break; - } - case RACE_ZOMBIE: - { - chart = 107; - break; - } - case RACE_VAMPIRE: - { - chart = 113; - break; - } - case RACE_SPECTRE: - { - chart = 118; - break; - } - case RACE_SPRITE: - { - chart = 124; - break; - } - case RACE_BEASTMAN: - { - chart = 129; - break; - } - case RACE_ENT: - { - chart = 137; - break; - } - case RACE_ANGEL: - { - chart = 142; - break; - } - case RACE_DEMON: - { - chart = 145; - break; - } - case RACE_S_FAIRY: - { - chart = 148; - break; - } - case RACE_KUTAR: - { - chart = 154; - break; - } - case RACE_ANDROID: - { - chart = 155; - break; - } - default: - { - chart = 0; - break; - } - } - - - /* Process the history */ - while (chart) - { - /* Start over */ - i = 0; - - /* Roll for nobility */ - roll = randint1(100); - - - /* Access the proper entry in the table */ - while ((chart != bg[i].chart) || (roll > bg[i].roll)) i++; - - /* Acquire the textual history */ - (void)strcat(buf, bg[i].info); - - /* Add in the social class */ - social_class += (int)(bg[i].bonus) - 50; - - /* Enter the next chart */ - chart = bg[i].next; - } - - - /* Verify social class */ - if (social_class > 100) social_class = 100; - else if (social_class < 1) social_class = 1; - - /* Save the social class */ - p_ptr->sc = (s16b)social_class; - - - /* Skip leading spaces */ - for (s = buf; *s == ' '; s++) /* loop */; - - /* Get apparent length */ - n = strlen(s); - - /* Kill trailing spaces */ - - while ((n > 0) && (s[n-1] == ' ')) s[--n] = '\0'; - - { - char temp[64*4]; - roff_to_buf(s, 60, temp, sizeof(temp)); - t = temp; - for(i=0 ; i<4 ; i++){ - if(t[0]==0)break; - else {strcpy(p_ptr->history[i], t);t += strlen(t)+1;} - } - } -} - -/*! - * @brief プレイヤーの身長体重を決める / Get character's height and weight - * @return なし - */ -void get_height_weight(void) -{ - int h_percent; /* 身長が平均にくらべてどのくらい違うか. */ - - /* Calculate the height/weight for males */ - if (p_ptr->psex == SEX_MALE) - { - p_ptr->ht = randnor(rp_ptr->m_b_ht, rp_ptr->m_m_ht); - h_percent = (int)(p_ptr->ht) * 100 / (int)(rp_ptr->m_b_ht); - p_ptr->wt = randnor((int)(rp_ptr->m_b_wt) * h_percent /100 - , (int)(rp_ptr->m_m_wt) * h_percent / 300 ); - } - - /* Calculate the height/weight for females */ - else if (p_ptr->psex == SEX_FEMALE) - { - p_ptr->ht = randnor(rp_ptr->f_b_ht, rp_ptr->f_m_ht); - h_percent = (int)(p_ptr->ht) * 100 / (int)(rp_ptr->f_b_ht); - p_ptr->wt = randnor((int)(rp_ptr->f_b_wt) * h_percent /100 - , (int)(rp_ptr->f_m_wt) * h_percent / 300 ); - } -} - - -/*! - * @brief プレイヤーの年齢を決める。 / Computes character's age, height, and weight by henkma - * @details 内部でget_height_weight()も呼び出している。 - * @return なし - */ -static void get_ahw(void) -{ - /* Get character's age */ - p_ptr->age = rp_ptr->b_age + randint1(rp_ptr->m_age); - - /* Get character's height and weight */ - get_height_weight(); -} - -/*! - * @brief プレイヤーの初期所持金を決める。 / Get the player's starting money - * @return なし - */ -static void get_money(void) -{ - int i, gold; - - /* Social Class determines starting gold */ - gold = (p_ptr->sc * 6) + randint1(100) + 300; - if (p_ptr->pclass == CLASS_TOURIST) - gold += 2000; - - /* Process the stats */ - for (i = 0; i < A_MAX; i++) - { - /* Mega-Hack -- reduce gold for high stats */ - if (p_ptr->stat_max[i] >= 18 + 50) gold -= 300; - else if (p_ptr->stat_max[i] >= 18 + 20) gold -= 200; - else if (p_ptr->stat_max[i] > 18) gold -= 150; - else gold -= (p_ptr->stat_max[i] - 8) * 10; - } - - /* Minimum 100 gold */ - if (gold < 100) gold = 100; - - if (p_ptr->pseikaku == SEIKAKU_NAMAKE) - gold /= 2; - else if (p_ptr->pseikaku == SEIKAKU_MUNCHKIN) - gold = 10000000; - if (p_ptr->prace == RACE_ANDROID) gold /= 5; - - /* Save the gold */ - p_ptr->au = gold; -} - - - -/*! - * @brief put_stats()のサブルーチンとして、オートロール中のステータスを表示する / Display stat values, subset of "put_stats()" - * @details See 'display_player()' for screen layout constraints. - * @return なし - */ -static void birth_put_stats(void) -{ - int i, j, m, p; - int col; - TERM_COLOR attr; - char buf[80]; - - - if (autoroller) - { - col = 42; - /* Put the stats (and percents) */ - for (i = 0; i < A_MAX; i++) - { - /* Race/Class bonus */ - j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i]; - - /* Obtain the current stat */ - m = adjust_stat(p_ptr->stat_max[i], j); - - /* Put the stat */ - cnv_stat(m, buf); - c_put_str(TERM_L_GREEN, buf, 3+i, col+24); - - /* Put the percent */ - if (stat_match[i]) - { - if (stat_match[i] > 1000000L) - { - /* Prevent overflow */ - p = stat_match[i] / (auto_round / 1000L); - } - else - { - p = 1000L * stat_match[i] / auto_round; - } - - attr = (p < 100) ? TERM_YELLOW : TERM_L_GREEN; - sprintf(buf, "%3d.%d%%", p/10, p%10); - c_put_str(attr, buf, 3+i, col+13); - } - - /* Never happened */ - else - { - c_put_str(TERM_RED, _("(なし)", "(NONE)"), 3+i, col+13); - } - } - } -} - - -/*! - * @brief ベースアイテム構造体の鑑定済みフラグをリセットする。 - * @return なし - */ -static void k_info_reset(void) -{ - int i; - - /* Reset the "objects" */ - for (i = 1; i < max_k_idx; i++) - { - object_kind *k_ptr = &k_info[i]; - - /* Reset "tried" */ - k_ptr->tried = FALSE; - - /* Reset "aware" */ - k_ptr->aware = FALSE; - } -} - - -/*! - * @brief プレイヤー構造体の内容を初期値で消去する(名前を除く) / Clear all the global "character" data (without name) - * @return なし - */ -static void player_wipe_without_name(void) -{ - int i; - player_type tmp; - - /* Temporary copy for migration - written back later */ - COPY(&tmp, p_ptr, player_type); - - /* Hack -- free the "last message" string */ - if (p_ptr->last_message) string_free(p_ptr->last_message); - - /* Hack -- zero the struct */ - (void)WIPE(p_ptr, player_type); - - /* Wipe the history */ - for (i = 0; i < 4; i++) - { - strcpy(p_ptr->history[i], ""); - } - - /* Wipe the quests */ - for (i = 0; i < max_q_idx; i++) - { - quest_type* const q_ptr = &quest[i]; - - q_ptr->status = QUEST_STATUS_UNTAKEN; - - q_ptr->cur_num = 0; - q_ptr->max_num = 0; - q_ptr->type = 0; - q_ptr->level = 0; - q_ptr->r_idx = 0; - q_ptr->complev = 0; - q_ptr->comptime = 0; - } - - /* No weight */ - p_ptr->total_weight = 0; - - /* No items */ - inven_cnt = 0; - equip_cnt = 0; - - /* Clear the inventory */ - for (i = 0; i < INVEN_TOTAL; i++) - { - object_wipe(&inventory[i]); - } - - - /* Start with no artifacts made yet */ - for (i = 0; i < max_a_idx; i++) - { - artifact_type *a_ptr = &a_info[i]; - a_ptr->cur_num = 0; - } - - /* Reset the objects */ - k_info_reset(); - - /* Reset the "monsters" */ - for (i = 1; i < max_r_idx; i++) - { - monster_race *r_ptr = &r_info[i]; - - /* Hack -- Reset the counter */ - r_ptr->cur_num = 0; - - /* Hack -- Reset the max counter */ - r_ptr->max_num = 100; - - /* Hack -- Reset the max counter */ - if (r_ptr->flags1 & RF1_UNIQUE) r_ptr->max_num = 1; - - /* Hack -- Non-unique Nazguls are semi-unique */ - else if (r_ptr->flags7 & RF7_NAZGUL) r_ptr->max_num = MAX_NAZGUL_NUM; - - /* Clear visible kills in this life */ - r_ptr->r_pkills = 0; - - /* Clear all kills in this life */ - r_ptr->r_akills = 0; - } - - - /* Hack -- Well fed player */ - p_ptr->food = PY_FOOD_FULL - 1; - - - /* Wipe the spells */ - if (p_ptr->pclass == CLASS_SORCERER) - { - p_ptr->spell_learned1 = p_ptr->spell_learned2 = 0xffffffffL; - p_ptr->spell_worked1 = p_ptr->spell_worked2 = 0xffffffffL; - } - else - { - p_ptr->spell_learned1 = p_ptr->spell_learned2 = 0L; - p_ptr->spell_worked1 = p_ptr->spell_worked2 = 0L; - } - p_ptr->spell_forgotten1 = p_ptr->spell_forgotten2 = 0L; - for (i = 0; i < 64; i++) p_ptr->spell_order[i] = 99; - p_ptr->learned_spells = 0; - p_ptr->add_spells = 0; - p_ptr->knowledge = 0; - - /* Clean the mutation count */ - p_ptr->mutant_regenerate_mod = 100; - - /* Clear "cheat" options */ - cheat_peek = FALSE; - cheat_hear = FALSE; - cheat_room = FALSE; - cheat_xtra = FALSE; - cheat_know = FALSE; - cheat_live = FALSE; - cheat_save = FALSE; - cheat_diary_output = FALSE; - cheat_turn = FALSE; - - /* Assume no winning game */ - p_ptr->total_winner = FALSE; - - p_ptr->timewalk = FALSE; - - /* Assume no panic save */ - p_ptr->panic_save = 0; - - /* Assume no cheating */ - p_ptr->noscore = 0; - p_ptr->wizard = FALSE; - - /* Not waiting to report score */ - p_ptr->wait_report_score = FALSE; - - /* Default pet command settings */ - p_ptr->pet_follow_distance = PET_FOLLOW_DIST; - p_ptr->pet_extra_flags = (PF_TELEPORT | PF_ATTACK_SPELL | PF_SUMMON_SPELL); - - /* Wipe the recall depths */ - for (i = 0; i < max_d_idx; i++) - { - max_dlv[i] = 0; - } - - p_ptr->visit = 1; - - /* Reset wild_mode to FALSE */ - p_ptr->wild_mode = FALSE; - - for (i = 0; i < 108; i++) - { - p_ptr->magic_num1[i] = 0; - p_ptr->magic_num2[i] = 0; - } - - /* Level one */ - p_ptr->max_plv = p_ptr->lev = 1; - - /* Initialize arena and rewards information -KMW- */ - p_ptr->arena_number = 0; - p_ptr->inside_arena = FALSE; - p_ptr->inside_quest = 0; - for (i = 0; i < MAX_MANE; i++) - { - p_ptr->mane_spell[i] = -1; - p_ptr->mane_dam[i] = 0; - } - p_ptr->mane_num = 0; - p_ptr->exit_bldg = TRUE; /* only used for arena now -KMW- */ - - /* Bounty */ - p_ptr->today_mon = 0; - - /* Reset monster arena */ - battle_monsters(); - - /* Reset mutations */ - p_ptr->muta1 = 0; - p_ptr->muta2 = 0; - p_ptr->muta3 = 0; - - /* Reset virtues */ - for (i = 0; i < 8; i++) p_ptr->virtues[i]=0; - - p_ptr->dungeon_idx = 0; - - /* Set the recall dungeon accordingly */ - if (vanilla_town || ironman_downward) - { - p_ptr->recall_dungeon = DUNGEON_ANGBAND; - } - else - { - p_ptr->recall_dungeon = DUNGEON_GALGALS; - } - - /* Data migration */ - memcpy(p_ptr->name, tmp.name, sizeof(tmp.name)); -} - - - -/*! - * @brief ダンジョン内部のクエストを初期化する / Initialize random quests and final quests - * @return なし - */ -static void init_dungeon_quests(void) -{ - int number_of_quests = MAX_RANDOM_QUEST - MIN_RANDOM_QUEST + 1; - int i; - - /* Init the random quests */ - init_flags = INIT_ASSIGN; - p_ptr->inside_quest = MIN_RANDOM_QUEST; - - process_dungeon_file("q_info.txt", 0, 0, 0, 0); - - p_ptr->inside_quest = 0; - - /* Generate quests */ - for (i = MIN_RANDOM_QUEST + number_of_quests - 1; i >= MIN_RANDOM_QUEST; i--) - { - quest_type *q_ptr = &quest[i]; - monster_race *quest_r_ptr; - - q_ptr->status = QUEST_STATUS_TAKEN; - determine_random_questor(q_ptr); - - /* Mark uniques */ - quest_r_ptr = &r_info[q_ptr->r_idx]; - quest_r_ptr->flags1 |= RF1_QUESTOR; - - q_ptr->max_num = 1; - } - - /* Init the two main quests (Oberon + Serpent) */ - init_flags = INIT_ASSIGN; - p_ptr->inside_quest = QUEST_OBERON; - - process_dungeon_file("q_info.txt", 0, 0, 0, 0); - - quest[QUEST_OBERON].status = QUEST_STATUS_TAKEN; - - p_ptr->inside_quest = QUEST_SERPENT; - - process_dungeon_file("q_info.txt", 0, 0, 0, 0); - - quest[QUEST_SERPENT].status = QUEST_STATUS_TAKEN; - p_ptr->inside_quest = 0; -} - -/*! - * @brief ゲームターンを初期化する / Reset current_world_ptr->game_turn - * @details アンデッド系種族は開始時刻を夜からにする。 - * @return なし - */ -static void init_turn(void) -{ - if ((p_ptr->prace == RACE_VAMPIRE) || - (p_ptr->prace == RACE_SKELETON) || - (p_ptr->prace == RACE_ZOMBIE) || - (p_ptr->prace == RACE_SPECTRE)) - { - /* Undead start just after midnight */ - current_world_ptr->game_turn = (TURNS_PER_TICK*3 * TOWN_DAWN) / 4 + 1; - current_world_ptr->game_turn_limit = TURNS_PER_TICK * TOWN_DAWN * MAX_DAYS + TURNS_PER_TICK * TOWN_DAWN * 3 / 4; - } - else - { - current_world_ptr->game_turn = 1; - current_world_ptr->game_turn_limit = TURNS_PER_TICK * TOWN_DAWN * (MAX_DAYS - 1) + TURNS_PER_TICK * TOWN_DAWN * 3 / 4; - } - - current_world_ptr->dungeon_turn = 1; - current_world_ptr->dungeon_turn_limit = TURNS_PER_TICK * TOWN_DAWN * (MAX_DAYS - 1) + TURNS_PER_TICK * TOWN_DAWN * 3 / 4; -} - - -/*! - * @brief 所持状態にあるアイテムの中から一部枠の装備可能なものを装備させる。 - * @details アンデッド系種族は開始時刻を夜からにする。 - * @return なし - */ -static void wield_all(void) -{ - object_type *o_ptr; - object_type *i_ptr; - object_type object_type_body; - - int slot; - INVENTORY_IDX item; - - /* Scan through the slots backwards */ - for (item = INVEN_PACK - 1; item >= 0; item--) - { - o_ptr = &inventory[item]; - - /* Skip non-objects */ - if (!o_ptr->k_idx) continue; - - /* Make sure we can wield it and that there's nothing else in that slot */ - slot = wield_slot(o_ptr); - if (slot < INVEN_RARM) continue; - if (slot == INVEN_LITE) continue; /* Does not wield toaches because buys a lantern soon */ - if (inventory[slot].k_idx) continue; - - i_ptr = &object_type_body; - object_copy(i_ptr, o_ptr); - i_ptr->number = 1; - - /* Decrease the item (from the pack) */ - if (item >= 0) - { - inven_item_increase(item, -1); - inven_item_optimize(item); - } - - /* Decrease the item (from the floor) */ - else - { - floor_item_increase(0 - item, -1); - floor_item_optimize(0 - item); - } - - o_ptr = &inventory[slot]; - object_copy(o_ptr, i_ptr); - p_ptr->total_weight += i_ptr->weight; - - /* Increment the equip counter by hand */ - equip_cnt++; - - } - return; -} - - -/*! - * プレイヤーの職業毎の初期装備テーブル。/\n - * Each player starts out with a few items, given as tval/sval pairs.\n - * In addition, he always has some food and a few torches.\n - */ -static byte player_init[MAX_CLASS][3][2] = -{ - { - /* Warrior */ - { TV_RING, SV_RING_RES_FEAR }, /* Warriors need it! */ - { TV_HARD_ARMOR, SV_CHAIN_MAIL }, - { TV_SWORD, SV_BROAD_SWORD } - }, - - { - /* Mage */ - { TV_SORCERY_BOOK, 0 }, /* Hack: for realm1 book */ - { TV_DEATH_BOOK, 0 }, /* Hack: for realm2 book */ - { TV_SWORD, SV_DAGGER } - }, - - { - /* Priest */ - { TV_SORCERY_BOOK, 0 }, /* Hack: for Life / Death book */ - { TV_DEATH_BOOK, 0 }, /* Hack: for realm2 book */ - { TV_HAFTED, SV_MACE } - }, - - { - /* Rogue */ - { TV_SORCERY_BOOK, 0 }, /* Hack: for realm1 book */ - { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, - { TV_SWORD, SV_DAGGER } - }, - - { - /* Ranger */ - { TV_NATURE_BOOK, 0 }, - { TV_DEATH_BOOK, 0 }, /* Hack: for realm2 book */ - { TV_SWORD, SV_DAGGER } - }, - - { - /* Paladin */ - { TV_SORCERY_BOOK, 0 }, - { TV_SCROLL, SV_SCROLL_PROTECTION_FROM_EVIL }, - { TV_SWORD, SV_BROAD_SWORD } - }, - - { - /* Warrior-Mage */ - { TV_SORCERY_BOOK, 0 }, /* Hack: for realm1 book */ - { TV_DEATH_BOOK, 0 }, /* Hack: for realm2 book */ - { TV_SWORD, SV_SHORT_SWORD } - }, - - { - /* Chaos Warrior */ - { TV_SORCERY_BOOK, 0 }, /* Hack: For realm1 book */ - { TV_HARD_ARMOR, SV_METAL_SCALE_MAIL }, - { TV_SWORD, SV_BROAD_SWORD } - }, - - { - /* Monk */ - { TV_SORCERY_BOOK, 0 }, - { TV_POTION, SV_POTION_SPEED }, - { TV_POTION, SV_POTION_HEROISM } - }, - - { - /* Mindcrafter */ - { TV_POTION, SV_POTION_SPEED }, - { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, - { TV_SWORD, SV_SMALL_SWORD } - }, - - { - /* High Mage */ - { TV_SORCERY_BOOK, 0 }, /* Hack: for realm1 book */ - { TV_RING, SV_RING_SUSTAIN_INT}, - { TV_SWORD, SV_DAGGER } - }, - - { - /* Tourist */ - { TV_FOOD, SV_FOOD_JERKY}, - { TV_SCROLL, SV_SCROLL_MAPPING }, - { TV_BOW, SV_SLING} - }, - - { - /* Imitator */ - { TV_POTION, SV_POTION_SPEED }, - { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, - { TV_SWORD, SV_SHORT_SWORD} - }, - - { - /* Beastmaster */ - { TV_TRUMP_BOOK, 0 }, - { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, - { TV_POLEARM, SV_SPEAR} - }, - - { - /* Sorcerer */ - { TV_HAFTED, SV_WIZSTAFF }, /* Hack: for realm1 book */ - { TV_RING, SV_RING_SUSTAIN_INT}, - { TV_WAND, SV_WAND_MAGIC_MISSILE } - }, - - { - /* Archer */ - { TV_BOW, SV_SHORT_BOW }, - { TV_SOFT_ARMOR, SV_LEATHER_SCALE_MAIL}, - { TV_SWORD, SV_SHORT_SWORD }, - }, - - { - /* Magic eater */ - { TV_WAND, SV_WAND_MAGIC_MISSILE }, - { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR}, - { TV_SWORD, SV_SHORT_SWORD }, - }, - - { - /* Bard */ - { TV_MUSIC_BOOK, 0 }, - { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR}, - { TV_SWORD, SV_SHORT_SWORD }, - }, - - { - /* Red Mage */ - { TV_ARCANE_BOOK, 0 }, - { TV_SOFT_ARMOR, SV_HARD_LEATHER_ARMOR}, - { TV_SWORD, SV_SHORT_SWORD }, - }, - - { - /* Samurai */ - { TV_HISSATSU_BOOK, 0 }, - { TV_HARD_ARMOR, SV_CHAIN_MAIL }, - { TV_SWORD, SV_BROAD_SWORD } - }, - - { - /* ForceTrainer */ - { TV_SORCERY_BOOK, 0 }, - { TV_POTION, SV_POTION_SPEED }, - { TV_POTION, SV_POTION_RESTORE_MANA } - }, - - { - /* Blue Mage */ - { TV_SOFT_ARMOR, SV_ROBE }, - { TV_WAND, SV_WAND_MAGIC_MISSILE }, - { TV_SWORD, SV_DAGGER } - }, - - { - /* Cavalry */ - { TV_BOW, SV_SHORT_BOW }, - { TV_SOFT_ARMOR, SV_LEATHER_SCALE_MAIL}, - { TV_POLEARM, SV_BROAD_SPEAR} - }, - - { - /* Berserker */ - { TV_POTION, SV_POTION_HEALING }, - { TV_HARD_ARMOR, SV_AUGMENTED_CHAIN_MAIL }, - { TV_POLEARM, SV_BROAD_AXE } - }, - - { - /* Weaponsmith */ - { TV_RING, SV_RING_RES_FEAR }, /* Warriors need it! */ - { TV_HARD_ARMOR, SV_CHAIN_MAIL }, - { TV_POLEARM, SV_BROAD_AXE } - }, - { - /* Mirror-Master */ - { TV_POTION, SV_POTION_SPEED }, - { TV_RING, SV_RING_SUSTAIN_INT}, - { TV_SWORD, SV_DAGGER } - }, - { - /* Ninja */ - { TV_POTION, SV_POTION_SPEED }, - { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, - { TV_SWORD, SV_DAGGER } - }, - { - /* Sniper */ - { TV_BOW, SV_LIGHT_XBOW }, - { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, - { TV_SWORD, SV_DAGGER } - }, -}; - -/*! - * @brief 初期所持アイテムの処理 / Add an outfit object - * @details アイテムを既知のものとした上でwield_all()関数により装備させる。 - * @param o_ptr 処理したいオブジェクト構造体の参照ポインタ - * @return なし - */ -static void add_outfit(object_type *o_ptr) -{ - s16b slot; - - object_aware(o_ptr); - object_known(o_ptr); - slot = inven_carry(o_ptr); - - /* Auto-inscription */ - autopick_alter_item(slot, FALSE); - - /* Now try wielding everything */ - wield_all(); -} - - -/*! - * @brief 種族/職業/性格などに基づき初期所持アイテムを設定するメインセット関数。 / Init players with some belongings - * @details Having an item makes the player "aware" of its purpose. - * @return なし - */ -void player_outfit(void) -{ - int i; - OBJECT_TYPE_VALUE tv; - OBJECT_SUBTYPE_VALUE sv; - - object_type forge; - object_type *q_ptr; - - q_ptr = &forge; - - /* Give the player some food */ - switch (p_ptr->prace) - { - case RACE_VAMPIRE: - /* Nothing! */ - /* Vampires can drain blood of creatures */ - break; - - case RACE_DEMON: - /* Demon can drain vitality from humanoid corpse */ - get_mon_num_prep(monster_hook_human, NULL); - - for (i = rand_range(3,4); i > 0; i--) - { - object_prep(q_ptr, lookup_kind(TV_CORPSE, SV_CORPSE)); - q_ptr->pval = get_mon_num(2); - if(q_ptr->pval) - { - q_ptr->number = 1; - add_outfit(q_ptr); - } - } - break; - - case RACE_SKELETON: - case RACE_GOLEM: - case RACE_ZOMBIE: - case RACE_SPECTRE: - /* Staff (of Nothing) */ - object_prep(q_ptr, lookup_kind(TV_STAFF, SV_STAFF_NOTHING)); - q_ptr->number = 1; - - add_outfit(q_ptr); - break; - - case RACE_ENT: - /* Potions of Water */ - object_prep(q_ptr, lookup_kind(TV_POTION, SV_POTION_WATER)); - q_ptr->number = (ITEM_NUMBER)rand_range(15, 23); - add_outfit(q_ptr); - - break; - - case RACE_ANDROID: - /* Flasks of oil */ - object_prep(q_ptr, lookup_kind(TV_FLASK, SV_ANY)); - - /* Fuel with oil (move pval to xtra4) */ - apply_magic(q_ptr, 1, AM_NO_FIXED_ART); - - q_ptr->number = (ITEM_NUMBER)rand_range(7, 12); - add_outfit(q_ptr); - - break; - - default: - /* Food rations */ - object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_RATION)); - q_ptr->number = (ITEM_NUMBER)rand_range(3, 7); - - add_outfit(q_ptr); - } - q_ptr = &forge; - - if ((p_ptr->prace == RACE_VAMPIRE) && (p_ptr->pclass != CLASS_NINJA)) - { - /* Hack -- Give the player scrolls of DARKNESS! */ - object_prep(q_ptr, lookup_kind(TV_SCROLL, SV_SCROLL_DARKNESS)); - - q_ptr->number = (ITEM_NUMBER)rand_range(2, 5); - - add_outfit(q_ptr); - } - else if (p_ptr->pclass != CLASS_NINJA) - { - /* Hack -- Give the player some torches */ - object_prep(q_ptr, lookup_kind(TV_LITE, SV_LITE_TORCH)); - q_ptr->number = (ITEM_NUMBER)rand_range(3, 7); - q_ptr->xtra4 = rand_range(3, 7) * 500; - - add_outfit(q_ptr); - } - q_ptr = &forge; - - if (p_ptr->prace == RACE_MERFOLK) - { - object_prep(q_ptr, lookup_kind(TV_RING, SV_RING_LEVITATION_FALL)); - q_ptr->number = 1; - add_outfit(q_ptr); - } - - if ((p_ptr->pclass == CLASS_RANGER) || (p_ptr->pclass == CLASS_CAVALRY)) - { - /* Hack -- Give the player some arrows */ - object_prep(q_ptr, lookup_kind(TV_ARROW, SV_AMMO_NORMAL)); - q_ptr->number = (byte)rand_range(15, 20); - - add_outfit(q_ptr); - } - if (p_ptr->pclass == CLASS_RANGER) - { - /* Hack -- Give the player some arrows */ - object_prep(q_ptr, lookup_kind(TV_BOW, SV_SHORT_BOW)); - - add_outfit(q_ptr); - } - else if (p_ptr->pclass == CLASS_ARCHER) - { - /* Hack -- Give the player some arrows */ - object_prep(q_ptr, lookup_kind(TV_ARROW, SV_AMMO_NORMAL)); - q_ptr->number = (ITEM_NUMBER)rand_range(15, 20); - - add_outfit(q_ptr); - } - else if (p_ptr->pclass == CLASS_HIGH_MAGE) - { - /* Hack -- Give the player some arrows */ - object_prep(q_ptr, lookup_kind(TV_WAND, SV_WAND_MAGIC_MISSILE)); - q_ptr->number = 1; - q_ptr->pval = (PARAMETER_VALUE)rand_range(25, 30); - - add_outfit(q_ptr); - } - else if (p_ptr->pclass == CLASS_SORCERER) - { - OBJECT_TYPE_VALUE book_tval; - for (book_tval = TV_LIFE_BOOK; book_tval <= TV_LIFE_BOOK+MAX_MAGIC-1; book_tval++) - { - /* Hack -- Give the player some arrows */ - object_prep(q_ptr, lookup_kind(book_tval, 0)); - q_ptr->number = 1; - - add_outfit(q_ptr); - } - } - else if (p_ptr->pclass == CLASS_TOURIST) - { - if (p_ptr->pseikaku != SEIKAKU_SEXY) - { - /* Hack -- Give the player some arrows */ - object_prep(q_ptr, lookup_kind(TV_SHOT, SV_AMMO_LIGHT)); - q_ptr->number = rand_range(15, 20); - - add_outfit(q_ptr); - } - - object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_BISCUIT)); - q_ptr->number = rand_range(2, 4); - - add_outfit(q_ptr); - - object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_WAYBREAD)); - q_ptr->number = rand_range(2, 4); - - add_outfit(q_ptr); - - object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_JERKY)); - q_ptr->number = rand_range(1, 3); - - add_outfit(q_ptr); - - object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_PINT_OF_ALE)); - q_ptr->number = rand_range(2, 4); - - add_outfit(q_ptr); - - object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_PINT_OF_WINE)); - q_ptr->number = rand_range(2, 4); - - add_outfit(q_ptr); - } - else if (p_ptr->pclass == CLASS_NINJA) - { - /* Hack -- Give the player some arrows */ - object_prep(q_ptr, lookup_kind(TV_SPIKE, 0)); - q_ptr->number = rand_range(15, 20); - - add_outfit(q_ptr); - } - else if (p_ptr->pclass == CLASS_SNIPER) - { - /* Hack -- Give the player some bolts */ - object_prep(q_ptr, lookup_kind(TV_BOLT, SV_AMMO_NORMAL)); - q_ptr->number = rand_range(15, 20); - - add_outfit(q_ptr); - } - - if(p_ptr->pseikaku == SEIKAKU_SEXY) - { - player_init[p_ptr->pclass][2][0] = TV_HAFTED; - player_init[p_ptr->pclass][2][1] = SV_WHIP; - } - - /* Hack -- Give the player three useful objects */ - for (i = 0; i < 3; i++) - { - /* Look up standard equipment */ - tv = player_init[p_ptr->pclass][i][0]; - sv = player_init[p_ptr->pclass][i][1]; - - if ((p_ptr->prace == RACE_ANDROID) && ((tv == TV_SOFT_ARMOR) || (tv == TV_HARD_ARMOR))) continue; - /* Hack to initialize spellbooks */ - if (tv == TV_SORCERY_BOOK) tv = TV_LIFE_BOOK + p_ptr->realm1 - 1; - else if (tv == TV_DEATH_BOOK) tv = TV_LIFE_BOOK + p_ptr->realm2 - 1; - - else if (tv == TV_RING && sv == SV_RING_RES_FEAR && - p_ptr->prace == RACE_BARBARIAN) - /* Barbarians do not need a ring of resist fear */ - sv = SV_RING_SUSTAIN_STR; - - else if (tv == TV_RING && sv == SV_RING_SUSTAIN_INT && p_ptr->prace == RACE_MIND_FLAYER) - { - tv = TV_POTION; - sv = SV_POTION_RESTORE_MANA; - } - q_ptr = &forge; - - /* Hack -- Give the player an object */ - object_prep(q_ptr, lookup_kind(tv, sv)); - - /* Assassins begin the game with a poisoned dagger */ - if ((tv == TV_SWORD || tv == TV_HAFTED) && (p_ptr->pclass == CLASS_ROGUE && - p_ptr->realm1 == REALM_DEATH)) /* Only assassins get a poisoned weapon */ - { - q_ptr->name2 = EGO_BRAND_POIS; - } - - add_outfit(q_ptr); - } - - /* Hack -- make aware of the water */ - k_info[lookup_kind(TV_POTION, SV_POTION_WATER)].aware = TRUE; -} - -/*! - * @brief プレイヤーの種族選択を行う / Player race - * @return なし - */ -static bool get_player_race(void) -{ - int k, n, cs, os; - concptr str; - char c; - char sym[MAX_RACES]; - char p2 = ')'; - char buf[80], cur[80]; - - /* Extra info */ - clear_from(10); - put_str(_("注意:《種族》によってキャラクターの先天的な資質やボーナスが変化します。", - "Note: Your 'race' determines various intrinsic factors and bonuses."), 23, 5); - - /* Dump races */ - for (n = 0; n < MAX_RACES; n++) - { - /* Analyze */ - rp_ptr = &race_info[n]; - str = rp_ptr->title; - - /* Display */ - if (n < 26) - sym[n] = I2A(n); - else - sym[n] = ('A' + n - 26); - sprintf(buf, "%c%c%s", sym[n], p2, str); - put_str(buf, 12 + (n / 5), 1 + 16 * (n % 5)); - - } - - sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); - - /* Choose */ - k = -1; - cs = p_ptr->prace; - os = MAX_RACES; - while (1) - { - /* Move Cursol */ - if (cs != os) - { - c_put_str(TERM_WHITE, cur, 12 + (os/5), 1 + 16 * (os%5)); - put_str(" ", 3, 40); - if(cs == MAX_RACES) - { - sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); - put_str(" ", 4, 40); - put_str(" ", 5, 40); - } - else - { - rp_ptr = &race_info[cs]; - str = rp_ptr->title; - sprintf(cur, "%c%c%s", sym[cs], p2, str); - c_put_str(TERM_L_BLUE, rp_ptr->title, 3, 40); - put_str(_("腕力 知能 賢さ 器用 耐久 魅力 経験 ", "Str Int Wis Dex Con Chr EXP "), 4, 40); - put_str(_("の種族修正", ": Race modification"), 3, 40 + strlen(rp_ptr->title)); - - sprintf(buf, "%+3d %+3d %+3d %+3d %+3d %+3d %+4d%% ", - rp_ptr->r_adj[0], rp_ptr->r_adj[1], rp_ptr->r_adj[2], rp_ptr->r_adj[3], - rp_ptr->r_adj[4], rp_ptr->r_adj[5], (rp_ptr->r_exp - 100)); - c_put_str(TERM_L_BLUE, buf, 5, 40); - } - c_put_str(TERM_YELLOW, cur, 12 + (cs/5), 1 + 16 * (cs%5)); - os = cs; - } - - if (k >= 0) break; - - sprintf(buf, _("種族を選んで下さい (%c-%c) ('='初期オプション設定): ", "Choose a race (%c-%c) ('=' for options): "), sym[0], sym[MAX_RACES-1]); - - put_str(buf, 10, 10); - c = inkey(); - if (c == 'Q') birth_quit(); - if (c == 'S') return (FALSE); - if (c == ' ' || c == '\r' || c == '\n') - { - if(cs == MAX_RACES) - { - k = randint0(MAX_RACES); - cs = k; - continue; - } - else - { - k = cs; - break; - } - } - if (c == '*') - { - k = randint0(MAX_RACES); - cs = k; - continue; - } - if (c == '8') - { - if (cs >= 5) cs -= 5; - } - if (c == '4') - { - if (cs > 0) cs--; - } - if (c == '6') - { - if (cs < MAX_RACES) cs++; - } - if (c == '2') - { - if ((cs + 5) <= MAX_RACES) cs += 5; - } - k = (islower(c) ? A2I(c) : -1); - if ((k >= 0) && (k < MAX_RACES)) - { - cs = k; - continue; - } - k = (isupper(c) ? (26 + c - 'A') : -1); - if ((k >= 26) && (k < MAX_RACES)) - { - cs = k; - continue; - } - else k = -1; - if (c == '?') - { -#ifdef JP - show_help("jraceclas.txt#TheRaces"); -#else - show_help("raceclas.txt#TheRaces"); -#endif - } - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Option((*)s effect score)")); - screen_load(); - } - else if (c !='2' && c !='4' && c !='6' && c !='8') bell(); - } - - /* Set race */ - p_ptr->prace = (byte_hack)k; - - rp_ptr = &race_info[p_ptr->prace]; - - /* Display */ - c_put_str(TERM_L_BLUE, rp_ptr->title, 4, 15); - - /* Success */ - return TRUE; -} - - -/*! - * @brief プレイヤーの職業選択を行う / Player class - * @return なし - */ -static bool get_player_class(void) -{ - int k, n, cs, os; - char c; - char sym[MAX_CLASS_CHOICE]; - char p2 = ')'; - char buf[80], cur[80]; - concptr str; - - - /* Extra info */ - clear_from(10); - put_str(_("注意:《職業》によってキャラクターの先天的な能力やボーナスが変化します。", - "Note: Your 'class' determines various intrinsic abilities and bonuses."), 23, 5); - - put_str(_("()で囲まれた選択肢はこの種族には似合わない職業です。", - "Any entries in parentheses should only be used by advanced players."), 11, 5); - - - /* Dump classes */ - for (n = 0; n < MAX_CLASS_CHOICE; n++) - { - /* Analyze */ - cp_ptr = &class_info[n]; - mp_ptr = &m_info[n]; - str = cp_ptr->title; - if (n < 26) - sym[n] = I2A(n); - else - sym[n] = ('A' + n - 26); - - /* Display */ - if (!(rp_ptr->choice & (1L << n))) - sprintf(buf, "%c%c(%s)", sym[n], p2, str); - else - sprintf(buf, "%c%c%s", sym[n], p2, str); - - put_str(buf, 13+ (n/4), 2 + 19 * (n%4)); - } - - sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); - - /* Get a class */ - k = -1; - cs = p_ptr->pclass; - os = MAX_CLASS_CHOICE; - while (1) - { - /* Move Cursol */ - if (cs != os) - { - c_put_str(TERM_WHITE, cur, 13 + (os/4), 2 + 19 * (os%4)); - put_str(" ", 3, 40); - if(cs == MAX_CLASS_CHOICE) - { - sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); - put_str(" ", 4, 40); - put_str(" ", 5, 40); - } - else - { - cp_ptr = &class_info[cs]; - mp_ptr = &m_info[cs]; - str = cp_ptr->title; - if (!(rp_ptr->choice & (1L << cs))) - sprintf(cur, "%c%c(%s)", sym[cs], p2, str); - else - sprintf(cur, "%c%c%s", sym[cs], p2, str); - - c_put_str(TERM_L_BLUE, cp_ptr->title, 3, 40); - put_str(_("の職業修正", ": Class modification"), 3, 40 + strlen(cp_ptr->title)); - put_str(_("腕力 知能 賢さ 器用 耐久 魅力 経験 ", "Str Int Wis Dex Con Chr EXP "), 4, 40); - sprintf(buf, "%+3d %+3d %+3d %+3d %+3d %+3d %+4d%% ", - cp_ptr->c_adj[0], cp_ptr->c_adj[1], cp_ptr->c_adj[2], cp_ptr->c_adj[3], - cp_ptr->c_adj[4], cp_ptr->c_adj[5], cp_ptr->c_exp); - c_put_str(TERM_L_BLUE, buf, 5, 40); - } - c_put_str(TERM_YELLOW, cur, 13 + (cs / 4), 2 + 19 * (cs % 4)); - os = cs; - } - - if (k >= 0) break; - - sprintf(buf, _("職業を選んで下さい (%c-%c) ('='初期オプション設定): ", "Choose a class (%c-%c) ('=' for options): "), sym[0], sym[MAX_CLASS_CHOICE-1]); - - put_str(buf, 10, 10); - c = inkey(); - if (c == 'Q') birth_quit(); - if (c == 'S') return (FALSE); - if (c == ' ' || c == '\r' || c == '\n') - { - if(cs == MAX_CLASS_CHOICE) - { - k = randint0(MAX_CLASS_CHOICE); - cs = k; - continue; - } - else - { - k = cs; - break; - } - } - if (c == '*') - { - k = randint0(MAX_CLASS_CHOICE); - cs = k; - continue; - } - if (c == '8') - { - if (cs >= 4) cs -= 4; - } - if (c == '4') - { - if (cs > 0) cs--; - } - if (c == '6') - { - if (cs < MAX_CLASS_CHOICE) cs++; - } - if (c == '2') - { - if ((cs + 4) <= MAX_CLASS_CHOICE) cs += 4; - } - k = (islower(c) ? A2I(c) : -1); - if ((k >= 0) && (k < MAX_CLASS_CHOICE)) - { - cs = k; - continue; - } - k = (isupper(c) ? (26 + c - 'A') : -1); - if ((k >= 26) && (k < MAX_CLASS_CHOICE)) - { - cs = k; - continue; - } - else k = -1; - if (c == '?') - { -#ifdef JP - show_help("jraceclas.txt#TheClasses"); -#else - show_help("raceclas.txt#TheClasses"); -#endif - } - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Option((*)s effect score)")); - screen_load(); - } - else if (c !='2' && c !='4' && c !='6' && c !='8') bell(); - } - - /* Set class */ - p_ptr->pclass = (byte_hack)k; - cp_ptr = &class_info[p_ptr->pclass]; - mp_ptr = &m_info[p_ptr->pclass]; - - /* Display */ - c_put_str(TERM_L_BLUE, cp_ptr->title, 5, 15); - - return TRUE; -} - - -/*! - * @brief プレイヤーの性格選択を行う / Player Player seikaku - * @return なし - */ -static bool get_player_seikaku(void) -{ - int k; - int n, os, cs; - char c; - char sym[MAX_SEIKAKU]; - char p2 = ')'; - char buf[80], cur[80]; - char tmp[64]; - concptr str; - - /* Extra info */ - clear_from(10); - put_str(_("注意:《性格》によってキャラクターの能力やボーナスが変化します。", "Note: Your personality determines various intrinsic abilities and bonuses."), 23, 5); - - /* Dump seikakus */ - for (n = 0; n < MAX_SEIKAKU; n++) - { - if(seikaku_info[n].sex && (seikaku_info[n].sex != (p_ptr->psex+1))) continue; - - /* Analyze */ - ap_ptr = &seikaku_info[n]; - str = ap_ptr->title; - if (n < 26) - sym[n] = I2A(n); - else - sym[n] = ('A' + n - 26); - - /* Display */ - sprintf(buf, "%c%c%s", I2A(n), p2, str); - put_str(buf, 12 + (n/4), 2 + 18 * (n%4)); - } - - sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); - - /* Get a seikaku */ - k = -1; - cs = p_ptr->pseikaku; - os = MAX_SEIKAKU; - while (1) - { - /* Move Cursol */ - if (cs != os) - { - c_put_str(TERM_WHITE, cur, 12 + (os/4), 2 + 18 * (os%4)); - put_str(" ", 3, 40); - if(cs == MAX_SEIKAKU) - { - sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); - put_str(" ", 4, 40); - put_str(" ", 5, 40); - } - else - { - ap_ptr = &seikaku_info[cs]; - str = ap_ptr->title; - sprintf(cur, "%c%c%s", sym[cs], p2, str); - c_put_str(TERM_L_BLUE, ap_ptr->title, 3, 40); - put_str(_("の性格修正", ": Personality modification"), 3, 40+strlen(ap_ptr->title)); - put_str(_("腕力 知能 賢さ 器用 耐久 魅力 ", "Str Int Wis Dex Con Chr "), 4, 40); - sprintf(buf, "%+3d %+3d %+3d %+3d %+3d %+3d ", - ap_ptr->a_adj[0], ap_ptr->a_adj[1], ap_ptr->a_adj[2], ap_ptr->a_adj[3], - ap_ptr->a_adj[4], ap_ptr->a_adj[5]); - c_put_str(TERM_L_BLUE, buf, 5, 40); - } - c_put_str(TERM_YELLOW, cur, 12 + (cs/4), 2 + 18 * (cs%4)); - os = cs; - } - - if (k >= 0) break; - - sprintf(buf, _("性格を選んで下さい (%c-%c) ('='初期オプション設定): ", "Choose a personality (%c-%c) ('=' for options): "), sym[0], sym[MAX_SEIKAKU-1]); - - put_str(buf, 10, 10); - c = inkey(); - if (c == 'Q') birth_quit(); - if (c == 'S') return (FALSE); - if (c == ' ' || c == '\r' || c == '\n') - { - if(cs == MAX_SEIKAKU) - { - do - { - k = randint0(MAX_SEIKAKU); - } - while(seikaku_info[k].sex && (seikaku_info[k].sex != (p_ptr->psex+1))); - cs = k; - continue; - } - else - { - k = cs; - break; - } - } - if (c == '*') - { - do - { - k = randint0(n); - } - while(seikaku_info[k].sex && (seikaku_info[k].sex != (p_ptr->psex+1))); - cs = k; - continue; - } - if (c == '8') - { - if (cs >= 4) cs -= 4; - if (cs != MAX_SEIKAKU && seikaku_info[cs].sex && (seikaku_info[cs].sex != (p_ptr->psex+1))) - { - if((cs - 4) > 0) - cs -= 4; - else - cs += 4; - } - } - if (c == '4') - { - if (cs > 0) cs--; - if (cs != MAX_SEIKAKU && seikaku_info[cs].sex && (seikaku_info[cs].sex != (p_ptr->psex+1))) - { - if((cs - 1) > 0) - cs--; - else - cs++; - } - } - if (c == '6') - { - if (cs < MAX_SEIKAKU) cs++; - if (cs != MAX_SEIKAKU && seikaku_info[cs].sex && (seikaku_info[cs].sex != (p_ptr->psex+1))) - { - if((cs + 1) <= MAX_SEIKAKU) - cs++; - else - cs--; - } - } - if (c == '2') - { - if ((cs + 4) <= MAX_SEIKAKU) cs += 4; - if (cs != MAX_SEIKAKU && seikaku_info[cs].sex && (seikaku_info[cs].sex != (p_ptr->psex+1))) - { - if((cs + 4) <= MAX_SEIKAKU) - cs += 4; - else - cs -= 4; - } - } - k = (islower(c) ? A2I(c) : -1); - if ((k >= 0) && (k < MAX_SEIKAKU)) - { - if((seikaku_info[k].sex == 0) || (seikaku_info[k].sex == (p_ptr->psex+1))) - { - cs = k; - continue; - } - } - k = (isupper(c) ? (26 + c - 'A') : -1); - if ((k >= 26) && (k < MAX_SEIKAKU)) - { - if((seikaku_info[k].sex == 0) || (seikaku_info[k].sex == (p_ptr->psex+1))) - { - cs = k; - continue; - } - } - else k = -1; - if (c == '?') - { -#ifdef JP - show_help("jraceclas.txt#ThePersonalities"); -#else - show_help("raceclas.txt#ThePersonalities"); -#endif - } - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Option((*)s effect score)")); - screen_load(); - } - else if (c !='2' && c !='4' && c !='6' && c !='8') bell(); - } - - /* Set seikaku */ - p_ptr->pseikaku = (CHARACTER_IDX)k; - ap_ptr = &seikaku_info[p_ptr->pseikaku]; -#ifdef JP - strcpy(tmp, ap_ptr->title); - if(ap_ptr->no == 1) - strcat(tmp,"の"); -#else - strcpy(tmp, ap_ptr->title); - strcat(tmp," "); -#endif - strcat(tmp,p_ptr->name); - - c_put_str(TERM_L_BLUE, tmp, 1, 34); - - return TRUE; -} - -#ifdef ALLOW_AUTOROLLER -/*! - * @brief オートローラで得たい能力値の基準を決める。 - * @return なし - */ -static bool get_stat_limits(void) -{ - int i, j, m, cs, os; - int cval[6]; - char c; - char buf[80], cur[80]; - char inp[80]; - - /* Clean up */ - clear_from(10); - - /* Extra infomation */ - put_str(_("最低限得たい能力値を設定して下さい。", "Set minimum stats."), 10, 10); - put_str(_("2/8で項目選択、4/6で値の増減、Enterで次へ", "2/8 for Select, 4/6 for Change value, Enter for Goto next"), 11, 10); - - put_str(_(" 基本値 種族 職業 性格 合計値 最大値", " Base Rac Cla Per Total Maximum"), 13, 10); - - /* Output the maximum stats */ - for (i = 0; i < A_MAX; i++) - { - /* Reset the "success" counter */ - stat_match[i] = 0; - cval[i] = 3; - - /* Race/Class bonus */ - j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i]; - - /* Obtain the "maximal" stat */ - m = adjust_stat(17, j); - - /* Above 18 */ - if (m > 18) - { - sprintf(cur, "18/%02d", (m - 18)); - } - - /* From 3 to 18 */ - else - { - sprintf(cur, "%2d", m); - } - - /* Obtain the current stat */ - m = adjust_stat(cval[i], j); - - /* Above 18 */ - if (m > 18) - { - sprintf(inp, "18/%02d", (m - 18)); - } - - /* From 3 to 18 */ - else - { - sprintf(inp, "%2d", m); - } - - /* Prepare a prompt */ - sprintf(buf, "%6s %2d %+3d %+3d %+3d = %6s %6s", - stat_names[i], cval[i], rp_ptr->r_adj[i], cp_ptr->c_adj[i], - ap_ptr->a_adj[i], inp, cur); - - /* Dump the prompt */ - put_str(buf, 14 + i, 10); - } - - /* Get a minimum stat */ - cs = 0; - os = 6; - while (TRUE) - { - /* Move Cursol */ - if (cs != os) - { - if(os == 6) - { - c_put_str(TERM_WHITE, _("決定する", "Accept"), 21, 35); - } - else if(os < A_MAX) - { - c_put_str(TERM_WHITE, cur, 14 + os, 10); - } - if(cs == 6) - { - c_put_str(TERM_YELLOW, _("決定する", "Accept"), 21, 35); - } - else - { - /* Race/Class bonus */ - j = rp_ptr->r_adj[cs] + cp_ptr->c_adj[cs] + ap_ptr->a_adj[cs]; - - /* Obtain the current stat */ - m = adjust_stat(cval[cs], j); - - /* Above 18 */ - if (m > 18) - { - sprintf(inp, "18/%02d", (m - 18)); - } - - /* From 3 to 18 */ - else - { - sprintf(inp, "%2d", m); - } - - /* Prepare a prompt */ - sprintf(cur, "%6s %2d %+3d %+3d %+3d = %6s", - stat_names[cs], cval[cs], rp_ptr->r_adj[cs], - cp_ptr->c_adj[cs], ap_ptr->a_adj[cs], inp); - c_put_str(TERM_YELLOW, cur, 14 + cs, 10); - } - os = cs; - } - - /* Prompt for the minimum stats */ - c = inkey(); - switch ( c ){ - case 'Q': - birth_quit(); - case 'S': - return FALSE; - case ESCAPE: - break; - case ' ': - case '\r': - case '\n': - if(cs == 6) break; - cs++; - c = '2'; - break; - case '8': - case 'k': - if (cs > 0) cs--; - break; - case '2': - case 'j': - if (cs < A_MAX) cs++; - break; - case '4': - case 'h': - if (cs != 6) - { - if (cval[cs] == 3) - { - cval[cs] = 17; - os = 7; - } - else if (cval[cs] > 3) - { - cval[cs]--; - os = 7; - } - else return FALSE; - } - break; - case '6': - case 'l': - if (cs != 6) - { - if (cval[cs] == 17) - { - cval[cs] = 3; - os = 7; - } - else if (cval[cs] < 17) - { - cval[cs]++; - os = 7; - } - else return FALSE; - } - break; - case 'm': - if(cs != 6) - { - cval[cs] = 17; - os = 7; - } - break; - case 'n': - if(cs != 6) - { - cval[cs] = 3; - os = 7; - } - break; - case '?': -#ifdef JP - show_help("jbirth.txt#AutoRoller"); -#else - show_help("birth.txt#AutoRoller"); -#endif - break; - case '=': - screen_save(); -#ifdef JP - do_cmd_options_aux(OPT_PAGE_BIRTH, "初期オプション((*)はスコアに影響)"); -#else - do_cmd_options_aux(OPT_PAGE_BIRTH, "Birth Option((*)s effect score)"); -#endif - - screen_load(); - break; - default: - bell(); - break; - } - if(c == ESCAPE || ((c == ' ' || c == '\r' || c == '\n') && cs == 6))break; - } - - for (i = 0; i < A_MAX; i++) - { - /* Save the minimum stat */ - stat_limit[i] = (s16b)cval[i]; - } - - return TRUE; -} -#endif - -#ifdef ALLOW_AUTOROLLER -/*! - * @brief オートローラで得たい年齢、身長、体重、社会的地位の基準を決める。 - * @return なし - */ -static bool get_chara_limits(void) -{ -#define MAXITEMS 8 - - int i, j, m, cs, os; - int mval[MAXITEMS], cval[MAXITEMS]; - int max_percent, min_percent; - char c; - char buf[80], cur[80]; - concptr itemname[] = { - _("å¹´é½¢", "age"), - _("身長(インチ)", "height"), - _("体重(ポンド)", "weight"), - _("社会的地位", "social class") - }; - - clear_from(10); - - /* Prompt for the minimum stats */ - put_str(_("2/4/6/8で項目選択、+/-で値の増減、Enterで次へ", "2/4/6/8 for Select, +/- for Change value, Enter for Goto next"), 11, 10); - put_str(_("注意:身長と体重の最大値/最小値ぎりぎりの値は非常に出現確率が低くなります。", "Caution: Values near minimum or maximum is extremery rare."), 23, 2); - - if (p_ptr->psex == SEX_MALE) - { - max_percent = (int)(rp_ptr->m_b_ht+rp_ptr->m_m_ht*4-1) * 100 / (int)(rp_ptr->m_b_ht); - min_percent = (int)(rp_ptr->m_b_ht-rp_ptr->m_m_ht*4+1) * 100 / (int)(rp_ptr->m_b_ht); - } - else - { - max_percent = (int)(rp_ptr->f_b_ht+rp_ptr->f_m_ht*4-1) * 100 / (int)(rp_ptr->f_b_ht); - min_percent = (int)(rp_ptr->f_b_ht-rp_ptr->f_m_ht*4+1) * 100 / (int)(rp_ptr->f_b_ht); - } - - put_str(_("体格/地位の最小値/最大値を設定して下さい。", "Set minimum/maximum attribute."), 10, 10); - put_str(_(" 項 目 最小値 最大値", " Parameter Min Max"), 13,20); - - /* Output the maximum stats */ - for (i = 0; i < MAXITEMS; i++) - { - /* Obtain the "maximal" stat */ - switch (i) - { - case 0: /* Minimum age */ - m = rp_ptr->b_age + 1; - break; - case 1: /* Maximum age */ - m = rp_ptr->b_age + rp_ptr->m_age; - break; - - case 2: /* Minimum height */ - if (p_ptr->psex == SEX_MALE) m = rp_ptr->m_b_ht-rp_ptr->m_m_ht*4+1; - else m = rp_ptr->f_b_ht-rp_ptr->f_m_ht*4+1; - break; - case 3: /* Maximum height */ - if (p_ptr->psex == SEX_MALE) m = rp_ptr->m_b_ht+rp_ptr->m_m_ht*4-1; - else m = rp_ptr->f_b_ht+rp_ptr->f_m_ht*4-1; - break; - case 4: /* Minimum weight */ - if (p_ptr->psex == SEX_MALE) m = (rp_ptr->m_b_wt * min_percent / 100) - (rp_ptr->m_m_wt * min_percent / 75) +1; - else m = (rp_ptr->f_b_wt * min_percent / 100) - (rp_ptr->f_m_wt * min_percent / 75) +1; - break; - case 5: /* Maximum weight */ - if (p_ptr->psex == SEX_MALE) m = (rp_ptr->m_b_wt * max_percent / 100) + (rp_ptr->m_m_wt * max_percent / 75) -1; - else m = (rp_ptr->f_b_wt * max_percent / 100) + (rp_ptr->f_m_wt * max_percent / 75) -1; - break; - case 6: /* Minimum social class */ - m = 1; - break; - case 7: /* Maximum social class */ - m = 100; - break; - default: - m = 1; - break; - } - - /* Save the maximum or minimum */ - mval[i] = m; - cval[i] = m; - } - - for (i = 0; i < 4; i++) - { - /* Prepare a prompt */ - sprintf(buf, "%-12s (%3d - %3d)", itemname[i], mval[i*2], mval[i*2+1]); - - /* Dump the prompt */ - put_str(buf, 14 + i, 20); - - for (j = 0; j < 2; j++) - { - sprintf(buf, " %3d", cval[i*2+j]); - put_str(buf, 14 + i, 45 + 8 * j); - } - } - - /* Get a minimum stat */ - cs = 0; - os = MAXITEMS; - while (TRUE) - { - /* Move Cursol */ - if (cs != os) - { - const char accept[] = _("決定する", "Accept"); - - if(os == MAXITEMS) - { - c_put_str(TERM_WHITE, accept, 19, 35); - } - else - { - c_put_str(TERM_WHITE, cur, 14 + os/2, 45 + 8 * (os%2)); - } - - if(cs == MAXITEMS) - { - c_put_str(TERM_YELLOW, accept, 19, 35); - } - else - { - /* Prepare a prompt */ - sprintf(cur, " %3d", cval[cs]); - c_put_str(TERM_YELLOW, cur, 14 + cs/2, 45 + 8 * (cs%2)); - } - os = cs; - } - - /* Prompt for the minimum stats */ - c = inkey(); - switch (c){ - case 'Q': - birth_quit(); - case 'S': - return (FALSE); - case ESCAPE: - break; /*後でもう一回breakせんと*/ - case ' ': - case '\r': - case '\n': - if(cs == MAXITEMS) break; - cs++; - c = '6'; - break; - case '8': - case 'k': - if (cs-2 >= 0) cs -= 2; - break; - case '2': - case 'j': - if (cs < MAXITEMS) cs += 2; - if (cs > MAXITEMS) cs = MAXITEMS; - break; - case '4': - case 'h': - if (cs > 0) cs--; - break; - case '6': - case 'l': - if (cs < MAXITEMS) cs++; - break; - case '-': - case '<': - if (cs != MAXITEMS) - { - if(cs%2) - { - if(cval[cs] > cval[cs-1]) - { - cval[cs]--; - os = 127; - } - } - else - { - if(cval[cs] > mval[cs]) - { - cval[cs]--; - os = 127; - } - } - } - break; - case '+': - case '>': - if (cs != MAXITEMS) - { - if(cs%2) - { - if(cval[cs] < mval[cs]) - { - cval[cs]++; - os = 127; - } - } - else - { - if(cval[cs] < cval[cs+1]) - { - cval[cs]++; - os = 127; - } - } - } - break; - case 'm': - if(cs != MAXITEMS) - { - if(cs%2) - { - if(cval[cs] < mval[cs]) - { - cval[cs] = mval[cs]; - os = 127; - } - } - else - { - if(cval[cs] < cval[cs+1]) - { - cval[cs] = cval[cs+1]; - os = 127; - } - } - } - break; - case 'n': - if(cs != MAXITEMS) - { - if(cs%2) - { - if(cval[cs] > cval[cs-1]) - { - cval[cs] = cval[cs-1]; - os = 255; - } - } - else - { - if(cval[cs] > mval[cs]) - { - cval[cs] = mval[cs]; - os = 255; - } - } - } - break; - case '?': -#ifdef JP - show_help("jbirth.txt#AutoRoller"); -#else - show_help("birth.txt#AutoRoller"); -#endif - break; - case '=': - screen_save(); - do_cmd_options_aux(OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Option((*)s effect score)")); - screen_load(); - break; - default: - bell(); - break; - } - if(c == ESCAPE || ((c == ' ' || c == '\r' || c == '\n') && cs == MAXITEMS))break; - } - - /* Input the minimum stats */ - chara_limit.agemin = (s16b)cval[0]; - chara_limit.agemax = (s16b)cval[1]; - chara_limit.htmin = (s16b)cval[2]; - chara_limit.htmax = (s16b)cval[3]; - chara_limit.wtmin = (s16b)cval[4]; - chara_limit.wtmax = (s16b)cval[5]; - chara_limit.scmin = (s16b)cval[6]; - chara_limit.scmax = (s16b)cval[7]; - - return TRUE; -} -#endif - -#define HISTPREF_LIMIT 1024 -static char *histpref_buf = NULL; - -/*! - * @brief 生い立ちメッセージの内容をバッファに加える。 / Hook function for reading the histpref.prf file. - * @return なし - */ -void add_history_from_pref_line(concptr t) -{ - /* Do nothing if the buffer is not ready */ - if (!histpref_buf) return; - - my_strcat(histpref_buf, t, HISTPREF_LIMIT); -} - -/*! - * @brief 生い立ちメッセージをファイルからロードする。 - * @return なし - */ -static bool do_cmd_histpref(void) -{ - char buf[80]; - errr err; - int i, j, n; - char *s, *t; - char temp[64 * 4]; - char histbuf[HISTPREF_LIMIT]; - - if (!get_check(_("生い立ち設定ファイルをロードしますか? ", "Load background history preference file? "))) return FALSE; - - /* Prepare the buffer */ - histbuf[0] = '\0'; - histpref_buf = histbuf; - -#ifdef JP - sprintf(buf, "histedit-%s.prf", player_base); -#else - sprintf(buf, "histpref-%s.prf", player_base); -#endif - err = process_histpref_file(buf); - - /* Process 'hist????.prf' if 'hist????-.prf' doesn't exist */ - if (0 > err) - { -#ifdef JP - strcpy(buf, "histedit.prf"); -#else - strcpy(buf, "histpref.prf"); -#endif - err = process_histpref_file(buf); - } - - if (err) - { - msg_print(_("生い立ち設定ファイルの読み込みに失敗しました。", "Failed to load background history preference.")); - msg_print(NULL); - - /* Kill the buffer */ - histpref_buf = NULL; - - return FALSE; - } - else if (!histpref_buf[0]) - { - msg_print(_("有効な生い立ち設定はこのファイルにありません。", "There does not exist valid background history preference.")); - msg_print(NULL); - - /* Kill the buffer */ - histpref_buf = NULL; - - return FALSE; - } - - /* Clear the previous history strings */ - for (i = 0; i < 4; i++) p_ptr->history[i][0] = '\0'; - - /* Skip leading spaces */ - for (s = histpref_buf; *s == ' '; s++) /* loop */; - - /* Get apparent length */ - n = strlen(s); - - /* Kill trailing spaces */ - while ((n > 0) && (s[n - 1] == ' ')) s[--n] = '\0'; - - roff_to_buf(s, 60, temp, sizeof(temp)); - t = temp; - for (i = 0; i < 4; i++) - { - if (t[0] == 0) break; - else - { - strcpy(p_ptr->history[i], t); - t += strlen(t) + 1; - } - } - - /* Fill the remaining spaces */ - for (i = 0; i < 4; i++) - { - for (j = 0; p_ptr->history[i][j]; j++) /* loop */; - - for (; j < 59; j++) p_ptr->history[i][j] = ' '; - p_ptr->history[i][59] = '\0'; - } - - /* Kill the buffer */ - histpref_buf = NULL; - - return TRUE; -} - -/*! - * @brief 生い立ちメッセージを編集する。/Character background edit-mode - * @return なし - */ -static void edit_history(void) -{ - char old_history[4][60]; - TERM_LEN y = 0, x = 0; - int i, j; - - /* Edit character background */ - for (i = 0; i < 4; i++) - { - sprintf(old_history[i], "%s", p_ptr->history[i]); - } - /* Turn 0 to space */ - for (i = 0; i < 4; i++) - { - for (j = 0; p_ptr->history[i][j]; j++) /* loop */; - - for (; j < 59; j++) p_ptr->history[i][j] = ' '; - p_ptr->history[i][59] = '\0'; - } - display_player(1); -#ifdef JP - c_put_str(TERM_L_GREEN, "(キャラクターの生い立ち - 編集モード)", 11, 20); - put_str("[ カーソルキーで移動、Enterで終了、Ctrl-Aでファイル読み込み ]", 17, 10); -#else - c_put_str(TERM_L_GREEN, "(Character Background - Edit Mode)", 11, 20); - put_str("[ Cursor key for Move, Enter for End, Ctrl-A for Read pref ]", 17, 10); -#endif - - while (TRUE) - { - int skey; - char c; - - for (i = 0; i < 4; i++) - { - put_str(p_ptr->history[i], i + 12, 10); - } -#ifdef JP - if (iskanji2(p_ptr->history[y], x)) - c_put_str(TERM_L_BLUE, format("%c%c", p_ptr->history[y][x],p_ptr->history[y][x+1]), y + 12, x + 10); - else -#endif - c_put_str(TERM_L_BLUE, format("%c", p_ptr->history[y][x]), y + 12, x + 10); - - /* Place cursor just after cost of current stat */ - Term_gotoxy(x + 10, y + 12); - - /* Get special key code */ - skey = inkey_special(TRUE); - - /* Get a character code */ - if (!(skey & SKEY_MASK)) c = (char)skey; - else c = 0; - - if (skey == SKEY_UP || c == KTRL('p')) - { - y--; - if (y < 0) y = 3; -#ifdef JP - if ((x > 0) && (iskanji2(p_ptr->history[y], x-1))) x--; -#endif - } - else if (skey == SKEY_DOWN || c == KTRL('n')) - { - y++; - if (y > 3) y = 0; -#ifdef JP - if ((x > 0) && (iskanji2(p_ptr->history[y], x-1))) x--; -#endif - } - else if (skey == SKEY_RIGHT || c == KTRL('f')) - { -#ifdef JP - if (iskanji2(p_ptr->history[y], x)) x++; -#endif - x++; - if (x > 58) - { - x = 0; - if (y < 3) y++; - } - } - else if (skey == SKEY_LEFT || c == KTRL('b')) - { - x--; - if (x < 0) - { - if (y) - { - y--; - x = 58; - } - else x = 0; - } - -#ifdef JP - if ((x > 0) && (iskanji2(p_ptr->history[y], x-1))) x--; -#endif - } - else if (c == '\r' || c == '\n') - { - Term_erase(0, 11, 255); - Term_erase(0, 17, 255); -#ifdef JP - put_str("(キャラクターの生い立ち - 編集済み)", 11, 20); -#else - put_str("(Character Background - Edited)", 11, 20); -#endif - break; - } - else if (c == ESCAPE) - { - clear_from(11); -#ifdef JP - put_str("(キャラクターの生い立ち)", 11, 25); -#else - put_str("(Character Background)", 11, 25); -#endif - - for (i = 0; i < 4; i++) - { - sprintf(p_ptr->history[i], "%s", old_history[i]); - put_str(p_ptr->history[i], i + 12, 10); - } - break; - } - else if (c == KTRL('A')) - { - if (do_cmd_histpref()) - { -#ifdef JP - if ((x > 0) && (iskanji2(p_ptr->history[y], x - 1))) x--; -#endif - } - } - else if (c == '\010') - { - x--; - if (x < 0) - { - if (y) - { - y--; - x = 58; - } - else x = 0; - } - - p_ptr->history[y][x] = ' '; -#ifdef JP - if ((x > 0) && (iskanji2(p_ptr->history[y], x - 1))) - { - x--; - p_ptr->history[y][x] = ' '; - } -#endif - } -#ifdef JP - else if (iskanji(c) || isprint(c)) -#else - else if (isprint(c)) /* BUGFIX */ -#endif - { -#ifdef JP - if (iskanji2(p_ptr->history[y], x)) - { - p_ptr->history[y][x+1] = ' '; - } - - if (iskanji(c)) - { - if (x > 57) - { - x = 0; - y++; - if (y > 3) y = 0; - } - - if (iskanji2(p_ptr->history[y], x+1)) - { - p_ptr->history[y][x+2] = ' '; - } - - p_ptr->history[y][x++] = c; - - c = inkey(); - } -#endif - p_ptr->history[y][x++] = c; - if (x > 58) - { - x = 0; - y++; - if (y > 3) y = 0; - } - } - } /* while (TRUE) */ - -} - - -/*! - * @brief player_birth()関数のサブセット/Helper function for 'player_birth()' - * @details - * The delay may be reduced, but is recommended to keep players - * from continuously rolling up characters, which can be VERY - * expensive CPU wise. And it cuts down on player stupidity. - * @return なし - */ -static bool player_birth_aux(void) -{ - int i, k, n, cs, os; - - BIT_FLAGS mode = 0; - - bool flag = FALSE; - bool prev = FALSE; - - concptr str; - - char c; - -#if 0 - char p1 = '('; -#endif - - char p2 = ')'; - char b1 = '['; - char b2 = ']'; - - char buf[80], cur[80]; - - - /*** Intro ***/ - Term_clear(); - - /* Title everything */ - put_str(_("名前 :", "Name :"), 1,26); - put_str(_("性別 :", "Sex :"), 3, 1); - put_str(_("種族 :", "Race :"), 4, 1); - put_str(_("職業 :", "Class :"), 5, 1); - - /* Dump the default name */ - c_put_str(TERM_L_BLUE, p_ptr->name, 1, 34); - - /*** Instructions ***/ - - /* Display some helpful information */ - put_str(_("キャラクターを作成します。('S'やり直す, 'Q'終了, '?'ヘルプ)", "Make your charactor. ('S' Restart, 'Q' Quit, '?' Help)"), 8, 10); - - /*** Player sex ***/ - - /* Extra info */ - put_str(_("注意:《性別》の違いはゲーム上ほとんど影響を及ぼしません。", "Note: Your 'sex' does not have any significant gameplay effects."), 23, 5); - - /* Prompt for "Sex" */ - for (n = 0; n < MAX_SEXES; n++) - { - /* Analyze */ - sp_ptr = &sex_info[n]; - - /* Display */ -#ifdef JP - sprintf(buf, "%c%c%s", I2A(n), p2, sp_ptr->title); -#else - sprintf(buf, "%c%c %s", I2A(n), p2, sp_ptr->title); -#endif - put_str(buf, 12 + (n/5), 2 + 15 * (n%5)); - } - -#ifdef JP - sprintf(cur, "%c%c%s", '*', p2, "ランダム"); -#else - sprintf(cur, "%c%c %s", '*', p2, "Random"); -#endif - - /* Choose */ - k = -1; - cs = 0; - os = MAX_SEXES; - while (1) - { - if (cs != os) - { - put_str(cur, 12 + (os/5), 2 + 15 * (os%5)); - if(cs == MAX_SEXES) -#ifdef JP - sprintf(cur, "%c%c%s", '*', p2, "ランダム"); -#else - sprintf(cur, "%c%c %s", '*', p2, "Random"); -#endif - else - { - sp_ptr = &sex_info[cs]; - str = sp_ptr->title; -#ifdef JP - sprintf(cur, "%c%c%s", I2A(cs), p2, str); -#else - sprintf(cur, "%c%c %s", I2A(cs), p2, str); -#endif - } - c_put_str(TERM_YELLOW, cur, 12 + (cs/5), 2 + 15 * (cs%5)); - os = cs; - } - - if (k >= 0) break; - -#ifdef JP - sprintf(buf, "性別を選んで下さい (%c-%c) ('='初期オプション設定): ", I2A(0), I2A(n-1)); -#else - sprintf(buf, "Choose a sex (%c-%c) ('=' for options): ", I2A(0), I2A(n-1)); -#endif - - put_str(buf, 10, 10); - c = inkey(); - if (c == 'Q') birth_quit(); - if (c == 'S') return (FALSE); - if (c == ' ' || c == '\r' || c == '\n') - { - if(cs == MAX_SEXES) - k = randint0(MAX_SEXES); - else - k = cs; - break; - } - if (c == '*') - { - k = randint0(MAX_SEXES); - break; - } - if (c == '4') - { - if (cs > 0) cs--; - } - if (c == '6') - { - if (cs < MAX_SEXES) cs++; - } - k = (islower(c) ? A2I(c) : -1); - if ((k >= 0) && (k < MAX_SEXES)) - { - cs = k; - continue; - } - else k = -1; - if (c == '?') do_cmd_help(); - else if (c == '=') - { - screen_save(); -#ifdef JP - do_cmd_options_aux(OPT_PAGE_BIRTH, "初期オプション((*)はスコアに影響)"); -#else - do_cmd_options_aux(OPT_PAGE_BIRTH, "Birth Option((*)s effect score)"); -#endif - - screen_load(); - } - else if(c != '4' && c != '6')bell(); - } - - /* Set sex */ - p_ptr->psex = (byte_hack)k; - sp_ptr = &sex_info[p_ptr->psex]; - - /* Display */ - c_put_str(TERM_L_BLUE, sp_ptr->title, 3, 15); - - /* Clean up */ - clear_from(10); - - /* Choose the players race */ - p_ptr->prace = 0; - while(1) - { - char temp[80*10]; - concptr t; - - if (!get_player_race()) return FALSE; - - clear_from(10); - - roff_to_buf(race_jouhou[p_ptr->prace], 74, temp, sizeof(temp)); - t = temp; - - for (i = 0; i< 10; i++) - { - if(t[0] == 0) - break; - else - { - prt(t, 12+i, 3); - t += strlen(t) + 1; - } - } -#ifdef JP - if (get_check_strict("よろしいですか?", CHECK_DEFAULT_Y)) break; -#else - if (get_check_strict("Are you sure? ", CHECK_DEFAULT_Y)) break; -#endif - clear_from(10); - c_put_str(TERM_WHITE, " ", 4, 15); - } - - /* Clean up */ - clear_from(10); - - /* Choose the players class */ - p_ptr->pclass = 0; - while(1) - { - char temp[80*9]; - concptr t; - - if (!get_player_class()) return FALSE; - - clear_from(10); - roff_to_buf(class_jouhou[p_ptr->pclass], 74, temp, sizeof(temp)); - t = temp; - - for (i = 0; i< 9; i++) - { - if(t[0] == 0) - break; - else - { - prt(t, 12+i, 3); - t += strlen(t) + 1; - } - } - -#ifdef JP - if (get_check_strict("よろしいですか?", CHECK_DEFAULT_Y)) break; -#else - if (get_check_strict("Are you sure? ", CHECK_DEFAULT_Y)) break; -#endif - c_put_str(TERM_WHITE, " ", 5, 15); - } - - /* Choose the magic realms */ - if (!get_player_realms()) return FALSE; - - /* Choose the players seikaku */ - p_ptr->pseikaku = 0; - while(1) - { - char temp[80*8]; - concptr t; - - if (!get_player_seikaku()) return FALSE; - - clear_from(10); - roff_to_buf(seikaku_jouhou[p_ptr->pseikaku], 74, temp, sizeof(temp)); - t = temp; - - for (i = 0; i< A_MAX; i++) - { - if(t[0] == 0) - break; - else - { - prt(t, 12+i, 3); - t += strlen(t) + 1; - } - } -#ifdef JP - if (get_check_strict("よろしいですか?", CHECK_DEFAULT_Y)) break; -#else - if (get_check_strict("Are you sure? ", CHECK_DEFAULT_Y)) break; -#endif - c_put_str(TERM_L_BLUE, p_ptr->name, 1, 34); - prt("", 1, 34+strlen(p_ptr->name)); - } - - /* Clean up */ - clear_from(10); - put_str(" ", 3, 40); - put_str(" ", 4, 40); - put_str(" ", 5, 40); - - screen_save(); -#ifdef JP - do_cmd_options_aux(OPT_PAGE_BIRTH, "初期オプション((*)はスコアに影響)"); -#else - do_cmd_options_aux(OPT_PAGE_BIRTH, "Birth Option((*)s effect score)"); -#endif - - screen_load(); - -#ifdef ALLOW_AUTOROLLER - - /*** Autoroll ***/ - - if (autoroller || autochara) - { - /* Clear fields */ - auto_round = 0L; - } - - if (autoroller) - { - if (!get_stat_limits()) return FALSE; - } - - if (autochara) - { - if (!get_chara_limits()) return FALSE; - } - -#endif /* ALLOW_AUTOROLLER */ - - /* Clear */ - clear_from(10); - - /* Reset current_world_ptr->game_turn; before auto-roll and after choosing race */ - init_turn(); - - /*** Generate ***/ - - /* Roll */ - while (TRUE) - { - int col; - - col = 42; - - if (autoroller || autochara) - { - Term_clear(); - - /* Label count */ -#ifdef JP - put_str("回数 :", 10, col+13); -#else - put_str("Round:", 10, col+13); -#endif - - - /* Indicate the state */ -#ifdef JP - put_str("(ESCで停止)", 12, col+13); -#else - put_str("(Hit ESC to stop)", 12, col+13); -#endif - } - - /* Otherwise just get a character */ - else - { - /* Get a new character */ - get_stats(); - - /* Roll for age/height/weight */ - get_ahw(); - - /* Roll for social class */ - get_history(); - } - - /* Feedback */ - if (autoroller) - { - /* Label */ -#ifdef JP - put_str("最小値", 2, col+5); -#else - put_str(" Limit", 2, col+5); -#endif - - - /* Label */ -#ifdef JP - put_str("成功率", 2, col+13); -#else - put_str(" Freq", 2, col+13); -#endif - - - /* Label */ -#ifdef JP - put_str("現在値", 2, col+24); -#else - put_str(" Roll", 2, col+24); -#endif - - - /* Put the minimal stats */ - for (i = 0; i < A_MAX; i++) - { - int j, m; - - /* Label stats */ - put_str(stat_names[i], 3+i, col); - - /* Race/Class bonus */ - j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i]; - - /* Obtain the current stat */ - m = adjust_stat(stat_limit[i], j); - - /* Put the stat */ - cnv_stat(m, buf); - c_put_str(TERM_L_BLUE, buf, 3+i, col+5); - } - } - - /* Auto-roll */ - while (autoroller || autochara) - { - bool accept = TRUE; - - /* Get a new character */ - get_stats(); - - /* Advance the round */ - auto_round++; - - /* Hack -- Prevent overflow */ - if (auto_round >= 1000000000L) - { - auto_round = 1; - - if (autoroller) - { - for (i = 0; i < A_MAX; i++) - { - stat_match[i] = 0; - } - } - } - - if (autoroller) - { - /* Check and count acceptable stats */ - for (i = 0; i < A_MAX; i++) - { - /* This stat is okay */ - if (p_ptr->stat_max[i] >= stat_limit[i]) - { - stat_match[i]++; - } - - /* This stat is not okay */ - else - { - accept = FALSE; - } - } - } - - /* Break if "happy" */ - if (accept) - { - /* Roll for age/height/weight */ - get_ahw(); - - /* Roll for social class */ - get_history(); - - if (autochara) - { - if ((p_ptr->age < chara_limit.agemin) || (p_ptr->age > chara_limit.agemax)) accept = FALSE; - if ((p_ptr->ht < chara_limit.htmin) || (p_ptr->ht > chara_limit.htmax)) accept = FALSE; - if ((p_ptr->wt < chara_limit.wtmin) || (p_ptr->wt > chara_limit.wtmax)) accept = FALSE; - if ((p_ptr->sc < chara_limit.scmin) || (p_ptr->sc > chara_limit.scmax)) accept = FALSE; - } - if (accept) break; - } - - /* Take note every x rolls */ - flag = (!(auto_round % AUTOROLLER_STEP)); - - /* Update display occasionally */ - if (flag) - { - /* Dump data */ - birth_put_stats(); - - /* Dump round */ - put_str(format("%10ld", auto_round), 10, col+20); - -#ifdef AUTOROLLER_DELAY - /* Delay 1/10 second */ - if (flag) Term_xtra(TERM_XTRA_DELAY, 10); -#endif - - /* Make sure they see everything */ - Term_fresh(); - - /* Do not wait for a key */ - inkey_scan = TRUE; - - /* Check for a keypress */ - if (inkey()) - { - /* Roll for age/height/weight */ - get_ahw(); - - /* Roll for social class */ - get_history(); - - break; - } - } - } - - if (autoroller || autochara) sound(SOUND_LEVEL); - - /* Flush input */ - flush(); - - /*** Display ***/ - - /* Mode */ - mode = 0; - - /* Roll for base hitpoints */ - get_extra(TRUE); - - /* Roll for gold */ - get_money(); - - /* Hack -- get a chaos patron even if you are not a chaos warrior */ - p_ptr->chaos_patron = (s16b)randint0(MAX_PATRON); - - /* Input loop */ - while (TRUE) - { - /* Calculate the bonuses and hitpoints */ - p_ptr->update |= (PU_BONUS | PU_HP); - update_creature(p_ptr); - - p_ptr->chp = p_ptr->mhp; - p_ptr->csp = p_ptr->msp; - - /* Display the player */ - display_player(mode); - - /* Prepare a prompt (must squeeze everything in) */ - Term_gotoxy(2, 23); - Term_addch(TERM_WHITE, b1); - Term_addstr(-1, TERM_WHITE, _("'r' 次の数値", "'r'eroll")); - - if (prev) Term_addstr(-1, TERM_WHITE, _(", 'p' 前の数値", "'p'previous")); - if (mode) Term_addstr(-1, TERM_WHITE, _(", 'h' その他の情報", ", 'h' Misc.")); - else Term_addstr(-1, TERM_WHITE, _(", 'h' 生い立ちを表示", ", 'h'istory")); - Term_addstr(-1, TERM_WHITE, _(", Enter この数値に決定", ", or Enter to accept")); - Term_addch(TERM_WHITE, b2); - - /* Prompt and get a command */ - c = inkey(); - - /* Quit */ - if (c == 'Q') birth_quit(); - - /* Start over */ - if (c == 'S') return (FALSE); - - /* Escape accepts the roll */ - if (c == '\r' || c == '\n' || c == ESCAPE) break; - - /* Reroll this character */ - if ((c == ' ') || (c == 'r')) break; - - /* Previous character */ - if (prev && (c == 'p')) - { - load_prev_data(TRUE); - continue; - } - - /* Toggle the display */ - if ((c == 'H') || (c == 'h')) - { - mode = ((mode != 0) ? 0 : 1); - continue; - } - - /* Help */ - if (c == '?') - { -#ifdef JP - show_help("jbirth.txt#AutoRoller"); -#else - show_help("birth.txt#AutoRoller"); -#endif - continue; - } - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Option((*)s effect score)")); - screen_load(); - continue; - } - - /* Warning */ - bell(); - } - - /* Are we done? */ - if (c == '\r' || c == '\n' || c == ESCAPE) break; - - /* Save this for the "previous" character */ - save_prev_data(&previous_char); - previous_char.quick_ok = FALSE; - - /* Note that a previous roll exists */ - prev = TRUE; - } - - /* Clear prompt */ - clear_from(23); - - /* Get a name, recolor it, prepare savefile */ - get_name(); - - /* Process the player name */ - process_player_name(creating_savefile); - - /*** Edit character background ***/ - edit_history(); - - /*** Finish up ***/ - - get_max_stats(); - - get_virtues(); - - /* Prompt for it */ -#ifdef JP - prt("[ 'Q' 中断, 'S' 初めから, Enter ゲーム開始 ]", 23, 14); -#else - prt("['Q'uit, 'S'tart over, or Enter to continue]", 23, 10); -#endif - - - /* Get a key */ - c = inkey(); - - /* Quit */ - if (c == 'Q') birth_quit(); - - /* Start over */ - if (c == 'S') return (FALSE); - - - /* Initialize random quests */ - init_dungeon_quests(); - - /* Save character data for quick start */ - save_prev_data(&previous_char); - previous_char.quick_ok = TRUE; - - /* Accept */ - return (TRUE); -} - -/*! - * @brief クイックスタート処理の問い合わせと実行を行う。/Ask whether the player use Quick Start or not. - * @return なし - */ -static bool ask_quick_start(void) -{ - /* Doesn't have previous data */ - if (!previous_char.quick_ok) return FALSE; - - Term_clear(); - - /* Extra info */ - put_str(_("クイック・スタートを使うと以前と全く同じキャラクターで始められます。", "Do you want to use the quick start function(same character as your last one)."), 11, 2); - - /* Choose */ - while (1) - { - char c; - - put_str(_("クイック・スタートを使いますか?[y/N]", "Use quick start? [y/N]"), 14, 10); - c = inkey(); - - if (c == 'Q') quit(NULL); - else if (c == 'S') return (FALSE); - else if (c == '?') - { -#ifdef JP - show_help("jbirth.txt#QuickStart"); -#else - show_help("birth.txt#QuickStart"); -#endif - } - else if ((c == 'y') || (c == 'Y')) - { - /* Yes */ - break; - } - else - { - /* No */ - return FALSE; - } - } - - load_prev_data(FALSE); - init_turn(); - init_dungeon_quests(); - - sp_ptr = &sex_info[p_ptr->psex]; - rp_ptr = &race_info[p_ptr->prace]; - cp_ptr = &class_info[p_ptr->pclass]; - mp_ptr = &m_info[p_ptr->pclass]; - ap_ptr = &seikaku_info[p_ptr->pseikaku]; - - /* Calc hitdie, but don't roll */ - get_extra(FALSE); - - p_ptr->update |= (PU_BONUS | PU_HP); - update_creature(p_ptr); - p_ptr->chp = p_ptr->mhp; - p_ptr->csp = p_ptr->msp; - - /* Process the player name */ - process_player_name(FALSE); - - return TRUE; -} - - -/*! - * @brief プレイヤー作成処理のメインルーチン/ Create a new character. - * @details - * Note that we may be called with "junk" leftover in the various - * fields, so we must be sure to clear them first. - * @return なし - */ -void player_birth(void) -{ - int i, j; - char buf[80]; - - current_world_ptr->play_time = 0; - - /* - * Wipe monsters in old dungeon - * This wipe destroys value of current_floor_ptr->m_list[].cur_num . - */ - wipe_m_list(); - - /* Wipe the player */ - player_wipe_without_name(); - - /* Create a new character */ - - /* Quick start? */ - if (!ask_quick_start()) - { - play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_DEFAULT); - - /* No, normal start */ - while (1) - { - /* Roll up a new character */ - if (player_birth_aux()) break; - - /* Wipe the player */ - player_wipe_without_name(); - } - } - - /* Note player birth in the message recall */ - message_add(" "); - message_add(" "); - message_add("===================="); - message_add(" "); - message_add(" "); - - do_cmd_write_nikki(NIKKI_GAMESTART, 1, _("-------- 新規ゲーム開始 --------", "-------- Start New Game --------")); - do_cmd_write_nikki(NIKKI_HIGAWARI, 0, NULL); - - sprintf(buf,_(" 性別に%sを選択した。", " choose %s personality."), sex_info[p_ptr->psex].title); - do_cmd_write_nikki(NIKKI_BUNSHOU, 1, buf); - - sprintf(buf,_(" 種族に%sを選択した。", " choose %s race."), race_info[p_ptr->prace].title); - do_cmd_write_nikki(NIKKI_BUNSHOU, 1, buf); - - sprintf(buf,_(" 職業に%sを選択した。", " choose %s class."), class_info[p_ptr->pclass].title); - do_cmd_write_nikki(NIKKI_BUNSHOU, 1, buf); - - if (p_ptr->realm1) - { - sprintf(buf,_(" 魔法の領域に%s%sを選択した。", " choose %s%s realm."),realm_names[p_ptr->realm1], p_ptr->realm2 ? format("と%s",realm_names[p_ptr->realm2]) : ""); - do_cmd_write_nikki(NIKKI_BUNSHOU, 1, buf); - } - - sprintf(buf,_(" 性格に%sを選択した。", " choose %s."), seikaku_info[p_ptr->pseikaku].title); - do_cmd_write_nikki(NIKKI_BUNSHOU, 1, buf); - - /* Init the shops */ - for (i = 1; i < max_towns; i++) - { - for (j = 0; j < MAX_STORES; j++) - { - store_init(i, j); - } - } - - /* Generate the random seeds for the wilderness */ - seed_wilderness(); - - /* Give beastman a mutation at character birth */ - if (p_ptr->prace == RACE_BEASTMAN) hack_mutation = TRUE; - else hack_mutation = FALSE; - - /* Set the message window flag as default */ - if (!window_flag[1]) - window_flag[1] |= PW_MESSAGE; - - /* Set the inv/equip window flag as default */ - if (!window_flag[2]) - window_flag[2] |= PW_INVEN; -} - -/*! - * @brief プレイヤー作成処理中のステータス表示処理 - * @param fff ファイルポインタ - * @return なし - */ -void dump_yourself(FILE *fff) -{ - char temp[80*10]; - int i; - concptr t; - - if (!fff) return; - - roff_to_buf(race_jouhou[p_ptr->prace], 78, temp, sizeof(temp)); - fprintf(fff, "\n\n"); - fprintf(fff, _("種族: %s\n", "Race: %s\n"), race_info[p_ptr->prace].title); - - t = temp; - for (i = 0; i < 10; i++) - { - if(t[0] == 0) - break; - fprintf(fff, "%s\n",t); - t += strlen(t) + 1; - } - roff_to_buf(class_jouhou[p_ptr->pclass], 78, temp, sizeof(temp)); - fprintf(fff, "\n"); - fprintf(fff, _("職業: %s\n", "Class: %s\n"), class_info[p_ptr->pclass].title); - - t = temp; - for (i = 0; i < 10; i++) - { - if(t[0] == 0) - break; - fprintf(fff, "%s\n",t); - t += strlen(t) + 1; - } - roff_to_buf(seikaku_jouhou[p_ptr->pseikaku], 78, temp, sizeof(temp)); - fprintf(fff, "\n"); - fprintf(fff, _("性格: %s\n", "Pesonality: %s\n"), seikaku_info[p_ptr->pseikaku].title); - - t = temp; - for (i = 0; i < A_MAX; i++) - { - if(t[0] == 0) - break; - fprintf(fff, "%s\n",t); - t += strlen(t) + 1; - } - fprintf(fff, "\n"); - if (p_ptr->realm1) - { - roff_to_buf(realm_jouhou[technic2magic(p_ptr->realm1)-1], 78, temp, sizeof(temp)); - fprintf(fff, _("魔法: %s\n", "Realm: %s\n"), realm_names[p_ptr->realm1]); - - t = temp; - for (i = 0; i < A_MAX; i++) - { - if(t[0] == 0) - break; - fprintf(fff, "%s\n",t); - t += strlen(t) + 1; - } - } - fprintf(fff, "\n"); - if (p_ptr->realm2) - { - roff_to_buf(realm_jouhou[technic2magic(p_ptr->realm2)-1], 78, temp, sizeof(temp)); - fprintf(fff, _("魔法: %s\n", "Realm: %s\n"), realm_names[p_ptr->realm2]); - - t = temp; - for (i = 0; i < A_MAX; i++) - { - if(t[0] == 0) - break; - fprintf(fff, "%s\n",t); - t += strlen(t) + 1; - } - } -} diff --git a/src/birth/auto-roller.c b/src/birth/auto-roller.c new file mode 100644 index 000000000..37eee7d6c --- /dev/null +++ b/src/birth/auto-roller.c @@ -0,0 +1,443 @@ +#include "birth/auto-roller.h" +#include "birth/birth-stat.h" +#include "birth/birth-util.h" +#include "cmd-io/cmd-gameoption.h" +#include "io/input-key-acceptor.h" +#include "main/sound-of-music.h" +#include "player/player-class.h" +#include "player/player-personality.h" +#include "player/player-race.h" +#include "player/player-status-table.h" +#include "system/game-option-types.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/int-char-converter.h" + +/*! オートローラの能力値的要求水準 / Autoroll limit */ +s16b stat_limit[6]; + +/*! オートローラ中、各能力値が水準を超えた回数 / Autoroll matches */ +s32b stat_match[6]; + +/*! オートローラの試行回数 / Autoroll round */ +s32b auto_round; + +/*! + * @brief オートローラで得たい能力値の基準を決める。 + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +bool get_stat_limits(player_type *creature_ptr) +{ + clear_from(10); + put_str(_("最低限得たい能力値を設定して下さい。", "Set minimum stats."), 10, 10); + put_str(_("2/8で項目選択、4/6で値の増減、Enterで次へ", "2/8 for Select, 4/6 for Change value, Enter for Goto next"), 11, 10); + put_str(_(" 基本値 種族 職業 性格 合計値 最大値", " Base Rac Cla Per Total Maximum"), 13, 10); + + int cval[6]; + char buf[80]; + char cur[80]; + char inp[80]; + for (int i = 0; i < A_MAX; i++) { + stat_match[i] = 0; + cval[i] = 3; + int j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i]; + int m = adjust_stat(17, j); + if (m > 18) + sprintf(cur, "18/%02d", (m - 18)); + else + sprintf(cur, "%2d", m); + + m = adjust_stat(cval[i], j); + if (m > 18) + sprintf(inp, "18/%02d", (m - 18)); + else + sprintf(inp, "%2d", m); + + sprintf(buf, "%6s %2d %+3d %+3d %+3d = %6s %6s", stat_names[i], cval[i], rp_ptr->r_adj[i], cp_ptr->c_adj[i], ap_ptr->a_adj[i], inp, cur); + put_str(buf, 14 + i, 10); + } + + int cs = 0; + int os = 6; + while (TRUE) { + if (cs != os) { + if (os == 6) { + c_put_str(TERM_WHITE, _("決定する", "Accept"), 21, 35); + } else if (os < A_MAX) { + c_put_str(TERM_WHITE, cur, 14 + os, 10); + } + if (cs == 6) { + c_put_str(TERM_YELLOW, _("決定する", "Accept"), 21, 35); + } else { + int j = rp_ptr->r_adj[cs] + cp_ptr->c_adj[cs] + ap_ptr->a_adj[cs]; + int m = adjust_stat(cval[cs], j); + if (m > 18) + sprintf(inp, "18/%02d", (m - 18)); + else + sprintf(inp, "%2d", m); + + sprintf( + cur, "%6s %2d %+3d %+3d %+3d = %6s", stat_names[cs], cval[cs], rp_ptr->r_adj[cs], cp_ptr->c_adj[cs], ap_ptr->a_adj[cs], inp); + c_put_str(TERM_YELLOW, cur, 14 + cs, 10); + } + + os = cs; + } + + char c = inkey(); + switch (c) { + case 'Q': + birth_quit(); + break; + case 'S': + return FALSE; + case ESCAPE: + break; + case ' ': + case '\r': + case '\n': + if (cs == 6) + break; + cs++; + c = '2'; + break; + case '8': + case 'k': + if (cs > 0) + cs--; + break; + case '2': + case 'j': + if (cs < A_MAX) + cs++; + break; + case '4': + case 'h': + if (cs != 6) { + if (cval[cs] == 3) { + cval[cs] = 17; + os = 7; + } else if (cval[cs] > 3) { + cval[cs]--; + os = 7; + } else + return FALSE; + } + + break; + case '6': + case 'l': + if (cs != 6) { + if (cval[cs] == 17) { + cval[cs] = 3; + os = 7; + } else if (cval[cs] < 17) { + cval[cs]++; + os = 7; + } else + return FALSE; + } + + break; + case 'm': + if (cs != 6) { + cval[cs] = 17; + os = 7; + } + + break; + case 'n': + if (cs != 6) { + cval[cs] = 3; + os = 7; + } + + break; + case '?': +#ifdef JP + show_help(creature_ptr, "jbirth.txt#AutoRoller"); +#else + show_help(creature_ptr, "birth.txt#AutoRoller"); +#endif + break; + case '=': + screen_save(); +#ifdef JP + do_cmd_options_aux(creature_ptr, OPT_PAGE_BIRTH, "初期オプション((*)はスコアに影響)"); +#else + do_cmd_options_aux(creature_ptr, OPT_PAGE_BIRTH, "Birth Option((*)s effect score)"); +#endif + + screen_load(); + break; + default: + bell(); + break; + } + + if (c == ESCAPE || ((c == ' ' || c == '\r' || c == '\n') && cs == 6)) + break; + } + + for (int i = 0; i < A_MAX; i++) + stat_limit[i] = (s16b)cval[i]; + + return TRUE; +} + +void initialize_chara_limit(chara_limit_type *chara_limit_ptr) +{ + chara_limit_ptr->agemin = 0; + chara_limit_ptr->agemax = 0; + chara_limit_ptr->htmin = 0; + chara_limit_ptr->htmax = 0; + chara_limit_ptr->wtmin = 0; + chara_limit_ptr->wtmax = 0; + chara_limit_ptr->scmin = 0; + chara_limit_ptr->scmax = 0; +} + +/*! + * @brief オートローラで得たい年齢、身長、体重、社会的地位の基準を決める。 + * @return なし + */ +bool get_chara_limits(player_type *creature_ptr, chara_limit_type *chara_limit_ptr) +{ +#define MAXITEMS 8 + + char buf[80], cur[80]; + concptr itemname[] = { _("å¹´é½¢", "age"), _("身長(インチ)", "height"), _("体重(ポンド)", "weight"), _("社会的地位", "social class") }; + + clear_from(10); + put_str(_("2/4/6/8で項目選択、+/-で値の増減、Enterで次へ", "2/4/6/8 for Select, +/- for Change value, Enter for Goto next"), 11, 10); + put_str( + _("注意:身長と体重の最大値/最小値ぎりぎりの値は非常に出現確率が低くなります。", "Caution: Values near minimum or maximum are extremely rare."), 23, 2); + + int max_percent, min_percent; + if (creature_ptr->psex == SEX_MALE) { + max_percent = (int)(rp_ptr->m_b_ht + rp_ptr->m_m_ht * 4 - 1) * 100 / (int)(rp_ptr->m_b_ht); + min_percent = (int)(rp_ptr->m_b_ht - rp_ptr->m_m_ht * 4 + 1) * 100 / (int)(rp_ptr->m_b_ht); + } else { + max_percent = (int)(rp_ptr->f_b_ht + rp_ptr->f_m_ht * 4 - 1) * 100 / (int)(rp_ptr->f_b_ht); + min_percent = (int)(rp_ptr->f_b_ht - rp_ptr->f_m_ht * 4 + 1) * 100 / (int)(rp_ptr->f_b_ht); + } + + put_str(_("体格/地位の最小値/最大値を設定して下さい。", "Set minimum/maximum attribute."), 10, 10); + put_str(_(" 項 目 最小値 最大値", " Parameter Min Max"), 13, 20); + int mval[MAXITEMS]; + int cval[MAXITEMS]; + for (int i = 0; i < MAXITEMS; i++) { + int m; + switch (i) { + case 0: /* Minimum age */ + m = rp_ptr->b_age + 1; + break; + case 1: /* Maximum age */ + m = rp_ptr->b_age + rp_ptr->m_age; + break; + + case 2: /* Minimum height */ + if (creature_ptr->psex == SEX_MALE) + m = rp_ptr->m_b_ht - rp_ptr->m_m_ht * 4 + 1; + else + m = rp_ptr->f_b_ht - rp_ptr->f_m_ht * 4 + 1; + break; + case 3: /* Maximum height */ + if (creature_ptr->psex == SEX_MALE) + m = rp_ptr->m_b_ht + rp_ptr->m_m_ht * 4 - 1; + else + m = rp_ptr->f_b_ht + rp_ptr->f_m_ht * 4 - 1; + break; + case 4: /* Minimum weight */ + if (creature_ptr->psex == SEX_MALE) + m = (rp_ptr->m_b_wt * min_percent / 100) - (rp_ptr->m_m_wt * min_percent / 75) + 1; + else + m = (rp_ptr->f_b_wt * min_percent / 100) - (rp_ptr->f_m_wt * min_percent / 75) + 1; + break; + case 5: /* Maximum weight */ + if (creature_ptr->psex == SEX_MALE) + m = (rp_ptr->m_b_wt * max_percent / 100) + (rp_ptr->m_m_wt * max_percent / 75) - 1; + else + m = (rp_ptr->f_b_wt * max_percent / 100) + (rp_ptr->f_m_wt * max_percent / 75) - 1; + break; + case 6: /* Minimum social class */ + m = 1; + break; + case 7: /* Maximum social class */ + m = 100; + break; + default: + m = 1; + break; + } + + mval[i] = m; + cval[i] = m; + } + + for (int i = 0; i < 4; i++) { + sprintf(buf, "%-12s (%3d - %3d)", itemname[i], mval[i * 2], mval[i * 2 + 1]); + put_str(buf, 14 + i, 20); + for (int j = 0; j < 2; j++) { + sprintf(buf, " %3d", cval[i * 2 + j]); + put_str(buf, 14 + i, 45 + 8 * j); + } + } + + int cs = 0; + int os = MAXITEMS; + while (TRUE) { + if (cs != os) { + const char accept[] = _("決定する", "Accept"); + if (os == MAXITEMS) + c_put_str(TERM_WHITE, accept, 19, 35); + else + c_put_str(TERM_WHITE, cur, 14 + os / 2, 45 + 8 * (os % 2)); + + if (cs == MAXITEMS) { + c_put_str(TERM_YELLOW, accept, 19, 35); + } else { + sprintf(cur, " %3d", cval[cs]); + c_put_str(TERM_YELLOW, cur, 14 + cs / 2, 45 + 8 * (cs % 2)); + } + + os = cs; + } + + char c = inkey(); + switch (c) { + case 'Q': + birth_quit(); + break; + case 'S': + return FALSE; + case ESCAPE: + break; /*後でもう一回breakせんと*/ + case ' ': + case '\r': + case '\n': + if (cs == MAXITEMS) + break; + cs++; + c = '6'; + break; + case '8': + case 'k': + if (cs - 2 >= 0) + cs -= 2; + break; + case '2': + case 'j': + if (cs < MAXITEMS) + cs += 2; + if (cs > MAXITEMS) + cs = MAXITEMS; + break; + case '4': + case 'h': + if (cs > 0) + cs--; + break; + case '6': + case 'l': + if (cs < MAXITEMS) + cs++; + break; + case '-': + case '<': + if (cs != MAXITEMS) { + if (cs % 2) { + if (cval[cs] > cval[cs - 1]) { + cval[cs]--; + os = 127; + } + } else { + if (cval[cs] > mval[cs]) { + cval[cs]--; + os = 127; + } + } + } + + break; + case '+': + case '>': + if (cs != MAXITEMS) { + if (cs % 2) { + if (cval[cs] < mval[cs]) { + cval[cs]++; + os = 127; + } + } else { + if (cval[cs] < cval[cs + 1]) { + cval[cs]++; + os = 127; + } + } + } + + break; + case 'm': + if (cs != MAXITEMS) { + if (cs % 2) { + if (cval[cs] < mval[cs]) { + cval[cs] = mval[cs]; + os = 127; + } + } else { + if (cval[cs] < cval[cs + 1]) { + cval[cs] = cval[cs + 1]; + os = 127; + } + } + } + + break; + case 'n': + if (cs != MAXITEMS) { + if (cs % 2) { + if (cval[cs] > cval[cs - 1]) { + cval[cs] = cval[cs - 1]; + os = 255; + } + } else { + if (cval[cs] > mval[cs]) { + cval[cs] = mval[cs]; + os = 255; + } + } + } + + break; + case '?': +#ifdef JP + show_help(creature_ptr, "jbirth.txt#AutoRoller"); +#else + show_help(creature_ptr, "birth.txt#AutoRoller"); +#endif + break; + case '=': + screen_save(); + do_cmd_options_aux(creature_ptr, OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Option((*)s effect score)")); + screen_load(); + break; + default: + bell(); + break; + } + + if (c == ESCAPE || ((c == ' ' || c == '\r' || c == '\n') && cs == MAXITEMS)) + break; + } + + chara_limit_ptr->agemin = (s16b)cval[0]; + chara_limit_ptr->agemax = (s16b)cval[1]; + chara_limit_ptr->htmin = (s16b)cval[2]; + chara_limit_ptr->htmax = (s16b)cval[3]; + chara_limit_ptr->wtmin = (s16b)cval[4]; + chara_limit_ptr->wtmax = (s16b)cval[5]; + chara_limit_ptr->scmin = (s16b)cval[6]; + chara_limit_ptr->scmax = (s16b)cval[7]; + return TRUE; +} diff --git a/src/birth/auto-roller.h b/src/birth/auto-roller.h new file mode 100644 index 000000000..189cd34b8 --- /dev/null +++ b/src/birth/auto-roller.h @@ -0,0 +1,19 @@ +#pragma once + +#include "system/angband.h" + +/*! オートローラの年齢、身長、体重、社会的地位の要求水準 */ +typedef struct { + s16b agemin, agemax; + s16b htmin, htmax; + s16b wtmin, wtmax; + s16b scmin, scmax; +} chara_limit_type; + +extern s16b stat_limit[6]; +extern s32b stat_match[6]; +extern s32b auto_round; + +bool get_stat_limits(player_type *creature_ptr); +void initialize_chara_limit(chara_limit_type *chara_limit_ptr); +bool get_chara_limits(player_type *creature_ptr, chara_limit_type *chara_limit_ptr); diff --git a/src/birth/birth-body-spec.c b/src/birth/birth-body-spec.c new file mode 100644 index 000000000..c1b826679 --- /dev/null +++ b/src/birth/birth-body-spec.c @@ -0,0 +1,73 @@ +#include "birth/birth-body-spec.h" +#include "player/player-personalities-types.h" +#include "player/player-race-types.h" +#include "player/player-race.h" + +/*! + * @brief プレイヤーの身長体重を決める / Get character's height and weight + * @return なし + */ +void get_height_weight(player_type *creature_ptr) +{ + int deviation; + switch (creature_ptr->psex) { + case SEX_MALE: + creature_ptr->ht = randnor(rp_ptr->m_b_ht, rp_ptr->m_m_ht); + deviation = (int)(creature_ptr->ht) * 100 / (int)(rp_ptr->m_b_ht); + creature_ptr->wt = randnor((int)(rp_ptr->m_b_wt) * deviation / 100, (int)(rp_ptr->m_m_wt) * deviation / 300); + return; + case SEX_FEMALE: + creature_ptr->ht = randnor(rp_ptr->f_b_ht, rp_ptr->f_m_ht); + deviation = (int)(creature_ptr->ht) * 100 / (int)(rp_ptr->f_b_ht); + creature_ptr->wt = randnor((int)(rp_ptr->f_b_wt) * deviation / 100, (int)(rp_ptr->f_m_wt) * deviation / 300); + default: + return; + } +} + +/*! + * @brief プレイヤーの年齢を決める。 / Computes character's age, height, and weight by henkma + * @details 内部でget_height_weight()も呼び出している。 + * @return なし + */ +void get_ahw(player_type *creature_ptr) +{ + creature_ptr->age = rp_ptr->b_age + randint1(rp_ptr->m_age); + get_height_weight(creature_ptr); +} + +/*! + * @brief プレイヤーの初期所持金を決める。 / Get the player's starting money + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void get_money(player_type *creature_ptr) +{ + int gold = (creature_ptr->sc * 6) + randint1(100) + 300; + if (creature_ptr->pclass == CLASS_TOURIST) + gold += 2000; + + for (int i = 0; i < A_MAX; i++) { + if (creature_ptr->stat_max[i] >= 18 + 50) + gold -= 300; + else if (creature_ptr->stat_max[i] >= 18 + 20) + gold -= 200; + else if (creature_ptr->stat_max[i] > 18) + gold -= 150; + else + gold -= (creature_ptr->stat_max[i] - 8) * 10; + } + + const int minimum_deposit = 100; + if (gold < minimum_deposit) + gold = minimum_deposit; + + if (creature_ptr->pseikaku == PERSONALITY_LAZY) + gold /= 2; + else if (creature_ptr->pseikaku == PERSONALITY_MUNCHKIN) + gold = 10000000; + if (creature_ptr->prace == RACE_ANDROID) + gold /= 5; + + creature_ptr->au = gold; +} diff --git a/src/birth/birth-body-spec.h b/src/birth/birth-body-spec.h new file mode 100644 index 000000000..811c68428 --- /dev/null +++ b/src/birth/birth-body-spec.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +void get_height_weight(player_type *creature_ptr); +void get_ahw(player_type *creature_ptr); +void get_money(player_type *creature_ptr); diff --git a/src/birth/birth-explanations-table.c b/src/birth/birth-explanations-table.c new file mode 100644 index 000000000..5a9b68808 --- /dev/null +++ b/src/birth/birth-explanations-table.c @@ -0,0 +1,308 @@ +#include "birth/birth-explanations-table.h" + +/*! 種族の解説メッセージテーブル */ +concptr race_explanations[MAX_RACES] = { + _("人間は基本となるキャラクタです。他の全ての種族は人間と比較されます。人間はどんな職業に就くこともでき、どの職業でも平均的にこなせます。人間は寿命が短いため、レベル上昇が他のどんな種族よりも早くなる傾向があります。また、特別な修正や特性は持っていません。", + "The human is the base character. All other races are compared to them. Humans can choose any class and are average at everything. Humans tend to go up levels faster than most other races because of their shorter life spans. No racial adjustments or intrinsics occur to characters choosing human."), + + _("ハーフエルフは人間より賢いですが、強くはありません。彼らは探索, 解除, 魔法防御, 隠密行動, 射撃, そして魔法道具使用でわずかに優れています。しかし武器の取り扱いはそう得意ではありません。ハーフエルフはどの職業に就くこともでき、生まれつきの特性はありません。", + "Half-elves tend to be smarter and faster than humans, but not as strong. Half-elves are slightly better at searching, disarming, saving throws, stealth, bows, and magic, but they are not as good at hand weapons. Half-elves may choose any class and do not receive any intrinsic abilities."), + + _("エルフは人間より良い魔法使いになれますが、戦闘は苦手です。彼らは人間やハーフエルフよりも頭が良く、高い賢さを持っています。エルフは探索, 解除, 知覚, 隠密行動, 射撃, そして魔法道具使用で優れていますが、武器の扱いは得意ではありません。彼らは生まれつき光に対する耐性を持っています。", + "Elves are better magicians then humans, but not as good at fighting. They tend to be smarter and faster than either humans or half-elves and also have better wisdom. Elves are better at searching, disarming, perception, stealth, bows, and magic, but they are not as good at hand weapons. They resist light effects intrinsically."), + + _("ホビット、またはハーフリングは弓や投擲に長け、魔法防御も優れています。また、探索, 解除, 知覚, そして隠密行動でもとても良い能力を示します。そのため、彼らは優れた盗賊となることができます(しかし、「忍びの者」と呼ばれることを好みます)。ホビットは人間より遥かに貧弱で、戦士としてはてんでダメです。彼らはかなり良い赤外線視力を持っており、温血動物を離れた場所から見つけることができます。彼らは経験値を保持する力が強く、経験値吸収攻撃に対して耐性を持っています。", + "Hobbits, or Halflings, are very good at bows, throwing, and have good saving throws. They also are very good at searching, disarming, perception, and stealth; so they make excellent rogues, but prefer to be called burglars. They are much weaker than humans and no good at melee fighting. Halflings have fair infravision, so they can detect warm creatures at a distance. They have a strong hold on their life force and are thus intrinsically resistant to life draining."), + + _("ノームはドワーフより小さいですが、ホビットよりは大きい種族です。彼らはホビット同様地表の洞穴のような家に住んでいます。ノームはとても良い魔法防御を持ち、探索, 解除, 知覚, 隠密行動でも優れています。彼らは人間より低い腕力を持ち、武器を持っての戦闘は苦手です。ノームはかなり良い赤外線視力を持っており、温血動物を離れた場所から見つけることができます。ノームは生まれつき麻痺に対する耐性を持っています。", + "Gnomes are smaller than dwarves but larger than Halflings. They, like the hobbits, live in the earth in burrow-like homes. Gnomes make excellent mages and have very good saving throws. They are good at searching, disarming, perception, and stealth. They have lower strength than humans so they are not very good at fighting with hand weapons. Gnomes have fair infravision, so they can detect warm-blooded creatures at a distance. Gnomes are intrinsically protected against paralysis."), + + _("ドワーフは頑固な坑夫であり、伝説の戦士です。彼らは人間にくらべ強くタフですが、知能は劣ります。しかし、長命ゆえに彼らは非常に賢いです。彼らは良い魔法防御を持ち、探索, 知覚, 戦闘, 射撃では優れています。彼らは一つ大きな欠点を持っています。ドワーフの隠密行動は絶望的に悪いです。彼らは決して盲目にはなりません。", + "Dwarves are the headstrong miners and fighters of legend. Dwarves tend to be stronger and tougher but slower and less intelligent than humans. Because they are so headstrong and are somewhat wise, they resist spells which are cast on them. They are very good at searching, perception, fighting, and bows. Dwarves have miserable stealth. They can never be blinded."), + + _("ハーフオークはよい戦士になれますが、魔法は期待できません。彼らはドワーフと同じくらい隠密行動が悪く、また探索や解除, 知覚もひどいです。ハーフオークは醜く、店での買い物ではより高い金額を要求されがちです。彼らは地下に住むことを好むため、ハーフオークは暗闇に対する耐性を備えています。", + "Half-orcs make excellent warriors, but are terrible at magic. They are as bad as dwarves at stealth, and horrible at searching, disarming, and perception. Half-orcs are quite ugly and tend to pay more for goods in town. Because of their preference to living underground to on the surface, half-orcs resist darkness attacks."), + + _("ハーフトロルは信じられないほど強く、他の大部分の種族より大きなHPを持ちます。彼らは不運にもとても愚かです。彼らの探索, 解除, 知覚, 隠密行動は悪く、その外見はハーフオークがしかめっ面をするほど醜悪です。ハーフトロルは腕力が下がることがありません。レベルが上がると、彼らは再生能力を手にいれ、戦士ならばさらに遅消化能力も獲得します。", + "Half-Trolls are incredibly strong and have more hit points than most other races. They are also very stupid and slow. They are bad at searching, disarming, perception, and stealth. They are so ugly that a Half-Orc grimaces in their presence. They also happen to be fun to run... Half-trolls always have their strength sustained. At higher levels, Half-Trolls regenerate wounds automatically and, if a warrior, require food less often."), + + _("アンバライトは多くのアドバンテージを授けられた、うわさによれば不死の種族です。彼らは知覚, 戦闘, 射撃に優れており、他の面でもかなり熟練しています。事実上あらゆるものを見てきており、新鮮なものはほとんどないため、彼らの成長は他のどの種族より遅いものです。彼らはとてもタフで頑強であり、彼らの耐久力が下がることはありません。また、怪我をすぐに治す再生能力があります。", + "The Amberites are a reputedly immortal race, who are endowed with numerous advantages in addition to their longevity. They are very tough and their constitution cannot be reduced. Their ability to heal wounds far surpasses that of any other race. Having seen virtually everything, very little is new to them, and they gain levels much slower than the other races."), + + _("ハイエルフは世界の始まりから存在する不死の種族です。彼らは全てのスキルに熟達しており、強く、知的で非常に人気があります - 誰もが彼らのことを好いています。ハイエルフは見えないものを見ることができ、普通のエルフ同様光に対する耐性を持っています。しかし、彼らにとって未知のものはほとんどなく、経験を得ることは大変に困難です。", + "High-elves are a race of immortal beings dating from the beginning of time. They are masters of all skills, and are strong and intelligent, although their wisdom is sometimes suspect. High-elves begin their lives able to see the unseen, and resist light effects just like regular elves. However, there are few things that they have not seen already, and experience is very hard for them to gain."), + + _("野蛮人は北方から来た頑強な種族です。彼らは激しく戦い、彼らの激怒は世界中で恐れられています。戦闘が彼らの人生です。彼らは恐れを知らず、ハーフトロルよりもすぐに狂暴に戦闘に入ってしまうことを学びます。しかし、野蛮人は魔法を疑っており、そのため魔法の道具を使うことはかなり大変なこととなっています。", + "Barbarians are hardy men of the north. They are fierce in combat, and their wrath is feared throughout the world. Combat is their life: they feel no fear, and they learn to enter battle frenzy at will even sooner than half-trolls. Barbarians are, however, suspicious of magic, which makes magic devices fairly hard for them to use."), + + _("ハーフオーガはハーフオークに似ていますが、それだけではありません。彼らは大きく、邪悪で愚かです。戦士としては彼らは必要な資質を全て持っており、また魔法使いになることさえできます。結局、彼らはオーガ・メイジに関係があり、レベルが十分に上がったら彼らから罠のルーンをセットするスキルを学ぶのです。ハーフオークのように、彼らは暗闇に対する耐性を持ち、ハーフトロル同様に腕力が下がることはありません。", + "Half-Ogres are like Half-Orcs, only more so. They are big, bad, and stupid. For warriors, they have all the necessary attributes, and they can even become wizards: after all, they are related to Ogre Magi, from whom they have learned the skill of setting trapped runes once their level is high enough. Like Half-Orcs, they resist darkness, and like Half-Trolls, they have their strength sustained."), + + _("半巨人は大変力強いのですが、呪文を唱えられるほど利口ではありません。彼らはよい戦闘能力を持ちますが、それ以外のことは苦手です。彼らの厚い皮膚は破片に対する耐性を持ちます。また、ハーフオーガやハーフトロル同様腕力を下げられることがありません。", + "Half-Giants' limited intelligence makes it difficult for them to become full spellcasters, but, with their great strength, they make excellent warriors. Their thick skin makes them resistant to shards, and, like Half-Ogres and Half-Trolls, they have their strength sustained."), + + _("巨大なタイタンと人間の子孫であり、この強大な生物は他のほぼ全ての種族よりはるかに勝っています。彼らは多種族にみられるような魅力的な特殊能力は持っていませんが、その大変大きなHPはそれを補ってあまりあります。半タイタンはそこそこのスキルを持っていますが、その巨大さゆえに罠の解除やこっそり歩くことは困難です。法と秩序を愛する彼らは、カオスに対する耐性を持っています。", + "Half-mortal descendants of the mighty titans, these immensely powerful creatures put almost any other race to shame. They may lack the fascinating special powers of certain other races, but their enhanced attributes more than make up for that. They learn to estimate the strengths of their foes, and their love for law and order makes them resistant to the effects of Chaos."), + + _("一つ目ではありますが、サイクロプスは多くの二つの目を持つ生物以上に見ることができます。サイクロプスは非常に力強いのですが、知的であるとはちょっと言えません。彼らに比べれば、ハーフトロルの方がハンサムに見えるということは言うまでもありません。サイクロプスは戦闘, 射撃に優れていますが、その他の大部分のスキルは苦手です。サイクロプスは音に対する耐性を持っています。", + "With but one eye, a Cyclops can see more than many with two eyes. They are headstrong, and loud noises bother them very little. They are not quite qualified for the magic using professions, but as a certain Mr. Ulysses can testify, their accuracy with thrown rocks can be deadly..."), + + _("イークは最も哀れな生物の一つであり、並のモンスターであっても不注意なイークならば徹底的に打ちのめせるほど肉体的には強くありませんが、彼らはかなり知的でいくらか賢い生物です。イークは戦闘スキルは苦手ですが、他の分野では優れています。彼らの皮膚は、時間とともに酸への耐性を増していき、レベルが十分に上がれば完全に免疫を持つようになります。", + "Yeeks are among the most pathetic creatures. Fortunately, their horrible screams can scare away less confident foes, and their skin becomes more and more resistant to acid, as they gain experience. But having said that, even a mediocre monster can wipe the proverbial floor with an unwary Yeek."), + + _("クラッコンは奇怪な半知的の昆虫型生物です。彼らはすばらしい戦士になれますが、精神的な能力はひどく制限されています。彼らは探索を除けば大部分のスキルをそこそこにこなします。クラッコンは決して混乱させられることがなく、レベルが上がるごとに速くなります。", + "Klackons are bizarre semi-intelligent ant-like insectoid creatures. They make great fighters, but their mental abilities are severely limited. Obedient and well-ordered, they can never be confused. They are also very nimble, and become faster as they advance levels. They are also very acidic, inherently resisting acid, and capable of spitting acid at higher levels."), + + _("コボルドは弱いゴブリンの種族です。彼らは毒を持った武器を好み、毒矢(無制限に供給されます)を投げる能力を身につけることができます。コボルドはそこそこの戦士になれますが、その他のスキルは軒並み悪いです。彼らは生まれつき毒に対する耐性を持っています。", + "Kobolds are a weak goblin race. They love poisoned weapons, and can learn to throw poisoned darts (of which they carry an unlimited supply). They are also inherently resistant to poison, although they are not one of the more powerful races."), + + _("嫌われ、迫害されてきた小人族です。彼らは大抵のスキルをそつなくこなします。洞穴居住者である彼らは、暗闇に悩まされることはありませんし、生まれつき持っている魔法のアイテムに対する嗜好のため、彼らは装備による魔法のボーナスを奪う効果に耐性を持っています。", + "The hated and persecuted race of nocturnal dwarves, these cavedwellers are not much bothered by darkness. Their natural inclination to magical items has made them immune to effects which could drain away magical energy."), + + _("闇の、洞穴に住む種族であるダークエルフは魔法の知識に対する長い伝統を持っています。ダークエルフは魔法の道具をうまく使うことができ、他の多くの種族より簡単に呪文を唱えられるだけの知能を持っています。その鋭い視覚によって、彼らはハイエルフ同様見えないものをみる能力を学びますが、それはある程度レベルが上がったときです。ダークエルフは暗闇に対する耐性を持っています。", + "Another dark, cavedwelling race, likewise unhampered by darkness attacks, the Dark Elves have a long tradition and knowledge of magic. They have an inherent magic missile attack available to them at a low level. With their keen sight, they also learn to see invisible things as their relatives High-Elves do, but at a higher level."), + + _("ドラゴンのような特性を持った人間型種族です。彼らはレベルが上がるにつれ、新しい元素への耐性を手にいれます。ドラコニアンは優れた能力値を持ってゲームを開始でき、大抵のスキルをうまくこなせます。その翼で、彼らは簡単に落とし穴や溶岩、水を無傷で飛び越えることができます。", + "A humanoid race with dragon-like attributes. As they advance levels, they gain new elemental resistances (up to Poison Resistance), and they also have a breath weapon, which becomes more powerful with experience. The exact type of the breath weapon depends on the Draconian's class and level. With their wings, they can easily escape any pit trap unharmed."), + + _("秘密主義の神秘的な古代種族です。彼らの文明はこの惑星上の何よりも古いかもしれません。その肉体的資質は決して誉められたものではありませんが、彼らの知能と賢さはマインドフレアを他のどんな種族よりも強力な魔法使いにします。マインドフレアの知能と賢さは下がることがなく、レベルが上がれば見えないものをみる能力、テレパシー能力を獲得します。", + "A secretive and mysterious ancient race. Their civilization may well be older than any other on our planet, and their intelligence and wisdom are naturally sustained, and are so great that they enable Mind Flayers to become more powerful spellcasters than any other race, even if their physical attributes are a good deal less admirable. As they advance levels, they gain the powers of See Invisible and Telepathy."), + + _("地獄からやってきた悪魔的な生物です。彼らは他の種族から毛嫌いされていますが、大抵の職業をかなりうまくこなすことができます。インプは生まれつき火に耐性を持っており、レベルが上がれば見えないものを見る能力を獲得します。", + "Demon-creatures from the nether-world, imps are naturally resistant to fire attacks and capable of learning fire bolt and fire ball attacks. They are little loved by other races but can perform fairly well in most professions. As they advance levels, they gain the powers of See Invisible."), + + _("ゴーレムは泥のような生命のない材料からつくられ、生命を吹き込まれた人工的な生物です。彼らには思考というものがほとんどなく、そのため魔法に依存する職業では役立たずです。しかし戦士としては大変にタフです。彼らは毒に耐性を持ち、見えないものを見ることができ、さらに麻痺知らずです。レベルが上がれば、彼らは生命力吸収攻撃に耐性を持つようになります。ゴーレムは通常の食物からはほとんど栄養を摂取できませんが、代わりに魔法棒や杖から魔力を吸収して動力源にする事ができます。また、その頑丈な身体のため、ACにボーナスを得ることができ、さらに決して気絶させられることがありません。", + "A Golem is an artificial creature, built from a lifeless raw material like clay, and awakened to life. They are nearly mindless, making them useless for professions which rely on magic, but as warriors they are very tough. They are resistant to poison, they can see invisible things, and move freely. At higher levels, they also become resistant to attacks which threaten to drain away their experience. Golems gain very little nutrition from ordinary food, but can absorb mana from staffs and wands as their power source. Golems also gain a natural armor class bonus from their tough body."), + + _("スケルトンには2つのタイプが存在します。普通の戦士タイプと、リッチと呼ばれる呪文を使うスケルトンです。アンデッドである彼らは、毒や生命力吸収攻撃を心配する必要はありません。彼らは物体を知覚するのに眼を利用していないため、見えない物に騙されません。彼らの骨はとがった破片のようなものに耐性を持ち、レベルが上がれば冷気に対する耐性を獲得します。薬や食物の持つ効果はスケルトンの胃(存在しませんが)を通過することなくその力を発揮しますが、薬や食物自体は彼の顎を通り抜けて落ちてしまい、栄養を吸収することはできません。その代わりに魔法棒や杖から魔力を吸収してエネルギー源にする事ができます。", + "There are two types of skeletons: the ordinary, warrior-like skeletons, and the spell-using skeletons, which are also called liches. As undead beings, skeletons need to worry very little about poison or attacks that can drain life. They do not really use eyes for perceiving things, and are thus not fooled by invisibility. Their bones are resistant to sharp shrapnel, and they will quickly become resistant to cold. Although the magical effects of these will affect the skeleton even without entering the skeleton's (non-existent) belly, the potion or food itself will fall through the skeleton's jaws, giving no nutritional benefit. They can absorb mana from staffs and wands as their energy source."), + + _("ゾンビはアンデッドであり、生命力吸収攻撃に耐性を持ち、スケルトンのようにレベルが上がれば冷気の耐性を獲得します。また、毒に耐性を持ち見えないものを見ることができます。(スケルトンとは違い)切る攻撃には弱いですが、地獄に対する耐性を持っています。ゴーレムのように、彼らは食物からほとんど栄養を摂取できませんが、代わりに魔法棒や杖から魔力を吸収してエネルギー源にする事ができます。", + "Much like Skeletons, Zombies too are undead horrors: they are resistant to exp-draining attacks, and can learn to restore their experience. Like skeletons, they become resistant to cold-based attacks (actually earlier than skeletons), resist poison and can see invisible. While still vulnerable to cuts (unlike skeletons), Zombies are resistant to Nether. Like Golems, they gain very little nutrition from the food of mortals, but can absorb mana from staffs and wands as their energy source."), + + _("強力なアンデッドの一種である吸血鬼は、畏敬の念を呼び起こす外見をしています。アンデッドの例にもれず、彼らも生命力を吸収されることがなく、地獄に対する耐性を持っています。また、冷気と毒に対する耐性も備えています。しかし、新鮮な血液に常に飢えており、それは近くにいる生物から血液を吸うことによってのみ満たされます。この強力な生物は深刻な弱点を持っています。太陽光線(や光源)は彼らの破滅を意味します。幸運にも、吸血鬼はその身体から「暗黒の光」のオーラを放出しています。一方、暗闇は彼らをより強力にするものです。", + "One of the mightier undead creatures, the Vampire is an awe-inspiring sight. Yet this dread creature has a serious weakness: the bright rays of sun are its bane, and it will need to flee the surface to the deep recesses of earth until the sun finally sets. Darkness, on the other hand, only makes the Vampire stronger. As undead, the Vampire has a firm hold on its experience, and resists nether attacks. The Vampire also resists cold and poison based attacks. It is, however, susceptible to its perpetual hunger for fresh blood, which can only be satiated by sucking the blood from a nearby monster."), + + _("幽霊は強力なアンデッドの一種です。彼らは不気味な緑色の光に包まれています。半物質的な存在である彼らは、壁を通り抜けることができますが、そのときには壁の密度によって傷つけられてしまいます。他のアンデッド同様、彼らも生命力を吸収されることがなく、見えないものを見ることができ、毒と冷気に対して耐性を備え、さらに地獄に対する耐性も持っています。レベルが十分に上がると彼らはテレパシーを獲得します。幽霊は卓越した魔法使いになることができますが、その身体的特性は非常に貧弱です。彼らは食物からほとんど栄養を摂取できませんが、代わりに魔法棒や杖から魔力を吸収してエネルギー源にする事ができます。", + "Another powerful undead creature: the Spectre is a ghastly apparition, surrounded by an unearthly green glow. They exist only partially on our plane of existence: half-corporeal, they can pass through walls, although the density of the wall will hurt them in the process of doing this. As undead, they have a firm hold on their experience, see invisible, and resist poison and cold. They also resist nether. At higher levels they develop telepathic abilities. Spectres make superb spellcasters, but their physical form is very weak. They gain very little nutrition from the food of mortals, but can absorb mana from staffs and wands as their energy source."), + + _("妖精は非常に小さいです。彼らは小さな翼を持ち、罠や危険な地形を飛び越えることができます。彼らは日光を大変好み、光に対する耐性を持っています。身体的にはもっとも貧弱な種族の一つですが、妖精は魔法の面で大変な才能を持っており、非常に熟練した魔法使いになることができます。高レベルではより速く飛ぶことができるようになります。", + "One of several fairy races, Sprites are very small. They have tiny wings and can fly over traps that may open up beneath them. They enjoy sunlight intensely, and need worry little about light based attacks. Although physically among the weakest races, Sprites are very talented in magic, and can become highly skilled wizards. Sprites have the special power of spraying Sleeping Dust, and at higher levels they learn to fly faster."), + + _("この種族はカオスによってつくられた冒涜的で嫌悪される存在です。彼らは独立した種族ではなく、人間型種族、大抵は人間がカオスによって歪められた存在、もしくは人間と獣の悪夢のような交配種です。全ての獣人はカオスに盲従しており、そのため混乱と音に対して耐性を備えていますが、純粋なログルスはまだ彼らに対し効果を持っています。獣人は混沌を好み、それは彼らをさらに歪めます。獣人は突然変異を起こしやすい性質を持っています。彼らがつくられたとき、ランダムな変異を受けます。その後、レベルが上がるごとに違う変異を受ける可能性があります。", + "This race is a blasphemous abomination produced by Chaos. It is not an independent race but rather a humanoid creature, most often a human, twisted by the Chaos, or a nightmarish crossbreed of a human and a beast. All Beastmen are accustomed to Chaos so much that they are untroubled by confusion and sound, although raw logrus can still have effects on them. Beastmen revel in chaos, as it twists them more and more. Beastmen are subject to mutations: when they have been created, they receive a random mutation. After that, every time they advance a level they have a small chance of gaining yet another mutation."), + + _("エントは非常に強く、賢いですが、その巨大さゆえに罠の解除やこっそりと歩くことは苦手です。成長するにつれて腕力や耐久力が上がりますが、器用さは下がっていきます。彼らには大きな欠点があり、炎によって通常よりも大きなダメージを受けてしまいます。彼らは食物からほとんど栄養を摂取できませんが、代わりに薬等から水分を摂取する事で活動できます。", + "The Ents are a powerful race dating from the beginning of the world, oldest of all animals or plants who inhabit Arda. Spirits of the land, they were summoned to guard the forests of Middle-earth. Being much like trees they are very clumsy but strong, and very susceptible to fire. They gain very little nutrition from the food of mortals, but they can absorb water from potions as their nutrition."), + + _("天使の上位種であるアルコンは、全てのスキルに熟達しており、強くて賢く、非常に人気があります。彼らは目に見えないものを見ることができ、その翼で罠や危険な地形を飛び越えることができます。しかし、非常に成長が遅いという欠点もあります。", + "Archons are a higher class of angels. They are good at all skills, and are strong, wise, and are a favorite with any people. They are able to see the unseen, and their wings allow them to safely fly over traps and other dangerous places. However, belonging to a higher plane as they do, the experiences of this world do not leave a strong impression on them and they gain levels slowly."), + + _("悪魔の上位種であるバルログは、強く、知的で、またタフでもあります。しかし、彼らは神を信じようとはせず、プリーストには全く向いていません。炎と地獄、経験値吸収への耐性を持っており、レベルが上がれば見えないものを見る能力を獲得します。また、地獄や火炎のブレスを吐くこともできます。彼等はほとんどの技能で優れていますが、静かに歩くことは苦手です。彼らは食物からほとんど栄養を摂取できませんが、人間タイプを生贄にする事で精力を回復する事ができます。", + "Balrogs are a higher class of demons. They are strong, intelligent and tough. They do not believe in gods, and are not suitable for priest at all. Balrog are resistant to fire and nether, and have a firm hold on their experience. They also eventually learn to see invisible things. They are good at almost all skills except stealth. They gain very little nutrition from the food of mortals, and need human corpses as sacrifices to regain their vitality."), + + _("ドゥナダンは西方から来た屈強な種族です。このいにしえの種族は全ての領域において人間の能力を凌駕し、特に耐久力に関してはそれが顕著です。しかしながらこの種族は全てに卓越していることが災いして、この世界には新しい経験といったものがほとんどなく、レベルを上げることが非常に困難です。彼らはとてもタフで頑強であり、彼らの耐久力が下がることはありません。", + "Dunedain are a race of hardy men from the West. This elder race surpasses human abilities in every field, especially constitution. However, being men of the world, very little is new to them, and levels are very hard for them to gain. Their constitution cannot be reduced."), + + _("影フェアリーは人間よりやや大きい妖精族で、翼を持ち、罠や危険な地形を飛び越えることができます。しかし、彼らは日光を嫌い、閃光によって通常よりも大きなダメージを受けてしまいます。肉体的には非常に貧弱ですが、魔法の面では優れた能力を持っています。彼らにはすばらしい長所が一つあり、モンスターの反感をかうような強力なアイテムを装備してもモンスターを怒らせることがありません。ただしその場合でも隠密行動能力が下がり、また、自分自身の性格によって反感をかっている場合には効果がありません。", + "Shadow Fairies are one of several fairy races. They have wings, and can fly over traps that may open up beneath them. Shadow Fairies must beware of sunlight, as they are vulnerable to bright light. They are physically weak, but have advantages in using magic and are amazingly stealthy. Shadow Fairies have a wonderful advantage in that they never aggravate monsters (If their equipment normally aggravates monsters, they only suffer a penalty to stealth, but if they aggravate by their personality itself, the advantage will be lost)."), + + _("クターとしている無表情の謎の生物です。彼らは外見がかわいらしいため、魅力が高いです。彼らは混乱しません。なぜなら、混乱してもクターとしているため変わりないからです。しかも、そのクターとしている外見から敵に見つかりにくいです。しかし、彼らは注意力が少ないため探索や知覚能力は悪いです。彼らはレベルが上がると横に伸びてACを上げる技を覚えますが、伸びている間は魔法防御能力は低くなってしまいます。", + "A Kutar is an expressionless animal-like living creature. The word 'kuta' means 'absentmindedly' or 'vacantly'. Their absentmindedness hurts their searching and perception skills, but renders them incapable of being confused. Their unearthly calmness and serenity make them among the most stealthy of any race. Kutars, although expressionless, are beautiful and so have a high charisma. Members of this race can learn to expand their body horizontally. This increases armour class, but renders them vulnerable to magical attacks."), + + _("アンドロイドは機械の身体を持つ人工的な存在です。魔法をうまく使うことはできませんが、戦士としては非常に優れています。彼らは他の種族のように経験値を得て成長するということはありません。身体に身につける装備によって成長します。ただし、指輪、アミュレット、光源は成長に影響しません。彼らは毒の耐性を持ち、麻痺知らずで、生命力を吸収されることがありません。また、身体が頑丈なのでACにボーナスを得ます。しかし身体のいたるところに電子回路が組み込まれているため、電撃によって通常よりも大きなダメージを受けてしまいます。彼らは食物からほとんど動力を得られませんが、油を補給する事で動力源を得る事ができます。", + "An android is a artificial creation with a body of machinery. They are poor at spell casting, but they make excellent warriors. They don't acquire experience like other races, but rather gain in power as they attach new equipment to their frame. Rings, amulets, and lights do not influence growth. Androids are resistant to poison, can move freely, and are immune to exp-draining attacks. Moreover, because of their hard metallic bodies, they get a bonus to AC. Androids have electronic circuits throughout their body and must beware of electric shocks. They gain very little nutrition from the food of mortals, but they can use flasks of oil as their energy source."), + + _("マーフォークは人型生物と水棲生物の合いの子たちの総称です。彼らは知的であり、陸上よりも水中での営みに適応している点で共通しています。彼らの真価は水中でこそ発揮されますが、彼らの文明は大抵陸上に長く滞在する何らかの術も有しています。それを失わない限り、陸上でも不自由はないでしょう。また、彼らは致命的な水難にも抗える能力を生まれつき持っています。", + "Merfolks are general terms for people of mixed races between humanoids and aquatic habitats. They have in common that they are intelligent and adapt to working underwater rather than on land. Their true value comes in water, but their civilization also has some form of staying longer on land. As long as you do not lose it, there will be no inconvenience on land. They also have the ability to withstand disaster by water."), +}; + +/*! 職業の解説メッセージテーブル */ +concptr class_explanations[MAX_CLASS] = +{ + _("戦士は、直面する問題のほとんどを細切れに叩き切ることで解決するキャラクタです。が、時折退却して魔法の道具の世話になることもあります。不運にも、高レベルなアイテムの多くは彼らが扱える範囲を越えています。", + "A Warrior is a hack-and-slash character, who solves most of his or her problems by cutting them to pieces, but will occasionally fall back on the help of a magical device. Unfortunately, many high-level devices may be forever beyond their use."), + + _("メイジは魔法使いであり、その機知によって生き延びなければなりません。戦士のように、単純に切りまくることで道を開くことは望めません。呪文書に加えて、メイジは助けになる魔法の道具を持ち運ぶべきです。これは他の何よりも遥かに簡単にマスターできます。魔法に必要な能力値は知能です。", + "A Mage is a spell caster that must live by his or her wits as a mage cannot hope to simply hack his or her way through the dungeon like a warrior. In addition to spellbooks, a mage should carry a range of magical devices to help his or her endeavors. A mage can master those devices far more easily than anyone else. A mage's prime statistic is Intelligence as this determines his or her spell casting ability."), + + _("プリーストは高貴な力を使うことに専念したキャラクタです。彼らは自身の神のためにダンジョンを探索し、もし宝を手にいれたなら、それは彼が信仰する宗教の栄光となります。プリーストは新しい祈りを神からの贈り物という形で受け取るため、どれを学ぶのか自分で選ぶことはできません。プリーストは魔法の道具の使い方をよく知っていますが、メイジほどうまくは使えません。刃のついた武器より鈍器を好み、祝福されていない刃のついた武器を装備すると不愉快な感覚に襲われ、戦闘能力が落ちてしまいます。魔法に必要な能力値は賢さです。", + "A Priest is a character devoted to serving a higher power. He or she explores the dungeon in the service of a God. Since Priests receive new prayers as gifts from their patron deity, they cannot choose which ones they will learn. Priests are familiar with magical devices which they believe act as foci for divine intervention in the natural order of things. A priest wielding an edged weapon will be so uncomfortable with it that his or her fighting ability decreases. A Priest's primary stat is Wisdom since this determines the success of the prayers to his or her deity."), + + _("盗賊はその狡猾さで生き抜くことを好むキャラクタですが、肝心なときには戦闘で道を切り開くことができます、盗賊は罠やドアを見つける能力に優れ、罠の解除や鍵開けに熟達しています。盗賊は高い隠密行動を持ち、たくさんのモンスターの群れのそばを起こすことなく通り抜けたり、忍び寄って先制攻撃することができます。魔法に必要な能力値は知能です。", + "A Rogue is a character that prefers to live by his or her cunning, but is capable of fighting out of a tight spot. Rogues are good at locating hidden traps and doors and are the masters of disarming traps and picking locks. A rogue is very stealthy, allowing him or her to sneak around many creatures without having to fight or to get in a telling first blow. A rogue may also backstab a fleeing monster. Intelligence determines a Rogue's spell casting ability."), + + _("レンジャーは戦士とメイジを合わせたような職業で、身の回りの自然と特別な関係を作り上げています。彼はより戦士であり、弓のような遠距離武器を巧く使える職業です。レンジャーはよい隠密行動、よい知覚、よい探索、よい魔法防御を持ち、魔法の道具の使用にも長けています。魔法に必要な能力値は知能です。", + "A Ranger is a combination of a warrior and a mage who has developed a special affinity for the natural world. He or she is a good fighter and also good with missile weapons such as bows. A ranger has good stealth, good perception, good searching, good saving throws and is good with magical devices. Intelligence determines a Ranger's spell casting ability."), + + _("パラディンは戦士とプリーストを合わせた職業です。パラディンはとてもよい戦士ですが、遠距離武器を扱うのは得意ではありません。パラディンには多くの能力が欠けています。隠密行動, 知覚, 探索, そして魔法道具使用が苦手ですが、その神との提携によって魔法防御はそこそこです。魔法に必要な能力値は賢さです。", + "A Paladin is a combination of a warrior and a priest. Paladins are very good fighters, but not very good at missile weapons. A paladin lacks much in the way of abilities. He or she is poor at stealth, perception, searching, and magical devices but has a decent saving throw due to his or her divine alliance. Wisdom determines a Paladin's success at praying to his or her deity."), + + _("魔法戦士はその名称が意味する通りの職業であり、戦士とメイジの資質をあわせ持ちます。彼らの同業者であるレンジャーが自然の魔法と生き抜くためのスキルに特化している一方、本当の魔法剣士はどちらの世界でも一番になろうとしています。戦士としては普通のメイジとは比べ物にならないほど優れています。しかし、実際には魔法でも戦闘でも専門の職業には及ばず、戦士とメイジの中間に位置するような職業です。魔法に必要な能力値は知能です。", + "A Warrior-Mage is precisely what the name suggests: a cross between the warrior and mage classes. Unlike rangers who specialize in Nature magic and survival skills, true Warrior-Mages attempt to reach the best of both worlds. As warriors they are much superior to the usual Mage class. Intelligence determines a Warrior-Mage's spell casting ability."), + + _("混沌の戦士は恐るべきカオスの魔王の使いとして恐れられる存在です。混沌の戦士はパトロンとなる悪魔を持ち、レベルが上がる度に報酬を得ることがあります。彼は治療してくれたり、こちらを変化させたり、能力値を上げてくれるかもしれませんし、回りに怪物達を出現させたり、能力値や装備を奪うかも知れません。もしくは単にこちらを無視するだけかもしれません。カオスの魔王は無秩序で予測のつかない存在です。報酬の種類はパトロンとなる悪魔と偶然に依存します(違う悪魔は異なる報酬を与えます)。魔法に必要な能力値は知能です。", + "Chaos Warriors are the feared servants of the terrible Demon Lords of Chaos. Every Chaos Warrior has a Patron Demon and, when gaining a level, may receive a reward from his or her Patron. He or she might be healed or polymorphed, given an awesome weapon, or have his or her stats increased. On the other hand, the Patron might surround the Chaos Warrior with monsters, drain his or her stats, wreck his or her equipment, or simply ignore the Chaos Warrior. The Demon Lords of Chaos are chaotic and unpredictable indeed. The exact type of reward depends on both the Patron Demon (different Demons give different rewards) and chance."), + + _("修行僧は他の職業とは著しく異なる職業です。彼らは他の職業同様武器と防具を使えますが、マーシャルアーツの訓練を積んでいるため、武器、防具なしでより強力な存在となります。高レベルでは、必要な耐性を身につけるためある種の防具を装備する必要がありますが、もしあまりに重すぎる防具を装備してしまうと、その体術に深刻な妨げとなります。レベルが上がると、彼らは新しい強力な攻撃法を学び、防御能力も上昇します。魔法に必要な能力値は賢さです。", + "The Monk character class is very different from all other classes. Their training in martial arts makes them much more powerful with no armor or weapons. To gain the resistances necessary for survival a monk may need to wear some kind of armor, but if the armor he or she wears is too heavy, it will severely disturb his or her martial arts maneuvers. As the monk advances levels, new, powerful forms of attack become available. Their defensive capabilities increase likewise, but if armour is being worn, this effect decreases. Wisdom determines a Monk's spell casting ability."), + + _("超能力者は魔法のかわりにその精神の力を使う唯一の職業です。この力は超能力者独特のもので、単に超感覚的なものから他人の精神を支配するものまで様々です。彼らの力はある種の訓練によって開発されるものなので、超能力者は力を使うのに呪文書を必要としません。使える力は単純にキャラクタのレベルによって決まります。超能力に必要な能力値は賢さです。", + "The Mindcrafter is a unique class that uses the powers of the mind instead of magic. These powers are unique to Mindcrafters, and vary from simple extrasensory powers to mental domination of others. Since these powers are developed by the practice of certain disciplines, a Mindcrafter requires no spellbooks to use them. The available powers are simply determined by the character's level. Wisdom determines a Mindcrafter's ability to use mind powers."), + + _("ハイメイジは一つの領域に特化し、その領域を通常のメイジよりはるかに深く学んだメイジです。1つの領域に特化したおかげで、彼らは自らが選択した領域の呪文を唱える際の消費MP、最低レベル、失敗率で相当な恩恵を受けます。しかし、生命の領域ではプリーストほどうまくはなれないことには注意すべきです。魔法に必要な能力値は知能です。", + "High-mages are mages who specialize in one particular field of magic and learn it very well - much better than the ordinary mage. For the price of giving up a second realm of magic, they gain substantial benefits in the mana costs, minimum levels, and failure rates in the spells of the realm of their specialty. A high mage's prime statistic is intelligence as this determines his or her spell casting ability."), + + _("観光客は観光のためにこの世界にやってきました。戦闘力が低く、強力な呪文を使うこともできないため、最も生きぬいていくのが厳しい職業と言えます。魔法に必要な能力値は知能です。", + "Tourists have visited this world for the purpose of sightseeing. Their fighting skills are bad, and they cannot cast powerful spells. They are the most difficult class to win the game with. Intelligence determines a tourist's spell casting ability."), + + _("ものまね師は戦闘力はそこそこありますが、自分から特殊な能力を使うことは全くできません。しかし、自分の目の前にいる相手が特殊能力を使った場合、その能力と全く同じ能力をそっくりそのまま使うことができます。ものまねに必要な能力は基本的に器用さですが、まねる特殊能力に関係ある他の能力も必要です。", + "Imitators have enough fighting skills to survive, but rely on their ability to imitate monster spells. When monsters in line of sight use spells, they are added to a temporary spell list which the imitator can choose among. Spells should be imitated quickly, because timing and situation are everything. An imitator can only repeat a spell once each time he or she observes it. Dexterity determines general imitation ability, but a stat related to the specific action is often also taken into account."), + + _("魔獣使いは馬鹿馬鹿蛮怒世界のダンジョンに住む生物と心を通い合わせられます。彼らは最もうまくモンスターを乗りこなすことができ、召喚したり手なづけたりしたモンスターを自分の手足のように使います。魔法に必要な能力は魅力です。", + "Beastmasters are in tune with the minds of the creatures of the world of Bakabakaband. They are very good at riding and have enough fighting ability. The monsters that a beastmaster summons or dominates become the beastmaster's hands and feet. Beastmasters can cast trump magic and are very good at summoning spells, but they can not summon non-living creatures. Charisma determines a Beastmaster's spell casting ability."), + + _("スペルマスターは全ての魔法を極める者です。彼らは全分野において非常に優れた魔法使いであり、あらゆる魔法書のすべての呪文を学習の手間なく使いこなすことができます。その反面、彼らは戦士としては最低で、どんな武器も満足に扱えません。魔術師の杖だけは例外ですが、武器としては使い物にならないでしょう。すべての魔法をうまく生かさなければならないため、非常に上級者向けな職業と言えます。魔法に必要な能力は知能です。", + "Sorcerers are the all-around best magicians, being able to cast any spell from most magic realms without having to learn it. On the downside, they are the worst fighters in the dungeon, being unable to use any weapon but a Wizardstaff."), + + _("アーチャーは魔法を使うことはできませんが、どんな職業よりも巧みに弓やスリングを使いこなします。大量の矢や弾を必要とするのは確かですが、岩石からスリング用の弾を作ったり、レベルが上がるとモンスターの骨やがらくたから矢を作ったりする技術を身につけます。また、戦士と比べて隠密行動、知覚、探索、魔法道具の使用などにも優れており、いざというときには魔法の道具に頼ることもできます。", + "Archers are to bows what warriors are to melee. They are the best class around with any bow, crossbow, or sling. They need a lot of ammunition, but will learn how to make it from junk found in the dungeon. An archer is better than a warrior at stealth, perception, searching and magical devices."), + + _("魔道具術師は杖、魔法棒、ロッドといった魔法のアイテムから魔力を取り込むことによって魔法を使います。魔法のアイテムを発見することが他の職業よりもはるかに重要になります。戦闘力は高くはないですが、そこそこの強さがあります。魔法に必要な能力は知能です。", + "Magic-Eaters can absorb the energy of wands, staffs, and rods, and can then use these magics as if they were carrying all of these absorbed devices. They are middling-poor at fighting. A Magic-Eater's prime statistic is intelligence."), + + _("吟遊詩人は魔力を帯びた歌を歌うことができます。多くの歌は普通の魔法と異なり、歌を歌っている間継続して効果を発揮します。しかし、同時に2つの歌を歌うことができない、という欠点もあります。視界内全体に影響を及ぼす歌が多い、という特徴もあります。肉体的な能力は貧弱で、単純に切りまくることで道を開くことはできません。魔法に必要な能力は魅力です。", + "Bards are something like traditional musicians. Their magical attacks are sound-based, and last as long as the Bard has mana. Although a bard cannot sing two or more songs at the same time, he or she does have the advantage that many songs affect all areas in sight. A bard's prime statistic is charisma."), + + _("赤魔道師は下級魔法のほとんどを使うことができ、戦闘力も十分にあります。レベルが上がると強力な能力「連続魔」を身につけることができます。しかし、魔法を覚えるスピードは遅く、上級魔法を使えないので、メイジほどには魔法を頼りにすることができません。魔法道具使用と魔法防御はそこそこですが、それ以外の技能は苦手です。魔法に必要な能力は知能です。", + "Red-Mages can use almost all spells from lower rank spellbooks of most realms without having to learn it. At higher level, they develop the powerful ability \"Double Magic\". However, they have large penalties in the mana costs, minimum levels, and failure rates of spells, and they cannot use any spells from higher rank spellbooks. They are not bad at using magical devices and magic resistance, and are decent fighters, but are bad at other skills. A red-mage's prime statistic is intelligence."), + + _("剣術家は戦士に次ぐ戦闘力があり、様々な技を使うことができます。彼らのMPはレベルに依存せず、賢さだけで決まり、気合いをためることにより、最大値を越えてMPを増やすことができます。しかし、戦士と同様、高レベルの魔法のアイテムは彼らの扱える範囲を越えており、罠の解除や探索の能力も高いとはいえません。必殺技の使用に必要な能力は賢さです。", + "Samurai, masters of the art of the blade, are the next strongest fighters after Warriors. Their spellpoints do not depend on level, but depend solely on wisdom, and they can use the technique Concentration to temporarily increase SP beyond its usual maximum value. Samurai are not good at most other skills, and many magical devices may be too difficult for them to use. Wisdom determines a Samurai's ability to use the special combat techniques available to him or her."), + + _("練気術師は「気」を使う達人です。修行僧と同様、武器や防具を持たずに戦うことを好み、武器・防具なしでより強力な存在となります。修行僧ほどの戦闘能力はありませんが、修行僧と同様の魔法が使え、さらに「気」の力を操ります。武器を持つことや、重すぎる防具を装備することは、「気」の力の使用を妨げます。魔法と練気術に必要な能力は賢さです。", + "A ForceTrainer is a master of the spiritual Force. They prefer fighting with neither weapons nor armor. They are not as good fighters as are Monks, but they can use both magic and the spiritual Force. Wielding weapons or wearing heavy armor disturbs use of the Force. Wisdom is a ForceTrainer's primary stat."), + + _("青魔道師は優れた魔法使いであり、その機知によって生き延びなければなりません。メイジ等の他の魔法使いとの違いは魔法の覚え方で、青魔道師はモンスターの魔法の効果を受けることでその魔法を覚えます。覚えるためには「ラーニング」の状態になっていないといけません。魔法に必要な能力は知能です。", + "A Blue-Mage is a spell caster that must live by his or her wits, as a Blue-Mage cannot hope to simply hack his or her way through the dungeon like a warrior. A major difference between the Mage and the Blue-Mage is the method of learning spells: a Blue-Mage may learn spells from monsters by activating his or her Learning ability. A Blue-Mage's prime statistic is Intelligence as this determines his or her spell casting ability."), + + _("騎兵は馬に乗り戦場を駆け抜けるエリート戦士です。魔法は使えませんが、馬上からの圧倒的な攻撃力を誇る上に、高い機動力を生かした射撃をも得意としています。レベルが上がれば、野生のモンスターにまたがり無理矢理手なずけることができます。彼らは己の肉体と精神に誇りを持ち、魔法道具にはあまり頼ろうとはしません。", + "Cavalry ride on horses into battle. Although they cannot cast spells, they are proud of their overwhelming offensive strength on horseback. They are good at shooting. At high levels, they learn to forcibly saddle and tame wild monsters. Since they take pride in the body and the soul, they don't use magical devices well."), + + _("狂戦士は怒り狂って武器を振るう恐るべき戦士です。全職業中最高の肉体能力を誇り、恐怖と麻痺に対する耐性を持ち、レベルが上がればその強靭な肉体で矢の呪文を跳ね返すことができます。さらに武器なしで戦うことや、呪いのかけられた装備を力づくで剥がすことができ、いくつかの技を(反魔法状態でも)使うことができます。しかし、巻物や魔法道具は全く使うことができず、罠の解除や隠密行動、探索、魔法防御、飛び道具の技能に関しては絶望的です。ひたすら殴って道を開くしかありません。幽霊は非常に勝利しやすいですがスコアがかなり低く修正されます。", + "A Berserker is a fearful fighter indeed, immune to fear and paralysis. At high levels, Berserkers can reflect bolt spells with their tough flesh. Furthermore, they can fight without weapons, can remove cursed equipment by force, and can even use their special combat techniques when surrounded by an anti-magic barrier. Berserkers, however, cannot use any magical devices or read any scrolls, and are hopeless at all non-combat skills. Since Berserker Spectres are quite easy to *win* with, their scores are lowered."), + + _("鍛冶師は武器や防具を自分で強化することができます。特殊効果を持つ武器や防具から特殊効果の元となるエッセンスを取り出し、別の武器や防具にエッセンスを付加することによってその特殊効果を付加できます。ある程度の戦闘能力も持ちますが、魔法は一切使用できず、隠密や魔法防御の技能も低くなります。", + "A Weaponsmith can improve weapons and armor for him or herself. They can extract the essences of special effects from weapons or armor which have various special abilities, and can add these essences to another weapon or armor. They are good at fighting, but cannot cast spells, and are poor at skills such as stealth or magic defense."), + + _("鏡使いは、魔力の込められた鏡を作り出して、それを触媒として攻撃を行なうことができる鏡魔法を使います。鏡使いは鏡の上で実力を発揮し、鏡の上では素早いテレポートが可能となります。魔法の鏡は、レベルによって一度に制御できる数が制限されます。鏡魔法に必要な能力は知能です。", + "Mirror-Masters are spell casters; like other mages, they must live by their wits. They can create magical mirrors, and employ them in the casting of Mirror-Magic spells. A Mirror-Master standing on a mirror has greater ability and, for example, can perform quick teleports. The maximum number of Magical Mirrors which can be controlled simultaneously depends on the level. Intelligence determines a Mirror-Master's spell casting ability."), + + _("忍者は暗闇に潜む恐るべき暗殺者であり、光源を持たずに行動し、相手の不意をつき一撃で息の根を止めます。また、相手を惑わすための忍術も身につけます。罠やドアを見つける能力に優れ、罠の解除や鍵開けに熟達しています。軽装を好み、重い鎧や武器を装備すると著しく動きが制限され、また、盾を装備しようとはしません。軽装ならば、レベルが上がるにつれより速くより静かに行動できます。さらに忍者は恐怖せず、成長すれば毒がほとんど効かなくなり、透明なものを見ることができるようになります。忍術に必要な能力は器用さです。", + "A Ninja is a fearful assassin lurking in darkness. He or she can navigate effectively with no light source, catch enemies unawares, and kill with a single blow. Ninjas can use Ninjutsu, and are good at locating hidden traps and doors, disarming traps and picking locks. Since heavy armor, heavy weapons, or shields will restrict their motion greatly, they prefer light clothes, and become faster and more stealthy as they gain levels. A Ninja knows no fear and, at high level, becomes almost immune to poison and able to see invisible things. Dexterity determines a Ninja's ability to use Ninjutsu."), + + _("スナイパーは一撃必殺を狙う恐るべき射手です。精神を高めることにより、射撃の威力と精度を高めます。また、魔法を使うことはできませんが、研ぎ澄まされた精神から繰り出される射撃術はさらなる威力をもたらすことでしょう。テクニックが必要とされる職業です。", + "Snipers are good at shooting, and they can kill targets by a few shots. After they concentrate deeply, they can demonstrate their shooting talents. You can see incredibly firepower of their shots."), +}; + +/*! 性格の解説メッセージテーブル */ +concptr personality_explanations[MAX_PERSONALITIES] = { + _("ふつうは、特に特筆するべき部分がない性格です。あらゆる技能を平均的にこなします。", + "\"Ordinary\" is a personality with no special skills or talents, with unmodified stats and skills."), + + _("ちからじまんは、肉体的な能力や技能が上昇します。しかし、魔法に関係する能力や技能は劣り、戦士よりのステータスを持ちます。", + "\"Mighty\" raises your physical stats and skills, but reduces stats and skills which influence magic. It makes your stats suitable for a warrior. Also it directly influences your hit-points and spell fail rate."), + + _("きれものは、肉体的な能力は下がりますが、知能や魔法に関係する技能は上昇し、メイジよりのステータスを持ちます。", + "\"Shrewd\" reduces your physical stats, and raises your intelligence and magical skills. It makes your stats suitable for a mage. Also it directly influences your hit-points and spell fail rate."), + + _("しあわせものは、神を信仰する能力が高くなります。肉体的には平均的な能力を持ち、プリーストに近いステータスとなります。", + "\"Pious\" deepens your faith in your God. It makes your physical ability average, and your stats suitable for priest."), + + _("すばしっこいは、どのスキルも比較的うまくこなしますが、肉体的な能力は低くなります。", + "\"Nimble\" improves most skills except for melee combat."), + + _("いのちしらずは、戦闘力、魔法能力の両方が上昇しますが、魔法防御、HPといった能力は悪くなります。", + "\"Fearless\" raises both your melee and magical ability. Stats such as magic defense and constitution are reduced. Also it has a direct bad influence on your hit-points."), + + _("好きな食べ物は焼きビーフン。抑えてはいるが、冒険心旺盛な一匹狼。正義感、勇気とも平均以上だがカッとしやすい所もある。計画的人生より行き当たりばったりの人生を選んでしまうタイプで、異性の扱いは苦手。", + "\"Combat\" gives you comparatively high melee and shooting abilities, and average constitution. Other skills such as stealth, magic defence, and magical devices are weakened. All \"Combat\" people have great respect for the legendary \"Combat Echizen\".\n\ +(See \"Death Crimson\" / Ecole Software Corp.)"), + + _("なまけものは、あらゆるスキルが低く、何をやってもうまくいきません。", + "A \"Lazy\" person has no good stats and can do no action well. Also it has a direct bad influence on your spell fail rate."), + + _("セクシーギャルは、あらゆるスキルをうまくこなすことができます。しかし、その人をなめた性格は全てのモンスターを怒らせることになるでしょう。この性格は女性しか選ぶことができません。", + "\"Sexy\" rises all of your abilities, but your haughty attitude will aggravate all monsters. Only females can choose this personality."), + + _("ラッキーマンは、能力値はなまけものに匹敵するくらい低いにもかかわらず、どんなことをしてもなぜかうまくいってしまいます。この性格は男性しか選ぶことができません。", + "A \"Lucky\" man has poor stats, equivalent to a \"Lazy\" person. Mysteriously, however, he can do all things well. Only males can choose this personality."), + + _("がまんづよいは、じっくりと物事にとりくむ慎重な性格で、他の性格に比べて高い耐久力を得ることができます。しかし、自分から行動するのは苦手で、多くの技能は低くなってしまいます。", + "A \"Patient\" person does things carefully. Patient people have high constitution, and high resilience, but poor abilities in most other skills. Also it directly influences your hit-points."), + + _("いかさまは、初心者の練習用の性格です。あらゆる能力が高くなっています。この性格を使えば勝利者になることは容易ですが、勝利しても全く自慢になりません。", + "\"Munchkin\" is a personality for beginners. It raises all your stats and skills. With this personality, you can win the game easily, but gain little honor in doing so."), + + _("チャージマンは「こんなところ」に連れて行かれても仕方のない可愛そうなお友達なんDA。腕っ節やタフさはマンモス並みに強いのだけれど知能面はまるで駄目なのが分かるだろう?この性格は最初から気が狂っているので、混乱したり幻覚を見る心配がないのです。", + "\"ChargeMan\" is a crazy killer. You are strong and tough but have poor intelligence. Since you're already insane, confusion and hallucinations do not affect you."), +}; + +/*! 魔法領域の詳細解説メッセージテーブル */ +concptr realm_explanations[VALID_REALM] = { + _("生命は回復能力に優れた魔法です。治療や防御、感知魔法が多く含まれていますが、攻撃呪文もわずかに持っています。特に高レベルの呪文にはアンデッドを塵に帰す力をあると言われています。", + "Life magic is very good for healing; it relies mostly on healing, protection and detection spells. Also life magic has a few attack spells as well. It's said that some high level spells of life magic can disintegrate Undead monsters into ash."), + + _("仙術は「meta」領域であり、感知や鑑定、さらに退却用の呪文や自身の能力を高める呪文などの便利な呪文が含まれています。しかし、直接攻撃用の呪文は持っていません。", + "Sorcery is a `meta` realm, including enchantment and general spells. It provides superb protection spells, spells to enhance your odds in combat and, most importantly, a vast selection of spells for gathering information. However, Sorcery has one weakness: it has no spells to deal direct damage to your enemies."), + + _("自然の魔法は使用者を元素のマスターにします。これには防御、探知、治療と攻撃呪文が含まれています。また、生命以外の領域で最高の治療呪文もこの領域にあります。", + "Nature magic makes you a master of the elements; it provides protection, detection, curing and attack spells. Nature also has a spell of Herbal Healing, which is the only powerful healing spell outside the realm of Life magic."), + + _("カオスの魔法は制御が困難で、予測のできない魔法もあります。カオスは非常に非元素的であり、カオスの呪文は想像できる最も恐るべき破壊兵器です。この呪文を唱えるものはカオスの尖兵に対し、敵や自分自身さえも変異させるよう要求します。", + "There are few types of magic more unpredictable and difficult to control than Chaos magic. Chaos is the very element of unmaking, and the Chaos spells are the most terrible weapons of destruction imaginable. The caster can also call on the primal forces of Chaos to induce mutations in his/her opponents and even him/herself."), + + _("黒魔術である暗黒の魔法ほど邪悪なカテゴリーはありません。これらの呪文は比較的学ぶのが困難ですが、高レベルになると術者に生物とアンデッドを自由に操る能力を与えます。残念なことに、もっとも強力な呪文はその触媒として術者自身の血を必要とし、詠唱中にしばしば術者を傷つけます。", + "There is no fouler nor more evil category of spells than the necromantic spells of Death Magic. These spells are relatively hard to learn, but at higher levels the spells give the caster power over living and the (un)dead, but the most powerful spells need his / her own blood as the focus, often hurting the caster in the process of casting."), + + _("トランプの魔法はテレポート系の呪文で精選されたものを持っており、その出入り口は他の生物を召喚するためにも使えるため、召喚呪文から選りすぐられたものも同様に持っています。しかし、この魔法によって全ての怪物が別の場所へ呼ばれるのを理解するわけではなく、もし召喚呪文に失敗するとその生物は敵となります。", + "Trump magic has, indeed, an admirable selection of teleportation spells. Since the Trump gateways can also be used to summon other creatures, Trump magic has an equally impressive selection of summoning spells. However, not all monsters appreciate being drawn to another place by Trump user."), + + _("秘術の魔法は、全ての領域から有用な呪文だけを取り入れようとした多用途領域です。必要な「道具」的呪文を持っていても高レベルの強力な呪文は持っていません。結果として、全ての呪文書は街で買い求めることができます。また、他の領域に存在する同様な呪文の方がより低レベル、低コストで唱えることができます。", + "Arcane magic is a general purpose realm of magic. It attempts to encompass all 'useful' spells from all realms. This is the downside of Arcane magic: while Arcane does have all the necessary 'tool' spells for a dungeon delver, it has no ultra-powerful high level spells. As a consequence, all Arcane spellbooks can be bought in town. It should also be noted that the 'specialized' realms usually offer the same spell at a lower level and cost."), + + _("匠の魔法は、自分や道具を強化するための魔法が含まれています。魔法によって自分自身の戦闘力を非常に高めることができますが、相手を直接攻撃するような呪文は含まれていません。", + "Craft magic can strengthen the caster or his or her equipment. These spells can greatly improve the caster's fighting ability. Using them against opponents directly is not possible."), + + _("悪魔の魔法は暗黒と同様非常に邪悪なカテゴリーです。様々な攻撃魔法に優れ、また悪魔のごとき知覚能力を得ることができます。高レベルの呪文は悪魔を自在に操り、自分自身の肉体をも悪魔化させることができます。", + "Demon is a very evil realm, same as Death. It provides various attack spells and devilish detection spells. At higher levels, Demon magic provides the ability to dominate demons and to polymorph yourself into a demon."), + + _("破邪は「正義」の魔法です。直接敵を傷つける魔法が多く含まれ、特に邪悪な敵に対する力は恐るべきものがあります。しかし、善良な敵にはあまり効果がありません。", + "Crusade is a magic of 'Justice'. It includes damage spells, which are greatly effective against foul and evil monsters, but have poor effects against good monsters."), + + _("歌集は、歌によって効果を発揮する魔法です。魔法と同様、使った時に効果のあるものと、歌い続けることによって持続して効果を発揮するものがあります。後者の場合は、MPの続く限り効果を発揮することができますが、同時に歌える歌は1つだけという制限もあります。", + "Music magic works through the caster singing songs. There are two types of songs; one which shows effects instantly and another which shows effects continuously until SP runs out. The latter type has a limit: only one song can be sung at a time."), + + _("武芸の書は、様々な戦闘の技について書かれています。この本は技を覚えるときに読む必要がありますが、一度覚えた技は使うのに本を持つ必要はありません。技を使うときには必ず武器を装備していなければいけません。", + "The books of Kenjutsu describe various combat techniques. When learning new techniques, you are required to carry the books, but once you memorize them, you don't have to carry them. When using a technique, wielding a weapon is required."), + + _("呪術は忌むべき領域です。複数の呪いの言葉を歌のように紡ぎながら詠唱します。多くの呪文は詠唱し続けることによって効果が持続されます。呪文には相手の行動を束縛するもの、ダメージを与えるもの、攻撃に対して反撃するものが多くあります。", + "Hex is an unsavory realm, like the death and demon realms. Some of the spells can act continuously by stringing together curses like a song. Spells may obstruct monsters' actions, deal damage to monsters in sight, or return damage to monsters who have damaged the caster."), +}; + +/*! 魔法領域の簡易解説メッセージテーブル */ +concptr realm_subinfo[VALID_REALM] = { + _("感知と防御と回復に優れています", "Good at detection and healing."), + _("攻撃はできませんが非常に便利です", "Utility and protective spells."), + _("感知と防御に優れています", "Good at detection and defence."), + _("破壊的な攻撃に優れています", "Offensive and destructive."), + _("生命のある敵への攻撃に優れています", "Ruins living creatures."), + _("召喚とテレポートに優れています", "Good at summoning and teleportation."), + _("やや弱いながらも非常に便利です", "Very useful but not as potent."), + _("直接戦闘の補助に優れています", "Support for melee fighting."), + _("攻撃と防御の両面に優れています", "Good at both offence and defence."), + _("邪悪な怪物に対する攻撃に優れています", "Destroys evil creatures."), + _("様々な魔法効果を持った歌を歌います", "Songs with magical effects."), + _("打撃攻撃に特殊能力を付加します", "Special attacks on melee."), + _("敵を邪魔しつつ復讐を狙います", "Good at obstacle and revenge."), +}; diff --git a/src/birth/birth-explanations-table.h b/src/birth/birth-explanations-table.h new file mode 100644 index 000000000..fd3b251c8 --- /dev/null +++ b/src/birth/birth-explanations-table.h @@ -0,0 +1,11 @@ +#pragma once + +#include "system/angband.h" +#include "player/player-personality.h" +#include "realm/realm-names-table.h" + +extern concptr race_explanations[MAX_RACES]; +extern concptr class_explanations[MAX_CLASS]; +extern concptr personality_explanations[MAX_PERSONALITIES]; +extern concptr realm_explanations[VALID_REALM]; +extern concptr realm_subinfo[VALID_REALM]; diff --git a/src/birth/birth-select-class.c b/src/birth/birth-select-class.c new file mode 100644 index 000000000..937c55c4d --- /dev/null +++ b/src/birth/birth-select-class.c @@ -0,0 +1,172 @@ +#include "birth/birth-select-class.h" +#include "birth/birth-util.h" +#include "player/player-class.h" +#include "player/player-race.h" +#include "io/input-key-acceptor.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/int-char-converter.h" + +static const char p2 = ')'; + +static void enumerate_class_list(char *sym) +{ + for (int n = 0; n < MAX_CLASS; n++) { + cp_ptr = &class_info[n]; + mp_ptr = &m_info[n]; + concptr str = cp_ptr->title; + if (n < 26) + sym[n] = I2A(n); + else + sym[n] = ('A' + n - 26); + + char buf[80]; + if (!(rp_ptr->choice & (1L << n))) + sprintf(buf, "%c%c(%s)", sym[n], p2, str); + else + sprintf(buf, "%c%c%s", sym[n], p2, str); + + put_str(buf, 13 + (n / 4), 2 + 19 * (n % 4)); + } +} + +static void display_class_stat(int cs, int *os, char *cur, char *sym) +{ + if (cs == *os) + return; + + c_put_str(TERM_WHITE, cur, 13 + (*os / 4), 2 + 19 * (*os % 4)); + put_str(" ", 3, 40); + if (cs == MAX_CLASS) { + sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); + put_str(" ", 4, 40); + put_str(" ", 5, 40); + } else { + cp_ptr = &class_info[cs]; + mp_ptr = &m_info[cs]; + concptr str = cp_ptr->title; + if (!(rp_ptr->choice & (1L << cs))) + sprintf(cur, "%c%c(%s)", sym[cs], p2, str); + else + sprintf(cur, "%c%c%s", sym[cs], p2, str); + + c_put_str(TERM_L_BLUE, cp_ptr->title, 3, 40); + put_str(_("の職業修正", ": Class modification"), 3, 40 + strlen(cp_ptr->title)); + put_str(_("腕力 知能 賢さ 器用 耐久 魅力 経験 ", "Str Int Wis Dex Con Chr EXP "), 4, 40); + char buf[80]; + sprintf(buf, "%+3d %+3d %+3d %+3d %+3d %+3d %+4d%% ", cp_ptr->c_adj[0], cp_ptr->c_adj[1], cp_ptr->c_adj[2], cp_ptr->c_adj[3], cp_ptr->c_adj[4], + cp_ptr->c_adj[5], cp_ptr->c_exp); + c_put_str(TERM_L_BLUE, buf, 5, 40); + } + + c_put_str(TERM_YELLOW, cur, 13 + (cs / 4), 2 + 19 * (cs % 4)); + *os = cs; +} + +static void interpret_class_select_key_move(char c, int *cs) +{ + if (c == '8') { + if (*cs >= 4) + *cs -= 4; + } + + if (c == '4') { + if (*cs > 0) + (*cs)--; + } + + if (c == '6') { + if (*cs < MAX_CLASS) + (*cs)++; + } + + if (c == '2') { + if ((*cs + 4) <= MAX_CLASS) + *cs += 4; + } +} + +static bool select_class(player_type *creature_ptr, char *cur, char *sym, int *k) +{ + int cs = creature_ptr->pclass; + int os = MAX_CLASS; + while (TRUE) { + display_class_stat(cs, &os, cur, sym); + if (*k >= 0) + break; + + char buf[80]; + sprintf(buf, _("職業を選んで下さい (%c-%c) ('='初期オプション設定): ", "Choose a class (%c-%c) ('=' for options): "), sym[0], sym[MAX_CLASS - 1]); + + put_str(buf, 10, 10); + char c = inkey(); + if (c == 'Q') + birth_quit(); + + if (c == 'S') + return FALSE; + + if (c == ' ' || c == '\r' || c == '\n') { + if (cs == MAX_CLASS) { + *k = randint0(MAX_CLASS); + cs = *k; + continue; + } else { + *k = cs; + break; + } + } + + interpret_class_select_key_move(c, &cs); + if (c == '*') { + *k = randint0(MAX_CLASS); + cs = *k; + continue; + } + + *k = (islower(c) ? A2I(c) : -1); + if ((*k >= 0) && (*k < MAX_CLASS)) { + cs = *k; + continue; + } + + *k = (isupper(c) ? (26 + c - 'A') : -1); + if ((*k >= 26) && (*k < MAX_CLASS)) { + cs = *k; + continue; + } else + *k = -1; + + birth_help_option(creature_ptr, c, BK_CLASS); + } + + return TRUE; +} + +/*! + * @brief プレイヤーの職業選択を行う / Player class + * @return なし + */ +bool get_player_class(player_type *creature_ptr) +{ + clear_from(10); + put_str( + _("注意:《職業》によってキャラクターの先天的な能力やボーナスが変化します。", "Note: Your 'class' determines various intrinsic abilities and bonuses."), + 23, 5); + put_str(_("()で囲まれた選択肢はこの種族には似合わない職業です。", "Any entries in parentheses should only be used by advanced players."), 11, 5); + + char sym[MAX_CLASS]; + enumerate_class_list(sym); + + char cur[80]; + sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); + int k = -1; + if (!select_class(creature_ptr, cur, sym, &k)) + return FALSE; + + creature_ptr->pclass = (byte)k; + cp_ptr = &class_info[creature_ptr->pclass]; + mp_ptr = &m_info[creature_ptr->pclass]; + c_put_str(TERM_L_BLUE, cp_ptr->title, 5, 15); + return TRUE; +} diff --git a/src/birth/birth-select-class.h b/src/birth/birth-select-class.h new file mode 100644 index 000000000..6d8220426 --- /dev/null +++ b/src/birth/birth-select-class.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool get_player_class(player_type *creature_ptr); diff --git a/src/birth/birth-select-personality.c b/src/birth/birth-select-personality.c new file mode 100644 index 000000000..1b0e0f148 --- /dev/null +++ b/src/birth/birth-select-personality.c @@ -0,0 +1,204 @@ +#include "birth/birth-select-personality.h" +#include "birth/birth-util.h" +#include "io/input-key-acceptor.h" +#include "player/player-personality.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/int-char-converter.h" + +static const char p2 = ')'; + +static void enumerate_personality_list(player_type *creature_ptr, concptr *str, char *sym) +{ + char buf[80]; + for (int n = 0; n < MAX_PERSONALITIES; n++) { + if (personality_info[n].sex && (personality_info[n].sex != (creature_ptr->psex + 1))) + continue; + + ap_ptr = &personality_info[n]; + *str = ap_ptr->title; + if (n < 26) + sym[n] = I2A(n); + else + sym[n] = ('A' + n - 26); + + sprintf(buf, "%c%c%s", I2A(n), p2, *str); + put_str(buf, 12 + (n / 4), 2 + 18 * (n % 4)); + } +} + +static void display_personality_stat(int cs, int *os, concptr *str, char *cur, char *sym) +{ + char buf[80]; + if (cs == *os) + return; + + c_put_str(TERM_WHITE, cur, 12 + (*os / 4), 2 + 18 * (*os % 4)); + put_str(" ", 3, 40); + if (cs == MAX_PERSONALITIES) { + sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); + put_str(" ", 4, 40); + put_str(" ", 5, 40); + } else { + ap_ptr = &personality_info[cs]; + *str = ap_ptr->title; + sprintf(cur, "%c%c%s", sym[cs], p2, *str); + c_put_str(TERM_L_BLUE, ap_ptr->title, 3, 40); + put_str(_("の性格修正", ": Personality modification"), 3, 40 + strlen(ap_ptr->title)); + put_str(_("腕力 知能 賢さ 器用 耐久 魅力 ", "Str Int Wis Dex Con Chr "), 4, 40); + sprintf(buf, "%+3d %+3d %+3d %+3d %+3d %+3d ", ap_ptr->a_adj[0], ap_ptr->a_adj[1], ap_ptr->a_adj[2], ap_ptr->a_adj[3], ap_ptr->a_adj[4], + ap_ptr->a_adj[5]); + c_put_str(TERM_L_BLUE, buf, 5, 40); + } + + c_put_str(TERM_YELLOW, cur, 12 + (cs / 4), 2 + 18 * (cs % 4)); + *os = cs; +} + +static void interpret_personality_select_key_move(player_type *creature_ptr, char c, int *cs) +{ + if (c == '8') { + if (*cs >= 4) + *cs -= 4; + if ((*cs != MAX_PERSONALITIES) && personality_info[*cs].sex && (personality_info[*cs].sex != (creature_ptr->psex + 1))) { + if ((*cs - 4) > 0) + *cs -= 4; + else + *cs += 4; + } + } + + if (c == '4') { + if (*cs > 0) + (*cs)--; + if ((*cs != MAX_PERSONALITIES) && personality_info[*cs].sex && (personality_info[*cs].sex != (creature_ptr->psex + 1))) { + if ((*cs - 1) > 0) + (*cs)--; + else + (*cs)++; + } + } + + if (c == '6') { + if (*cs < MAX_PERSONALITIES) + (*cs)++; + if ((*cs != MAX_PERSONALITIES) && personality_info[*cs].sex && (personality_info[*cs].sex != (creature_ptr->psex + 1))) { + if ((*cs + 1) <= MAX_PERSONALITIES) + (*cs)++; + else + (*cs)--; + } + } + + if (c == '2') { + if ((*cs + 4) <= MAX_PERSONALITIES) + *cs += 4; + if ((*cs != MAX_PERSONALITIES) && personality_info[*cs].sex && (personality_info[*cs].sex != (creature_ptr->psex + 1))) { + if ((*cs + 4) <= MAX_PERSONALITIES) + *cs += 4; + else + *cs -= 4; + } + } +} + +static bool select_personality(player_type *creature_ptr, int *k, concptr *str, char *sym) +{ + char cur[80]; + sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); + int cs = creature_ptr->pseikaku; + int os = MAX_PERSONALITIES; + while (TRUE) { + display_personality_stat(cs, &os, str, cur, sym); + if (*k >= 0) + break; + + char buf[80]; + sprintf( + buf, _("性格を選んで下さい (%c-%c) ('='初期オプション設定): ", "Choose a personality (%c-%c) ('=' for options): "), sym[0], sym[MAX_PERSONALITIES - 1]); + put_str(buf, 10, 10); + char c = inkey(); + if (c == 'Q') + birth_quit(); + + if (c == 'S') + return FALSE; + + if (c == ' ' || c == '\r' || c == '\n') { + if (cs == MAX_PERSONALITIES) { + do { + *k = randint0(MAX_PERSONALITIES); + } while (personality_info[*k].sex && (personality_info[*k].sex != (creature_ptr->psex + 1))); + + cs = *k; + continue; + } else { + *k = cs; + break; + } + } + + interpret_personality_select_key_move(creature_ptr, c, &cs); + if (c == '*') { + do { + *k = randint0(MAX_PERSONALITIES); + } while (personality_info[*k].sex && (personality_info[*k].sex != (creature_ptr->psex + 1))); + + cs = *k; + continue; + } + + *k = (islower(c) ? A2I(c) : -1); + if ((*k >= 0) && (*k < MAX_PERSONALITIES)) { + if ((personality_info[*k].sex == 0) || (personality_info[*k].sex == (creature_ptr->psex + 1))) { + cs = *k; + continue; + } + } + + *k = (isupper(c) ? (26 + c - 'A') : -1); + if ((*k >= 26) && (*k < MAX_PERSONALITIES)) { + if ((personality_info[*k].sex == 0) || (personality_info[*k].sex == (creature_ptr->psex + 1))) { + cs = *k; + continue; + } + } else + *k = -1; + + birth_help_option(creature_ptr, c, BK_PERSONALITY); + } + + return TRUE; +} + +/*! + * @brief プレイヤーの性格選択を行う / Player Player seikaku + * @return なし + */ +bool get_player_personality(player_type *creature_ptr) +{ + clear_from(10); + put_str(_("注意:《性格》によってキャラクターの能力やボーナスが変化します。", "Note: Your personality determines various intrinsic abilities and bonuses."), + 23, 5); + concptr str; + char sym[MAX_PERSONALITIES]; + enumerate_personality_list(creature_ptr, &str, sym); + int k = -1; + if (!select_personality(creature_ptr, &k, &str, sym)) + return FALSE; + + creature_ptr->pseikaku = (player_personality_type)k; + ap_ptr = &personality_info[creature_ptr->pseikaku]; + char tmp[64]; +#ifdef JP + strcpy(tmp, ap_ptr->title); + if (ap_ptr->no == 1) + strcat(tmp, "の"); +#else + strcpy(tmp, ap_ptr->title); + strcat(tmp, " "); +#endif + strcat(tmp, creature_ptr->name); + c_put_str(TERM_L_BLUE, tmp, 1, 34); + return TRUE; +} diff --git a/src/birth/birth-select-personality.h b/src/birth/birth-select-personality.h new file mode 100644 index 000000000..a60f1c017 --- /dev/null +++ b/src/birth/birth-select-personality.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool get_player_personality(player_type *creature_ptr); diff --git a/src/birth/birth-select-race.c b/src/birth/birth-select-race.c new file mode 100644 index 000000000..fbd44e243 --- /dev/null +++ b/src/birth/birth-select-race.c @@ -0,0 +1,159 @@ +#include "birth/birth-select-race.h" +#include "birth/birth-util.h" +#include "io/input-key-acceptor.h" +#include "player/player-race.h" +#include "player/race-info-table.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/int-char-converter.h" + +static const char p2 = ')'; + +static void enumerate_race_list(char *sym) +{ + char buf[80]; + for (int n = 0; n < MAX_RACES; n++) { + rp_ptr = &race_info[n]; + concptr str = rp_ptr->title; + if (n < 26) + sym[n] = I2A(n); + else + sym[n] = ('A' + n - 26); + + sprintf(buf, "%c%c%s", sym[n], p2, str); + put_str(buf, 12 + (n / 5), 1 + 16 * (n % 5)); + } +} + +static void display_race_stat(int cs, int *os, char *cur, char *sym) +{ + char buf[80]; + if (cs == *os) + return; + + c_put_str(TERM_WHITE, cur, 12 + (*os / 5), 1 + 16 * (*os % 5)); + put_str(" ", 3, 40); + if (cs == MAX_RACES) { + sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); + put_str(" ", 4, 40); + put_str(" ", 5, 40); + } else { + rp_ptr = &race_info[cs]; + concptr str = rp_ptr->title; + sprintf(cur, "%c%c%s", sym[cs], p2, str); + c_put_str(TERM_L_BLUE, rp_ptr->title, 3, 40); + put_str(_("腕力 知能 賢さ 器用 耐久 魅力 経験 ", "Str Int Wis Dex Con Chr EXP "), 4, 40); + put_str(_("の種族修正", ": Race modification"), 3, 40 + strlen(rp_ptr->title)); + + sprintf(buf, "%+3d %+3d %+3d %+3d %+3d %+3d %+4d%% ", rp_ptr->r_adj[0], rp_ptr->r_adj[1], rp_ptr->r_adj[2], rp_ptr->r_adj[3], rp_ptr->r_adj[4], + rp_ptr->r_adj[5], (rp_ptr->r_exp - 100)); + c_put_str(TERM_L_BLUE, buf, 5, 40); + } + + c_put_str(TERM_YELLOW, cur, 12 + (cs / 5), 1 + 16 * (cs % 5)); + *os = cs; +} + +static void interpret_race_select_key_move(char c, int *cs) +{ + if (c == '8') { + if (*cs >= 5) + *cs -= 5; + } + + if (c == '4') { + if (*cs > 0) + (*cs)--; + } + + if (c == '6') { + if (*cs < MAX_RACES) + (*cs)++; + } + + if (c == '2') { + if ((*cs + 5) <= MAX_RACES) + *cs += 5; + } +} + +static bool select_race(player_type *creature_ptr, char *sym, int *k) +{ + char cur[80]; + sprintf(cur, "%c%c%s", '*', p2, _("ランダム", "Random")); + int cs = creature_ptr->prace; + int os = MAX_RACES; + while (TRUE) { + display_race_stat(cs, &os, cur, sym); + if (*k >= 0) + break; + + char buf[80]; + sprintf(buf, _("種族を選んで下さい (%c-%c) ('='初期オプション設定): ", "Choose a race (%c-%c) ('=' for options): "), sym[0], sym[MAX_RACES - 1]); + put_str(buf, 10, 10); + char c = inkey(); + if (c == 'Q') + birth_quit(); + + if (c == 'S') + return FALSE; + + if (c == ' ' || c == '\r' || c == '\n') { + if (cs == MAX_RACES) { + *k = randint0(MAX_RACES); + cs = *k; + continue; + } else { + *k = cs; + break; + } + } + + if (c == '*') { + *k = randint0(MAX_RACES); + cs = *k; + continue; + } + + interpret_race_select_key_move(c, &cs); + *k = (islower(c) ? A2I(c) : -1); + if ((*k >= 0) && (*k < MAX_RACES)) { + cs = *k; + continue; + } + + *k = (isupper(c) ? (26 + c - 'A') : -1); + if ((*k >= 26) && (*k < MAX_RACES)) { + cs = *k; + continue; + } else + *k = -1; + + birth_help_option(creature_ptr, c, BK_RACE); + } + + return TRUE; +} + +/*! + * @brief プレイヤーの種族選択を行う / Player race + * @return なし + */ +bool get_player_race(player_type *creature_ptr) +{ + clear_from(10); + put_str( + _("注意:《種族》によってキャラクターの先天的な資質やボーナスが変化します。", "Note: Your 'race' determines various intrinsic factors and bonuses."), + 23, 5); + + char sym[MAX_RACES]; + enumerate_race_list(sym); + int k = -1; + if (!select_race(creature_ptr, sym, &k)) + return FALSE; + + creature_ptr->prace = (byte)k; + rp_ptr = &race_info[creature_ptr->prace]; + c_put_str(TERM_L_BLUE, rp_ptr->title, 4, 15); + return TRUE; +} diff --git a/src/birth/birth-select-race.h b/src/birth/birth-select-race.h new file mode 100644 index 000000000..74b866b44 --- /dev/null +++ b/src/birth/birth-select-race.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool get_player_race(player_type *creature_ptr); diff --git a/src/birth/birth-select-realm.c b/src/birth/birth-select-realm.c new file mode 100644 index 000000000..d42567f46 --- /dev/null +++ b/src/birth/birth-select-realm.c @@ -0,0 +1,384 @@ +#include "birth/birth-select-realm.h" +#include "birth/birth-explanations-table.h" +#include "birth/birth-util.h" +#include "core/asking-player.h" +#include "io/input-key-acceptor.h" +#include "player/player-realm.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/buffer-shaper.h" +#include "util/int-char-converter.h" + +static const byte REALM_SELECT_CANCEL = 255; + +typedef struct birth_realm_type { + int cs; + int n; + char p2; + char sym[VALID_REALM]; + char buf[80]; + int picks[VALID_REALM]; + char cur[80]; + int k; + int os; +} birth_realm_type; + +static byte count_realm_selection(s32b choices, int *count) +{ + byte auto_select = REALM_NONE; + if (choices & CH_LIFE) { + (*count)++; + auto_select = REALM_LIFE; + } + + if (choices & CH_SORCERY) { + (*count)++; + auto_select = REALM_SORCERY; + } + + if (choices & CH_NATURE) { + (*count)++; + auto_select = REALM_NATURE; + } + + if (choices & CH_CHAOS) { + (*count)++; + auto_select = REALM_CHAOS; + } + + if (choices & CH_DEATH) { + (*count)++; + auto_select = REALM_DEATH; + } + + if (choices & CH_TRUMP) { + (*count)++; + auto_select = REALM_TRUMP; + } + + if (choices & CH_ARCANE) { + (*count)++; + auto_select = REALM_ARCANE; + } + + if (choices & CH_ENCHANT) { + (*count)++; + auto_select = REALM_CRAFT; + } + + if (choices & CH_DAEMON) { + (*count)++; + auto_select = REALM_DAEMON; + } + + if (choices & CH_CRUSADE) { + (*count)++; + auto_select = REALM_CRUSADE; + } + + if (choices & CH_MUSIC) { + (*count)++; + auto_select = REALM_MUSIC; + } + + if (choices & CH_HISSATSU) { + (*count)++; + auto_select = REALM_HISSATSU; + } + + if (choices & CH_HEX) { + (*count)++; + auto_select = REALM_HEX; + } + + return auto_select; +} + +static birth_realm_type *initialize_birth_realm_type(birth_realm_type *birth_realm_ptr) +{ + birth_realm_ptr->cs = 0; + birth_realm_ptr->n = 0; + birth_realm_ptr->p2 = ')'; + for (int i = 0; i < VALID_REALM; i++) + birth_realm_ptr->picks[i] = 0; + + birth_realm_ptr->k = -1; + return birth_realm_ptr; +} + +static void impose_first_realm(player_type *creature_ptr, s32b choices) +{ + if (creature_ptr->realm2 == REALM_SELECT_CANCEL) + return; + + if (creature_ptr->pclass != CLASS_PRIEST) + return; + + if (is_good_realm(creature_ptr->realm1)) { + choices &= ~(CH_DEATH | CH_DAEMON); + } else { + choices &= ~(CH_LIFE | CH_CRUSADE); + } +} + +static void analyze_realms(player_type *creature_ptr, s32b choices, birth_realm_type *birth_realm_ptr) +{ + for (int i = 0; i < 32; i++) { + if ((choices & (1L << i)) == 0) + continue; + + if (creature_ptr->realm1 == i + 1) { + if (creature_ptr->realm2 == REALM_SELECT_CANCEL) + birth_realm_ptr->cs = birth_realm_ptr->n; + else + continue; + } + + if (creature_ptr->realm2 == i + 1) + birth_realm_ptr->cs = birth_realm_ptr->n; + + birth_realm_ptr->sym[birth_realm_ptr->n] = I2A(birth_realm_ptr->n); + + sprintf(birth_realm_ptr->buf, "%c%c %s", birth_realm_ptr->sym[birth_realm_ptr->n], birth_realm_ptr->p2, realm_names[i + 1]); + put_str(birth_realm_ptr->buf, 12 + (birth_realm_ptr->n / 5), 2 + 15 * (birth_realm_ptr->n % 5)); + birth_realm_ptr->picks[birth_realm_ptr->n++] = i + 1; + } +} + +static void move_birth_realm_cursor(birth_realm_type *birth_realm_ptr) +{ + if (birth_realm_ptr->cs == birth_realm_ptr->os) + return; + + c_put_str(TERM_WHITE, birth_realm_ptr->cur, 12 + (birth_realm_ptr->os / 5), 2 + 15 * (birth_realm_ptr->os % 5)); + + if (birth_realm_ptr->cs == birth_realm_ptr->n) { + sprintf(birth_realm_ptr->cur, "%c%c %s", '*', birth_realm_ptr->p2, _("ランダム", "Random")); + } else { + sprintf(birth_realm_ptr->cur, "%c%c %s", birth_realm_ptr->sym[birth_realm_ptr->cs], birth_realm_ptr->p2, + realm_names[birth_realm_ptr->picks[birth_realm_ptr->cs]]); + sprintf(birth_realm_ptr->buf, "%s", realm_names[birth_realm_ptr->picks[birth_realm_ptr->cs]]); + c_put_str(TERM_L_BLUE, birth_realm_ptr->buf, 3, 40); + prt(_("の特徴", ": Characteristic"), 3, 40 + strlen(birth_realm_ptr->buf)); + prt(realm_subinfo[technic2magic(birth_realm_ptr->picks[birth_realm_ptr->cs]) - 1], 4, 40); + } + + c_put_str(TERM_YELLOW, birth_realm_ptr->cur, 12 + (birth_realm_ptr->cs / 5), 2 + 15 * (birth_realm_ptr->cs % 5)); + birth_realm_ptr->os = birth_realm_ptr->cs; +} + +static void interpret_realm_select_key(birth_realm_type *birth_realm_ptr, char c) +{ + if (c == 'Q') + birth_quit(); + + if (c == '8') { + if (birth_realm_ptr->cs >= 5) + birth_realm_ptr->cs -= 5; + } + + if (c == '4') { + if (birth_realm_ptr->cs > 0) + birth_realm_ptr->cs--; + } + + if (c == '6') { + if (birth_realm_ptr->cs < birth_realm_ptr->n) + birth_realm_ptr->cs++; + } + + if (c == '2') { + if ((birth_realm_ptr->cs + 5) <= birth_realm_ptr->n) + birth_realm_ptr->cs += 5; + } +} + +static bool get_a_realm(player_type *creature_ptr, birth_realm_type *birth_realm_ptr) +{ + birth_realm_ptr->os = birth_realm_ptr->n; + while (TRUE) { + move_birth_realm_cursor(birth_realm_ptr); + if (birth_realm_ptr->k >= 0) + break; + + sprintf(birth_realm_ptr->buf, _("領域を選んで下さい(%c-%c) ('='初期オプション設定): ", "Choose a realm (%c-%c) ('=' for options): "), + birth_realm_ptr->sym[0], birth_realm_ptr->sym[birth_realm_ptr->n - 1]); + + put_str(birth_realm_ptr->buf, 10, 10); + char c = inkey(); + interpret_realm_select_key(birth_realm_ptr, c); + if (c == 'S') + return TRUE; + + if (c == ' ' || c == '\r' || c == '\n') { + if (birth_realm_ptr->cs == birth_realm_ptr->n) { + birth_realm_ptr->k = randint0(birth_realm_ptr->n); + break; + } else { + birth_realm_ptr->k = birth_realm_ptr->cs; + break; + } + } + + if (c == '*') { + birth_realm_ptr->k = randint0(birth_realm_ptr->n); + break; + } + + birth_realm_ptr->k = (islower(c) ? A2I(c) : -1); + if ((birth_realm_ptr->k >= 0) && (birth_realm_ptr->k < birth_realm_ptr->n)) { + birth_realm_ptr->cs = birth_realm_ptr->k; + continue; + } + + birth_realm_ptr->k = (isupper(c) ? (26 + c - 'A') : -1); + if ((birth_realm_ptr->k >= 26) && (birth_realm_ptr->k < birth_realm_ptr->n)) { + birth_realm_ptr->cs = birth_realm_ptr->k; + continue; + } else + birth_realm_ptr->k = -1; + + birth_help_option(creature_ptr, c, BK_REALM); + } + + return FALSE; +} + +/*! + * @brief プレイヤーの魔法領域を選択する / Choose from one of the available magical realms + * @param choices 選択可能な魔法領域のビット配列 + * @param count 選択可能な魔法領域を返すポインタ群。 + * @return 選択した魔法領域のID + * @details 領域数が0 (戦士等)or 1 (観光客等)なら自動での値を返す + */ +static byte select_realm(player_type *creature_ptr, s32b choices, int *count) +{ + byte auto_select = count_realm_selection(choices, count); + clear_from(10); + if ((*count) < 2) + return auto_select; + + impose_first_realm(creature_ptr, choices); + put_str(_("注意:魔法の領域の選択によりあなたが習得する呪文のタイプが決まります。", "Note: The realm of magic will determine which spells you can learn."), + 23, 5); + + birth_realm_type tmp_birth_realm; + birth_realm_type *birth_realm_ptr = initialize_birth_realm_type(&tmp_birth_realm); + analyze_realms(creature_ptr, choices, birth_realm_ptr); + sprintf(birth_realm_ptr->cur, "%c%c %s", '*', birth_realm_ptr->p2, _("ランダム", "Random")); + if (get_a_realm(creature_ptr, birth_realm_ptr)) + return REALM_SELECT_CANCEL; + + clear_from(10); + return (byte)(birth_realm_ptr->picks[birth_realm_ptr->k]); +} + +static void cleanup_realm_selection_window(void) +{ + clear_from(10); + put_str(" ", 3, 40); + put_str(" ", 4, 40); + put_str(" ", 5, 40); +} + +/*! + * @brief 選んだ魔法領域で本当に良いか問い合わせる + * @param count 魔法領域の数 + * @return 選んだ魔法領域で良ければTRUE、再選択ならばFALSE + */ +static bool check_realm_selection(player_type *creature_ptr, int count) +{ + if (count < 2) { + prt(_("何かキーを押してください", "Hit any key."), 0, 0); + (void)inkey(); + prt("", 0, 0); + return TRUE; + } else if (get_check_strict(creature_ptr, _("よろしいですか?", "Are you sure? "), CHECK_DEFAULT_Y)) + return TRUE; + + return FALSE; +} + +/*! + * @brief 選択した魔法領域の解説を表示する / Choose the magical realms + * @return ユーザが魔法領域の確定を選んだらTRUEを返す。 + */ +bool get_player_realms(player_type *creature_ptr) +{ + /* Clean up infomation of modifications */ + put_str(" ", 3, 40); + put_str(" ", 4, 40); + put_str(" ", 5, 40); + + /* Select the first realm */ + creature_ptr->realm1 = REALM_NONE; + creature_ptr->realm2 = REALM_SELECT_CANCEL; + while (TRUE) { + char temp[80 * 10]; + int count = 0; + creature_ptr->realm1 = select_realm(creature_ptr, realm_choices1[creature_ptr->pclass], &count); + + if (creature_ptr->realm1 == REALM_SELECT_CANCEL) + return FALSE; + if (!creature_ptr->realm1) + break; + + cleanup_realm_selection_window(); + shape_buffer(realm_explanations[technic2magic(creature_ptr->realm1) - 1], 74, temp, sizeof(temp)); + concptr t = temp; + for (int i = 0; i < 10; i++) { + if (t[0] == 0) + break; + else { + prt(t, 12 + i, 3); + t += strlen(t) + 1; + } + } + + if (check_realm_selection(creature_ptr, count)) + break; + } + + /* Select the second realm */ + creature_ptr->realm2 = REALM_NONE; + if (creature_ptr->realm1 == REALM_NONE) + return TRUE; + + /* Print the realm */ + put_str(_("魔法 :", "Magic :"), 6, 1); + c_put_str(TERM_L_BLUE, realm_names[creature_ptr->realm1], 6, 15); + + /* Select the second realm */ + while (TRUE) { + char temp[80 * 8]; + int count = 0; + creature_ptr->realm2 = select_realm(creature_ptr, realm_choices2[creature_ptr->pclass], &count); + + if (creature_ptr->realm2 == REALM_SELECT_CANCEL) + return FALSE; + if (!creature_ptr->realm2) + break; + + cleanup_realm_selection_window(); + shape_buffer(realm_explanations[technic2magic(creature_ptr->realm2) - 1], 74, temp, sizeof(temp)); + concptr t = temp; + for (int i = 0; i < A_MAX; i++) { + if (t[0] == 0) + break; + else { + prt(t, 12 + i, 3); + t += strlen(t) + 1; + } + } + + if (check_realm_selection(creature_ptr, count)) + break; + } + + if (creature_ptr->realm2) { + /* Print the realm */ + c_put_str(TERM_L_BLUE, format("%s, %s", realm_names[creature_ptr->realm1], realm_names[creature_ptr->realm2]), 6, 15); + } + + return TRUE; +} diff --git a/src/birth/birth-select-realm.h b/src/birth/birth-select-realm.h new file mode 100644 index 000000000..109bc3923 --- /dev/null +++ b/src/birth/birth-select-realm.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool get_player_realms(player_type* creature_ptr); diff --git a/src/birth/birth-stat.c b/src/birth/birth-stat.c new file mode 100644 index 000000000..7d7ad278e --- /dev/null +++ b/src/birth/birth-stat.c @@ -0,0 +1,181 @@ +#include "birth/birth-stat.h" +#include "core/player-redraw-types.h" +#include "sv-definition/sv-weapon-types.h" +#include "player/player-class.h" +#include "player/player-personality.h" +#include "player/player-personalities-types.h" +#include "player/player-race.h" +#include "player/player-skill.h" +#include "spell/spells-status.h" +#include "player/player-race-types.h" + +/*! + * @brief プレイヤーの能力値表現に基づいて加減算を行う。 + * @param value 現在の能力値 + * @param amount 加減算する値 + * @return 加減算の結果 + */ +int adjust_stat(int value, int amount) +{ + if (amount < 0) { + for (int i = 0; i < (0 - amount); i++) { + if (value >= 18 + 10) { + value -= 10; + } else if (value > 18) { + value = 18; + } else if (value > 3) { + value--; + } + } + } else if (amount > 0) { + for (int i = 0; i < amount; i++) { + if (value < 18) { + value++; + } else { + value += 10; + } + } + } + + return value; +} + +/*! + * @brief プレイヤーの能力値を一通りロールする。 / Roll for a characters stats + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + * @details + * calc_bonuses()による、独立ステータスからの副次ステータス算出も行っている。 + * For efficiency, we include a chunk of "calc_bonuses()".\n + */ +void get_stats(player_type* creature_ptr) +{ + while (TRUE) { + int sum = 0; + for (int i = 0; i < 2; i++) { + s32b tmp = randint0(60 * 60 * 60); + BASE_STATUS val; + + /* Extract 5 + 1d3 + 1d4 + 1d5 */ + val = 5 + 3; + val += tmp % 3; + tmp /= 3; + val += tmp % 4; + tmp /= 4; + val += tmp % 5; + tmp /= 5; + + sum += val; + creature_ptr->stat_cur[3 * i] = creature_ptr->stat_max[3 * i] = val; + + /* Extract 5 + 1d3 + 1d4 + 1d5 */ + val = 5 + 3; + val += tmp % 3; + tmp /= 3; + val += tmp % 4; + tmp /= 4; + val += tmp % 5; + tmp /= 5; + + sum += val; + creature_ptr->stat_cur[3 * i + 1] = creature_ptr->stat_max[3 * i + 1] = val; + + val = 5 + 3; + val += tmp % 3; + tmp /= 3; + val += tmp % 4; + tmp /= 4; + val += (BASE_STATUS)tmp; + + sum += val; + creature_ptr->stat_cur[3 * i + 2] = creature_ptr->stat_max[3 * i + 2] = val; + } + + if ((sum > 42 + 5 * 6) && (sum < 57 + 5 * 6)) + break; + } +} + +/*! + * @brief その他「オートローラ中は算出の対象にしない」副次ステータスを処理する / Roll for some info that the auto-roller ignores + * @return なし + */ +void get_extra(player_type* creature_ptr, bool roll_hitdie) +{ + if (creature_ptr->prace == RACE_ANDROID) + creature_ptr->expfact = rp_ptr->r_exp; + else + creature_ptr->expfact = rp_ptr->r_exp + cp_ptr->c_exp; + + if (((creature_ptr->pclass == CLASS_MONK) || (creature_ptr->pclass == CLASS_FORCETRAINER) || (creature_ptr->pclass == CLASS_NINJA)) && ((creature_ptr->prace == RACE_KLACKON) || (creature_ptr->prace == RACE_SPRITE))) + creature_ptr->expfact -= 15; + + /* Reset record of race/realm changes */ + creature_ptr->start_race = creature_ptr->prace; + creature_ptr->old_race1 = 0L; + creature_ptr->old_race2 = 0L; + creature_ptr->old_realm = 0; + + for (int i = 0; i < 64; i++) { + if (creature_ptr->pclass == CLASS_SORCERER) + creature_ptr->spell_exp[i] = SPELL_EXP_MASTER; + else if (creature_ptr->pclass == CLASS_RED_MAGE) + creature_ptr->spell_exp[i] = SPELL_EXP_SKILLED; + else + creature_ptr->spell_exp[i] = SPELL_EXP_UNSKILLED; + } + + for (int i = 0; i < 5; i++) + for (int j = 0; j < 64; j++) + creature_ptr->weapon_exp[i][j] = s_info[creature_ptr->pclass].w_start[i][j]; + + if ((creature_ptr->pseikaku == PERSONALITY_SEXY) && (creature_ptr->weapon_exp[TV_HAFTED - TV_WEAPON_BEGIN][SV_WHIP] < WEAPON_EXP_BEGINNER)) { + creature_ptr->weapon_exp[TV_HAFTED - TV_WEAPON_BEGIN][SV_WHIP] = WEAPON_EXP_BEGINNER; + } + + for (int i = 0; i < GINOU_MAX; i++) + creature_ptr->skill_exp[i] = s_info[creature_ptr->pclass].s_start[i]; + + if (creature_ptr->pclass == CLASS_SORCERER) + creature_ptr->hitdie = rp_ptr->r_mhp / 2 + cp_ptr->c_mhp + ap_ptr->a_mhp; + else + creature_ptr->hitdie = rp_ptr->r_mhp + cp_ptr->c_mhp + ap_ptr->a_mhp; + + if (roll_hitdie) + roll_hitdice(creature_ptr, SPOP_NO_UPDATE); + + creature_ptr->mhp = creature_ptr->player_hp[0]; +} + +/*! + * @brief プレイヤーの限界ステータスを決める。 + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + * @details 新生の薬やステータスシャッフルでもこの関数が呼ばれる + */ +void get_max_stats(player_type* creature_ptr) +{ + int dice[6]; + while (TRUE) { + int j = 0; + for (int i = 0; i < A_MAX; i++) { + dice[i] = randint1(7); + j += dice[i]; + } + + if (j == 24) + break; + } + + for (int i = 0; i < A_MAX; i++) { + BASE_STATUS max_max = 18 + 60 + dice[i] * 10; + creature_ptr->stat_max_max[i] = max_max; + if (creature_ptr->stat_max[i] > max_max) + creature_ptr->stat_max[i] = max_max; + if (creature_ptr->stat_cur[i] > max_max) + creature_ptr->stat_cur[i] = max_max; + } + + creature_ptr->knowledge &= ~(KNOW_STAT); + creature_ptr->redraw |= (PR_STATS); +} diff --git a/src/birth/birth-stat.h b/src/birth/birth-stat.h new file mode 100644 index 000000000..12d46e225 --- /dev/null +++ b/src/birth/birth-stat.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" + +int adjust_stat(int value, int amount); +void get_stats(player_type* creature_ptr); +void get_extra(player_type* creature_ptr, bool roll_hitdie); + +void get_max_stats(player_type* creature_ptr); diff --git a/src/birth/birth-util.c b/src/birth/birth-util.c new file mode 100644 index 000000000..1cec82d72 --- /dev/null +++ b/src/birth/birth-util.c @@ -0,0 +1,62 @@ +#include "birth/birth-util.h" +#include "cmd-io/cmd-gameoption.h" +#include "core/show-file.h" +#include "main/sound-of-music.h" +#include "system/game-option-types.h" +#include "term/screen-processor.h" + +/*! + * @brief プレイヤー作成を中断して馬鹿馬鹿蛮怒を終了する + * @return なし + */ +void birth_quit(void) +{ + quit(NULL); +} + +/*! + * @brief 指定されたヘルプファイルを表示する / Show specific help file + * @param creature_ptr プレーヤーへの参照ポインタ + * @param helpfile ファイル名 + * @return なし + */ +void show_help(player_type* creature_ptr, concptr helpfile) +{ + screen_save(); + (void)show_file(creature_ptr, TRUE, helpfile, NULL, 0, 0); + screen_load(); +} + +void birth_help_option(player_type *creature_ptr, char c, birth_kind bk) +{ + concptr help_file; + switch (bk) { + case BK_RACE: + help_file = _("jraceclas.txt#TheRaces", "raceclas.txt#TheRaces"); + break; + case BK_CLASS: + help_file = _("jraceclas.txt#TheClasses", "raceclas.txt#TheClasses"); + break; + case BK_REALM: + help_file = _("jmagic.txt#MagicRealms", "magic.txt#MagicRealms"); + break; + case BK_PERSONALITY: + help_file = _("jraceclas.txt#ThePersonalities", "raceclas.txt#ThePersonalities"); + break; + case BK_AUTO_ROLLER: + help_file = _("jbirth.txt#AutoRoller", "birth.txt#AutoRoller"); + break; + default: + help_file = ""; + break; + } + + if (c == '?') { + show_help(creature_ptr, help_file); + } else if (c == '=') { + screen_save(); + do_cmd_options_aux(creature_ptr, OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth option((*)s effect score)")); + screen_load(); + } else if (c != '2' && c != '4' && c != '6' && c != '8') + bell(); +} diff --git a/src/birth/birth-util.h b/src/birth/birth-util.h new file mode 100644 index 000000000..fbcc6f6a9 --- /dev/null +++ b/src/birth/birth-util.h @@ -0,0 +1,16 @@ +#pragma once + +#include "system/angband.h" + +typedef enum birth_kind +{ + BK_REALM, + BK_RACE, + BK_CLASS, + BK_PERSONALITY, + BK_AUTO_ROLLER, +} birth_kind; + +void birth_quit(void); +void show_help(player_type* creature_ptr, concptr helpfile); +void birth_help_option(player_type *creature_ptr, char c, birth_kind bk); diff --git a/src/birth/birth-wizard.c b/src/birth/birth-wizard.c new file mode 100644 index 000000000..17ae7c844 --- /dev/null +++ b/src/birth/birth-wizard.c @@ -0,0 +1,547 @@ +#include "birth/birth-wizard.h" +#include "birth/auto-roller.h" +#include "birth/birth-body-spec.h" +#include "birth/birth-explanations-table.h" +#include "birth/birth-select-class.h" +#include "birth/birth-select-personality.h" +#include "birth/birth-select-race.h" +#include "birth/birth-select-realm.h" +#include "birth/birth-stat.h" +#include "birth/birth-util.h" +#include "birth/game-play-initializer.h" +#include "birth/history-editor.h" +#include "birth/history-generator.h" +#include "birth/quick-start.h" +#include "cmd-io/cmd-gameoption.h" +#include "cmd-io/cmd-help.h" +#include "core/asking-player.h" +#include "core/player-update-types.h" +#include "game-option/birth-options.h" +#include "io/input-key-acceptor.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "player-info/avatar.h" +#include "player/patron.h" +#include "player/player-class.h" +#include "player/player-race.h" +#include "player/player-sex.h" +#include "player/process-name.h" +#include "player/player-status-table.h" +#include "system/game-option-types.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/buffer-shaper.h" +#include "util/int-char-converter.h" +#include "view/display-birth.h" // 暫定。後で消す予定。 +#include "view/display-player.h" // 暫定。後で消す. +#include "world/world.h" + +/*! + * オートローラーの内容を描画する間隔 / + * How often the autoroller will update the display and pause + * to check for user interuptions. + * Bigger values will make the autoroller faster, but slower + * system may have problems because the user can't stop the + * autoroller for this number of rolls. + */ +#define AUTOROLLER_STEP 5431L + +static void display_initial_birth_message(player_type *creature_ptr) +{ + term_clear(); + put_str(_("名前 :", "Name :"), 1, 26); + put_str(_("性別 :", "Sex :"), 3, 1); + put_str(_("種族 :", "Race :"), 4, 1); + put_str(_("職業 :", "Class :"), 5, 1); + c_put_str(TERM_L_BLUE, creature_ptr->name, 1, 34); + put_str(_("キャラクターを作成します。('S'やり直す, 'Q'終了, '?'ヘルプ)", "Make your character. ('S' Restart, 'Q' Quit, '?' Help)"), 8, 10); + put_str(_("注意:《性別》の違いはゲーム上ほとんど影響を及ぼしません。", "Note: Your 'sex' does not have any significant gameplay effects."), 23, 5); +} + +/*! + * @prief 性別選択画面でヘルプを表示させる + * @param creature_ptr プレーヤーへの参照ポインタ + * @param c 入力したコマンド + * @return なし + * @details 他の関数名と被りそうだったので少し眺め + */ +static void display_help_on_sex_select(player_type *creature_ptr, char c) +{ + if (c == '?') + do_cmd_help(creature_ptr); + else if (c == '=') { + screen_save(); + do_cmd_options_aux(creature_ptr, OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Option((*)s effect score)")); + screen_load(); + } else if (c != '4' && c != '6') + bell(); +} + +/*! + * @brief プレイヤーの性別選択を行う / Player sex + * @param creature_ptr プレーヤーへの参照ポインタ + * @buf 表示用バッファ + * @return やり直すならFALSE、それ以外はTRUE + */ +static bool get_player_sex(player_type *creature_ptr, char *buf) +{ + const char p2 = ')'; + char cur[80]; + sprintf(cur, _("%c%c%s", "%c%c %s"), '*', p2, _("ランダム", "Random")); + int k = -1; + int cs = 0; + int os = MAX_SEXES; + while (TRUE) { + if (cs != os) { + put_str(cur, 12 + (os / 5), 2 + 15 * (os % 5)); + if (cs == MAX_SEXES) + sprintf(cur, _("%c%c%s", "%c%c %s"), '*', p2, _("ランダム", "Random")); + else { + sp_ptr = &sex_info[cs]; + concptr str = sp_ptr->title; + sprintf(cur, _("%c%c%s", "%c%c %s"), I2A(cs), p2, str); + } + + c_put_str(TERM_YELLOW, cur, 12 + (cs / 5), 2 + 15 * (cs % 5)); + os = cs; + } + + if (k >= 0) + break; + + sprintf(buf, _("性別を選んで下さい (%c-%c) ('='初期オプション設定): ", "Choose a sex (%c-%c) ('=' for options): "), I2A(0), I2A(1)); + put_str(buf, 10, 10); + char c = inkey(); + if (c == 'Q') + birth_quit(); + + if (c == 'S') + return FALSE; + + if (c == ' ' || c == '\r' || c == '\n') { + k = cs == MAX_SEXES ? randint0(MAX_SEXES) : cs; + break; + } + + if (c == '*') { + k = randint0(MAX_SEXES); + break; + } + + if (c == '4') { + if (cs > 0) + cs--; + } + + if (c == '6') { + if (cs < MAX_SEXES) + cs++; + } + + k = (islower(c) ? A2I(c) : -1); + if ((k >= 0) && (k < MAX_SEXES)) { + cs = k; + continue; + } else + k = -1; + + display_help_on_sex_select(creature_ptr, c); + } + + creature_ptr->psex = (byte)k; + sp_ptr = &sex_info[creature_ptr->psex]; + c_put_str(TERM_L_BLUE, sp_ptr->title, 3, 15); + return TRUE; +} + +static bool let_player_select_race(player_type *creature_ptr) +{ + clear_from(10); + creature_ptr->prace = 0; + while (TRUE) { + char temp[80 * 10]; + if (!get_player_race(creature_ptr)) + return FALSE; + + clear_from(10); + shape_buffer(race_explanations[creature_ptr->prace], 74, temp, sizeof(temp)); + concptr t = temp; + for (int i = 0; i < 10; i++) { + if (t[0] == 0) + break; + else { + prt(t, 12 + i, 3); + t += strlen(t) + 1; + } + } + if (get_check_strict(creature_ptr, _("よろしいですか?", "Are you sure? "), CHECK_DEFAULT_Y)) + break; + + clear_from(10); + c_put_str(TERM_WHITE, " ", 4, 15); + } + + return TRUE; +} + +static bool let_player_select_class(player_type *creature_ptr) +{ + clear_from(10); + creature_ptr->pclass = 0; + while (TRUE) { + char temp[80 * 9]; + if (!get_player_class(creature_ptr)) + return FALSE; + + clear_from(10); + shape_buffer(class_explanations[creature_ptr->pclass], 74, temp, sizeof(temp)); + concptr t = temp; + for (int i = 0; i < 9; i++) { + if (t[0] == 0) + break; + else { + prt(t, 12 + i, 3); + t += strlen(t) + 1; + } + } + + if (get_check_strict(creature_ptr, _("よろしいですか?", "Are you sure? "), CHECK_DEFAULT_Y)) + break; + + c_put_str(TERM_WHITE, " ", 5, 15); + } + + return TRUE; +} + +static bool let_player_select_personality(player_type *creature_ptr) +{ + creature_ptr->pseikaku = 0; + while (TRUE) { + char temp[80 * 8]; + if (!get_player_personality(creature_ptr)) + return FALSE; + + clear_from(10); + shape_buffer(personality_explanations[creature_ptr->pseikaku], 74, temp, sizeof(temp)); + concptr t = temp; + for (int i = 0; i < A_MAX; i++) { + if (t[0] == 0) + break; + else { + prt(t, 12 + i, 3); + t += strlen(t) + 1; + } + } + + if (get_check_strict(creature_ptr, _("よろしいですか?", "Are you sure? "), CHECK_DEFAULT_Y)) + break; + + c_put_str(TERM_L_BLUE, creature_ptr->name, 1, 34); + prt("", 1, 34 + strlen(creature_ptr->name)); + } + + return TRUE; +} + +static bool let_player_build_character(player_type *creature_ptr) +{ + char buf[80]; + if (!get_player_sex(creature_ptr, buf)) + return FALSE; + + if (!let_player_select_race(creature_ptr)) + return FALSE; + + if (!let_player_select_class(creature_ptr)) + return FALSE; + + if (!get_player_realms(creature_ptr)) + return FALSE; + + if (!let_player_select_personality(creature_ptr)) + return FALSE; + + return TRUE; +} + +static void display_initial_options(player_type *creature_ptr) +{ + clear_from(10); + put_str(" ", 3, 40); + put_str(" ", 4, 40); + put_str(" ", 5, 40); + screen_save(); + do_cmd_options_aux(creature_ptr, OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Option((*)s effect score)")); + screen_load(); +} + +static void display_auto_roller_success_rate(const int col) +{ + if (!autoroller) + return; + + put_str(_("最小値", " Limit"), 2, col + 5); + put_str(_("成功率", " Freq"), 2, col + 13); + put_str(_("現在値", " Roll"), 2, col + 24); + for (int i = 0; i < A_MAX; i++) { + put_str(stat_names[i], 3 + i, col); + int j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i]; + int m = adjust_stat(stat_limit[i], j); + char buf[32]; + cnv_stat(m, buf); + c_put_str(TERM_L_BLUE, buf, 3 + i, col + 5); + } +} + +static void auto_roller_count(void) +{ + if (auto_round < 1000000000L) + return; + + auto_round = 1; + if (!autoroller) + return; + + for (int i = 0; i < A_MAX; i++) { + stat_match[i] = 0; + } +} + +static bool decide_initial_stat(player_type *creature_ptr) +{ + if (!autoroller) + return TRUE; + + bool accept = TRUE; + for (int i = 0; i < A_MAX; i++) { + if (creature_ptr->stat_max[i] >= stat_limit[i]) + stat_match[i]++; + else + accept = FALSE; + } + + return accept; +} + +static bool decide_body_spec(player_type *creature_ptr, chara_limit_type chara_limit, bool *accept) +{ + if (!*accept) + return FALSE; + + get_ahw(creature_ptr); + get_history(creature_ptr); + + if (autochara) { + if ((creature_ptr->age < chara_limit.agemin) || (creature_ptr->age > chara_limit.agemax)) + *accept = FALSE; + if ((creature_ptr->ht < chara_limit.htmin) || (creature_ptr->ht > chara_limit.htmax)) + *accept = FALSE; + if ((creature_ptr->wt < chara_limit.wtmin) || (creature_ptr->wt > chara_limit.wtmax)) + *accept = FALSE; + if ((creature_ptr->sc < chara_limit.scmin) || (creature_ptr->sc > chara_limit.scmax)) + *accept = FALSE; + } + + return *accept; +} + +static bool display_auto_roller_count(player_type *creature_ptr, const int col) +{ + if ((auto_round % AUTOROLLER_STEP) != 0) + return FALSE; + + birth_put_stats(creature_ptr); + put_str(format("%10ld", auto_round), 10, col + 20); + term_fresh(); + inkey_scan = TRUE; + if (inkey()) { + get_ahw(creature_ptr); + get_history(creature_ptr); + return TRUE; + } + + return FALSE; +} + +static void exe_auto_roller(player_type *creature_ptr, chara_limit_type chara_limit, const int col) +{ + while (autoroller || autochara) { + get_stats(creature_ptr); + auto_round++; + auto_roller_count(); + bool accept = decide_initial_stat(creature_ptr); + if (decide_body_spec(creature_ptr, chara_limit, &accept)) + return; + + if (display_auto_roller_count(creature_ptr, col)) + return; + } +} + +static bool display_auto_roller_result(player_type *creature_ptr, bool prev, char *c) +{ + BIT_FLAGS mode = 0; + while (TRUE) { + creature_ptr->update |= (PU_BONUS | PU_HP); + update_creature(creature_ptr); + creature_ptr->chp = creature_ptr->mhp; + creature_ptr->csp = creature_ptr->msp; + display_player(creature_ptr, mode); + term_gotoxy(2, 23); + const char b1 = '['; + term_addch(TERM_WHITE, b1); + term_addstr(-1, TERM_WHITE, _("'r' 次の数値", "'r'eroll")); + if (prev) + term_addstr(-1, TERM_WHITE, _(", 'p' 前の数値", "'p'previous")); + + if (mode) + term_addstr(-1, TERM_WHITE, _(", 'h' その他の情報", ", 'h' Misc.")); + else + term_addstr(-1, TERM_WHITE, _(", 'h' 生い立ちを表示", ", 'h'istory")); + + term_addstr(-1, TERM_WHITE, _(", Enter この数値に決定", ", or Enter to accept")); + const char b2 = ']'; + term_addch(TERM_WHITE, b2); + *c = inkey(); + if (*c == 'Q') + birth_quit(); + + if (*c == 'S') + return FALSE; + + if (*c == '\r' || *c == '\n' || *c == ESCAPE) + break; + + if ((*c == ' ') || (*c == 'r')) + break; + + if (prev && (*c == 'p')) { + load_prev_data(creature_ptr, TRUE); + continue; + } + + if ((*c == 'H') || (*c == 'h')) { + mode = ((mode != 0) ? 0 : 1); + continue; + } + + birth_help_option(creature_ptr, *c, BK_AUTO_ROLLER); + bell(); + } + + return TRUE; +} + +static bool display_auto_roller(player_type *creature_ptr, chara_limit_type chara_limit) +{ + while (TRUE) { + int col = 42; + if (autoroller || autochara) { + term_clear(); + put_str(_("回数 :", "Round:"), 10, col + 13); + put_str(_("(ESCで停止)", "(Hit ESC to stop)"), 12, col + 13); + } else { + get_stats(creature_ptr); + get_ahw(creature_ptr); + get_history(creature_ptr); + } + + display_auto_roller_success_rate(col); + exe_auto_roller(creature_ptr, chara_limit, col); + if (autoroller || autochara) + sound(SOUND_LEVEL); + + flush(); + + get_extra(creature_ptr, TRUE); + get_money(creature_ptr); + creature_ptr->chaos_patron = (s16b)randint0(MAX_PATRON); + bool prev = FALSE; + char c; + if (!display_auto_roller_result(creature_ptr, prev, &c)) + return FALSE; + + if (c == '\r' || c == '\n' || c == ESCAPE) + break; + + save_prev_data(creature_ptr, &previous_char); + previous_char.quick_ok = FALSE; + prev = TRUE; + } + + return TRUE; +} + +/*! + * @brief 名前と生い立ちを設定する + * @param creature_ptr プレーヤーへの参照ポインタ + * @param process_autopick_file_command 自動拾いコマンドへの関数ポインタ + * @return なし + * @details ついでにステータス限界もここで決めている + */ +static void set_name_history(player_type *creature_ptr, void (*process_autopick_file_command)(char *)) +{ + clear_from(23); + get_name(creature_ptr); + process_player_name(creature_ptr, current_world_ptr->creating_savefile); + edit_history(creature_ptr, process_autopick_file_command); + get_max_stats(creature_ptr); + get_virtues(creature_ptr); + prt(_("[ 'Q' 中断, 'S' 初めから, Enter ゲーム開始 ]", "['Q'uit, 'S'tart over, or Enter to continue]"), 23, _(14, 10)); +} + +/*! + * @brief プレーヤーキャラ作成ウィザード + * @details + * The delay may be reduced, but is recommended to keep players + * from continuously rolling up characters, which can be VERY + * expensive CPU wise. And it cuts down on player stupidity. + * @return なし + */ +bool player_birth_wizard(player_type *creature_ptr, void (*process_autopick_file_command)(char *)) +{ + display_initial_birth_message(creature_ptr); + const char p2 = ')'; + char buf[80]; + for (int n = 0; n < MAX_SEXES; n++) { + sp_ptr = &sex_info[n]; + sprintf(buf, _("%c%c%s", "%c%c %s"), I2A(n), p2, sp_ptr->title); + put_str(buf, 12 + (n / 5), 2 + 15 * (n % 5)); + } + + if (!let_player_build_character(creature_ptr)) + return FALSE; + + display_initial_options(creature_ptr); + if (autoroller || autochara) + auto_round = 0L; + + if (autoroller) + if (!get_stat_limits(creature_ptr)) + return FALSE; + + chara_limit_type chara_limit; + initialize_chara_limit(&chara_limit); + if (autochara) + if (!get_chara_limits(creature_ptr, &chara_limit)) + return FALSE; + + clear_from(10); + init_turn(creature_ptr); + if (!display_auto_roller(creature_ptr, chara_limit)) + return FALSE; + + set_name_history(creature_ptr, process_autopick_file_command); + char c = inkey(); + if (c == 'Q') + birth_quit(); + + if (c == 'S') + return FALSE; + + init_dungeon_quests(creature_ptr); + save_prev_data(creature_ptr, &previous_char); + previous_char.quick_ok = TRUE; + return TRUE; +} diff --git a/src/birth/birth-wizard.h b/src/birth/birth-wizard.h new file mode 100644 index 000000000..a77d0b384 --- /dev/null +++ b/src/birth/birth-wizard.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool player_birth_wizard(player_type *creature_ptr, void (*process_autopick_file_command)(char *)); diff --git a/src/birth/character-builder.c b/src/birth/character-builder.c new file mode 100644 index 000000000..6da56aab8 --- /dev/null +++ b/src/birth/character-builder.c @@ -0,0 +1,108 @@ +/*! + * @file birth.c + * @brief プレイヤーの作成を行う / Create a player character + * @date 2013/12/28 + * @author + * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n + *\n + * This software may be copied and distributed for educational, research,\n + * and not for profit purposes provided that this copyright and statement\n + * are included in all such copies. Other copyrights may also apply.\n + * 2013 Deskull Doxygen向けのコメント整理\n + */ + +#include "birth/character-builder.h" +#include "birth/birth-explanations-table.h" +#include "birth/birth-wizard.h" +#include "birth/game-play-initializer.h" +#include "birth/quick-start.h" +#include "core/window-redrawer.h" +#include "floor/floor-town.h" +#include "floor/wild.h" +#include "game-option/option-flags.h" +#include "io/write-diary.h" +#include "main/music-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-floor/monster-remover.h" +#include "player/player-class.h" +#include "player/player-race-types.h" +#include "player/player-sex.h" +#include "player/race-info-table.h" +#include "store/store.h" +#include "view/display-messages.h" +#include "world/world.h" + +/*! + * @brief プレーヤーキャラの作成結果を日記に書く + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +static void write_birth_diary(player_type *creature_ptr) +{ + message_add(" "); + message_add(" "); + message_add("===================="); + message_add(" "); + message_add(" "); + + exe_write_diary(creature_ptr, DIARY_GAMESTART, 1, _("-------- 新規ゲーム開始 --------", "------- Started New Game -------")); + exe_write_diary(creature_ptr, DIARY_DIALY, 0, NULL); + char buf[80]; + sprintf(buf, _(" 性別に%sを選択した。", " chose %s gender."), sex_info[creature_ptr->psex].title); + exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 1, buf); + sprintf(buf, _(" 種族に%sを選択した。", " chose %s race."), race_info[creature_ptr->prace].title); + exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 1, buf); + sprintf(buf, _(" 職業に%sを選択した。", " chose %s class."), class_info[creature_ptr->pclass].title); + exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 1, buf); + if (creature_ptr->realm1) { + sprintf(buf, _(" 魔法の領域に%s%sを選択した。", " chose %s%s."), + realm_names[creature_ptr->realm1], creature_ptr->realm2 ? format(_("と%s", " and %s realms"), realm_names[creature_ptr->realm2]) : _("", " realm")); + exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 1, buf); + } + + sprintf(buf, _(" 性格に%sを選択した。", " chose %s personality."), + personality_info[creature_ptr->pseikaku].title); + exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 1, buf); +} + +/*! + * @brief プレイヤー作成処理のメインルーチン/ Create a new character. + * @details + * Note that we may be called with "junk" leftover in the various + * fields, so we must be sure to clear them first. + * @return なし + */ +void player_birth(player_type *creature_ptr, void (*process_autopick_file_command)(char *)) +{ + current_world_ptr->play_time = 0; + wipe_monsters_list(creature_ptr); + player_wipe_without_name(creature_ptr); + if (!ask_quick_start(creature_ptr)) { + play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_DEFAULT); + while (TRUE) { + if (player_birth_wizard(creature_ptr, process_autopick_file_command)) + break; + + player_wipe_without_name(creature_ptr); + } + } + + write_birth_diary(creature_ptr); + for (int i = 1; i < max_towns; i++) { + for (int j = 0; j < MAX_STORES; j++) { + store_init(i, j); + } + } + + seed_wilderness(); + if (creature_ptr->prace == RACE_BEASTMAN) + creature_ptr->hack_mutation = TRUE; + else + creature_ptr->hack_mutation = FALSE; + + if (!window_flag[1]) + window_flag[1] |= PW_MESSAGE; + + if (!window_flag[2]) + window_flag[2] |= PW_INVEN; +} diff --git a/src/birth/character-builder.h b/src/birth/character-builder.h new file mode 100644 index 000000000..9a8c18f6c --- /dev/null +++ b/src/birth/character-builder.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void player_birth(player_type *creature_ptr, void(*process_autopick_file_command)(char*)); diff --git a/src/birth/game-play-initializer.c b/src/birth/game-play-initializer.c new file mode 100644 index 000000000..c3a966a5b --- /dev/null +++ b/src/birth/game-play-initializer.c @@ -0,0 +1,229 @@ +#include "birth/game-play-initializer.h" +#include "info-reader/fixed-map-parser.h" +#include "dungeon/dungeon.h" +#include "dungeon/quest.h" +#include "floor/floor-util.h" +#include "game-option/birth-options.h" +#include "game-option/cheat-options.h" +#include "inventory/inventory-slot-types.h" +#include "market/arena.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags7.h" +#include "object/object-generator.h" +#include "object/object-kind.h" +#include "pet/pet-util.h" +#include "player/player-race-types.h" +#include "system/artifact-type-definition.h" +#include "system/floor-type-definition.h" +#include "system/system-variables.h" +#include "world/world.h" + +/*! + * @brief ベースアイテム構造体の鑑定済みフラグをリセットする。 + * @return なし + */ +static void k_info_reset(void) +{ + for (int i = 1; i < max_k_idx; i++) { + object_kind *k_ptr = &k_info[i]; + k_ptr->tried = FALSE; + k_ptr->aware = FALSE; + } +} + +/*! + * @brief プレイヤー構造体の内容を初期値で消去する(名前を除く) / Clear all the global "character" data (without name) + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + * @details 少し長いが、これ1つで処理が完結しているので分割は見送る + */ +void player_wipe_without_name(player_type *creature_ptr) +{ + player_type tmp; + + COPY(&tmp, creature_ptr, player_type); + if (creature_ptr->last_message) + string_free(creature_ptr->last_message); + + if (creature_ptr->inventory_list != NULL) + C_WIPE(creature_ptr->inventory_list, INVEN_TOTAL, object_type); + + (void)WIPE(creature_ptr, player_type); + + //TODO: キャラ作成からゲーム開始までに current_floor_ptr を参照しなければならない処理は今後整理して外す。 + creature_ptr->current_floor_ptr = &floor_info; + C_MAKE(creature_ptr->inventory_list, INVEN_TOTAL, object_type); + for (int i = 0; i < 4; i++) + strcpy(creature_ptr->history[i], ""); + + for (int i = 0; i < max_q_idx; i++) { + quest_type *const q_ptr = &quest[i]; + q_ptr->status = QUEST_STATUS_UNTAKEN; + q_ptr->cur_num = 0; + q_ptr->max_num = 0; + q_ptr->type = 0; + q_ptr->level = 0; + q_ptr->r_idx = 0; + q_ptr->complev = 0; + q_ptr->comptime = 0; + } + + creature_ptr->total_weight = 0; + creature_ptr->inven_cnt = 0; + creature_ptr->equip_cnt = 0; + for (int i = 0; i < INVEN_TOTAL; i++) + object_wipe(&creature_ptr->inventory_list[i]); + + for (int i = 0; i < max_a_idx; i++) { + artifact_type *a_ptr = &a_info[i]; + a_ptr->cur_num = 0; + } + + k_info_reset(); + for (int i = 1; i < max_r_idx; i++) { + monster_race *r_ptr = &r_info[i]; + r_ptr->cur_num = 0; + r_ptr->max_num = 100; + if (r_ptr->flags1 & RF1_UNIQUE) + r_ptr->max_num = 1; + else if (r_ptr->flags7 & RF7_NAZGUL) + r_ptr->max_num = MAX_NAZGUL_NUM; + + r_ptr->r_pkills = 0; + r_ptr->r_akills = 0; + } + + creature_ptr->food = PY_FOOD_FULL - 1; + if (creature_ptr->pclass == CLASS_SORCERER) { + creature_ptr->spell_learned1 = creature_ptr->spell_learned2 = 0xffffffffL; + creature_ptr->spell_worked1 = creature_ptr->spell_worked2 = 0xffffffffL; + } else { + creature_ptr->spell_learned1 = creature_ptr->spell_learned2 = 0L; + creature_ptr->spell_worked1 = creature_ptr->spell_worked2 = 0L; + } + + creature_ptr->spell_forgotten1 = creature_ptr->spell_forgotten2 = 0L; + for (int i = 0; i < 64; i++) + creature_ptr->spell_order[i] = 99; + + creature_ptr->learned_spells = 0; + creature_ptr->add_spells = 0; + creature_ptr->knowledge = 0; + creature_ptr->mutant_regenerate_mod = 100; + + cheat_peek = FALSE; + cheat_hear = FALSE; + cheat_room = FALSE; + cheat_xtra = FALSE; + cheat_know = FALSE; + cheat_live = FALSE; + cheat_save = FALSE; + cheat_diary_output = FALSE; + cheat_turn = FALSE; + + current_world_ptr->total_winner = FALSE; + creature_ptr->timewalk = FALSE; + creature_ptr->panic_save = 0; + + current_world_ptr->noscore = 0; + current_world_ptr->wizard = FALSE; + creature_ptr->wait_report_score = FALSE; + creature_ptr->pet_follow_distance = PET_FOLLOW_DIST; + creature_ptr->pet_extra_flags = (PF_TELEPORT | PF_ATTACK_SPELL | PF_SUMMON_SPELL); + + for (int i = 0; i < current_world_ptr->max_d_idx; i++) + max_dlv[i] = 0; + + creature_ptr->visit = 1; + creature_ptr->wild_mode = FALSE; + + for (int i = 0; i < MAX_SPELLS; i++) { + creature_ptr->magic_num1[i] = 0; + creature_ptr->magic_num2[i] = 0; + } + + creature_ptr->max_plv = creature_ptr->lev = 1; + creature_ptr->arena_number = 0; + creature_ptr->current_floor_ptr->inside_arena = FALSE; + creature_ptr->current_floor_ptr->inside_quest = 0; + for (int i = 0; i < MAX_MANE; i++) { + creature_ptr->mane_spell[i] = -1; + creature_ptr->mane_dam[i] = 0; + } + + creature_ptr->mane_num = 0; + creature_ptr->exit_bldg = TRUE; + creature_ptr->today_mon = 0; + update_gambling_monsters(creature_ptr); + creature_ptr->muta1 = 0; + creature_ptr->muta2 = 0; + creature_ptr->muta3 = 0; + + for (int i = 0; i < 8; i++) + creature_ptr->virtues[i] = 0; + + creature_ptr->dungeon_idx = 0; + if (vanilla_town || ironman_downward) { + creature_ptr->recall_dungeon = DUNGEON_ANGBAND; + } else { + creature_ptr->recall_dungeon = DUNGEON_GALGALS; + } + + memcpy(creature_ptr->name, tmp.name, sizeof(tmp.name)); +} + +/*! + * @brief ダンジョン内部のクエストを初期化する / Initialize random quests and final quests + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void init_dungeon_quests(player_type *creature_ptr) +{ + int number_of_quests = MAX_RANDOM_QUEST - MIN_RANDOM_QUEST + 1; + init_flags = INIT_ASSIGN; + floor_type *floor_ptr = creature_ptr->current_floor_ptr; + floor_ptr->inside_quest = MIN_RANDOM_QUEST; + parse_fixed_map(creature_ptr, "q_info.txt", 0, 0, 0, 0); + floor_ptr->inside_quest = 0; + for (int i = MIN_RANDOM_QUEST + number_of_quests - 1; i >= MIN_RANDOM_QUEST; i--) { + quest_type *q_ptr = &quest[i]; + monster_race *quest_r_ptr; + q_ptr->status = QUEST_STATUS_TAKEN; + determine_random_questor(creature_ptr, q_ptr); + quest_r_ptr = &r_info[q_ptr->r_idx]; + quest_r_ptr->flags1 |= RF1_QUESTOR; + q_ptr->max_num = 1; + } + + init_flags = INIT_ASSIGN; + floor_ptr->inside_quest = QUEST_OBERON; + parse_fixed_map(creature_ptr, "q_info.txt", 0, 0, 0, 0); + quest[QUEST_OBERON].status = QUEST_STATUS_TAKEN; + + floor_ptr->inside_quest = QUEST_SERPENT; + parse_fixed_map(creature_ptr, "q_info.txt", 0, 0, 0, 0); + quest[QUEST_SERPENT].status = QUEST_STATUS_TAKEN; + floor_ptr->inside_quest = 0; +} + +/*! + * @brief ゲームターンを初期化する / Reset turn + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + * @details アンデッド系種族は開始時刻を夜からにする / Undead start just sunset + * @details + */ +void init_turn(player_type *creature_ptr) +{ + if ((creature_ptr->prace == RACE_VAMPIRE) || (creature_ptr->prace == RACE_SKELETON) || (creature_ptr->prace == RACE_ZOMBIE) || (creature_ptr->prace == RACE_SPECTRE)) { + current_world_ptr->game_turn = (TURNS_PER_TICK * 3 * TOWN_DAWN) / 4 + 1; + current_world_ptr->game_turn_limit = TURNS_PER_TICK * TOWN_DAWN * MAX_DAYS + TURNS_PER_TICK * TOWN_DAWN * 3 / 4; + } else { + current_world_ptr->game_turn = 1; + current_world_ptr->game_turn_limit = TURNS_PER_TICK * TOWN_DAWN * (MAX_DAYS - 1) + TURNS_PER_TICK * TOWN_DAWN * 3 / 4; + } + + current_world_ptr->dungeon_turn = 1; + current_world_ptr->dungeon_turn_limit = TURNS_PER_TICK * TOWN_DAWN * (MAX_DAYS - 1) + TURNS_PER_TICK * TOWN_DAWN * 3 / 4; +} diff --git a/src/birth/game-play-initializer.h b/src/birth/game-play-initializer.h new file mode 100644 index 000000000..3e1d11fee --- /dev/null +++ b/src/birth/game-play-initializer.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +void player_wipe_without_name(player_type *creature_ptr); +void init_dungeon_quests(player_type *creature_ptr); +void init_turn(player_type *creature_ptr); diff --git a/src/birth/history-editor.c b/src/birth/history-editor.c new file mode 100644 index 000000000..875795746 --- /dev/null +++ b/src/birth/history-editor.c @@ -0,0 +1,178 @@ +#include "birth/history-editor.h" +#include "io/input-key-acceptor.h" +#include "io/read-pref-file.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/int-char-converter.h" +#include "view/display-player.h" // 暫定。後で消す. +#ifdef JP +#include "locale/japanese.h" +#endif + +/*! + * @brief 生い立ちメッセージを編集する。/Character background edit-mode + * @param creature_ptr プレーヤーへの参照ポインタ + * @param process_autopick_file_command 自動拾いファイルコマンドへの関数ポインタ + * @return なし + */ +void edit_history(player_type *creature_ptr, void (*process_autopick_file_command)(char *)) +{ + char old_history[4][60]; + for (int i = 0; i < 4; i++) { + sprintf(old_history[i], "%s", creature_ptr->history[i]); + } + + for (int i = 0; i < 4; i++) { + /* loop */ + int j; + for (j = 0; creature_ptr->history[i][j]; j++) + ; + + for (; j < 59; j++) + creature_ptr->history[i][j] = ' '; + creature_ptr->history[i][59] = '\0'; + } + + display_player(creature_ptr, 1); + c_put_str(TERM_L_GREEN, _("(キャラクターの生い立ち - 編集モード)", "(Character Background - Edit Mode)"), 11, 20); + put_str(_("[ カーソルキーで移動、Enterで終了、Ctrl-Aでファイル読み込み ]", "[ Cursor key for Move, Enter for End, Ctrl-A for Read pref ]"), 17, 10); + TERM_LEN y = 0; + TERM_LEN x = 0; + while (TRUE) { + char c; + + for (int i = 0; i < 4; i++) { + put_str(creature_ptr->history[i], i + 12, 10); + } +#ifdef JP + if (iskanji2(creature_ptr->history[y], x)) + c_put_str(TERM_L_BLUE, format("%c%c", creature_ptr->history[y][x], creature_ptr->history[y][x + 1]), y + 12, x + 10); + else +#endif + c_put_str(TERM_L_BLUE, format("%c", creature_ptr->history[y][x]), y + 12, x + 10); + + term_gotoxy(x + 10, y + 12); + int skey = inkey_special(TRUE); + if (!(skey & SKEY_MASK)) + c = (char)skey; + else + c = 0; + + if (skey == SKEY_UP || c == KTRL('p')) { + y--; + if (y < 0) + y = 3; +#ifdef JP + if ((x > 0) && (iskanji2(creature_ptr->history[y], x - 1))) + x--; +#endif + } else if (skey == SKEY_DOWN || c == KTRL('n')) { + y++; + if (y > 3) + y = 0; +#ifdef JP + if ((x > 0) && (iskanji2(creature_ptr->history[y], x - 1))) + x--; +#endif + } else if (skey == SKEY_RIGHT || c == KTRL('f')) { +#ifdef JP + if (iskanji2(creature_ptr->history[y], x)) + x++; +#endif + x++; + if (x > 58) { + x = 0; + if (y < 3) + y++; + } + } else if (skey == SKEY_LEFT || c == KTRL('b')) { + x--; + if (x < 0) { + if (y) { + y--; + x = 58; + } else + x = 0; + } + +#ifdef JP + if ((x > 0) && (iskanji2(creature_ptr->history[y], x - 1))) + x--; +#endif + } else if (c == '\r' || c == '\n') { + term_erase(0, 11, 255); + term_erase(0, 17, 255); + put_str(_("(キャラクターの生い立ち - 編集済み)", "(Character Background - Edited)"), 11, 20); + break; + } else if (c == ESCAPE) { + clear_from(11); + put_str(_("(キャラクターの生い立ち)", "(Character Background)"), 11, 25); + for (int i = 0; i < 4; i++) { + sprintf(creature_ptr->history[i], "%s", old_history[i]); + put_str(creature_ptr->history[i], i + 12, 10); + } + + break; + } else if (c == KTRL('A')) { + if (read_histpref(creature_ptr, process_autopick_file_command)) { +#ifdef JP + if ((x > 0) && (iskanji2(creature_ptr->history[y], x - 1))) + x--; +#endif + } + } else if (c == '\010') { + x--; + if (x < 0) { + if (y) { + y--; + x = 58; + } else + x = 0; + } + + creature_ptr->history[y][x] = ' '; +#ifdef JP + if ((x > 0) && (iskanji2(creature_ptr->history[y], x - 1))) { + x--; + creature_ptr->history[y][x] = ' '; + } +#endif + } +#ifdef JP + else if (iskanji(c) || isprint(c)) +#else + else if (isprint(c)) /* BUGFIX */ +#endif + { +#ifdef JP + if (iskanji2(creature_ptr->history[y], x)) { + creature_ptr->history[y][x + 1] = ' '; + } + + if (iskanji(c)) { + if (x > 57) { + x = 0; + y++; + if (y > 3) + y = 0; + } + + if (iskanji2(creature_ptr->history[y], x + 1)) { + creature_ptr->history[y][x + 2] = ' '; + } + + creature_ptr->history[y][x++] = c; + + c = inkey(); + } +#endif + creature_ptr->history[y][x++] = c; + if (x > 58) { + x = 0; + y++; + if (y > 3) + y = 0; + } + } + } +} diff --git a/src/birth/history-editor.h b/src/birth/history-editor.h new file mode 100644 index 000000000..e2e943ae4 --- /dev/null +++ b/src/birth/history-editor.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void edit_history(player_type *creature_ptr, void (*process_autopick_file_command)(char *)); diff --git a/src/birth/history-generator.c b/src/birth/history-generator.c new file mode 100644 index 000000000..d11edc83f --- /dev/null +++ b/src/birth/history-generator.c @@ -0,0 +1,154 @@ +#include "birth/history-generator.h" +#include "birth/history.h" +#include "player/player-race-types.h" +#include "util/buffer-shaper.h" + +static int get_history_chart(player_type *creature_ptr) +{ + switch (creature_ptr->prace) { + case RACE_AMBERITE: + return 67; + case RACE_HUMAN: + case RACE_BARBARIAN: + case RACE_DUNADAN: + return 1; + case RACE_HALF_ELF: + return 4; + case RACE_ELF: + case RACE_HIGH_ELF: + return 7; + case RACE_HOBBIT: + return 10; + case RACE_GNOME: + return 13; + case RACE_DWARF: + return 16; + case RACE_HALF_ORC: + return 19; + case RACE_HALF_TROLL: + return 22; + case RACE_DARK_ELF: + return 69; + case RACE_HALF_OGRE: + return 74; + case RACE_HALF_GIANT: + return 75; + case RACE_HALF_TITAN: + return 76; + case RACE_CYCLOPS: + return 77; + case RACE_YEEK: + return 78; + case RACE_KOBOLD: + return 82; + case RACE_KLACKON: + return 84; + case RACE_NIBELUNG: + return 87; + case RACE_DRACONIAN: + return 89; + case RACE_MIND_FLAYER: + return 92; + case RACE_IMP: + return 94; + case RACE_GOLEM: + return 98; + case RACE_SKELETON: + return 102; + case RACE_ZOMBIE: + return 107; + case RACE_VAMPIRE: + return 113; + case RACE_SPECTRE: + return 118; + case RACE_SPRITE: + return 124; + case RACE_BEASTMAN: + return 129; + case RACE_ENT: + return 137; + case RACE_ARCHON: + return 142; + case RACE_BALROG: + return 145; + case RACE_S_FAIRY: + return 148; + case RACE_KUTAR: + return 154; + case RACE_ANDROID: + return 155; + case RACE_MERFOLK: + return 170; + default: + return 0; + } +} + +/*! + * @brief 生い立ちを画面に表示しつつ、種族から社会的地位を決定する + * @param creature_ptr プレーヤーへの参照ポインタ + * @param buf 生い立ち情報のバッファ + * @return なし + * @details 画面表示と社会的地位の決定が密結合していて分離できない + */ +static void decide_social_class(player_type *creature_ptr, char *buf) +{ + int social_class = randint1(4); + int chart = get_history_chart(creature_ptr); + while (chart != 0) { + int i = 0; + int roll = randint1(100); + while ((chart != bg[i].chart) || (roll > bg[i].roll)) { + i++; + } + + (void)strcat(buf, bg[i].info); + social_class += (int)(bg[i].bonus) - 50; + chart = bg[i].next; + } + + if (social_class > 100) + social_class = 100; + else if (social_class < 1) + social_class = 1; + + creature_ptr->sc = (s16b)social_class; +} + +/*! + * @brief プレイヤーの生い立ちの自動生成を行う。 / Get the racial history, and social class, using the "history charts". + * @return なし + */ +void get_history(player_type *creature_ptr) +{ + for (int i = 0; i < 4; i++) + creature_ptr->history[i][0] = '\0'; + + char buf[240]; + buf[0] = '\0'; + decide_social_class(creature_ptr, buf); + + /* loop */ + char *s; + for (s = buf; *s == ' '; s++) + ; + + int n = strlen(s); + while ((n > 0) && (s[n - 1] == ' ')) + s[--n] = '\0'; + + { + char temp[64 * 4]; + shape_buffer(s, 60, temp, sizeof(temp)); + char *t; + t = temp; + for (int i = 0; i < 4; i++) { + if (t[0] == 0) + break; + else { + strcpy(creature_ptr->history[i], t); + t += strlen(t) + 1; + } + } + } +} diff --git a/src/birth/history-generator.h b/src/birth/history-generator.h new file mode 100644 index 000000000..b81306517 --- /dev/null +++ b/src/birth/history-generator.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void get_history(player_type* creature_ptr); diff --git a/src/birth/history.c b/src/birth/history.c new file mode 100644 index 000000000..a7ed9ccd9 --- /dev/null +++ b/src/birth/history.c @@ -0,0 +1,1646 @@ +/*! + * @brief 生い立ちメッセージテーブル / Forward declare + * @date 2002/01/12 + * @author mogami + */ + +#include "birth/history.h" + +/*! +* 生い立ちテーブルの定義 / Background information (see below)\n +*\n +* Chart progression by race:\n +* Human --> 1 --> 2 --> 3 --> 50 --> 51 --> 52 --> 53\n +* Half-Elf --> 4 --> 1 --> 2 --> 3 --> 50 --> 51 --> 52 --> 53\n +* Elf/High-Elf --> 7 --> 8 --> 9 --> 54 --> 55 --> 56\n +* Hobbit --> 10 --> 11 --> 3 --> 50 --> 51 --> 52 --> 53\n +* Gnome --> 13 --> 14 --> 3 --> 50 --> 51 --> 52 --> 53\n +* Dwarf --> 16 --> 17 --> 18 --> 57 --> 58 --> 59 --> 60 --> 61\n +* Half-Orc --> 19 --> 20 --> 2 --> 3 --> 50 --> 51 --> 52 --> 53\n +* Half-Troll --> 22 --> 23 --> 62 --> 63 --> 64 --> 65 --> 66\n +*\n +* This table *must* be correct or drastic errors may occur!\n +*/ +hist_type bg[MAX_BACKGROUNDS] = { +#ifdef JP +{ "妾腹の子で認知すらされていません。", 10, 2, 3, 25 }, +{ "妾腹の子ですが認知はされています。", 20, 2, 3, 35 }, +{ "幾人かの子供のうちの一人です。", 95, 2, 3, 45 }, +{ "長子です。", 100, 2, 3, 50 }, +#else +{ "You are the illegitimate and unacknowledged child ", 10, 1, 2, 25 }, +{ "You are the illegitimate but acknowledged child ", 20, 1, 2, 35 }, +{ "You are one of several children ", 95, 1, 2, 45 }, +{ "You are the first child ", 100, 1, 2, 50 }, +#endif + + +#ifdef JP +{ "あなたは農奴の", 40, 1, 2, 65 }, +{ "あなたは自作農の", 65, 1, 2, 80 }, +{ "あなたは町人の", 80, 1, 2, 90 }, +{ "あなたは職人の", 90, 1, 2,105 }, +{ "あなたは土着の騎士の", 96, 1, 2,120 }, +{ "あなたは混沌の宮廷の爵位ある貴族の", 99, 1, 2,130 }, +{ "あなたはアンバーの王家の血を引く者の", 100, 1, 2,140 }, +#else +{ "of a Serf. ", 40, 2, 3, 65 }, +{ "of a Yeoman. ", 65, 2, 3, 80 }, +{ "of a Townsman. ", 80, 2, 3, 90 }, +{ "of a Guildsman. ", 90, 2, 3, 105 }, +{ "of a Landed Knight. ", 96, 2, 3, 120 }, +{ "of a Noble Family in the Courts of Chaos. ", 99, 2, 3, 130 }, +{ "of the Royal Blood Line of Amber. ", 100, 2, 3, 140 }, +#endif + + +#ifdef JP +{ "あなたは一家のお荷物です。", 20, 3,50, 20 }, +{ "あなたは一家の誇りです。", 80, 3,50, 55 }, +{ "あなたは家族に大切にされています。", 100, 3,50, 60 }, +#else +{ "You are the black sheep of the family. ", 20, 3, 50, 20 }, +{ "You are a credit to the family. ", 80, 3, 50, 55 }, +{ "You are a well liked child. ", 100, 3, 50, 60 }, +#endif + + +#ifdef JP +{ "あなたの母はテレリ族のエルフでした。", 40, 4, 1, 50 }, +{ "あなたの父はテレリ族のエルフでした。", 75, 4, 1, 55 }, +{ "あなたの母はノルドール族のエルフでした。", 90, 4, 1, 55 }, +{ "あなたの父はノルドール族のエルフでした。", 95, 4, 1, 60 }, +{ "あなたの母はヴァンヤール族のエルフでした。", 98, 4, 1, 65 }, +{ "あなたの父はヴァンヤール族のエルフでした。", 100, 4, 1, 70 }, +#else +{ "Your mother was of the Teleri. ", 40, 4, 1, 50 }, +{ "Your father was of the Teleri. ", 75, 4, 1, 55 }, +{ "Your mother was of the Noldor. ", 90, 4, 1, 55 }, +{ "Your father was of the Noldor. ", 95, 4, 1, 60 }, +{ "Your mother was of the Vanyar. ", 98, 4, 1, 65 }, +{ "Your father was of the Vanyar. ", 100, 4, 1, 70 }, +#endif + + +#ifdef JP +{ "幾人かの子供のうちの一人です。", 60, 9, 54, 50 }, +{ "一粒種です。", 100, 9, 54, 55 }, +#else +{ "You are one of several children ", 60, 7, 8, 50 }, +{ "You are the only child ", 100, 7, 8, 55 }, +#endif + + +#ifdef JP +{ "あなたはテレリ族のエルフの", 75, 7, 8, 50 }, +{ "あなたはノルドール族のエルフの", 95, 7, 8, 55 }, +{ "あなたはヴァンヤール族のエルフの", 100, 7, 8, 60 }, +#else +{ "of a Teleri ", 75, 8, 9, 50 }, +{ "of a Noldor ", 95, 8, 9, 55 }, +{ "of a Vanyar ", 100, 8, 9, 60 }, +#endif + + +#ifdef JP +{ "レンジャーの", 40, 8,9, 80 }, +{ "アーチャーの", 70, 8,9, 90 }, +{ "戦士の", 87, 8,9,110 }, +{ "メイジの", 95, 8,9,125 }, +{ "王子の", 99, 8,9,140 }, +{ "王の", 100, 8,9,145 }, +#else +{ "Ranger. ", 40, 9, 54, 80 }, +{ "Archer. ", 70, 9, 54, 90 }, +{ "Warrior. ", 87, 9, 54, 110 }, +{ "Mage. ", 95, 9, 54, 125 }, +{ "Prince. ", 99, 9, 54, 140 }, +{ "King. ", 100, 9, 54, 145 }, +#endif + + +#ifdef JP +{ "ホビットの何人かの子供のうちの一人です。", 85,11,3, 45 }, +{ "ホビットの一粒種です。", 100,11,3, 55 }, +#else +{ "You are one of several children of a Hobbit ", 85, 10, 11, 45 }, +{ "You are the only child of a Hobbit ", 100, 10, 11, 55 }, +#endif + + +#ifdef JP +{ "あなたは乞食の", 20,10,11, 55 }, +{ "あなたは酒場の店主の", 30,10,11, 80 }, +{ "あなたは粉屋の", 40,10,11, 90 }, +{ "あなたは家主の", 50,10,11,100 }, +{ "あなたは忍びの者の", 80,10,11,110 }, +{ "あなたは戦士の", 95,10,11,115 }, +{ "あなたはメイジの", 99,10,11,125 }, +{ "あなたは一族の長の", 100,10,11,140 }, +#else +{ "Bum. ", 20, 11, 3, 55 }, +{ "Tavern Owner. ", 30, 11, 3, 80 }, +{ "Miller. ", 40, 11, 3, 90 }, +{ "Home Owner. ", 50, 11, 3, 100 }, +{ "Burglar. ", 80, 11, 3, 110 }, +{ "Warrior. ", 95, 11, 3, 115 }, +{ "Mage. ", 99, 11, 3, 125 }, +{ "Clan Elder. ", 100, 11, 3, 140 }, +#endif + + +#ifdef JP +{ "ノームの幾人かの子供のうちの一人です。", 85,14,3, 45 }, +{ "ノームの一粒種です。", 100,14,3, 55 }, +#else +{ "You are one of several children of a Gnome ", 85, 13, 14, 45 }, +{ "You are the only child of a Gnome ", 100, 13, 14, 55 }, +#endif + + +#ifdef JP +{ "あなたは物乞いの", 20,13,14, 55 }, +{ "あなたはホラ吹きの", 50,13,14, 70 }, +{ "あなたはお調子者の", 75,13,14, 85 }, +{ "あなたは戦士の", 95,13,14,100 }, +{ "あなたはメイジの", 100,13,14,125 }, +#else +{ "Beggar. ", 20, 14, 3, 55 }, +{ "Braggart. ", 50, 14, 3, 70 }, +{ "Prankster. ", 75, 14, 3, 85 }, +{ "Warrior. ", 95, 14, 3, 100 }, +{ "Mage. ", 100, 14, 3, 125 }, +#endif + + +#ifdef JP +{ "ドワーフの二人の子供のうちの一人です。", 25,17,18, 40 }, +{ "ドワーフの一粒種です。", 100,17,18, 50 }, +#else +{ "You are one of two children of a Dwarven ", 25, 16, 17, 40 }, +{ "You are the only child of a Dwarven ", 100, 16, 17, 50 }, +#endif + + +#ifdef JP +{ "あなたは泥棒の", 10,16,17, 60 }, +{ "あなたは牢番の", 25,16,17, 75 }, +{ "あなたは坑夫の", 75,16,17, 90 }, +{ "あなたは戦士の", 90,16,17,110 }, +{ "あなたはプリーストの", 99,16,17,130 }, +{ "あなたは王の", 100,16,17,150 }, +#else +{ "Thief. ", 10, 17, 18, 60 }, +{ "Prison Guard. ", 25, 17, 18, 75 }, +{ "Miner. ", 75, 17, 18, 90 }, +{ "Warrior. ", 90, 17, 18, 110 }, +{ "Priest. ", 99, 17, 18, 130 }, +{ "King. ", 100, 17, 18, 150 }, +#endif + + +#ifdef JP +{ "あなたは一家のお荷物です。", 15,18,57,10 }, +{ "あなたは一家の誇りです。", 85,18,57, 50 }, +{ "あなたは家族に大切にされています。", 100,18,57, 55 }, +#else +{ "You are the black sheep of the family. ", 15, 18, 57, 10 }, +{ "You are a credit to the family. ", 85, 18, 57, 50 }, +{ "You are a well liked child. ", 100, 18, 57, 55 }, +#endif + + +#ifdef JP +{ "あなたの母はオークでしたが、それは秘密にされています。", 25,19,20, 25 }, +{ "あなたの父はオークでしたが、それは秘密にされています。", 100,19,20, 25 }, +#else +{ "Your mother was an Orc, but it is unacknowledged. ", 25, 19, 20, 25 }, +{ "Your father was an Orc, but it is unacknowledged. ", 100, 19, 20, 25 }, +#endif + + +#ifdef JP +{ "あなたは農奴の養子です。", 40,20, 3, 65 }, +{ "あなたは自作農の養子です。", 65,20, 3, 80 }, +{ "あなたは町人の養子です。", 80,20, 3, 90 }, +{ "あなたは職人の養子です。", 90,20, 3,105 }, +{ "あなたは土着の騎士の養子です。", 96,20, 3,120 }, +{ "あなたは爵位ある貴族の養子です。", 99,20, 3,130 }, +{ "あなたは王家の血を引く者の養子です。", 100,20, 3,140 }, +#else +{ "You are the adopted child ", 100, 20, 2, 50 }, +#endif + + +#ifdef JP +{ "あなたの母は洞窟トロルの", 30,22,23, 20 }, +{ "あなたの父は洞窟トロルの", 60,22,23, 25 }, +{ "あなたの母は丘トロルの", 75,22,23, 30 }, +{ "あなたの父は丘トロルの", 90,22,23, 35 }, +{ "あなたの母は水トロルの", 95,22,23, 40 }, +{ "あなたの父は水トロルの", 100,22,23, 45 }, +#else +{ "Your mother was a Cave-Troll ", 30, 22, 23, 20 }, +{ "Your father was a Cave-Troll ", 60, 22, 23, 25 }, +{ "Your mother was a Hill-Troll ", 75, 22, 23, 30 }, +{ "Your father was a Hill-Troll ", 90, 22, 23, 35 }, +{ "Your mother was a Water-Troll ", 95, 22, 23, 40 }, +{ "Your father was a Water-Troll ", 100, 22, 23, 45 }, +#endif + + +#ifdef JP +{ "コックでした。", 5,23,62, 60 }, +{ "戦士でした。", 95,23,62, 55 }, +{ "呪術師でした。", 99,23,62, 65 }, +{ "一族の長でした。", 100,23,62, 80 }, +#else +{ "Cook. ", 5, 23, 62, 60 }, +{ "Warrior. ", 95, 23, 62, 55 }, +{ "Shaman. ", 99, 23, 62, 65 }, +{ "Clan Chief. ", 100, 23, 62, 80 }, +#endif + + +#ifdef JP +{ "あなたは深いブラウンの瞳と", 20,50,51, 50 }, +{ "あなたはブラウンの瞳と", 60,50,51, 50 }, +{ "あなたは淡い色の瞳と", 70,50,51, 50 }, +{ "あなたはグリーンの瞳と", 80,50,51, 50 }, +{ "あなたは青い瞳と", 90,50,51, 50 }, +{ "あなたはブルーグレイの瞳と", 100,50,51, 50 }, +#else +{ "You have dark brown eyes, ", 20, 50, 51, 50 }, +{ "You have brown eyes, ", 60, 50, 51, 50 }, +{ "You have hazel eyes, ", 70, 50, 51, 50 }, +{ "You have green eyes, ", 80, 50, 51, 50 }, +{ "You have blue eyes, ", 90, 50, 51, 50 }, +{ "You have blue-gray eyes, ", 100, 50, 51, 50 }, +#endif + + +#ifdef JP +{ "なめらかな", 70,51,52, 50 }, +{ "波打った", 90,51,52, 50 }, +{ "カールした", 100,51,52, 50 }, +#else +{ "straight ", 70, 51, 52, 50 }, +{ "wavy ", 90, 51, 52, 50 }, +{ "curly ", 100, 51, 52, 50 }, +#endif + + +#ifdef JP +{ "黒髪を持ち、", 30,52,53, 50 }, +{ "茶髪を持ち、", 70,52,53, 50 }, +{ "とび色の髪を持ち、", 80,52,53, 50 }, +{ "赤い髪を持ち、", 90,52,53, 50 }, +{ "ブロンドの髪を持ち、", 100,52,53, 50 }, +#else +{ "black hair, ", 30, 52, 53, 50 }, +{ "brown hair, ", 70, 52, 53, 50 }, +{ "auburn hair, ", 80, 52, 53, 50 }, +{ "red hair, ", 90, 52, 53, 50 }, +{ "blond hair, ", 100, 52, 53, 50 }, +#endif + + +#ifdef JP +{ "漆黒の肌をしています。", 10,53, 0, 50 }, +{ "黒い肌をしています。", 30,53, 0, 50 }, +{ "普通の肌色をしています。", 80,53, 0, 50 }, +{ "白い肌をしています。", 90,53, 0, 50 }, +{ "透き通るような白い肌をしています。", 100,53, 0, 50 }, +#else +{ "and a very dark complexion.", 10, 53, 0, 50 }, +{ "and a dark complexion.", 30, 53, 0, 50 }, +{ "and an average complexion.", 80, 53, 0, 50 }, +{ "and a fair complexion.", 90, 53, 0, 50 }, +{ "and a very fair complexion.", 100, 53, 0, 50 }, +#endif + + +#ifdef JP +{ "あなたは明るいグレーの瞳と", 85,54,55, 50 }, +{ "あなたは明るいブルーの瞳と", 95,54,55, 50 }, +{ "あなたは明るいグリーンの瞳と", 100,54,55, 50 }, +#else +{ "You have light grey eyes, ", 85, 54, 55, 50 }, +{ "You have light blue eyes, ", 95, 54, 55, 50 }, +{ "You have light green eyes, ", 100, 54, 55, 50 }, +#endif + + +#ifdef JP +{ "なめらかな", 75,55,56, 50 }, +{ "波打った", 100,55,56, 50 }, +#else +{ "straight ", 75, 55, 56, 50 }, +{ "wavy ", 100, 55, 56, 50 }, +#endif + + +#ifdef JP +{ "黒髪を持ち、白い肌をしています。", 75,56, 0, 50 }, +{ "茶髪を持ち、白い肌をしています。", 85,56, 0, 50 }, +{ "ブロンドの髪を持ち、白い肌をしています。", 95,56, 0, 50 }, +{ "銀髪を持ち、白い肌をしています。", 100,56, 0, 50 }, +#else +{ "black hair, and a fair complexion.", 75, 56, 0, 50 }, +{ "brown hair, and a fair complexion.", 85, 56, 0, 50 }, +{ "blond hair, and a fair complexion.", 95, 56, 0, 50 }, +{ "silver hair, and a fair complexion.", 100, 56, 0, 50 }, +#endif + + +#ifdef JP +{ "あなたは深いブラウンの瞳と", 99,57,58, 50 }, +{ "あなたは輝く赤い瞳と", 100,57,58, 60 }, +#else +{ "You have dark brown eyes, ", 99, 57, 58, 50 }, +{ "You have glowing red eyes, ", 100, 57, 58, 60 }, +#endif + + +#ifdef JP +{ "なめらかな", 90,58,59, 50 }, +{ "波打った", 100,58,59, 50 }, +#else +{ "straight ", 90, 58, 59, 50 }, +{ "wavy ", 100, 58, 59, 50 }, +#endif + + +#ifdef JP +{ "黒髪、そして", 75,59,60, 50 }, +{ "茶髪、そして", 100,59,60, 50 }, +#else +{ "black hair, ", 75, 59, 60, 50 }, +{ "brown hair, ", 100, 59, 60, 50 }, +#endif + + +#ifdef JP +{ " 30cm ほどのヒゲを持ち、", 25,60,61, 50 }, +{ " 60cm ほどのヒゲを持ち、", 60,60,61, 51 }, +{ " 90cm ほどのヒゲを持ち、", 90,60,61, 53 }, +{ " 1m20cm ほどのヒゲを持ち、 ", 100,60,61, 55 }, +#else +{ "a one foot beard, ", 25, 60, 61, 50 }, +{ "a two foot beard, ", 60, 60, 61, 51 }, +{ "a three foot beard, ", 90, 60, 61, 53 }, +{ "a four foot beard, ", 100, 60, 61, 55 }, +#endif + + +#ifdef JP +{ "黒い肌をしています。", 100,61, 0, 50 }, +#else +{ "and a dark complexion.", 100, 61, 0, 50 }, +#endif + + +#ifdef JP +{ "あなたはベトつくような緑の瞳と", 60,62,63, 50 }, +{ "あなたは汚物のような黄色い瞳と", 85,62,63, 50 }, +{ "あなたは青く血走った瞳と", 99,62,63, 50 }, +{ "あなたは輝く赤い瞳と", 100,62,63, 55 }, +#else +{ "You have slime green eyes, ", 60, 62, 63, 50 }, +{ "You have puke yellow eyes, ", 85, 62, 63, 50 }, +{ "You have blue-bloodshot eyes, ", 99, 62, 63, 50 }, +{ "You have glowing red eyes, ", 100, 62, 63, 55 }, +#endif + + +#ifdef JP +{ "汚らしい", 33,63,64, 50 }, +{ "不潔な", 66,63,64, 50 }, +{ "脂ぎった", 100,63,64, 50 }, +#else +{ "dirty ", 33, 63, 64, 50 }, +{ "mangy ", 66, 63, 64, 50 }, +{ "oily ", 100, 63, 64, 50 }, +#endif + + +#ifdef JP +{ "ワカメの様な髪を持ち、", 33,64,65, 50 }, +{ "明るい赤色の髪を持ち、", 66,64,65, 50 }, +{ "暗い紫色の髪を持ち、", 100,64,65, 50 }, +#else +{ "sea-weed green hair, ", 33, 64, 65, 50 }, +{ "bright red hair, ", 66, 64, 65, 50 }, +{ "dark purple hair, ", 100, 64, 65, 50 }, +#endif + + +#ifdef JP +{ "緑色の", 25,65,66, 50 }, +{ "青い", 50,65,66, 50 }, +{ "白い", 75,65,66, 50 }, +{ "黒い", 100,65,66, 50 }, +#else +{ "and green ", 25, 65, 66, 50 }, +{ "and blue ", 50, 65, 66, 50 }, +{ "and white ", 75, 65, 66, 50 }, +{ "and black ", 100, 65, 66, 50 }, +#endif + + +#ifdef JP +{ "ブツブツした肌をしています。", 33,66, 0, 50 }, +{ "カサブタだらけの肌をしています。", 66,66, 0, 50 }, +{ "ガサガサの肌をしています。", 100,66, 0, 50 }, +#else +{ "ulcerous skin.", 33, 66, 0, 50 }, +{ "scabby skin.", 66, 66, 0, 50 }, +{ "leprous skin.", 100, 66, 0, 50 }, +#endif + + +#ifdef JP +{ "認知されていない子供です。", 50, 68, 50, 45 }, +{ "勘当された子供です。", 80, 68, 50, 65 }, +{ "早くして生き別れた子供です。", 100, 68, 50, 55 }, +#else +{ "You are an unacknowledged child of ", 50, 67, 68, 45 }, +{ "You are a rebel child of ", 80, 67, 68, 65 }, +{ "You are a long lost child of ", 100, 67, 68, 55 }, +#endif + + +#ifdef JP +{ "あなたは名の知れぬアンバーの王族の", 50, 67, 68, 80 }, +{ "あなたは第三世代のアンバー王族の", 65, 67, 68, 90 }, +{ "あなたは第二世代のアンバー王族の", 79, 67, 68, 100 }, +{ "あなたはオベロンの", 80, 67, 68, 130 }, +{ "あなたはオズリックの", 83, 67, 68, 105 }, +{ "あなたはフィンドーの", 84, 67, 68, 105 }, +{ "あなたはブランドの", 85, 67, 68, 90 }, +{ "あなたはフローラの", 87, 67, 68, 100 }, +{ "あなたはジェラードの", 88, 67, 68, 125 }, +{ "あなたはディアドラの", 89, 67, 68, 120 }, +{ "あなたはランダムの", 90, 67, 68, 140 }, +{ "あなたはベネディクトの", 91, 67, 68, 115 }, +{ "あなたはコーウィンの", 92, 67, 68, 110 }, +{ "あなたはジュリアンの", 93, 67, 68, 105 }, +{ "あなたはケインの", 94, 67, 68, 95 }, +{ "あなたはブレイズの", 95, 67, 68, 115 }, +{ "あなたはフィオナの", 96, 67, 68, 110 }, +{ "あなたはエリックの", 97, 67, 68, 135 }, +{ "あなたはリナルドの", 98, 67, 68, 90 }, +{ "あなたはマーリンの", 99, 67, 68, 105 }, +{ "あなたはマーティンの", 100, 67,68, 80 }, +#else +{ "an unknown Amberite. ", 50, 68, 50, 80 }, +{ "an unknown third generation Amberite. ", 65, 68, 50, 90 }, +{ "an unknown second generation Amberite. ", 79, 68, 50, 100 }, +{ "Oberon. ", 80, 68, 50, 130 }, +{ "Osric. ", 83, 68, 50, 105 }, +{ "Finndo. ", 84, 68, 50, 105 }, +{ "Brand. ", 85, 68, 50, 90 }, +{ "Flora. ", 87, 68, 50, 100 }, +{ "Gerard. ", 88, 68, 50, 125 }, +{ "Deirdre. ", 89, 68, 50, 120 }, +{ "Random. ", 90, 68, 50, 140 }, +{ "Benedict. ", 91, 68, 50, 115 }, +{ "Corwin. ", 92, 68, 50, 110 }, +{ "Julian. ", 93, 68, 50, 105 }, +{ "Caine. ", 94, 68, 50, 95 }, +{ "Bleys. ", 95, 68, 50, 115 }, +{ "Fiona. ", 96, 68, 50, 110 }, +{ "Eric. ", 97, 68, 50, 135 }, +{ "Rinaldo. ", 98, 68, 50, 90 }, +{ "Merlin. ", 99, 68, 50, 105 }, +{ "Martin. ", 100, 68, 50, 80 }, +#endif + + + +#ifdef JP +{ "何人かの子供のうちの一人です。", 85, 70, 71, 45 }, +{ "一粒種です。", 100, 70, 71, 55 }, + +{ "あなたはダークエルフの戦士の", 50, 69, 70, 60 }, +{ "あなたはダークエルフの魔術士の", 80, 69, 70, 75 }, +{ "あなたはダークエルフの貴族の", 100, 69, 70, 95 }, +#else +{ "You are one of several children of a Dark Elven ", 85, 69, 70, 45 }, +{ "You are the only child of a Dark Elven ", 100, 69, 70, 55 }, + +{ "Warrior. ", 50, 70, 71, 60 }, +{ "Warlock. ", 80, 70, 71, 75 }, +{ "Noble. ", 100, 70, 71, 95 }, +#endif + + +#ifdef JP +{ "あなたは黒い瞳と", 100, 71, 72, 50 }, +#else +{ "You have black eyes, ", 100, 71, 72, 50 }, +#endif + + +#ifdef JP +{ "なめらかな", 70, 72, 73, 50 }, +{ "波打った", 90, 72, 73, 50 }, +{ "カールした", 100, 72, 73, 50 }, + +{ "黒い髪、そしてとても暗い色の肌をしています。", 100, 73, 0, 50 }, +#else +{ "straight ", 70, 72, 73, 50 }, +{ "wavy ", 90, 72, 73, 50 }, +{ "curly ", 100, 72, 73, 50 }, + +{ "black hair and a very dark complexion.", 100, 73, 0, 50 }, +#endif + + +#ifdef JP +{ "あなたの母親はオーガでしたが、それは秘密にされています。", 25, 74, 20, 25 }, +{ "あなたの父親はオーガでしたが、それは秘密にされています。", 100, 74, 20, 25 }, +#else +{ "Your mother was an Ogre, but it is unacknowledged. ", 25, 74, 20, 25 }, +{ "Your father was an Ogre, but it is unacknowledged. ", 100, 74, 20, 25 }, +#endif + + +#ifdef JP +{ "あなたの母親は丘ジャイアントでした。", 10, 75, 20, 50 }, +{ "あなたの母親はファイアー・ジャイアントでした。", 12, 75, 20, 55 }, +{ "あなたの母親はフロスト・ジャイアントでした。", 20, 75, 20, 60 }, +{ "あなたの母親はクラウド・ジャイアントでした。", 23, 75, 20, 65 }, +{ "あなたの母親はストーム・ジャイアントでした。", 25, 75, 20, 70 }, +{ "あなたの父親は丘ジャイアントでした。", 60, 75, 20, 50 }, +{ "あなたの父親はファイアー・ジャイアントでした。", 70, 75, 20, 55 }, +{ "あなたの父親はフロスト・ジャイアントでした。", 80, 75, 20, 60 }, +{ "あなたの父親はクラウド・ジャイアントでした。", 90, 75, 20, 65 }, +{ "あなたの父親はストーム・ジャイアントでした。", 100, 75, 20, 70 }, +#else +{ "Your mother was a Hill Giant. ", 10, 75, 20, 50 }, +{ "Your mother was a Fire Giant. ", 12, 75, 20, 55 }, +{ "Your mother was a Frost Giant. ", 20, 75, 20, 60 }, +{ "Your mother was a Cloud Giant. ", 23, 75, 20, 65 }, +{ "Your mother was a Storm Giant. ", 25, 75, 20, 70 }, +{ "Your father was a Hill Giant. ", 60, 75, 20, 50 }, +{ "Your father was a Fire Giant. ", 70, 75, 20, 55 }, +{ "Your father was a Frost Giant. ", 80, 75, 20, 60 }, +{ "Your father was a Cloud Giant. ", 90, 75, 20, 65 }, +{ "Your father was a Storm Giant. ", 100, 75, 20, 70 }, +#endif + + +#ifdef JP +{ "あなたの父親は名の知れぬタイタンでした。", 75, 76, 20, 50 }, +{ "あなたの母親はテミスでした。", 80, 76, 20, 100 }, +{ "あなたの母親はメノシンでした。", 85, 76, 20, 100 }, +{ "あなたの父親はオケアノスでした。", 90, 76, 20, 100 }, +{ "あなたの父親はクリウスでした。", 95, 76, 20, 100 }, +{ "あなたの父親はハイペリオンでした。", 98, 76, 20, 125 }, +{ "あなたの父親はクロノスでした。", 100, 76, 20, 150 }, +#else +{ "Your father was an unknown Titan. ", 75, 76, 20, 50 }, +{ "Your mother was Themis. ", 80, 76, 20, 100 }, +{ "Your mother was Mnemosyne. ", 85, 76, 20, 100 }, +{ "Your father was Okeanoas. ", 90, 76, 20, 100 }, +{ "Your father was Crius. ", 95, 76, 20, 100 }, +{ "Your father was Hyperion. ", 98, 76, 20, 125 }, +{ "Your father was Kronos. ", 100, 76, 20, 150 }, +#endif + + +#ifdef JP +{ "あなたは名の知れぬサイクロプスの子孫です。", 90, 77, 109, 50 }, +{ "あなたはポリフェモスの子供です。", 98, 77, 109, 80 }, +{ "あなたはウラノスの子供です。", 100, 77, 109, 135 }, +#else +{ "You are the offspring of an unknown Cyclops. ", 90, 77, 109, 50 }, +{ "You are Polyphemos's child. ", 98, 77, 109, 80 }, +{ "You are Uranos's child. ", 100, 77, 109, 135 }, +#endif + + +#ifdef JP +{ "何人かの子供のうちの一人です。", 100, 79, 80, 50 }, + +{ "あなたはブラウン・イークの", 50, 78, 79, 50 }, +{ "あなたはブルー・イークの", 75, 78, 79, 50 }, +{ "あなたはマスター・イークの", 95, 78, 79, 85 }, +{ "あなたはイークの王『ボルドール』の", 100, 78, 79, 120 }, +#else +{ "You are one of several children of ", 100, 78, 79, 50 }, + +{ "a Brown Yeek. ", 50, 79, 80, 50 }, +{ "a Blue Yeek. ", 75, 79, 80, 50 }, +{ "a Master Yeek. ", 95, 79, 80, 85 }, +{ "Boldor, the King of the Yeeks. ", 100, 79, 80, 120 }, +#endif + + +#ifdef JP +{ "あなたは青い瞳と", 25, 80, 81, 50 }, +{ "あなたは光る瞳と", 50, 80, 81, 50 }, +{ "あなたは小さな黒い瞳と", 75, 80, 81, 50 }, +{ "あなたは黒く輝く瞳と", 100, 80, 81, 50 }, + +{ "髪のない頭、", 20, 81, 65, 50 }, +{ "黒く短い髪、", 40, 81, 65, 50 }, +{ "黒く長い髪、", 60, 81, 65, 50 }, +{ "燃えるような赤い髪、", 80, 81, 65, 50 }, +{ "色のない白い髪、", 100, 81, 65, 50 }, +#else +{ "You have pale eyes, ", 25, 80, 81, 50 }, +{ "You have glowing eyes, ", 50, 80, 81, 50 }, +{ "You have tiny black eyes, ", 75, 80, 81, 50 }, +{ "You have shining black eyes, ", 100, 80, 81, 50 }, + +{ "no hair at all, ", 20, 81, 65, 50 }, +{ "short black hair, ", 40, 81, 65, 50 }, +{ "long black hair, ", 60, 81, 65, 50 }, +{ "bright red hair, ", 80, 81, 65, 50 }, +{ "colourless albino hair, ", 100, 81, 65, 50 }, +#endif + + +#ifdef JP +{ "の何人かの子供のうちの一人です。 ", 100, 83, 80, 50 }, + +{ "あなたはスモール・コボルド", 40, 82, 83, 50 }, +{ "あなたはコボルド", 75, 82, 83, 55 }, +{ "あなたはラージ・コボルド", 95, 82, 83, 65 }, +{ "あなたはコボルドの王『ムガッシュ』", 100, 82, 83, 100 }, +#else +{ "You are one of several children of ", 100, 82, 83, 50 }, + +{ "a Small Kobold. ", 40, 83, 80, 50 }, +{ "a Kobold. ", 75, 83, 80, 55 }, +{ "a Large Kobold. ", 95, 83, 80, 65 }, +{ "Mughash, the Kobold Lord. ", 100, 83, 80, 100 }, +#endif + + +#ifdef JP +{ "あなたは女王クラッコンの何人かの子供のうちの一人です。" +, 100, 84, 85, 50 }, + +{ "あなたは赤い肌と", 40, 85, 86, 50 }, +{ "あなたは黒い肌と", 90, 85, 86, 50 }, +{ "あなたは黄色い肌と", 100, 85, 86, 50 }, + +{ "黒い目をしています。", 100, 86, 0, 50 }, +#else +{ "You are one of several children of a Klackon hive queen. " +, 100, 84, 85, 50 }, + +{ "You have red skin, ", 40, 85, 86, 50 }, +{ "You have black skin, ", 90, 85, 86, 50 }, +{ "You have yellow skin, ", 100, 85, 86, 50 }, + +{ "and black eyes.", 100, 86, 0, 50 }, +#endif + + +#ifdef JP +{ "の何人かの子供のうちの一人です。", 100, 88, 18, 89 }, + +{ "あなたはニーベルングの奴隷", 30, 87, 88, 20 }, +{ "あなたはニーベルングの盗賊", 50, 87, 88, 40 }, +{ "あなたはニーベルングの鍛冶屋", 70, 87, 88, 60 }, +{ "あなたはニーベルングの坑夫", 90, 87, 88, 75 }, +{ "あなたはニーベルングのシャーマン", 95,87, 88, 100 }, +{ "あなたはニーベルングの王『ミーメ』", 100,87, 88, 100 },/*nuke me*/ +#else +{ "You are one of several children of ", 100, 87, 88, 89 }, + +{ "a Nibelung Slave. ", 30, 88, 18, 20 }, +{ "a Nibelung Thief. ", 50, 88, 18, 40 }, +{ "a Nibelung Smith. ", 70, 88, 18, 60 }, +{ "a Nibelung Miner. ", 90, 88, 18, 75 }, +{ "a Nibelung Shaman. ", 95, 88, 18, 100 }, +{ "Mime, the Nibelung. ", 100, 88, 18, 100 }, +#endif + +#ifdef JP +{ "あなたはドラコニアンの", 100, 89, 90, 50 }, + +{ "の長子です。", 30, 135, 91, 55 }, +{ "の末子です。", 50, 135, 91, 50 }, +{ "の養子です。", 55, 135, 91, 50 }, +{ "の孤児です。", 60, 135, 91, 45 }, +{ "の幾人かの子供のうちの一人です。", 85, 135, 91, 50 }, +{ "の一粒種です。", 100, 135, 91, 55 }, + +{ "乞食", 10, 90, 135, 20 }, +{ "盗賊", 21, 90, 135, 30 }, +{ "水夫", 26, 90, 135, 45 }, +{ "傭兵", 42, 90, 135, 45 }, +{ "戦士", 73, 90, 135, 50 }, +{ "商人", 78, 90, 135, 50 }, +{ "職人", 85, 90, 135, 55 }, +{ "治療家", 89, 90, 135, 60 }, +{ "僧侶", 94, 90, 135, 65 }, +{ "魔術師", 97, 90, 135, 70 }, +{ "学者", 99, 90, 135, 80 }, +{ "貴族", 100, 90, 135, 100 }, + +{ "あなたは", 100, 91, 136, 50 }, + +{ "は黒灰色の翼と肌、そして灰色の腹をしています。", 11, 136, 0, 50 }, +{ "ブロンズ色の翼と肌、そして銅色の腹をしています。", 16, 136, 0, 50 }, +{ "黄金の翼を持ち、黄金の肌をしています。", 24, 136, 0, 50 }, +{ "白い翼を持ち、白い肌をしています。", 26, 136, 0, 60 }, +{ "青い翼と肌、そして水色の腹をしています。", 32, 136, 0, 50 }, +{ "万色の翼を持ち、肌も万色です。", 33, 136, 0, 70 }, +{ "茶色の翼を持ち、茶色の肌をしています。", 37, 136, 0, 45 }, +{ "黒い翼と肌、そして白い腹をしています。", 41, 136, 0, 50 }, +{ "薄紫色の翼と肌、そして白い腹をしています。", 48, 136, 0, 50 }, +{ "緑色の翼と肌、そして黄色い腹をしています。", 65, 136, 0, 50 }, +{ "緑色の翼を持ち、緑色の肌をしています。", 75, 136, 0, 50 }, +{ "赤い翼を持ち、赤い肌をしています。", 88, 136, 0, 50 }, +{ "黒い翼を持ち、黒い肌をしています。", 94, 136, 0, 50 }, +{ "きらめく翼を持ち、金属的な肌をしています。", 100, 136, 0, 55 }, +#else +{ "You are ", 100, 89, 135, 50 }, + +{ "the oldest child of a Draconian ", 30, 135, 90, 55 }, +{ "the youngest child of a Draconian ", 50, 135, 90, 50 }, +{ "the adopted child of a Draconian ", 55, 135, 90, 50 }, +{ "an orphaned child of a Draconian ", 60, 135, 90, 45 }, +{ "one of several children of a Draconian ", 85, 135, 90, 50 }, +{ "the only child of a Draconian ", 100, 135, 90, 55 }, + +{ "Beggar. ", 10, 90, 91, 20 }, +{ "Thief. ", 21, 90, 91, 30 }, +{ "Sailor. ", 26, 90, 91, 45 }, +{ "Mercenary. ", 42, 90, 91, 45 }, +{ "Warrior. ", 73, 90, 91, 50 }, +{ "Merchant. ", 78, 90, 91, 50 }, +{ "Artisan. ", 85, 90, 91, 55 }, +{ "Healer. ", 89, 90, 91, 60 }, +{ "Priest. ", 94, 90, 91, 65 }, +{ "Mage. ", 97, 90, 91, 70 }, +{ "Scholar. ", 99, 90, 91, 80 }, +{ "Noble. ", 100, 90, 91, 100 }, + +{ "You have ", 100, 91, 136, 50 }, + +{ "charcoal wings, charcoal skin and a smoke-gray belly.", 11, 136, 0, 50 }, +{ "bronze wings, bronze skin, and a copper belly.", 16, 136, 0, 50 }, +{ "golden wings, and golden skin.", 24, 136, 0, 50 }, +{ "white wings, and white skin.", 26, 136, 0, 60 }, +{ "blue wings, blue skin, and a cyan belly.", 32, 136, 0, 50 }, +{ "multi-hued wings, and multi-hued skin.", 33, 136, 0, 70 }, +{ "brown wings, and brown skin.", 37, 136, 0, 45 }, +{ "black wings, black skin, and a white belly.", 41, 136, 0, 50 }, +{ "lavender wings, lavender skin, and a white belly.", 48, 136, 0, 50 }, +{ "green wings, green skin and yellow belly.", 65, 136, 0, 50 }, +{ "green wings, and green skin.", 75, 136, 0, 50 }, +{ "red wings, and red skin.", 88, 136, 0, 50 }, +{ "black wings, and black skin.", 94, 136, 0, 50 }, +{ "metallic skin, and shining wings.", 100, 136, 0, 55 }, +#endif + + + +#ifdef JP +{ "あなたは偉大なる長老たちの脳味噌が浮かんでいる母なる池でオタマジャクシとして生まれました。あなたはヌルヌルした肌と輝く空虚な目をしていて、", 100, 92, 93, 80 }, +{ "口の周りに三本の触手が生えています。", 20, 93, 0, 45 }, +{ "口の周りに四本の触手が生えています。", 80, 93, 0, 50 }, +{ "口の周りに五本の触手が生えています。", 100, 93, 0, 55 }, +#else +{ "You have slimy skin, empty glowing eyes, and ", 100, 92, 93, 80 }, +{ "three tentacles around your mouth.", 20, 93, 0, 45 }, +{ "four tentacles around your mouth.", 80, 93, 0, 50 }, +{ "five tentacles around your mouth.", 100, 93, 0, 55 }, +#endif + + +#ifdef JP +{ "あなたの祖先は", 100, 94, 95, 50 }, + +{ "心を持たない地獄の低級な生物でした。", 30, 95, 96, 20 }, +{ "下級悪魔でした。", 60, 95, 96, 50 }, +{ "上級悪魔でした。", 90, 95, 96, 75 }, +{ "魔王でした。", 100, 95, 96, 99 }, + +{ "あなたは赤い肌と", 50, 96, 97, 50 }, +{ "あなたは茶色い肌と", 100, 96, 97, 50 }, + +{ "赤く燃える瞳をしていて、鉤爪と牙と刺が生えています。", 40, 97, 0, 50 }, +{ "赤く燃える瞳をしていて、鉤爪と牙が生えています。", 70, 97, 0, 50 }, +{ "赤く燃える瞳をしていて、鉤爪が生えています。", 100, 97, 0, 50 }, +#else +{ "You ancestor was ", 100, 94, 95, 50 }, + +{ "a mindless demonic spawn. ", 30, 95, 96, 20 }, +{ "a minor demon. ", 60, 95, 96, 50 }, +{ "a major demon. ", 90, 95, 96, 75 }, +{ "a demon lord. ", 100, 95, 96, 99 }, + +{ "You have red skin, ", 50, 96, 97, 50 }, +{ "You have brown skin, ", 100, 96, 97, 50 }, + +{ "claws, fangs, spikes, and glowing red eyes.", 40, 97, 0, 50 }, +{ "claws, fangs, and glowing red eyes.", 70, 97, 0, 50 }, +{ "claws, and glowing red eyes.", 100, 97, 0, 50 }, +#endif + + +#ifdef JP +{ "あなたはカバラの秘術によって", 40, 98, 99, 50 }, +{ "あなたは魔法使いによって", 65, 98, 99, 50 }, +{ "あなたは錬金術師によって", 90, 98, 99, 50 }, +{ "あなたは僧侶によって", 100, 98, 99, 60 }, + +{ "悪と戦うために", 10, 99, 100, 65 }, +{ "", 100, 99, 100, 50 }, + +{ "粘土から", 40, 100, 101, 50 }, +{ "岩石から", 80, 100, 101, 50 }, +{ "木から", 85, 100, 101, 40 }, +{ "鉄から", 99, 100, 101, 50 }, +{ "純金から", 100, 100, 101, 100 }, + +{ "作り出されました。", 100,101, 0, 50 }, +#else +{ "You were shaped from ", 100, 98, 99, 50 }, + +{ "clay ", 40, 99, 100, 50 }, +{ "stone ", 80, 99, 100, 50 }, +{ "wood ", 85, 99, 100, 40 }, +{ "iron ", 99, 99, 100, 50 }, +{ "pure gold ", 100, 99, 100, 100 }, + +{ "by a Kabbalist", 40, 100, 101, 50 }, +{ "by a Wizard", 65, 100, 101, 50 }, +{ "by an Alchemist", 90, 100, 101, 50 }, +{ "by a Priest", 100, 100, 101, 60 }, + +{ " to fight evil.", 10, 101, 0, 65 }, +{ ".", 100, 101, 0, 50 }, +#endif + + +#ifdef JP +{ "あなたは", 100, 102, 103, 50 }, + +{ "死霊術士により作り出されました。", 30, 103, 104, 50 }, +{ "魔法の実験により作り出されました。", 50, 103, 104, 50 }, +{ "邪悪な僧侶により作り出されました。", 70, 103, 104, 50 }, +{ "悪魔との契約により生み出されました。", 75, 103, 104, 50 }, +{ "怨霊から生まれました。", 85, 103, 104, 50 }, +{ "呪いから生まれました。", 95, 103, 104, 30 }, +{ "神名濫用により生み出されました。", 100, 103, 104, 50 }, + +{ "あなたは", 100, 104, 105, 50 }, +{ "古く汚れた骨で出来ていて、", 40, 105, 106, 50 }, +{ "腐った黒い骨で出来ていて、", 60, 105, 106, 50 }, +{ "うす汚れた茶色い骨で出来ていて、", 80, 105, 106, 50 }, +{ "白く輝く骨で出来ていて、", 100, 105, 106, 50 }, + +{ "光る目をしています。", 30, 106, 0, 50 }, +{ "地獄の劫火が燃えさかる目をしています。", 50, 106, 0, 50 }, +{ "眼窩はからっぽです。", 100, 106, 0, 50 }, +#else +{ "You were created by ", 100, 102, 103, 50 }, + +{ "a Necromancer. ", 30, 103, 104, 50 }, +{ "a magical experiment. ", 50, 103, 104, 50 }, +{ "an Evil Priest. ", 70, 103, 104, 50 }, +{ "a pact with the demons. ", 75, 103, 104, 50 }, +{ "a restless spirit. ", 85, 103, 104, 50 }, +{ "a curse. ", 95, 103, 104, 30 }, +{ "an oath. ", 100, 103, 104, 50 }, + +{ "You have ", 100, 104, 105, 50 }, +{ "dirty, dry bones, ", 40, 105, 106, 50 }, +{ "rotten black bones, ", 60, 105, 106, 50 }, +{ "filthy, brown bones, ", 80, 105, 106, 50 }, +{ "shining white bones, ", 100, 105, 106, 50 }, + +{ "and glowing eyes.", 30, 106, 0, 50 }, +{ "and eyes which burn with hellfire.", 50, 106, 0, 50 }, +{ "and empty eyesockets.", 100, 106, 0, 50 }, +#endif + + +#ifdef JP +{ "あなたは", 100, 107, 108, 50 }, + +{ "死霊術士により生み出されました。", 30, 108, 62, 50 }, +{ "魔法使いにより生み出されました。", 50, 108, 62, 50 }, +{ "怨霊から生まれました。",60, 108, 62, 50 }, +{ "邪悪な僧侶により生み出されました。", 70, 108, 62, 50 }, +{ "悪魔との契約により生み出されました。", 80, 108, 62, 50 }, +{ "呪いから生まれました。", 95, 108, 62, 30 }, +{ "神名濫用により生み出されました。", 100, 108, 62, 50 }, + +{ "あなたは暗褐色の瞳、", 20, 109, 110, 50 }, +{ "あなたは褐色の瞳、", 60, 109, 110, 50 }, +{ "あなたは薄茶色の瞳、", 70, 109, 110, 50 }, +{ "あなたは緑色の瞳、", 80, 109, 110, 50 }, +{ "あなたは青い瞳、", 90, 109, 110, 50 }, +{ "あなたは淡青色の瞳、", 100, 109, 110, 50 }, /*tansei.cc.u-tokyoの由来 */ + +{ "なめらかな", 70, 110, 111, 50 }, +{ "波打った", 90, 110, 111, 50 }, +{ "カールした", 100, 110, 111, 50 }, + +{ "黒い髪、", 30, 111, 112, 50 }, +{ "茶色い髪、", 70, 111, 112, 50 }, +{ "赤茶色の髪、", 80, 111, 112, 50 }, +{ "赤い髪、", 90, 111, 112, 50 }, +{ "金髪、", 100, 111, 112, 50 }, + +{ "そしてとても暗い肌をしています。", 10, 112, 0, 50 }, +{ "そして暗い肌をしています。", 30, 112, 0, 50 }, +{ "そして平均的な肌の色をしています。", 80, 112, 0, 50 }, +{ "そして血色のいい肌をしています。", 90, 112, 0, 50 }, +{ "そしてとても血色のいい肌をしています。", 100, 112, 0, 50 }, +#else +{ "You were created by ", 100, 107, 108, 50 }, + +{ "a Necromancer. ", 30, 108, 62, 50 }, +{ "a Wizard. ", 50, 108, 62, 50 }, +{ "a restless spirit. ",60, 108, 62, 50 }, +{ "an Evil Priest. ", 70, 108, 62, 50 }, +{ "a pact with the demons. ", 80, 108, 62, 50 }, +{ "a curse. ", 95, 108, 62, 30 }, +{ "an oath. ", 100, 108, 62, 50 }, + +{ "You have a dark brown eye, ", 20, 109, 110, 50 }, +{ "You have a brown eye, ", 60, 109, 110, 50 }, +{ "You have a hazel eye, ", 70, 109, 110, 50 }, +{ "You have a green eye, ", 80, 109, 110, 50 }, +{ "You have a blue eye, ", 90, 109, 110, 50 }, +{ "You have a blue-gray eye, ", 100, 109, 110, 50 }, + +{ "straight ", 70, 110, 111, 50 }, +{ "wavy ", 90, 110, 111, 50 }, +{ "curly ", 100, 110, 111, 50 }, + +{ "black hair, ", 30, 111, 112, 50 }, +{ "brown hair, ", 70, 111, 112, 50 }, +{ "auburn hair, ", 80, 111, 112, 50 }, +{ "red hair, ", 90, 111, 112, 50 }, +{ "blond hair, ", 100, 111, 112, 50 }, + +{ "and a very dark complexion.", 10, 112, 0, 50 }, +{ "and a dark complexion.", 30, 112, 0, 50 }, +{ "and an average complexion.", 80, 112, 0, 50 }, +{ "and a fair complexion.", 90, 112, 0, 50 }, +{ "and a very fair complexion.", 100, 112, 0, 50 }, +#endif + + +#ifdef JP +{ "あなたは銘のない墓の中から甦りました。", 20, 113, 114, 50 }, +{ "あなたは生前ただの百姓でしたが、強大なバンパイア・ロードの餌食となってしまいました。", 40, 113, 114, 50 }, +{ "あなたは生前はバンパイア・ハンターでしたが、彼らの餌食となってしまいました。", 60, 113, 114, 50 }, +{ "あなたは生前は死霊術士でした。", 80, 113, 114, 50 }, +{ "あなたは生前は強大な貴族でした。", 95, 113, 114, 50 }, +{ "あなたは生前は強大で残忍な専制君主でした。", 100, 113, 114, 50 }, +#else +{ "You arose from an unmarked grave. ", 20, 113, 114, 50 }, +{ "In life you were a simple peasant, the victim of a powerful Vampire Lord. ", 40, 113, 114, 50 }, +{ "In life you were a Vampire Hunter, but they got you. ", 60, 113, 114, 50 }, +{ "In life you were a Necromancer. ", 80, 113, 114, 50 }, +{ "In life you were a powerful noble. ", 95, 113, 114, 50 }, +{ "In life you were a powerful and cruel tyrant. ", 100, 113, 114, 50 }, +#endif + + +#ifdef JP +{ "あなたは", 100, 114, 115, 50 }, + +{ "漆黒の髪、", 25, 115, 116, 50 }, +{ "もつれたブラウンの髪、", 50, 115, 116, 50 }, +{ "白い髪、", 75, 115, 116, 50 }, +{ "髪のない頭、", 100, 115, 116, 50 }, +#else +{ "You have ", 100, 114, 115, 50 }, + +{ "jet-black hair, ", 25, 115, 116, 50 }, +{ "matted brown hair, ", 50, 115, 116, 50 }, +{ "white hair, ", 75, 115, 116, 50 }, +{ "a hairless head, ", 100, 115, 116, 50 }, +#endif + + +#ifdef JP +{ "燃える石炭のような瞳、", 25, 116, 117, 50 }, +{ "瞳のない目、", 50, 116, 117, 50 }, +{ "凶暴な黄色い瞳、", 75, 116, 117, 50 }, +{ "血走った赤い瞳、", 100, 116, 117, 50 }, + +{ "そして死人のように青ざめた肌をしています。", 100, 117, 0, 50 }, +#else +{ "eyes like red coals, ", 25, 116, 117, 50 }, +{ "blank white eyes, ", 50, 116, 117, 50 }, +{ "feral yellow eyes, ", 75, 116, 117, 50 }, +{ "bloodshot red eyes, ", 100, 116, 117, 50 }, + +{ "and a deathly pale complexion.", 100, 117, 0, 50 }, +#endif + + +#ifdef JP +{ "あなたは", 100, 118, 119, 50 }, + +{ "死霊術士により作り出されました。", 30, 119, 134, 50 }, +{ "魔法の実験により作り出されました。", 50, 119, 134, 50 }, +{ "邪悪な僧侶により作り出されました。", 70, 119, 134, 50 }, +{ "悪魔との契約により生み出されました。", 75, 119, 134, 50 }, +{ "怨霊から生まれました。", 85, 119, 134, 50 }, +{ "呪いから生まれました。", 95, 119, 134, 30 }, +{ "神名濫用により生み出されました。", 100, 119, 134, 50 }, +#else +{ "You were created by ", 100, 118, 119, 50 }, + +{ "a Necromancer. ", 30, 119, 134, 50 }, +{ "a magical experiment. ", 50, 119, 134, 50 }, +{ "an Evil Priest. ", 70, 119, 134, 50 }, +{ "a pact with the demons. ", 75, 119, 134, 50 }, +{ "a restless spirit. ", 85, 119, 134, 50 }, +{ "a curse. ", 95, 119, 134, 30 }, +{ "an oath. ", 100, 119, 134, 50 }, +#endif + + +#ifdef JP +{ "漆黒の髪、", 25, 120, 121, 50 }, +{ "もつれたブラウンの髪、", 50, 120, 121, 50 }, +{ "白い髪、", 75, 120, 121, 50 }, +{ "髪のない頭、", 100, 120, 121, 50 }, +#else +{ "jet-black hair, ", 25, 120, 121, 50 }, +{ "matted brown hair, ", 50, 120, 121, 50 }, +{ "white hair, ", 75, 120, 121, 50 }, +{ "a hairless head, ", 100, 120, 121, 50 }, +#endif + + +#ifdef JP +{ "燃える石炭のような瞳、", 25, 121, 122, 50 }, +{ "瞳のない目、", 50, 121, 122, 50 }, +{ "凶暴な黄色い瞳、", 75, 121, 122, 50 }, +{ "血走った赤い瞳、", 100, 121, 122, 50 }, +#else +{ "eyes like red coals, ", 25, 121, 122, 50 }, +{ "blank white eyes, ", 50, 121, 122, 50 }, +{ "feral yellow eyes, ", 75, 121, 122, 50 }, +{ "bloodshot red eyes, ", 100, 121, 122, 50 }, +#endif + + +#ifdef JP +{ "そして死人のような土色の肌をしています。", 100, 122, 123, 50 }, +{ "あなたの周りには不気味な緑色のオーラがただよっています。", 100, 123, 0, 50 }, +#else +{ " and a deathly gray complexion. ", 100, 122, 123, 50 }, +{ "An eerie green aura surrounds you.", 100, 123, 0, 50 }, +#endif + + +#ifdef JP +{ "あなたの両親は", 100, 124, 125, 50 }, + +{ "ピクシーでした。", 20, 125, 126, 35 }, +{ "ニクシーでした。", 30, 125, 126, 25 }, +{ "森の妖精でした。", 75, 125, 126, 50 }, +{ "森の精霊でした。", 90, 125, 126, 75 }, +{ "妖精の貴族でした。", 100, 125, 126, 85 }, /*nuke me カタカナのほうがいいかも */ +#else +{ "Your parents were ", 100, 124, 125, 50 }, + +{ "pixies. ", 20, 125, 126, 35 }, +{ "nixies. ", 30, 125, 126, 25 }, +{ "wood sprites. ", 75, 125, 126, 50 }, +{ "wood spirits. ", 90, 125, 126, 75 }, +{ "noble faerie folk. ", 100, 125, 126, 85 }, +#endif + + +#ifdef JP +{ "あなたは背中にライトブルーの羽根が生えていて、", 100, 126, 127, 50 }, + +{ "なめらかな金髪、", 80, 127, 128, 50 }, +{ "波打った金髪、", 100, 127, 128, 50 }, + +{ "青い瞳、そして非常に生き生きとした肌をしています。", 100, 128, 0, 50 }, +#else +{ "You have light blue wings attached to your back, ", 100, 126, 127, 50 }, + +{ "straight blond hair, ", 80, 127, 128, 50 }, +{ "wavy blond hair, ", 100, 127, 128, 50 }, + +{ "blue eyes, and a very fair complexion.", 100, 128, 0, 50 }, +#endif + + +#ifdef JP +{ "あなたは魔法の実験により生み出されました。", 30, 129, 130, 40 }, +{ "あなたは子供時代、愚かにも純ログルスに頭を突っ込んでしまいました。", +50, 129, 130, 50 }, /*nuke me*/ +{ "あるカオスの魔王が遊びであなたを作り上げました。", +60, 129, 130, 60 }, +{ "あなたは魔法により掛け合わされた動物と人間の子供です。", 75, 129, 130, 50 }, +{ "あなたは言うもおぞましいカオスの生物の冒涜的な掛け合わせにより生まれました。", 100, 129, 130, 30 }, +#else +{ "You were produced by a magical experiment. ", 30, 129, 130, 40 }, +{ "In your childhood, you were stupid enough to stick your head in raw Logrus. ", +50, 129, 130, 50 }, +{ "A Demon Lord of Chaos decided to have some fun, and so he created you. ", +60, 129, 130, 60 }, +{ "You are the magical crossbreed of an animal and a man. ", 75, 129, 130, 50 }, +{ "You are the blasphemous crossbreed of unspeakable creatures of chaos. ", 100, 129, 130, 30 }, +#endif + + + +#ifdef JP +{ "あなたは緑色の爬虫類の目", 60, 130, 131, 50 }, +{ "あなたは黒い鳥の目", 85, 130, 131, 50 }, +{ "あなたはオレンジ色の猫の目", 99, 130, 131, 50 }, +{ "あなたは燃えるような悪魔の目", 100, 130, 131, 55 }, +#else +{ "You have green reptilian eyes, ", 60, 130, 131, 50 }, +{ "You have the black eyes of a bird, ", 85, 130, 131, 50 }, +{ "You have the orange eyes of a cat, ", 99, 130, 131, 50 }, +{ "You have the fiery eyes of a demon, ", 100, 130, 131, 55 }, +#endif + + +#ifdef JP + +{ "と髪のない頭を持ち、", 10, 131, 133, 50 }, +{ "をしていて、汚い", 33, 131, 132, 50 }, +{ "をしていて、みすぼらしい", 66, 131, 132, 50 }, +{ "をしていて、てかった", 100, 131, 132, 50 }, +#else +{ "no hair at all, ", 10, 131, 133, 50 }, +{ "dirty ", 33, 131, 132, 50 }, +{ "mangy ", 66, 131, 132, 50 }, +{ "oily ", 100, 131, 132, 50 }, +#endif + + +#ifdef JP + +{ "茶色の毛皮と", 33, 132, 133, 50 }, +{ "灰色の毛皮と", 66, 132, 133, 50 }, +{ "白い毛皮と", 100, 132, 133, 50 }, +#else +{ "brown fur, ", 33, 132, 133, 50 }, +{ "gray fur, ", 66, 132, 133, 50 }, +{ "albino fur, ", 100, 132, 133, 50 }, +#endif + + +#ifdef JP +{ "山羊の蹄があります。", 50, 133, 0, 50 }, +{ "人間の足が生えています。", 75, 133, 0, 50 }, +{ "鳥の足が生えています。", 85, 133, 0, 50 }, +{ "爬虫類の足が生えています。",90, 133, 0, 50 }, +{ "牛の足が生えています。", 95, 133, 0, 50 }, +{ "猫の足が生えています。", 97, 133, 0, 50 }, +{ "犬の足が生えています。", 100, 133, 0, 50 }, + +{ "あなたは", 100, 134, 120, 50 }, +#else +{ "and the hooves of a goat.", 50, 133, 0, 50 }, +{ "and human feet.", 75, 133, 0, 50 }, +{ "and bird's feet.", 85, 133, 0, 50 }, +{ "and reptilian feet.", 90, 133, 0, 50 }, +{ "and bovine feet.", 95, 133, 0, 50 }, +{ "and feline feet.", 97, 133, 0, 50 }, +{ "and canine feet.", 100, 133, 0, 50 }, + +{ "You have ", 100, 134, 120, 50 }, +#endif + + +#ifdef JP +{ "行方不明の子です。", 25, 138, 139, 40 }, +{ "さまよう子です。", 50, 138, 139, 50 }, +{ "唯一の子です。", 75, 138, 139, 60 }, +{ "愛されている子です。", 100, 138, 139, 70 }, +#else +{ "You are the lost offspring of ", 25, 137, 138, 40 }, +{ "You are the wandering offspring of ", 50, 137, 138, 50 }, +{ "You are the only offspring of ", 75, 137, 138, 60 }, +{ "You are the beloved offspring of ", 100, 137, 138, 70 }, +#endif + + +#ifdef JP +{ "あなたは名も知れぬエントの", 10, 137, 138, 35 }, +{ "あなたは孤独なエントの", 35, 137, 138, 50 }, +{ "あなたはエントの一団の一員の", 55, 137, 138, 60 }, +{ "あなたは繁栄しているエントの社会のリーダーの", 70, 137, 138, 70 }, +{ "あなたはエントの森の長の", 81, 137, 138, 80 }, +{ "あなたは尊敬されているエントの賢者の", 91, 137, 138, 90 }, +{ "あなたは今では追憶の中にしかいないエント女の", 96, 137, 138, 100 }, +{ "あなたはファンゴルンその人の", 100, 137, 138, 110 }, +#else +{ "an Ent whose name you have no recollection of. ", 10, 138, 139, 35 }, +{ "a solitary Ent. ", 35, 138, 139, 50 }, +{ "a member of a farflung Entish band. ", 55, 138, 139, 60 }, +{ "a leader of a prosperous community of Ents. ", 70, 138, 139, 70 }, +{ "an Entish Forestwarden. ", 81, 138, 139, 80 }, +{ "a respected Entish sage. ", 91, 138, 139, 90 }, +{ "an Entwife whose memory men cherish. ", 96, 138, 139, 100 }, +{ "Fangorn himself. ", 100, 138, 139, 110 }, +#endif + +#ifdef JP +{ "あなたは", 100, 139, 140, 50 }, +#else +{ "You have ", 100, 139, 140, 50 }, +#endif + +#ifdef JP +{ "三本の指を持ち、", 5, 140, 141, 50 }, +{ "四本の指を持ち、", 20, 140, 141, 50 }, +{ "五本の指を持ち、", 40, 140, 141, 50 }, +{ "六本の指を持ち、", 60, 140, 141, 50 }, +{ "七本の指を持ち、", 80, 140, 141, 50 }, +{ "八本の指を持ち、", 95, 140, 141, 50 }, +{ "九本の指を持ち、", 100, 140, 141, 50 }, +#else +{ "three fingers and toes, and are covered in ", 5, 140, 141, 50 }, +{ "four fingers and toes, and are covered in ", 20, 140, 141, 50 }, +{ "five fingers and toes, and are covered in ", 40, 140, 141, 50 }, +{ "six fingers and toes, and are covered in ", 60, 140, 141, 50 }, +{ "seven fingers and toes, and are covered in ", 80, 140, 141, 50 }, +{ "eight fingers and toes, and are covered in ", 95, 140, 141, 50 }, +{ "nine fingers and toes, and are covered in ", 100, 140, 141, 50 }, +#endif +#ifdef JP +{ "茶色い鱗状の肌に覆われています。", 10, 141, 0, 50 }, +{ "茶色の荒い肌に覆われています。", 20, 141, 0, 50 }, +{ "灰色のなめらかな肌に覆われています。", 30, 141, 0, 50 }, +{ "深いグリーンの肌に覆われています。", 40, 141, 0, 50 }, +{ "苔で覆われた肌をしています。", 50, 141, 0, 50 }, +{ "深いブラウンの肌に覆われています。", 60, 141, 0, 50 }, +{ "パールブラウンのパサパサの肌に覆われています。", 70, 141, 0, 50 }, +{ "チョコレート色の豊かな肌に覆われています。", 80, 141, 0, 50 }, +{ "黒い筋状の肌に覆われています。", 90, 141, 0, 50 }, +{ "ほとんどひからびた、厚い肌に覆われています。", 100, 141, 0, 50 }, +#else +{ "scaly brown skin.", 10, 141, 0, 50 }, +{ "rough brown skin.", 20, 141, 0, 50 }, +{ "smooth grey skin.", 30, 141, 0, 50 }, +{ "dark green skin.", 40, 141, 0, 50 }, +{ "mossy skin.", 50, 141, 0, 50 }, +{ "deep brown skin.", 60, 141, 0, 50 }, +{ "pale brown, flaky skin.", 70, 141, 0, 50 }, +{ "rich chocolate-colored skin.", 80, 141, 0, 50 }, +{ "ridged black skin.", 90, 141, 0, 50 }, +{ "thick, almost corky skin.", 100, 141, 0, 50 }, +#endif + +#ifdef JP +{ "あなたは天界の主人です。", 100, 142, 143, 80 }, +{ "あなたは悪を滅ぼすためにこの地に送られてきました。", 100, 143, 144, 80 }, +{ "この目的を成し遂げるまでは休むことは許されません。", 100, 144, 0, 80 }, +#else +{ "You are of the blessed host of heaven. ", 100, 142, 143, 80 }, +{ "You have been sent to earth to eradicate the wicked, ", 100, 143, 144, 80 }, +{ "and shall not rest until you have succeeded.", 100, 144, 0, 80 }, +#endif + +#ifdef JP +{ "あなたは地獄の呪われた子です。", 100, 145, 146, 20 }, +{ "あなたはグレーター・デーモンの気まぐれによって生まれました。", 100, 146, 147, 20 }, +{ "あなたは復讐の機会をうかがっています。", 100, 147, 0, 20 }, +#else +{ "You are of the cursed spawn of hell. ", 100, 145, 146, 20 }, +{ "You have been cast out by the whim of the greater demons, ", 100, 146, 147, 20 }, +{ "and now seek revenge.", 100, 147, 0, 20 }, +#endif + + + +#ifdef JP +{ "あなたは素性の知れない", 5, 148, 149, 25 }, +{ "あなたは捕虜の", 20, 148, 149, 35 }, +{ "あなたは戦士の", 40, 148, 149, 45 }, +{ "あなたはレンジャーの", 50, 148, 149, 50 }, +{ "あなたは書記の", 70, 148, 149, 65 }, +{ "あなたは魔女の", 83, 148, 149, 75 }, +{ "あなたは錬金術師の", 93, 148, 149, 90 }, +{ "あなたは貴族の女性の", 98, 148, 149, 110 }, +{ "あなたは女王の", 100, 148, 149, 140 }, +#else +{ "whose identity you are uncertain of.", 5, 149, 8, 25 }, +{ "Captive. ", 20, 149, 150, 35 }, +{ "Fighter. ", 40, 149, 150, 45 }, +{ "Ranger. ", 50, 149, 150, 50 }, +{ "Scribe. ", 70, 149, 150, 65 }, +{ "Witch. ", 83, 149, 150, 75 }, +{ "Alchemist. ", 93, 149, 150, 90 }, +{ "Lady. ", 98, 149, 150, 110 }, +{ "Queen. ", 100, 149, 150, 140 }, +#endif +#ifdef JP +{ "影フェアリーの私生児です。", 10, 149, 150, 35 }, +{ "影フェアリーの幾人かの子供のうちの一人です。", 30, 149, 150, 45 }, +{ "影フェアリーの第二子です。", 55, 149, 150, 50 }, +{ "影フェアリーの長子です。", 80, 149, 150, 55 }, +{ "影フェアリーの一粒種です。", 100, 149, 150, 60 }, +#else +{ "You are the bastard child of a Shadow-Fairy ", 10, 148, 149, 35 }, +{ "You are one of several children of a Shadow-Fairy ", 30, 148, 149, 45 }, +{ "You are the second child of a Shadow-Fairy ", 55, 148, 149, 50 }, +{ "You are the first child of a Shadow-Fairy ", 80, 148, 149, 55 }, +{ "You are the only child of a Shadow-Fairy ", 100, 148, 149, 60 }, +#endif + + +#ifdef JP +{ "あなたは黒い瞳と", 10, 150, 151, 50 }, +{ "あなたは深いブラウンの瞳と", 25, 50, 151, 50 }, +{ "あなたはブラウンの瞳と", 60, 150, 151, 50 }, +{ "あなたは淡い色の瞳と", 70, 150, 151, 50 }, +{ "あなたはグリーンの瞳と", 80, 150, 151, 50 }, +{ "あなたは青い瞳と", 90, 150, 151, 50 }, +{ "あなたはブルーグレイの瞳と", 100, 150, 151, 50 }, +#else +{ "You have black eyes, straight ", 10, 150, 151, 50 }, +{ "You have dark brown eyes, straight ", 25, 50, 151, 50 }, +{ "You have brown eyes, straight ", 60, 150, 151, 50 }, +{ "You have hazel eyes, straight ", 70, 150, 151, 50 }, +{ "You have green eyes, straight ", 80, 150, 151, 50 }, +{ "You have blue eyes, straight ", 90, 150, 151, 50 }, +{ "You have blue-gray eyes, straight ", 100, 150, 151, 50 }, +#endif + +#ifdef JP +{ "グレーの髪を持ち、", 30, 152, 153, 50 }, +{ "純白の髪を持ち、", 70, 152, 153, 50 }, +{ "パールイエローの髪を持ち、", 80, 152, 153, 50 }, +{ "白がかった灰色の髪を持ち、", 90, 152, 153, 50 }, +{ "パールブラウンの髪を持ち、", 100, 152, 153, 50 }, +#else +{ "grey hair ", 30, 151, 152, 50 }, +{ "pure white hair ", 70, 151, 152, 50 }, +{ "pale yellow hair ", 80, 151, 152, 50 }, +{ "grey-white hair ", 90, 151, 152, 50 }, +{ "pale brown hair ", 100, 151, 152, 50 }, +#endif + +#ifdef JP +{ "わずかに肩にかかるくらいのなめらかな", 30, 151, 152, 50 }, +{ "腕まで届くくらいのなめらかな", 60, 151, 152, 55 }, +{ "腰まであるなめらかな", 90, 151, 152, 60 }, +{ "頭から足まで輝く滝のようになめらかな", 100, 151, 152, 75 }, +#else +{ "that barely covers your shoulders, ", 30, 152, 153, 50 }, +{ "that reaches to your arms, ", 60, 152, 153, 55 }, +{ "that flows down to your waist, ", 90, 152, 153, 60 }, +{ "that forms a shining waterfall from head to foot, ", 100, 152, 153, 75 }, +#endif + +#ifdef JP +{ "透き通るような白い肌をしています。", 20, 153, 0, 50 }, +{ "ミルク色の肌をしています。", 35, 153, 0, 50 }, +{ "真珠色の肌をしています。", 50, 153, 0, 50 }, +{ "青白い肌をしています。", 85, 153, 0, 50 }, +{ "白い肌をしています。", 100, 153, 0, 50 }, +#else +{ "and an extremely fair complexion.", 20, 153, 0, 50 }, +{ "and a milky complexion.", 35, 153, 0, 50 }, +{ "and a pearly complexion.", 50, 153, 0, 50 }, +{ "and a pale complexion.", 85, 153, 0, 50 }, +{ "and an utterly white complexion.", 100, 153, 0, 50 }, +#endif + +#ifdef JP +{ "あなたは普段ザクザクデザートで遊んでいる、", 4, 154, 159, 50 }, +{ "あなたは普段グラグラタワーで遊んでいる、", 8, 154, 159, 50 }, +{ "あなたは普段ホヘホヘ峡谷で遊んでいる、", 12, 154, 159, 50 }, +{ "あなたは普段ドプドプ池で遊んでいる、", 16, 154, 159, 50 }, +{ "あなたは普段テクテク雑技場で遊んでいる、", 20, 154, 159, 50 }, +{ "あなたは普段フムフム畑で遊んでいる、", 24, 154, 159, 50 }, +{ "あなたは普段クノクノ滝で遊んでいる、", 28, 154, 159, 50 }, +{ "あなたは普段クリクリ川で遊んでいる、", 32, 154, 159, 50 }, +{ "あなたは普段テリテリキャンプ場で遊んでいる、", 36, 154, 159, 50 }, +{ "あなたは普段クター像前で遊んでいる、", 40, 154, 159, 50 }, +{ "あなたは普段テクノ湯で遊んでいる、", 44, 154, 159, 50 }, +{ "あなたは普段テクノアイランドで遊んでいる、", 48, 154, 159, 50 }, +{ "あなたは普段テクノマリンで遊んでいる、", 52, 154, 159, 50 }, +{ "あなたは普段テクノドームで遊んでいる、", 56, 154, 159, 50 }, +{ "あなたは普段テクノホールで遊んでいる、", 60, 154, 159, 50 }, +{ "あなたは普段テクノ高原で遊んでいる、", 64, 154, 159, 50 }, +{ "あなたは普段テクノ市民会館で遊んでいる、", 68, 154, 159, 50 }, +{ "あなたは普段テクノ公園で遊んでいる、", 72, 154, 159, 50 }, +{ "あなたは普段スイスイアルプスで遊んでいる、", 76, 154, 159, 65 }, +{ "あなたは普段ヒソヒソ森で遊んでいる、", 80, 154, 159, 65 }, +{ "あなたは普段テクノ生態研究所で遊んでいる、", 84, 154, 159, 65 }, +{ "あなたは普段テクノロケット発射台で遊んでいる、", 88, 154, 159, 65 }, +{ "あなたは普段チャイナウォールで遊んでいる、", 92, 154, 159, 65 }, +{ "あなたは普段スペースウォールで遊んでいる、", 96, 154, 159, 70 }, +{ "あなたは普段テクノリゾートホテルで遊んでいる、", 100, 154, 159, 75 }, + +{ "普通のクターです。", 70, 159, 160, 50 }, +{ "みんなが頼りにしている親クターです。", 85, 159, 160, 65 }, +{ "笹が大好物なパンダクターです。", 92, 159, 161, 75 }, +{ "とても珍しいトラクターです。", 96, 159, 162, 80 }, +{ "とても珍しいピカクターです。", 100, 159, 163, 90 }, + +{ "あなたは赤色の毛をもち、", 6, 160, 164, 50 }, +{ "あなたはクリーム色の毛をもち、", 12, 160, 164, 50 }, +{ "あなたは黄土色の毛をもち、", 18, 160, 164, 50 }, +{ "あなたは黄色の毛をもち、", 24, 160, 164, 50 }, +{ "あなたは黄緑色の毛をもち、", 30, 160, 164, 50 }, +{ "あなたは抹茶色の毛をもち、", 36, 160, 164, 50 }, +{ "あなたは濃い緑色の毛をもち、", 42, 160, 164, 50 }, +{ "あなたは青緑色の毛をもち、", 48, 160, 164, 50 }, +{ "あなたは水色の毛をもち、", 54, 160, 164, 50 }, +{ "あなたは薄い紫色の毛をもち、", 60, 160, 164, 50 }, +{ "あなたは紫色の毛をもち、", 65, 160, 164, 50 }, +{ "あなたは茜色の毛をもち、", 70, 160, 164, 60 }, +{ "あなたはピンク色の毛をもち、", 75, 160, 164, 60 }, +{ "あなたは白色の毛をもち、", 80, 160, 164, 60 }, +{ "あなたは青色の毛をもち、", 85, 160, 164, 65 }, +{ "あなたは黒色の毛をもち、", 90, 160, 164, 65 }, +{ "あなたは緑色の毛をもち、", 95, 160, 164, 65 }, +{ "あなたは橙色の毛をもち、", 100, 160, 164, 70 }, +{ "あなたはパンダのような白と黒の斑模様の毛をもち、", 100, 161, 164, 70 }, +{ "あなたはトラのような黄と黒の縞模様の毛をもち、", 100, 162, 164, 70 }, +{ "あなたは明るく輝いていて、", 100, 163, 164, 70 }, + +{ "マフラーを宝物にしています。", 4, 164, 0, 50 }, +{ "ライターを宝物にしています。", 8, 164, 0, 50 }, +{ "リモコンを宝物にしています。", 12, 164, 0, 50 }, +{ "手ぬぐいを宝物にしています。", 16, 164, 0, 50 }, +{ "牛乳ビンを宝物にしています。", 20, 164, 0, 50 }, +{ "ビンのふたを宝物にしています。", 24, 164, 0, 50 }, +{ "野球帽を宝物にしています。", 28, 164, 0, 50 }, +{ "浮き輪を宝物にしています。", 32, 164, 0, 50 }, +{ "バットを宝物にしています。", 36, 164, 0, 50 }, +{ "大根を宝物にしています。", 40, 164, 0, 50 }, +{ "リュックサックを宝物にしています。", 44, 164, 0, 50 }, +{ "将棋盤を宝物にしています。", 48, 164, 0, 50 }, +{ "将棋の駒を宝物にしています。", 52, 164, 0, 50 }, +{ "傘を宝物にしています。", 56, 164, 0, 50 }, +{ "やかんを宝物にしています。", 60, 164, 0, 50 }, +{ "ほうきを宝物にしています。", 64, 164, 0, 50 }, +{ "ティッシュ箱を宝物にしています。", 68, 164, 0, 50 }, +{ "ダルマを宝物にしています。", 71, 164, 0, 50 }, +{ "ニンジンを宝物にしています。", 75, 164, 0, 60 }, +{ "ホルンを宝物にしています。", 79, 164, 0, 60 }, +{ "みかん箱を宝物にしています。", 83, 164, 0, 60 }, +{ "宝箱を宝物にしています。", 86, 164, 0, 60 }, +{ "テンガロンハットを宝物にしています。", 90, 164, 0, 60 }, +{ "アフロを宝物にしています。", 94, 164, 0, 65 }, +{ "しゃけを宝物にしています。", 97, 164, 0, 65 }, +{ "39ボウヤを宝物にしています。", 100, 164, 0, 70 }, + +#else +{ "You are a normal Kutar. You have orange colored fur.", 65, 154, 0, 55 }, +{ "You are a father Kutar, the patriarch of many normal Kutars. You have green colored fur.", 95, 154, 0, 65 }, +{ "You are a very rare type of Kutar, famed for the yellow and black stripes on your body.", 100, 154, 0, 80 }, +#endif + +#ifdef JP +{ "あなたはあるプロジェクトの試作品として", 10, 155, 156, 50 }, +{ "あなたは子供を教育するために", 30, 155, 156, 60 }, +{ "あなたは身の回りの世話をするために", 50, 155, 156, 70 }, +{ "あなたは亡くなった子供の身代わりとして", 60, 155, 156, 10 }, +{ "あなたは戦闘用アンドロイドとして", 90, 155, 156, 20 }, +{ "あなたは世界征服のための道具として", 100, 155, 156, 10 }, + +{ "気の狂った科学者によって作られました。", 20, 156, 157, 10 }, +{ "企業の研究所で作られました。", 50, 156, 157, 80 }, +{ "平和を願う科学者によって作られました。", 85, 156, 157, 50 }, +{ "一人の天才少年によって作られました。", 90, 156, 157, 30 }, +{ "22世紀からやって来ました。", 100, 156, 157, 100 }, + +{ "ネコのような形をして", 15, 157, 158, 40 }, +{ "イヌのような形をして", 30, 157, 158, 30 }, +{ "クターのような形をして", 45, 157, 158, 20 }, +{ "人間のような形をして", 70, 157, 158, 60 }, +{ "ドワーフのような形をして", 80, 157, 158, 70 }, +{ "ホビットのような形をして", 90, 157, 158, 70 }, +{ "エルフのような形をして", 100, 157, 158, 80 }, + +{ "いますが、耳はネズミにかじられてなくなっています。", 5, 158, 0, 20 }, +{ "いると作者は主張していますが、とてもそうは見えません。", 20, 158, 0, 30 }, +{ "います。", 85, 158, 0, 50 }, +{ "いて、本人は自分のことを本物だと信じています。", 95, 158, 0, 50 }, +{ "いて、非常によくできているので本物と見分けがつきません。", 100, 158, 0, 100 }, +#else +{ "You were created by a mad scientist ", 20, 155, 156, 10 }, +{ "You were created in a corporate laboratory ", 50, 155, 156, 80 }, +{ "You were created by a peace-loving scientist ", 85, 155, 156, 50 }, +{ "You were created by a boy genius ", 90, 155, 156, 30 }, +{ "You have come from the twenty-second century ", 100, 155, 156, 100 }, + +{ "as a project prototype. ", 10, 156, 157, 50 }, +{ "to educate children. ", 30, 156, 157, 60 }, +{ "to look after someone. ", 50, 156, 157, 70 }, +{ "as a substitute for a dead child. ", 60, 156, 157, 10 }, +{ "as a combat trooper. ", 90, 156, 157, 20 }, +{ "as a tool for conquest of the world. ", 100, 156, 157, 10 }, + +{ "You have a cat-like appearance", 15, 157, 158, 40 }, +{ "You have a dog-like appearance", 30, 157, 158, 30 }, +{ "You have a Kutar-like appearance", 45, 157, 158, 20 }, +{ "You have a human-like appearance", 70, 157, 158, 60 }, +{ "You have a dwarf-like appearance", 80, 157, 158, 70 }, +{ "You have a hobbit-like appearance", 90, 157, 158, 70 }, +{ "You have a elf-like appearance", 100, 157, 158, 80 }, + +{ ", but your ears have been eaten by mice, and no trace of them remains.", 5, 158, 0, 20 }, +{ "... at least your creator thinks so. Most people disagree.", 20, 158, 0, 30 }, +{ ".", 85, 158, 0, 50 }, +{ ", and you firmly believe that you are a real one.", 95, 158, 0, 50 }, +{ ", and you are almost indistinguishable from a real one.", 100, 158, 0, 100 }, +#endif + +#ifdef JP +{ "あなたはマーフォークの乞食の", 5, 170, 171, 30 }, +{ "あなたはマーフォークの物あさりの", 10, 170, 171, 50 }, +{ "あなたはマーフォークのペテン師の", 15, 170, 171, 70 }, +{ "あなたはマーフォークの平民の", 60, 170, 171, 90 }, +{ "あなたは川守りの", 70, 170, 171, 80 }, +{ "あなたはメロウの", 80, 170, 171, 80 }, +{ "あなたはセルキーの", 85, 170, 171, 80 }, +{ "あなたはトリトンの", 90, 170, 171, 80 }, +{ "あなたはマーフォークの交易商人の", 95, 170, 171, 100 }, +{ "あなたはマーフォークの君主の", 100, 170, 171, 130 }, +{ "何人かの子供のうちの一人です。", 80, 171, 172, 45 }, +{ "一粒種です。", 100, 171, 172, 55 }, +#else +{ "a Merfolk Begger. ", 5 , 171, 172, 30 }, +{ "a Merfolk Looter. ", 10, 171, 172, 50 }, +{ "a Merfolk Trickster. ", 15, 171, 172, 70 }, +{ "a Merfolk Citizen. ", 60, 171, 172, 90 }, +{ "a River Herald. ", 70, 171, 172, 80 }, +{ "a Merrow. ", 80, 171, 172, 80 }, +{ "a Selkie. ", 85, 171, 172, 80 }, +{ "a Triton. ", 90, 171, 172, 80 }, +{ "a Merfolk Traders. ", 95, 171, 172, 100 }, +{ "a Merfolk Sovereign. ", 100, 171, 172, 130 }, +{ "You are one of several children of ", 80, 170, 171, 45 }, +{ "You are the only child of ", 100, 170, 171, 55 }, +#endif + +#ifdef JP +{ "あなたの下半身は一本の尾で、", 50, 172, 173, 50}, +{ "あなたの下半身は二股の尾で、", 60, 172, 173, 50}, +{ "あなたの下半身は陸上の種族とあまり変わりなく、", 100, 172, 173, 50 }, +#else +{ "Your lower body is a tail, ", 50, 172, 173, 50 }, +{ "Your lower body are two tails, ", 60, 172, 173, 50 }, +{ "Your lower body is not much different from a land race, ", 100, 172, 173, 50 }, +#endif + + +#ifdef JP +{ "全身のほとんどが鱗に覆われています。", 20, 173, 174, 50 }, +{ "主に上半身が鱗に覆われています。", 30, 173, 174, 50 }, +{ "主に下半身が鱗に覆われています。", 40, 173, 174, 50 }, +{ "全身の半分が鱗に覆われています。", 60, 173, 174, 50 }, +{ "全身のいくらかが鱗に覆われています。", 80, 173, 174, 50 }, +{ "鱗はほとんど見られません。", 100, 173, 174, 50 }, +#else +{ "and most of your whole body is covered with scales. ", 20, 173, 174, 50 }, +{ "and mainly your upper body is covered with scales. ", 30, 173, 174, 50 }, +{ "and mainly your lower body is covered with scales. ", 40, 173, 174, 50 }, +{ "and half of your body is covered with scales. ", 60, 173, 174, 50 }, +{ "and some of your body is covered with scales. ", 80, 173, 174, 50 }, +{ "and there are few scales on your body. ", 100, 173, 174, 50 }, + +#endif + +#ifdef JP +{ "あなたは黒の瞳と", 20, 174, 175, 50 }, +{ "あなたは緑の瞳と", 40, 174, 175, 50 }, +{ "あなたは黄色い瞳と", 60, 174, 175, 50 }, +{ "あなたは青い瞳と", 80, 174, 175, 50 }, +{ "あなたは赤い瞳と", 100, 174, 175, 50 }, +#else +{ "You have black eyes, ", 20, 174, 175, 50 }, +{ "You have green eyes, ", 40, 174, 175, 50 }, +{ "You have yellow eyes, ", 60, 174, 175, 50 }, +{ "You have blue eyes, ", 80, 174, 175, 50 }, +{ "You have red eyes, ", 100, 174, 175, 55 }, +#endif + +#ifdef JP +{ "海藻の様な髪を持っています。", 25, 175, 0, 50 }, +{ "珊瑚のような角を持っています。", 50, 175, 0, 50 }, +{ "地上人に似た髪を持っています。", 75, 175, 0, 50 }, +{ "大きく発達した鰓を持っています。", 100, 175, 0, 50 }, +#else +{ "hair like seaweed.", 25, 175, 0, 50 }, +{ "coral-like horns.", 50, 175, 0, 50 }, +{ "hair similar to land races.", 75, 175, 0, 50 }, +{ "large gills.", 100, 175, 0, 50 }, +#endif + +}; diff --git a/src/birth/history.h b/src/birth/history.h new file mode 100644 index 000000000..4b367a269 --- /dev/null +++ b/src/birth/history.h @@ -0,0 +1,17 @@ +#include "system/angband.h" + +/*! +* 生い立ちメッセージテーブルの構造体定義 / Player background information +*/ +typedef struct hist_type { + concptr info; /*!> メッセージ本文 / Textual History */ + + byte roll; /*!> 確率の重み / Frequency of this entry */ + byte chart; /*!> 生い立ちメッセージの流れを示すチャートID / Chart index */ + byte next; /*!> 次のチャートID */ + byte bonus; /*!> メッセージに伴う社会的地位の変化量(50が基準値) / Social Class Bonus + 50 */ +} hist_type; + +#define MAX_BACKGROUNDS 593 + +extern hist_type bg[MAX_BACKGROUNDS]; diff --git a/src/birth/initial-equipments-table.c b/src/birth/initial-equipments-table.c new file mode 100644 index 000000000..a3d0393d2 --- /dev/null +++ b/src/birth/initial-equipments-table.c @@ -0,0 +1,174 @@ +#include "birth/initial-equipments-table.h" +#include "object/tval-types.h" +#include "sv-definition/sv-armor-types.h" +#include "sv-definition/sv-bow-types.h" +#include "sv-definition/sv-food-types.h" +#include "sv-definition/sv-potion-types.h" +#include "sv-definition/sv-ring-types.h" +#include "sv-definition/sv-scroll-types.h" +#include "sv-definition/sv-wand-types.h" +#include "sv-definition/sv-weapon-types.h" + +/*! + * プレイヤーの職業毎の初期装備テーブル。/\n + * Each player starts out with a few items, given as tval/sval pairs.\n + * In addition, he always has some food and a few torches.\n + */ +byte player_init[MAX_CLASS][3][2] = { + { /* Warrior */ + { TV_RING, SV_RING_RES_FEAR }, + { TV_HARD_ARMOR, SV_CHAIN_MAIL }, + { TV_SWORD, SV_BROAD_SWORD } }, + + { /* Mage */ + { TV_SORCERY_BOOK, 0 }, + { TV_DEATH_BOOK, 0 }, + { TV_SWORD, SV_DAGGER } }, + + { /* Priest */ + { TV_SORCERY_BOOK, 0 }, + { TV_DEATH_BOOK, 0 }, + { TV_HAFTED, SV_MACE } }, + + { /* Rogue */ + { TV_SORCERY_BOOK, 0 }, + { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, + { TV_SWORD, SV_DAGGER } }, + + { /* Ranger */ + { TV_NATURE_BOOK, 0 }, + { TV_DEATH_BOOK, 0 }, + { TV_SWORD, SV_DAGGER } }, + + { /* Paladin */ + { TV_SORCERY_BOOK, 0 }, + { TV_SCROLL, SV_SCROLL_PROTECTION_FROM_EVIL }, + { TV_SWORD, SV_BROAD_SWORD } }, + + { /* Warrior-Mage */ + { TV_SORCERY_BOOK, 0 }, + { TV_DEATH_BOOK, 0 }, + { TV_SWORD, SV_SHORT_SWORD } }, + + { /* Chaos Warrior */ + { TV_SORCERY_BOOK, 0 }, + { TV_HARD_ARMOR, SV_METAL_SCALE_MAIL }, + { TV_SWORD, SV_BROAD_SWORD } }, + + { /* Monk */ + { TV_SORCERY_BOOK, 0 }, + { TV_POTION, SV_POTION_SPEED }, + { TV_POTION, SV_POTION_HEROISM } }, + + { /* Mindcrafter */ + { TV_POTION, SV_POTION_SPEED }, + { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, + { TV_SWORD, SV_SMALL_SWORD } }, + + { /* High Mage */ + { TV_SORCERY_BOOK, 0 }, + { TV_RING, SV_RING_SUSTAIN_INT }, + { TV_SWORD, SV_DAGGER } }, + + { /* Tourist */ + { TV_FOOD, SV_FOOD_JERKY }, + { TV_SCROLL, SV_SCROLL_MAPPING }, + { TV_BOW, SV_SLING } }, + + { /* Imitator */ + { TV_POTION, SV_POTION_SPEED }, + { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, + { TV_SWORD, SV_SHORT_SWORD } }, + + { /* Beastmaster */ + { TV_TRUMP_BOOK, 0 }, + { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, + { TV_POLEARM, SV_SPEAR } }, + + { /* Sorcerer */ + { TV_HAFTED, SV_WIZSTAFF }, + { TV_RING, SV_RING_SUSTAIN_INT }, + { TV_WAND, SV_WAND_MAGIC_MISSILE } }, + + { + /* Archer */ + { TV_BOW, SV_SHORT_BOW }, + { TV_SOFT_ARMOR, SV_LEATHER_SCALE_MAIL }, + { TV_SWORD, SV_SHORT_SWORD }, + }, + + { + /* Magic eater */ + { TV_WAND, SV_WAND_MAGIC_MISSILE }, + { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, + { TV_SWORD, SV_SHORT_SWORD }, + }, + + { + /* Bard */ + { TV_MUSIC_BOOK, 0 }, + { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, + { TV_SWORD, SV_SHORT_SWORD }, + }, + + { + /* Red Mage */ + { TV_ARCANE_BOOK, 0 }, + { TV_SOFT_ARMOR, SV_HARD_LEATHER_ARMOR }, + { TV_SWORD, SV_SHORT_SWORD }, + }, + + { /* Samurai */ + { TV_HISSATSU_BOOK, 0 }, + { TV_HARD_ARMOR, SV_CHAIN_MAIL }, + { TV_SWORD, SV_BROAD_SWORD } + }, + + { /* ForceTrainer */ + { TV_SORCERY_BOOK, 0 }, + { TV_POTION, SV_POTION_SPEED }, + { TV_POTION, SV_POTION_RESTORE_MANA } + }, + + { /* Blue Mage */ + { TV_SOFT_ARMOR, SV_ROBE }, + { TV_WAND, SV_WAND_MAGIC_MISSILE }, + { TV_SWORD, SV_DAGGER } + }, + + { /* Cavalry */ + { TV_BOW, SV_SHORT_BOW }, + { TV_SOFT_ARMOR, SV_LEATHER_SCALE_MAIL }, + { TV_POLEARM, SV_BROAD_SPEAR } + }, + + { /* Berserker */ + { TV_POTION, SV_POTION_HEALING }, + { TV_HARD_ARMOR, SV_AUGMENTED_CHAIN_MAIL }, + { TV_POLEARM, SV_BROAD_AXE } + }, + + { /* Weaponsmith */ + { TV_RING, SV_RING_RES_FEAR }, + { TV_HARD_ARMOR, SV_CHAIN_MAIL }, + { TV_POLEARM, SV_BROAD_AXE } + }, + + { /* Mirror-Master */ + { TV_POTION, SV_POTION_SPEED }, + { TV_RING, SV_RING_SUSTAIN_INT }, + { TV_SWORD, SV_DAGGER } + }, + + { /* Ninja */ + { TV_POTION, SV_POTION_SPEED }, + { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, + { TV_SWORD, SV_DAGGER } + }, + + { /* Sniper */ + { TV_BOW, SV_LIGHT_XBOW }, + { TV_SOFT_ARMOR, SV_SOFT_LEATHER_ARMOR }, + { TV_SWORD, SV_DAGGER } + }, +}; diff --git a/src/birth/initial-equipments-table.h b/src/birth/initial-equipments-table.h new file mode 100644 index 000000000..2d0bef76f --- /dev/null +++ b/src/birth/initial-equipments-table.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +extern byte player_init[MAX_CLASS][3][2]; diff --git a/src/birth/inventory-initializer.c b/src/birth/inventory-initializer.c new file mode 100644 index 000000000..dfdadba3b --- /dev/null +++ b/src/birth/inventory-initializer.c @@ -0,0 +1,269 @@ +#include "birth/inventory-initializer.h" +#include "autopick/autopick.h" +#include "birth/initial-equipments-table.h" +#include "floor/floor-object.h" +#include "inventory/inventory-object.h" +#include "inventory/inventory-slot-types.h" +#include "monster-race/monster-race-hook.h" +#include "monster/monster-list.h" +#include "monster/monster-util.h" +#include "object-enchant/apply-magic.h" +#include "object-enchant/item-apply-magic.h" +#include "object-enchant/object-ego.h" +#include "perception/object-perception.h" +#include "object/object-generator.h" +#include "object/object-kind-hook.h" +#include "object/object-kind.h" +#include "object/object-info.h" +#include "player/player-personalities-types.h" +#include "player/player-race-types.h" +#include "realm/realm-types.h" +#include "sv-definition/sv-bow-types.h" +#include "sv-definition/sv-food-types.h" +#include "sv-definition/sv-lite-types.h" +#include "sv-definition/sv-other-types.h" +#include "sv-definition/sv-potion-types.h" +#include "sv-definition/sv-ring-types.h" +#include "sv-definition/sv-scroll-types.h" +#include "sv-definition/sv-staff-types.h" +#include "sv-definition/sv-wand-types.h" +#include "sv-definition/sv-weapon-types.h" + +/*! + * @brief 所持状態にあるアイテムの中から一部枠の装備可能なものを装備させる。 + * @return なし + */ +void wield_all(player_type *creature_ptr) +{ + object_type object_type_body; + for (INVENTORY_IDX item = INVEN_PACK - 1; item >= 0; item--) { + object_type *o_ptr; + o_ptr = &creature_ptr->inventory_list[item]; + if (!o_ptr->k_idx) + continue; + + int slot = wield_slot(creature_ptr, o_ptr); + if (slot < INVEN_RARM) + continue; + if (slot == INVEN_LITE) + continue; + if (creature_ptr->inventory_list[slot].k_idx) + continue; + + object_type *i_ptr; + i_ptr = &object_type_body; + object_copy(i_ptr, o_ptr); + i_ptr->number = 1; + + if (item >= 0) { + inven_item_increase(creature_ptr, item, -1); + inven_item_optimize(creature_ptr, item); + } else { + floor_item_increase(creature_ptr->current_floor_ptr, 0 - item, -1); + floor_item_optimize(creature_ptr, 0 - item); + } + + o_ptr = &creature_ptr->inventory_list[slot]; + object_copy(o_ptr, i_ptr); + creature_ptr->total_weight += i_ptr->weight; + creature_ptr->equip_cnt++; + } +} + +/*! + * @brief 初期所持アイテムの処理 / Add an outfit object + * @details アイテムを既知のものとした上でwield_all()関数により装備させる。 + * @param o_ptr 処理したいオブジェクト構造体の参照ポインタ + * @return なし + */ +void add_outfit(player_type *creature_ptr, object_type *o_ptr) +{ + object_aware(creature_ptr, o_ptr); + object_known(o_ptr); + s16b slot = store_item_to_inventory(creature_ptr, o_ptr); + autopick_alter_item(creature_ptr, slot, FALSE); + wield_all(creature_ptr); +} + +static void decide_initial_items(player_type *creature_ptr, object_type *q_ptr) +{ + switch (creature_ptr->prace) { + case RACE_VAMPIRE: + /* Nothing! */ + /* Vampires can drain blood of creatures */ + break; + case RACE_BALROG: + /* Demon can drain vitality from humanoid corpse */ + get_mon_num_prep(creature_ptr, monster_hook_human, NULL); + for (int i = rand_range(3, 4); i > 0; i--) { + object_prep(creature_ptr, q_ptr, lookup_kind(TV_CORPSE, SV_CORPSE)); + q_ptr->pval = get_mon_num(creature_ptr, 2, 0); + if (q_ptr->pval) { + q_ptr->number = 1; + add_outfit(creature_ptr, q_ptr); + } + } + + break; + case RACE_SKELETON: + case RACE_GOLEM: + case RACE_ZOMBIE: + case RACE_SPECTRE: + /* Staff (of Nothing) */ + object_prep(creature_ptr, q_ptr, lookup_kind(TV_STAFF, SV_STAFF_NOTHING)); + q_ptr->number = 1; + add_outfit(creature_ptr, q_ptr); + break; + case RACE_ENT: + /* Potions of Water */ + object_prep(creature_ptr, q_ptr, lookup_kind(TV_POTION, SV_POTION_WATER)); + q_ptr->number = (ITEM_NUMBER)rand_range(15, 23); + add_outfit(creature_ptr, q_ptr); + break; + case RACE_ANDROID: + /* Flasks of oil */ + object_prep(creature_ptr, q_ptr, lookup_kind(TV_FLASK, SV_ANY)); + apply_magic(creature_ptr, q_ptr, 1, AM_NO_FIXED_ART); + q_ptr->number = (ITEM_NUMBER)rand_range(7, 12); + add_outfit(creature_ptr, q_ptr); + break; + default: + /* Food rations */ + object_prep(creature_ptr, q_ptr, lookup_kind(TV_FOOD, SV_FOOD_RATION)); + q_ptr->number = (ITEM_NUMBER)rand_range(3, 7); + add_outfit(creature_ptr, q_ptr); + } +} + +/*! + * @brief 種族/職業/性格などに基づき初期所持アイテムを設定するメインセット関数。 / Init players with some belongings + * @details Having an item makes the player "aware" of its purpose. + * @return なし + */ +void player_outfit(player_type *creature_ptr) +{ + object_type *q_ptr; + object_type forge; + q_ptr = &forge; + + decide_initial_items(creature_ptr, q_ptr); + q_ptr = &forge; + + if ((creature_ptr->prace == RACE_VAMPIRE) && (creature_ptr->pclass != CLASS_NINJA)) { + object_prep(creature_ptr, q_ptr, lookup_kind(TV_SCROLL, SV_SCROLL_DARKNESS)); + q_ptr->number = (ITEM_NUMBER)rand_range(2, 5); + add_outfit(creature_ptr, q_ptr); + } else if (creature_ptr->pclass != CLASS_NINJA) { + object_prep(creature_ptr, q_ptr, lookup_kind(TV_LITE, SV_LITE_TORCH)); + q_ptr->number = (ITEM_NUMBER)rand_range(3, 7); + q_ptr->xtra4 = rand_range(3, 7) * 500; + + add_outfit(creature_ptr, q_ptr); + } + + q_ptr = &forge; + if (creature_ptr->prace == RACE_MERFOLK) { + object_prep(creature_ptr, q_ptr, lookup_kind(TV_RING, SV_RING_LEVITATION_FALL)); + q_ptr->number = 1; + add_outfit(creature_ptr, q_ptr); + } + + if ((creature_ptr->pclass == CLASS_RANGER) || (creature_ptr->pclass == CLASS_CAVALRY)) { + object_prep(creature_ptr, q_ptr, lookup_kind(TV_ARROW, SV_AMMO_NORMAL)); + q_ptr->number = (byte)rand_range(15, 20); + add_outfit(creature_ptr, q_ptr); + } + + if (creature_ptr->pclass == CLASS_RANGER) { + object_prep(creature_ptr, q_ptr, lookup_kind(TV_BOW, SV_SHORT_BOW)); + add_outfit(creature_ptr, q_ptr); + } else if (creature_ptr->pclass == CLASS_ARCHER) { + object_prep(creature_ptr, q_ptr, lookup_kind(TV_ARROW, SV_AMMO_NORMAL)); + q_ptr->number = (ITEM_NUMBER)rand_range(15, 20); + add_outfit(creature_ptr, q_ptr); + } else if (creature_ptr->pclass == CLASS_HIGH_MAGE) { + object_prep(creature_ptr, q_ptr, lookup_kind(TV_WAND, SV_WAND_MAGIC_MISSILE)); + q_ptr->number = 1; + q_ptr->pval = (PARAMETER_VALUE)rand_range(25, 30); + add_outfit(creature_ptr, q_ptr); + } else if (creature_ptr->pclass == CLASS_SORCERER) { + tval_type book_tval; + for (book_tval = TV_LIFE_BOOK; book_tval <= TV_LIFE_BOOK + MAX_MAGIC - 1; book_tval++) { + object_prep(creature_ptr, q_ptr, lookup_kind(book_tval, 0)); + q_ptr->number = 1; + add_outfit(creature_ptr, q_ptr); + } + } else if (creature_ptr->pclass == CLASS_TOURIST) { + if (creature_ptr->pseikaku != PERSONALITY_SEXY) { + object_prep(creature_ptr, q_ptr, lookup_kind(TV_SHOT, SV_AMMO_LIGHT)); + q_ptr->number = rand_range(15, 20); + add_outfit(creature_ptr, q_ptr); + } + + object_prep(creature_ptr, q_ptr, lookup_kind(TV_FOOD, SV_FOOD_BISCUIT)); + q_ptr->number = rand_range(2, 4); + + add_outfit(creature_ptr, q_ptr); + + object_prep(creature_ptr, q_ptr, lookup_kind(TV_FOOD, SV_FOOD_WAYBREAD)); + q_ptr->number = rand_range(2, 4); + + add_outfit(creature_ptr, q_ptr); + + object_prep(creature_ptr, q_ptr, lookup_kind(TV_FOOD, SV_FOOD_JERKY)); + q_ptr->number = rand_range(1, 3); + + add_outfit(creature_ptr, q_ptr); + + object_prep(creature_ptr, q_ptr, lookup_kind(TV_FOOD, SV_FOOD_PINT_OF_ALE)); + q_ptr->number = rand_range(2, 4); + + add_outfit(creature_ptr, q_ptr); + + object_prep(creature_ptr, q_ptr, lookup_kind(TV_FOOD, SV_FOOD_PINT_OF_WINE)); + q_ptr->number = rand_range(2, 4); + + add_outfit(creature_ptr, q_ptr); + } else if (creature_ptr->pclass == CLASS_NINJA) { + object_prep(creature_ptr, q_ptr, lookup_kind(TV_SPIKE, 0)); + q_ptr->number = rand_range(15, 20); + add_outfit(creature_ptr, q_ptr); + } else if (creature_ptr->pclass == CLASS_SNIPER) { + object_prep(creature_ptr, q_ptr, lookup_kind(TV_BOLT, SV_AMMO_NORMAL)); + q_ptr->number = rand_range(15, 20); + add_outfit(creature_ptr, q_ptr); + } + + if (creature_ptr->pseikaku == PERSONALITY_SEXY) { + player_init[creature_ptr->pclass][2][0] = TV_HAFTED; + player_init[creature_ptr->pclass][2][1] = SV_WHIP; + } + + for (int i = 0; i < 3; i++) { + tval_type tv = player_init[creature_ptr->pclass][i][0]; + OBJECT_SUBTYPE_VALUE sv = player_init[creature_ptr->pclass][i][1]; + if ((creature_ptr->prace == RACE_ANDROID) && ((tv == TV_SOFT_ARMOR) || (tv == TV_HARD_ARMOR))) + continue; + + if (tv == TV_SORCERY_BOOK) + tv = TV_LIFE_BOOK + creature_ptr->realm1 - 1; + else if (tv == TV_DEATH_BOOK) + tv = TV_LIFE_BOOK + creature_ptr->realm2 - 1; + else if (tv == TV_RING && sv == SV_RING_RES_FEAR && creature_ptr->prace == RACE_BARBARIAN) + sv = SV_RING_SUSTAIN_STR; + else if (tv == TV_RING && sv == SV_RING_SUSTAIN_INT && creature_ptr->prace == RACE_MIND_FLAYER) { + tv = TV_POTION; + sv = SV_POTION_RESTORE_MANA; + } + + q_ptr = &forge; + object_prep(creature_ptr, q_ptr, lookup_kind(tv, sv)); + if ((tv == TV_SWORD || tv == TV_HAFTED) + && (creature_ptr->pclass == CLASS_ROGUE && creature_ptr->realm1 == REALM_DEATH)) /* Only assassins get a poisoned weapon */ + q_ptr->name2 = EGO_BRAND_POIS; + + add_outfit(creature_ptr, q_ptr); + } + + k_info[lookup_kind(TV_POTION, SV_POTION_WATER)].aware = TRUE; +} diff --git a/src/birth/inventory-initializer.h b/src/birth/inventory-initializer.h new file mode 100644 index 000000000..4c0ba1cce --- /dev/null +++ b/src/birth/inventory-initializer.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +void wield_all(player_type *creature_ptr); +void add_outfit(player_type *creature_ptr, object_type *o_ptr); +void player_outfit(player_type *creature_ptr); diff --git a/src/birth/quick-start.c b/src/birth/quick-start.c new file mode 100644 index 000000000..76d1e1f2f --- /dev/null +++ b/src/birth/quick-start.c @@ -0,0 +1,152 @@ +#include "birth/quick-start.h" +#include "birth/birth-stat.h" +#include "birth/birth-util.h" +#include "birth/game-play-initializer.h" +#include "core/player-update-types.h" +#include "io/input-key-acceptor.h" +#include "player/player-class.h" +#include "player/player-personality.h" +#include "player/player-race.h" +#include "player/player-sex.h" +#include "player/process-name.h" +#include "player/race-info-table.h" +#include "term/screen-processor.h" + +/* + * The last character rolled, + * holded for quick start + */ +birther previous_char; + +/*! + * @brief クイックスタート処理の問い合わせと実行を行う。/Ask whether the player use Quick Start or not. + * @return なし + */ +bool ask_quick_start(player_type *creature_ptr) +{ + if (!previous_char.quick_ok) + return FALSE; + + term_clear(); + put_str(_("クイック・スタートを使うと以前と全く同じキャラクターで始められます。", + "Do you want to use the quick start function(same character as your last one)."), + 11, 2); + while (TRUE) { + char c; + put_str(_("クイック・スタートを使いますか?[y/N]", "Use quick start? [y/N]"), 14, 10); + c = inkey(); + if (c == 'Q') + quit(NULL); + else if (c == 'S') + return FALSE; + else if (c == '?') + show_help(creature_ptr, _("jbirth.txt#QuickStart", "birth.txt#QuickStart")); + else if ((c == 'y') || (c == 'Y')) + break; + else + return FALSE; + } + + load_prev_data(creature_ptr, FALSE); + init_turn(creature_ptr); + init_dungeon_quests(creature_ptr); + + sp_ptr = &sex_info[creature_ptr->psex]; + rp_ptr = &race_info[creature_ptr->prace]; + cp_ptr = &class_info[creature_ptr->pclass]; + mp_ptr = &m_info[creature_ptr->pclass]; + ap_ptr = &personality_info[creature_ptr->pseikaku]; + + get_extra(creature_ptr, FALSE); + creature_ptr->update |= (PU_BONUS | PU_HP); + update_creature(creature_ptr); + creature_ptr->chp = creature_ptr->mhp; + creature_ptr->csp = creature_ptr->msp; + process_player_name(creature_ptr, FALSE); + return TRUE; +} +/*! + * @brief プレイヤーのクイックスタート情報をプレイヤー構造体から保存する / Save the current data for later + * @param birther_ptr クイックスタート構造体の参照ポインタ + * @return なし。 + */ +void save_prev_data(player_type *creature_ptr, birther *birther_ptr) +{ + birther_ptr->psex = creature_ptr->psex; + birther_ptr->prace = creature_ptr->prace; + birther_ptr->pclass = creature_ptr->pclass; + birther_ptr->pseikaku = creature_ptr->pseikaku; + birther_ptr->realm1 = creature_ptr->realm1; + birther_ptr->realm2 = creature_ptr->realm2; + birther_ptr->age = creature_ptr->age; + birther_ptr->ht = creature_ptr->ht; + birther_ptr->wt = creature_ptr->wt; + birther_ptr->sc = creature_ptr->sc; + birther_ptr->au = creature_ptr->au; + + for (int i = 0; i < A_MAX; i++) { + birther_ptr->stat_max[i] = creature_ptr->stat_max[i]; + birther_ptr->stat_max_max[i] = creature_ptr->stat_max_max[i]; + } + + for (int i = 0; i < PY_MAX_LEVEL; i++) { + birther_ptr->player_hp[i] = creature_ptr->player_hp[i]; + } + + birther_ptr->chaos_patron = creature_ptr->chaos_patron; + for (int i = 0; i < 8; i++) { + birther_ptr->vir_types[i] = creature_ptr->vir_types[i]; + } + + for (int i = 0; i < 4; i++) { + strcpy(birther_ptr->history[i], creature_ptr->history[i]); + } +} + +/*! + * @brief プレイヤーのクイックスタート情報をプレイヤー構造体へ読み込む / Load the previous data + * @param swap TRUEならば現在のプレイヤー構造体上との内容をスワップする形で読み込む。 + * @return なし。 + */ +void load_prev_data(player_type *creature_ptr, bool swap) +{ + birther temp; + if (swap) + save_prev_data(creature_ptr, &temp); + + creature_ptr->psex = previous_char.psex; + creature_ptr->prace = previous_char.prace; + creature_ptr->pclass = previous_char.pclass; + creature_ptr->pseikaku = previous_char.pseikaku; + creature_ptr->realm1 = previous_char.realm1; + creature_ptr->realm2 = previous_char.realm2; + creature_ptr->age = previous_char.age; + creature_ptr->ht = previous_char.ht; + creature_ptr->wt = previous_char.wt; + creature_ptr->sc = previous_char.sc; + creature_ptr->au = previous_char.au; + + for (int i = 0; i < A_MAX; i++) { + creature_ptr->stat_cur[i] = creature_ptr->stat_max[i] = previous_char.stat_max[i]; + creature_ptr->stat_max_max[i] = previous_char.stat_max_max[i]; + } + + for (int i = 0; i < PY_MAX_LEVEL; i++) { + creature_ptr->player_hp[i] = previous_char.player_hp[i]; + } + + creature_ptr->mhp = creature_ptr->player_hp[0]; + creature_ptr->chp = creature_ptr->player_hp[0]; + creature_ptr->chaos_patron = previous_char.chaos_patron; + for (int i = 0; i < 8; i++) { + creature_ptr->vir_types[i] = previous_char.vir_types[i]; + } + + for (int i = 0; i < 4; i++) { + strcpy(creature_ptr->history[i], previous_char.history[i]); + } + + if (swap) { + (void)COPY(&previous_char, &temp, birther); + } +} diff --git a/src/birth/quick-start.h b/src/birth/quick-start.h new file mode 100644 index 000000000..6e2f4b022 --- /dev/null +++ b/src/birth/quick-start.h @@ -0,0 +1,40 @@ +#pragma once + +#include "system/angband.h" + +/* + * A structure to hold "rolled" information + */ +typedef struct birther { + SEX_IDX psex; /* Sex index */ + player_race_type prace; /* Race index */ + player_class_type pclass; /* Class index */ + player_personality_type pseikaku; /* Seikaku index */ + REALM_IDX realm1; /* First magic realm */ + REALM_IDX realm2; /* Second magic realm */ + + s16b age; + s16b ht; + s16b wt; + s16b sc; + + PRICE au; /*!< 初期の所持金 */ + + BASE_STATUS stat_max[6]; /* Current "maximal" stat values */ + BASE_STATUS stat_max_max[6]; /* Maximal "maximal" stat values */ + HIT_POINT player_hp[PY_MAX_LEVEL]; + + PATRON_IDX chaos_patron; + + s16b vir_types[8]; + + char history[4][60]; + + bool quick_ok; +} birther; + +extern birther previous_char; + +bool ask_quick_start(player_type *creature_ptr); +void save_prev_data(player_type *creature_ptr, birther *birther_ptr); +void load_prev_data(player_type *creature_ptr, bool swap); diff --git a/src/bldg.c b/src/bldg.c deleted file mode 100644 index f79e9903f..000000000 --- a/src/bldg.c +++ /dev/null @@ -1,4368 +0,0 @@ -/*! - @file bldg.c - @brief 町の施設処理 / Building commands - @date 2013/12/23 - @author - Created by Ken Wigle for Kangband - a variant of Angband 2.8.3\n - -KMW-\n - \n - Rewritten for Kangband 2.8.3i using Kamband's version of\n - bldg.c as written by Ivan Tkatchev\n - \n - Changed for ZAngband by Robert Ruehlmann\n -*/ - -#include "angband.h" -#include "floor.h" -#include "object-boost.h" -#include "object-hook.h" -#include "monster.h" -#include "monsterrace-hook.h" -#include "melee.h" -#include "wild.h" -#include "world.h" -#include "sort.h" - -#include "avatar.h" -#include "mutation.h" -#include "quest.h" -#include "artifact.h" -#include "cmd-spell.h" -#include "rumor.h" -#include "player-status.h" -#include "spells-status.h" - -/*! - * ループ中で / hack as in leave_store in store.c - */ -static bool leave_bldg = FALSE; - -/*! - * @brief 施設毎に設定された種族、職業、魔法領域フラグがプレイヤーと一致するかを判定する。 - * @details 各種ギルドや寺院など、特定の職業ならば優遇措置を得られる施設、 - * あるいは食堂など特定の種族では利用できない施設の判定処理を行う。 - * @param bldg 施設構造体の参照ポインタ - * @return 種族、職業、魔法領域のいずれかが一致しているかの是非。 - */ -static bool is_owner(building_type *bldg) -{ - if (bldg->member_class[p_ptr->pclass] == BUILDING_OWNER) - { - return (TRUE); - } - - if (bldg->member_race[p_ptr->prace] == BUILDING_OWNER) - { - return (TRUE); - } - - if ((is_magic(p_ptr->realm1) && (bldg->member_realm[p_ptr->realm1] == BUILDING_OWNER)) || - (is_magic(p_ptr->realm2) && (bldg->member_realm[p_ptr->realm2] == BUILDING_OWNER))) - { - return (TRUE); - } - - return (FALSE); -} - -/*! - * @brief 施設毎に設定された種族、職業、魔法領域フラグがプレイヤーと一致するかを判定する。 - (スペルマスターの特別判定つき) - * @details 各種ギルドや寺院など、特定の職業ならば優遇措置を得られる施設、 - * あるいは食堂など特定の種族では利用できない施設の判定処理を行う。 - * @param bldg 施設構造体の参照ポインタ - * @return 種族、職業、魔法領域のいずれかが一致しているかの是非。 - * @todo is_owner()との実質的な多重実装なので、リファクタリングを行うべきである。 - */ -static bool is_member(building_type *bldg) -{ - if (bldg->member_class[p_ptr->pclass]) - { - return (TRUE); - } - - if (bldg->member_race[p_ptr->prace]) - { - return (TRUE); - } - - if ((is_magic(p_ptr->realm1) && bldg->member_realm[p_ptr->realm1]) || - (is_magic(p_ptr->realm2) && bldg->member_realm[p_ptr->realm2])) - { - return (TRUE); - } - - - if (p_ptr->pclass == CLASS_SORCERER) - { - int i; - bool OK = FALSE; - for (i = 0; i < MAX_MAGIC; i++) - { - if (bldg->member_realm[i+1]) OK = TRUE; - } - return OK; - } - return (FALSE); -} - -/*! - * @brief コンソールに表示された施設に関する情報を消去する / Clear the building information - * @details 消去は行毎にヌル文字列で行われる。 - * @param min_row 開始行番号 - * @param max_row 末尾行番号 - * @return なし - */ -static void clear_bldg(int min_row, int max_row) -{ - int i; - - for (i = min_row; i <= max_row; i++) - prt("", i, 0); -} - -/*! - * @brief 所持金を表示する。 - * @return なし - */ -static void building_prt_gold(void) -{ - char tmp_str[80]; - prt(_("手持ちのお金: ", "Gold Remaining: "), 23,53); - sprintf(tmp_str, "%9ld", (long)p_ptr->au); - prt(tmp_str, 23, 68); -} - -/*! - * @brief 施設のサービス一覧を表示する / Display a building. - * @param bldg 施設構造体の参照ポインタ - * @return なし - */ -static void show_building(building_type* bldg) -{ - char buff[20]; - int i; - byte action_color; - char tmp_str[80]; - - Term_clear(); - sprintf(tmp_str, "%s (%s) %35s", bldg->owner_name, bldg->owner_race, bldg->name); - prt(tmp_str, 2, 1); - - - for (i = 0; i < 8; i++) - { - if (bldg->letters[i]) - { - if (bldg->action_restr[i] == 0) - { - if ((is_owner(bldg) && (bldg->member_costs[i] == 0)) || - (!is_owner(bldg) && (bldg->other_costs[i] == 0))) - { - action_color = TERM_WHITE; - buff[0] = '\0'; - } - else if (is_owner(bldg)) - { - action_color = TERM_YELLOW; - sprintf(buff, _("($%ld)", "(%ldgp)"), (long int)bldg->member_costs[i]); - } - else - { - action_color = TERM_YELLOW; - sprintf(buff, _("($%ld)", "(%ldgp)"), (long int)bldg->other_costs[i]); } - } - else if (bldg->action_restr[i] == 1) - { - if (!is_member(bldg)) - { - action_color = TERM_L_DARK; - strcpy(buff, _("(閉店)", "(closed)")); - } - else if ((is_owner(bldg) && (bldg->member_costs[i] == 0)) || - (is_member(bldg) && (bldg->other_costs[i] == 0))) - { - action_color = TERM_WHITE; - buff[0] = '\0'; - } - else if (is_owner(bldg)) - { - action_color = TERM_YELLOW; - sprintf(buff, _("($%ld)", "(%ldgp)"), (long int)bldg->member_costs[i]); - } - else - { - action_color = TERM_YELLOW; - sprintf(buff, _("($%ld)", "(%ldgp)"), (long int)bldg->other_costs[i]); - } - } - else - { - if (!is_owner(bldg)) - { - action_color = TERM_L_DARK; - strcpy(buff, _("(閉店)", "(closed)")); - } - else if (bldg->member_costs[i] != 0) - { - action_color = TERM_YELLOW; - sprintf(buff, _("($%ld)", "(%ldgp)"), (long int)bldg->member_costs[i]); - } - else - { - action_color = TERM_WHITE; - buff[0] = '\0'; - } - } - - sprintf(tmp_str," %c) %s %s", bldg->letters[i], bldg->act_names[i], buff); - c_put_str(action_color, tmp_str, 19+(i/2), 35*(i%2)); - } - } - prt(_(" ESC) 建物を出る", " ESC) Exit building"), 23, 0); -} - -/*! - * @brief 闘技場に入るコマンドの処理 / arena commands - * @param cmd 闘技場処理のID - * @return なし - */ -static void arena_comm(int cmd) -{ - monster_race *r_ptr; - concptr name; - - - switch (cmd) - { - case BACT_ARENA: - if (p_ptr->arena_number == MAX_ARENA_MONS) - { - clear_bldg(5, 19); - prt(_("アリーナの優勝者!", " Arena Victor!"), 5, 0); - prt(_("おめでとう!あなたは全ての敵を倒しました。", "Congratulations! You have defeated all before you."), 7, 0); - prt(_("賞金として $1,000,000 が与えられます。", "For that, receive the prize: 1,000,000 gold pieces"), 8, 0); - - prt("", 10, 0); - prt("", 11, 0); - p_ptr->au += 1000000L; - msg_print(_("スペースキーで続行", "Press the space bar to continue")); - msg_print(NULL); - p_ptr->arena_number++; - } - else if (p_ptr->arena_number > MAX_ARENA_MONS) - { - if (p_ptr->arena_number < MAX_ARENA_MONS+2) - { - msg_print(_("君のために最強の挑戦者を用意しておいた。", "The strongest challenger is waiting for you.")); - msg_print(NULL); - if (get_check(_("挑戦するかね?", "Do you fight? "))) - { - msg_print(_("死ぬがよい。", "Die, maggots.")); - msg_print(NULL); - - p_ptr->exit_bldg = FALSE; - reset_tim_flags(); - - /* Save the surface floor as saved floor */ - prepare_change_floor_mode(CFM_SAVE_FLOORS); - - p_ptr->inside_arena = TRUE; - p_ptr->leaving = TRUE; - leave_bldg = TRUE; - } - else - { - msg_print(_("残念だ。", "We are disappointed.")); - } - } - else - { - msg_print(_("あなたはアリーナに入り、しばらくの間栄光にひたった。", - "You enter the arena briefly and bask in your glory.")); - msg_print(NULL); - } - } - else if (p_ptr->riding && (p_ptr->pclass != CLASS_BEASTMASTER) && (p_ptr->pclass != CLASS_CAVALRY)) - { - msg_print(_("ペットに乗ったままではアリーナへ入れさせてもらえなかった。", - "You don't have permission to enter with pet.")); - msg_print(NULL); - } - else - { - p_ptr->exit_bldg = FALSE; - reset_tim_flags(); - - /* Save the surface floor as saved floor */ - prepare_change_floor_mode(CFM_SAVE_FLOORS); - - p_ptr->inside_arena = TRUE; - p_ptr->leaving = TRUE; - leave_bldg = TRUE; - } - break; - case BACT_POSTER: - if (p_ptr->arena_number == MAX_ARENA_MONS) - msg_print(_("あなたは勝利者だ。 アリーナでのセレモニーに参加しなさい。", - "You are victorious. Enter the arena for the ceremony.")); - - else if (p_ptr->arena_number > MAX_ARENA_MONS) - { - msg_print(_("あなたはすべての敵に勝利した。", "You have won against all foes.")); - } - else - { - r_ptr = &r_info[arena_info[p_ptr->arena_number].r_idx]; - name = (r_name + r_ptr->name); - msg_format(_("%s に挑戦するものはいないか?", "Do I hear any challenges against: %s"), name); - - p_ptr->monster_race_idx = arena_info[p_ptr->arena_number].r_idx; - p_ptr->window |= (PW_MONSTER); - handle_stuff(); - - } - break; - case BACT_ARENA_RULES: - screen_save(); - - /* Peruse the arena help file */ - (void)show_file(TRUE, _("arena_j.txt", "arena.txt"), NULL, 0, 0); - screen_load(); - - break; - } -} - -/*! - * @brief カジノのスロットシンボルを表示する / display fruit for dice slots - * @param row シンボルを表示する行の上端 - * @param col シンボルを表示する行の左端 - * @param fruit 表示するシンボルID - * @return なし - */ -static void display_fruit(int row, int col, int fruit) -{ - switch (fruit) - { - case 0: /* lemon */ - c_put_str(TERM_YELLOW, " ####.", row, col); - c_put_str(TERM_YELLOW, " # #", row + 1, col); - c_put_str(TERM_YELLOW, " # #", row + 2, col); - c_put_str(TERM_YELLOW, "# #", row + 3, col); - c_put_str(TERM_YELLOW, "# #", row + 4, col); - c_put_str(TERM_YELLOW, "# # ", row + 5, col); - c_put_str(TERM_YELLOW, "# # ", row + 6, col); - c_put_str(TERM_YELLOW, ".#### ", row + 7, col); - prt( _(" レモン ", - " Lemon "), row + 8, col); - break; - case 1: /* orange */ - c_put_str(TERM_ORANGE, " ## ", row, col); - c_put_str(TERM_ORANGE, " #..# ", row + 1, col); - c_put_str(TERM_ORANGE, " #....# ", row + 2, col); - c_put_str(TERM_ORANGE, "#......#", row + 3, col); - c_put_str(TERM_ORANGE, "#......#", row + 4, col); - c_put_str(TERM_ORANGE, " #....# ", row + 5, col); - c_put_str(TERM_ORANGE, " #..# ", row + 6, col); - c_put_str(TERM_ORANGE, " ## ", row + 7, col); - prt( _("オレンジ", - " Orange "), row + 8, col); - break; - case 2: /* sword */ - c_put_str(TERM_SLATE, _(" Λ ", " /\\ ") , row, col); - c_put_str(TERM_SLATE, _(" || ", " ## ") , row + 1, col); - c_put_str(TERM_SLATE, _(" || ", " ## ") , row + 2, col); - c_put_str(TERM_SLATE, _(" || ", " ## ") , row + 3, col); - c_put_str(TERM_SLATE, _(" || ", " ## ") , row + 4, col); - c_put_str(TERM_SLATE, _(" || ", " ## ") , row + 5, col); - c_put_str(TERM_UMBER, _(" |=亜=| ", " ###### ") , row + 6, col); - c_put_str(TERM_UMBER, _(" 目 ", " ## ") , row + 7, col); - prt( _(" 剣 ", " Sword ") , row + 8, col); - break; - case 3: /* shield */ - c_put_str(TERM_SLATE, " ###### ", row, col); - c_put_str(TERM_SLATE, "# #", row + 1, col); - c_put_str(TERM_SLATE, "# ++++ #", row + 2, col); - c_put_str(TERM_SLATE, "# +==+ #", row + 3, col); - c_put_str(TERM_SLATE, "# ++ #", row + 4, col); - c_put_str(TERM_SLATE, " # # ", row + 5, col); - c_put_str(TERM_SLATE, " # # ", row + 6, col); - c_put_str(TERM_SLATE, " ## ", row + 7, col); - prt( _(" 盾 ", - " Shield "), row + 8, col); - break; - case 4: /* plum */ - c_put_str(TERM_VIOLET, " ## ", row, col); - c_put_str(TERM_VIOLET, " ###### ", row + 1, col); - c_put_str(TERM_VIOLET, "########", row + 2, col); - c_put_str(TERM_VIOLET, "########", row + 3, col); - c_put_str(TERM_VIOLET, "########", row + 4, col); - c_put_str(TERM_VIOLET, " ###### ", row + 5, col); - c_put_str(TERM_VIOLET, " #### ", row + 6, col); - c_put_str(TERM_VIOLET, " ## ", row + 7, col); - prt( _(" プラム ", - " Plum "), row + 8, col); - break; - case 5: /* cherry */ - c_put_str(TERM_RED, " ##", row, col); - c_put_str(TERM_RED, " ### ", row + 1, col); - c_put_str(TERM_RED, " #..# ", row + 2, col); - c_put_str(TERM_RED, " #..# ", row + 3, col); - c_put_str(TERM_RED, " ###### ", row + 4, col); - c_put_str(TERM_RED, "#..##..#", row + 5, col); - c_put_str(TERM_RED, "#..##..#", row + 6, col); - c_put_str(TERM_RED, " ## ## ", row + 7, col); - prt( _("チェリー", - " Cherry "), row + 8, col); - break; - } -} - -/*! @note - * kpoker no (tyuto-hannpa na)pakuri desu... - * joker ha shineru node haitte masen. - * - * TODO: donataka! tsukutte! - * - agatta yaku no kiroku (like DQ). - * - kakkoii card no e. - * - sousa-sei no koujyo. - * - code wo wakariyasuku. - * - double up. - * - Joker... -- done. - * - * 9/13/2000 --Koka - * 9/15/2000 joker wo jissou. soreto, code wo sukosi kakikae. --Habu - */ - -#define SUIT_OF(card) ((card) / 13) /*!< トランプカードのスートを返す */ -#define NUM_OF(card) ((card) % 13) /*!< トランプカードの番号を返す */ -#define IS_JOKER(card) ((card) == 52) /*!< トランプカードがジョーカーかどうかを返す */ - -static int cards[5]; /*!< ポーカーの現在の手札ID */ - -/*! - * @brief ポーカーの山札を切る。 - * @param deck デッキの配列 - * @return なし - */ -static void reset_deck(int deck[]) -{ - int i; - for (i = 0; i < 53; i++) deck[i] = i; - - /* shuffle cards */ - for (i = 0; i < 53; i++){ - int tmp1 = randint0(53 - i) + i; - int tmp2 = deck[i]; - deck[i] = deck[tmp1]; - deck[tmp1] = tmp2; - } -} - -/*! - * @brief ポーカープレイ中にジョーカーを持っているかの判定を返す。 - * @return ジョーカーを持っているか。 - */ -static bool have_joker(void) -{ - int i; - - for (i = 0; i < 5; i++){ - if(IS_JOKER(cards[i])) return TRUE; - } - return FALSE; -} - -/*! - * @brief ポーカーの手札に該当の番号の札があるかを返す。 - * @param num 探したいカードの番号。 - * @return 該当の番号が手札にあるか。 - */ -static bool find_card_num(int num) -{ - int i; - for (i = 0; i < 5; i++) - if (NUM_OF(cards[i]) == num && !IS_JOKER(cards[i])) return TRUE; - return FALSE; -} - -/*! - * @brief ポーカーの手札がフラッシュ役を得ているかを帰す。 - * @return 役の判定結果 - */ -static bool yaku_check_flush(void) -{ - int i, suit; - bool joker_is_used = FALSE; - - suit = IS_JOKER(cards[0]) ? SUIT_OF(cards[1]) : SUIT_OF(cards[0]); - for (i = 0; i < 5; i++){ - if (SUIT_OF(cards[i]) != suit){ - if(have_joker() && !joker_is_used) - joker_is_used = TRUE; - else - return FALSE; - } - } - - return TRUE; -} - -/*! - * @brief ポーカーの手札がストレートを含んだ高位の役を得ているかを帰す。 - * @return 役の判定結果 0…ストレート、フラッシュいずれもなし/1…ストレートのみ/2…ストレートフラッシュ/3…ロイヤルストレートフラッシュ - */ -static int yaku_check_straight(void) -{ - int i, lowest = 99; - bool joker_is_used = FALSE; - bool straight = FALSE; - - /* get lowest */ - for (i = 0; i < 5; i++) - { - if (NUM_OF(cards[i]) < lowest && !IS_JOKER(cards[i])) - lowest = NUM_OF(cards[i]); - } - - /* Check Royal Straight Flush */ - if (yaku_check_flush()) - { - if( lowest == 0 ){ - for (i = 0; i < 4; i++) - { - if (!find_card_num(9 + i)){ - if( have_joker() && !joker_is_used ) - joker_is_used = TRUE; - else - break; - } - } - if (i == 4) return 3; /* Wow! Royal Straight Flush!!! */ - } - if(lowest == 9){ - for (i = 0; i < 3; i++) - { - if (!find_card_num(10 + i)) - break; - } - if (i == 3 && have_joker()) return 3; /* Wow! Royal Straight Flush!!! */ - } - } - - joker_is_used = FALSE; - - /* Straight Only Check */ - - if (lowest == 0) { /* (10 - J - Q - K)[JOKER] - A */ - for (i = 0; i < 4; i++) - { - if (!find_card_num(9 + i)) { - if (have_joker() && !joker_is_used) - joker_is_used = TRUE; - else - break; /* None */ - } - } - if(i == 4) straight = TRUE; - } - - joker_is_used = FALSE; - - for (i = 0; i < 5; i++) - { - if(!find_card_num(lowest + i)){ - if( have_joker() && !joker_is_used ) - joker_is_used = TRUE; - else - break; /* None */ - } - } - if(i == 5) straight = TRUE; - - if (straight && yaku_check_flush()) return 2; /* Straight Flush */ - else if(straight) return 1; /* Only Straight */ - else return 0; -} - -/*! - * @brief ポーカーのペア役の状態を返す。 - * @return 0:nopair 1:1 pair 2:2 pair 3:3 cards 4:full house 6:4cards - */ -static int yaku_check_pair(void) -{ - int i, i2, matching = 0; - - for (i = 0; i < 5; i++) - { - for (i2 = i+1; i2 < 5; i2++) - { - if (IS_JOKER(cards[i]) || IS_JOKER(cards[i2])) continue; - if (NUM_OF(cards[i]) == NUM_OF(cards[i2])) - matching++; - } - } - - if(have_joker()){ - switch(matching){ - case 0: - matching = 1; - break; - case 1: - matching = 3; - break; - case 2: - matching = 4; - break; - case 3: - matching = 6; - break; - case 6: - matching = 7; - break; - default: - /* don't reach */ - break; - } - } - - return matching; -} - -#define ODDS_5A 3000 /*!< ファイブエースの役倍率 */ -#define ODDS_5C 400 /*!< ファイブカードの役倍率 */ -#define ODDS_RF 200 /*!< ロイヤルストレートフラッシュの役倍率 */ -#define ODDS_SF 80 /*!< ストレートフラッシュの役倍率 */ -#define ODDS_4C 16 /*!< フォアカードの役倍率 */ -#define ODDS_FH 12 /*!< フルハウスの役倍率 */ -#define ODDS_FL 8 /*!< フラッシュの役倍率 */ -#define ODDS_ST 4 /*!< ストレートの役倍率 */ -#define ODDS_3C 1 /*!< スリーカードの役倍率 */ -#define ODDS_2P 1 /*!< ツーペアの役倍率 */ - -/*! - * @brief ポーカーの役をチェックし、その結果を画面に表示しつつ結果を返す。 - * @return 役のID - */ -static int yaku_check(void) -{ - prt(" ", 4, 3); - - switch(yaku_check_straight()){ - case 3: /* RF! */ - c_put_str(TERM_YELLOW, _("ロイヤルストレートフラッシュ", "Royal Flush"), 4, 3); - return ODDS_RF; - case 2: /* SF! */ - c_put_str(TERM_YELLOW, _("ストレートフラッシュ", "Straight Flush"), 4, 3); - return ODDS_SF; - case 1: - c_put_str(TERM_YELLOW, _("ストレート", "Straight"), 4, 3); - return ODDS_ST; - default: - /* Not straight -- fall through */ - break; - } - - if (yaku_check_flush()) - { - c_put_str(TERM_YELLOW, _("フラッシュ", "Flush"), 4, 3); - return ODDS_FL; - } - - switch (yaku_check_pair()) - { - case 1: - c_put_str(TERM_YELLOW, _("ワンペア", "One pair"), 4, 3); - return 0; - case 2: - c_put_str(TERM_YELLOW, _("ツーペア", "Two pair"), 4, 3); - return ODDS_2P; - case 3: - c_put_str(TERM_YELLOW, _("スリーカード", "Three of a kind"), 4, 3); - return ODDS_3C; - case 4: - c_put_str(TERM_YELLOW, _("フルハウス", "Full house"), 4, 3); - return ODDS_FH; - case 6: - c_put_str(TERM_YELLOW, _("フォーカード", "Four of a kind"), 4, 3); - return ODDS_4C; - case 7: - if (!NUM_OF(cards[0]) && !NUM_OF(cards[1])) - { - c_put_str(TERM_YELLOW, _("ファイブエース", "Five ace"), 4, 3); - return ODDS_5A; - } - else - { - c_put_str(TERM_YELLOW, _("ファイブカード", "Five of a kind"), 4, 3); - return ODDS_5C; - } - default: - break; - } - return 0; -} - -/*! - * @brief ポーカーの捨てる/残すインターフェイスの表示を更新する。 - * @param hoge カーソルの現在位置 - * @param kaeruka カードの捨てる/残すフラグ配列 - * @return なし - */ -static void display_kaeruka(int hoge, int kaeruka[]) -{ - int i; - char col = TERM_WHITE; - for (i = 0; i < 5; i++) - { - if (i == hoge) col = TERM_YELLOW; - else if(kaeruka[i]) col = TERM_WHITE; - else col = TERM_L_BLUE; - - if(kaeruka[i]) - c_put_str(col, _("かえる", "Change"), 14, 5+i*16); - else - c_put_str(col, _("のこす", " Stay "), 14, 5+i*16); - } - if (hoge > 4) col = TERM_YELLOW; - else col = TERM_WHITE; - c_put_str(col, _("決定", "Sure"), 16, 38); - - /* Hilite current option */ - if (hoge < 5) move_cursor(14, 5+hoge*16); - else move_cursor(16, 38); -} - -/*! - * @brief ポーカーの手札を表示する。 - * @return なし - */ -static void display_cards(void) -{ - int i, j; - char suitcolor[4] = {TERM_YELLOW, TERM_L_RED, TERM_L_BLUE, TERM_L_GREEN}; -#ifdef JP - concptr suit[4] = {"★", "●", "¶", "†"}; - concptr card_grph[13][7] = {{"A %s ", - " 変 ", - " 愚 ", - " 蛮 ", - " 怒 ", - " %s ", - " A"}, - {"2 ", - " %s ", - " ", - " ", - " ", - " %s ", - " 2"}, - {"3 ", - " %s ", - " ", - " %s ", - " ", - " %s ", - " 3"}, - {"4 ", - " %s %s ", - " ", - " ", - " ", - " %s %s ", - " 4"}, - {"5 ", - " %s %s ", - " ", - " %s ", - " ", - " %s %s ", - " 5"}, - {"6 ", - " %s %s ", - " ", - " %s %s ", - " ", - " %s %s ", - " 6"}, - {"7 ", - " %s %s ", - " %s ", - " %s %s ", - " ", - " %s %s ", - " 7"}, - {"8 ", - " %s %s ", - " %s ", - " %s %s ", - " %s ", - " %s %s ", - " 8"}, - {"9 %s %s ", - " ", - " %s %s ", - " %s ", - " %s %s ", - " ", - " %s %s 9"}, - {"10 %s %s ", - " %s ", - " %s %s ", - " ", - " %s %s ", - " %s ", - " %s %s 10"}, - {"J Λ ", - "%s || ", - " || ", - " || ", - " || ", - " |=亜=| %s", - " 目 J"}, - {"ï¼± ###### ", - "%s# # ", - " # ++++ # ", - " # +==+ # ", - " # ++ # ", - " # # %s", - " ## ï¼±"}, - {"K ", - "%s `⌒´ ", - " γγγλ ", - " ο ο ι ", - " υ ∂ ", - " σ ノ %s", - " K"}}; - concptr joker_grph[7] = { " ", - " J ", - " O ", - " K ", - " ï¼¥ ", - " ï¼² ", - " "}; - -#else - - concptr suit[4] = {"[]", "qp", "<>", "db"}; - concptr card_grph[13][7] = {{"A %s ", - " He ", - " ng ", - " ba ", - " nd ", - " %s ", - " A"}, - {"2 ", - " %s ", - " ", - " ", - " ", - " %s ", - " 2"}, - {"3 ", - " %s ", - " ", - " %s ", - " ", - " %s ", - " 3"}, - {"4 ", - " %s %s ", - " ", - " ", - " ", - " %s %s ", - " 4"}, - {"5 ", - " %s %s ", - " ", - " %s ", - " ", - " %s %s ", - " 5"}, - {"6 ", - " %s %s ", - " ", - " %s %s ", - " ", - " %s %s ", - " 6"}, - {"7 ", - " %s %s ", - " %s ", - " %s %s ", - " ", - " %s %s ", - " 7"}, - {"8 ", - " %s %s ", - " %s ", - " %s %s ", - " %s ", - " %s %s ", - " 8"}, - {"9 %s %s ", - " ", - " %s %s ", - " %s ", - " %s %s ", - " ", - " %s %s 9"}, - {"10 %s %s ", - " %s ", - " %s %s ", - " ", - " %s %s ", - " %s ", - " %s %s 10"}, - {"J /\\ ", - "%s || ", - " || ", - " || ", - " || ", - " |=HH=| %s", - " ][ J"}, - {"Q ###### ", - "%s# # ", - " # ++++ # ", - " # +==+ # ", - " # ++ # ", - " # # %s", - " ## Q"}, - {"K ", - "%s _'~~`_ ", - " jjjjj$& ", - " q q uu ", - " c & ", - " v__/ %s", - " K"}}; - concptr joker_grph[7] = { " ", - " J ", - " O ", - " K ", - " E ", - " R ", - " "}; -#endif - - for (i = 0; i < 5; i++) - { - prt(_("┏━━━━━━┓", " +------------+ "), 5, i*16); - } - - for (i = 0; i < 5; i++) - { - for (j = 0; j < 7; j++) - { - prt(_("┃", " |"), j+6, i*16); - if(IS_JOKER(cards[i])) - c_put_str(TERM_VIOLET, joker_grph[j], j+6, 2+i*16); - else - c_put_str(suitcolor[SUIT_OF(cards[i])], format(card_grph[NUM_OF(cards[i])][j], suit[SUIT_OF(cards[i])], suit[SUIT_OF(cards[i])]), j+6, 2+i*16); - prt(_("┃", "| "), j+6, i*16+14); - } - } - for (i = 0; i < 5; i++) - { - prt(_("┗━━━━━━┛", " +------------+ "), 13, i*16); - } -} - -/*! - * @brief ポーカーの1プレイルーチン。 - * @return 1プレイの役の結果 - */ -static int do_poker(void) -{ - int i, k = 2; - char cmd; - int deck[53]; /* yamafuda : 0...52 */ - int deck_ptr = 0; - int kaeruka[5]; /* 0:kaenai 1:kaeru */ - - bool done = FALSE; - bool kettei = TRUE; - bool kakikae = TRUE; - - reset_deck(deck); - - for (i = 0; i < 5; i++) - { - cards[i] = deck[deck_ptr++]; - kaeruka[i] = 0; /* default:nokosu */ - } - - /* suteruno wo kimeru */ - prt(_("残すカードを決めて下さい(方向で移動, スペースで選択)。", "Stay witch? "), 0, 0); - - display_cards(); - yaku_check(); - - while (!done) - { - if (kakikae) display_kaeruka(k+kettei*5, kaeruka); - kakikae = FALSE; - cmd = inkey(); - switch (cmd) - { - case '6': case 'l': case 'L': case KTRL('F'): - if (!kettei) k = (k+1)%5; - else {k = 0;kettei = FALSE;} - kakikae = TRUE; - break; - case '4': case 'h': case 'H': case KTRL('B'): - if (!kettei) k = (k+4)%5; - else {k = 4;kettei = FALSE;} - kakikae = TRUE; - break; - case '2': case 'j': case 'J': case KTRL('N'): - if (!kettei) {kettei = TRUE;kakikae = TRUE;} - break; - case '8': case 'k': case 'K': case KTRL('P'): - if (kettei) {kettei = FALSE;kakikae = TRUE;} - break; - case ' ': case '\r': - if (kettei) done = TRUE; - else {kaeruka[k] = !kaeruka[k];kakikae = TRUE;} - break; - default: - break; - } - } - - prt("",0,0); - - for (i = 0; i < 5; i++) - if (kaeruka[i] == 1) cards[i] = deck[deck_ptr++]; /* soshite toru */ - - display_cards(); - - return yaku_check(); -} -#undef SUIT_OF -#undef NUM_OF -#undef IS_JOKER -/* end of poker codes --Koka */ - -/*! - * @brief カジノ1プレイごとのメインルーチン / gamble_comm - * @param cmd プレイするゲームID - * @return なし - */ -static bool gamble_comm(int cmd) -{ - int i; - int roll1, roll2, roll3, choice, odds, win; - s32b wager; - s32b maxbet; - s32b oldgold; - - char out_val[160], tmp_str[80], again; - concptr p; - - screen_save(); - - if (cmd == BACT_GAMBLE_RULES) - { - /* Peruse the gambling help file */ - (void)show_file(TRUE, _("jgambling.txt", "gambling.txt"), NULL, 0, 0); - } - else - { - /* No money */ - if (p_ptr->au < 1) - { - msg_print(_("おい!おまえ一文なしじゃないか!こっから出ていけ!", - "Hey! You don't have gold - get out of here!")); - msg_print(NULL); - screen_load(); - return FALSE; - } - - clear_bldg(5, 23); - - maxbet = p_ptr->lev * 200; - - /* We can't bet more than we have */ - maxbet = MIN(maxbet, p_ptr->au); - - /* Get the wager */ - strcpy(out_val, ""); - sprintf(tmp_str,_("賭け金 (1-%ld)?", "Your wager (1-%ld) ? "), (long int)maxbet); - - - /* - * Use get_string() because we may need more than - * the s16b value returned by get_quantity(). - */ - if (get_string(tmp_str, out_val, 32)) - { - /* Strip spaces */ - for (p = out_val; *p == ' '; p++); - - /* Get the wager */ - wager = atol(p); - - if (wager > p_ptr->au) - { - msg_print(_("おい!金が足りないじゃないか!出ていけ!", "Hey! You don't have the gold - get out of here!")); - msg_print(NULL); - screen_load(); - return (FALSE); - } - else if (wager > maxbet) - { - msg_format(_("%ldゴールドだけ受けよう。残りは取っときな。", - "I'll take %ld gold of that. Keep the rest."), (long int)maxbet); - wager = maxbet; - } - else if (wager < 1) - { - msg_print(_("OK、1ゴールドからはじめよう。", "Ok, we'll start with 1 gold.")); - wager = 1; - } - msg_print(NULL); - win = FALSE; - odds = 0; - oldgold = p_ptr->au; - - sprintf(tmp_str, _("ゲーム前の所持金: %9ld", "Gold before game: %9ld"), (long int)oldgold); - prt(tmp_str, 20, 2); - sprintf(tmp_str, _("現在の掛け金: %9ld", "Current Wager: %9ld"), (long int)wager); - prt(tmp_str, 21, 2); - - do - { - p_ptr->au -= wager; - switch (cmd) - { - case BACT_IN_BETWEEN: /* Game of In-Between */ - c_put_str(TERM_GREEN, _("イン・ビトイーン", "In Between"),5,2); - - odds = 4; - win = FALSE; - roll1 = randint1(10); - roll2 = randint1(10); - choice = randint1(10); - sprintf(tmp_str, _("黒ダイス: %d 黒ダイス: %d", "Black die: %d Black Die: %d"), roll1, roll2); - - prt(tmp_str, 8, 3); - sprintf(tmp_str, _("赤ダイス: %d", "Red die: %d"), choice); - - prt(tmp_str, 11, 14); - if (((choice > roll1) && (choice < roll2)) || - ((choice < roll1) && (choice > roll2))) - win = TRUE; - break; - case BACT_CRAPS: /* Game of Craps */ - c_put_str(TERM_GREEN, _("クラップス", "Craps"), 5, 2); - - win = 3; - odds = 2; - roll1 = randint1(6); - roll2 = randint1(6); - roll3 = roll1 + roll2; - choice = roll3; - sprintf(tmp_str, _("1振りめ: %d %d Total: %d", - "First roll: %d %d Total: %d"), roll1, roll2, roll3); - prt(tmp_str, 7, 5); - if ((roll3 == 7) || (roll3 == 11)) - win = TRUE; - else if ((roll3 == 2) || (roll3 == 3) || (roll3 == 12)) - win = FALSE; - else - do - { - msg_print(_("なにかキーを押すともう一回振ります。", "Hit any key to roll again")); - - msg_print(NULL); - roll1 = randint1(6); - roll2 = randint1(6); - roll3 = roll1 + roll2; - sprintf(tmp_str, _("出目: %d %d 合計: %d", - "Roll result: %d %d Total: %d"), roll1, roll2, roll3); - prt(tmp_str, 8, 5); - if (roll3 == choice) - win = TRUE; - else if (roll3 == 7) - win = FALSE; - } while ((win != TRUE) && (win != FALSE)); - break; - - case BACT_SPIN_WHEEL: /* Spin the Wheel Game */ - win = FALSE; - odds = 9; - c_put_str(TERM_GREEN, _("ルーレット", "Wheel"), 5, 2); - - prt("0 1 2 3 4 5 6 7 8 9", 7, 5); - prt("--------------------------------", 8, 3); - strcpy(out_val, ""); - get_string(_("何番? (0-9): ", "Pick a number (0-9): "), out_val, 32); - - for (p = out_val; iswspace(*p); p++); - choice = atol(p); - if (choice < 0) - { - msg_print(_("0番にしとくぜ。", "I'll put you down for 0.")); - choice = 0; - } - else if (choice > 9) - { - msg_print(_("OK、9番にしとくぜ。", "Ok, I'll put you down for 9.")); - choice = 9; - } - msg_print(NULL); - roll1 = randint0(10); - sprintf(tmp_str, _("ルーレットは回り、止まった。勝者は %d番だ。", - "The wheel spins to a stop and the winner is %d"), roll1); - prt(tmp_str, 13, 3); - prt("", 9, 0); - prt("*", 9, (3 * roll1 + 5)); - if (roll1 == choice) - win = TRUE; - break; - - case BACT_DICE_SLOTS: /* The Dice Slots */ - c_put_str(TERM_GREEN, _("ダイス・スロット", "Dice Slots"), 5, 2); - c_put_str(TERM_YELLOW, _("レモン レモン 2", ""), 6, 37); - c_put_str(TERM_YELLOW, _("レモン レモン レモン 5", ""), 7, 37); - c_put_str(TERM_ORANGE, _("オレンジ オレンジ オレンジ 10", ""), 8, 37); - c_put_str(TERM_UMBER, _("剣 剣 剣 20", ""), 9, 37); - c_put_str(TERM_SLATE, _("盾 盾 盾 50", ""), 10, 37); - c_put_str(TERM_VIOLET, _("プラム プラム プラム 200", ""), 11, 37); - c_put_str(TERM_RED, _("チェリー チェリー チェリー 1000", ""), 12, 37); - - win = FALSE; - roll1 = randint1(21); - for (i=6;i>0;i--) - { - if ((roll1-i) < 1) - { - roll1 = 7-i; - break; - } - roll1 -= i; - } - roll2 = randint1(21); - for (i=6;i>0;i--) - { - if ((roll2-i) < 1) - { - roll2 = 7-i; - break; - } - roll2 -= i; - } - choice = randint1(21); - for (i=6;i>0;i--) - { - if ((choice-i) < 1) - { - choice = 7-i; - break; - } - choice -= i; - } - put_str("/--------------------------\\", 7, 2); - prt("\\--------------------------/", 17, 2); - display_fruit(8, 3, roll1 - 1); - display_fruit(8, 12, roll2 - 1); - display_fruit(8, 21, choice - 1); - if ((roll1 == roll2) && (roll2 == choice)) - { - win = TRUE; - switch(roll1) - { - case 1: - odds = 5;break; - case 2: - odds = 10;break; - case 3: - odds = 20;break; - case 4: - odds = 50;break; - case 5: - odds = 200;break; - case 6: - odds = 1000;break; - } - } - else if ((roll1 == 1) && (roll2 == 1)) - { - win = TRUE; - odds = 2; - } - break; - case BACT_POKER: - win = FALSE; - odds = do_poker(); - if (odds) win = TRUE; - break; - } - - if (win) - { - prt(_("あなたの勝ち", "YOU WON"), 16, 37); - - p_ptr->au += odds * wager; - sprintf(tmp_str, _("倍率: %d", "Payoff: %d"), odds); - - prt(tmp_str, 17, 37); - } - else - { - prt(_("あなたの負け", "You Lost"), 16, 37); - prt("", 17, 37); - } - sprintf(tmp_str, _("現在の所持金: %9ld", "Current Gold: %9ld"), (long int)p_ptr->au); - - prt(tmp_str, 22, 2); - prt(_("もう一度(Y/N)?", "Again(Y/N)?"), 18, 37); - - move_cursor(18, 52); - again = inkey(); - prt("", 16, 37); - prt("", 17, 37); - prt("", 18, 37); - if (wager > p_ptr->au) - { - msg_print(_("おい!金が足りないじゃないか!ここから出て行け!", - "Hey! You don't have the gold - get out of here!")); - msg_print(NULL); - - /* Get out here */ - break; - } - } while ((again == 'y') || (again == 'Y')); - - prt("", 18, 37); - if (p_ptr->au >= oldgold) - { - msg_print(_("「今回は儲けたな!でも次はこっちが勝ってやるからな、絶対に!」", - "You came out a winner! We'll win next time, I'm sure.")); - chg_virtue(V_CHANCE, 3); - } - else - { - msg_print(_("「金をスッてしまったな、わはは!うちに帰った方がいいぜ。」", "You lost gold! Haha, better head home.")); - chg_virtue(V_CHANCE, -3); - } - } - msg_print(NULL); - } - screen_load(); - return (TRUE); -} - -/*! - * @brief モンスター闘技場に参加するモンスターをリセットする。 - * @return なし - */ -void battle_monsters(void) -{ - int total, i; - int max_dl = 0; - int mon_level; - int power[4]; - bool tekitou; - bool old_inside_battle = p_ptr->inside_battle; - - for (i = 0; i < max_d_idx; i++) - if (max_dl < max_dlv[i]) max_dl = max_dlv[i]; - - mon_level = randint1(MIN(max_dl, 122))+5; - if (randint0(100) < 60) - { - i = randint1(MIN(max_dl, 122))+5; - mon_level = MAX(i, mon_level); - } - if (randint0(100) < 30) - { - i = randint1(MIN(max_dl, 122))+5; - mon_level = MAX(i, mon_level); - } - - while (1) - { - total = 0; - tekitou = FALSE; - for(i = 0; i < 4; i++) - { - MONRACE_IDX r_idx; - int j; - while (1) - { - get_mon_num_prep(monster_can_entry_arena, NULL); - p_ptr->inside_battle = TRUE; - r_idx = get_mon_num(mon_level); - p_ptr->inside_battle = old_inside_battle; - if (!r_idx) continue; - - if ((r_info[r_idx].flags1 & RF1_UNIQUE) || (r_info[r_idx].flags7 & RF7_UNIQUE2)) - { - if ((r_info[r_idx].level + 10) > mon_level) continue; - } - - for (j = 0; j < i; j++) - if(r_idx == battle_mon[j]) break; - if (jflagsr & (RFR_IM_ACID | RFR_IM_ELEC | RFR_IM_FIRE | RFR_IM_COLD | RFR_IM_POIS)); - - if (r_ptr->flags1 & RF1_FORCE_MAXHP) - power[i] = r_ptr->hdice * r_ptr->hside * 2; - else - power[i] = r_ptr->hdice * (r_ptr->hside + 1); - power[i] = power[i] * (100 + r_ptr->level) / 100; - if (r_ptr->speed > 110) - power[i] = power[i] * (r_ptr->speed * 2 - 110) / 100; - if (r_ptr->speed < 110) - power[i] = power[i] * (r_ptr->speed - 20) / 100; - if (num_taisei > 2) - power[i] = power[i] * (num_taisei*2+5) / 10; - else if (r_ptr->a_ability_flags2 & RF6_INVULNER) - power[i] = power[i] * 4 / 3; - else if (r_ptr->a_ability_flags2 & RF6_HEAL) - power[i] = power[i] * 4 / 3; - else if (r_ptr->a_ability_flags1 & RF5_DRAIN_MANA) - power[i] = power[i] * 11 / 10; - if (r_ptr->flags1 & RF1_RAND_25) - power[i] = power[i] * 9 / 10; - if (r_ptr->flags1 & RF1_RAND_50) - power[i] = power[i] * 9 / 10; - if (r_ptr->flagsr & RFR_RES_ALL) power[i] *= 100000; - if (r_ptr->arena_ratio) power[i] = power[i] * r_ptr->arena_ratio / 100; - - - total += power[i]; - } - for (i=0;i<4;i++) - { - power[i] = total*60/power[i]; - if (tekitou && ((power[i] < 160) || power[i] > 1500)) break; - if ((power[i] < 160) && randint0(20)) break; - if (power[i] < 101) power[i] = 100 + randint1(5); - mon_odds[i] = power[i]; - } - if (i == 4) break; - } -} - -/*! - * @brief モンスター闘技場のメインルーチン - * @return 賭けを開始したか否か - */ -static bool kakutoujou(void) -{ - PRICE maxbet; - PRICE wager; - char out_val[160], tmp_str[80]; - concptr p; - - if ((current_world_ptr->game_turn - old_battle) > TURNS_PER_TICK * 250) - { - battle_monsters(); - old_battle = current_world_ptr->game_turn; - } - - screen_save(); - - /* No money */ - if (p_ptr->au < 1) - { - msg_print(_("おい!おまえ一文なしじゃないか!こっから出ていけ!", "Hey! You don't have gold - get out of here!")); - msg_print(NULL); - screen_load(); - return FALSE; - } - else - { - int i; - - clear_bldg(4, 10); - - prt(_("モンスター 倍率", - "Monsters Odds"), 4, 4); - for (i=0;i<4;i++) - { - char buf[80]; - monster_race *r_ptr = &r_info[battle_mon[i]]; - - sprintf(buf, _("%d) %-58s %4ld.%02ld倍", "%d) %-58s %4ld.%02ld"), i+1, - _(format("%s%s",r_name + r_ptr->name, (r_ptr->flags1 & RF1_UNIQUE) ? "もどき" : " "), - format("%s%s", (r_ptr->flags1 & RF1_UNIQUE) ? "Fake " : "", r_name + r_ptr->name)), - (long int)mon_odds[i]/100, (long int)mon_odds[i]%100); - prt(buf, 5+i, 1); - } - prt(_("どれに賭けますか:", "Which monster: "), 0, 0); - while(1) - { - i = inkey(); - - if (i == ESCAPE) - { - screen_load(); - return FALSE; - } - if (i >= '1' && i <= '4') - { - sel_monster = i-'1'; - battle_odds = mon_odds[sel_monster]; - break; - } - else bell(); - } - - clear_bldg(4, 4); - for (i = 0; i < 4; i++) - if (i != sel_monster) clear_bldg(i + 5, i + 5); - - maxbet = p_ptr->lev * 200; - - /* We can't bet more than we have */ - maxbet = MIN(maxbet, p_ptr->au); - - /* Get the wager */ - strcpy(out_val, ""); - sprintf(tmp_str,_("賭け金 (1-%ld)?", "Your wager (1-%ld) ? "), (long int)maxbet); - /* - * Use get_string() because we may need more than - * the s16b value returned by get_quantity(). - */ - if (get_string(tmp_str, out_val, 32)) - { - /* Strip spaces */ - for (p = out_val; *p == ' '; p++); - - /* Get the wager */ - wager = atol(p); - - if (wager > p_ptr->au) - { - msg_print(_("おい!金が足りないじゃないか!出ていけ!", "Hey! You don't have the gold - get out of here!")); - - msg_print(NULL); - screen_load(); - return (FALSE); - } - else if (wager > maxbet) - { - msg_format(_("%ldゴールドだけ受けよう。残りは取っときな。", "I'll take %ld gold of that. Keep the rest."), (long int)maxbet); - - wager = maxbet; - } - else if (wager < 1) - { - msg_print(_("OK、1ゴールドでいこう。", "Ok, we'll start with 1 gold.")); - wager = 1; - } - msg_print(NULL); - battle_odds = MAX(wager+1, wager * battle_odds / 100); - kakekin = wager; - p_ptr->au -= wager; - reset_tim_flags(); - - /* Save the surface floor as saved floor */ - prepare_change_floor_mode(CFM_SAVE_FLOORS); - - p_ptr->inside_battle = TRUE; - p_ptr->leaving = TRUE; - - leave_bldg = TRUE; - screen_load(); - - return (TRUE); - } - } - screen_load(); - - return (FALSE); -} - -/*! - * @brief 本日の賞金首情報を表示する。 - * @return なし - */ -static void today_target(void) -{ - char buf[160]; - monster_race *r_ptr = &r_info[today_mon]; - - clear_bldg(4,18); - c_put_str(TERM_YELLOW, _("本日の賞金首", "Wanted monster that changes from day to day"), 5, 10); - sprintf(buf,_("ターゲット: %s", "target: %s"),r_name + r_ptr->name); - c_put_str(TERM_YELLOW, buf, 6, 10); - sprintf(buf,_("死体 ---- $%d", "corpse ---- $%d"), (int)r_ptr->level * 50 + 100); - prt(buf, 8, 10); - sprintf(buf,_("骨 ---- $%d", "skeleton ---- $%d"), (int)r_ptr->level * 30 + 60); - prt(buf, 9, 10); - p_ptr->today_mon = today_mon; -} - -/*! - * @brief ツチノコの賞金首情報を表示する。 - * @return なし - */ -static void tsuchinoko(void) -{ - clear_bldg(4,18); - c_put_str(TERM_YELLOW, _("一獲千金の大チャンス!!!", "Big chance to quick money!!!"), 5, 10); - c_put_str(TERM_YELLOW, _("ターゲット:幻の珍獣「ツチノコ」", "target: the rarest animal 'Tsuchinoko'"), 6, 10); - c_put_str(TERM_WHITE, _("生け捕り ---- $1,000,000", "catch alive ---- $1,000,000"), 8, 10); - c_put_str(TERM_WHITE, _("死体 ---- $200,000", "corpse ---- $200,000"), 9, 10); - c_put_str(TERM_WHITE, _("骨 ---- $100,000", "bones ---- $100,000"), 10, 10); -} - -/*! - * @brief 通常の賞金首情報を表示する。 - * @return なし - */ -static void shoukinkubi(void) -{ - int i; - TERM_LEN y = 0; - - clear_bldg(4,18); - prt(_("死体を持ち帰れば報酬を差し上げます。", "Offer a prize when you bring a wanted monster's corpse"),4 ,10); - c_put_str(TERM_YELLOW, _("現在の賞金首", "Wanted monsters"), 6, 10); - - for (i = 0; i < MAX_KUBI; i++) - { - byte color; - concptr done_mark; - monster_race *r_ptr = &r_info[(current_world_ptr->bounty_r_idx[i] > 10000 ? current_world_ptr->bounty_r_idx[i] - 10000 : current_world_ptr->bounty_r_idx[i])]; - - if (current_world_ptr->bounty_r_idx[i] > 10000) - { - color = TERM_RED; - done_mark = _("(済)", "(done)"); - } - else - { - color = TERM_WHITE; - done_mark = ""; - } - - c_prt(color, format("%s %s", r_name + r_ptr->name, done_mark), y+7, 10); - - y = (y+1) % 10; - if (!y && (i < MAX_KUBI -1)) - { - prt(_("何かキーを押してください", "Hit any key."), 0, 0); - (void)inkey(); - prt("", 0, 0); - clear_bldg(7,18); - } - } -} - - - -/*! - * 賞金首の報酬テーブル / List of prize object - */ -static struct { - OBJECT_TYPE_VALUE tval; /*!< ベースアイテムのメイン種別ID */ - OBJECT_SUBTYPE_VALUE sval; /*!< ベースアイテムのサブ種別ID */ -} prize_list[MAX_KUBI] = -{ - {TV_POTION, SV_POTION_CURING}, - {TV_POTION, SV_POTION_SPEED}, - {TV_POTION, SV_POTION_SPEED}, - {TV_POTION, SV_POTION_RESISTANCE}, - {TV_POTION, SV_POTION_ENLIGHTENMENT}, - - {TV_POTION, SV_POTION_HEALING}, - {TV_POTION, SV_POTION_RESTORE_MANA}, - {TV_SCROLL, SV_SCROLL_STAR_DESTRUCTION}, - {TV_POTION, SV_POTION_STAR_ENLIGHTENMENT}, - {TV_SCROLL, SV_SCROLL_SUMMON_PET}, - - {TV_SCROLL, SV_SCROLL_GENOCIDE}, - {TV_POTION, SV_POTION_STAR_HEALING}, - {TV_POTION, SV_POTION_STAR_HEALING}, - {TV_POTION, SV_POTION_NEW_LIFE}, - {TV_SCROLL, SV_SCROLL_MASS_GENOCIDE}, - - {TV_POTION, SV_POTION_LIFE}, - {TV_POTION, SV_POTION_LIFE}, - {TV_POTION, SV_POTION_AUGMENTATION}, - {TV_POTION, SV_POTION_INVULNERABILITY}, - {TV_SCROLL, SV_SCROLL_ARTIFACT}, -}; - -/*! - * @brief 賞金首の引き換え処理 / Get prize - * @return 各種賞金首のいずれかでも換金が行われたか否か。 - */ -static bool kankin(void) -{ - INVENTORY_IDX i; - int j; - bool change = FALSE; - GAME_TEXT o_name[MAX_NLEN]; - object_type *o_ptr; - - /* Loop for inventory and right/left arm */ - for (i = 0; i <= INVEN_LARM; i++) - { - o_ptr = &inventory[i]; - - /* Living Tsuchinoko worthes $1000000 */ - if ((o_ptr->tval == TV_CAPTURE) && (o_ptr->pval == MON_TSUCHINOKO)) - { - char buf[MAX_NLEN+20]; - object_desc(o_name, o_ptr, 0); - sprintf(buf, _("%s を換金しますか?", "Convert %s into money? "),o_name); - if (get_check(buf)) - { - msg_format(_("賞金 %ld$を手に入れた。", "You get %ldgp."), (long int)(1000000L * o_ptr->number)); - p_ptr->au += 1000000L * o_ptr->number; - p_ptr->redraw |= (PR_GOLD); - inven_item_increase(i, -o_ptr->number); - inven_item_describe(i); - inven_item_optimize(i); - } - change = TRUE; - } - } - - for (i = 0; i < INVEN_PACK; i++) - { - o_ptr = &inventory[i]; - - /* Corpse of Tsuchinoko worthes $200000 */ - if ((o_ptr->tval == TV_CORPSE) && (o_ptr->sval == SV_CORPSE) && (o_ptr->pval == MON_TSUCHINOKO)) - { - char buf[MAX_NLEN+20]; - object_desc(o_name, o_ptr, 0); - sprintf(buf, _("%s を換金しますか?", "Convert %s into money? "),o_name); - if (get_check(buf)) - { - msg_format(_("賞金 %ld$を手に入れた。", "You get %ldgp."), (long int)(200000L * o_ptr->number)); - p_ptr->au += 200000L * o_ptr->number; - p_ptr->redraw |= (PR_GOLD); - inven_item_increase(i, -o_ptr->number); - inven_item_describe(i); - inven_item_optimize(i); - } - change = TRUE; - } - } - - for (i = 0; i < INVEN_PACK; i++) - { - o_ptr = &inventory[i]; - - /* Bones of Tsuchinoko worthes $100000 */ - if ((o_ptr->tval == TV_CORPSE) && (o_ptr->sval == SV_SKELETON) && (o_ptr->pval == MON_TSUCHINOKO)) - { - char buf[MAX_NLEN+20]; - object_desc(o_name, o_ptr, 0); - sprintf(buf, _("%s を換金しますか?", "Convert %s into money? "),o_name); - if (get_check(buf)) - { - msg_format(_("賞金 %ld$を手に入れた。", "You get %ldgp."), (long int)(100000L * o_ptr->number)); - p_ptr->au += 100000L * o_ptr->number; - p_ptr->redraw |= (PR_GOLD); - inven_item_increase(i, -o_ptr->number); - inven_item_describe(i); - inven_item_optimize(i); - } - change = TRUE; - } - } - - for (i = 0; i < INVEN_PACK; i++) - { - o_ptr = &inventory[i]; - if ((o_ptr->tval == TV_CORPSE) && (o_ptr->sval == SV_CORPSE) && (streq(r_name + r_info[o_ptr->pval].name, r_name + r_info[today_mon].name))) - { - char buf[MAX_NLEN+20]; - object_desc(o_name, o_ptr, 0); - sprintf(buf, _("%s を換金しますか?", "Convert %s into money? "),o_name); - if (get_check(buf)) - { - msg_format(_("賞金 %ld$を手に入れた。", "You get %ldgp."), (long int)((r_info[today_mon].level * 50 + 100) * o_ptr->number)); - p_ptr->au += (r_info[today_mon].level * 50 + 100) * o_ptr->number; - p_ptr->redraw |= (PR_GOLD); - inven_item_increase(i, -o_ptr->number); - inven_item_describe(i); - inven_item_optimize(i); - } - change = TRUE; - } - } - - for (i = 0; i < INVEN_PACK; i++) - { - o_ptr = &inventory[i]; - - if ((o_ptr->tval == TV_CORPSE) && (o_ptr->sval == SV_SKELETON) && (streq(r_name + r_info[o_ptr->pval].name, r_name + r_info[today_mon].name))) - { - char buf[MAX_NLEN+20]; - object_desc(o_name, o_ptr, 0); - sprintf(buf, _("%s を換金しますか?", "Convert %s into money? "),o_name); - if (get_check(buf)) - { - msg_format(_("賞金 %ld$を手に入れた。", "You get %ldgp."), (long int)((r_info[today_mon].level * 30 + 60) * o_ptr->number)); - p_ptr->au += (r_info[today_mon].level * 30 + 60) * o_ptr->number; - p_ptr->redraw |= (PR_GOLD); - inven_item_increase(i, -o_ptr->number); - inven_item_describe(i); - inven_item_optimize(i); - } - change = TRUE; - } - } - - for (j = 0; j < MAX_KUBI; j++) - { - /* Need reverse order --- Positions will be changed in the loop */ - for (i = INVEN_PACK-1; i >= 0; i--) - { - o_ptr = &inventory[i]; - if ((o_ptr->tval == TV_CORPSE) && (o_ptr->pval == current_world_ptr->bounty_r_idx[j])) - { - char buf[MAX_NLEN+20]; - int num, k; - INVENTORY_IDX item_new; - object_type forge; - - object_desc(o_name, o_ptr, 0); - sprintf(buf, _("%sを渡しますか?", "Hand %s over? "),o_name); - if (!get_check(buf)) continue; - -#if 0 /* Obsoleted */ - msg_format(_("賞金 %ld$を手に入れた。", "You get %ldgp."), (r_info[current_world_ptr->bounty_r_idx[j]].level + 1) * 300 * o_ptr->number); - p_ptr->au += (r_info[current_world_ptr->bounty_r_idx[j]].level+1) * 300 * o_ptr->number; - p_ptr->redraw |= (PR_GOLD); - inven_item_increase(i, -o_ptr->number); - inven_item_describe(i); - inven_item_optimize(i); - chg_virtue(V_JUSTICE, 5); - current_world_ptr->bounty_r_idx[j] += 10000; - - change = TRUE; -#endif /* Obsoleted */ - - /* Hand it first */ - inven_item_increase(i, -o_ptr->number); - inven_item_describe(i); - inven_item_optimize(i); - - chg_virtue(V_JUSTICE, 5); - current_world_ptr->bounty_r_idx[j] += 10000; - - /* Count number of unique corpses already handed */ - for (num = 0, k = 0; k < MAX_KUBI; k++) - { - if (current_world_ptr->bounty_r_idx[k] >= 10000) num++; - } - msg_format(_("これで合計 %d ポイント獲得しました。" ,"You earned %d point%s total."), num, (num > 1 ? "s" : "")); - - /* Prepare to make a prize */ - object_prep(&forge, lookup_kind(prize_list[num-1].tval, prize_list[num-1].sval)); - apply_magic(&forge, current_floor_ptr->object_level, AM_NO_FIXED_ART); - - object_aware(&forge); - object_known(&forge); - - /* - * Hand it --- Assume there is an empty slot. - * Since a corpse is handed at first, - * there is at least one empty slot. - */ - item_new = inven_carry(&forge); - - object_desc(o_name, &forge, 0); - msg_format(_("%s(%c)を貰った。", "You get %s (%c). "), o_name, index_to_label(item_new)); - - /* Auto-inscription */ - autopick_alter_item(item_new, FALSE); - handle_stuff(); - - change = TRUE; - } - } - } - - if (!change) - { - msg_print(_("賞金を得られそうなものは持っていなかった。", "You have nothing.")); - msg_print(NULL); - return FALSE; - } - return TRUE; -} - -/*! - * @brief 宿屋の利用サブルーチン - * @details inn commands\n - * Note that resting for the night was a perfect way to avoid player\n - * ghosts in the town *if* you could only make it to the inn in time (-:\n - * Now that the ghosts are temporarily disabled in 2.8.X, this function\n - * will not be that useful. I will keep it in the hopes the player\n - * ghost code does become a reality again. Does help to avoid filthy urchins.\n - * Resting at night is also a quick way to restock stores -KMW-\n - * @param cmd 宿屋の利用施設ID - * @return 施設の利用が実際に行われたか否か。 - */ -static bool inn_comm(int cmd) -{ - switch (cmd) - { - case BACT_FOOD: /* Buy food & drink */ - if (p_ptr->food >= PY_FOOD_FULL) - { - msg_print(_("今は満腹だ。", "You are full now.")); - return FALSE; - } - msg_print(_("バーテンはいくらかの食べ物とビールをくれた。", "The barkeep gives you some gruel and a beer.")); - (void)set_food(PY_FOOD_MAX - 1); - break; - - case BACT_REST: /* Rest for the night */ - if ((p_ptr->poisoned) || (p_ptr->cut)) - { - msg_print(_("あなたに必要なのは部屋ではなく、治療者です。", "You need a healer, not a room.")); - msg_print(NULL); - msg_print(_("すみません、でもうちで誰かに死なれちゃ困りますんで。", "Sorry, but don't want anyone dying in here.")); - } - else - { - s32b oldturn = current_world_ptr->game_turn; - int prev_day, prev_hour, prev_min; - - extract_day_hour_min(&prev_day, &prev_hour, &prev_min); - if ((prev_hour >= 6) && (prev_hour <= 17)) - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("宿屋に泊まった。", "stay over daytime at the inn.")); - else - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("宿屋に泊まった。", "stay over night at the inn.")); - - current_world_ptr->game_turn = (current_world_ptr->game_turn / (TURNS_PER_TICK * TOWN_DAWN / 2) + 1) * (TURNS_PER_TICK * TOWN_DAWN / 2); - if (current_world_ptr->dungeon_turn < current_world_ptr->dungeon_turn_limit) - { - current_world_ptr->dungeon_turn += MIN((current_world_ptr->game_turn - oldturn), TURNS_PER_TICK * 250) * INN_DUNGEON_TURN_ADJ; - if (current_world_ptr->dungeon_turn > current_world_ptr->dungeon_turn_limit) current_world_ptr->dungeon_turn = current_world_ptr->dungeon_turn_limit; - } - - prevent_turn_overflow(); - - if ((prev_hour >= 18) && (prev_hour <= 23)) do_cmd_write_nikki(NIKKI_HIGAWARI, 0, NULL); - p_ptr->chp = p_ptr->mhp; - - if (ironman_nightmare) - { - msg_print(_("眠りに就くと恐ろしい光景が心をよぎった。", "Horrible visions flit through your mind as you sleep.")); - - /* Have some nightmares */ - while(1) - { - sanity_blast(NULL, FALSE); - if (!one_in_(3)) break; - } - - msg_print(_("あなたは絶叫して目を覚ました。", "You awake screaming.")); - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("悪夢にうなされてよく眠れなかった。", "be troubled by a nightmare.")); - } - else - { - set_blind(0); - set_confused(0); - p_ptr->stun = 0; - p_ptr->chp = p_ptr->mhp; - p_ptr->csp = p_ptr->msp; - if (p_ptr->pclass == CLASS_MAGIC_EATER) - { - int i; - for (i = 0; i < 72; i++) - { - p_ptr->magic_num1[i] = p_ptr->magic_num2[i] * EATER_CHARGE; - } - for (; i < 108; i++) - { - p_ptr->magic_num1[i] = 0; - } - } - - if ((prev_hour >= 6) && (prev_hour <= 17)) - { - msg_print(_("あなたはリフレッシュして目覚め、夕方を迎えた。", "You awake refreshed for the evening.")); - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("夕方を迎えた。", "awake refreshed.")); - } - else - { - msg_print(_("あなたはリフレッシュして目覚め、新たな日を迎えた。", "You awake refreshed for the new day.")); - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("すがすがしい朝を迎えた。", "awake refreshed.")); - } - } - } - break; - - case BACT_RUMORS: /* Listen for rumors */ - { - display_rumor(TRUE); - break; - } - } - - return (TRUE); -} - - -/*! - * @brief クエスト情報を表示しつつ処理する。/ Display quest information - * @param questnum クエストのID - * @param do_init クエストの開始処理(TRUE)、結果処理か(FALSE) - * @return なし - */ -static void get_questinfo(IDX questnum, bool do_init) -{ - int i; - QUEST_IDX old_quest; - GAME_TEXT tmp_str[80]; - - /* Clear the text */ - for (i = 0; i < 10; i++) - { - quest_text[i][0] = '\0'; - } - - quest_text_line = 0; - - /* Set the quest number temporary */ - old_quest = p_ptr->inside_quest; - p_ptr->inside_quest = questnum; - - /* Get the quest text */ - init_flags = INIT_SHOW_TEXT; - if (do_init) init_flags |= INIT_ASSIGN; - - process_dungeon_file("q_info.txt", 0, 0, 0, 0); - - /* Reset the old quest number */ - p_ptr->inside_quest = old_quest; - - /* Print the quest info */ - sprintf(tmp_str, _("クエスト情報 (危険度: %d 階相当)", "Quest Information (Danger level: %d)"), (int)quest[questnum].level); - - prt(tmp_str, 5, 0); - - prt(quest[questnum].name, 7, 0); - - for (i = 0; i < 10; i++) - { - c_put_str(TERM_YELLOW, quest_text[i], i + 8, 0); - } -} - -/*! - * @brief クエスト処理のメインルーチン / Request a quest from the Lord. - * @return なし - */ -static void castle_quest(void) -{ - QUEST_IDX q_index = 0; - monster_race *r_ptr; - quest_type *q_ptr; - concptr name; - - - clear_bldg(4, 18); - - /* Current quest of the building */ - q_index = current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].special; - - /* Is there a quest available at the building? */ - if (!q_index) - { - put_str(_("今のところクエストはありません。", "I don't have a quest for you at the moment."), 8, 0); - return; - } - - q_ptr = &quest[q_index]; - - /* Quest is completed */ - if (q_ptr->status == QUEST_STATUS_COMPLETED) - { - /* Rewarded quest */ - q_ptr->status = QUEST_STATUS_REWARDED; - - get_questinfo(q_index, FALSE); - - reinit_wilderness = TRUE; - } - /* Failed quest */ - else if (q_ptr->status == QUEST_STATUS_FAILED) - { - get_questinfo(q_index, FALSE); - - /* Mark quest as done (but failed) */ - q_ptr->status = QUEST_STATUS_FAILED_DONE; - - reinit_wilderness = TRUE; - } - /* Quest is still unfinished */ - else if (q_ptr->status == QUEST_STATUS_TAKEN) - { - put_str(_("あなたは現在のクエストを終了させていません!", "You have not completed your current quest yet!"), 8, 0); - put_str(_("CTRL-Qを使えばクエストの状態がチェックできます。", "Use CTRL-Q to check the status of your quest."), 9, 0); - put_str(_("クエストを終わらせたら戻って来て下さい。", "Return when you have completed your quest."), 12, 0); - } - /* No quest yet */ - else if (q_ptr->status == QUEST_STATUS_UNTAKEN) - { - q_ptr->status = QUEST_STATUS_TAKEN; - - reinit_wilderness = TRUE; - - /* Assign a new quest */ - if (q_ptr->type == QUEST_TYPE_KILL_ANY_LEVEL) - { - if (q_ptr->r_idx == 0) - { - /* Random monster at least 5 - 10 levels out of deep */ - q_ptr->r_idx = get_mon_num(q_ptr->level + 4 + randint1(6)); - } - - r_ptr = &r_info[q_ptr->r_idx]; - - while ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->rarity != 1)) - { - q_ptr->r_idx = get_mon_num(q_ptr->level) + 4 + randint1(6); - r_ptr = &r_info[q_ptr->r_idx]; - } - - if (q_ptr->max_num == 0) - { - /* Random monster number */ - if (randint1(10) > 7) - q_ptr->max_num = 1; - else - q_ptr->max_num = randint1(3) + 1; - } - - q_ptr->cur_num = 0; - name = (r_name + r_ptr->name); - msg_format(_("クエスト: %sを %d体倒す", "Your quest: kill %d %s"), name,q_ptr->max_num); - } - else - { - get_questinfo(q_index, TRUE); - } - } -} - - -/*! - * @brief 町に関するヘルプを表示する / Display town history - * @return なし - */ -static void town_history(void) -{ - screen_save(); - - /* Peruse the building help file */ - (void)show_file(TRUE, _("jbldg.txt", "bldg.txt"), NULL, 0, 0); - screen_load(); -} - -/*! - * @brief 射撃時クリティカルによるダメージ期待値修正計算(スナイパーの集中処理と武器経験値) / critical happens at i / 10000 - * @param plus_ammo 矢弾のダメージ修正 - * @param plus_bow 弓のダメージ修正 - * @return ダメージ期待値 - * @note 基本ダメージ量と重量はこの部位では計算に加わらない。 - */ -HIT_POINT calc_crit_ratio_shot(HIT_POINT plus_ammo, HIT_POINT plus_bow) -{ - HIT_POINT i; - object_type *j_ptr = &inventory[INVEN_BOW]; - - /* Extract "shot" power */ - i = p_ptr->to_h_b + plus_ammo; - - if (p_ptr->tval_ammo == TV_BOLT) - i = (p_ptr->skill_thb + (p_ptr->weapon_exp[0][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ); - else - i = (p_ptr->skill_thb + ((p_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + i) * BTH_PLUS_ADJ); - - /* Snipers can shot more critically with crossbows */ - if (p_ptr->concent) i += ((i * p_ptr->concent) / 5); - if ((p_ptr->pclass == CLASS_SNIPER) && (p_ptr->tval_ammo == TV_BOLT)) i *= 2; - - /* Good bow makes more critical */ - i += plus_bow * 8 * (p_ptr->concent ? p_ptr->concent + 5 : 5); - - if (i < 0) i = 0; - - return i; -} - -/*! - * @brief 射撃時クリティカルによるダメージ期待値修正計算(重量依存部分) / critical happens at i / 10000 - * @param weight 武器の重量 - * @param plus_ammo 矢弾のダメージ修正 - * @param plus_bow 弓のダメージ修正 - * @param dam 基本ダメージ量 - * @return ダメージ期待値 - */ -HIT_POINT calc_expect_crit_shot(WEIGHT weight, int plus_ammo, int plus_bow, HIT_POINT dam) -{ - u32b num; - int i, k, crit; - i = calc_crit_ratio_shot(plus_ammo, plus_bow); - - k = 0; - num = 0; - - crit = MIN(500, 900/weight); - num += dam * 3 /2 * crit; - k = crit; - - crit = MIN(500, 1350/weight); - crit -= k; - num += dam * 2 * crit; - k += crit; - - if(k < 500) - { - crit = 500 - k; - num += dam * 3 * crit; - } - - num /= 500; - - num *= i; - num += (10000 - i) * dam; - num /= 10000; - - return num; -} - -/*! - * @brief 攻撃時クリティカルによるダメージ期待値修正計算(重量と毒針処理) / critical happens at i / 10000 - * @param weight 武器の重量 - * @param plus 武器のダメージ修正 - * @param dam 基本ダメージ - * @param meichuu 命中値 - * @param dokubari 毒針処理か否か - * @return ダメージ期待値 - */ -HIT_POINT calc_expect_crit(WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, bool dokubari) -{ - u32b k, num; - int i; - - if(dokubari) return dam; - - i = (weight + (meichuu * 3 + plus * 5) + p_ptr->skill_thn); - if (i < 0) i = 0; - - k = weight; - num = 0; - - if (k < 400) num += (2 * dam + 5) * (400 - k); - if (k < 700) num += (2 * dam + 10) * (MIN(700, k + 650) - MAX(400, k)); - if (k > (700 - 650) && k < 900) num += (3 * dam + 15) * (MIN(900, k + 650) - MAX(700, k)); - if (k > (900 - 650) && k < 1300) num += (3 * dam + 20) * (MIN(1300, k + 650) - MAX(900, k)); - if (k > (1300 - 650)) num += (7 * dam / 2 + 25) * MIN(650, k - (1300 - 650)); - - num /= 650; - if(p_ptr->pclass == CLASS_NINJA) - { - num *= i; - num += (4444 - i) * dam; - num /= 4444; - } - else - { - num *= i; - num += (5000 - i) * dam; - num /= 5000; - } - - return num; -} - -/*! - * @brief 攻撃時スレイによるダメージ期待値修正計算 / critical happens at i / 10000 - * @param dam 基本ダメージ - * @param mult スレイ倍率(掛け算部分) - * @param div スレイ倍率(割り算部分) - * @param force 理力特別計算フラグ - * @return ダメージ期待値 - */ -static HIT_POINT calc_slaydam(HIT_POINT dam, int mult, int div, bool force) -{ - int tmp; - if(force) - { - tmp = dam * 60; - tmp *= mult * 3; - tmp /= div * 2; - tmp += dam * 60 * 2; - tmp /= 60; - } - else - { - tmp = dam * 60; - tmp *= mult; - tmp /= div; - tmp /= 60; - } - return tmp; -} - -/*! - * @brief 攻撃時の期待値計算(スレイ→重量クリティカル→切れ味効果) - * @param dam 基本ダメージ - * @param mult スレイ倍率(掛け算部分) - * @param div スレイ倍率(割り算部分) - * @param force 理力特別計算フラグ - * @param weight 重量 - * @param plus 武器ダメージ修正 - * @param meichuu 命中値 - * @param dokubari 毒針処理か否か - * @param vorpal_mult 切れ味倍率(掛け算部分) - * @param vorpal_div 切れ味倍率(割り算部分) - * @return ダメージ期待値 - */ -static u32b calc_expect_dice(u32b dam, int mult, int div, bool force, WEIGHT weight, int plus, s16b meichuu, bool dokubari, int vorpal_mult, int vorpal_div) -{ - dam = calc_slaydam(dam, mult, div, force); - dam = calc_expect_crit(weight, plus, dam, meichuu, dokubari); - dam = calc_slaydam(dam, vorpal_mult, vorpal_div, FALSE); - return dam; -} - - -/*! - * @brief 武器の各条件毎のダメージ期待値を表示する。 - * @param r 表示行 - * @param c 表示列 - * @param mindice ダイス部分最小値 - * @param maxdice ダイス部分最大値 - * @param blows 攻撃回数 - * @param dam_bonus ダメージ修正値 - * @param attr 条件内容 - * @param color 条件内容の表示色 - * @details - * Display the damage figure of an object\n - * (used by compare_weapon_aux)\n - * \n - * Only accurate for the current weapon, because it includes\n - * the current +dam of the player.\n - * @return なし - */ -static void show_weapon_dmg(int r, int c, int mindice, int maxdice, int blows, int dam_bonus, concptr attr, byte color) -{ - GAME_TEXT tmp_str[80]; - int mindam, maxdam; - - mindam = blows * (mindice + dam_bonus); - maxdam = blows * (maxdice + dam_bonus); - - /* Print the intro text */ - c_put_str(color, attr, r, c); - - /* Calculate the min and max damage figures */ - sprintf(tmp_str, _("1ターン: %d-%d ダメージ", "Attack: %d-%d damage"), mindam, maxdam); - - /* Print the damage */ - put_str(tmp_str, r, c + 8); -} - - -/*! - * @brief 武器一つ毎のダメージ情報を表示する。 - * @param o_ptr オブジェクトの構造体の参照ポインタ。 - * @param col 表示する行の上端 - * @param r 表示する列の左端 - * @details - * Show the damage figures for the various monster types\n - * \n - * Only accurate for the current weapon, because it includes\n - * the current number of blows for the player.\n - * @return なし - */ -static void compare_weapon_aux(object_type *o_ptr, int col, int r) -{ - BIT_FLAGS flgs[TR_FLAG_SIZE]; - int blow = p_ptr->num_blow[0]; - bool force = FALSE; - bool dokubari = FALSE; - - /* Effective dices */ - int eff_dd = o_ptr->dd + p_ptr->to_dd[0]; - int eff_ds = o_ptr->ds + p_ptr->to_ds[0]; - - int mindice = eff_dd; - int maxdice = eff_ds * eff_dd; - int mindam = 0; - int maxdam = 0; - int vorpal_mult = 1; - int vorpal_div = 1; - int dmg_bonus = o_ptr->to_d + p_ptr->to_d[0]; - - - /* Get the flags of the weapon */ - object_flags(o_ptr, flgs); - - if((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_DOKUBARI)) dokubari = TRUE; - - - /* Show Critical Damage*/ - mindam = calc_expect_crit(o_ptr->weight, o_ptr->to_h, mindice, p_ptr->to_h[0], dokubari); - maxdam = calc_expect_crit(o_ptr->weight, o_ptr->to_h, maxdice, p_ptr->to_h[0], dokubari); - - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("会心:", "Critical:"), TERM_L_RED); - - - /* Vorpal Hit*/ - if ((have_flag(flgs, TR_VORPAL) || hex_spelling(HEX_RUNESWORD))) - { - if((o_ptr->name1 == ART_VORPAL_BLADE) || (o_ptr->name1 == ART_CHAINSWORD)) - { - vorpal_mult = 5; - vorpal_div = 3; - } - else - { - vorpal_mult = 11; - vorpal_div = 9; - } - - mindam = calc_expect_dice(mindice, 1, 1, FALSE, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 1, 1, FALSE, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("切れ味:", "Vorpal:") , TERM_L_RED); - } - - if ((p_ptr->pclass != CLASS_SAMURAI) && have_flag(flgs, TR_FORCE_WEAPON) && (p_ptr->csp > (o_ptr->dd * o_ptr->ds / 5))) - { - force = TRUE; - - mindam = calc_expect_dice(mindice, 1, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 1, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("理力:", "Force :"), TERM_L_BLUE); - } - - /* Print the relevant lines */ - if (have_flag(flgs, TR_KILL_ANIMAL)) - { - mindam = calc_expect_dice(mindice, 4, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 4, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("動物:", "Animals:"), TERM_YELLOW); - } - else if (have_flag(flgs, TR_SLAY_ANIMAL)) - { - mindam = calc_expect_dice(mindice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("動物:", "Animals:"), TERM_YELLOW); - } - if (have_flag(flgs, TR_KILL_EVIL)) - { - mindam = calc_expect_dice(mindice, 7, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 7, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("邪悪:", "Evil:"), TERM_YELLOW); - } - else if (have_flag(flgs, TR_SLAY_EVIL)) - { - mindam = calc_expect_dice(mindice, 2, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 2, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("邪悪:", "Evil:"), TERM_YELLOW); - } - if (have_flag(flgs, TR_KILL_HUMAN)) - { - mindam = calc_expect_dice(mindice, 4, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 4, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("人間:", "Human:"), TERM_YELLOW); - } - else if (have_flag(flgs, TR_SLAY_HUMAN)) - { - mindam = calc_expect_dice(mindice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("人間:", "Human:"), TERM_YELLOW); - } - if (have_flag(flgs, TR_KILL_UNDEAD)) - { - mindam = calc_expect_dice(mindice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("不死:", "Undead:"), TERM_YELLOW); - } - else if (have_flag(flgs, TR_SLAY_UNDEAD)) - { - mindam = calc_expect_dice(mindice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("不死:", "Undead:"), TERM_YELLOW); - } - if (have_flag(flgs, TR_KILL_DEMON)) - { - mindam = calc_expect_dice(mindice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("悪魔:", "Demons:") , TERM_YELLOW); - } - else if (have_flag(flgs, TR_SLAY_DEMON)) - { - mindam = calc_expect_dice(mindice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("悪魔:", "Demons:") , TERM_YELLOW); - } - if (have_flag(flgs, TR_KILL_ORC)) - { - mindam = calc_expect_dice(mindice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("オーク:", "Orcs:"), TERM_YELLOW); - } - else if (have_flag(flgs, TR_SLAY_ORC)) - { - mindam = calc_expect_dice(mindice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("オーク:", "Orcs:"), TERM_YELLOW); - } - if (have_flag(flgs, TR_KILL_TROLL)) - { - mindam = calc_expect_dice(mindice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("トロル:", "Trolls:") , TERM_YELLOW); - } - else if (have_flag(flgs, TR_SLAY_TROLL)) - { - mindam = calc_expect_dice(mindice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("トロル:", "Trolls:") , TERM_YELLOW); - } - if (have_flag(flgs, TR_KILL_GIANT)) - { - mindam = calc_expect_dice(mindice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("巨人:", "Giants:"), TERM_YELLOW); - } - else if (have_flag(flgs, TR_SLAY_GIANT)) - { - mindam = calc_expect_dice(mindice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("巨人:", "Giants:"), TERM_YELLOW); - } - if (have_flag(flgs, TR_KILL_DRAGON)) - { - mindam = calc_expect_dice(mindice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("竜:", "Dragons:"), TERM_YELLOW); - } - else if (have_flag(flgs, TR_SLAY_DRAGON)) - { - mindam = calc_expect_dice(mindice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 3, 1, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("竜:", "Dragons:"), TERM_YELLOW); - } - if (have_flag(flgs, TR_BRAND_ACID)) - { - mindam = calc_expect_dice(mindice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("酸属性:", "Acid:"), TERM_RED); - } - if (have_flag(flgs, TR_BRAND_ELEC)) - { - mindam = calc_expect_dice(mindice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("電属性:", "Elec:"), TERM_RED); - } - if (have_flag(flgs, TR_BRAND_FIRE)) - { - mindam = calc_expect_dice(mindice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("炎属性:", "Fire:"), TERM_RED); - } - if (have_flag(flgs, TR_BRAND_COLD)) - { - mindam = calc_expect_dice(mindice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("冷属性:", "Cold:"), TERM_RED); - } - if (have_flag(flgs, TR_BRAND_POIS)) - { - mindam = calc_expect_dice(mindice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - maxdam = calc_expect_dice(maxdice, 5, 2, force, o_ptr->weight, o_ptr->to_h, p_ptr->to_h[0], dokubari, vorpal_mult, vorpal_div); - show_weapon_dmg(r++, col, mindam, maxdam, blow, dmg_bonus, _("毒属性:", "Poison:"), TERM_RED); - } -} - -/*! - * @brief 武器匠における武器一つ毎の完全情報を表示する。 - * @param o_ptr オブジェクトの構造体の参照ポインタ。 - * @param row 表示する列の左端 - * @param col 表示する行の上端 - * @details - * Displays all info about a weapon - * - * Only accurate for the current weapon, because it includes - * various info about the player's +to_dam and number of blows. - * @return なし - */ -static void list_weapon(object_type *o_ptr, TERM_LEN row, TERM_LEN col) -{ - GAME_TEXT o_name[MAX_NLEN]; - GAME_TEXT tmp_str[80]; - - DICE_NUMBER eff_dd = o_ptr->dd + p_ptr->to_dd[0]; - DICE_SID eff_ds = o_ptr->ds + p_ptr->to_ds[0]; - HIT_RELIABILITY reli = p_ptr->skill_thn + (p_ptr->to_h[0] + o_ptr->to_h) * BTH_PLUS_ADJ; - - /* Print the weapon name */ - object_desc(o_name, o_ptr, OD_NAME_ONLY); - c_put_str(TERM_YELLOW, o_name, row, col); - - /* Print the player's number of blows */ - sprintf(tmp_str, _("攻撃回数: %d", "Number of Blows: %d"), p_ptr->num_blow[0]); - put_str(tmp_str, row+1, col); - - /* Print to_hit and to_dam of the weapon */ - sprintf(tmp_str, _("命中率: 0 50 100 150 200 (敵のAC)", "To Hit: 0 50 100 150 200 (AC)")); - put_str(tmp_str, row+2, col); - - /* Print the weapons base damage dice */ - sprintf(tmp_str, " %2d %2d %2d %2d %2d (%%)", - (int)hit_chance(reli, 0), - (int)hit_chance(reli, 50), - (int)hit_chance(reli, 100), - (int)hit_chance(reli, 150), - (int)hit_chance(reli, 200)); - put_str(tmp_str, row+3, col); - c_put_str(TERM_YELLOW, _("可能なダメージ:", "Possible Damage:"), row+5, col); - - /* Damage for one blow (if it hits) */ - sprintf(tmp_str, _("攻撃一回につき %d-%d", "One Strike: %d-%d damage"), - (int)(eff_dd + o_ptr->to_d + p_ptr->to_d[0]), - (int)(eff_ds * eff_dd + o_ptr->to_d + p_ptr->to_d[0])); - put_str(tmp_str, row+6, col+1); - - /* Damage for the complete attack (if all blows hit) */ - sprintf(tmp_str, _("1ターンにつき %d-%d", "One Attack: %d-%d damage"), - (int)(p_ptr->num_blow[0] * (eff_dd + o_ptr->to_d + p_ptr->to_d[0])), - (int)(p_ptr->num_blow[0] * (eff_ds * eff_dd + o_ptr->to_d + p_ptr->to_d[0]))); - put_str(tmp_str, row+7, col+1); -} - -/*! - * @brief 武器匠鑑定1回分(オブジェクト2種)の処理。/ Compare weapons - * @details - * Copies the weapons to compare into the weapon-slot and\n - * compares the values for both weapons.\n - * 武器1つだけで比較をしないなら費用は半額になる。 - * @param bcost 基本鑑定費用 - * @return 最終的にかかった費用 - */ -static PRICE compare_weapons(PRICE bcost) -{ - int i, n; - OBJECT_IDX item, item2; - object_type *o_ptr[2]; - object_type orig_weapon; - object_type *i_ptr; - concptr q, s; - TERM_LEN row = 2; - TERM_LEN wid = 38, mgn = 2; - bool old_character_xtra = character_xtra; - char ch; - PRICE total = 0; - PRICE cost = 0; /* First time no price */ - - screen_save(); - clear_bldg(0, 22); - - /* Store copy of original wielded weapon */ - i_ptr = &inventory[INVEN_RARM]; - object_copy(&orig_weapon, i_ptr); - - item_tester_hook = item_tester_hook_orthodox_melee_weapons; - - /* Get the first weapon */ - q = _("第一の武器は?", "What is your first weapon? "); - s = _("比べるものがありません。", "You have nothing to compare."); - - o_ptr[0] = choose_object(&item, q, s, (USE_EQUIP | USE_INVEN | IGNORE_BOTHHAND_SLOT)); - if (!o_ptr[0]) - { - screen_load(); - return (0); - } - - n = 1; - total = bcost; - - while (TRUE) - { - clear_bldg(0, 22); - - /* Only compare melee weapons */ - item_tester_hook = item_tester_hook_orthodox_melee_weapons; - - /* Hack -- prevent "icky" message */ - character_xtra = TRUE; - - /* Diaplay selected weapon's infomation */ - for (i = 0; i < n; i++) - { - int col = (wid * i + mgn); - - /* Copy i-th weapon into the weapon slot (if it's not already there) */ - if (o_ptr[i] != i_ptr) object_copy(i_ptr, o_ptr[i]); - - p_ptr->update |= PU_BONUS; - handle_stuff(); - - /* List the new values */ - list_weapon(o_ptr[i], row, col); - compare_weapon_aux(o_ptr[i], col, row + 8); - - /* Copy back the original weapon into the weapon slot */ - object_copy(i_ptr, &orig_weapon); - } - - /* Reset the values for the old weapon */ - p_ptr->update |= PU_BONUS; - handle_stuff(); - - character_xtra = old_character_xtra; - -#ifdef JP - put_str(format("[ 比較対象: 's'で変更 ($%d) ]", cost), 1, (wid + mgn)); - put_str("(一番高いダメージが適用されます。複数の倍打効果は足し算されません。)", row + 4, 0); - prt("現在の技量から判断すると、あなたの武器は以下のような威力を発揮します:", 0, 0); -#else - put_str(format("[ 's' Select secondary weapon($%d) ]", cost), row + 1, (wid * i + mgn)); - put_str("(Only highest damage applies per monster. Special damage not cumulative.)", row + 4, 0); - prt("Based on your current abilities, here is what your weapons will do", 0, 0); -#endif - - flush(); - ch = inkey(); - - if (ch == 's') - { - if (total + cost > p_ptr->au) - { - msg_print(_("お金が足りません!", "You don't have enough money!")); - msg_print(NULL); - continue; - } - - q = _("第二の武器は?", "What is your second weapon? "); - s = _("比べるものがありません。", "You have nothing to compare."); - - /* Get the second weapon */ - o_ptr[1] = choose_object(&item2, q, s, (USE_EQUIP | USE_INVEN | IGNORE_BOTHHAND_SLOT)); - if (!o_ptr[1]) continue; - - total += cost; - cost = bcost / 2; - n = 2; - } - else - { - break; - } - } - screen_load(); - - return (total); -} - - -/*! - * @brief ACから回避率、ダメージ減少率を計算し表示する。 / Evaluate AC - * @details - * Calculate and display the dodge-rate and the protection-rate - * based on AC - * @param iAC プレイヤーのAC。 - * @return 常にTRUEを返す。 - */ -static bool eval_ac(ARMOUR_CLASS iAC) -{ -#ifdef JP - const char memo[] = - "ダメージ軽減率とは、敵の攻撃が当たった時そのダメージを\n" - "何パーセント軽減するかを示します。\n" - "ダメージ軽減は通常の直接攻撃(種類が「攻撃する」と「粉砕する」の物)\n" - "に対してのみ効果があります。\n \n" - "敵のレベルとは、その敵が通常何階に現れるかを示します。\n \n" - "回避率は敵の直接攻撃を何パーセントの確率で避けるかを示し、\n" - "敵のレベルとあなたのACによって決定されます。\n \n" - "ダメージ期待値とは、敵の100ポイントの通常攻撃に対し、\n" - "回避率とダメージ軽減率を考慮したダメージの期待値を示します。\n"; -#else - const char memo[] = - "'Protection Rate' means how much damage is reduced by your armor.\n" - "Note that the Protection rate is effective only against normal " - "'attack' and 'shatter' type melee attacks, " - "and has no effect against any other types such as 'poison'.\n \n" - "'Dodge Rate' indicates the success rate on dodging the " - "monster's melee attacks. " - "It is depend on the level of the monster and your AC.\n \n" - "'Average Damage' indicates the expected amount of damage " - "when you are attacked by normal melee attacks with power=100."; -#endif - - int protection; - TERM_LEN col, row = 2; - DEPTH lvl; - char buf[80*20], *t; - - /* AC lower than zero has no effect */ - if (iAC < 0) iAC = 0; - - /* ダメージ軽減率を計算 */ - protection = 100 * MIN(iAC, 150) / 250; - - screen_save(); - clear_bldg(0, 22); - - put_str(format(_("あなたの現在のAC: %3d", "Your current AC : %3d"), iAC), row++, 0); - put_str(format(_("ダメージ軽減率 : %3d%%", "Protection rate : %3d%%"), protection), row++, 0); - row++; - - put_str(_("敵のレベル :", "Level of Monster:"), row + 0, 0); - put_str(_("回避率 :", "Dodge Rate :"), row + 1, 0); - put_str(_("ダメージ期待値 :", "Average Damage :"), row + 2, 0); - - for (col = 17 + 1, lvl = 0; lvl <= 100; lvl += 10, col += 5) - { - int quality = 60 + lvl * 3; /* attack quality with power 60 */ - int dodge; /* 回避率(%) */ - int average; /* ダメージ期待値 */ - - put_str(format("%3d", lvl), row + 0, col); - - /* 回避率を計算 */ - dodge = 5 + (MIN(100, 100 * (iAC * 3 / 4) / quality) * 9 + 5) / 10; - put_str(format("%3d%%", dodge), row + 1, col); - - /* 100点の攻撃に対してのダメージ期待値を計算 */ - average = (100 - dodge) * (100 - protection) / 100; - put_str(format("%3d", average), row + 2, col); - } - - /* Display note */ - roff_to_buf(memo, 70, buf, sizeof(buf)); - for (t = buf; t[0]; t += strlen(t) + 1) - put_str(t, (row++) + 4, 4); - - prt(_("現在のあなたの装備からすると、あなたの防御力はこれくらいです:", "Defense abilities from your current Armor Class are evaluated below."), 0, 0); - - flush(); - (void)inkey(); - screen_load(); - - return (TRUE); -} - - - -/*! - * @brief 修復材料のオブジェクトから修復対象に特性を移植する。 - * @param to_ptr 修復対象オブジェクトの構造体の参照ポインタ。 - * @param from_ptr 修復材料オブジェクトの構造体の参照ポインタ。 - * @return 修復対象になるならTRUEを返す。 - */ -static void give_one_ability_of_object(object_type *to_ptr, object_type *from_ptr) -{ - int i, n = 0; - int cand[TR_FLAG_MAX]; - BIT_FLAGS to_flgs[TR_FLAG_SIZE]; - BIT_FLAGS from_flgs[TR_FLAG_SIZE]; - - object_flags(to_ptr, to_flgs); - object_flags(from_ptr, from_flgs); - - for (i = 0; i < TR_FLAG_MAX; i++) - { - switch (i) - { - case TR_IGNORE_ACID: - case TR_IGNORE_ELEC: - case TR_IGNORE_FIRE: - case TR_IGNORE_COLD: - case TR_ACTIVATE: - case TR_RIDING: - case TR_THROW: - case TR_SHOW_MODS: - case TR_HIDE_TYPE: - case TR_ES_ATTACK: - case TR_ES_AC: - case TR_FULL_NAME: - case TR_FIXED_FLAVOR: - break; - default: - if (have_flag(from_flgs, i) && !have_flag(to_flgs, i)) - { - if (!(is_pval_flag(i) && (from_ptr->pval < 1))) cand[n++] = i; - } - } - } - - if (n > 0) - { - int bmax; - int tr_idx = cand[randint0(n)]; - add_flag(to_ptr->art_flags, tr_idx); - if (is_pval_flag(tr_idx)) to_ptr->pval = MAX(to_ptr->pval, 1); - bmax = MIN(3, MAX(1, 40 / (to_ptr->dd * to_ptr->ds))); - if (tr_idx == TR_BLOWS) to_ptr->pval = MIN(to_ptr->pval, bmax); - if (tr_idx == TR_SPEED) to_ptr->pval = MIN(to_ptr->pval, 4); - } - - return; -} - -/*! - * @brief アイテム修復処理のメインルーチン / Repair broken weapon - * @param bcost 基本修復費用 - * @return 実際にかかった費用 - */ -static PRICE repair_broken_weapon_aux(PRICE bcost) -{ - PRICE cost; - OBJECT_IDX item, mater; - object_type *o_ptr, *mo_ptr; /* broken weapon and material weapon */ - object_kind *k_ptr; - int i, dd_bonus, ds_bonus; - KIND_OBJECT_IDX k_idx; - char basenm[MAX_NLEN]; - concptr q, s; - int row = 7; - clear_bldg(0, 22); - - prt(_("修復には材料となるもう1つの武器が必要です。", "Hand one material weapon to repair a broken weapon."), row, 2); - prt(_("材料に使用した武器はなくなります!", "The material weapon will disappear after repairing!!"), row+1, 2); - - q = _("どの折れた武器を修復しますか?", "Repair which broken weapon? "); - s = _("修復できる折れた武器がありません。", "You have no broken weapon to repair."); - - /* Only forge broken weapons */ - item_tester_hook = item_tester_hook_broken_weapon; - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_EQUIP)); - if (!o_ptr) return (0); - - /* It is worthless */ - if (!object_is_ego(o_ptr) && !object_is_artifact(o_ptr)) - { - msg_format(_("それは直してもしょうがないぜ。", "It is worthless to repair.")); - return (0); - } - - /* They are too many */ - if (o_ptr->number > 1) - { - msg_format(_("一度に複数を修復することはできません!", "They are too many to repair at once!")); - return (0); - } - - /* Display item name */ - object_desc(basenm, o_ptr, OD_NAME_ONLY); - prt(format(_("修復する武器 : %s", "Repairing: %s"), basenm), row+3, 2); - - q = _("材料となる武器は?", "Which weapon for material? "); - s = _("材料となる武器がありません。", "You have no material to repair."); - - /* Only forge broken weapons */ - item_tester_hook = item_tester_hook_orthodox_melee_weapons; - - mo_ptr = choose_object(&mater, q, s, (USE_INVEN | USE_EQUIP)); - if (!mo_ptr) return (0); - if (mater == item) - { - msg_print(_("クラインの壷じゃない!", "This is not a klein bottle!")); - return (0); - } - - /* Display item name */ - object_desc(basenm, mo_ptr, OD_NAME_ONLY); - prt(format(_("材料とする武器: %s", "Material : %s"), basenm), row+4, 2); - - /* Get the value of one of the items (except curses) */ - cost = bcost + object_value_real(o_ptr) * 2; - - if (!get_check(format(_("$%dかかりますがよろしいですか? ", "Costs %d gold, okay? "), cost))) return (0); - - /* Check if the player has enough money */ - if (p_ptr->au < cost) - { - object_desc(basenm, o_ptr, OD_NAME_ONLY); - msg_format(_("%sを修復するだけのゴールドがありません!", "You do not have the gold to repair %s!"), basenm); - msg_print(NULL); - return (0); - } - - p_ptr->total_weight -= o_ptr->weight; - - if (o_ptr->sval == SV_BROKEN_DAGGER) - { - KIND_OBJECT_IDX j; - int n = 1; - - /* Suppress compiler warning */ - k_idx = 0; - - for (j = 1; j < max_k_idx; j++) - { - object_kind *k_aux_ptr = &k_info[j]; - - if (k_aux_ptr->tval != TV_SWORD) continue; - if ((k_aux_ptr->sval == SV_BROKEN_DAGGER) || - (k_aux_ptr->sval == SV_BROKEN_SWORD) || - (k_aux_ptr->sval == SV_DOKUBARI)) continue; - if (k_aux_ptr->weight > 99) continue; - - if (one_in_(n)) - { - k_idx = j; - n++; - } - } - } - else /* TV_BROKEN_SWORD */ - { - /* Repair to a sword or sometimes material's type weapon */ - OBJECT_TYPE_VALUE tval = (one_in_(5) ? mo_ptr->tval : TV_SWORD); - - while(1) - { - object_kind *ck_ptr; - - k_idx = lookup_kind(tval, SV_ANY); - ck_ptr = &k_info[k_idx]; - - if (tval == TV_SWORD) - { - if ((ck_ptr->sval == SV_BROKEN_DAGGER) || - (ck_ptr->sval == SV_BROKEN_SWORD) || - (ck_ptr->sval == SV_DIAMOND_EDGE) || - (ck_ptr->sval == SV_DOKUBARI)) continue; - } - if (tval == TV_POLEARM) - { - if ((ck_ptr->sval == SV_DEATH_SCYTHE) || - (ck_ptr->sval == SV_TSURIZAO)) continue; - } - if (tval == TV_HAFTED) - { - if ((ck_ptr->sval == SV_GROND) || - (ck_ptr->sval == SV_WIZSTAFF) || - (ck_ptr->sval == SV_NAMAKE_HAMMER)) continue; - } - - break; - } - } - - /* Calculate dice bonuses */ - dd_bonus = o_ptr->dd - k_info[o_ptr->k_idx].dd; - ds_bonus = o_ptr->ds - k_info[o_ptr->k_idx].ds; - dd_bonus += mo_ptr->dd - k_info[mo_ptr->k_idx].dd; - ds_bonus += mo_ptr->ds - k_info[mo_ptr->k_idx].ds; - - /* Change base object */ - k_ptr = &k_info[k_idx]; - o_ptr->k_idx = k_idx; - o_ptr->weight = k_ptr->weight; - o_ptr->tval = k_ptr->tval; - o_ptr->sval = k_ptr->sval; - o_ptr->dd = k_ptr->dd; - o_ptr->ds = k_ptr->ds; - - /* Copy base object's ability */ - for (i = 0; i < TR_FLAG_SIZE; i++) o_ptr->art_flags[i] |= k_ptr->flags[i]; - if (k_ptr->pval) o_ptr->pval = MAX(o_ptr->pval, randint1(k_ptr->pval)); - if (have_flag(k_ptr->flags, TR_ACTIVATE)) o_ptr->xtra2 = (byte_hack)k_ptr->act_idx; - - /* Dice up */ - if (dd_bonus > 0) - { - o_ptr->dd++; - for (i = 1; i < dd_bonus; i++) - { - if (one_in_(o_ptr->dd + i)) o_ptr->dd++; - } - } - if (ds_bonus > 0) - { - o_ptr->ds++; - for (i = 1; i < ds_bonus; i++) - { - if (one_in_(o_ptr->ds + i)) o_ptr->ds++; - } - } - - if (have_flag(k_ptr->flags, TR_BLOWS)) - { - int bmax = MIN(3, MAX(1, 40 / (o_ptr->dd * o_ptr->ds))); - o_ptr->pval = MIN(o_ptr->pval, bmax); - } - - /* Add one random ability from material weapon */ - give_one_ability_of_object(o_ptr, mo_ptr); - - /* Add to-dam, to-hit and to-ac from material weapon */ - o_ptr->to_d += MAX(0, (mo_ptr->to_d / 3)); - o_ptr->to_h += MAX(0, (mo_ptr->to_h / 3)); - o_ptr->to_a += MAX(0, (mo_ptr->to_a)); - - if ((o_ptr->name1 == ART_NARSIL) || - (object_is_random_artifact(o_ptr) && one_in_(1)) || - (object_is_ego(o_ptr) && one_in_(7))) - { - /* Forge it */ - if (object_is_ego(o_ptr)) - { - add_flag(o_ptr->art_flags, TR_IGNORE_FIRE); - add_flag(o_ptr->art_flags, TR_IGNORE_ACID); - } - - /* Add one random ability from material weapon */ - give_one_ability_of_object(o_ptr, mo_ptr); - - /* Add one random activation */ - if (!activation_index(o_ptr)) one_activation(o_ptr); - - /* Narsil */ - if (o_ptr->name1 == ART_NARSIL) - { - one_high_resistance(o_ptr); - one_ability(o_ptr); - } - - msg_print(_("これはかなりの業物だったようだ。", "This blade seems to be exceptionally.")); - } - - object_desc(basenm, o_ptr, OD_NAME_ONLY); -#ifdef JP - msg_format("$%dで%sに修復しました。", cost, basenm); -#else - msg_format("Repaired into %s for %d gold.", basenm, cost); -#endif - msg_print(NULL); - - /* Remove BROKEN flag */ - o_ptr->ident &= ~(IDENT_BROKEN); - - /* Add repaired flag */ - o_ptr->discount = 99; - - p_ptr->total_weight += o_ptr->weight; - calc_android_exp(); - - /* Decrease material object */ - inven_item_increase(mater, -1); - inven_item_optimize(mater); - - /* Copyback */ - p_ptr->update |= PU_BONUS; - handle_stuff(); - - /* Something happened */ - return (cost); -} - -/*! - * @brief アイテム修復処理の過渡ルーチン / Repair broken weapon - * @param bcost 基本鑑定費用 - * @return 実際にかかった費用 - */ -static int repair_broken_weapon(PRICE bcost) -{ - PRICE cost; - screen_save(); - cost = repair_broken_weapon_aux(bcost); - screen_load(); - return cost; -} - - -/*! - * @brief アイテムの強化を行う。 / Enchant item - * @param cost 1回毎の費用 - * @param to_hit 命中をアップさせる量 - * @param to_dam ダメージをアップさせる量 - * @param to_ac ACをアップさせる量 - * @return 実際に行ったらTRUE - */ -static bool enchant_item(PRICE cost, HIT_PROB to_hit, HIT_POINT to_dam, ARMOUR_CLASS to_ac) -{ - int i; - OBJECT_IDX item; - bool okay = FALSE; - object_type *o_ptr; - concptr q, s; - int maxenchant = (p_ptr->lev / 5); - char tmp_str[MAX_NLEN]; - - clear_bldg(4, 18); - prt(format(_("現在のあなたの技量だと、+%d まで改良できます。", " Based on your skill, we can improve up to +%d."), maxenchant), 5, 0); - prt(format(_(" 改良の料金は一個につき$%d です。", " The price for the service is %d gold per item."), cost), 7, 0); - - q = _("どのアイテムを改良しますか?", "Improve which item? "); - s = _("改良できるものがありません。", "You have nothing to improve."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_EQUIP | IGNORE_BOTHHAND_SLOT)); - if (!o_ptr) return (FALSE); - - /* Check if the player has enough money */ - if (p_ptr->au < (cost * o_ptr->number)) - { - object_desc(tmp_str, o_ptr, OD_NAME_ONLY); - msg_format(_("%sを改良するだけのゴールドがありません!", "You do not have the gold to improve %s!"), tmp_str); - return (FALSE); - } - - /* Enchant to hit */ - for (i = 0; i < to_hit; i++) - { - if (o_ptr->to_h < maxenchant) - { - if (enchant(o_ptr, 1, (ENCH_TOHIT | ENCH_FORCE))) - { - okay = TRUE; - break; - } - } - } - - /* Enchant to damage */ - for (i = 0; i < to_dam; i++) - { - if (o_ptr->to_d < maxenchant) - { - if (enchant(o_ptr, 1, (ENCH_TODAM | ENCH_FORCE))) - { - okay = TRUE; - break; - } - } - } - - /* Enchant to AC */ - for (i = 0; i < to_ac; i++) - { - if (o_ptr->to_a < maxenchant) - { - if (enchant(o_ptr, 1, (ENCH_TOAC | ENCH_FORCE))) - { - okay = TRUE; - break; - } - } - } - - /* Failure */ - if (!okay) - { - if (flush_failure) flush(); - msg_print(_("改良に失敗した。", "The improvement failed.")); - return (FALSE); - } - else - { - object_desc(tmp_str, o_ptr, OD_NAME_AND_ENCHANT); -#ifdef JP - msg_format("$%dで%sに改良しました。", cost * o_ptr->number, tmp_str); -#else - msg_format("Improved into %s for %d gold.", tmp_str, cost * o_ptr->number); -#endif - - /* Charge the money */ - p_ptr->au -= (cost * o_ptr->number); - - if (item >= INVEN_RARM) calc_android_exp(); - - /* Something happened */ - return (TRUE); - } -} - - -/*! - * @brief 魔道具の使用回数を回復させる施設のメインルーチン / Recharge rods, wands and staves - * @details - * The player can select the number of charges to add\n - * (up to a limit), and the recharge never fails.\n - *\n - * The cost for rods depends on the level of the rod. The prices\n - * for recharging wands and staves are dependent on the cost of\n - * the base-item.\n - * @return なし - */ -static void building_recharge(void) -{ - OBJECT_IDX item; - DEPTH lev; - object_type *o_ptr; - object_kind *k_ptr; - concptr q, s; - PRICE price; - PARAMETER_VALUE charges; - int max_charges; - char tmp_str[MAX_NLEN]; - - msg_flag = FALSE; - - /* Display some info */ - clear_bldg(4, 18); - prt(_(" 再充填の費用はアイテムの種類によります。", " The prices of recharge depend on the type."), 6, 0); - - - /* Only accept legal items */ - item_tester_hook = item_tester_hook_recharge; - - q = _("どのアイテムに魔力を充填しますか? ", "Recharge which item? "); - s = _("魔力を充填すべきアイテムがない。", "You have nothing to recharge."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR)); - if (!o_ptr) return; - - k_ptr = &k_info[o_ptr->k_idx]; - - /* - * We don't want to give the player free info about - * the level of the item or the number of charges. - */ - /* The item must be "known" */ - if (!object_is_known(o_ptr)) - { - msg_format(_("充填する前に鑑定されている必要があります!", "The item must be identified first!")); - msg_print(NULL); - - if ((p_ptr->au >= 50) && - get_check(_("$50で鑑定しますか? ", "Identify for 50 gold? "))) - - { - p_ptr->au -= 50; - identify_item(o_ptr); - object_desc(tmp_str, o_ptr, 0); - msg_format(_("%s です。", "You have: %s."), tmp_str); - - /* Auto-inscription */ - autopick_alter_item(item, FALSE); - - /* Update the gold display */ - building_prt_gold(); - } - else - { - return; - } - } - - /* Extract the object "level" */ - lev = k_info[o_ptr->k_idx].level; - - /* Price for a rod */ - if (o_ptr->tval == TV_ROD) - { - if (o_ptr->timeout > 0) - { - /* Fully recharge */ - price = (lev * 50 * o_ptr->timeout) / k_ptr->pval; - } - else - { - /* No recharge necessary */ - price = 0; - msg_format(_("それは再充填する必要はありません。", "That doesn't need to be recharged.")); - return; - } - } - else if (o_ptr->tval == TV_STAFF) - { - /* Price per charge ( = double the price paid by shopkeepers for the charge) */ - price = (k_info[o_ptr->k_idx].cost / 10) * o_ptr->number; - - /* Pay at least 10 gold per charge */ - price = MAX(10, price); - } - else - { - /* Price per charge ( = double the price paid by shopkeepers for the charge) */ - price = (k_info[o_ptr->k_idx].cost / 10); - - /* Pay at least 10 gold per charge */ - price = MAX(10, price); - } - - /* Limit the number of charges for wands and staffs */ - if (o_ptr->tval == TV_WAND - && (o_ptr->pval / o_ptr->number >= k_ptr->pval)) - { - if (o_ptr->number > 1) - { - msg_print(_("この魔法棒はもう充分に充填されています。", "These wands are already fully charged.")); - } - else - { - msg_print(_("この魔法棒はもう充分に充填されています。", "This wand is already fully charged.")); - } - return; - } - else if (o_ptr->tval == TV_STAFF && o_ptr->pval >= k_ptr->pval) - { - if (o_ptr->number > 1) - { - msg_print(_("この杖はもう充分に充填されています。", "These staffs are already fully charged.")); - } - else - { - msg_print(_("この杖はもう充分に充填されています。", "This staff is already fully charged.")); - } - return; - } - - /* Check if the player has enough money */ - if (p_ptr->au < price) - { - object_desc(tmp_str, o_ptr, OD_NAME_ONLY); -#ifdef JP - msg_format("%sを再充填するには$%d 必要です!", tmp_str,price ); -#else - msg_format("You need %d gold to recharge %s!", price, tmp_str); -#endif - - return; - } - - if (o_ptr->tval == TV_ROD) - { -#ifdef JP - if (get_check(format("そのロッドを$%d で再充填しますか?", price))) -#else - if (get_check(format("Recharge the %s for %d gold? ", - ((o_ptr->number > 1) ? "rods" : "rod"), price))) -#endif - - { - /* Recharge fully */ - o_ptr->timeout = 0; - } - else - { - return; - } - } - else - { - if (o_ptr->tval == TV_STAFF) - max_charges = k_ptr->pval - o_ptr->pval; - else - max_charges = o_ptr->number * k_ptr->pval - o_ptr->pval; - - /* Get the quantity for staves and wands */ - charges = (PARAMETER_VALUE)get_quantity(format(_("一回分$%d で何回分充填しますか?", "Add how many charges for %d gold? "), price), - MIN(p_ptr->au / price, max_charges)); - - /* Do nothing */ - if (charges < 1) return; - - /* Get the new price */ - price *= charges; - - /* Recharge */ - o_ptr->pval += charges; - - /* We no longer think the item is empty */ - o_ptr->ident &= ~(IDENT_EMPTY); - } - - /* Give feedback */ - object_desc(tmp_str, o_ptr, 0); -#ifdef JP - msg_format("%sを$%d で再充填しました。", tmp_str, price); -#else - msg_format("%^s %s recharged for %d gold.", tmp_str, ((o_ptr->number > 1) ? "were" : "was"), price); -#endif - p_ptr->update |= (PU_COMBINE | PU_REORDER); - - p_ptr->window |= (PW_INVEN); - - /* Pay the price */ - p_ptr->au -= price; - - /* Finished */ - return; -} - - -/*! - * @brief 魔道具の使用回数を回復させる施設の一括処理向けサブルーチン / Recharge rods, wands and staves - * @details - * The player can select the number of charges to add\n - * (up to a limit), and the recharge never fails.\n - *\n - * The cost for rods depends on the level of the rod. The prices\n - * for recharging wands and staves are dependent on the cost of\n - * the base-item.\n - * @return なし - */ -static void building_recharge_all(void) -{ - INVENTORY_IDX i; - DEPTH lev; - object_type *o_ptr; - object_kind *k_ptr; - PRICE price = 0; - PRICE total_cost = 0; - - - /* Display some info */ - msg_flag = FALSE; - clear_bldg(4, 18); - prt(_(" 再充填の費用はアイテムの種類によります。", " The prices of recharge depend on the type."), 6, 0); - - /* Calculate cost */ - for ( i = 0; i < INVEN_PACK; i++) - { - o_ptr = &inventory[i]; - - /* skip non magic device */ - if (o_ptr->tval < TV_STAFF || o_ptr->tval > TV_ROD) continue; - - /* need identified */ - if (!object_is_known(o_ptr)) total_cost += 50; - - /* Extract the object "level" */ - lev = k_info[o_ptr->k_idx].level; - - k_ptr = &k_info[o_ptr->k_idx]; - - switch (o_ptr->tval) - { - case TV_ROD: - price = (lev * 50 * o_ptr->timeout) / k_ptr->pval; - break; - - case TV_STAFF: - /* Price per charge ( = double the price paid by shopkeepers for the charge) */ - price = (k_info[o_ptr->k_idx].cost / 10) * o_ptr->number; - - /* Pay at least 10 gold per charge */ - price = MAX(10, price); - - /* Fully charge */ - price = (k_ptr->pval - o_ptr->pval) * price; - break; - - case TV_WAND: - /* Price per charge ( = double the price paid by shopkeepers for the charge) */ - price = (k_info[o_ptr->k_idx].cost / 10); - - /* Pay at least 10 gold per charge */ - price = MAX(10, price); - - /* Fully charge */ - price = (o_ptr->number * k_ptr->pval - o_ptr->pval) * price; - break; - } - - /* if price <= 0 then item have enough charge */ - if (price > 0) total_cost += price; - } - - if (!total_cost) - { - msg_print(_("充填する必要はありません。", "No need to recharge.")); - msg_print(NULL); - return; - } - - /* Check if the player has enough money */ - if (p_ptr->au < total_cost) - { - msg_format(_("すべてのアイテムを再充填するには$%d 必要です!", "You need %d gold to recharge all items!"), total_cost ); - msg_print(NULL); - return; - } - if (!get_check(format(_("すべてのアイテムを $%d で再充填しますか?", "Recharge all items for %d gold? "), total_cost))) return; - - for (i = 0; i < INVEN_PACK; i++) - { - o_ptr = &inventory[i]; - k_ptr = &k_info[o_ptr->k_idx]; - - /* skip non magic device */ - if (o_ptr->tval < TV_STAFF || o_ptr->tval > TV_ROD) continue; - - if (!object_is_known(o_ptr)) - { - identify_item(o_ptr); - - /* Auto-inscription */ - autopick_alter_item(i, FALSE); - } - - /* Recharge */ - switch (o_ptr->tval) - { - case TV_ROD: - o_ptr->timeout = 0; - break; - case TV_STAFF: - if (o_ptr->pval < k_ptr->pval) o_ptr->pval = k_ptr->pval; - /* We no longer think the item is empty */ - o_ptr->ident &= ~(IDENT_EMPTY); - break; - case TV_WAND: - if (o_ptr->pval < o_ptr->number * k_ptr->pval) - o_ptr->pval = o_ptr->number * k_ptr->pval; - /* We no longer think the item is empty */ - o_ptr->ident &= ~(IDENT_EMPTY); - break; - } - } - - /* Give feedback */ - msg_format(_("$%d で再充填しました。", "You pay %d gold."), total_cost); - msg_print(NULL); - p_ptr->update |= (PU_COMBINE | PU_REORDER); - - p_ptr->window |= (PW_INVEN); - - /* Pay the price */ - p_ptr->au -= total_cost; - - /* Finished */ - return; -} - -/*! - * @brief 町間のテレポートを行うメインルーチン。 - * @return テレポート処理を決定したか否か - */ -bool tele_town(void) -{ - int i; - POSITION x, y; - int num = 0; - - if (current_floor_ptr->dun_level) - { - msg_print(_("この魔法は地上でしか使えない!", "This spell can only be used on the surface!")); - return FALSE; - } - - if (p_ptr->inside_arena || p_ptr->inside_battle) - { - msg_print(_("この魔法は外でしか使えない!", "This spell can only be used outside!")); - return FALSE; - } - - screen_save(); - clear_bldg(4, 10); - - for (i = 1; i < max_towns; i++) - { - char buf[80]; - - if ((i == NO_TOWN) || (i == SECRET_TOWN) || (i == p_ptr->town_num) || !(p_ptr->visit & (1L << (i - 1)))) continue; - - sprintf(buf, "%c) %-20s", I2A(i - 1), town_info[i].name); - prt(buf, 5 + i, 5); - num++; - } - - if (!num) - { - msg_print(_("まだ行けるところがない。", "You have not yet visited any town.")); - msg_print(NULL); - screen_load(); - return FALSE; - } - - prt(_("どこに行きますか:", "Which town you go: "), 0, 0); - while(1) - { - i = inkey(); - - if (i == ESCAPE) - { - screen_load(); - return FALSE; - } - else if ((i < 'a') || (i > ('a'+max_towns-2))) continue; - else if (((i-'a'+1) == p_ptr->town_num) || ((i-'a'+1) == NO_TOWN) || ((i-'a'+1) == SECRET_TOWN) || !(p_ptr->visit & (1L << (i-'a')))) continue; - break; - } - - for (y = 0; y < current_world_ptr->max_wild_y; y++) - { - for (x = 0; x < current_world_ptr->max_wild_x; x++) - { - if(wilderness[y][x].town == (i-'a'+1)) - { - p_ptr->wilderness_y = y; - p_ptr->wilderness_x = x; - } - } - } - - p_ptr->leaving = TRUE; - leave_bldg = TRUE; - p_ptr->teleport_town = TRUE; - screen_load(); - return TRUE; -} - -/*! - * @brief 施設でモンスターの情報を知るメインルーチン / research_mon -KMW- - * @return 常にTRUEを返す。 - * @todo 返り値が意味不明なので直した方が良いかもしれない。 - */ -static bool research_mon(void) -{ - IDX i; - int n; - MONRACE_IDX r_idx; - char sym, query; - char buf[128]; - bool notpicked; - bool recall = FALSE; - u16b why = 0; - MONSTER_IDX *who; - - /* XTRA HACK WHATSEARCH */ - bool all = FALSE; - bool uniq = FALSE; - bool norm = FALSE; - char temp[80] = ""; - - /* XTRA HACK REMEMBER_IDX */ - static int old_sym = '\0'; - static IDX old_i = 0; - - screen_save(); - - /* Get a character, or abort */ - if (!get_com(_("モンスターの文字を入力して下さい(記号 or ^A全,^Uユ,^N非ユ,^M名前):", - "Enter character to be identified(^A:All,^U:Uniqs,^N:Non uniqs,^M:Name): "), &sym, FALSE)) - - { - screen_load(); - - return (FALSE); - } - - /* Find that character info, and describe it */ - for (i = 0; ident_info[i]; ++i) - { - if (sym == ident_info[i][0]) break; - } - - /* XTRA HACK WHATSEARCH */ - if (sym == KTRL('A')) - { - all = TRUE; - strcpy(buf, _("全モンスターのリスト", "Full monster list.")); - } - else if (sym == KTRL('U')) - { - all = uniq = TRUE; - strcpy(buf, _("ユニーク・モンスターのリスト", "Unique monster list.")); - } - else if (sym == KTRL('N')) - { - all = norm = TRUE; - strcpy(buf, _("ユニーク外モンスターのリスト", "Non-unique monster list.")); - } - else if (sym == KTRL('M')) - { - all = TRUE; - if (!get_string(_("名前(英語の場合小文字で可)", "Enter name:"),temp, 70)) - { - temp[0]=0; - screen_load(); - - return FALSE; - } - sprintf(buf, _("名前:%sにマッチ", "Monsters with a name \"%s\""),temp); - } - else if (ident_info[i]) - { - sprintf(buf, "%c - %s.", sym, ident_info[i] + 2); - } - else - { - sprintf(buf, "%c - %s", sym, _("無効な文字", "Unknown Symbol")); - } - - /* Display the result */ - prt(buf, 16, 10); - - /* Allocate the "who" array */ - C_MAKE(who, max_r_idx, MONRACE_IDX); - - /* Collect matching monsters */ - for (n = 0, i = 1; i < max_r_idx; i++) - { - monster_race *r_ptr = &r_info[i]; - - /* Empty monster */ - if (!r_ptr->name) continue; - - /* XTRA HACK WHATSEARCH */ - /* Require non-unique monsters if needed */ - if (norm && (r_ptr->flags1 & (RF1_UNIQUE))) continue; - - /* Require unique monsters if needed */ - if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) continue; - - /* 名前検索 */ - if (temp[0]) - { - int xx; - char temp2[80]; - - for (xx = 0; temp[xx] && xx < 80; xx++) - { -#ifdef JP - if (iskanji(temp[xx])) - { - xx++; - continue; - } -#endif - if (isupper(temp[xx])) temp[xx] = (char)tolower(temp[xx]); - } - -#ifdef JP - strcpy(temp2, r_name + r_ptr->E_name); -#else - strcpy(temp2, r_name + r_ptr->name); -#endif - for (xx = 0; temp2[xx] && xx < 80; xx++) - if (isupper(temp2[xx])) temp2[xx] = (char)tolower(temp2[xx]); - -#ifdef JP - if (my_strstr(temp2, temp) || my_strstr(r_name + r_ptr->name, temp)) -#else - if (my_strstr(temp2, temp)) -#endif - who[n++] = i; - } - else if (all || (r_ptr->d_char == sym)) who[n++] = i; - } - - /* Nothing to recall */ - if (!n) - { - /* Free the "who" array */ - C_KILL(who, max_r_idx, MONRACE_IDX); - screen_load(); - - return (FALSE); - } - - /* Sort by level */ - why = 2; - query = 'y'; - - /* Sort if needed */ - if (why) - { - ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook); - } - - - /* Start at the end */ - /* XTRA HACK REMEMBER_IDX */ - if (old_sym == sym && old_i < n) i = old_i; - else i = n - 1; - - notpicked = TRUE; - - /* Scan the monster memory */ - while (notpicked) - { - /* Extract a race */ - r_idx = who[i]; - - /* Hack -- Begin the prompt */ - roff_top(r_idx); - - /* Hack -- Complete the prompt */ - Term_addstr(-1, TERM_WHITE, _(" ['r'思い出, ' 'で続行, ESC]", " [(r)ecall, ESC, space to continue]")); - - /* Interact */ - while (1) - { - /* Recall */ - if (recall) - { - /*** Recall on screen ***/ - - /* Get maximal info about this monster */ - lore_do_probe(r_idx); - - /* Save this monster ID */ - monster_race_track(r_idx); - handle_stuff(); - - /* know every thing mode */ - screen_roff(r_idx, 0x01); - notpicked = FALSE; - - /* XTRA HACK REMEMBER_IDX */ - old_sym = sym; - old_i = i; - } - - /* Command */ - query = inkey(); - - /* Normal commands */ - if (query != 'r') break; - - /* Toggle recall */ - recall = !recall; - } - - /* Stop scanning */ - if (query == ESCAPE) break; - - /* Move to "prev" monster */ - if (query == '-') - { - if (++i == n) - { - i = 0; - if (!expand_list) break; - } - } - - /* Move to "next" monster */ - else - { - if (i-- == 0) - { - i = n - 1; - if (!expand_list) break; - } - } - } - - - /* Re-display the identity */ - /* prt(buf, 5, 5);*/ - - /* Free the "who" array */ - C_KILL(who, max_r_idx, MONRACE_IDX); - screen_load(); - - return (!notpicked); -} - - -/*! - * @brief 施設の処理実行メインルーチン / Execute a building command - * @param bldg 施設構造体の参照ポインタ - * @param i 実行したい施設のサービステーブルの添字 - * @return なし - */ -static void bldg_process_command(building_type *bldg, int i) -{ - BACT_IDX bact = bldg->actions[i]; - PRICE bcost; - bool paid = FALSE; - - msg_flag = FALSE; - msg_erase(); - - if (is_owner(bldg)) - bcost = bldg->member_costs[i]; - else - bcost = bldg->other_costs[i]; - - /* action restrictions */ - if (((bldg->action_restr[i] == 1) && !is_member(bldg)) || - ((bldg->action_restr[i] == 2) && !is_owner(bldg))) - { - msg_print(_("それを選択する権利はありません!", "You have no right to choose that!")); - return; - } - - /* check gold (HACK - Recharge uses variable costs) */ - if ((bact != BACT_RECHARGE) && - (((bldg->member_costs[i] > p_ptr->au) && is_owner(bldg)) || - ((bldg->other_costs[i] > p_ptr->au) && !is_owner(bldg)))) - { - msg_print(_("お金が足りません!", "You do not have the gold!")); - return; - } - - switch (bact) - { - case BACT_NOTHING: - /* Do nothing */ - break; - case BACT_RESEARCH_ITEM: - paid = identify_fully(FALSE); - break; - case BACT_TOWN_HISTORY: - town_history(); - break; - case BACT_RACE_LEGENDS: - race_legends(); - break; - case BACT_QUEST: - castle_quest(); - break; - case BACT_KING_LEGENDS: - case BACT_ARENA_LEGENDS: - case BACT_LEGENDS: - show_highclass(); - break; - case BACT_POSTER: - case BACT_ARENA_RULES: - case BACT_ARENA: - arena_comm(bact); - break; - case BACT_IN_BETWEEN: - case BACT_CRAPS: - case BACT_SPIN_WHEEL: - case BACT_DICE_SLOTS: - case BACT_GAMBLE_RULES: - case BACT_POKER: - gamble_comm(bact); - break; - case BACT_REST: - case BACT_RUMORS: - case BACT_FOOD: - paid = inn_comm(bact); - break; - case BACT_RESEARCH_MONSTER: - paid = research_mon(); - break; - case BACT_COMPARE_WEAPONS: - paid = TRUE; - bcost = compare_weapons(bcost); - break; - case BACT_ENCHANT_WEAPON: - item_tester_hook = object_allow_enchant_melee_weapon; - enchant_item(bcost, 1, 1, 0); - break; - case BACT_ENCHANT_ARMOR: - item_tester_hook = object_is_armour; - enchant_item(bcost, 0, 0, 1); - break; - case BACT_RECHARGE: - building_recharge(); - break; - case BACT_RECHARGE_ALL: - building_recharge_all(); - break; - case BACT_IDENTS: /* needs work */ - if (!get_check(_("持ち物を全て鑑定してよろしいですか?", "Do you pay for identify all your possession? "))) break; - identify_pack(); - msg_print(_(" 持ち物全てが鑑定されました。", "Your possessions have been identified.")); - paid = TRUE; - break; - case BACT_IDENT_ONE: /* needs work */ - paid = ident_spell(FALSE); - break; - case BACT_LEARN: - do_cmd_study(); - break; - case BACT_HEALING: /* needs work */ - paid = cure_critical_wounds(200); - break; - case BACT_RESTORE: /* needs work */ - paid = restore_all_status(); - break; - case BACT_ENCHANT_ARROWS: - item_tester_hook = item_tester_hook_ammo; - enchant_item(bcost, 1, 1, 0); - break; - case BACT_ENCHANT_BOW: - item_tester_tval = TV_BOW; - enchant_item(bcost, 1, 1, 0); - break; - - case BACT_RECALL: - if (recall_player(p_ptr, 1)) paid = TRUE; - break; - - case BACT_TELEPORT_LEVEL: - clear_bldg(4, 20); - paid = free_level_recall(p_ptr); - break; - - case BACT_LOSE_MUTATION: - if (p_ptr->muta1 || p_ptr->muta2 || (p_ptr->muta3 & ~MUT3_GOOD_LUCK) || - (p_ptr->pseikaku != SEIKAKU_LUCKY && (p_ptr->muta3 & MUT3_GOOD_LUCK))) - { - while(!lose_mutation(0)); - paid = TRUE; - } - else - { - msg_print(_("治すべき突然変異が無い。", "You have no mutations.")); - msg_print(NULL); - } - break; - - case BACT_BATTLE: - kakutoujou(); - break; - - case BACT_TSUCHINOKO: - tsuchinoko(); - break; - - case BACT_KUBI: - shoukinkubi(); - break; - - case BACT_TARGET: - today_target(); - break; - - case BACT_KANKIN: - kankin(); - break; - - case BACT_HEIKOUKA: - msg_print(_("平衡化の儀式を行なった。", "You received an equalization ritual.")); - set_virtue(V_COMPASSION, 0); - set_virtue(V_HONOUR, 0); - set_virtue(V_JUSTICE, 0); - set_virtue(V_SACRIFICE, 0); - set_virtue(V_KNOWLEDGE, 0); - set_virtue(V_FAITH, 0); - set_virtue(V_ENLIGHTEN, 0); - set_virtue(V_ENCHANT, 0); - set_virtue(V_CHANCE, 0); - set_virtue(V_NATURE, 0); - set_virtue(V_HARMONY, 0); - set_virtue(V_VITALITY, 0); - set_virtue(V_UNLIFE, 0); - set_virtue(V_PATIENCE, 0); - set_virtue(V_TEMPERANCE, 0); - set_virtue(V_DILIGENCE, 0); - set_virtue(V_VALOUR, 0); - set_virtue(V_INDIVIDUALISM, 0); - get_virtues(); - paid = TRUE; - break; - - case BACT_TELE_TOWN: - paid = tele_town(); - break; - - case BACT_EVAL_AC: - paid = eval_ac(p_ptr->dis_ac + p_ptr->dis_to_a); - break; - - case BACT_BROKEN_WEAPON: - paid = TRUE; - bcost = repair_broken_weapon(bcost); - break; - } - - if (paid) - { - p_ptr->au -= bcost; - } -} - -/*! - * @brief クエスト入り口にプレイヤーが乗った際の処理 / Do building commands - * @return なし - */ -void do_cmd_quest(void) -{ - if(p_ptr->wild_mode) return; - - take_turn(p_ptr, 100); - - if (!cave_have_flag_bold(p_ptr->y, p_ptr->x, FF_QUEST_ENTER)) - { - msg_print(_("ここにはクエストの入口はない。", "You see no quest level here.")); - return; - } - else - { - msg_print(_("ここにはクエストへの入口があります。", "There is an entry of a quest.")); - if (!get_check(_("クエストに入りますか?", "Do you enter? "))) return; - if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) - msg_print(_("『とにかく入ってみようぜぇ。』", "")); - else if(p_ptr->pseikaku == SEIKAKU_CHARGEMAN) msg_print("『全滅してやるぞ!』"); - - /* Player enters a new quest */ - p_ptr->oldpy = 0; - p_ptr->oldpx = 0; - - leave_quest_check(); - - if (quest[p_ptr->inside_quest].type != QUEST_TYPE_RANDOM) current_floor_ptr->dun_level = 1; - p_ptr->inside_quest = current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].special; - - p_ptr->leaving = TRUE; - } -} - - -/*! - * @brief 施設入り口にプレイヤーが乗った際の処理 / Do building commands - * @return なし - */ -void do_cmd_bldg(void) -{ - int i, which; - char command; - bool validcmd; - building_type *bldg; - - if(p_ptr->wild_mode) return; - - take_turn(p_ptr, 100); - - if (!cave_have_flag_bold(p_ptr->y, p_ptr->x, FF_BLDG)) - { - msg_print(_("ここには建物はない。", "You see no building here.")); - return; - } - - which = f_info[current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].feat].subtype; - - bldg = &building[which]; - - /* Don't re-init the wilderness */ - reinit_wilderness = FALSE; - - if ((which == 2) && (p_ptr->arena_number < 0)) - { - msg_print(_("「敗者に用はない。」", "'There's no place here for a LOSER like you!'")); - return; - } - else if ((which == 2) && p_ptr->inside_arena) - { - if (!p_ptr->exit_bldg && m_cnt > 0) - { - prt(_("ゲートは閉まっている。モンスターがあなたを待っている!", "The gates are closed. The monster awaits!"), 0, 0); - } - else - { - /* Don't save the arena as saved floor */ - prepare_change_floor_mode(CFM_SAVE_FLOORS | CFM_NO_RETURN); - - p_ptr->inside_arena = FALSE; - p_ptr->leaving = TRUE; - - /* Re-enter the arena */ - command_new = SPECIAL_KEY_BUILDING; - - /* No energy needed to re-enter the arena */ - free_turn(p_ptr); - } - - return; - } - else if (p_ptr->inside_battle) - { - /* Don't save the arena as saved floor */ - prepare_change_floor_mode(CFM_SAVE_FLOORS | CFM_NO_RETURN); - - p_ptr->leaving = TRUE; - p_ptr->inside_battle = FALSE; - - /* Re-enter the monster arena */ - command_new = SPECIAL_KEY_BUILDING; - - /* No energy needed to re-enter the arena */ - free_turn(p_ptr); - - return; - } - else - { - p_ptr->oldpy = p_ptr->y; - p_ptr->oldpx = p_ptr->x; - } - - forget_lite(); - forget_view(); - - /* Hack -- Increase "icky" depth */ - character_icky++; - - command_arg = 0; - command_rep = 0; - command_new = 0; - - show_building(bldg); - leave_bldg = FALSE; - - play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_BUILD); - - while (!leave_bldg) - { - validcmd = FALSE; - prt("", 1, 0); - - building_prt_gold(); - - command = inkey(); - - if (command == ESCAPE) - { - leave_bldg = TRUE; - p_ptr->inside_arena = FALSE; - p_ptr->inside_battle = FALSE; - break; - } - - for (i = 0; i < 8; i++) - { - if (bldg->letters[i]) - { - if (bldg->letters[i] == command) - { - validcmd = TRUE; - break; - } - } - } - - if(validcmd) bldg_process_command(bldg, i); - - handle_stuff(); - } - - select_floor_music(); - - msg_flag = FALSE; - msg_erase(); - - /* Reinit wilderness to activate quests ... */ - if (reinit_wilderness) - { - p_ptr->leaving = TRUE; - } - - /* Hack -- Decrease "icky" depth */ - character_icky--; - - Term_clear(); - - p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_BONUS | PU_LITE | PU_MON_LITE); - p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_EQUIPPY | PR_MAP); - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); -} diff --git a/src/blue-magic/blue-magic-ball-bolt.c b/src/blue-magic/blue-magic-ball-bolt.c new file mode 100644 index 000000000..0b4e1c367 --- /dev/null +++ b/src/blue-magic/blue-magic-ball-bolt.c @@ -0,0 +1,257 @@ +#include "blue-magic/blue-magic-ball-bolt.h" +#include "blue-magic/blue-magic-util.h" +#include "mspell/mspell-damage-calculator.h" +#include "mspell/mspell-type.h" +#include "spell-kind/spells-launcher.h" +#include "spell/spell-types.h" +#include "target/target-getter.h" +#include "view/display-messages.h" + +bool cast_blue_ball_acid(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("アシッド・ボールの呪文を唱えた。", "You cast an acid ball.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BALL_ACID, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_ACID, bmc_ptr->dir, bmc_ptr->damage, 2); + return TRUE; +} + +bool cast_blue_ball_elec(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("サンダー・ボールの呪文を唱えた。", "You cast a lightning ball.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BALL_ELEC, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_ELEC, bmc_ptr->dir, bmc_ptr->damage, 2); + return TRUE; +} + +bool cast_blue_ball_fire(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("ファイア・ボールの呪文を唱えた。", "You cast a fire ball.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BALL_FIRE, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_FIRE, bmc_ptr->dir, bmc_ptr->damage, 2); + return TRUE; +} + +bool cast_blue_ball_cold(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("アイス・ボールの呪文を唱えた。", "You cast a frost ball.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BALL_COLD, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_COLD, bmc_ptr->dir, bmc_ptr->damage, 2); + return TRUE; +} + +bool cast_blue_ball_pois(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("悪臭雲の呪文を唱えた。", "You cast a stinking cloud.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BALL_POIS, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_POIS, bmc_ptr->dir, bmc_ptr->damage, 2); + return TRUE; +} + +bool cast_blue_ball_nuke(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("放射能球を放った。", "You cast a ball of radiation.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BALL_NUKE, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_NUKE, bmc_ptr->dir, bmc_ptr->damage, 2); + return TRUE; +} + +bool cast_blue_ball_nether(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("地獄球の呪文を唱えた。", "You cast a nether ball.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BALL_NETHER, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_NETHER, bmc_ptr->dir, bmc_ptr->damage, 2); + return TRUE; +} + +bool cast_blue_ball_chaos(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("純ログルスを放った。", "You invoke a raw Logrus.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BALL_CHAOS, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_CHAOS, bmc_ptr->dir, bmc_ptr->damage, 4); + return TRUE; +} + +/*! + * @brief ウォーター・ボールの青魔法 + * @brief 分解のブレスの青魔法 + * @param caster_ptr プレーヤーへの参照ポインタ + * @param bmc_ptr 青魔法詠唱への参照ポインタ + * @details All my worries are blown away. + */ +bool cast_blue_ball_water(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("流れるような身振りをした。", "You gesture fluidly.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BALL_WATER, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_WATER, bmc_ptr->dir, bmc_ptr->damage, 4); + return TRUE; +} + +bool cast_blue_ball_star_burst(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("スターバーストの呪文を念じた。", "You invoke a starburst.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_STARBURST, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_LITE, bmc_ptr->dir, bmc_ptr->damage, 4); + return TRUE; +} + +bool cast_blue_ball_dark_storm(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("暗黒の嵐の呪文を念じた。", "You invoke a darkness storm.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BALL_DARK, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_DARK, bmc_ptr->dir, bmc_ptr->damage, 4); + return TRUE; +} + +bool cast_blue_ball_mana_storm(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("魔力の嵐の呪文を念じた。", "You invoke a mana storm.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BALL_MANA, bmc_ptr->plev, DAM_ROLL); + fire_ball(caster_ptr, GF_MANA, bmc_ptr->dir, bmc_ptr->damage, 4); + return TRUE; +} + +bool cast_blue_bolt_acid(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("アシッド・ボルトの呪文を唱えた。", "You cast an acid bolt.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BOLT_ACID, bmc_ptr->plev, DAM_ROLL); + fire_bolt(caster_ptr, GF_ACID, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} + +bool cast_blue_bolt_elec(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("サンダー・ボルトの呪文を唱えた。", "You cast a lightning bolt.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BOLT_ELEC, bmc_ptr->plev, DAM_ROLL); + fire_bolt(caster_ptr, GF_ELEC, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} + +bool cast_blue_bolt_fire(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("ファイア・ボルトの呪文を唱えた。", "You cast a fire bolt.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BOLT_FIRE, bmc_ptr->plev, DAM_ROLL); + fire_bolt(caster_ptr, GF_FIRE, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} + +bool cast_blue_bolt_cold(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("アイス・ボルトの呪文を唱えた。", "You cast a frost bolt.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BOLT_COLD, bmc_ptr->plev, DAM_ROLL); + fire_bolt(caster_ptr, GF_COLD, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} + +bool cast_blue_bolt_nether(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("地獄の矢の呪文を唱えた。", "You cast a nether bolt.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BOLT_NETHER, bmc_ptr->plev, DAM_ROLL); + fire_bolt(caster_ptr, GF_NETHER, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} + +bool cast_blue_bolt_water(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("ウォーター・ボルトの呪文を唱えた。", "You cast a water bolt.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BOLT_WATER, bmc_ptr->plev, DAM_ROLL); + fire_bolt(caster_ptr, GF_WATER, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} + +bool cast_blue_bolt_mana(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("魔力の矢の呪文を唱えた。", "You cast a mana bolt.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BOLT_MANA, bmc_ptr->plev, DAM_ROLL); + fire_bolt(caster_ptr, GF_MANA, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} + +bool cast_blue_bolt_plasma(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("プラズマ・ボルトの呪文を唱えた。", "You cast a plasma bolt.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BOLT_PLASMA, bmc_ptr->plev, DAM_ROLL); + fire_bolt(caster_ptr, GF_PLASMA, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} + +bool cast_blue_bolt_icee(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("極寒の矢の呪文を唱えた。", "You cast a ice bolt.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BOLT_ICE, bmc_ptr->plev, DAM_ROLL); + fire_bolt(caster_ptr, GF_ICE, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} + +bool cast_blue_bolt_missile(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("マジック・ミサイルの呪文を唱えた。", "You cast a magic missile.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_MAGIC_MISSILE, bmc_ptr->plev, DAM_ROLL); + fire_bolt(caster_ptr, GF_MISSILE, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} diff --git a/src/blue-magic/blue-magic-ball-bolt.h b/src/blue-magic/blue-magic-ball-bolt.h new file mode 100644 index 000000000..4069b1025 --- /dev/null +++ b/src/blue-magic/blue-magic-ball-bolt.h @@ -0,0 +1,28 @@ +#pragma once + +#include "system/angband.h" + +typedef struct bmc_type bmc_type; +bool cast_blue_ball_acid(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_ball_elec(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_ball_fire(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_ball_cold(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_ball_pois(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_ball_nuke(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_ball_nether(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_ball_chaos(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_ball_water(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_ball_star_burst(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_ball_dark_storm(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_ball_mana_storm(player_type *caster_ptr, bmc_type *bmc_ptr); + +bool cast_blue_bolt_acid(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_bolt_elec(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_bolt_fire(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_bolt_cold(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_bolt_nether(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_bolt_water(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_bolt_mana(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_bolt_plasma(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_bolt_icee(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_bolt_missile(player_type *caster_ptr, bmc_type *bmc_ptr); diff --git a/src/blue-magic/blue-magic-breath.c b/src/blue-magic/blue-magic-breath.c new file mode 100644 index 000000000..d74312a1a --- /dev/null +++ b/src/blue-magic/blue-magic-breath.c @@ -0,0 +1,257 @@ +#include "blue-magic/blue-magic-breath.h" +#include "blue-magic/blue-magic-util.h" +#include "mind/mind-blue-mage.h" +#include "mspell/mspell-damage-calculator.h" +#include "mspell/mspell-type.h" +#include "spell-kind/spells-launcher.h" +#include "spell/spell-types.h" +#include "target/target-getter.h" +#include "view/display-messages.h" + +bool cast_blue_breath_acid(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("酸のブレスを吐いた。", "You breathe acid.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_ACID, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_ACID, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_elec(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("稲妻のブレスを吐いた。", "You breathe lightning.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_ELEC, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_ELEC, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_fire(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("火炎のブレスを吐いた。", "You breathe fire.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_FIRE, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_FIRE, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_cold(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("冷気のブレスを吐いた。", "You breathe frost.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_COLD, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_COLD, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_pois(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("ガスのブレスを吐いた。", "You breathe gas.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_POIS, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_POIS, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_nether(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("地獄のブレスを吐いた。", "You breathe nether.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_NETHER, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_NETHER, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_lite(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("閃光のブレスを吐いた。", "You breathe light.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_LITE, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_LITE, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_dark(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("暗黒のブレスを吐いた。", "You breathe darkness.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_DARK, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_DARK, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_conf(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("混乱のブレスを吐いた。", "You breathe confusion.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_CONF, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_CONFUSION, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_sound(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("轟音のブレスを吐いた。", "You breathe sound.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_SOUND, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_SOUND, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_chaos(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("カオスのブレスを吐いた。", "You breathe chaos.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_CHAOS, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_CHAOS, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_disenchant(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("劣化のブレスを吐いた。", "You breathe disenchantment.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_DISEN, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_DISENCHANT, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_nexus(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("因果混乱のブレスを吐いた。", "You breathe nexus.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_NEXUS, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_NEXUS, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_time(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("時間逆転のブレスを吐いた。", "You breathe time.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_TIME, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_TIME, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_inertia(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("遅鈍のブレスを吐いた。", "You breathe inertia.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_INERTIA, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_INERTIAL, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_gravity(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("重力のブレスを吐いた。", "You breathe gravity.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_GRAVITY, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_GRAVITY, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_shards(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("破片のブレスを吐いた。", "You breathe shards.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_SHARDS, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_SHARDS, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_plasma(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("プラズマのブレスを吐いた。", "You breathe plasma.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_PLASMA, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_PLASMA, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_force(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("フォースのブレスを吐いた。", "You breathe force.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_FORCE, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_FORCE, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_mana(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("魔力のブレスを吐いた。", "You breathe mana.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BR_MANA, bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_MANA, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +bool cast_blue_breath_nuke(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("放射性廃棄物のブレスを吐いた。", "You breathe toxic waste.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, (MS_BR_NUKE), bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_NUKE, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} + +/*! + * @brief 分解のブレスの青魔法 + * @param caster_ptr プレーヤーへの参照ポインタ + * @param bmc_ptr 青魔法詠唱への参照ポインタ + * @details 永久の刻は過ぎ去れリ. + */ +bool cast_blue_breath_disintegration(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("分解のブレスを吐いた。", "You breathe disintegration.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, (MS_BR_DISI), bmc_ptr->plev, DAM_ROLL); + fire_breath(caster_ptr, GF_DISINTEGRATE, bmc_ptr->dir, bmc_ptr->damage, (bmc_ptr->plev > 40 ? 3 : 2)); + return TRUE; +} diff --git a/src/blue-magic/blue-magic-breath.h b/src/blue-magic/blue-magic-breath.h new file mode 100644 index 000000000..976ed4dd4 --- /dev/null +++ b/src/blue-magic/blue-magic-breath.h @@ -0,0 +1,27 @@ +#pragma once + +#include "system/angband.h" + +typedef struct bmc_type bmc_type; +bool cast_blue_breath_acid(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_elec(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_fire(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_cold(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_pois(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_nether(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_lite(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_dark(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_conf(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_sound(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_chaos(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_disenchant(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_nexus(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_time(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_inertia(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_gravity(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_shards(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_plasma(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_force(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_mana(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_nuke(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_breath_disintegration(player_type *caster_ptr, bmc_type *bmc_ptr); diff --git a/src/blue-magic/blue-magic-caster.c b/src/blue-magic/blue-magic-caster.c new file mode 100644 index 000000000..c71c07d15 --- /dev/null +++ b/src/blue-magic/blue-magic-caster.c @@ -0,0 +1,395 @@ +#include "blue-magic/blue-magic-caster.h" +#include "blue-magic/blue-magic-ball-bolt.h" +#include "blue-magic/blue-magic-breath.h" +#include "blue-magic/blue-magic-spirit-curse.h" +#include "blue-magic/blue-magic-status.h" +#include "blue-magic/blue-magic-summon.h" +#include "blue-magic/blue-magic-util.h" +#include "blue-magic/learnt-info.h" +#include "core/hp-mp-processor.h" +#include "floor/cave.h" +#include "grid/grid.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags-resistance.h" +#include "monster-race/race-flags1.h" +#include "monster/monster-describer.h" +#include "monster/monster-info.h" +#include "monster/monster-status.h" +#include "mspell/mspell-damage-calculator.h" +#include "spell-kind/spells-launcher.h" +#include "spell-kind/spells-lite.h" +#include "spell-kind/spells-neighbor.h" +#include "spell-kind/spells-sight.h" +#include "spell-kind/spells-teleport.h" +#include "spell-kind/spells-world.h" +#include "spell/spell-types.h" +#include "spell/spells-status.h" +#include "status/bad-status-setter.h" +#include "status/body-improvement.h" +#include "status/buff-setter.h" +#include "system/floor-type-definition.h" +#include "target/projection-path-calculator.h" +#include "target/target-checker.h" +#include "target/target-getter.h" +#include "target/target-setter.h" +#include "target/target-types.h" +#include "view/display-messages.h" + +static bool cast_blue_dispel(player_type *caster_ptr) +{ + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + + MONSTER_IDX m_idx = caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx; + if ((m_idx == 0) || !player_has_los_bold(caster_ptr, target_row, target_col) + || !projectable(caster_ptr, caster_ptr->y, caster_ptr->x, target_row, target_col)) + return TRUE; + + dispel_monster_status(caster_ptr, m_idx); + return TRUE; +} + +static bool cast_blue_rocket(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("ロケットを発射した。", "You fire a rocket.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, (MS_ROCKET), bmc_ptr->plev, DAM_ROLL); + fire_rocket(caster_ptr, GF_ROCKET, bmc_ptr->dir, bmc_ptr->damage, 2); + return TRUE; +} + +static bool cast_blue_shoot(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("矢を放った。", "You fire an arrow.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, (MS_SHOOT), bmc_ptr->plev, DAM_ROLL); + fire_bolt(caster_ptr, GF_ARROW, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} + +static bool cast_blue_hand_doom(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("<破滅の手>を放った!", "You invoke the Hand of Doom!")); + fire_ball_hide(caster_ptr, GF_HAND_DOOM, bmc_ptr->dir, bmc_ptr->plev * 3, 0); + return TRUE; +} + +static bool exe_blue_teleport_back(player_type *caster_ptr, GAME_TEXT *m_name) +{ + monster_type *m_ptr; + monster_race *r_ptr; + floor_type *floor_ptr = caster_ptr->current_floor_ptr; + if ((floor_ptr->grid_array[target_row][target_col].m_idx == 0) || !player_has_los_bold(caster_ptr, target_row, target_col) + || !projectable(caster_ptr, caster_ptr->y, caster_ptr->x, target_row, target_col)) + return TRUE; + + m_ptr = &floor_ptr->m_list[floor_ptr->grid_array[target_row][target_col].m_idx]; + r_ptr = &r_info[m_ptr->r_idx]; + monster_desc(caster_ptr, m_name, m_ptr, 0); + if ((r_ptr->flagsr & RFR_RES_TELE) == 0) + return FALSE; + + if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flagsr & RFR_RES_ALL)) { + if (is_original_ap_and_seen(caster_ptr, m_ptr)) + r_ptr->r_flagsr |= RFR_RES_TELE; + + msg_format(_("%sには効果がなかった!", "%s is unaffected!"), m_name); + return TRUE; + } + + if (r_ptr->level <= randint1(100)) + return FALSE; + + if (is_original_ap_and_seen(caster_ptr, m_ptr)) + r_ptr->r_flagsr |= RFR_RES_TELE; + + msg_format(_("%sには耐性がある!", "%s resists!"), m_name); + return TRUE; +} + +static bool cast_blue_teleport_back(player_type *caster_ptr) +{ + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + + GAME_TEXT m_name[MAX_NLEN]; + if (exe_blue_teleport_back(caster_ptr, m_name)) + return TRUE; + + msg_format(_("%sを引き戻した。", "You command %s to return."), m_name); + teleport_monster_to( + caster_ptr, caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx, caster_ptr->y, caster_ptr->x, 100, TELEPORT_PASSIVE); + return TRUE; +} + +static bool cast_blue_teleport_away(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + (void)fire_beam(caster_ptr, GF_AWAY_ALL, bmc_ptr->dir, 100); + return TRUE; +} + +static bool cast_blue_psy_spear(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("光の剣を放った。", "You throw a psycho-spear.")); + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, (MS_PSY_SPEAR), bmc_ptr->plev, DAM_ROLL); + (void)fire_beam(caster_ptr, GF_PSY_SPEAR, bmc_ptr->dir, bmc_ptr->damage); + return TRUE; +} + +static bool cast_blue_make_trap(player_type *caster_ptr) +{ + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + + msg_print(_("呪文を唱えて邪悪に微笑んだ。", "You cast a spell and cackle evilly.")); + trap_creation(caster_ptr, target_row, target_col); + return TRUE; +} + +bool switch_cast_blue_magic(player_type *caster_ptr, bmc_type *bmc_ptr, SPELL_IDX spell) +{ + switch (spell) { + case MS_SHRIEK: + msg_print(_("かん高い金切り声をあげた。", "You make a high pitched shriek.")); + aggravate_monsters(caster_ptr, 0); + return TRUE; + case MS_XXX1: + case MS_XXX2: + case MS_XXX3: + case MS_XXX4: + return TRUE; + case MS_DISPEL: + return cast_blue_dispel(caster_ptr); + case MS_ROCKET: + return cast_blue_rocket(caster_ptr, bmc_ptr); + case MS_SHOOT: + return cast_blue_shoot(caster_ptr, bmc_ptr); + case MS_BR_ACID: + return cast_blue_breath_acid(caster_ptr, bmc_ptr); + case MS_BR_ELEC: + return cast_blue_breath_elec(caster_ptr, bmc_ptr); + case MS_BR_FIRE: + return cast_blue_breath_fire(caster_ptr, bmc_ptr); + case MS_BR_COLD: + return cast_blue_breath_cold(caster_ptr, bmc_ptr); + case MS_BR_POIS: + return cast_blue_breath_pois(caster_ptr, bmc_ptr); + case MS_BR_NETHER: + return cast_blue_breath_nether(caster_ptr, bmc_ptr); + case MS_BR_LITE: + return cast_blue_breath_lite(caster_ptr, bmc_ptr); + case MS_BR_DARK: + return cast_blue_breath_dark(caster_ptr, bmc_ptr); + case MS_BR_CONF: + return cast_blue_breath_conf(caster_ptr, bmc_ptr); + case MS_BR_SOUND: + return cast_blue_breath_sound(caster_ptr, bmc_ptr); + case MS_BR_CHAOS: + return cast_blue_breath_chaos(caster_ptr, bmc_ptr); + case MS_BR_DISEN: + return cast_blue_breath_disenchant(caster_ptr, bmc_ptr); + case MS_BR_NEXUS: + return cast_blue_breath_nexus(caster_ptr, bmc_ptr); + case MS_BR_TIME: + return cast_blue_breath_time(caster_ptr, bmc_ptr); + case MS_BR_INERTIA: + return cast_blue_breath_inertia(caster_ptr, bmc_ptr); + case MS_BR_GRAVITY: + return cast_blue_breath_gravity(caster_ptr, bmc_ptr); + case MS_BR_SHARDS: + return cast_blue_breath_shards(caster_ptr, bmc_ptr); + case MS_BR_PLASMA: + return cast_blue_breath_plasma(caster_ptr, bmc_ptr); + case MS_BR_FORCE: + return cast_blue_breath_force(caster_ptr, bmc_ptr); + case MS_BR_MANA: + return cast_blue_breath_mana(caster_ptr, bmc_ptr); + case MS_BR_NUKE: + return cast_blue_breath_nuke(caster_ptr, bmc_ptr); + case MS_BR_DISI: + return cast_blue_breath_disintegration(caster_ptr, bmc_ptr); + case MS_BALL_ACID: + return cast_blue_ball_acid(caster_ptr, bmc_ptr); + case MS_BALL_ELEC: + return cast_blue_ball_elec(caster_ptr, bmc_ptr); + case MS_BALL_FIRE: + return cast_blue_ball_fire(caster_ptr, bmc_ptr); + case MS_BALL_COLD: + return cast_blue_ball_cold(caster_ptr, bmc_ptr); + case MS_BALL_POIS: + return cast_blue_ball_pois(caster_ptr, bmc_ptr); + case MS_BALL_NUKE: + return cast_blue_ball_nuke(caster_ptr, bmc_ptr); + case MS_BALL_NETHER: + return cast_blue_ball_nether(caster_ptr, bmc_ptr); + case MS_BALL_CHAOS: + return cast_blue_ball_chaos(caster_ptr, bmc_ptr); + case MS_BALL_WATER: + return cast_blue_ball_water(caster_ptr, bmc_ptr); + case MS_STARBURST: + return cast_blue_ball_star_burst(caster_ptr, bmc_ptr); + case MS_BALL_DARK: + return cast_blue_ball_dark_storm(caster_ptr, bmc_ptr); + case MS_BALL_MANA: + return cast_blue_ball_mana_storm(caster_ptr, bmc_ptr); + case MS_DRAIN_MANA: + return cast_blue_drain_mana(caster_ptr, bmc_ptr); + case MS_MIND_BLAST: + return cast_blue_mind_blast(caster_ptr, bmc_ptr); + case MS_BRAIN_SMASH: + return cast_blue_brain_smash(caster_ptr, bmc_ptr); + case MS_CAUSE_1: + return cast_blue_curse_1(caster_ptr, bmc_ptr); + case MS_CAUSE_2: + return cast_blue_curse_2(caster_ptr, bmc_ptr); + case MS_CAUSE_3: + return cast_blue_curse_3(caster_ptr, bmc_ptr); + case MS_CAUSE_4: + return cast_blue_curse_4(caster_ptr, bmc_ptr); + case MS_BOLT_ACID: + return cast_blue_bolt_acid(caster_ptr, bmc_ptr); + case MS_BOLT_ELEC: + return cast_blue_bolt_elec(caster_ptr, bmc_ptr); + case MS_BOLT_FIRE: + return !cast_blue_bolt_fire(caster_ptr, bmc_ptr); + case MS_BOLT_COLD: + return cast_blue_bolt_cold(caster_ptr, bmc_ptr); + case MS_BOLT_NETHER: + return cast_blue_bolt_nether(caster_ptr, bmc_ptr); + case MS_BOLT_WATER: + return cast_blue_bolt_water(caster_ptr, bmc_ptr); + case MS_BOLT_MANA: + return cast_blue_bolt_mana(caster_ptr, bmc_ptr); + case MS_BOLT_PLASMA: + return cast_blue_bolt_plasma(caster_ptr, bmc_ptr); + case MS_BOLT_ICE: + return cast_blue_bolt_icee(caster_ptr, bmc_ptr); + case MS_MAGIC_MISSILE: + return cast_blue_bolt_missile(caster_ptr, bmc_ptr); + case MS_SCARE: + return cast_blue_scare(caster_ptr, bmc_ptr); + case MS_BLIND: + return cast_blue_blind(caster_ptr, bmc_ptr); + case MS_CONF: + return cast_blue_confusion(caster_ptr, bmc_ptr); + case MS_SLOW: + return cast_blue_slow(caster_ptr, bmc_ptr); + case MS_SLEEP: + return cast_blue_sleep(caster_ptr, bmc_ptr); + case MS_SPEED: + (void)set_fast(caster_ptr, randint1(20 + bmc_ptr->plev) + bmc_ptr->plev, FALSE); + return TRUE; + case MS_HAND_DOOM: + return cast_blue_hand_doom(caster_ptr, bmc_ptr); + case MS_HEAL: + msg_print(_("自分の傷に念を集中した。", "You concentrate on your wounds!")); + (void)hp_player(caster_ptr, bmc_ptr->plev * 4); + (void)set_stun(caster_ptr, 0); + (void)set_cut(caster_ptr, 0); + return TRUE; + case MS_INVULNER: + msg_print(_("無傷の球の呪文を唱えた。", "You cast a Globe of Invulnerability.")); + (void)set_invuln(caster_ptr, randint1(4) + 4, FALSE); + return TRUE; + case MS_BLINK: + teleport_player(caster_ptr, 10, TELEPORT_SPONTANEOUS); + return TRUE; + case MS_TELEPORT: + teleport_player(caster_ptr, bmc_ptr->plev * 5, TELEPORT_SPONTANEOUS); + return TRUE; + case MS_WORLD: + (void)time_walk(caster_ptr); + return TRUE; + case MS_SPECIAL: + return TRUE; + case MS_TELE_TO: + return cast_blue_teleport_back(caster_ptr); + case MS_TELE_AWAY: + return cast_blue_teleport_away(caster_ptr, bmc_ptr); + case MS_TELE_LEVEL: + return teleport_level_other(caster_ptr); + case MS_PSY_SPEAR: + return cast_blue_psy_spear(caster_ptr, bmc_ptr); + case MS_DARKNESS: + msg_print(_("暗闇の中で手を振った。", "You gesture in shadow.")); + (void)unlite_area(caster_ptr, 10, 3); + return TRUE; + case MS_MAKE_TRAP: + return cast_blue_make_trap(caster_ptr); + case MS_FORGET: + msg_print(_("しかし何も起きなかった。", "Nothing happen.")); + return TRUE; + case MS_RAISE_DEAD: + msg_print(_("死者復活の呪文を唱えた。", "You animate the dead.")); + (void)animate_dead(caster_ptr, 0, caster_ptr->y, caster_ptr->x); + return TRUE; + case MS_S_KIN: + return cast_blue_summon_kin(caster_ptr, bmc_ptr); + case MS_S_CYBER: + return cast_blue_summon_cyber(caster_ptr, bmc_ptr); + case MS_S_MONSTER: + return cast_blue_summon_monster(caster_ptr, bmc_ptr); + case MS_S_MONSTERS: + return cast_blue_summon_monsters(caster_ptr, bmc_ptr); + case MS_S_ANT: + return cast_blue_summon_ant(caster_ptr, bmc_ptr); + case MS_S_SPIDER: + return cast_blue_summon_spider(caster_ptr, bmc_ptr); + case MS_S_HOUND: + return cast_blue_summon_hound(caster_ptr, bmc_ptr); + case MS_S_HYDRA: + return cast_blue_summon_hydra(caster_ptr, bmc_ptr); + case MS_S_ANGEL: + return cast_blue_summon_angel(caster_ptr, bmc_ptr); + case MS_S_DEMON: + return cast_blue_summon_demon(caster_ptr, bmc_ptr); + case MS_S_UNDEAD: + return cast_blue_summon_undead(caster_ptr, bmc_ptr); + case MS_S_DRAGON: + return cast_blue_summon_dragon(caster_ptr, bmc_ptr); + case MS_S_HI_UNDEAD: + return cast_blue_summon_high_undead(caster_ptr, bmc_ptr); + case MS_S_HI_DRAGON: + return cast_blue_summon_high_dragon(caster_ptr, bmc_ptr); + case MS_S_AMBERITE: + return cast_blue_summon_amberite(caster_ptr, bmc_ptr); + case MS_S_UNIQUE: + return cast_blue_summon_unique(caster_ptr, bmc_ptr); + default: + msg_print("hoge?"); + return TRUE; + } +} + +/*! + * @brief 青魔法の発動 / + * do_cmd_cast calls this function if the player's class is 'blue-mage'. + * @param spell 発動するモンスター攻撃のID + * @param success TRUEは成功時、FALSEは失敗時の処理を行う + * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。 + */ +bool cast_learned_spell(player_type *caster_ptr, SPELL_IDX spell, const bool success) +{ + bmc_type tmp_bm; + bmc_type *bmc_ptr = initialize_blue_magic_type(caster_ptr, &tmp_bm, success, get_pseudo_monstetr_level); + if (switch_cast_blue_magic(caster_ptr, bmc_ptr, spell)) + return FALSE; + + if (bmc_ptr->no_trump) + msg_print(_("何も現れなかった。", "No one appeared.")); + + return TRUE; +} diff --git a/src/blue-magic/blue-magic-caster.h b/src/blue-magic/blue-magic-caster.h new file mode 100644 index 000000000..5f0b27ce1 --- /dev/null +++ b/src/blue-magic/blue-magic-caster.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool cast_learned_spell(player_type *caster_ptr, SPELL_IDX spell, const bool success); diff --git a/src/blue-magic/blue-magic-checker.c b/src/blue-magic/blue-magic-checker.c new file mode 100644 index 000000000..f698ee1af --- /dev/null +++ b/src/blue-magic/blue-magic-checker.c @@ -0,0 +1,96 @@ +/*! + * @brief 青魔法の処理実装 / Blue magic + * @date 2014/01/15 + * @author + * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke + * This software may be copied and distributed for educational, research, + * and not for profit purposes provided that this copyright and statement + * are included in all such copies. Other copyrights may also apply. + * 2014 Deskull rearranged comment for Doxygen. + */ + +#include "blue-magic/blue-magic-checker.h" +#include "core/player-redraw-types.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "mind/mind-blue-mage.h" +#include "monster-race/race-flags4.h" +#include "monster-race/race-flags-ability1.h" +#include "monster-race/race-flags-ability2.h" +#include "mspell/monster-power-table.h" +#include "mspell/mspell-mask-definitions.h" +#include "player/attack-defense-types.h" +#include "status/experience.h" +#include "view/display-messages.h" + +/*! + * @brief 青魔法のラーニング判定と成功した場合のラーニング処理 + * @param monspell ラーニングを試みるモンスター攻撃のID + * @return なし + */ +void learn_spell(player_type *learner_ptr, int monspell) +{ + if (learner_ptr->action != ACTION_LEARN) + return; + if (monspell < 0) + return; + if (learner_ptr->magic_num2[monspell]) + return; + if (learner_ptr->confused || learner_ptr->blind || learner_ptr->image || learner_ptr->stun || learner_ptr->paralyzed) + return; + if (randint1(learner_ptr->lev + 70) > monster_powers[monspell].level + 40) { + learner_ptr->magic_num2[monspell] = 1; + msg_format(_("%sを学習した!", "You have learned %s!"), monster_powers[monspell].name); + gain_exp(learner_ptr, monster_powers[monspell].level * monster_powers[monspell].smana); + sound(SOUND_STUDY); + learner_ptr->new_mane = TRUE; + learner_ptr->redraw |= PR_STATE; + } +} + +/*! + * todo f4, f5, f6を構造体にまとめ直す + * @brief モンスター特殊能力のフラグ配列から特定条件の魔法だけを抜き出す処理 + * Extract monster spells mask for the given mode + * @param f4 モンスター特殊能力の4番目のフラグ配列 + * @param f5 モンスター特殊能力の5番目のフラグ配列 + * @param f6 モンスター特殊能力の6番目のフラグ配列 + * @param mode 抜き出したい条件 + * @return なし + */ +/* + */ +void set_rf_masks(BIT_FLAGS *f4, BIT_FLAGS *f5, BIT_FLAGS *f6, blue_magic_type mode) +{ + switch (mode) { + case MONSPELL_TYPE_BOLT: + *f4 = ((RF4_BOLT_MASK | RF4_BEAM_MASK) & ~(RF4_ROCKET)); + *f5 = RF5_BOLT_MASK | RF5_BEAM_MASK; + *f6 = RF6_BOLT_MASK | RF6_BEAM_MASK; + break; + + case MONSPELL_TYPE_BALL: + *f4 = (RF4_BALL_MASK & ~(RF4_BREATH_MASK)); + *f5 = (RF5_BALL_MASK & ~(RF5_BREATH_MASK)); + *f6 = (RF6_BALL_MASK & ~(RF6_BREATH_MASK)); + break; + + case MONSPELL_TYPE_BREATH: + *f4 = (BIT_FLAGS)RF4_BREATH_MASK; + *f5 = RF5_BREATH_MASK; + *f6 = RF6_BREATH_MASK; + break; + + case MONSPELL_TYPE_SUMMON: + *f4 = RF4_SUMMON_MASK; + *f5 = RF5_SUMMON_MASK; + *f6 = (BIT_FLAGS)RF6_SUMMON_MASK; + break; + + case MONSPELL_TYPE_OTHER: + *f4 = RF4_ATTACK_MASK & ~(RF4_BOLT_MASK | RF4_BEAM_MASK | RF4_BALL_MASK | RF4_INDIRECT_MASK); + *f5 = RF5_ATTACK_MASK & ~(RF5_BOLT_MASK | RF5_BEAM_MASK | RF5_BALL_MASK | RF5_INDIRECT_MASK); + *f6 = RF6_ATTACK_MASK & ~(RF6_BOLT_MASK | RF6_BEAM_MASK | RF6_BALL_MASK | RF6_INDIRECT_MASK); + break; + } +} diff --git a/src/blue-magic/blue-magic-checker.h b/src/blue-magic/blue-magic-checker.h new file mode 100644 index 000000000..1604b4d35 --- /dev/null +++ b/src/blue-magic/blue-magic-checker.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +typedef enum blue_magic_type blue_magic_type; +void learn_spell(player_type *learner_ptr, int monspell); +void set_rf_masks(BIT_FLAGS *f4, BIT_FLAGS *f5, BIT_FLAGS *f6, blue_magic_type mode); diff --git a/src/blue-magic/blue-magic-spirit-curse.c b/src/blue-magic/blue-magic-spirit-curse.c new file mode 100644 index 000000000..dd762d255 --- /dev/null +++ b/src/blue-magic/blue-magic-spirit-curse.c @@ -0,0 +1,78 @@ +#include "blue-magic/blue-magic-spirit-curse.h" +#include "blue-magic/blue-magic-util.h" +#include "mspell/mspell-damage-calculator.h" +#include "mspell/mspell-type.h" +#include "spell-kind/spells-launcher.h" +#include "spell/spell-types.h" +#include "target/target-getter.h" +#include "view/display-messages.h" + +bool cast_blue_drain_mana(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_DRAIN_MANA, bmc_ptr->plev, DAM_ROLL); + fire_ball_hide(caster_ptr, GF_DRAIN_MANA, bmc_ptr->dir, bmc_ptr->damage, 0); + return TRUE; +} + +bool cast_blue_mind_blast(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_MIND_BLAST, bmc_ptr->plev, DAM_ROLL); + fire_ball_hide(caster_ptr, GF_MIND_BLAST, bmc_ptr->dir, bmc_ptr->damage, 0); + return TRUE; +} + +bool cast_blue_brain_smash(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_BRAIN_SMASH, bmc_ptr->plev, DAM_ROLL); + fire_ball_hide(caster_ptr, GF_BRAIN_SMASH, bmc_ptr->dir, bmc_ptr->damage, 0); + return TRUE; +} + +bool cast_blue_curse_1(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_CAUSE_1, bmc_ptr->plev, DAM_ROLL); + fire_ball_hide(caster_ptr, GF_CAUSE_1, bmc_ptr->dir, bmc_ptr->damage, 0); + return TRUE; +} + +bool cast_blue_curse_2(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_CAUSE_2, bmc_ptr->plev, DAM_ROLL); + fire_ball_hide(caster_ptr, GF_CAUSE_2, bmc_ptr->dir, bmc_ptr->damage, 0); + return TRUE; +} + +bool cast_blue_curse_3(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_CAUSE_3, bmc_ptr->plev, DAM_ROLL); + fire_ball_hide(caster_ptr, GF_CAUSE_3, bmc_ptr->dir, bmc_ptr->damage, 0); + return TRUE; +} + +bool cast_blue_curse_4(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + bmc_ptr->damage = monspell_bluemage_damage(caster_ptr, MS_CAUSE_4, bmc_ptr->plev, DAM_ROLL); + fire_ball_hide(caster_ptr, GF_CAUSE_4, bmc_ptr->dir, bmc_ptr->damage, 0); + return TRUE; +} diff --git a/src/blue-magic/blue-magic-spirit-curse.h b/src/blue-magic/blue-magic-spirit-curse.h new file mode 100644 index 000000000..4f87b86f2 --- /dev/null +++ b/src/blue-magic/blue-magic-spirit-curse.h @@ -0,0 +1,12 @@ +#pragma once + +#include "system/angband.h" + +typedef struct bmc_type bmc_type; +bool cast_blue_drain_mana(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_mind_blast(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_brain_smash(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_curse_1(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_curse_2(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_curse_3(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_curse_4(player_type *caster_ptr, bmc_type *bmc_ptr); diff --git a/src/blue-magic/blue-magic-status.c b/src/blue-magic/blue-magic-status.c new file mode 100644 index 000000000..dff7a1210 --- /dev/null +++ b/src/blue-magic/blue-magic-status.c @@ -0,0 +1,52 @@ +#include "blue-magic/blue-magic-status.h" +#include "blue-magic/blue-magic-util.h" +#include "spell/spells-status.h" +#include "target/target-getter.h" +#include "view/display-messages.h" + +bool cast_blue_scare(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("恐ろしげな幻覚を作り出した。", "You cast a fearful illusion.")); + fear_monster(caster_ptr, bmc_ptr->dir, bmc_ptr->plev + 10); + return TRUE; +} + +bool cast_blue_blind(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + confuse_monster(caster_ptr, bmc_ptr->dir, bmc_ptr->plev * 2); + return TRUE; +} + +bool cast_blue_confusion(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + msg_print(_("誘惑的な幻覚をつくり出した。", "You cast a mesmerizing illusion.")); + confuse_monster(caster_ptr, bmc_ptr->dir, bmc_ptr->plev * 2); + return TRUE; +} + +bool cast_blue_slow(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + slow_monster(caster_ptr, bmc_ptr->dir, bmc_ptr->plev); + return TRUE; +} + +bool cast_blue_sleep(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + if (!get_aim_dir(caster_ptr, &bmc_ptr->dir)) + return FALSE; + + sleep_monster(caster_ptr, bmc_ptr->dir, bmc_ptr->plev); + return TRUE; +} diff --git a/src/blue-magic/blue-magic-status.h b/src/blue-magic/blue-magic-status.h new file mode 100644 index 000000000..1fca09748 --- /dev/null +++ b/src/blue-magic/blue-magic-status.h @@ -0,0 +1,10 @@ +#pragma once + +#include "system/angband.h" + +typedef struct bmc_type bmc_type; +bool cast_blue_scare(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_blind(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_confusion(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_slow(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_sleep(player_type *caster_ptr, bmc_type *bmc_ptr); diff --git a/src/blue-magic/blue-magic-summon.c b/src/blue-magic/blue-magic-summon.c new file mode 100644 index 000000000..3f6ad765b --- /dev/null +++ b/src/blue-magic/blue-magic-summon.c @@ -0,0 +1,249 @@ +#include "blue-magic/blue-magic-summon.h" +#include "blue-magic/blue-magic-util.h" +#include "monster-floor/monster-summon.h" +#include "monster-floor/place-monster-types.h" +#include "spell/spells-summon.h" +#include "spell/summon-types.h" +#include "view/display-messages.h" + +bool cast_blue_summon_kin(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("援軍を召喚した。", "You summon one of your kin.")); + for (int k = 0; k < 1; k++) { + if (summon_kin_player(caster_ptr, bmc_ptr->summon_lev, caster_ptr->y, caster_ptr->x, (bmc_ptr->pet ? PM_FORCE_PET : 0L))) { + if (!bmc_ptr->pet) + msg_print(_("召喚された仲間は怒っている!", "The summoned companion is angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + } + + return TRUE; +} + +bool cast_blue_summon_cyber(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("サイバーデーモンを召喚した!", "You summon a Cyberdemon!")); + for (int k = 0; k < 1; k++) { + if (summon_specific(caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_CYBER, bmc_ptr->p_mode)) { + if (!bmc_ptr->pet) + msg_print(_("召喚されたサイバーデーモンは怒っている!", "The summoned Cyberdemon are angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + } + + return TRUE; +} + +bool cast_blue_summon_monster(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("仲間を召喚した。", "You summon help.")); + for (int k = 0; k < 1; k++) { + if (summon_specific(caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, 0, bmc_ptr->p_mode)) { + if (!bmc_ptr->pet) + msg_print(_("召喚されたモンスターは怒っている!", "The summoned monster is angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + } + + return TRUE; +} + +bool cast_blue_summon_monsters(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("モンスターを召喚した!", "You summon monsters!")); + for (int k = 0; k < bmc_ptr->plev / 15 + 2; k++) { + if (summon_specific(caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, 0, (bmc_ptr->p_mode | bmc_ptr->u_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚されたモンスターは怒っている!", "The summoned monsters are angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + } + + return TRUE; +} + +bool cast_blue_summon_ant(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("アリを召喚した。", "You summon ants.")); + if (summon_specific( + caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_ANT, (PM_ALLOW_GROUP | bmc_ptr->p_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚されたアリは怒っている!", "The summoned ants are angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + + return TRUE; +} + +bool cast_blue_summon_spider(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("蜘蛛を召喚した。", "You summon spiders.")); + if (summon_specific( + caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_SPIDER, (PM_ALLOW_GROUP | bmc_ptr->p_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚された蜘蛛は怒っている!", "Summoned spiders are angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + + return TRUE; +} + +bool cast_blue_summon_hound(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("ハウンドを召喚した。", "You summon hounds.")); + if (summon_specific( + caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_HOUND, (PM_ALLOW_GROUP | bmc_ptr->p_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚されたハウンドは怒っている!", "Summoned hounds are angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + + return TRUE; +} + +bool cast_blue_summon_hydra(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("ヒドラを召喚した。", "You summon a hydras.")); + if (summon_specific( + caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_HYDRA, (bmc_ptr->g_mode | bmc_ptr->p_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚されたヒドラは怒っている!", "Summoned hydras are angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + + return TRUE; +} + +bool cast_blue_summon_angel(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("天使を召喚した!", "You summon an angel!")); + if (summon_specific( + caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_ANGEL, (bmc_ptr->g_mode | bmc_ptr->p_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚された天使は怒っている!", "The summoned angel is angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + + return TRUE; +} + +bool cast_blue_summon_demon(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("混沌の宮廷から悪魔を召喚した!", "You summon a demon from the Courts of Chaos!")); + if (summon_specific( + caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_DEMON, (bmc_ptr->g_mode | bmc_ptr->p_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚されたデーモンは怒っている!", "The summoned demon is angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + + return TRUE; +} + +bool cast_blue_summon_undead(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("アンデッドの強敵を召喚した!", "You summon an undead adversary!")); + if (summon_specific( + caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_UNDEAD, (bmc_ptr->g_mode | bmc_ptr->p_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚されたアンデッドは怒っている!", "The summoned undead is angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + + return TRUE; +} + +bool cast_blue_summon_dragon(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("ドラゴンを召喚した!", "You summon a dragon!")); + if (summon_specific( + caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_DRAGON, (bmc_ptr->g_mode | bmc_ptr->p_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚されたドラゴンは怒っている!", "The summoned dragon is angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + + return TRUE; +} + +bool cast_blue_summon_high_undead(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("強力なアンデッドを召喚した!", "You summon a greater undead!")); + if (summon_specific(caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_HI_UNDEAD, + (bmc_ptr->g_mode | bmc_ptr->p_mode | bmc_ptr->u_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚された上級アンデッドは怒っている!", "The summoned greater undead is angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + + return TRUE; +} + +bool cast_blue_summon_high_dragon(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("古代ドラゴンを召喚した!", "You summon an ancient dragon!")); + if (summon_specific(caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_HI_DRAGON, + (bmc_ptr->g_mode | bmc_ptr->p_mode | bmc_ptr->u_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚された古代ドラゴンは怒っている!", "The summoned ancient dragon is angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + + return TRUE; +} + +bool cast_blue_summon_amberite(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + msg_print(_("アンバーの王族を召喚した!", "You summon a Lord of Amber!")); + if (summon_specific(caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_AMBERITES, + (bmc_ptr->g_mode | bmc_ptr->p_mode | bmc_ptr->u_mode))) { + if (!bmc_ptr->pet) + msg_print(_("召喚されたアンバーの王族は怒っている!", "The summoned Lord of Amber is angry!")); + } else { + bmc_ptr->no_trump = TRUE; + } + + return TRUE; +} + +bool cast_blue_summon_unique(player_type *caster_ptr, bmc_type *bmc_ptr) +{ + int count = 0; + msg_print(_("特別な強敵を召喚した!", "You summon a special opponent!")); + for (int k = 0; k < 1; k++) { + if (summon_specific(caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_UNIQUE, + (bmc_ptr->g_mode | bmc_ptr->p_mode | PM_ALLOW_UNIQUE))) { + count++; + if (!bmc_ptr->pet) + msg_print(_("召喚されたユニーク・モンスターは怒っている!", "The summoned special opponent is angry!")); + } + } + + for (int k = count; k < 1; k++) { + if (summon_specific(caster_ptr, (bmc_ptr->pet ? -1 : 0), caster_ptr->y, caster_ptr->x, bmc_ptr->summon_lev, SUMMON_HI_UNDEAD, + (bmc_ptr->g_mode | bmc_ptr->p_mode | PM_ALLOW_UNIQUE))) { + count++; + if (!bmc_ptr->pet) + msg_print(_("召喚された上級アンデッドは怒っている!", "The summoned greater undead is angry!")); + } + } + + if (!count) + bmc_ptr->no_trump = TRUE; + + return TRUE; +} diff --git a/src/blue-magic/blue-magic-summon.h b/src/blue-magic/blue-magic-summon.h new file mode 100644 index 000000000..51223769a --- /dev/null +++ b/src/blue-magic/blue-magic-summon.h @@ -0,0 +1,21 @@ +#pragma once + +#include "system/angband.h" + +typedef struct bmc_type bmc_type; +bool cast_blue_summon_kin(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_cyber(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_monster(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_monsters(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_ant(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_spider(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_hound(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_hydra(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_angel(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_demon(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_undead(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_dragon(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_high_undead(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_high_dragon(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_amberite(player_type *caster_ptr, bmc_type *bmc_ptr); +bool cast_blue_summon_unique(player_type *caster_ptr, bmc_type *bmc_ptr); diff --git a/src/blue-magic/blue-magic-util.c b/src/blue-magic/blue-magic-util.c new file mode 100644 index 000000000..8ec36dfdc --- /dev/null +++ b/src/blue-magic/blue-magic-util.c @@ -0,0 +1,19 @@ +#include "blue-magic/blue-magic-util.h" +#include "monster-floor/place-monster-types.h" + +bmc_type *initialize_blue_magic_type( + player_type *caster_ptr, bmc_type *bmc_ptr, const bool success, get_pseudo_monstetr_level_pf get_pseudo_monstetr_level) +{ + bmc_ptr->plev = (*get_pseudo_monstetr_level)(caster_ptr); + bmc_ptr->summon_lev = caster_ptr->lev * 2 / 3 + randint1(caster_ptr->lev / 2); + bmc_ptr->damage = 0; + bmc_ptr->pet = success; // read-only. + bmc_ptr->no_trump = FALSE; + bmc_ptr->p_mode = bmc_ptr->pet ? PM_FORCE_PET : PM_NO_PET; + bmc_ptr->u_mode = 0L; + bmc_ptr->g_mode = bmc_ptr->pet ? 0 : PM_ALLOW_GROUP; + if (!success || (randint1(50 + bmc_ptr->plev) < bmc_ptr->plev / 10)) + bmc_ptr->u_mode = PM_ALLOW_UNIQUE; + + return bmc_ptr; +} diff --git a/src/blue-magic/blue-magic-util.h b/src/blue-magic/blue-magic-util.h new file mode 100644 index 000000000..c1142aeab --- /dev/null +++ b/src/blue-magic/blue-magic-util.h @@ -0,0 +1,20 @@ +#pragma once + +#include "system/angband.h" + +// Blue Magic Cast. +typedef struct bmc_type { + DIRECTION dir; + PLAYER_LEVEL plev; + PLAYER_LEVEL summon_lev; + HIT_POINT damage; + bool pet; + bool no_trump; + BIT_FLAGS p_mode; + BIT_FLAGS u_mode; + BIT_FLAGS g_mode; +} bmc_type; + +typedef PLAYER_LEVEL (*get_pseudo_monstetr_level_pf)(player_type *caster_ptr); +bmc_type *initialize_blue_magic_type( + player_type *caster_ptr, bmc_type *bmc_ptr, const bool success, get_pseudo_monstetr_level_pf get_pseudo_monstetr_level); diff --git a/src/blue-magic/learnt-info.c b/src/blue-magic/learnt-info.c new file mode 100644 index 000000000..f91206062 --- /dev/null +++ b/src/blue-magic/learnt-info.c @@ -0,0 +1,176 @@ +#include "blue-magic/learnt-info.h" +#include "cmd-action/cmd-spell.h" +#include "lore/lore-calculator.h" // todo 少し違和感. +#include "mspell/mspell-damage-calculator.h" +#include "mspell/mspell-type.h" + +/*! + * @brief モンスター魔法をプレイヤーが使用する場合の換算レベル + * @param caster_ptr プレーヤーへの参照ポインタ + * @param 換算レベル + */ +PLAYER_LEVEL get_pseudo_monstetr_level(player_type *caster_ptr) +{ + PLAYER_LEVEL monster_level = caster_ptr->lev + 40; + return (monster_level * monster_level - 1550) / 130; +} + +/*! + * @brief 文字列に青魔導師の呪文の攻撃力を加える + * @param SPELL_NUM 呪文番号 + * @param plev プレイヤーレベル + * @param msg 表示する文字列 + * @param tmp 返すメッセージを格納する配列 + * @return なし + */ +static void set_bluemage_damage(player_type *learner_type, monster_spell_type ms_type, PLAYER_LEVEL plev, concptr msg, char *tmp) +{ + int base_damage = monspell_bluemage_damage(learner_type, ms_type, plev, BASE_DAM); + int dice_num = monspell_bluemage_damage(learner_type, ms_type, plev, DICE_NUM); + int dice_side = monspell_bluemage_damage(learner_type, ms_type, plev, DICE_SIDE); + int dice_mult = monspell_bluemage_damage(learner_type, ms_type, plev, DICE_MULT); + int dice_div = monspell_bluemage_damage(learner_type, ms_type, plev, DICE_DIV); + char dmg_str[80]; + dice_to_string(base_damage, dice_num, dice_side, dice_mult, dice_div, dmg_str); + sprintf(tmp, " %s %s", msg, dmg_str); +} + +/*! + * @brief 受け取ったモンスター魔法のIDに応じて青魔法の効果情報をまとめたフォーマットを返す + * @param learner_ptr プレーヤーへの参照ポインタ + * @param p 情報を返す文字列参照ポインタ + * @param power モンスター魔法のID + * @return なし + */ +void learnt_info(player_type *learner_ptr, char *p, int power) +{ + PLAYER_LEVEL plev = get_pseudo_monstetr_level(learner_ptr); + + strcpy(p, ""); + + switch (power) { + case MS_SHRIEK: + case MS_XXX1: + case MS_XXX2: + case MS_XXX3: + case MS_XXX4: + case MS_SCARE: + case MS_BLIND: + case MS_CONF: + case MS_SLOW: + case MS_SLEEP: + case MS_HAND_DOOM: + case MS_WORLD: + case MS_SPECIAL: + case MS_TELE_TO: + case MS_TELE_AWAY: + case MS_TELE_LEVEL: + case MS_DARKNESS: + case MS_MAKE_TRAP: + case MS_FORGET: + case MS_S_KIN: + case MS_S_CYBER: + case MS_S_MONSTER: + case MS_S_MONSTERS: + case MS_S_ANT: + case MS_S_SPIDER: + case MS_S_HOUND: + case MS_S_HYDRA: + case MS_S_ANGEL: + case MS_S_DEMON: + case MS_S_UNDEAD: + case MS_S_DRAGON: + case MS_S_HI_UNDEAD: + case MS_S_HI_DRAGON: + case MS_S_AMBERITE: + case MS_S_UNIQUE: + break; + case MS_BALL_MANA: + case MS_BALL_DARK: + case MS_STARBURST: + set_bluemage_damage(learner_ptr, power, plev, KWD_DAM, p); + break; + case MS_DISPEL: + break; + case MS_ROCKET: + case MS_SHOOT: + case MS_BR_ACID: + case MS_BR_ELEC: + case MS_BR_FIRE: + case MS_BR_COLD: + case MS_BR_POIS: + case MS_BR_NUKE: + case MS_BR_NEXUS: + case MS_BR_TIME: + case MS_BR_GRAVITY: + case MS_BR_MANA: + case MS_BR_NETHER: + case MS_BR_LITE: + case MS_BR_DARK: + case MS_BR_CONF: + case MS_BR_SOUND: + case MS_BR_CHAOS: + case MS_BR_DISEN: + case MS_BR_SHARDS: + case MS_BR_PLASMA: + case MS_BR_INERTIA: + case MS_BR_FORCE: + case MS_BR_DISI: + case MS_BALL_NUKE: + case MS_BALL_CHAOS: + case MS_BALL_ACID: + case MS_BALL_ELEC: + case MS_BALL_FIRE: + case MS_BALL_COLD: + case MS_BALL_POIS: + case MS_BALL_NETHER: + case MS_BALL_WATER: + set_bluemage_damage(learner_ptr, power, plev, KWD_DAM, p); + break; + case MS_DRAIN_MANA: + set_bluemage_damage(learner_ptr, power, plev, KWD_HEAL, p); + break; + case MS_MIND_BLAST: + case MS_BRAIN_SMASH: + case MS_CAUSE_1: + case MS_CAUSE_2: + case MS_CAUSE_3: + case MS_CAUSE_4: + case MS_BOLT_ACID: + case MS_BOLT_ELEC: + case MS_BOLT_FIRE: + case MS_BOLT_COLD: + case MS_BOLT_NETHER: + case MS_BOLT_WATER: + case MS_BOLT_MANA: + case MS_BOLT_PLASMA: + case MS_BOLT_ICE: + case MS_MAGIC_MISSILE: + set_bluemage_damage(learner_ptr, power, plev, KWD_DAM, p); + break; + case MS_SPEED: + sprintf(p, " %sd%d+%d", KWD_DURATION, 20 + plev, plev); + break; + case MS_HEAL: + set_bluemage_damage(learner_ptr, power, plev, KWD_HEAL, p); + break; + case MS_INVULNER: + sprintf(p, " %sd7+7", KWD_DURATION); + break; + case MS_BLINK: + sprintf(p, " %s10", KWD_SPHERE); + break; + case MS_TELEPORT: + sprintf(p, " %s%d", KWD_SPHERE, plev * 5); + break; + case MS_PSY_SPEAR: + set_bluemage_damage(learner_ptr, power, plev, KWD_DAM, p); + break; + break; + case MS_RAISE_DEAD: + sprintf(p, " %s5", KWD_SPHERE); + break; + default: + break; + } +} diff --git a/src/blue-magic/learnt-info.h b/src/blue-magic/learnt-info.h new file mode 100644 index 000000000..96c819a06 --- /dev/null +++ b/src/blue-magic/learnt-info.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" + +PLAYER_LEVEL get_pseudo_monstetr_level(player_type *caster_ptr); +void learnt_info(player_type *learner_ptr, char *p, int power); diff --git a/src/blue-magic/learnt-power-getter.c b/src/blue-magic/learnt-power-getter.c new file mode 100644 index 000000000..95fdb4339 --- /dev/null +++ b/src/blue-magic/learnt-power-getter.c @@ -0,0 +1,439 @@ +#include "blue-magic/learnt-power-getter.h" +#include "blue-magic/blue-magic-checker.h" +#include "blue-magic/learnt-info.h" +#include "core/asking-player.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "game-option/text-display-options.h" +#include "io/command-repeater.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "main/sound-of-music.h" +#include "mind/mind-blue-mage.h" +#include "mspell/monster-power-table.h" +#include "realm/realm-types.h" +#include "spell/spell-info.h" +#include "term/screen-processor.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" +#include "player/player-status-table.h" + +typedef struct learnt_magic_type { + int blue_magic_num; + int count; + TERM_LEN y; + TERM_LEN x; + PLAYER_LEVEL plev; + PERCENTAGE chance; + int ask; + int mode; + int blue_magics[MAX_MONSPELLS]; + char choice; + char out_val[160]; + char comment[80]; + BIT_FLAGS f4; + BIT_FLAGS f5; + BIT_FLAGS f6; + monster_power spell; + int menu_line; + bool flag; + bool redraw; + int need_mana; + char psi_desc[80]; +} learnt_magic_type; + +static learnt_magic_type *initialize_lenat_magic_type(player_type *caster_ptr, learnt_magic_type *lm_ptr) +{ + lm_ptr->blue_magic_num = 0; + lm_ptr->count = 0; + lm_ptr->y = 1; + lm_ptr->x = 18; + lm_ptr->plev = caster_ptr->lev; + lm_ptr->chance = 0; + lm_ptr->ask = TRUE; + lm_ptr->mode = 0; + lm_ptr->f4 = 0L; + lm_ptr->f5 = 0L; + lm_ptr->f6 = 0L; + lm_ptr->menu_line = use_menu ? 1 : 0; + lm_ptr->flag = FALSE; + lm_ptr->redraw = FALSE; + return lm_ptr; +} + +/*! + * @brief コマンド反復チェック + * @param sn 選択したモンスター攻撃ID + * @return 発動可能な魔法を選択した場合TRUE、処理続行の場合FALSE + */ +static bool check_blue_magic_cancel(SPELL_IDX *sn) +{ + *sn = -1; + COMMAND_CODE code; + if (!repeat_pull(&code)) + return FALSE; + + *sn = (SPELL_IDX)code; + return TRUE; +} + +static bool select_blue_magic_kind_menu(learnt_magic_type *lm_ptr) +{ + while (lm_ptr->mode == 0) { + prt(format(_(" %s ボルト", " %s bolt"), (lm_ptr->menu_line == 1) ? _("》", "> ") : " "), 2, 14); + prt(format(_(" %s ボール", " %s ball"), (lm_ptr->menu_line == 2) ? _("》", "> ") : " "), 3, 14); + prt(format(_(" %s ブレス", " %s breath"), (lm_ptr->menu_line == 3) ? _("》", "> ") : " "), 4, 14); + prt(format(_(" %s 召喚", " %s sommoning"), (lm_ptr->menu_line == 4) ? _("》", "> ") : " "), 5, 14); + prt(format(_(" %s その他", " %s others"), (lm_ptr->menu_line == 5) ? _("》", "> ") : " "), 6, 14); + prt(_("どの種類の魔法を使いますか?", "use which type of magic? "), 0, 0); + + lm_ptr->choice = inkey(); + switch (lm_ptr->choice) { + case ESCAPE: + case 'z': + case 'Z': + screen_load(); + return FALSE; + case '2': + case 'j': + case 'J': + lm_ptr->menu_line++; + break; + case '8': + case 'k': + case 'K': + lm_ptr->menu_line += 4; + break; + case '\r': + case 'x': + case 'X': + lm_ptr->mode = lm_ptr->menu_line; + break; + } + + if (lm_ptr->menu_line > 5) + lm_ptr->menu_line -= 5; + } + + return TRUE; +} + +static bool select_blue_magic_kind_command(learnt_magic_type *lm_ptr) +{ + sprintf(lm_ptr->comment, _("[A]ボルト, [B]ボール, [C]ブレス, [D]召喚, [E]その他:", "[A] bolt, [B] ball, [C] breath, [D] summoning, [E] others:")); + while (TRUE) { + char ch; + if (!get_com(lm_ptr->comment, &ch, TRUE)) + return FALSE; + + if (ch == 'A' || ch == 'a') { + lm_ptr->mode = 1; + break; + } + + if (ch == 'B' || ch == 'b') { + lm_ptr->mode = 2; + break; + } + + if (ch == 'C' || ch == 'c') { + lm_ptr->mode = 3; + break; + } + + if (ch == 'D' || ch == 'd') { + lm_ptr->mode = 4; + break; + } + + if (ch == 'E' || ch == 'e') { + lm_ptr->mode = 5; + break; + } + } + + return TRUE; +} + +static bool check_blue_magic_kind(learnt_magic_type *lm_ptr) +{ + if (!use_menu) + return select_blue_magic_kind_command(lm_ptr); + + screen_save(); + if (!select_blue_magic_kind_menu(lm_ptr)) + return FALSE; + + screen_load(); + return TRUE; +} + +static bool sweep_learnt_spells(player_type *caster_ptr, learnt_magic_type *lm_ptr) +{ + set_rf_masks(&lm_ptr->f4, &lm_ptr->f5, &lm_ptr->f6, lm_ptr->mode); + for (lm_ptr->blue_magic_num = 0, lm_ptr->count = 0; lm_ptr->blue_magic_num < 32; lm_ptr->blue_magic_num++) + if ((0x00000001 << lm_ptr->blue_magic_num) & lm_ptr->f4) + lm_ptr->blue_magics[lm_ptr->count++] = lm_ptr->blue_magic_num; + + for (; lm_ptr->blue_magic_num < 64; lm_ptr->blue_magic_num++) + if ((0x00000001 << (lm_ptr->blue_magic_num - 32)) & lm_ptr->f5) + lm_ptr->blue_magics[lm_ptr->count++] = lm_ptr->blue_magic_num; + + for (; lm_ptr->blue_magic_num < 96; lm_ptr->blue_magic_num++) + if ((0x00000001 << (lm_ptr->blue_magic_num - 64)) & lm_ptr->f6) + lm_ptr->blue_magics[lm_ptr->count++] = lm_ptr->blue_magic_num; + + for (lm_ptr->blue_magic_num = 0; lm_ptr->blue_magic_num < lm_ptr->count; lm_ptr->blue_magic_num++) { + if (caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->blue_magic_num]] == 0) + continue; + + if (use_menu) + lm_ptr->menu_line = lm_ptr->blue_magic_num + 1; + + break; + } + + if (lm_ptr->blue_magic_num == lm_ptr->count) { + msg_print(_("その種類の魔法は覚えていない!", "You don't know any spell of this type.")); + return FALSE; + } + + (void)strnfmt(lm_ptr->out_val, 78, _("(%c-%c, '*'で一覧, ESC) どの%sを唱えますか?", "(%c-%c, *=List, ESC=exit) Use which %s? "), I2A(0), + I2A(lm_ptr->count - 1), _("魔法", "magic")); + return TRUE; +} + +static bool switch_blue_magic_choice(player_type *caster_ptr, learnt_magic_type *lm_ptr) +{ + switch (lm_ptr->choice) { + case '0': + screen_load(); + return FALSE; + case '8': + case 'k': + case 'K': + do { + lm_ptr->menu_line += (lm_ptr->count - 1); + if (lm_ptr->menu_line > lm_ptr->count) + lm_ptr->menu_line -= lm_ptr->count; + } while (!caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->menu_line - 1]]); + return TRUE; + case '2': + case 'j': + case 'J': + do { + lm_ptr->menu_line++; + if (lm_ptr->menu_line > lm_ptr->count) + lm_ptr->menu_line -= lm_ptr->count; + } while (!caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->menu_line - 1]]); + return TRUE; + case '6': + case 'l': + case 'L': + lm_ptr->menu_line = lm_ptr->count; + while (!caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->menu_line - 1]]) + lm_ptr->menu_line--; + + return TRUE; + case '4': + case 'h': + case 'H': + lm_ptr->menu_line = 1; + while (!caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->menu_line - 1]]) + lm_ptr->menu_line++; + + return TRUE; + case 'x': + case 'X': + case '\r': + lm_ptr->blue_magic_num = lm_ptr->menu_line - 1; + lm_ptr->ask = FALSE; + return TRUE; + default: + return TRUE; + } +} + +static void calculate_blue_magic_success_probability(player_type *caster_ptr, learnt_magic_type *lm_ptr) +{ + lm_ptr->chance = lm_ptr->spell.fail; + if (lm_ptr->plev > lm_ptr->spell.level) + lm_ptr->chance -= 3 * (lm_ptr->plev - lm_ptr->spell.level); + else + lm_ptr->chance += (lm_ptr->spell.level - lm_ptr->plev); + + lm_ptr->chance -= 3 * (adj_mag_stat[caster_ptr->stat_ind[A_INT]] - 1); + lm_ptr->chance = mod_spell_chance_1(caster_ptr, lm_ptr->chance); + lm_ptr->need_mana = mod_need_mana(caster_ptr, monster_powers[lm_ptr->blue_magics[lm_ptr->blue_magic_num]].smana, 0, REALM_NONE); + if (lm_ptr->need_mana > caster_ptr->csp) + lm_ptr->chance += 5 * (lm_ptr->need_mana - caster_ptr->csp); + + PERCENTAGE minfail = adj_mag_fail[caster_ptr->stat_ind[A_INT]]; + if (lm_ptr->chance < minfail) + lm_ptr->chance = minfail; + + if (caster_ptr->stun > 50) + lm_ptr->chance += 25; + else if (caster_ptr->stun) + lm_ptr->chance += 15; + + if (lm_ptr->chance > 95) + lm_ptr->chance = 95; + + lm_ptr->chance = mod_spell_chance_2(caster_ptr, lm_ptr->chance); +} + +static void close_blue_magic_name(learnt_magic_type *lm_ptr) +{ + if (!use_menu) { + sprintf(lm_ptr->psi_desc, " %c)", I2A(lm_ptr->blue_magic_num)); + return; + } + + if (lm_ptr->blue_magic_num == (lm_ptr->menu_line - 1)) + strcpy(lm_ptr->psi_desc, _(" 》", " > ")); + else + strcpy(lm_ptr->psi_desc, " "); +} + +static void describe_blue_magic_name(player_type *caster_ptr, learnt_magic_type *lm_ptr) +{ + prt("", lm_ptr->y, lm_ptr->x); + put_str(_("名前", "Name"), lm_ptr->y, lm_ptr->x + 5); + put_str(_("MP 失率 効果", "SP Fail Info"), lm_ptr->y, lm_ptr->x + 33); + for (lm_ptr->blue_magic_num = 0; lm_ptr->blue_magic_num < lm_ptr->count; lm_ptr->blue_magic_num++) { + prt("", lm_ptr->y + lm_ptr->blue_magic_num + 1, lm_ptr->x); + if (!caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->blue_magic_num]]) + continue; + + lm_ptr->spell = monster_powers[lm_ptr->blue_magics[lm_ptr->blue_magic_num]]; + calculate_blue_magic_success_probability(caster_ptr, lm_ptr); + learnt_info(caster_ptr, lm_ptr->comment, lm_ptr->blue_magics[lm_ptr->blue_magic_num]); + close_blue_magic_name(lm_ptr); + strcat(lm_ptr->psi_desc, format(" %-26s %3d %3d%%%s", lm_ptr->spell.name, lm_ptr->need_mana, lm_ptr->chance, lm_ptr->comment)); + prt(lm_ptr->psi_desc, lm_ptr->y + lm_ptr->blue_magic_num + 1, lm_ptr->x); + } +} + +static bool blue_magic_key_input(player_type *caster_ptr, learnt_magic_type *lm_ptr) +{ + if ((lm_ptr->choice != ' ') && (lm_ptr->choice != '*') && (lm_ptr->choice != '?') && (!use_menu || (lm_ptr->ask == 0))) + return FALSE; + + if (lm_ptr->redraw && !use_menu) { + lm_ptr->redraw = FALSE; + screen_load(); + return TRUE; + } + + lm_ptr->redraw = TRUE; + if (!use_menu) + screen_save(); + + describe_blue_magic_name(caster_ptr, lm_ptr); + if (lm_ptr->y < 22) + prt("", lm_ptr->y + lm_ptr->blue_magic_num + 1, lm_ptr->x); + + return TRUE; +} + +static void convert_lower_blue_magic_selection(learnt_magic_type *lm_ptr) +{ + if (use_menu) + return; + + lm_ptr->ask = isupper(lm_ptr->choice); + if (lm_ptr->ask) + lm_ptr->choice = (char)tolower(lm_ptr->choice); + + lm_ptr->blue_magic_num = islower(lm_ptr->choice) ? A2I(lm_ptr->choice) : -1; +} + +static bool ask_cast_blue_magic(learnt_magic_type *lm_ptr) +{ + if (lm_ptr->ask == 0) + return TRUE; + + char tmp_val[160]; + (void)strnfmt(tmp_val, 78, _("%sの魔法を唱えますか?", "Use %s? "), monster_powers[lm_ptr->blue_magics[lm_ptr->blue_magic_num]].name); + return get_check(tmp_val); +} + +static bool select_learnt_spells(player_type *caster_ptr, learnt_magic_type *lm_ptr) +{ + while (!lm_ptr->flag) { + if (lm_ptr->choice == ESCAPE) + lm_ptr->choice = ' '; + else if (!get_com(lm_ptr->out_val, &lm_ptr->choice, TRUE)) + break; + + if (use_menu && (lm_ptr->choice != ' ') && !switch_blue_magic_choice(caster_ptr, lm_ptr)) + return FALSE; + + if (blue_magic_key_input(caster_ptr, lm_ptr)) + continue; + + convert_lower_blue_magic_selection(lm_ptr); + if ((lm_ptr->blue_magic_num < 0) || (lm_ptr->blue_magic_num >= lm_ptr->count) || !caster_ptr->magic_num2[lm_ptr->blue_magics[lm_ptr->blue_magic_num]]) { + bell(); + continue; + } + + lm_ptr->spell = monster_powers[lm_ptr->blue_magics[lm_ptr->blue_magic_num]]; + if (!ask_cast_blue_magic(lm_ptr)) + continue; + + lm_ptr->flag = TRUE; + } + + return TRUE; +} + +/*! + * @brief 使用可能な青魔法を選択する / + * Allow user to choose a imitation. + * @param caster_ptr プレーヤーへの参照ポインタ + * @param sn 選択したモンスター攻撃ID、キャンセルの場合-1、不正な選択の場合-2を返す + * @return 発動可能な魔法を選択した場合TRUE、キャンセル処理か不正な選択が行われた場合FALSEを返す。 + * @details + * If a valid spell is chosen, saves it in '*sn' and returns TRUE\n + * If the user hits escape, returns FALSE, and set '*sn' to -1\n + * If there are no legal choices, returns FALSE, and sets '*sn' to -2\n + *\n + * The "prompt" should be "cast", "recite", or "study"\n + * The "known" should be TRUE for cast/pray, FALSE for study\n + *\n + * nb: This function has a (trivial) display bug which will be obvious\n + * when you run it. It's probably easy to fix but I haven't tried,\n + * sorry.\n + */ +bool get_learned_power(player_type *caster_ptr, SPELL_IDX *sn) +{ + learnt_magic_type tmp_magic; + learnt_magic_type *lm_ptr = initialize_lenat_magic_type(caster_ptr, &tmp_magic); + if (check_blue_magic_cancel(sn)) + return TRUE; + + if (!check_blue_magic_kind(lm_ptr) || !sweep_learnt_spells(caster_ptr, lm_ptr)) + return FALSE; + + if (use_menu) + screen_save(); + + lm_ptr->choice = (always_show_list || use_menu) ? ESCAPE : 1; + if (!select_learnt_spells(caster_ptr, lm_ptr)) + return FALSE; + + if (lm_ptr->redraw) + screen_load(); + + caster_ptr->window |= PW_SPELL; + handle_stuff(caster_ptr); + + if (!lm_ptr->flag) + return FALSE; + + *sn = lm_ptr->blue_magics[lm_ptr->blue_magic_num]; + repeat_push((COMMAND_CODE)lm_ptr->blue_magics[lm_ptr->blue_magic_num]); + return TRUE; +} diff --git a/src/blue-magic/learnt-power-getter.h b/src/blue-magic/learnt-power-getter.h new file mode 100644 index 000000000..4b862cf85 --- /dev/null +++ b/src/blue-magic/learnt-power-getter.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool get_learned_power(player_type *caster_ptr, SPELL_IDX *sn); diff --git a/src/chest.c b/src/chest.c deleted file mode 100644 index b2cacbab2..000000000 --- a/src/chest.c +++ /dev/null @@ -1,331 +0,0 @@ - -#include "angband.h" -#include "spells-summon.h" -#include "trap.h" -#include "player-status.h" - -/*! -* @brief 箱からアイテムを引き出す / -* Allocates objects upon opening a chest -BEN- -* @param scatter TRUEならばトラップによるアイテムの拡散処理 -* @param y 箱の存在するマスのY座標 -* @param x 箱の存在するマスのX座標 -* @param o_idx 箱のオブジェクトID -* @return なし -* @details -*
-* Disperse treasures from the given chest, centered at (x,y).
-*
-* Small chests often contain "gold", while Large chests always contain
-* items.  Wooden chests contain 2 items, Iron chests contain 4 items,
-* and Steel chests contain 6 items.  The "value" of the items in a
-* chest is based on the "power" of the chest, which is in current_world_ptr->game_turn based
-* on the level on which the chest is generated.
-* 
-*/ -void chest_death(bool scatter, POSITION y, POSITION x, OBJECT_IDX o_idx) -{ - int number; - - bool small; - BIT_FLAGS mode = AM_GOOD; - - object_type forge; - object_type *q_ptr; - - object_type *o_ptr = ¤t_floor_ptr->o_list[o_idx]; - - - /* Small chests often hold "gold" */ - small = (o_ptr->sval < SV_CHEST_MIN_LARGE); - - /* Determine how much to drop (see above) */ - number = (o_ptr->sval % SV_CHEST_MIN_LARGE) * 2; - - if (o_ptr->sval == SV_CHEST_KANDUME) - { - number = 5; - small = FALSE; - mode |= AM_GREAT; - current_floor_ptr->object_level = o_ptr->xtra3; - } - else - { - /* Determine the "value" of the items */ - current_floor_ptr->object_level = ABS(o_ptr->pval) + 10; - } - - /* Zero pval means empty chest */ - if (!o_ptr->pval) number = 0; - - /* Opening a chest */ - opening_chest = TRUE; - - /* Drop some objects (non-chests) */ - for (; number > 0; --number) - { - q_ptr = &forge; - object_wipe(q_ptr); - - /* Small chests often drop gold */ - if (small && (randint0(100) < 25)) - { - /* Make some gold */ - if (!make_gold(q_ptr)) continue; - } - - /* Otherwise drop an item */ - else - { - /* Make a good object */ - if (!make_object(q_ptr, mode)) continue; - } - - /* If chest scatters its contents, pick any floor square. */ - if (scatter) - { - int i; - for (i = 0; i < 200; i++) - { - /* Pick a totally random spot. */ - y = randint0(MAX_HGT); - x = randint0(MAX_WID); - - /* Must be an empty floor. */ - if (!cave_empty_bold(y, x)) continue; - - /* Place the object there. */ - (void)drop_near(q_ptr, -1, y, x); - - /* Done. */ - break; - } - } - /* Normally, drop object near the chest. */ - else (void)drop_near(q_ptr, -1, y, x); - } - - /* Reset the object level */ - current_floor_ptr->object_level = current_floor_ptr->base_level; - - /* No longer opening a chest */ - opening_chest = FALSE; - - /* Empty */ - o_ptr->pval = 0; - - /* Known */ - object_known(o_ptr); -} - - -/*! -* @brief 箱のトラップ処理 / -* Chests have traps too. -* @param y 箱の存在するマスのY座標 -* @param x 箱の存在するマスのX座標 -* @param o_idx 箱のオブジェクトID -* @return なし -* @details -*
-* Exploding chest destroys contents (and traps).
-* Note that the chest itself is never destroyed.
-* 
-*/ -void chest_trap(POSITION y, POSITION x, OBJECT_IDX o_idx) -{ - int i, trap; - - object_type *o_ptr = ¤t_floor_ptr->o_list[o_idx]; - - int mon_level = o_ptr->xtra3; - - /* Ignore disarmed chests */ - if (o_ptr->pval <= 0) return; - - /* Obtain the traps */ - trap = chest_traps[o_ptr->pval]; - - /* Lose strength */ - if (trap & (CHEST_LOSE_STR)) - { - msg_print(_("仕掛けられていた小さな針に刺されてしまった!", "A small needle has pricked you!")); - take_hit(DAMAGE_NOESCAPE, damroll(1, 4), _("毒針", "a poison needle"), -1); - (void)do_dec_stat(A_STR); - } - - /* Lose constitution */ - if (trap & (CHEST_LOSE_CON)) - { - msg_print(_("仕掛けられていた小さな針に刺されてしまった!", "A small needle has pricked you!")); - take_hit(DAMAGE_NOESCAPE, damroll(1, 4), _("毒針", "a poison needle"), -1); - (void)do_dec_stat(A_CON); - } - - /* Poison */ - if (trap & (CHEST_POISON)) - { - msg_print(_("突如吹き出した緑色のガスに包み込まれた!", "A puff of green gas surrounds you!")); - if (!(p_ptr->resist_pois || IS_OPPOSE_POIS())) - { - (void)set_poisoned(p_ptr->poisoned + 10 + randint1(20)); - } - } - - /* Paralyze */ - if (trap & (CHEST_PARALYZE)) - { - msg_print(_("突如吹き出した黄色いガスに包み込まれた!", "A puff of yellow gas surrounds you!")); - if (!p_ptr->free_act) - { - (void)set_paralyzed(p_ptr->paralyzed + 10 + randint1(20)); - } - } - - /* Summon monsters */ - if (trap & (CHEST_SUMMON)) - { - int num = 2 + randint1(3); - msg_print(_("突如吹き出した煙に包み込まれた!", "You are enveloped in a cloud of smoke!")); - for (i = 0; i < num; i++) - { - if (randint1(100)dun_level) - activate_hi_summon(p_ptr->y, p_ptr->x, FALSE); - else - (void)summon_specific(0, y, x, mon_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'); - } - } - - /* Elemental summon. */ - if (trap & (CHEST_E_SUMMON)) - { - msg_print(_("宝を守るためにエレメンタルが現れた!", "Elemental beings appear to protect their treasures!")); - for (i = 0; i < randint1(3) + 5; i++) - { - (void)summon_specific(0, y, x, mon_level, SUMMON_ELEMENTAL, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'); - } - } - - /* Force clouds, then summon birds. */ - if (trap & (CHEST_BIRD_STORM)) - { - msg_print(_("鳥の群れがあなたを取り巻いた!", "A storm of birds swirls around you!")); - - for (i = 0; i < randint1(3) + 3; i++) - (void)fire_meteor(-1, GF_FORCE, y, x, o_ptr->pval / 5, 7); - - for (i = 0; i < randint1(5) + o_ptr->pval / 5; i++) - { - (void)summon_specific(0, y, x, mon_level, SUMMON_BIRD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'); - } - } - - /* Various colorful summonings. */ - if (trap & (CHEST_H_SUMMON)) - { - /* Summon demons. */ - if (one_in_(4)) - { - msg_print(_("炎と硫黄の雲の中に悪魔が姿を現した!", "Demons materialize in clouds of fire and brimstone!")); - for (i = 0; i < randint1(3) + 2; i++) - { - (void)fire_meteor(-1, GF_FIRE, y, x, 10, 5); - (void)summon_specific(0, y, x, mon_level, SUMMON_DEMON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'); - } - } - - /* Summon dragons. */ - else if (one_in_(3)) - { - msg_print(_("暗闇にドラゴンの影がぼんやりと現れた!", "Draconic forms loom out of the darkness!")); - for (i = 0; i < randint1(3) + 2; i++) - { - (void)summon_specific(0, y, x, mon_level, SUMMON_DRAGON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'); - } - } - - /* Summon hybrids. */ - else if (one_in_(2)) - { - msg_print(_("奇妙な姿の怪物が襲って来た!", "Creatures strange and twisted assault you!")); - for (i = 0; i < randint1(5) + 3; i++) - { - (void)summon_specific(0, y, x, mon_level, SUMMON_HYBRID, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'); - } - } - - /* Summon vortices (scattered) */ - else - { - msg_print(_("渦巻が合体し、破裂した!", "Vortices coalesce and wreak destruction!")); - for (i = 0; i < randint1(3) + 2; i++) - { - (void)summon_specific(0, y, x, mon_level, SUMMON_VORTEX, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'); - } - } - } - - /* Dispel player. */ - if ((trap & (CHEST_RUNES_OF_EVIL)) && o_ptr->k_idx) - { - /* Determine how many nasty tricks can be played. */ - int nasty_tricks_count = 4 + randint0(3); - - msg_print(_("恐ろしい声が響いた: 「暗闇が汝をつつまん!」", "Hideous voices bid: 'Let the darkness have thee!'")); - /* This is gonna hurt... */ - for (; nasty_tricks_count > 0; nasty_tricks_count--) - { - /* ...but a high saving throw does help a little. */ - if (randint1(100 + o_ptr->pval * 2) > p_ptr->skill_sav) - { - if (one_in_(6)) take_hit(DAMAGE_NOESCAPE, damroll(5, 20), _("破滅のトラップの宝箱", "a chest dispel-player trap"), -1); - else if (one_in_(5)) (void)set_cut(p_ptr->cut + 200); - else if (one_in_(4)) - { - if (!p_ptr->free_act) - (void)set_paralyzed(p_ptr->paralyzed + 2 + - randint0(6)); - else - (void)set_stun(p_ptr->stun + 10 + - randint0(100)); - } - else if (one_in_(3)) apply_disenchant(0); - else if (one_in_(2)) - { - (void)do_dec_stat(A_STR); - (void)do_dec_stat(A_DEX); - (void)do_dec_stat(A_CON); - (void)do_dec_stat(A_INT); - (void)do_dec_stat(A_WIS); - (void)do_dec_stat(A_CHR); - } - else (void)fire_meteor(-1, GF_NETHER, y, x, 150, 1); - } - } - } - - /* Aggravate monsters. */ - if (trap & (CHEST_ALARM)) - { - msg_print(_("けたたましい音が鳴り響いた!", "An alarm sounds!")); - aggravate_monsters(0); - } - - /* Explode */ - if ((trap & (CHEST_EXPLODE)) && o_ptr->k_idx) - { - msg_print(_("突然、箱が爆発した!", "There is a sudden explosion!")); - msg_print(_("箱の中の物はすべて粉々に砕け散った!", "Everything inside the chest is destroyed!")); - o_ptr->pval = 0; - sound(SOUND_EXPLODE); - take_hit(DAMAGE_ATTACK, damroll(5, 8), _("爆発する箱", "an exploding chest"), -1); - } - /* Scatter contents. */ - if ((trap & (CHEST_SCATTER)) && o_ptr->k_idx) - { - msg_print(_("宝箱の中身はダンジョンじゅうに散乱した!", "The contents of the chest scatter all over the dungeon!")); - chest_death(TRUE, y, x, o_idx); - o_ptr->pval = 0; - } -} - diff --git a/src/chest.h b/src/chest.h deleted file mode 100644 index 99b171f56..000000000 --- a/src/chest.h +++ /dev/null @@ -1,4 +0,0 @@ - -extern void chest_death(bool scatter, POSITION y, POSITION x, OBJECT_IDX o_idx); -extern void chest_trap(POSITION y, POSITION x, OBJECT_IDX o_idx); - diff --git a/src/chuukei.c b/src/chuukei.c deleted file mode 100644 index 840e0383b..000000000 --- a/src/chuukei.c +++ /dev/null @@ -1,1128 +0,0 @@ -/*! - @file chuukei.c - @brief 中継機能の実装 - @date 2014/01/02 - @author - 2014 Deskull rearranged comment for Doxygen. - */ - -#include "angband.h" - -#include -#include -#include -#ifdef WINDOWS -#include -#endif - -#ifdef CHUUKEI -#if defined(WINDOWS) -#include -#elif defined(MACINTOSH) -#include -#include -#else -#include -#include -#include -#include -#include -#include - -#include -#include -#endif - -#define MAX_HOSTNAME 256 -#endif - -#define RINGBUF_SIZE 1024*1024 -#define FRESH_QUEUE_SIZE 4096 -#ifdef WINDOWS -#define WAIT 100 -#else -#define WAIT 100*1000 /* ブラウズ側のウエイト(us単位) */ -#endif -#define DEFAULT_DELAY 50 -#define RECVBUF_SIZE 1024 - -static long epoch_time; /* バッファ開始時刻 */ -static int browse_delay; /* 表示するまでの時間(100ms単位)(この間にラグを吸収する) */ -#ifdef CHUUKEI -static int sd; /* ソケットのファイルディスクリプタ */ -static long time_diff; /* プレイ側との時間のずれ(これを見ながらディレイを調整していく) */ -static int server_port; -static GAME_TEXT server_name[MAX_HOSTNAME]; -#endif - -static int movie_fd; -static int movie_mode; - -#ifdef CHUUKEI -#ifdef WINDOWS -#define close closesocket -#endif - -#ifdef MACINTOSH -static InetSvcRef inet_services = nil; -static EndpointRef ep = kOTInvalidEndpointRef; -#endif -#endif -/* 描画する時刻を覚えておくキュー構造体 */ -static struct -{ - int time[FRESH_QUEUE_SIZE]; - int next; - int tail; -}fresh_queue; - - -/* リングバッファ構造体 */ -static struct -{ - char *buf; - int wptr; - int rptr; - int inlen; -}ring; - -#ifdef MACINTOSH -int recv(int s, char *buffer, size_t buflen, int flags) -{ - OTFlags junkFlags; - int n = OTRcv(ep, (void *) buffer, buflen, &junkFlags); - if( n <= 0 ) - return n; - return n; -} -#endif - -/* - * Original hooks - */ -static errr (*old_xtra_hook)(int n, int v); -static errr (*old_curs_hook)(int x, int y); -static errr (*old_bigcurs_hook)(int x, int y); -static errr (*old_wipe_hook)(int x, int y, int n); -static errr (*old_text_hook)(int x, int y, int n, TERM_COLOR a, concptr s); - -static void disable_chuukei_server(void) -{ - term *t = angband_term[0]; -#ifdef CHUUKEI - chuukei_server = FALSE; -#endif /* CHUUKEI */ - t->xtra_hook = old_xtra_hook; - t->curs_hook = old_curs_hook; - t->bigcurs_hook = old_bigcurs_hook; - t->wipe_hook = old_wipe_hook; - t->text_hook = old_text_hook; -} - -/* ANSI Cによればstatic変数は0で初期化されるが一応初期化する */ -static errr init_buffer(void) -{ - fresh_queue.next = fresh_queue.tail = 0; - ring.wptr = ring.rptr = ring.inlen = 0; - fresh_queue.time[0] = 0; - ring.buf = malloc(RINGBUF_SIZE); - if (ring.buf == NULL) return (-1); - - return (0); -} - -/* 現在の時間を100ms単位で取得する */ -static long get_current_time(void) -{ -#ifdef WINDOWS - return timeGetTime() / 100; -#elif defined(MACINTOSH) - return TickCount(); -#else - struct timeval tv; - gettimeofday(&tv, NULL); - - return (tv.tv_sec * 10 + tv.tv_usec / 100000); -#endif -} - - -/* リングバッファ構造体に buf の内容を加える */ -static errr insert_ringbuf(char *buf) -{ - int len; - len = strlen(buf) + 1; /* +1は終端文字分 */ - - if (movie_mode) - { - fd_write(movie_fd, buf, len); -#ifdef CHUUKEI - if (!chuukei_server) return 0; -#else - return 0; -#endif - } - - /* バッファをオーバー */ - if (ring.inlen + len >= RINGBUF_SIZE) - { -#ifdef CHUUKEI - if (chuukei_server) disable_chuukei_server(); - else chuukei_client = FALSE; - - prt("送受信バッファが溢れました。サーバとの接続を切断します。", 0, 0); - inkey(); - - close(sd); -#endif - return (-1); - } - - /* バッファの終端までに収まる */ - if (ring.wptr + len < RINGBUF_SIZE) - { - memcpy(ring.buf + ring.wptr, buf, len); - ring.wptr += len; - } - /* バッファの終端までに収まらない(ピッタリ収まる場合も含む) */ - else - { - int head = RINGBUF_SIZE - ring.wptr; /* 前半 */ - int tail = len - head; /* 後半 */ - - memcpy(ring.buf + ring.wptr, buf, head); - memcpy(ring.buf, buf + head, tail); - ring.wptr = tail; - } - - ring.inlen += len; - - /* Success */ - return (0); -} - -#ifdef CHUUKEI -void flush_ringbuf(void) -{ -#ifndef MACINTOSH - fd_set fdset; - struct timeval tv; - - if (!chuukei_server) return; - - if (ring.inlen == 0) return; - - tv.tv_sec = 0; - tv.tv_usec = 0; - - FD_ZERO(&fdset); - FD_SET(sd, &fdset); - - while (1) - { - fd_set tmp_fdset; - int result; - - tmp_fdset = fdset; - - /* ソケットにデータを書き込めるかどうか調べる */ - select(sd+1, (fd_set *)NULL, &tmp_fdset, (fd_set *)NULL, &tv); - - /* 書き込めなければ戻る */ - if (FD_ISSET(sd, &tmp_fdset) == 0) break; - - result = send(sd, ring.buf + ring.rptr, ((ring.wptr > ring.rptr ) ? ring.wptr : RINGBUF_SIZE) - ring.rptr, 0); - - if (result <= 0) - { - /* サーバとの接続断? */ - if (chuukei_server) disable_chuukei_server(); - - prt("サーバとの接続が切断されました。", 0, 0); - inkey(); - close(sd); - - return; - } - - ring.rptr += result; - ring.inlen -= result; - - if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0; - if (ring.inlen == 0) break; - } -#else - if (!chuukei_server) return; - - if (ring.inlen == 0) return; - - while (1) - { - int result; - - /* ソケットにデータを書き込めるかどうか調べる */ - result = OTSnd(ep, ring.buf + ring.rptr, ((ring.wptr > ring.rptr ) ? ring.wptr : RINGBUF_SIZE) - ring.rptr, 0); - - if (result <= 0) - { - /* サーバとの接続断? */ - if (chuukei_server) disable_chuukei_server(); - - prt("サーバとの接続が切断されました。", 0, 0); - inkey(); - close(sd); - - return; - } - - ring.rptr += result; - ring.inlen -= result; - - if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0; - if (ring.inlen == 0) break; - } -#endif -} - - -static int read_chuukei_prf(concptr prf_name) -{ - char buf[1024]; - FILE *fp; - - path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA, prf_name); - fp = my_fopen(buf, "r"); - - if (!fp) return (-1); - - /* 初期化 */ - server_port = -1; - server_name[0] = 0; - browse_delay = DEFAULT_DELAY; - - while (0 == my_fgets(fp, buf, sizeof(buf))) - { - /* サーバ名 */ - if (!strncmp(buf, "server:", 7)) - { - strncpy(server_name, buf + 7, MAX_HOSTNAME - 1); - server_name[MAX_HOSTNAME - 1] = '\0'; - } - - /* ポート番号 */ - if (!strncmp(buf, "port:", 5)) - { - server_port = atoi(buf + 5); - } - - /* ディレイ */ - if (!strncmp(buf, "delay:", 6)) - { - browse_delay = atoi(buf + 6); - } - } - - my_fclose(fp); - - /* prfファイルが完全でない */ - if (server_port == -1 || server_name[0] == 0) return (-1); - - return (0); -} - -int connect_chuukei_server(char *prf_name) -{ -#ifndef MACINTOSH - -#ifdef WINDOWS - WSADATA wsaData; - WORD wVersionRequested = (WORD) (( 1) | ( 1 << 8)); -#endif - - struct sockaddr_in ask; - struct hostent *hp; - - if (read_chuukei_prf(prf_name) < 0) - { - printf("Wrong prf file\n"); - return (-1); - } - - if (init_buffer() < 0) - { - printf("Malloc error\n"); - return (-1); - } - -#ifdef WINDOWS - if (WSAStartup(wVersionRequested, &wsaData)) - { - msg_print("Report: WSAStartup failed."); - return (-1); - } -#endif - - printf("server = %s\nport = %d\n", server_name, server_port); - - if ((hp = gethostbyname(server_name)) != NULL) - { - memset(&ask, 0, sizeof(ask)); - memcpy(&ask.sin_addr, hp->h_addr_list[0], hp->h_length); - } - else - { - if ((ask.sin_addr.s_addr=inet_addr(server_name)) == 0) - { - printf("Bad hostname\n"); - return (-1); - } - } - - ask.sin_family = AF_INET; - ask.sin_port = htons((unsigned short)server_port); - -#ifndef WINDOWS - if ((sd=socket(PF_INET,SOCK_STREAM, 0)) < 0) -#else - if ((sd=socket(PF_INET,SOCK_STREAM, 0)) == INVALID_SOCKET) -#endif - { - printf("Can't create socket\n"); - return (-1); - } - - if (connect(sd, (struct sockaddr *)&ask, sizeof(ask)) < 0) - { - close(sd); - printf("Can't connect %s port %d\n", server_name, server_port); - return (-1); - } - - return (0); -#else /* MACINTOSH */ - OSStatus err; - InetHostInfo response; - InetHost host_addr; - InetAddress inAddr; - TCall sndCall; - Boolean bind = false; - OSStatus junk; - - if (read_chuukei_prf(prf_name) < 0){ - printf("Wrong prf file\n"); - return (-1); - } - - init_buffer(); - - printf("server = %s\nport = %d\n", server_name, server_port); - - -#if TARGET_API_MAC_CARBON - err = InitOpenTransportInContext(kInitOTForApplicationMask, NULL); -#else - err = InitOpenTransport(); -#endif - - memset(&response, 0, sizeof(response)); - - -#if TARGET_API_MAC_CARBON - inet_services = OTOpenInternetServicesInContext(kDefaultInternetServicesPath, 0, &err, NULL); -#else - inet_services = OTOpenInternetServices(kDefaultInternetServicesPath, 0, &err); -#endif - - if (err == noErr) { - err = OTInetStringToAddress(inet_services, (char *)server_name, &response); - - if (err == noErr) { - host_addr = response.addrs[0]; - } else { - printf("Bad hostname\n"); - } - -#if TARGET_API_MAC_CARBON - ep = (void *)OTOpenEndpointInContext(OTCreateConfiguration(kTCPName), 0, nil, &err, NULL); -#else - ep = (void *)OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, nil, &err); -#endif - - if (err == noErr) { - err = OTBind(ep, nil, nil); - bind = (err == noErr); - } - if (err == noErr){ - OTInitInetAddress(&inAddr, server_port, host_addr); - - sndCall.addr.len = sizeof(InetAddress); - sndCall.addr.buf = (unsigned char*) &inAddr; - sndCall.opt.buf = nil; /* no connection options */ - sndCall.opt.len = 0; - sndCall.udata.buf = nil; /* no connection data */ - sndCall.udata.len = 0; - sndCall.sequence = 0; /* ignored by OTConnect */ - - err = OTConnect(ep, &sndCall, NULL); - - if( err != noErr ){ - printf("Can't connect %s port %d\n", server_name, server_port); - } - } - - err = OTSetSynchronous(ep); - if (err == noErr) - err = OTSetBlocking(ep); - - } - - if( err != noErr ){ - if( bind ){ - OTUnbind(ep); - } - /* Clean up. */ - if (ep != kOTInvalidEndpointRef) { - OTCloseProvider(ep); - ep = nil; - } - if (inet_services != nil) { - OTCloseProvider(inet_services); - inet_services = nil; - } - - return -1; - } - - return 0; - -#endif -} -#endif /* CHUUKEI */ - -/* strが同じ文字の繰り返しかどうか調べる */ -static bool string_is_repeat(char *str, int len) -{ - char c = str[0]; - int i; - - if (len < 2) return (FALSE); -#ifdef JP - if (iskanji(c)) return (FALSE); -#endif - - for (i = 1; i < len; i++) - { -#ifdef JP - if(c != str[i] || iskanji(str[i])) return (FALSE); -#else - if(c != str[i]) return (FALSE); -#endif - } - - return (TRUE); -} - -static errr send_text_to_chuukei_server(TERM_LEN x, TERM_LEN y, int len, TERM_COLOR col, concptr str) -{ - char buf[1024]; - char buf2[1024]; - - strncpy(buf2, str, len); - buf2[len] = '\0'; - - if (len == 1) - { - sprintf(buf, "s%c%c%c%c", x+1, y+1, col, buf2[0]); - } - else if(string_is_repeat(buf2, len)) - { - int i; - for (i = len; i > 0; i -= 127) - { - sprintf(buf, "n%c%c%c%c%c", x+1, y+1, MIN(i, 127), col, buf2[0]); - } - } - else - { -#if defined(SJIS) && defined(JP) - sjis2euc(buf2); -#endif - sprintf(buf, "t%c%c%c%c%s", x+1, y+1, len, col, buf2); - } - - insert_ringbuf(buf); - - return (*old_text_hook)(x, y, len, col, str); -} - -static errr send_wipe_to_chuukei_server(int x, int y, int len) -{ - char buf[1024]; - - sprintf(buf, "w%c%c%c", x+1, y+1, len); - - insert_ringbuf(buf); - - return (*old_wipe_hook)(x, y, len); -} - -static errr send_xtra_to_chuukei_server(int n, int v) -{ - char buf[1024]; - - if (n == TERM_XTRA_CLEAR || n == TERM_XTRA_FRESH || n == TERM_XTRA_SHAPE) - { - sprintf(buf, "x%c", n+1); - - insert_ringbuf(buf); - - if (n == TERM_XTRA_FRESH) - { - sprintf(buf, "d%ld", get_current_time() - epoch_time); - insert_ringbuf(buf); - } - } - - /* Verify the hook */ - if (!old_xtra_hook) return -1; - - return (*old_xtra_hook)(n, v); -} - -static errr send_curs_to_chuukei_server(int x, int y) -{ - char buf[1024]; - - sprintf(buf, "c%c%c", x+1, y+1); - - insert_ringbuf(buf); - - return (*old_curs_hook)(x, y); -} - -static errr send_bigcurs_to_chuukei_server(int x, int y) -{ - char buf[1024]; - - sprintf(buf, "C%c%c", x+1, y+1); - - insert_ringbuf(buf); - - return (*old_bigcurs_hook)(x, y); -} - - -/* - * Prepare z-term hooks to call send_*_to_chuukei_server()'s - */ -void prepare_chuukei_hooks(void) -{ - term *t0 = angband_term[0]; - - /* Save original z-term hooks */ - old_xtra_hook = t0->xtra_hook; - old_curs_hook = t0->curs_hook; - old_bigcurs_hook = t0->bigcurs_hook; - old_wipe_hook = t0->wipe_hook; - old_text_hook = t0->text_hook; - - /* Prepare z-term hooks */ - t0->xtra_hook = send_xtra_to_chuukei_server; - t0->curs_hook = send_curs_to_chuukei_server; - t0->bigcurs_hook = send_bigcurs_to_chuukei_server; - t0->wipe_hook = send_wipe_to_chuukei_server; - t0->text_hook = send_text_to_chuukei_server; -} - - -/* - * Prepare z-term hooks to call send_*_to_chuukei_server()'s - */ -void prepare_movie_hooks(void) -{ - char buf[1024]; - char tmp[80]; - - if (movie_mode) - { - movie_mode = 0; -#ifdef CHUUKEI - if (!chuukei_server) disable_chuukei_server(); -#else - disable_chuukei_server(); -#endif - fd_close(movie_fd); - msg_print(_("録画を終了しました。", "Stopped recording.")); - } - else - { - sprintf(tmp, "%s.amv", player_base); - if (get_string(_("ムービー記録ファイル: ", "Movie file name: "), tmp, 80)) - { - int fd; - - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp); - - fd = fd_open(buf, O_RDONLY); - - /* Existing file */ - if (fd >= 0) - { - char out_val[160]; - (void)fd_close(fd); - - /* Build query */ - (void)sprintf(out_val, _("現存するファイルに上書きしますか? (%s)", "Replace existing file %s? "), buf); - - /* Ask */ - if (!get_check(out_val)) return; - - movie_fd = fd_open(buf, O_WRONLY | O_TRUNC); - } - else - { - movie_fd = fd_make(buf, 0644); - } - - if (!movie_fd) - { - msg_print(_("ファイルを開けません!", "Can not open file.")); - return; - } - - movie_mode = 1; -#ifdef CHUUKEI - if (!chuukei_server) prepare_chuukei_hooks(); -#else - prepare_chuukei_hooks(); -#endif - do_cmd_redraw(); - } - } -} - -#ifdef CHUUKEI -static int handle_timestamp_data(int timestamp) -{ - long current_time = get_current_time(); - - /* 描画キューは空かどうか? */ - if (fresh_queue.tail == fresh_queue.next) - { - /* バッファリングし始めの時間を保存しておく */ - epoch_time = current_time; - epoch_time += browse_delay; - epoch_time -= timestamp; - time_diff = current_time - timestamp; - } - - /* 描画キューに保存し、保存位置を進める */ - fresh_queue.time[fresh_queue.tail] = timestamp; - fresh_queue.tail ++; - - /* キューの最後尾に到達したら先頭に戻す */ - fresh_queue.tail %= FRESH_QUEUE_SIZE; - - if (fresh_queue.tail == fresh_queue.next) - { - /* 描画キュー溢れ */ - prt("描画タイミングキューが溢れました。サーバとの接続を切断します。", 0, 0); - inkey(); - close(sd); - - return -1; - } - - /* プレイ側とのディレイを調整 */ - if (time_diff != current_time - timestamp) - { - long old_time_diff = time_diff; - time_diff = current_time - timestamp; - epoch_time -= (old_time_diff - time_diff); - } - - /* Success */ - return 0; -} -#endif /* CHUUKEI */ - -static int handle_movie_timestamp_data(int timestamp) -{ - static int initialized = FALSE; - - /* 描画キューは空かどうか? */ - if (!initialized) - { - /* バッファリングし始めの時間を保存しておく */ - epoch_time = get_current_time(); - epoch_time += browse_delay; - epoch_time -= timestamp; - //time_diff = current_time - timestamp; - initialized = TRUE; - } - - /* 描画キューに保存し、保存位置を進める */ - fresh_queue.time[fresh_queue.tail] = timestamp; - fresh_queue.tail ++; - - /* キューの最後尾に到達したら先頭に戻す */ - fresh_queue.tail %= FRESH_QUEUE_SIZE; - - /* Success */ - return 0; -} - -#ifdef CHUUKEI -static int read_sock(void) -{ - static char recv_buf[RECVBUF_SIZE]; - static int remain_bytes = 0; - int recv_bytes; - int i; - - /* 前回残ったデータの後につづけて配信サーバからデータ受信 */ - recv_bytes = recv(sd, recv_buf + remain_bytes, RECVBUF_SIZE - remain_bytes, 0); - - if (recv_bytes <= 0) - return -1; - - /* 前回残ったデータ量に今回読んだデータ量を追加 */ - remain_bytes += recv_bytes; - - for (i = 0; i < remain_bytes; i ++) - { - /* データのくぎり('\0')を探す */ - if (recv_buf[i] == '\0') - { - /* 'd'で始まるデータ(タイムスタンプ)の場合は - 描画キューに保存する処理を呼ぶ */ - if ((recv_buf[0] == 'd') && - (handle_timestamp_data(atoi(recv_buf + 1)) < 0)) - return -1; - - /* 受信データを保存 */ - if (insert_ringbuf(recv_buf) < 0) - return -1; - - /* 次のデータ移行をrecv_bufの先頭に移動 */ - memmove(recv_buf, recv_buf + i + 1, remain_bytes - i - 1); - - remain_bytes -= (i+1); - i = 0; - } - } - - return 0; -} -#endif - -static int read_movie_file(void) -{ - static char recv_buf[RECVBUF_SIZE]; - static int remain_bytes = 0; - int recv_bytes; - int i; - - recv_bytes = read(movie_fd, recv_buf + remain_bytes, RECVBUF_SIZE - remain_bytes); - - if (recv_bytes <= 0) - return -1; - - /* 前回残ったデータ量に今回読んだデータ量を追加 */ - remain_bytes += recv_bytes; - - for (i = 0; i < remain_bytes; i ++) - { - /* データのくぎり('\0')を探す */ - if (recv_buf[i] == '\0') - { - /* 'd'で始まるデータ(タイムスタンプ)の場合は - 描画キューに保存する処理を呼ぶ */ - if ((recv_buf[0] == 'd') && - (handle_movie_timestamp_data(atoi(recv_buf + 1)) < 0)) - return -1; - - /* 受信データを保存 */ - if (insert_ringbuf(recv_buf) < 0) - return -1; - - /* 次のデータ移行をrecv_bufの先頭に移動 */ - memmove(recv_buf, recv_buf + i + 1, remain_bytes - i - 1); - - remain_bytes -= (i+1); - i = 0; - } - } - - return 0; -} - - -#ifndef WINDOWS -/* Win版の床の中点と壁の豆腐をピリオドとシャープにする。*/ -static void win2unix(int col, char *buf) -{ - char kabe; - if ( col == 9 ) kabe = '%'; - else kabe = '#'; - - while (*buf) - { -#ifdef JP - if (iskanji(*buf)) - { - buf += 2; - continue; - } -#endif - if (*buf == 127) *buf = kabe; - else if(*buf == 31) *buf = '.'; - buf++; - } -} -#endif - -static bool get_nextbuf(char *buf) -{ - char *ptr = buf; - - while (1) - { - *ptr = ring.buf[ring.rptr ++]; - ring.inlen --; - if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0; - if (*ptr++ == '\0') break; - } - - if (buf[0] == 'd') return (FALSE); - - return (TRUE); -} - -/* プレイホストのマップが大きいときクライアントのマップもリサイズする */ -static void update_term_size(int x, int y, int len) -{ - int ox, oy; - int nx, ny; - Term_get_size(&ox, &oy); - nx = ox; - ny = oy; - - /* 横方向のチェック */ - if (x + len > ox) nx = x + len; - /* 縦方向のチェック */ - if (y + 1 > oy) ny = y + 1; - - if (nx != ox || ny != oy) Term_resize(nx, ny); -} - -static bool flush_ringbuf_client(void) -{ - char buf[1024]; - - /* 書くデータなし */ - if (fresh_queue.next == fresh_queue.tail) return (FALSE); - - /* まだ書くべき時でない */ - if (fresh_queue.time[fresh_queue.next] > get_current_time() - epoch_time) return (FALSE); - - /* 時間情報(区切り)が得られるまで書く */ - while (get_nextbuf(buf)) - { - char id; - int x, y, len; - TERM_COLOR col; - int i; - unsigned char tmp1, tmp2, tmp3, tmp4; - char *mesg; - - sscanf(buf, "%c%c%c%c%c", &id, &tmp1, &tmp2, &tmp3, &tmp4); - x = tmp1-1; y = tmp2-1; len = tmp3; col = tmp4; - if (id == 's') - { - col = tmp3; - mesg = &buf[4]; - } - else mesg = &buf[5]; -#ifndef WINDOWS - win2unix(col, mesg); -#endif - - switch (id) - { - case 't': /* 通常 */ -#if defined(SJIS) && defined(JP) - euc2sjis(mesg); -#endif - update_term_size(x, y, len); - (void)((*angband_term[0]->text_hook)(x, y, len, (byte)col, mesg)); - strncpy(&Term->scr->c[y][x], mesg, len); - for (i = x; i < x+len; i++) - { - Term->scr->a[y][i] = col; - } - break; - - case 'n': /* 繰り返し */ - for (i = 1; i < len; i++) - { - mesg[i] = mesg[0]; - } - mesg[i] = '\0'; - update_term_size(x, y, len); - (void)((*angband_term[0]->text_hook)(x, y, len, (byte)col, mesg)); - strncpy(&Term->scr->c[y][x], mesg, len); - for (i = x; i < x+len; i++) - { - Term->scr->a[y][i] = col; - } - break; - - case 's': /* 一文字 */ - update_term_size(x, y, 1); - (void)((*angband_term[0]->text_hook)(x, y, 1, (byte)col, mesg)); - strncpy(&Term->scr->c[y][x], mesg, 1); - Term->scr->a[y][x] = col; - break; - - case 'w': - update_term_size(x, y, len); - (void)((*angband_term[0]->wipe_hook)(x, y, len)); - break; - - case 'x': - if (x == TERM_XTRA_CLEAR) Term_clear(); - (void)((*angband_term[0]->xtra_hook)(x, 0)); - break; - - case 'c': - update_term_size(x, y, 1); - (void)((*angband_term[0]->curs_hook)(x, y)); - break; - case 'C': - update_term_size(x, y, 1); - (void)((*angband_term[0]->bigcurs_hook)(x, y)); - break; - } - } - - fresh_queue.next++; - if (fresh_queue.next == FRESH_QUEUE_SIZE) fresh_queue.next = 0; - return (TRUE); -} - -#ifdef CHUUKEI -void browse_chuukei() -{ -#ifndef MACINTOSH - fd_set fdset; - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = WAIT; - - FD_ZERO(&fdset); - FD_SET(sd, &fdset); - - Term_clear(); - Term_fresh(); - Term_xtra(TERM_XTRA_REACT, 0); - - while (1) - { - fd_set tmp_fdset; - struct timeval tmp_tv; - - if (flush_ringbuf_client()) continue; - - tmp_fdset = fdset; - tmp_tv = tv; - - /* ソケットにデータが来ているかどうか調べる */ - select(sd+1, &tmp_fdset, (fd_set *)NULL, (fd_set *)NULL, &tmp_tv); - if (FD_ISSET(sd, &tmp_fdset) == 0) - { - Term_xtra(TERM_XTRA_FLUSH, 0); - continue; - } - - if (read_sock() < 0) - { - chuukei_client = FALSE; - } - - /* 接続が切れた状態で書くべきデータがなくなっていたら終了 */ - if (!chuukei_client && fresh_queue.next == fresh_queue.tail ) break; - } -#else - Term_clear(); - Term_fresh(); - Term_xtra(TERM_XTRA_REACT, 0); - - while (1) - { - UInt32 unreadData = 0; - int n; - - if (flush_ringbuf_client()) continue; - - /* ソケットにデータが来ているかどうか調べる */ - - OTCountDataBytes(ep, &unreadData); - if(unreadData <= 0 ){ - Term_xtra(TERM_XTRA_FLUSH, 0); - continue; - } - if (read_sock() < 0) - { - chuukei_client = FALSE; - } - - /* 接続が切れた状態で書くべきデータがなくなっていたら終了 */ - if (!chuukei_client && fresh_queue.next == fresh_queue.tail ) break; - } -#endif /*MACINTOSH*/ -} -#endif /* CHUUKEI */ - -void prepare_browse_movie_aux(concptr filename) -{ - movie_fd = fd_open(filename, O_RDONLY); - - browsing_movie = TRUE; - - init_buffer(); -} - -void prepare_browse_movie(concptr filename) -{ - char buf[1024]; - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename); - - prepare_browse_movie_aux(buf); -} - -void browse_movie(void) -{ - Term_clear(); - Term_fresh(); - Term_xtra(TERM_XTRA_REACT, 0); - - while (read_movie_file() == 0) - { - while (fresh_queue.next != fresh_queue.tail) - { - if (!flush_ringbuf_client()) - { - Term_xtra(TERM_XTRA_FLUSH, 0); - - /* ソケットにデータが来ているかどうか調べる */ -#ifdef WINDOWS - Sleep(WAIT); -#else - usleep(WAIT); -#endif - } - } - } -} diff --git a/src/cmd-action/cmd-attack.c b/src/cmd-action/cmd-attack.c new file mode 100644 index 000000000..7c50e8ded --- /dev/null +++ b/src/cmd-action/cmd-attack.c @@ -0,0 +1,312 @@ +/*! + * @brief 攻撃コマンド処理 + * @date 2020/05/23 + * @author Hourier + */ + +#include "cmd-action/cmd-attack.h" +#include "art-definition/art-sword-types.h" +#include "combat/attack-accuracy.h" +#include "combat/attack-criticality.h" +#include "core/asking-player.h" +#include "core/disturbance.h" +#include "core/player-update-types.h" +#include "core/stuff-handler.h" +#include "dungeon/dungeon-flag-types.h" +#include "dungeon/dungeon.h" +#include "effect/effect-characteristics.h" +#include "effect/effect-processor.h" +#include "game-option/cheat-types.h" +#include "inventory/inventory-slot-types.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags2.h" +#include "monster-race/race-flags3.h" +#include "monster/monster-describer.h" +#include "monster/monster-info.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "mutation/mutation-flag-types.h" +#include "object/item-use-flags.h" +#include "player-attack/player-attack.h" +#include "player/attack-defense-types.h" +#include "player-info/avatar.h" +#include "player/player-damage.h" +#include "player/player-skill.h" +#include "player/player-status-flags.h" +#include "player/special-defense-types.h" +#include "spell/spell-types.h" +#include "status/action-setter.h" +#include "system/floor-type-definition.h" +#include "view/display-messages.h" +#include "wizard/wizard-messages.h" + +/*! + * @brief プレイヤーの変異要素による打撃処理 + * @param attacker_ptr プレーヤーへの参照ポインタ + * @param m_idx 攻撃目標となったモンスターの参照ID + * @param attack 変異要素による攻撃要素の種類 + * @param fear 攻撃を受けたモンスターが恐慌状態に陥ったかを返す参照ポインタ + * @param mdeath 攻撃を受けたモンスターが死亡したかを返す参照ポインタ + * @return なし + */ +static void natural_attack(player_type *attacker_ptr, MONSTER_IDX m_idx, int attack, bool *fear, bool *mdeath) +{ + WEIGHT n_weight = 0; + monster_type *m_ptr = &attacker_ptr->current_floor_ptr->m_list[m_idx]; + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + + int dice_num, dice_side; + concptr atk_desc; + switch (attack) { + case MUT2_SCOR_TAIL: + dice_num = 3; + dice_side = 7; + n_weight = 5; + atk_desc = _("尻尾", "tail"); + break; + case MUT2_HORNS: + dice_num = 2; + dice_side = 6; + n_weight = 15; + atk_desc = _("角", "horns"); + break; + case MUT2_BEAK: + dice_num = 2; + dice_side = 4; + n_weight = 5; + atk_desc = _("クチバシ", "beak"); + break; + case MUT2_TRUNK: + dice_num = 1; + dice_side = 4; + n_weight = 35; + atk_desc = _("象の鼻", "trunk"); + break; + case MUT2_TENTACLES: + dice_num = 2; + dice_side = 5; + n_weight = 5; + atk_desc = _("触手", "tentacles"); + break; + default: + dice_num = dice_side = n_weight = 1; + atk_desc = _("未定義の部位", "undefined body part"); + } + + GAME_TEXT m_name[MAX_NLEN]; + monster_desc(attacker_ptr, m_name, m_ptr, 0); + + int bonus = attacker_ptr->to_h_m + (attacker_ptr->lev * 6 / 5); + int chance = (attacker_ptr->skill_thn + (bonus * BTH_PLUS_ADJ)); + + bool is_hit = ((r_ptr->flags2 & RF2_QUANTUM) == 0) || !randint0(2); + is_hit &= test_hit_norm(attacker_ptr, chance, r_ptr->ac, m_ptr->ml); + if (!is_hit) { + sound(SOUND_MISS); + msg_format(_("ミス! %sにかわされた。", "You miss %s."), m_name); + return; + } + + sound(SOUND_HIT); + msg_format(_("%sを%sで攻撃した。", "You hit %s with your %s."), m_name, atk_desc); + + HIT_POINT k = damroll(dice_num, dice_side); + k = critical_norm(attacker_ptr, n_weight, bonus, k, (s16b)bonus, 0); + k += attacker_ptr->to_d_m; + if (k < 0) + k = 0; + + k = mon_damage_mod(attacker_ptr, m_ptr, k, FALSE); + msg_format_wizard(attacker_ptr, CHEAT_MONSTER, _("%dのダメージを与えた。(残りHP %d/%d(%d))", "You do %d damage. (left HP %d/%d(%d))"), k, m_ptr->hp - k, + m_ptr->maxhp, m_ptr->max_maxhp); + if (k > 0) + anger_monster(attacker_ptr, m_ptr); + + switch (attack) { + case MUT2_SCOR_TAIL: + project(attacker_ptr, 0, 0, m_ptr->fy, m_ptr->fx, k, GF_POIS, PROJECT_KILL, -1); + *mdeath = (m_ptr->r_idx == 0); + break; + case MUT2_HORNS: + *mdeath = mon_take_hit(attacker_ptr, m_idx, k, fear, NULL); + break; + case MUT2_BEAK: + *mdeath = mon_take_hit(attacker_ptr, m_idx, k, fear, NULL); + break; + case MUT2_TRUNK: + *mdeath = mon_take_hit(attacker_ptr, m_idx, k, fear, NULL); + break; + case MUT2_TENTACLES: + *mdeath = mon_take_hit(attacker_ptr, m_idx, k, fear, NULL); + break; + default: + *mdeath = mon_take_hit(attacker_ptr, m_idx, k, fear, NULL); + } + + touch_zap_player(m_ptr, attacker_ptr); +} + +/*! + * @brief プレイヤーの打撃処理メインルーチン + * @param y 攻撃目標のY座標 + * @param x 攻撃目標のX座標 + * @param mode 発動中の剣術ID + * @return 実際に攻撃処理が行われた場合TRUEを返す。 + * @details + * If no "weapon" is available, then "punch" the monster one time. + */ +bool do_cmd_attack(player_type *attacker_ptr, POSITION y, POSITION x, combat_options mode) +{ + grid_type *g_ptr = &attacker_ptr->current_floor_ptr->grid_array[y][x]; + monster_type *m_ptr = &attacker_ptr->current_floor_ptr->m_list[g_ptr->m_idx]; + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + GAME_TEXT m_name[MAX_NLEN]; + + disturb(attacker_ptr, FALSE, TRUE); + + take_turn(attacker_ptr, 100); + + if (!have_right_hand_weapon(attacker_ptr) && !have_left_hand_weapon(attacker_ptr) + && !(attacker_ptr->muta2 & (MUT2_HORNS | MUT2_BEAK | MUT2_SCOR_TAIL | MUT2_TRUNK | MUT2_TENTACLES))) { + msg_format(_("%s攻撃できない。", "You cannot do attacking."), (empty_hands(attacker_ptr, FALSE) == EMPTY_HAND_NONE) ? _("両手がふさがって", "") : ""); + return FALSE; + } + + monster_desc(attacker_ptr, m_name, m_ptr, 0); + + if (m_ptr->ml) { + if (!attacker_ptr->image) + monster_race_track(attacker_ptr, m_ptr->ap_r_idx); + + health_track(attacker_ptr, g_ptr->m_idx); + } + + if ((r_ptr->flags1 & RF1_FEMALE) && !(attacker_ptr->stun || attacker_ptr->confused || attacker_ptr->image || !m_ptr->ml)) { + if ((attacker_ptr->inventory_list[INVEN_RARM].name1 == ART_ZANTETSU) || (attacker_ptr->inventory_list[INVEN_LARM].name1 == ART_ZANTETSU)) { + msg_print(_("拙者、おなごは斬れぬ!", "I can not attack women!")); + return FALSE; + } + } + + if (d_info[attacker_ptr->dungeon_idx].flags1 & DF1_NO_MELEE) { + msg_print(_("なぜか攻撃することができない。", "Something prevents you from attacking.")); + return FALSE; + } + + bool stormbringer = FALSE; + if (!is_hostile(m_ptr) && !(attacker_ptr->stun || attacker_ptr->confused || attacker_ptr->image || attacker_ptr->shero || !m_ptr->ml)) { + if (attacker_ptr->inventory_list[INVEN_RARM].name1 == ART_STORMBRINGER) + stormbringer = TRUE; + if (attacker_ptr->inventory_list[INVEN_LARM].name1 == ART_STORMBRINGER) + stormbringer = TRUE; + if (stormbringer) { + msg_format(_("黒い刃は強欲に%sを攻撃した!", "Your black blade greedily attacks %s!"), m_name); + chg_virtue(attacker_ptr, V_INDIVIDUALISM, 1); + chg_virtue(attacker_ptr, V_HONOUR, -1); + chg_virtue(attacker_ptr, V_JUSTICE, -1); + chg_virtue(attacker_ptr, V_COMPASSION, -1); + } else if (attacker_ptr->pclass != CLASS_BERSERKER) { + if (get_check(_("本当に攻撃しますか?", "Really hit it? "))) { + chg_virtue(attacker_ptr, V_INDIVIDUALISM, 1); + chg_virtue(attacker_ptr, V_HONOUR, -1); + chg_virtue(attacker_ptr, V_JUSTICE, -1); + chg_virtue(attacker_ptr, V_COMPASSION, -1); + } else { + msg_format(_("%sを攻撃するのを止めた。", "You stop to avoid hitting %s."), m_name); + return FALSE; + } + } + } + + if (attacker_ptr->afraid) { + if (m_ptr->ml) + msg_format(_("恐くて%sを攻撃できない!", "You are too afraid to attack %s!"), m_name); + else + msg_format(_("そっちには何か恐いものがいる!", "There is something scary in your way!")); + + (void)set_monster_csleep(attacker_ptr, g_ptr->m_idx, 0); + return FALSE; + } + + if (monster_csleep_remaining(m_ptr)) { + if (!(r_ptr->flags3 & RF3_EVIL) || one_in_(5)) + chg_virtue(attacker_ptr, V_COMPASSION, -1); + if (!(r_ptr->flags3 & RF3_EVIL) || one_in_(5)) + chg_virtue(attacker_ptr, V_HONOUR, -1); + } + + if (have_right_hand_weapon(attacker_ptr) && have_left_hand_weapon(attacker_ptr)) { + if ((attacker_ptr->skill_exp[GINOU_NITOURYU] < s_info[attacker_ptr->pclass].s_max[GINOU_NITOURYU]) + && ((attacker_ptr->skill_exp[GINOU_NITOURYU] - 1000) / 200 < r_ptr->level)) { + if (attacker_ptr->skill_exp[GINOU_NITOURYU] < WEAPON_EXP_BEGINNER) + attacker_ptr->skill_exp[GINOU_NITOURYU] += 80; + else if (attacker_ptr->skill_exp[GINOU_NITOURYU] < WEAPON_EXP_SKILLED) + attacker_ptr->skill_exp[GINOU_NITOURYU] += 4; + else if (attacker_ptr->skill_exp[GINOU_NITOURYU] < WEAPON_EXP_EXPERT) + attacker_ptr->skill_exp[GINOU_NITOURYU] += 1; + else if (attacker_ptr->skill_exp[GINOU_NITOURYU] < WEAPON_EXP_MASTER) + if (one_in_(3)) + attacker_ptr->skill_exp[GINOU_NITOURYU] += 1; + attacker_ptr->update |= (PU_BONUS); + } + } + + if (attacker_ptr->riding) { + int cur = attacker_ptr->skill_exp[GINOU_RIDING]; + int max = s_info[attacker_ptr->pclass].s_max[GINOU_RIDING]; + + if (cur < max) { + DEPTH ridinglevel = r_info[attacker_ptr->current_floor_ptr->m_list[attacker_ptr->riding].r_idx].level; + DEPTH targetlevel = r_ptr->level; + int inc = 0; + + if ((cur / 200 - 5) < targetlevel) + inc += 1; + + if ((cur / 100) < ridinglevel) { + if ((cur / 100 + 15) < ridinglevel) + inc += 1 + (ridinglevel - (cur / 100 + 15)); + else + inc += 1; + } + + attacker_ptr->skill_exp[GINOU_RIDING] = MIN(max, cur + inc); + attacker_ptr->update |= (PU_BONUS); + } + } + + attacker_ptr->riding_t_m_idx = g_ptr->m_idx; + bool fear = FALSE; + bool mdeath = FALSE; + if (have_right_hand_weapon(attacker_ptr)) + exe_player_attack_to_monster(attacker_ptr, y, x, &fear, &mdeath, 0, mode); + if (have_left_hand_weapon(attacker_ptr) && !mdeath) + exe_player_attack_to_monster(attacker_ptr, y, x, &fear, &mdeath, 1, mode); + + if (!mdeath) { + if ((attacker_ptr->muta2 & MUT2_HORNS) && !mdeath) + natural_attack(attacker_ptr, g_ptr->m_idx, MUT2_HORNS, &fear, &mdeath); + if ((attacker_ptr->muta2 & MUT2_BEAK) && !mdeath) + natural_attack(attacker_ptr, g_ptr->m_idx, MUT2_BEAK, &fear, &mdeath); + if ((attacker_ptr->muta2 & MUT2_SCOR_TAIL) && !mdeath) + natural_attack(attacker_ptr, g_ptr->m_idx, MUT2_SCOR_TAIL, &fear, &mdeath); + if ((attacker_ptr->muta2 & MUT2_TRUNK) && !mdeath) + natural_attack(attacker_ptr, g_ptr->m_idx, MUT2_TRUNK, &fear, &mdeath); + if ((attacker_ptr->muta2 & MUT2_TENTACLES) && !mdeath) + natural_attack(attacker_ptr, g_ptr->m_idx, MUT2_TENTACLES, &fear, &mdeath); + } + + if (fear && m_ptr->ml && !mdeath) { + sound(SOUND_FLEE); + msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), m_name); + } + + if ((attacker_ptr->special_defense & KATA_IAI) && ((mode != HISSATSU_IAI) || mdeath)) { + set_action(attacker_ptr, ACTION_NONE); + } + + return mdeath; +} diff --git a/src/cmd-action/cmd-attack.h b/src/cmd-action/cmd-attack.h new file mode 100644 index 000000000..843696cc0 --- /dev/null +++ b/src/cmd-action/cmd-attack.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" +#include "player-attack/player-attack-util.h" + +bool do_cmd_attack(player_type *attacker_ptr, POSITION y, POSITION x, combat_options mode); diff --git a/src/cmd-action/cmd-hissatsu.c b/src/cmd-action/cmd-hissatsu.c new file mode 100644 index 000000000..7199ac8d3 --- /dev/null +++ b/src/cmd-action/cmd-hissatsu.c @@ -0,0 +1,427 @@ +/*! + * @brief 剣術の実装 / Blade arts + * @date 2014/01/17 + * @author + * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n + * This software may be copied and distributed for educational, research,\n + * and not for profit purposes provided that this copyright and statement\n + * are included in all such copies. Other copyrights may also apply.\n + * 2014 Deskull rearranged comment for Doxygen.\n + */ + +#include "cmd-action/cmd-spell.h" +#include "action/action-limited.h" +#include "core/asking-player.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "floor/floor-object.h" +#include "game-option/disturbance-options.h" +#include "game-option/text-display-options.h" +#include "inventory/inventory-slot-types.h" +#include "io/command-repeater.h" +#include "io/input-key-requester.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-race/monster-race-hook.h" +#include "object/item-use-flags.h" +#include "player/attack-defense-types.h" +#include "player/player-status.h" +#include "player/special-defense-types.h" +#include "spell/spells-execution.h" +#include "spell/technic-info-table.h" +#include "status/action-setter.h" +#include "system/object-type-definition.h" +#include "term/screen-processor.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" + +#define TECHNIC_HISSATSU (REALM_HISSATSU - MIN_TECHNIC) + +/*! + * @brief 使用可能な剣術を選択する / + * Allow user to choose a blade arts. + * @param sn 選択した特殊技能ID、キャンセルの場合-1、不正な選択の場合-2を返す + * @return 発動可能な魔法を選択した場合TRUE、キャンセル処理か不正な選択が行われた場合FALSEを返す。 + * @details + * If a valid spell is chosen, saves it in '*sn' and returns TRUE\n + * If the user hits escape, returns FALSE, and set '*sn' to -1\n + * If there are no legal choices, returns FALSE, and sets '*sn' to -2\n + *\n + * The "prompt" should be "cast", "recite", or "study"\n + * The "known" should be TRUE for cast/pray, FALSE for study\n + *\n + * nb: This function has a (trivial) display bug which will be obvious\n + * when you run it. It's probably easy to fix but I haven't tried,\n + * sorry.\n + */ +static int get_hissatsu_power(player_type *creature_ptr, SPELL_IDX *sn) +{ + SPELL_IDX i; + int j = 0; + int num = 0; + POSITION y = 1; + POSITION x = 15; + PLAYER_LEVEL plev = creature_ptr->lev; + int ask = TRUE; + char choice; + char out_val[160]; + SPELL_IDX sentaku[32]; + concptr p = _("必殺剣", "special attack"); + COMMAND_CODE code; + magic_type spell; + bool flag, redraw; + int menu_line = (use_menu ? 1 : 0); + + /* Assume cancelled */ + *sn = (-1); + + /* Get the spell, if available */ + if (repeat_pull(&code)) { + *sn = (SPELL_IDX)code; + /* Verify the spell */ + if (technic_info[TECHNIC_HISSATSU][*sn].slevel <= plev) { + /* Success */ + return TRUE; + } + } + + flag = FALSE; + redraw = FALSE; + + for (i = 0; i < 32; i++) { + if (technic_info[TECHNIC_HISSATSU][i].slevel <= PY_MAX_LEVEL) { + sentaku[num] = i; + num++; + } + } + + /* Build a prompt (accept all spells) */ + (void)strnfmt(out_val, 78, _("(%^s %c-%c, '*'で一覧, ESC) どの%sを使いますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "), p, I2A(0), + "abcdefghijklmnopqrstuvwxyz012345"[num - 1], p); + + if (use_menu) + screen_save(); + choice = always_show_list ? ESCAPE : 1; + + while (!flag) { + if (choice == ESCAPE) + choice = ' '; + else if (!get_com(out_val, &choice, FALSE)) + break; + + if (use_menu && choice != ' ') { + switch (choice) { + case '0': { + screen_load(); + return FALSE; + } + + case '8': + case 'k': + case 'K': { + do { + menu_line += 31; + if (menu_line > 32) + menu_line -= 32; + } while (!(creature_ptr->spell_learned1 & (1L << (menu_line - 1)))); + break; + } + + case '2': + case 'j': + case 'J': { + do { + menu_line++; + if (menu_line > 32) + menu_line -= 32; + } while (!(creature_ptr->spell_learned1 & (1L << (menu_line - 1)))); + break; + } + + case '4': + case 'h': + case 'H': + case '6': + case 'l': + case 'L': { + bool reverse = FALSE; + if ((choice == '4') || (choice == 'h') || (choice == 'H')) + reverse = TRUE; + if (menu_line > 16) { + menu_line -= 16; + reverse = TRUE; + } else + menu_line += 16; + while (!(creature_ptr->spell_learned1 & (1L << (menu_line - 1)))) { + if (reverse) { + menu_line--; + if (menu_line < 2) + reverse = FALSE; + } else { + menu_line++; + if (menu_line > 31) + reverse = TRUE; + } + } + break; + } + + case 'x': + case 'X': + case '\r': + case '\n': { + i = menu_line - 1; + ask = FALSE; + break; + } + } + } + /* Request redraw */ + if ((choice == ' ') || (choice == '*') || (choice == '?') || (use_menu && ask)) { + /* Show the list */ + if (!redraw || use_menu) { + char psi_desc[80]; + int line; + redraw = TRUE; + if (!use_menu) + screen_save(); + + /* Display a list of spells */ + prt("", y, x); + put_str(_("名前 Lv MP 名前 Lv MP ", "name Lv SP name Lv SP "), y, x + 5); + prt("", y + 1, x); + /* Dump the spells */ + for (i = 0, line = 0; i < 32; i++) { + spell = technic_info[TECHNIC_HISSATSU][i]; + + if (spell.slevel > PY_MAX_LEVEL) + continue; + line++; + if (!(creature_ptr->spell_learned1 >> i)) + break; + + /* Access the spell */ + if (spell.slevel > plev) + continue; + if (!(creature_ptr->spell_learned1 & (1L << i))) + continue; + if (use_menu) { + if (i == (menu_line - 1)) + strcpy(psi_desc, _(" 》", " > ")); + else + strcpy(psi_desc, " "); + + } else { + char letter; + if (line <= 26) + letter = I2A(line - 1); + else + letter = '0' + line - 27; + sprintf(psi_desc, " %c)", letter); + } + + /* Dump the spell --(-- */ + strcat(psi_desc, format(" %-18s%2d %3d", exe_spell(creature_ptr, REALM_HISSATSU, i, SPELL_NAME), spell.slevel, spell.smana)); + prt(psi_desc, y + (line % 17) + (line >= 17), x + (line / 17) * 30); + prt("", y + (line % 17) + (line >= 17) + 1, x + (line / 17) * 30); + } + } + + /* Hide the list */ + else { + /* Hide list */ + redraw = FALSE; + screen_load(); + } + + /* Redo asking */ + continue; + } + + if (!use_menu) { + if (isalpha(choice)) { + /* Note verify */ + ask = (isupper(choice)); + + /* Lowercase */ + if (ask) + choice = (char)tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + } else { + ask = FALSE; /* Can't uppercase digits */ + + i = choice - '0' + 26; + } + } + + /* Totally Illegal */ + if ((i < 0) || (i >= 32) || !(creature_ptr->spell_learned1 & (1 << sentaku[i]))) { + bell(); + continue; + } + + j = sentaku[i]; + + /* Verify it */ + if (ask) { + char tmp_val[160]; + + /* Prompt */ + (void)strnfmt(tmp_val, 78, _("%sを使いますか?", "Use %s? "), exe_spell(creature_ptr, REALM_HISSATSU, j, SPELL_NAME)); + + /* Belay that order */ + if (!get_check(tmp_val)) + continue; + } + + /* Stop the loop */ + flag = TRUE; + } + if (redraw) + screen_load(); + + creature_ptr->window |= (PW_SPELL); + handle_stuff(creature_ptr); + + /* Abort if needed */ + if (!flag) + return FALSE; + + /* Save the choice */ + (*sn) = j; + + repeat_push((COMMAND_CODE)j); + + /* Success */ + return TRUE; +} + +/*! + * @brief 剣術コマンドのメインルーチン + * @return なし + */ +void do_cmd_hissatsu(player_type *creature_ptr) +{ + SPELL_IDX n = 0; + magic_type spell; + + if (cmd_limit_confused(creature_ptr)) + return; + if (!has_melee_weapon(creature_ptr, INVEN_RARM) && !has_melee_weapon(creature_ptr, INVEN_LARM)) { + if (flush_failure) + flush(); + msg_print(_("武器を持たないと必殺技は使えない!", "You need to wield a weapon!")); + return; + } + if (!creature_ptr->spell_learned1) { + msg_print(_("何も技を知らない。", "You don't know any special attacks.")); + return; + } + + if (creature_ptr->special_defense & KATA_MASK) { + set_action(creature_ptr, ACTION_NONE); + } + + if (!get_hissatsu_power(creature_ptr, &n)) + return; + + spell = technic_info[TECHNIC_HISSATSU][n]; + + /* Verify "dangerous" spells */ + if (spell.smana > creature_ptr->csp) { + if (flush_failure) + flush(); + /* Warning */ + msg_print(_("MPが足りません。", "You do not have enough mana to use this power.")); + msg_print(NULL); + return; + } + + sound(SOUND_ZAP); + + if (!exe_spell(creature_ptr, REALM_HISSATSU, n, SPELL_CAST)) + return; + + take_turn(creature_ptr, 100); + + /* Use some mana */ + creature_ptr->csp -= spell.smana; + + /* Limit */ + if (creature_ptr->csp < 0) + creature_ptr->csp = 0; + creature_ptr->redraw |= (PR_MANA); + creature_ptr->window |= (PW_PLAYER | PW_SPELL); +} + +/*! + * @brief 剣術コマンドの学習 + * @return なし + */ +void do_cmd_gain_hissatsu(player_type *creature_ptr) +{ + OBJECT_IDX item; + int i, j; + + object_type *o_ptr; + concptr q, s; + + bool gain = FALSE; + + if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) { + set_action(creature_ptr, ACTION_NONE); + } + + if (cmd_limit_blind(creature_ptr)) + return; + if (cmd_limit_confused(creature_ptr)) + return; + + if (!(creature_ptr->new_spells)) { + msg_print(_("新しい必殺技を覚えることはできない!", "You cannot learn any new special attacks!")); + return; + } + +#ifdef JP + msg_format("あと %d 種の必殺技を学べる。", creature_ptr->new_spells); +#else + msg_format("You can learn %d new special attack%s.", creature_ptr->new_spells, (creature_ptr->new_spells == 1 ? "" : "s")); +#endif + + q = _("どの書から学びますか? ", "Study which book? "); + s = _("読める書がない。", "You have no books that you can read."); + + o_ptr = choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), TV_HISSATSU_BOOK); + if (!o_ptr) + return; + + for (i = o_ptr->sval * 8; i < o_ptr->sval * 8 + 8; i++) { + if (creature_ptr->spell_learned1 & (1L << i)) + continue; + if (technic_info[TECHNIC_HISSATSU][i].slevel > creature_ptr->lev) + continue; + + creature_ptr->spell_learned1 |= (1L << i); + creature_ptr->spell_worked1 |= (1L << i); + msg_format(_("%sの技を覚えた。", "You have learned the special attack of %s."), exe_spell(creature_ptr, REALM_HISSATSU, i, SPELL_NAME)); + for (j = 0; j < 64; j++) { + /* Stop at the first empty space */ + if (creature_ptr->spell_order[j] == 99) + break; + } + creature_ptr->spell_order[j] = i; + gain = TRUE; + } + + if (!gain) { + msg_print(_("何も覚えられなかった。", "You were not able to learn any special attacks.")); + } else { + take_turn(creature_ptr, 100); + } + + creature_ptr->update |= (PU_SPELLS); +} diff --git a/src/cmd-action/cmd-hissatsu.h b/src/cmd-action/cmd-hissatsu.h new file mode 100644 index 000000000..0300cd0e2 --- /dev/null +++ b/src/cmd-action/cmd-hissatsu.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_hissatsu(player_type *creature_ptr); +void do_cmd_gain_hissatsu(player_type *creature_ptr); diff --git a/src/cmd-action/cmd-mane.c b/src/cmd-action/cmd-mane.c new file mode 100644 index 000000000..ac315a1fb --- /dev/null +++ b/src/cmd-action/cmd-mane.c @@ -0,0 +1,1143 @@ +/*! + * @brief ものまねの処理実装 / Imitation code + * @date 2014/01/14 + * @author + * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n + * This software may be copied and distributed for educational, research,\n + * and not for profit purposes provided that this copyright and statement\n + * are included in all such copies. Other copyrights may also apply.\n + * 2014 Deskull rearranged comment for Doxygen.\n + */ + +#include "action/action-limited.h" +#include "cmd-action/cmd-spell.h" +#include "core/asking-player.h" +#include "core/hp-mp-processor.h" +#include "core/player-redraw-types.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "floor/cave.h" +#include "floor/floor-object.h" +#include "game-option/disturbance-options.h" +#include "game-option/text-display-options.h" +#include "grid/grid.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "mind/mind-mage.h" +#include "monster-floor/monster-summon.h" +#include "monster-floor/place-monster-types.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags-resistance.h" +#include "monster-race/race-flags1.h" +#include "monster/monster-describer.h" +#include "monster/monster-info.h" +#include "monster/monster-processor.h" +#include "monster/monster-status.h" +#include "mspell/monster-power-table.h" +#include "mspell/mspell-type.h" +#include "player/player-status.h" +#include "player/player-status-table.h" +#include "spell-kind/spells-launcher.h" +#include "spell-kind/spells-lite.h" +#include "spell-kind/spells-neighbor.h" +#include "spell-kind/spells-sight.h" +#include "spell-kind/spells-teleport.h" +#include "spell-kind/spells-world.h" +#include "spell/spell-types.h" +#include "spell/spells-status.h" +#include "spell/spells-summon.h" +#include "spell/summon-types.h" +#include "status/bad-status-setter.h" +#include "status/body-improvement.h" +#include "status/buff-setter.h" +#include "system/floor-type-definition.h" +#include "target/projection-path-calculator.h" +#include "target/target-checker.h" +#include "target/target-getter.h" +#include "target/target-setter.h" +#include "target/target-types.h" +#include "term/screen-processor.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" + +static int damage; + +/*! + * @brief 受け取ったパラメータに応じてものまねの効果情報をまとめたフォーマットを返す + * @param p 情報を返す文字列参照ポインタ + * @param power ものまねの効力の種類 + * @param dam ものまねの威力 + * @return なし + */ +static void mane_info(player_type *caster_ptr, char *p, int power, HIT_POINT dam) +{ + PLAYER_LEVEL plev = caster_ptr->lev; + + strcpy(p, ""); + + if ((power > 2 && power < 41) || (power > 41 && power < 59) || (power == 75)) + sprintf(p, " %s%d", KWD_DAM, (int)dam); + else { + switch (power) { + case 41: + sprintf(p, " %sd%d+%d", KWD_HEAL, plev * 3, plev); + break; + case 64: + sprintf(p, " %sd%d+%d", KWD_DURATION, 20 + plev, plev); + break; + case 66: + sprintf(p, " %s%d", KWD_HEAL, plev * 6); + break; + case 67: + sprintf(p, " %sd7+7", KWD_DURATION); + break; + case 68: + sprintf(p, " %s10", KWD_SPHERE); + break; + case 69: + sprintf(p, " %s%d", KWD_SPHERE, plev * 5); + break; + case 79: + sprintf(p, " %s5", KWD_SPHERE); + break; + default: + break; + } + } +} + +/*! + * @brief どのものまねを発動するか選択する処理 / + * Allow user to choose a imitation. + * @param sn 実行したものまねのIDを返す参照ポインタ(キャンセルなどの場合-1を返す) + * @param baigaesi TRUEならば倍返し上の処理として行う + * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。 + * @details + * If a valid spell is chosen, saves it in '*sn' and returns TRUE + * If the user hits escape, returns FALSE, and set '*sn' to -1 + * If there are no legal choices, returns FALSE, and sets '*sn' to -2 + * + * The "prompt" should be "cast", "recite", or "study" + * The "known" should be TRUE for cast/pray, FALSE for study + * + * nb: This function has a (trivial) display bug which will be obvious + * when you run it. It's probably easy to fix but I haven't tried, + * sorry. + */ +static int get_mane_power(player_type *caster_ptr, int *sn, bool baigaesi) +{ + int i = 0; + int num = 0; + TERM_LEN y = 1; + TERM_LEN x = 18; + PERCENTAGE minfail = 0; + PLAYER_LEVEL plev = caster_ptr->lev; + PERCENTAGE chance = 0; + int ask; + char choice; + char out_val[160]; + char comment[80]; + concptr p = _("能力", "power"); + + monster_power spell; + bool flag, redraw; + + /* Assume cancelled */ + *sn = (-1); + + flag = FALSE; + redraw = FALSE; + + num = caster_ptr->mane_num; + + /* Build a prompt (accept all spells) */ + (void)strnfmt(out_val, 78, _("(%c-%c, '*'で一覧, ESC) どの%sをまねますか?", "(%c-%c, *=List, ESC=exit) Use which %s? "), I2A(0), I2A(num - 1), p); + + choice = always_show_list ? ESCAPE : 1; + while (!flag) { + if (choice == ESCAPE) + choice = ' '; + else if (!get_com(out_val, &choice, TRUE)) + break; + + /* Request redraw */ + if ((choice == ' ') || (choice == '*') || (choice == '?')) { + /* Show the list */ + if (!redraw) { + char psi_desc[80]; + redraw = TRUE; + screen_save(); + + /* Display a list of spells */ + prt("", y, x); + put_str(_("名前", "Name"), y, x + 5); + put_str(_("失率 効果", "Fail Info"), y, x + 36); + + /* Dump the spells */ + for (i = 0; i < num; i++) { + /* Access the spell */ + spell = monster_powers[caster_ptr->mane_spell[i]]; + + chance = spell.manefail; + + /* Reduce failure rate by "effective" level adjustment */ + if (plev > spell.level) + chance -= 3 * (plev - spell.level); + + /* Reduce failure rate by INT/WIS adjustment */ + chance -= 3 * (adj_mag_stat[caster_ptr->stat_ind[spell.use_stat]] + adj_mag_stat[caster_ptr->stat_ind[A_DEX]] - 2) / 2; + + if (spell.manedam) + chance = chance * (baigaesi ? caster_ptr->mane_dam[i] * 2 : caster_ptr->mane_dam[i]) / spell.manedam; + + chance += caster_ptr->to_m_chance; + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[caster_ptr->stat_ind[spell.use_stat]]; + + /* Minimum failure rate */ + if (chance < minfail) + chance = minfail; + + /* Stunning makes spells harder */ + if (caster_ptr->stun > 50) + chance += 25; + else if (caster_ptr->stun) + chance += 15; + + /* Always a 5 percent chance of working */ + if (chance > 95) + chance = 95; + + /* Get info */ + mane_info(caster_ptr, comment, caster_ptr->mane_spell[i], (baigaesi ? caster_ptr->mane_dam[i] * 2 : caster_ptr->mane_dam[i])); + + /* Dump the spell --(-- */ + sprintf(psi_desc, " %c) %-30s %3d%%%s", I2A(i), spell.name, chance, comment); + prt(psi_desc, y + i + 1, x); + } + + /* Clear the bottom line */ + prt("", y + i + 1, x); + } + + /* Hide the list */ + else { + /* Hide list */ + redraw = FALSE; + screen_load(); + } + + /* Redo asking */ + continue; + } + + /* Note verify */ + ask = isupper(choice); + + /* Lowercase */ + if (ask) + choice = (char)tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + + /* Totally Illegal */ + if ((i < 0) || (i >= num)) { + bell(); + continue; + } + + /* Save the spell index */ + spell = monster_powers[caster_ptr->mane_spell[i]]; + + /* Verify it */ + if (ask) { + char tmp_val[160]; + + /* Prompt */ + (void)strnfmt(tmp_val, 78, _("%sをまねますか?", "Use %s? "), monster_powers[caster_ptr->mane_spell[i]].name); + + /* Belay that order */ + if (!get_check(tmp_val)) + continue; + } + + /* Stop the loop */ + flag = TRUE; + } + if (redraw) + screen_load(); + + caster_ptr->window |= (PW_SPELL); + handle_stuff(caster_ptr); + + /* Abort if needed */ + if (!flag) + return FALSE; + + /* Save the choice */ + (*sn) = i; + + damage = (baigaesi ? caster_ptr->mane_dam[i] * 2 : caster_ptr->mane_dam[i]); + + /* Success */ + return TRUE; +} + +/*! + * @brief ものまね処理の発動 / + * do_cmd_cast calls this function if the player's class is 'imitator'. + * @param caster_ptr プレーヤーへの参照ポインタ + * @param spell 発動するモンスター攻撃のID + * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。 + */ +static bool use_mane(player_type *caster_ptr, int spell) +{ + DIRECTION dir; + PLAYER_LEVEL plev = caster_ptr->lev; + BIT_FLAGS mode = (PM_ALLOW_GROUP | PM_FORCE_PET); + BIT_FLAGS u_mode = 0L; + + if (randint1(50 + plev) < plev / 10) + u_mode = PM_ALLOW_UNIQUE; + + /* spell code */ + switch (spell) { + + case MS_SHRIEK: + msg_print(_("かん高い金切り声をあげた。", "You make a high pitched shriek.")); + aggravate_monsters(caster_ptr, 0); + break; + + case MS_XXX1: + break; + + case MS_DISPEL: { + MONSTER_IDX m_idx; + + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + m_idx = caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx; + if (!m_idx) + break; + if (!player_has_los_bold(caster_ptr, target_row, target_col)) + break; + if (!projectable(caster_ptr, caster_ptr->y, caster_ptr->x, target_row, target_col)) + break; + dispel_monster_status(caster_ptr, m_idx); + break; + } + + case MS_ROCKET: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("ロケットを発射した。", "You fire a rocket.")); + fire_rocket(caster_ptr, GF_ROCKET, dir, damage, 2); + break; + + case MS_SHOOT: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("矢を放った。", "You fire an arrow.")); + fire_bolt(caster_ptr, GF_ARROW, dir, damage); + break; + + case MS_XXX2: + break; + + case MS_XXX3: + break; + + case MS_XXX4: + break; + + case MS_BR_ACID: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("酸のブレスを吐いた。", "You breathe acid.")); + fire_breath(caster_ptr, GF_ACID, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_ELEC: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("稲妻のブレスを吐いた。", "You breathe lightning.")); + fire_breath(caster_ptr, GF_ELEC, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_FIRE: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("火炎のブレスを吐いた。", "You breathe fire.")); + fire_breath(caster_ptr, GF_FIRE, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_COLD: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("冷気のブレスを吐いた。", "You breathe frost.")); + fire_breath(caster_ptr, GF_COLD, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_POIS: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("ガスのブレスを吐いた。", "You breathe gas.")); + fire_breath(caster_ptr, GF_POIS, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_NETHER: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("地獄のブレスを吐いた。", "You breathe nether.")); + fire_breath(caster_ptr, GF_NETHER, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_LITE: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("閃光のブレスを吐いた。", "You breathe light.")); + fire_breath(caster_ptr, GF_LITE, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_DARK: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("暗黒のブレスを吐いた。", "You breathe darkness.")); + fire_breath(caster_ptr, GF_DARK, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_CONF: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("混乱のブレスを吐いた。", "You breathe confusion.")); + fire_breath(caster_ptr, GF_CONFUSION, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_SOUND: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("轟音のブレスを吐いた。", "You breathe sound.")); + fire_breath(caster_ptr, GF_SOUND, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_CHAOS: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("カオスのブレスを吐いた。", "You breathe chaos.")); + fire_breath(caster_ptr, GF_CHAOS, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_DISEN: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("劣化のブレスを吐いた。", "You breathe disenchantment.")); + fire_breath(caster_ptr, GF_DISENCHANT, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_NEXUS: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("因果混乱のブレスを吐いた。", "You breathe nexus.")); + fire_breath(caster_ptr, GF_NEXUS, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_TIME: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("時間逆転のブレスを吐いた。", "You breathe time.")); + fire_breath(caster_ptr, GF_TIME, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_INERTIA: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("遅鈍のブレスを吐いた。", "You breathe inertia.")); + fire_breath(caster_ptr, GF_INERTIAL, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_GRAVITY: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("重力のブレスを吐いた。", "You breathe gravity.")); + fire_breath(caster_ptr, GF_GRAVITY, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_SHARDS: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("破片のブレスを吐いた。", "You breathe shards.")); + fire_breath(caster_ptr, GF_SHARDS, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_PLASMA: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("プラズマのブレスを吐いた。", "You breathe plasma.")); + + fire_breath(caster_ptr, GF_PLASMA, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_FORCE: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("フォースのブレスを吐いた。", "You breathe force.")); + + fire_breath(caster_ptr, GF_FORCE, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BR_MANA: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("魔力のブレスを吐いた。", "You breathe mana.")); + + fire_breath(caster_ptr, GF_MANA, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BALL_NUKE: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("放射能球を放った。", "You cast a ball of radiation.")); + + fire_ball(caster_ptr, GF_NUKE, dir, damage, 2); + break; + + case MS_BR_NUKE: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("放射性廃棄物のブレスを吐いた。", "You breathe toxic waste.")); + + fire_breath(caster_ptr, GF_NUKE, dir, damage, (plev > 35 ? 3 : 2)); + break; + + case MS_BALL_CHAOS: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("純ログルスを放った。", "You invoke a raw Logrus.")); + + fire_ball(caster_ptr, GF_CHAOS, dir, damage, 4); + break; + case MS_BR_DISI: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("分解のブレスを吐いた。", "You breathe disintegration.")); + + fire_breath(caster_ptr, GF_DISINTEGRATE, dir, damage, (plev > 35 ? 3 : 2)); + break; + case MS_BALL_ACID: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("アシッド・ボールの呪文を唱えた。", "You cast an acid ball.")); + + fire_ball(caster_ptr, GF_ACID, dir, damage, 2); + break; + case MS_BALL_ELEC: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("サンダー・ボールの呪文を唱えた。", "You cast a lightning ball.")); + + fire_ball(caster_ptr, GF_ELEC, dir, damage, 2); + break; + case MS_BALL_FIRE: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("ファイア・ボールの呪文を唱えた。", "You cast a fire ball.")); + + fire_ball(caster_ptr, GF_FIRE, dir, damage, 2); + break; + case MS_BALL_COLD: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("アイス・ボールの呪文を唱えた。", "You cast a frost ball.")); + + fire_ball(caster_ptr, GF_COLD, dir, damage, 2); + break; + case MS_BALL_POIS: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("悪臭雲の呪文を唱えた。", "You cast a stinking cloud.")); + + fire_ball(caster_ptr, GF_POIS, dir, damage, 2); + break; + case MS_BALL_NETHER: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("地獄球の呪文を唱えた。", "You cast a nether ball.")); + + fire_ball(caster_ptr, GF_NETHER, dir, damage, 2); + break; + case MS_BALL_WATER: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("流れるような身振りをした。", "You gesture fluidly.")); + + fire_ball(caster_ptr, GF_WATER, dir, damage, 4); + break; + case MS_BALL_MANA: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("魔力の嵐の呪文を念じた。", "You invoke a mana storm.")); + + fire_ball(caster_ptr, GF_MANA, dir, damage, 4); + break; + case MS_BALL_DARK: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("暗黒の嵐の呪文を念じた。", "You invoke a darkness storm.")); + + fire_ball(caster_ptr, GF_DARK, dir, damage, 4); + break; + case MS_DRAIN_MANA: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + fire_ball_hide(caster_ptr, GF_DRAIN_MANA, dir, randint1(plev * 3) + plev, 0); + break; + case MS_MIND_BLAST: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + fire_ball_hide(caster_ptr, GF_MIND_BLAST, dir, damage, 0); + break; + case MS_BRAIN_SMASH: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + fire_ball_hide(caster_ptr, GF_BRAIN_SMASH, dir, damage, 0); + break; + case MS_CAUSE_1: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + fire_ball_hide(caster_ptr, GF_CAUSE_1, dir, damage, 0); + break; + case MS_CAUSE_2: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + fire_ball_hide(caster_ptr, GF_CAUSE_2, dir, damage, 0); + break; + case MS_CAUSE_3: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + fire_ball_hide(caster_ptr, GF_CAUSE_3, dir, damage, 0); + break; + case MS_CAUSE_4: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + fire_ball_hide(caster_ptr, GF_CAUSE_4, dir, damage, 0); + break; + case MS_BOLT_ACID: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("アシッド・ボルトの呪文を唱えた。", "You cast an acid bolt.")); + + fire_bolt(caster_ptr, GF_ACID, dir, damage); + break; + case MS_BOLT_ELEC: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("サンダー・ボルトの呪文を唱えた。", "You cast a lightning bolt.")); + + fire_bolt(caster_ptr, GF_ELEC, dir, damage); + break; + case MS_BOLT_FIRE: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("ファイア・ボルトの呪文を唱えた。", "You cast a fire bolt.")); + + fire_bolt(caster_ptr, GF_FIRE, dir, damage); + break; + case MS_BOLT_COLD: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("アイス・ボルトの呪文を唱えた。", "You cast a frost bolt.")); + + fire_bolt(caster_ptr, GF_COLD, dir, damage); + break; + case MS_STARBURST: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("スターバーストの呪文を念じた。", "You invoke a starburst.")); + + fire_ball(caster_ptr, GF_LITE, dir, damage, 4); + break; + case MS_BOLT_NETHER: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("地獄の矢の呪文を唱えた。", "You cast a nether bolt.")); + + fire_bolt(caster_ptr, GF_NETHER, dir, damage); + break; + case MS_BOLT_WATER: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("ウォーター・ボルトの呪文を唱えた。", "You cast a water bolt.")); + + fire_bolt(caster_ptr, GF_WATER, dir, damage); + break; + case MS_BOLT_MANA: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("魔力の矢の呪文を唱えた。", "You cast a mana bolt.")); + + fire_bolt(caster_ptr, GF_MANA, dir, damage); + break; + case MS_BOLT_PLASMA: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("プラズマ・ボルトの呪文を唱えた。", "You cast a plasma bolt.")); + + fire_bolt(caster_ptr, GF_PLASMA, dir, damage); + break; + case MS_BOLT_ICE: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("極寒の矢の呪文を唱えた。", "You cast a ice bolt.")); + + fire_bolt(caster_ptr, GF_ICE, dir, damage); + break; + case MS_MAGIC_MISSILE: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("マジック・ミサイルの呪文を唱えた。", "You cast a magic missile.")); + + fire_bolt(caster_ptr, GF_MISSILE, dir, damage); + break; + case MS_SCARE: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("恐ろしげな幻覚を作り出した。", "You cast a fearful illusion.")); + + fear_monster(caster_ptr, dir, plev + 10); + break; + case MS_BLIND: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + confuse_monster(caster_ptr, dir, plev * 2); + break; + case MS_CONF: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("誘惑的な幻覚をつくり出した。", "You cast a mesmerizing illusion.")); + + confuse_monster(caster_ptr, dir, plev * 2); + break; + case MS_SLOW: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + slow_monster(caster_ptr, dir, plev); + break; + case MS_SLEEP: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + sleep_monster(caster_ptr, dir, plev); + break; + case MS_SPEED: + (void)set_fast(caster_ptr, randint1(20 + plev) + plev, FALSE); + break; + case MS_HAND_DOOM: { + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("<破滅の手>を放った!", "You invoke the Hand of Doom!")); + + fire_ball_hide(caster_ptr, GF_HAND_DOOM, dir, 200, 0); + break; + } + case MS_HEAL: + msg_print(_("自分の傷に念を集中した。", "You concentrate on your wounds!")); + (void)hp_player(caster_ptr, plev * 6); + (void)set_stun(caster_ptr, 0); + (void)set_cut(caster_ptr, 0); + break; + case MS_INVULNER: + msg_print(_("無傷の球の呪文を唱えた。", "You cast a Globe of Invulnerability.")); + (void)set_invuln(caster_ptr, randint1(7) + 7, FALSE); + break; + case MS_BLINK: + teleport_player(caster_ptr, 10, TELEPORT_SPONTANEOUS); + break; + case MS_TELEPORT: + teleport_player(caster_ptr, plev * 5, TELEPORT_SPONTANEOUS); + break; + case MS_WORLD: + (void)time_walk(caster_ptr); + break; + case MS_SPECIAL: + break; + case MS_TELE_TO: { + monster_type *m_ptr; + monster_race *r_ptr; + GAME_TEXT m_name[MAX_NLEN]; + + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + if (!caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx) + break; + if (!player_has_los_bold(caster_ptr, target_row, target_col)) + break; + if (!projectable(caster_ptr, caster_ptr->y, caster_ptr->x, target_row, target_col)) + break; + m_ptr = &caster_ptr->current_floor_ptr->m_list[caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx]; + r_ptr = &r_info[m_ptr->r_idx]; + monster_desc(caster_ptr, m_name, m_ptr, 0); + if (r_ptr->flagsr & RFR_RES_TELE) { + if ((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flagsr & RFR_RES_ALL)) { + if (is_original_ap_and_seen(caster_ptr, m_ptr)) + r_ptr->r_flagsr |= RFR_RES_TELE; + msg_format(_("%sには効果がなかった!", "%s is unaffected!"), m_name); + + break; + } else if (r_ptr->level > randint1(100)) { + if (is_original_ap_and_seen(caster_ptr, m_ptr)) + r_ptr->r_flagsr |= RFR_RES_TELE; + msg_format(_("%sには耐性がある!", "%s resists!"), m_name); + + break; + } + } + msg_format(_("%sを引き戻した。", "You command %s to return."), m_name); + + teleport_monster_to( + caster_ptr, caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx, caster_ptr->y, caster_ptr->x, 100, TELEPORT_PASSIVE); + break; + } + case MS_TELE_AWAY: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + + (void)fire_beam(caster_ptr, GF_AWAY_ALL, dir, plev); + break; + + case MS_TELE_LEVEL: + return teleport_level_other(caster_ptr); + break; + + case MS_PSY_SPEAR: + if (!get_aim_dir(caster_ptr, &dir)) + return FALSE; + else + msg_print(_("光の剣を放った。", "You throw a psycho-spear.")); + (void)fire_beam(caster_ptr, GF_PSY_SPEAR, dir, damage); + break; + + case MS_DARKNESS: + msg_print(_("暗闇の中で手を振った。", "You gesture in shadow.")); + (void)unlite_area(caster_ptr, 10, 3); + break; + + case MS_MAKE_TRAP: + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("呪文を唱えて邪悪に微笑んだ。", "You cast a spell and cackle evilly.")); + trap_creation(caster_ptr, target_row, target_col); + break; + case MS_FORGET: + msg_print(_("しかし何も起きなかった。", "Nothing happen.")); + break; + case MS_RAISE_DEAD: + msg_print(_("死者復活の呪文を唱えた。", "You animate the dead.")); + (void)animate_dead(caster_ptr, 0, caster_ptr->y, caster_ptr->x); + break; + case MS_S_KIN: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + + msg_print(_("援軍を召喚した。", "You summon minions.")); + for (k = 0; k < 4; k++) { + (void)summon_kin_player(caster_ptr, plev, target_row, target_col, (PM_FORCE_PET | PM_ALLOW_GROUP)); + } + break; + } + case MS_S_CYBER: { + int k; + int max_cyber = (caster_ptr->current_floor_ptr->dun_level / 50) + randint1(3); + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("サイバーデーモンを召喚した!", "You summon Cyberdemons!")); + if (max_cyber > 4) + max_cyber = 4; + for (k = 0; k < max_cyber; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_CYBER, mode); + break; + } + case MS_S_MONSTER: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("仲間を召喚した。", "You summon help.")); + for (k = 0; k < 1; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, 0, (mode | u_mode)); + break; + } + case MS_S_MONSTERS: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("モンスターを召喚した!", "You summon monsters!")); + for (k = 0; k < 6; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, 0, (mode | u_mode)); + break; + } + case MS_S_ANT: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("アリを召喚した。", "You summon ants.")); + for (k = 0; k < 6; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_ANT, mode); + break; + } + case MS_S_SPIDER: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("蜘蛛を召喚した。", "You summon spiders.")); + for (k = 0; k < 6; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_SPIDER, mode); + break; + } + case MS_S_HOUND: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("ハウンドを召喚した。", "You summon hounds.")); + for (k = 0; k < 4; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_HOUND, mode); + break; + } + case MS_S_HYDRA: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("ヒドラを召喚した。", "You summon hydras.")); + for (k = 0; k < 4; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_HYDRA, mode); + break; + } + case MS_S_ANGEL: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("天使を召喚した!", "You summon an angel!")); + for (k = 0; k < 1; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_ANGEL, mode); + break; + } + case MS_S_DEMON: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("混沌の宮廷から悪魔を召喚した!", "You summon a demon from the Courts of Chaos!")); + for (k = 0; k < 1; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_DEMON, (mode | u_mode)); + break; + } + case MS_S_UNDEAD: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("アンデッドの強敵を召喚した!", "You summon an undead adversary!")); + for (k = 0; k < 1; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_UNDEAD, (mode | u_mode)); + break; + } + case MS_S_DRAGON: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("ドラゴンを召喚した!", "You summon a dragon!")); + for (k = 0; k < 1; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_DRAGON, (mode | u_mode)); + break; + } + case MS_S_HI_UNDEAD: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("強力なアンデッドを召喚した!", "You summon greater undead!")); + for (k = 0; k < 6; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_HI_UNDEAD, (mode | u_mode)); + break; + } + case MS_S_HI_DRAGON: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("古代ドラゴンを召喚した!", "You summon ancient dragons!")); + for (k = 0; k < 4; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_HI_DRAGON, (mode | u_mode)); + break; + } + case MS_S_AMBERITE: { + int k; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("アンバーの王族を召喚した!", "You summon Lords of Amber!")); + for (k = 0; k < 4; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_AMBERITES, (mode | PM_ALLOW_UNIQUE)); + break; + } + case MS_S_UNIQUE: { + int k, count = 0; + if (!target_set(caster_ptr, TARGET_KILL)) + return FALSE; + msg_print(_("特別な強敵を召喚した!", "You summon special opponents!")); + for (k = 0; k < 4; k++) + if (summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_UNIQUE, (mode | PM_ALLOW_UNIQUE))) + count++; + for (k = count; k < 4; k++) + summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_HI_UNDEAD, (mode | u_mode)); + break; + } + default: + msg_print("hoge?"); + } + + return TRUE; +} + +/*! + * @brief ものまねコマンドのメインルーチン / + * do_cmd_cast calls this function if the player's class is 'imitator'. + * @param baigaesi TRUEならば倍返し上の処理として行う + * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。 + * @details + * If a valid spell is chosen, saves it in '*sn' and returns TRUE + * If the user hits escape, returns FALSE, and set '*sn' to -1 + * If there are no legal choices, returns FALSE, and sets '*sn' to -2 + * + * The "prompt" should be "cast", "recite", or "study" + * The "known" should be TRUE for cast/pray, FALSE for study + * + * nb: This function has a (trivial) display bug which will be obvious + * when you run it. It's probably easy to fix but I haven't tried, + * sorry. + */ +bool do_cmd_mane(player_type *creature_ptr, bool baigaesi) +{ + int n = 0, j; + PERCENTAGE chance; + PERCENTAGE minfail = 0; + PLAYER_LEVEL plev = creature_ptr->lev; + monster_power spell; + bool cast; + + if (cmd_limit_confused(creature_ptr)) + return FALSE; + + if (!creature_ptr->mane_num) { + msg_print(_("まねられるものが何もない!", "You don't remember any action!")); + return FALSE; + } + + if (!get_mane_power(creature_ptr, &n, baigaesi)) + return FALSE; + + spell = monster_powers[creature_ptr->mane_spell[n]]; + + /* Spell failure chance */ + chance = spell.manefail; + + /* Reduce failure rate by "effective" level adjustment */ + if (plev > spell.level) + chance -= 3 * (plev - spell.level); + + /* Reduce failure rate by 1 stat and DEX adjustment */ + chance -= 3 * (adj_mag_stat[creature_ptr->stat_ind[spell.use_stat]] + adj_mag_stat[creature_ptr->stat_ind[A_DEX]] - 2) / 2; + + if (spell.manedam) + chance = chance * damage / spell.manedam; + + chance += creature_ptr->to_m_chance; + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[creature_ptr->stat_ind[spell.use_stat]]; + + /* Minimum failure rate */ + if (chance < minfail) + chance = minfail; + + /* Stunning makes spells harder */ + if (creature_ptr->stun > 50) + chance += 25; + else if (creature_ptr->stun) + chance += 15; + + /* Always a 5 percent chance of working */ + if (chance > 95) + chance = 95; + + /* Failed spell */ + if (randint0(100) < chance) { + if (flush_failure) + flush(); + msg_print(_("ものまねに失敗した!", "You failed to concentrate hard enough!")); + sound(SOUND_FAIL); + } else { + sound(SOUND_ZAP); + cast = use_mane(creature_ptr, creature_ptr->mane_spell[n]); + if (!cast) + return FALSE; + } + + creature_ptr->mane_num--; + for (j = n; j < creature_ptr->mane_num; j++) { + creature_ptr->mane_spell[j] = creature_ptr->mane_spell[j + 1]; + creature_ptr->mane_dam[j] = creature_ptr->mane_dam[j + 1]; + } + + take_turn(creature_ptr, 100); + + creature_ptr->redraw |= (PR_IMITATION); + creature_ptr->window |= (PW_PLAYER); + creature_ptr->window |= (PW_SPELL); + + return TRUE; +} diff --git a/src/cmd-action/cmd-mane.h b/src/cmd-action/cmd-mane.h new file mode 100644 index 000000000..89218cec5 --- /dev/null +++ b/src/cmd-action/cmd-mane.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool do_cmd_mane(player_type *creature_ptr, bool baigaesi); diff --git a/src/cmd-action/cmd-mind.c b/src/cmd-action/cmd-mind.c new file mode 100644 index 000000000..81101df98 --- /dev/null +++ b/src/cmd-action/cmd-mind.c @@ -0,0 +1,442 @@ +/*! + * @brief 各職業の特殊技能実装 / Special magics + * @date 2014/01/15 + * @author + * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n + * This software may be copied and distributed for educational, research,\n + * and not for profit purposes provided that this copyright and statement\n + * are included in all such copies. Other copyrights may also apply.\n + * 2005 henkma \n + * 2014 Deskull rearranged comment for Doxygen.\n + */ + +#include "cmd-action/cmd-mind.h" +#include "action/action-limited.h" +#include "core/asking-player.h" +#include "core/player-redraw-types.h" +#include "core/window-redrawer.h" +#include "effect/effect-characteristics.h" +#include "effect/effect-processor.h" +#include "game-option/disturbance-options.h" +#include "game-option/input-options.h" +#include "grid/grid.h" +#include "inventory/inventory-slot-types.h" +#include "io/input-key-acceptor.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "mind/mind-berserker.h" +#include "mind/mind-explanations-table.h" +#include "mind/mind-force-trainer.h" +#include "mind/mind-mindcrafter.h" +#include "mind/mind-mirror-master.h" +#include "mind/mind-ninja.h" +#include "mind/mind-numbers.h" +#include "mind/mind-power-getter.h" +#include "mind/mind-types.h" +#include "player/player-class.h" +#include "player/player-damage.h" +#include "spell-kind/spells-teleport.h" +#include "player/player-status-table.h" +#include "spell/spell-types.h" +#include "status/bad-status-setter.h" +#include "status/base-status.h" +#include "system/floor-type-definition.h" +#include "term/screen-processor.h" +#include "util/buffer-shaper.h" +#include "view/display-messages.h" + +typedef struct cm_type { + mind_kind_type use_mind; + concptr mind_explanation; + SPELL_IDX n; + int b; + PERCENTAGE chance; + PERCENTAGE minfail; + PLAYER_LEVEL plev; + int old_csp; + mind_type spell; + bool cast; + int mana_cost; + bool on_mirror; +} cm_type; + +static cm_type *initialize_cm_type(player_type *caster_ptr, cm_type *cm_ptr) +{ + cm_ptr->n = 0; + cm_ptr->b = 0; + cm_ptr->minfail = 0; + cm_ptr->plev = caster_ptr->lev; + cm_ptr->old_csp = caster_ptr->csp; + cm_ptr->on_mirror = FALSE; + return cm_ptr; +} + +static void switch_mind_kind(player_type *caster_ptr, cm_type *cm_ptr) +{ + switch (caster_ptr->pclass) { + case CLASS_MINDCRAFTER: + cm_ptr->use_mind = MIND_MINDCRAFTER; + cm_ptr->mind_explanation = _("精神", "skill"); + break; + case CLASS_FORCETRAINER: + cm_ptr->use_mind = MIND_KI; + cm_ptr->mind_explanation = _("気", "skill"); + break; + case CLASS_BERSERKER: + cm_ptr->use_mind = MIND_BERSERKER; + cm_ptr->mind_explanation = _("怒り", "skill"); + break; + case CLASS_MIRROR_MASTER: + cm_ptr->use_mind = MIND_MIRROR_MASTER; + cm_ptr->mind_explanation = _("鏡魔法", "skill"); + break; + case CLASS_NINJA: + cm_ptr->use_mind = MIND_NINJUTSU; + cm_ptr->mind_explanation = _("精神", "skill"); + break; + default: + cm_ptr->use_mind = (mind_kind_type)0; + cm_ptr->mind_explanation = _("超能力", "skill"); + break; + } +} + +static void decide_mind_ki_chance(player_type *caster_ptr, cm_type *cm_ptr) +{ + if (cm_ptr->use_mind != MIND_KI) + return; + + if (heavy_armor(caster_ptr)) + cm_ptr->chance += 20; + + if (caster_ptr->icky_wield[0]) + cm_ptr->chance += 20; + else if (has_melee_weapon(caster_ptr, INVEN_RARM)) + cm_ptr->chance += 10; + + if (caster_ptr->icky_wield[1]) + cm_ptr->chance += 20; + else if (has_melee_weapon(caster_ptr, INVEN_LARM)) + cm_ptr->chance += 10; + + if (cm_ptr->n == 5) + for (int j = 0; j < get_current_ki(caster_ptr) / 50; j++) + cm_ptr->mana_cost += (j + 1) * 3 / 2; +} + +static bool check_mind_hp_mp_sufficiency(player_type *caster_ptr, cm_type *cm_ptr) +{ + if ((cm_ptr->use_mind == MIND_BERSERKER) || (cm_ptr->use_mind == MIND_NINJUTSU)) { + if (cm_ptr->mana_cost > caster_ptr->chp) { + msg_print(_("HPが足りません。", "You do not have enough hp to use this power.")); + return FALSE; + } + + return TRUE; + } + + if (cm_ptr->mana_cost <= caster_ptr->csp) + return TRUE; + + msg_print(_("MPが足りません。", "You do not have enough mana to use this power.")); + if (!over_exert) + return FALSE; + + return get_check(_("それでも挑戦しますか? ", "Attempt it anyway? ")); +} + +static void decide_mind_chance(player_type *caster_ptr, cm_type *cm_ptr) +{ + if (cm_ptr->chance == 0) + return; + + cm_ptr->chance -= 3 * (cm_ptr->plev - cm_ptr->spell.min_lev); + cm_ptr->chance += caster_ptr->to_m_chance; + cm_ptr->chance -= 3 * (adj_mag_stat[caster_ptr->stat_ind[mp_ptr->spell_stat]] - 1); + if ((cm_ptr->mana_cost > caster_ptr->csp) && (cm_ptr->use_mind != MIND_BERSERKER) && (cm_ptr->use_mind != MIND_NINJUTSU)) + cm_ptr->chance += 5 * (cm_ptr->mana_cost - caster_ptr->csp); + + cm_ptr->minfail = adj_mag_fail[caster_ptr->stat_ind[mp_ptr->spell_stat]]; + if (cm_ptr->chance < cm_ptr->minfail) + cm_ptr->chance = cm_ptr->minfail; + + if (caster_ptr->stun > 50) + cm_ptr->chance += 25; + else if (caster_ptr->stun) + cm_ptr->chance += 15; + + if (cm_ptr->use_mind != MIND_KI) + return; + + if (heavy_armor(caster_ptr)) + cm_ptr->chance += 5; + + if (caster_ptr->icky_wield[0]) + cm_ptr->chance += 5; + + if (caster_ptr->icky_wield[1]) + cm_ptr->chance += 5; +} + +static void check_mind_mindcrafter(player_type *caster_ptr, cm_type *cm_ptr) +{ + if (cm_ptr->use_mind != MIND_MINDCRAFTER) + return; + + if (cm_ptr->b < 5) { + msg_print(_("なんてこった!頭の中が真っ白になった!", "Oh, no! Your mind has gone blank!")); + lose_all_info(caster_ptr); + return; + } + + if (cm_ptr->b < 15) { + msg_print(_("奇妙な光景が目の前で踊っている...", "Weird visions seem to dance before your eyes...")); + set_image(caster_ptr, caster_ptr->image + 5 + randint1(10)); + return; + } + + if (cm_ptr->b < 45) { + msg_print(_("あなたの頭は混乱した!", "Your brain is addled!")); + set_confused(caster_ptr, caster_ptr->confused + randint1(8)); + return; + } + + if (cm_ptr->b < 90) { + set_stun(caster_ptr, caster_ptr->stun + randint1(8)); + return; + } + + msg_format(_("%sの力が制御できない氾流となって解放された!", "Your mind unleashes its power in an uncontrollable storm!"), cm_ptr->mind_explanation); + project(caster_ptr, PROJECT_WHO_UNCTRL_POWER, 2 + cm_ptr->plev / 10, caster_ptr->y, caster_ptr->x, cm_ptr->plev * 2, GF_MANA, + PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM, -1); + caster_ptr->csp = MAX(0, caster_ptr->csp - cm_ptr->plev * MAX(1, cm_ptr->plev / 10)); +} + +static void check_mind_mirror_master(player_type *caster_ptr, cm_type *cm_ptr) +{ + if (cm_ptr->use_mind != MIND_MIRROR_MASTER) + return; + + if (cm_ptr->b < 51) + return; + + if (cm_ptr->b < 81) { + msg_print(_("鏡の世界の干渉を受けた!", "Weird visions seem to dance before your eyes...")); + teleport_player(caster_ptr, 10, TELEPORT_PASSIVE); + return; + } + + if (cm_ptr->b < 96) { + msg_print(_("まわりのものがキラキラ輝いている!", "Your brain is addled!")); + set_image(caster_ptr, caster_ptr->image + 5 + randint1(10)); + return; + } + + msg_format(_("%sの力が制御できない氾流となって解放された!", "Your mind unleashes its power in an uncontrollable storm!"), cm_ptr->mind_explanation); + project(caster_ptr, PROJECT_WHO_UNCTRL_POWER, 2 + cm_ptr->plev / 10, caster_ptr->y, caster_ptr->x, cm_ptr->plev * 2, GF_MANA, + PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM, -1); + caster_ptr->csp = MAX(0, caster_ptr->csp - cm_ptr->plev * MAX(1, cm_ptr->plev / 10)); +} + +static void check_mind_class(player_type *caster_ptr, cm_type *cm_ptr) +{ + if ((cm_ptr->use_mind == MIND_BERSERKER) || (cm_ptr->use_mind == MIND_NINJUTSU)) + return; + + if ((cm_ptr->use_mind == MIND_KI) && (cm_ptr->n != 5) && get_current_ki(caster_ptr)) { + msg_print(_("気が散ってしまった...", "Your improved Force has gone away...")); + set_current_ki(caster_ptr, TRUE, 0); + } + + if (randint1(100) >= (cm_ptr->chance / 2)) + return; + + cm_ptr->b = randint1(100); + check_mind_mindcrafter(caster_ptr, cm_ptr); + check_mind_mirror_master(caster_ptr, cm_ptr); +} + +static bool switch_mind_class(player_type *caster_ptr, cm_type *cm_ptr) +{ + switch (cm_ptr->use_mind) { + case MIND_MINDCRAFTER: + cm_ptr->cast = cast_mindcrafter_spell(caster_ptr, cm_ptr->n); + return TRUE; + case MIND_KI: + cm_ptr->cast = cast_force_spell(caster_ptr, cm_ptr->n); + return TRUE; + case MIND_BERSERKER: + cm_ptr->cast = cast_berserk_spell(caster_ptr, cm_ptr->n); + return TRUE; + case MIND_MIRROR_MASTER: + if (is_mirror_grid(&caster_ptr->current_floor_ptr->grid_array[caster_ptr->y][caster_ptr->x])) + cm_ptr->on_mirror = TRUE; + + cm_ptr->cast = cast_mirror_spell(caster_ptr, cm_ptr->n); + return TRUE; + case MIND_NINJUTSU: + cm_ptr->cast = cast_ninja_spell(caster_ptr, cm_ptr->n); + return TRUE; + default: + msg_format(_("謎の能力:%d, %d", "Mystery power:%d, %d"), cm_ptr->use_mind, cm_ptr->n); + return FALSE; + } +} + +static void mind_turn_passing(player_type *caster_ptr, cm_type *cm_ptr) +{ + if (!cm_ptr->on_mirror || (caster_ptr->pclass != CLASS_MIRROR_MASTER)) { + take_turn(caster_ptr, 100); + return; + } + + if (cm_ptr->n == 3 || cm_ptr->n == 5 || cm_ptr->n == 7 || cm_ptr->n == 16) + take_turn(caster_ptr, 50); +} + +static bool judge_mind_chance(player_type *caster_ptr, cm_type *cm_ptr) +{ + if (randint0(100) >= cm_ptr->chance) { + sound(SOUND_ZAP); + return switch_mind_class(caster_ptr, cm_ptr) && cm_ptr->cast; + } + + if (flush_failure) + flush(); + + msg_format(_("%sの集中に失敗した!", "You failed to concentrate hard enough for %s!"), cm_ptr->mind_explanation); + sound(SOUND_FAIL); + check_mind_class(caster_ptr, cm_ptr); + return TRUE; +} + +static void mind_reflection(player_type *caster_ptr, cm_type *cm_ptr) +{ + int oops = cm_ptr->mana_cost - cm_ptr->old_csp; + if ((caster_ptr->csp - cm_ptr->mana_cost) < 0) + caster_ptr->csp_frac = 0; + + caster_ptr->csp = MAX(0, caster_ptr->csp - cm_ptr->mana_cost); + msg_format(_("%sを集中しすぎて気を失ってしまった!", "You faint from the effort!"), cm_ptr->mind_explanation); + (void)set_paralyzed(caster_ptr, caster_ptr->paralyzed + randint1(5 * oops + 1)); + if (randint0(100) >= 50) + return; + + bool perm = randint0(100) < 25; + msg_print(_("自分の精神を攻撃してしまった!", "You have damaged your mind!")); + (void)dec_stat(caster_ptr, A_WIS, 15 + randint1(10), perm); +} + +static void process_hard_concentration(player_type *caster_ptr, cm_type *cm_ptr) +{ + if ((cm_ptr->use_mind == MIND_BERSERKER) || (cm_ptr->use_mind == MIND_NINJUTSU)) { + take_hit(caster_ptr, DAMAGE_USELIFE, cm_ptr->mana_cost, _("過度の集中", "concentrating too hard"), -1); + caster_ptr->redraw |= PR_HP; + return; + } + + if (cm_ptr->mana_cost > cm_ptr->old_csp) { + mind_reflection(caster_ptr, cm_ptr); + return; + } + + caster_ptr->csp -= cm_ptr->mana_cost; + if (caster_ptr->csp < 0) + caster_ptr->csp = 0; + + if ((cm_ptr->use_mind == MIND_MINDCRAFTER) && (cm_ptr->n == 13)) { + caster_ptr->csp = 0; + caster_ptr->csp_frac = 0; + } +} + +/*! + * @brief 特殊技能コマンドのメインルーチン / + * @return なし + */ +void do_cmd_mind(player_type *caster_ptr) +{ + cm_type tmp_cm; + cm_type *cm_ptr = initialize_cm_type(caster_ptr, &tmp_cm); + if (cmd_limit_confused(caster_ptr) || !get_mind_power(caster_ptr, &cm_ptr->n, FALSE)) + return; + + switch_mind_kind(caster_ptr, cm_ptr); + cm_ptr->spell = mind_powers[cm_ptr->use_mind].info[cm_ptr->n]; + cm_ptr->chance = cm_ptr->spell.fail; + cm_ptr->mana_cost = cm_ptr->spell.mana_cost; + decide_mind_ki_chance(caster_ptr, cm_ptr); + if (!check_mind_hp_mp_sufficiency(caster_ptr, cm_ptr)) + return; + + decide_mind_chance(caster_ptr, cm_ptr); + if (cm_ptr->chance > 95) + cm_ptr->chance = 95; + + if (!judge_mind_chance(caster_ptr, cm_ptr)) + return; + + mind_turn_passing(caster_ptr, cm_ptr); + process_hard_concentration(caster_ptr, cm_ptr); + caster_ptr->redraw |= PR_MANA; + caster_ptr->window |= PW_PLAYER; + caster_ptr->window |= PW_SPELL; +} + +static mind_kind_type decide_use_mind_browse(player_type *caster_ptr) +{ + switch (caster_ptr->pclass) { + case CLASS_MINDCRAFTER: + return MIND_MINDCRAFTER; + case CLASS_FORCETRAINER: + return MIND_KI; + case CLASS_BERSERKER: + return MIND_BERSERKER; + case CLASS_NINJA: + return MIND_NINJUTSU; + case CLASS_MIRROR_MASTER: + return MIND_MIRROR_MASTER; + default: + return (mind_kind_type)0; // 実質CLASS_MINDCRAFTERと同じ. + } +} + +/*! + * @brief 現在プレイヤーが使用可能な特殊技能の一覧表示 / + * @return なし + */ +void do_cmd_mind_browse(player_type *caster_ptr) +{ + SPELL_IDX n = 0; + char temp[62 * 5]; + mind_kind_type use_mind = decide_use_mind_browse(caster_ptr); + screen_save(); + while (TRUE) { + if (!get_mind_power(caster_ptr, &n, TRUE)) { + screen_load(); + return; + } + + term_erase(12, 21, 255); + term_erase(12, 20, 255); + term_erase(12, 19, 255); + term_erase(12, 18, 255); + term_erase(12, 17, 255); + term_erase(12, 16, 255); + shape_buffer(mind_tips[use_mind][n], 62, temp, sizeof(temp)); + for (int j = 0, line = 17; temp[j]; j += (1 + strlen(&temp[j]))) { + prt(&temp[j], line, 15); + line++; + } + + switch (use_mind) { + case MIND_MIRROR_MASTER: + case MIND_NINJUTSU: + prt(_("何かキーを押して下さい。", "Hit any key."), 0, 0); + (void)inkey(); + break; + default: + break; + } + } +} diff --git a/src/cmd-action/cmd-mind.h b/src/cmd-action/cmd-mind.h new file mode 100644 index 000000000..cdc092f53 --- /dev/null +++ b/src/cmd-action/cmd-mind.h @@ -0,0 +1,8 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_mind(player_type *caster_ptr); +void do_cmd_mind_browse(player_type *caster_ptr); +void do_cmd_mind_browse(player_type *caster_ptr); + diff --git a/src/cmd-action/cmd-move.c b/src/cmd-action/cmd-move.c new file mode 100644 index 000000000..1ff204525 --- /dev/null +++ b/src/cmd-action/cmd-move.c @@ -0,0 +1,429 @@ +#include "cmd-action/cmd-move.h" +#include "action/action-limited.h" +#include "action/movement-execution.h" +#include "action/run-execution.h" +#include "cmd-io/cmd-save.h" +#include "core/asking-player.h" +#include "core/disturbance.h" +#include "core/output-updater.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "dungeon/dungeon.h" +#include "dungeon/quest.h" +#include "floor/cave.h" +#include "floor/floor-mode-changer.h" +#include "floor/wild.h" +#include "game-option/birth-options.h" +#include "game-option/input-options.h" +#include "game-option/play-record-options.h" +#include "game-option/special-options.h" +#include "grid/grid.h" +#include "info-reader/fixed-map-parser.h" +#include "io/input-key-requester.h" +#include "io/write-diary.h" +#include "mind/mind-ninja.h" +#include "player/attack-defense-types.h" +#include "player-info/avatar.h" +#include "player/player-move.h" +#include "player/special-defense-types.h" +#include "spell-realm/spells-hex.h" +#include "status/action-setter.h" +#include "system/floor-type-definition.h" +#include "system/system-variables.h" +#include "target/target-getter.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" + +/*! + * @brief フロア脱出時に出戻りが不可能だった場合に警告を加える処理 + * @param down_stair TRUEならば階段を降りる処理、FALSEなら階段を昇る処理による内容 + * @return フロア移動を実際に行うならTRUE、キャンセルする場合はFALSE + */ +static bool confirm_leave_level(player_type *creature_ptr, bool down_stair) +{ + quest_type *q_ptr = &quest[creature_ptr->current_floor_ptr->inside_quest]; + if (confirm_quest && creature_ptr->current_floor_ptr->inside_quest + && (q_ptr->type == QUEST_TYPE_RANDOM || (q_ptr->flags & QUEST_FLAG_ONCE && q_ptr->status != QUEST_STATUS_COMPLETED) + || (q_ptr->flags & QUEST_FLAG_TOWER + && ((q_ptr->status != QUEST_STATUS_STAGE_COMPLETED) || (down_stair && (quest[QUEST_TOWER1].status != QUEST_STATUS_COMPLETED)))))) { + msg_print(_("この階を一度去ると二度と戻って来られません。", "You can't come back here once you leave this floor.")); + return get_check(_("本当にこの階を去りますか?", "Really leave this floor? ")); + } + + return TRUE; +} + +/*! + * @brief 階段を使って階層を昇る処理 / Go up one level + * @return なし + */ +void do_cmd_go_up(player_type *creature_ptr) +{ + bool go_up = FALSE; + grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x]; + feature_type *f_ptr = &f_info[g_ptr->feat]; + int up_num = 0; + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + if (!have_flag(f_ptr->flags, FF_LESS)) { + msg_print(_("ここには上り階段が見当たらない。", "I see no up staircase here.")); + return; + } + + if (have_flag(f_ptr->flags, FF_QUEST)) { + if (!confirm_leave_level(creature_ptr, FALSE)) + return; + + if (is_echizen(creature_ptr)) + msg_print(_("なんだこの階段は!", "What's this STAIRWAY!")); + else + msg_print(_("上の階に登った。", "You enter the up staircase.")); + + leave_quest_check(creature_ptr); + creature_ptr->current_floor_ptr->inside_quest = g_ptr->special; + if (!quest[creature_ptr->current_floor_ptr->inside_quest].status) { + if (quest[creature_ptr->current_floor_ptr->inside_quest].type != QUEST_TYPE_RANDOM) { + init_flags = INIT_ASSIGN; + parse_fixed_map(creature_ptr, "q_info.txt", 0, 0, 0, 0); + } + + quest[creature_ptr->current_floor_ptr->inside_quest].status = QUEST_STATUS_TAKEN; + } + + if (!creature_ptr->current_floor_ptr->inside_quest) + creature_ptr->current_floor_ptr->dun_level = 0; + + creature_ptr->leaving = TRUE; + creature_ptr->oldpx = 0; + creature_ptr->oldpy = 0; + take_turn(creature_ptr, 100); + return; + } + + if (!creature_ptr->current_floor_ptr->dun_level) + go_up = TRUE; + else + go_up = confirm_leave_level(creature_ptr, FALSE); + + if (!go_up) + return; + + take_turn(creature_ptr, 100); + + if (autosave_l) + do_cmd_save_game(creature_ptr, TRUE); + + if (creature_ptr->current_floor_ptr->inside_quest && quest[creature_ptr->current_floor_ptr->inside_quest].type == QUEST_TYPE_RANDOM) { + leave_quest_check(creature_ptr); + creature_ptr->current_floor_ptr->inside_quest = 0; + } + + if (creature_ptr->current_floor_ptr->inside_quest && quest[creature_ptr->current_floor_ptr->inside_quest].type != QUEST_TYPE_RANDOM) { + leave_quest_check(creature_ptr); + creature_ptr->current_floor_ptr->inside_quest = g_ptr->special; + creature_ptr->current_floor_ptr->dun_level = 0; + up_num = 0; + } else { + if (have_flag(f_ptr->flags, FF_SHAFT)) { + prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_UP | CFM_SHAFT); + up_num = 2; + } else { + prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_UP); + up_num = 1; + } + + if (creature_ptr->current_floor_ptr->dun_level - up_num < d_info[creature_ptr->dungeon_idx].mindepth) + up_num = creature_ptr->current_floor_ptr->dun_level; + } + + if (record_stair) + exe_write_diary(creature_ptr, DIARY_STAIR, 0 - up_num, _("階段を上った", "climbed up the stairs to")); + + if (is_echizen(creature_ptr)) + msg_print(_("なんだこの階段は!", "What's this STAIRWAY!")); + else if (up_num == creature_ptr->current_floor_ptr->dun_level) + msg_print(_("地上に戻った。", "You go back to the surface.")); + else + msg_print(_("階段を上って新たなる迷宮へと足を踏み入れた。", "You enter a maze of up staircases.")); + + creature_ptr->leaving = TRUE; +} + +/*! + * @brief 階段を使って階層を降りる処理 / Go down one level + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void do_cmd_go_down(player_type *creature_ptr) +{ + bool fall_trap = FALSE; + int down_num = 0; + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x]; + feature_type *f_ptr = &f_info[g_ptr->feat]; + if (!have_flag(f_ptr->flags, FF_MORE)) { + msg_print(_("ここには下り階段が見当たらない。", "I see no down staircase here.")); + return; + } + + if (have_flag(f_ptr->flags, FF_TRAP)) + fall_trap = TRUE; + + if (have_flag(f_ptr->flags, FF_QUEST_ENTER)) { + do_cmd_quest(creature_ptr); + return; + } + + if (have_flag(f_ptr->flags, FF_QUEST)) { + if (!confirm_leave_level(creature_ptr, TRUE)) + return; + + if (is_echizen(creature_ptr)) + msg_print(_("なんだこの階段は!", "What's this STAIRWAY!")); + else + msg_print(_("下の階に降りた。", "You enter the down staircase.")); + + leave_quest_check(creature_ptr); + leave_tower_check(creature_ptr); + creature_ptr->current_floor_ptr->inside_quest = g_ptr->special; + if (!quest[creature_ptr->current_floor_ptr->inside_quest].status) { + if (quest[creature_ptr->current_floor_ptr->inside_quest].type != QUEST_TYPE_RANDOM) { + init_flags = INIT_ASSIGN; + parse_fixed_map(creature_ptr, "q_info.txt", 0, 0, 0, 0); + } + + quest[creature_ptr->current_floor_ptr->inside_quest].status = QUEST_STATUS_TAKEN; + } + + if (!creature_ptr->current_floor_ptr->inside_quest) + creature_ptr->current_floor_ptr->dun_level = 0; + + creature_ptr->leaving = TRUE; + creature_ptr->oldpx = 0; + creature_ptr->oldpy = 0; + take_turn(creature_ptr, 100); + return; + } + + DUNGEON_IDX target_dungeon = 0; + if (!creature_ptr->current_floor_ptr->dun_level) { + target_dungeon = have_flag(f_ptr->flags, FF_ENTRANCE) ? g_ptr->special : DUNGEON_ANGBAND; + if (ironman_downward && (target_dungeon != DUNGEON_ANGBAND)) { + msg_print(_("ダンジョンの入口は塞がれている!", "The entrance of this dungeon is closed!")); + return; + } + + if (!max_dlv[target_dungeon]) { + msg_format(_("ここには%sの入り口(%d階相当)があります", "There is the entrance of %s (Danger level: %d)"), d_name + d_info[target_dungeon].name, + d_info[target_dungeon].mindepth); + if (!get_check(_("本当にこのダンジョンに入りますか?", "Do you really get in this dungeon? "))) + return; + } + + creature_ptr->oldpx = creature_ptr->x; + creature_ptr->oldpy = creature_ptr->y; + creature_ptr->dungeon_idx = target_dungeon; + prepare_change_floor_mode(creature_ptr, CFM_FIRST_FLOOR); + } + + take_turn(creature_ptr, 100); + if (autosave_l) + do_cmd_save_game(creature_ptr, TRUE); + + if (have_flag(f_ptr->flags, FF_SHAFT)) + down_num += 2; + else + down_num += 1; + + if (!creature_ptr->current_floor_ptr->dun_level) { + creature_ptr->enter_dungeon = TRUE; + down_num = d_info[creature_ptr->dungeon_idx].mindepth; + } + + if (record_stair) { + if (fall_trap) + exe_write_diary(creature_ptr, DIARY_STAIR, down_num, _("落とし戸に落ちた", "fell through a trap door")); + else + exe_write_diary(creature_ptr, DIARY_STAIR, down_num, _("階段を下りた", "climbed down the stairs to")); + } + + if (fall_trap) { + msg_print(_("わざと落とし戸に落ちた。", "You deliberately jump through the trap door.")); + } else { + if (target_dungeon) { + msg_format(_("%sへ入った。", "You entered %s."), d_text + d_info[creature_ptr->dungeon_idx].text); + } else { + if (is_echizen(creature_ptr)) + msg_print(_("なんだこの階段は!", "What's this STAIRWAY!")); + else + msg_print(_("階段を下りて新たなる迷宮へと足を踏み入れた。", "You enter a maze of down staircases.")); + } + } + + creature_ptr->leaving = TRUE; + + if (fall_trap) { + prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_DOWN | CFM_RAND_PLACE | CFM_RAND_CONNECT); + return; + } + + if (have_flag(f_ptr->flags, FF_SHAFT)) + prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_DOWN | CFM_SHAFT); + else + prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_DOWN); +} + +/*! + * @brief 「歩く」動作コマンドのメインルーチン / + * Support code for the "Walk" and "Jump" commands + * @param creature_ptr プレーヤーへの参照ポインタ + * @param pickup アイテムの自動拾いを行うならTRUE + * @return なし + */ +void do_cmd_walk(player_type *creature_ptr, bool pickup) +{ + if (command_arg) { + command_rep = command_arg - 1; + creature_ptr->redraw |= PR_STATE; + command_arg = 0; + } + + bool more = FALSE; + DIRECTION dir; + if (get_rep_dir(creature_ptr, &dir, FALSE)) { + take_turn(creature_ptr, 100); + if ((dir != 5) && (creature_ptr->special_defense & KATA_MUSOU)) + set_action(creature_ptr, ACTION_NONE); + + if (creature_ptr->wild_mode) + creature_ptr->energy_use *= ((MAX_HGT + MAX_WID) / 2); + + if (creature_ptr->action == ACTION_HAYAGAKE) + creature_ptr->energy_use = creature_ptr->energy_use * (45 - (creature_ptr->lev / 2)) / 100; + + exe_movement(creature_ptr, dir, pickup, FALSE); + more = TRUE; + } + + if (creature_ptr->wild_mode && !cave_have_flag_bold(creature_ptr->current_floor_ptr, creature_ptr->y, creature_ptr->x, FF_TOWN)) { + int tmp = 120 + creature_ptr->lev * 10 - wilderness[creature_ptr->y][creature_ptr->x].level + 5; + if (tmp < 1) + tmp = 1; + + if (((wilderness[creature_ptr->y][creature_ptr->x].level + 5) > (creature_ptr->lev / 2)) && randint0(tmp) < (21 - creature_ptr->skill_stl)) { + msg_print(_("襲撃だ!", "You are ambushed !")); + creature_ptr->oldpy = randint1(MAX_HGT - 2); + creature_ptr->oldpx = randint1(MAX_WID - 2); + change_wild_mode(creature_ptr, TRUE); + take_turn(creature_ptr, 100); + } + } + + if (!more) + disturb(creature_ptr, FALSE, FALSE); +} + +/*! + * @brief 「走る」動作コマンドのメインルーチン / + * Start running. + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void do_cmd_run(player_type *creature_ptr) +{ + DIRECTION dir; + if (cmd_limit_confused(creature_ptr)) + return; + + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + if (get_rep_dir(creature_ptr, &dir, FALSE)) { + creature_ptr->running = (command_arg ? command_arg : 1000); + run_step(creature_ptr, dir); + } +} + +/*! + * @brief 「留まる」動作コマンドのメインルーチン / + * Stay still. Search. Enter stores. + * Pick up treasure if "pickup" is true. + * @param creature_ptr プレーヤーへの参照ポインタ + * @param pickup アイテムの自動拾いを行うならTRUE + * @return なし + */ +void do_cmd_stay(player_type *creature_ptr, bool pickup) +{ + u32b mpe_mode = MPE_STAYING | MPE_ENERGY_USE; + if (command_arg) { + command_rep = command_arg - 1; + creature_ptr->redraw |= (PR_STATE); + command_arg = 0; + } + + take_turn(creature_ptr, 100); + if (pickup) + mpe_mode |= MPE_DO_PICKUP; + + (void)move_player_effect(creature_ptr, creature_ptr->y, creature_ptr->x, mpe_mode); +} + +/*! + * @brief 「休む」動作コマンドのメインルーチン / + * Resting allows a player to safely restore his hp -RAK- + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void do_cmd_rest(player_type *creature_ptr) +{ + set_action(creature_ptr, ACTION_NONE); + if ((creature_ptr->pclass == CLASS_BARD) && (SINGING_SONG_EFFECT(creature_ptr) || INTERUPTING_SONG_EFFECT(creature_ptr))) + stop_singing(creature_ptr); + + if (hex_spelling_any(creature_ptr)) + stop_hex_spell_all(creature_ptr); + + if (command_arg <= 0) { + concptr p = _("休憩 (0-9999, '*' で HP/MP全快, '&' で必要なだけ): ", "Rest (0-9999, '*' for HP/SP, '&' as needed): "); + char out_val[80]; + strcpy(out_val, "&"); + if (!get_string(p, out_val, 4)) + return; + + if (out_val[0] == '&') { + command_arg = COMMAND_ARG_REST_UNTIL_DONE; + } else if (out_val[0] == '*') { + command_arg = COMMAND_ARG_REST_FULL_HEALING; + } else { + command_arg = (COMMAND_ARG)atoi(out_val); + if (command_arg <= 0) + return; + } + } + + if (command_arg > 9999) + command_arg = 9999; + + if (creature_ptr->special_defense & NINJA_S_STEALTH) + set_superstealth(creature_ptr, FALSE); + + take_turn(creature_ptr, 100); + if (command_arg > 100) + chg_virtue(creature_ptr, V_DILIGENCE, -1); + + if ((creature_ptr->chp == creature_ptr->mhp) && (creature_ptr->csp == creature_ptr->msp) && !creature_ptr->blind && !creature_ptr->confused + && !creature_ptr->poisoned && !creature_ptr->afraid && !creature_ptr->stun && !creature_ptr->cut && !creature_ptr->slow && !creature_ptr->paralyzed + && !creature_ptr->image && !creature_ptr->word_recall && !creature_ptr->alter_reality) + chg_virtue(creature_ptr, V_DILIGENCE, -1); + + creature_ptr->resting = command_arg; + creature_ptr->action = ACTION_REST; + creature_ptr->update |= PU_BONUS; + update_creature(creature_ptr); + creature_ptr->redraw |= (PR_STATE); + update_output(creature_ptr); + term_fresh(); +} diff --git a/src/cmd-action/cmd-move.h b/src/cmd-action/cmd-move.h new file mode 100644 index 000000000..97d8aead9 --- /dev/null +++ b/src/cmd-action/cmd-move.h @@ -0,0 +1,10 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_go_up(player_type *creature_ptr); +void do_cmd_go_down(player_type *creature_ptr); +void do_cmd_walk(player_type *creature_ptr, bool pickup); +void do_cmd_run(player_type *creature_ptr); +void do_cmd_stay(player_type *creature_ptr, bool pickup); +void do_cmd_rest(player_type *creature_ptr); diff --git a/src/cmd-action/cmd-open-close.c b/src/cmd-action/cmd-open-close.c new file mode 100644 index 000000000..d94fbe8fe --- /dev/null +++ b/src/cmd-action/cmd-open-close.c @@ -0,0 +1,368 @@ +#include "cmd-action/cmd-open-close.h" +#include "action/open-close-execution.h" +#include "action/open-util.h" +#include "cmd-action/cmd-attack.h" +#include "core/disturbance.h" +#include "core/player-redraw-types.h" +#include "game-option/disturbance-options.h" +#include "game-option/input-options.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "inventory/inventory-object.h" +#include "inventory/inventory-slot-types.h" +#include "io/input-key-requester.h" +#include "player/attack-defense-types.h" +#include "player/special-defense-types.h" +#include "specific-object/chest.h" +#include "status/action-setter.h" +#include "status/experience.h" +#include "system/floor-type-definition.h" +#include "system/object-type-definition.h" +#include "target/target-getter.h" +#include "term/screen-processor.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" + +/*! + * @brief 箱を開ける実行処理 / + * Attempt to open the given chest at the given location + * @param y 箱の存在するマスのY座標 + * @param x 箱の存在するマスのX座標 + * @param o_idx 箱のオブジェクトID + * @return 箱が開かなかった場合TRUE / Returns TRUE if repeated commands may continue + * @details + * Assume there is no monster blocking the destination + */ +static bool exe_open_chest(player_type *creature_ptr, POSITION y, POSITION x, OBJECT_IDX o_idx) +{ + bool flag = TRUE; + bool more = FALSE; + object_type *o_ptr = &creature_ptr->current_floor_ptr->o_list[o_idx]; + take_turn(creature_ptr, 100); + if (o_ptr->pval > 0) { + flag = FALSE; + int i = creature_ptr->skill_dis; + if (creature_ptr->blind || no_lite(creature_ptr)) + i = i / 10; + + if (creature_ptr->confused || creature_ptr->image) + i = i / 10; + + int j = i - o_ptr->pval; + if (j < 2) + j = 2; + + if (randint0(100) < j) { + msg_print(_("鍵をはずした。", "You have picked the lock.")); + gain_exp(creature_ptr, 1); + flag = TRUE; + } else { + more = TRUE; + if (flush_failure) + flush(); + + msg_print(_("鍵をはずせなかった。", "You failed to pick the lock.")); + } + } + + if (flag) { + chest_trap(creature_ptr, y, x, o_idx); + chest_death(creature_ptr, FALSE, y, x, o_idx); + } + + return more; +} + +/*! + * @brief 「開ける」コマンドのメインルーチン / + * Open a closed/locked/jammed door or a closed/locked chest. + * @return なし + * @details + * Unlocking a locked door/chest is worth one experience point. + */ +void do_cmd_open(player_type *creature_ptr) +{ + POSITION y, x; + DIRECTION dir; + OBJECT_IDX o_idx; + bool more = FALSE; + if (creature_ptr->wild_mode) + return; + + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + if (easy_open) { + int num_doors = count_dt(creature_ptr, &y, &x, is_closed_door, FALSE); + int num_chests = count_chests(creature_ptr, &y, &x, FALSE); + if (num_doors || num_chests) { + bool too_many = (num_doors && num_chests) || (num_doors > 1) || (num_chests > 1); + if (!too_many) + command_dir = coords_to_dir(creature_ptr, y, x); + } + } + + if (command_arg) { + command_rep = command_arg - 1; + creature_ptr->redraw |= PR_STATE; + command_arg = 0; + } + + if (get_rep_dir(creature_ptr, &dir, TRUE)) { + FEAT_IDX feat; + grid_type *g_ptr; + y = creature_ptr->y + ddy[dir]; + x = creature_ptr->x + ddx[dir]; + g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + feat = get_feat_mimic(g_ptr); + o_idx = chest_check(creature_ptr->current_floor_ptr, y, x, FALSE); + if (!have_flag(f_info[feat].flags, FF_OPEN) && !o_idx) { + msg_print(_("そこには開けるものが見当たらない。", "You see nothing there to open.")); + } else if (g_ptr->m_idx && creature_ptr->riding != g_ptr->m_idx) { + take_turn(creature_ptr, 100); + msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); + do_cmd_attack(creature_ptr, y, x, 0); + } else if (o_idx) { + more = exe_open_chest(creature_ptr, y, x, o_idx); + } else { + more = exe_open(creature_ptr, y, x); + } + } + + if (!more) + disturb(creature_ptr, FALSE, FALSE); +} + +/*! + * @brief 「閉じる」コマンドのメインルーチン / + * Close an open door. + * @return なし + * @details + * Unlocking a locked door/chest is worth one experience point. + */ +void do_cmd_close(player_type *creature_ptr) +{ + POSITION y, x; + DIRECTION dir; + bool more = FALSE; + if (creature_ptr->wild_mode) + return; + + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + if (easy_open && (count_dt(creature_ptr, &y, &x, is_open, FALSE) == 1)) + command_dir = coords_to_dir(creature_ptr, y, x); + + if (command_arg) { + command_rep = command_arg - 1; + creature_ptr->redraw |= (PR_STATE); + command_arg = 0; + } + + if (get_rep_dir(creature_ptr, &dir, FALSE)) { + grid_type *g_ptr; + FEAT_IDX feat; + y = creature_ptr->y + ddy[dir]; + x = creature_ptr->x + ddx[dir]; + g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + feat = get_feat_mimic(g_ptr); + if (!have_flag(f_info[feat].flags, FF_CLOSE)) { + msg_print(_("そこには閉じるものが見当たらない。", "You see nothing there to close.")); + } else if (g_ptr->m_idx) { + take_turn(creature_ptr, 100); + msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); + do_cmd_attack(creature_ptr, y, x, 0); + } else { + more = exe_close(creature_ptr, y, x); + } + } + + if (!more) + disturb(creature_ptr, FALSE, FALSE); +} + +/*! + * @brief 箱、床のトラップ解除処理双方の統合メインルーチン / + * Disarms a trap, or chest + * @return なし + */ +void do_cmd_disarm(player_type *creature_ptr) +{ + POSITION y, x; + DIRECTION dir; + OBJECT_IDX o_idx; + bool more = FALSE; + if (creature_ptr->wild_mode) + return; + + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + if (easy_disarm) { + int num_traps = count_dt(creature_ptr, &y, &x, is_trap, TRUE); + int num_chests = count_chests(creature_ptr, &y, &x, TRUE); + if (num_traps || num_chests) { + bool too_many = (num_traps && num_chests) || (num_traps > 1) || (num_chests > 1); + if (!too_many) + command_dir = coords_to_dir(creature_ptr, y, x); + } + } + + if (command_arg) { + command_rep = command_arg - 1; + creature_ptr->redraw |= (PR_STATE); + command_arg = 0; + } + + if (get_rep_dir(creature_ptr, &dir, TRUE)) { + grid_type *g_ptr; + FEAT_IDX feat; + y = creature_ptr->y + ddy[dir]; + x = creature_ptr->x + ddx[dir]; + g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + feat = get_feat_mimic(g_ptr); + o_idx = chest_check(creature_ptr->current_floor_ptr, y, x, TRUE); + if (!is_trap(creature_ptr, feat) && !o_idx) { + msg_print(_("そこには解除するものが見当たらない。", "You see nothing there to disarm.")); + } else if (g_ptr->m_idx && creature_ptr->riding != g_ptr->m_idx) { + msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); + do_cmd_attack(creature_ptr, y, x, 0); + } else if (o_idx) { + more = exe_disarm_chest(creature_ptr, y, x, o_idx); + } else { + more = exe_disarm(creature_ptr, y, x, dir); + } + } + + if (!more) + disturb(creature_ptr, FALSE, FALSE); +} + +/*! + * @brief 「打ち破る」動作コマンドのメインルーチン / + * Bash open a door, success based on character strength + * @return なし + * @details + *
+ * For a closed door, pval is positive if locked; negative if stuck.
+ *
+ * For an open door, pval is positive for a broken door.
+ *
+ * A closed door can be opened - harder if locked. Any door might be
+ * bashed open (and thereby broken). Bashing a door is (potentially)
+ * faster! You move into the door way. To open a stuck door, it must
+ * be bashed. A closed door can be jammed (see do_cmd_spike()).
+ *
+ * Creatures can also open or bash doors, see elsewhere.
+ * 
+ */ +void do_cmd_bash(player_type *creature_ptr) +{ + POSITION y, x; + DIRECTION dir; + grid_type *g_ptr; + bool more = FALSE; + if (creature_ptr->wild_mode) + return; + + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + if (command_arg) { + command_rep = command_arg - 1; + creature_ptr->redraw |= (PR_STATE); + command_arg = 0; + } + + if (get_rep_dir(creature_ptr, &dir, FALSE)) { + FEAT_IDX feat; + y = creature_ptr->y + ddy[dir]; + x = creature_ptr->x + ddx[dir]; + g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + feat = get_feat_mimic(g_ptr); + if (!have_flag(f_info[feat].flags, FF_BASH)) { + msg_print(_("そこには体当たりするものが見当たらない。", "You see nothing there to bash.")); + } else if (g_ptr->m_idx) { + take_turn(creature_ptr, 100); + msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); + do_cmd_attack(creature_ptr, y, x, 0); + } else { + more = exe_bash(creature_ptr, y, x, dir); + } + } + + if (!more) + disturb(creature_ptr, FALSE, FALSE); +} + + +/*! + * @brief 「くさびを打つ」ために必要なオブジェクトを所持しているかどうかの判定を返す / + * Find the index of some "spikes", if possible. + * @param ip くさびとして打てるオブジェクトのID + * @return オブジェクトがある場合TRUEを返す + * @details + *
+ * Let user choose a pile of spikes, perhaps?
+ * 
+ */ +static bool get_spike(player_type *creature_ptr, INVENTORY_IDX *ip) +{ + for (INVENTORY_IDX i = 0; i < INVEN_PACK; i++) { + object_type *o_ptr = &creature_ptr->inventory_list[i]; + if (!o_ptr->k_idx) + continue; + + if (o_ptr->tval == TV_SPIKE) { + *ip = i; + return TRUE; + } + } + + return FALSE; +} + +/*! + * @brief 「くさびを打つ」動作コマンドのメインルーチン / + * Jam a closed door with a spike + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + * @details + *
+ * This command may NOT be repeated
+ * 
+ */ +void do_cmd_spike(player_type *creature_ptr) +{ + DIRECTION dir; + if (creature_ptr->wild_mode) + return; + + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + if (!get_rep_dir(creature_ptr, &dir, FALSE)) + return; + + POSITION y = creature_ptr->y + ddy[dir]; + POSITION x = creature_ptr->x + ddx[dir]; + grid_type *g_ptr; + g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + FEAT_IDX feat = get_feat_mimic(g_ptr); + INVENTORY_IDX item; + if (!have_flag(f_info[feat].flags, FF_SPIKE)) { + msg_print(_("そこにはくさびを打てるものが見当たらない。", "You see nothing there to spike.")); + } else if (!get_spike(creature_ptr, &item)) { + msg_print(_("くさびを持っていない!", "You have no spikes!")); + } else if (g_ptr->m_idx) { + take_turn(creature_ptr, 100); + msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); + do_cmd_attack(creature_ptr, y, x, 0); + } else { + take_turn(creature_ptr, 100); + msg_format(_("%sにくさびを打ち込んだ。", "You jam the %s with a spike."), f_name + f_info[feat].name); + cave_alter_feat(creature_ptr, y, x, FF_SPIKE); + vary_item(creature_ptr, item, -1); + } +} diff --git a/src/cmd-action/cmd-open-close.h b/src/cmd-action/cmd-open-close.h new file mode 100644 index 000000000..5176ad970 --- /dev/null +++ b/src/cmd-action/cmd-open-close.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_open(player_type *creature_ptr); +void do_cmd_close(player_type *creature_ptr); +void do_cmd_disarm(player_type *creature_ptr); +void do_cmd_bash(player_type *creature_ptr); +void do_cmd_spike(player_type *creature_ptr); diff --git a/src/cmd-action/cmd-others.c b/src/cmd-action/cmd-others.c new file mode 100644 index 000000000..43fafb9b7 --- /dev/null +++ b/src/cmd-action/cmd-others.c @@ -0,0 +1,183 @@ +/*! + * @brief その他の小さなコマンド処理群 (探索、汎用グリッド処理、自殺/引退/切腹) + * @date 2014/01/02 + * @author + * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke + * + * This software may be copied and distributed for educational, research, + * and not for profit purposes provided that this copyright and statement + * are included in all such copies. Other copyrights may also apply. + */ + +#include "cmd-action/cmd-others.h" +#include "action/open-close-execution.h" +#include "action/tunnel-execution.h" +#include "cmd-action/cmd-attack.h" +#include "core/asking-player.h" +#include "core/disturbance.h" +#include "core/player-redraw-types.h" +#include "floor/geometry.h" +#include "game-option/game-play-options.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "io/write-diary.h" +#include "main/music-definitions-table.h" +#include "main/sound-of-music.h" +#include "player/attack-defense-types.h" +#include "player/player-move.h" +#include "player/special-defense-types.h" +#include "status/action-setter.h" +#include "system/floor-type-definition.h" +#include "target/target-getter.h" +#include "term/screen-processor.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" +#include "world/world.h" + +/*! + * @brief 探索コマンドのメインルーチン / Simple command to "search" for one turn + * @return なし + */ +void do_cmd_search(player_type *creature_ptr) +{ + if (command_arg) { + command_rep = command_arg - 1; + creature_ptr->redraw |= PR_STATE; + command_arg = 0; + } + + take_turn(creature_ptr, 100); + search(creature_ptr); +} + +static bool exe_alter(player_type *creature_ptr) +{ + DIRECTION dir; + if (!get_rep_dir(creature_ptr, &dir, TRUE)) + return FALSE; + + POSITION y = creature_ptr->y + ddy[dir]; + POSITION x = creature_ptr->x + ddx[dir]; + grid_type *g_ptr; + g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + FEAT_IDX feat = get_feat_mimic(g_ptr); + feature_type *f_ptr; + f_ptr = &f_info[feat]; + take_turn(creature_ptr, 100); + if (g_ptr->m_idx) { + do_cmd_attack(creature_ptr, y, x, 0); + return FALSE; + } + + if (have_flag(f_ptr->flags, FF_OPEN)) + return exe_open(creature_ptr, y, x); + + if (have_flag(f_ptr->flags, FF_BASH)) + return exe_bash(creature_ptr, y, x, dir); + + if (have_flag(f_ptr->flags, FF_TUNNEL)) + return exe_tunnel(creature_ptr, y, x); + + if (have_flag(f_ptr->flags, FF_CLOSE)) + return exe_close(creature_ptr, y, x); + + if (have_flag(f_ptr->flags, FF_DISARM)) + return exe_disarm(creature_ptr, y, x, dir); + + msg_print(_("何もない空中を攻撃した。", "You attack the empty air.")); + return FALSE; +} + +/*! + * @brief 特定のマスに影響を及ぼすための汎用的コマンド / Manipulate an adjacent grid in some way + * @return なし + * @details + */ +void do_cmd_alter(player_type *creature_ptr) +{ + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + if (command_arg) { + command_rep = command_arg - 1; + creature_ptr->redraw |= PR_STATE; + command_arg = 0; + } + + if (!exe_alter(creature_ptr)) + disturb(creature_ptr, FALSE, FALSE); +} + +/*! + * @brief 自殺/引退/切腹の確認 + * @param なし + * @return 自殺/引退/切腹を実施するならTRUE、キャンセルならFALSE + */ +static bool decide_suicide(void) +{ + if (current_world_ptr->noscore) + return TRUE; + + prt(_("確認のため '@' を押して下さい。", "Please verify SUICIDE by typing the '@' sign: "), 0, 0); + flush(); + int i = inkey(); + prt("", 0, 0); + return i == '@'; +} + +static void accept_winner_message(player_type *creature_ptr) +{ + if (!current_world_ptr->total_winner || !last_words) + return; + + char buf[1024] = ""; + play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_WINNER); + do { + while (!get_string(_("*勝利*メッセージ: ", "*Winning* message: "), buf, sizeof(buf))) + ; + } while (!get_check_strict(creature_ptr, _("よろしいですか?", "Are you sure? "), CHECK_NO_HISTORY)); + + if (buf[0]) { + creature_ptr->last_message = string_make(buf); + msg_print(creature_ptr->last_message); + } +} + +/*! + * @brief 自殺するコマンドのメインルーチン + * commit suicide + * @return なし + * @details + */ +void do_cmd_suicide(player_type *creature_ptr) +{ + flush(); + if (current_world_ptr->total_winner) { + if (!get_check_strict(creature_ptr, _("引退しますか? ", "Do you want to retire? "), CHECK_NO_HISTORY)) + return; + } else { + if (!get_check(_("本当に自殺しますか?", "Do you really want to commit suicide? "))) + return; + } + + if (!decide_suicide()) + return; + + if (creature_ptr->last_message) + string_free(creature_ptr->last_message); + + creature_ptr->last_message = NULL; + accept_winner_message(creature_ptr); + creature_ptr->playing = FALSE; + creature_ptr->is_dead = TRUE; + creature_ptr->leaving = TRUE; + if (!current_world_ptr->total_winner) { + exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 0, _("ダンジョンの探索に絶望して自殺した。", "gave up all hope to commit suicide.")); + exe_write_diary(creature_ptr, DIARY_GAMESTART, 1, _("-------- ゲームオーバー --------", "-------- Game Over --------")); + exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 1, "\n\n\n\n"); + } + + (void)strcpy(creature_ptr->died_from, _("途中終了", "Quitting")); +} diff --git a/src/cmd-action/cmd-others.h b/src/cmd-action/cmd-others.h new file mode 100644 index 000000000..3d2f32f7b --- /dev/null +++ b/src/cmd-action/cmd-others.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_search(player_type *creature_ptr); +void do_cmd_alter(player_type *creature_ptr); +void do_cmd_suicide(player_type *creature_ptr); diff --git a/src/cmd-action/cmd-pet.c b/src/cmd-action/cmd-pet.c new file mode 100644 index 000000000..dc08c1118 --- /dev/null +++ b/src/cmd-action/cmd-pet.c @@ -0,0 +1,821 @@ +#include "cmd-action/cmd-pet.h" +#include "action/action-limited.h" +#include "cmd-action/cmd-attack.h" +#include "cmd-io/cmd-dump.h" +#include "core/asking-player.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "effect/spells-effect-util.h" +#include "floor/pattern-walk.h" +#include "game-option/input-options.h" +#include "game-option/play-record-options.h" +#include "game-option/text-display-options.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "inventory/inventory-slot-types.h" +#include "io/command-repeater.h" +#include "io/cursor.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "io/write-diary.h" +#include "main/sound-of-music.h" +#include "monster-floor/monster-object.h" +#include "monster-floor/monster-remover.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags7.h" +#include "monster/monster-describer.h" +#include "monster/monster-description-types.h" +#include "monster/monster-info.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "monster/smart-learn-types.h" +#include "object-hook/hook-weapon.h" +#include "pet/pet-util.h" +#include "player/attack-defense-types.h" +#include "player/player-class.h" +#include "player/player-damage.h" +#include "player/player-move.h" +#include "player/player-skill.h" +#include "player/player-status.h" +#include "player/special-defense-types.h" +#include "player/player-status-flags.h" +#include "status/action-setter.h" +#include "system/floor-type-definition.h" +#include "target/target-checker.h" +#include "target/target-getter.h" +#include "target/target-setter.h" +#include "target/target-types.h" +#include "term/screen-processor.h" +#include "util/bit-flags-calculator.h" +#include "util/int-char-converter.h" +#include "util/quarks.h" +#include "util/sort.h" +#include "view/display-messages.h" +#include "world/world.h" + +int total_friends = 0; + +/*! + * @brief ペットを開放するコマンドのメインルーチン + * @return なし + */ +void do_cmd_pet_dismiss(player_type *creature_ptr) +{ + monster_type *m_ptr; + bool all_pets = FALSE; + MONSTER_IDX pet_ctr; + int i; + int Dismissed = 0; + + MONSTER_IDX *who; + u16b dummy_why; + int max_pet = 0; + bool cu, cv; + + cu = Term->scr->cu; + cv = Term->scr->cv; + Term->scr->cu = 0; + Term->scr->cv = 1; + + /* Allocate the "who" array */ + C_MAKE(who, current_world_ptr->max_m_idx, MONSTER_IDX); + + /* Process the monsters (backwards) */ + for (pet_ctr = creature_ptr->current_floor_ptr->m_max - 1; pet_ctr >= 1; pet_ctr--) { + if (is_pet(&creature_ptr->current_floor_ptr->m_list[pet_ctr])) + who[max_pet++] = pet_ctr; + } + + ang_sort(creature_ptr, who, &dummy_why, max_pet, ang_sort_comp_pet_dismiss, ang_sort_swap_hook); + + /* Process the monsters (backwards) */ + for (i = 0; i < max_pet; i++) { + bool delete_this; + GAME_TEXT friend_name[MAX_NLEN]; + bool kakunin; + + pet_ctr = who[i]; + m_ptr = &creature_ptr->current_floor_ptr->m_list[pet_ctr]; + + delete_this = FALSE; + kakunin = ((pet_ctr == creature_ptr->riding) || (m_ptr->nickname)); + monster_desc(creature_ptr, friend_name, m_ptr, MD_ASSUME_VISIBLE); + + if (!all_pets) { + /* Hack -- health bar for this monster */ + health_track(creature_ptr, pet_ctr); + handle_stuff(creature_ptr); + + msg_format(_("%sを放しますか? [Yes/No/Unnamed (%d体)]", "Dismiss %s? [Yes/No/Unnamed (%d remain)]"), friend_name, max_pet - i); + + if (m_ptr->ml) + move_cursor_relative(m_ptr->fy, m_ptr->fx); + + while (TRUE) { + char ch = inkey(); + + if (ch == 'Y' || ch == 'y') { + delete_this = TRUE; + + if (kakunin) { + msg_format(_("本当によろしいですか? (%s) ", "Are you sure? (%s) "), friend_name); + ch = inkey(); + if (ch != 'Y' && ch != 'y') + delete_this = FALSE; + } + break; + } + + if (ch == 'U' || ch == 'u') { + all_pets = TRUE; + break; + } + + if (ch == ESCAPE || ch == 'N' || ch == 'n') + break; + + bell(); + } + } + + if ((all_pets && !kakunin) || (!all_pets && delete_this)) { + if (record_named_pet && m_ptr->nickname) { + GAME_TEXT m_name[MAX_NLEN]; + + monster_desc(creature_ptr, m_name, m_ptr, MD_INDEF_VISIBLE); + exe_write_diary(creature_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_DISMISS, m_name); + } + + if (pet_ctr == creature_ptr->riding) { + msg_format(_("%sから降りた。", "You have got off %s. "), friend_name); + + creature_ptr->riding = 0; + + creature_ptr->update |= (PU_MONSTERS); + creature_ptr->redraw |= (PR_EXTRA | PR_UHEALTH); + } + + /* HACK : Add the line to message buffer */ + msg_format(_("%s を放した。", "Dismissed %s."), friend_name); + creature_ptr->update |= (PU_BONUS); + creature_ptr->window |= (PW_MESSAGE); + + delete_monster_idx(creature_ptr, pet_ctr); + Dismissed++; + } + } + + Term->scr->cu = cu; + Term->scr->cv = cv; + term_fresh(); + + C_KILL(who, current_world_ptr->max_m_idx, MONSTER_IDX); + +#ifdef JP + msg_format("%d 体のペットを放しました。", Dismissed); +#else + msg_format("You have dismissed %d pet%s.", Dismissed, (Dismissed == 1 ? "" : "s")); +#endif + if (Dismissed == 0 && all_pets) + msg_print(_("'U'nnamed は、乗馬以外の名前のないペットだけを全て解放します。", "'U'nnamed means all your pets except named pets and your mount.")); + + handle_stuff(creature_ptr); +} + +/*! + * @brief ペットから騎乗/下馬するコマンドのメインルーチン / + * @param force 強制的に騎乗/下馬するならばTRUE + * @return 騎乗/下馬できたらTRUE + */ +bool do_cmd_riding(player_type *creature_ptr, bool force) +{ + POSITION x, y; + DIRECTION dir = 0; + grid_type *g_ptr; + monster_type *m_ptr; + + if (!get_direction(creature_ptr, &dir, FALSE, FALSE)) + return FALSE; + y = creature_ptr->y + ddy[dir]; + x = creature_ptr->x + ddx[dir]; + g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + if (creature_ptr->riding) { + /* Skip non-empty grids */ + if (!can_player_ride_pet(creature_ptr, g_ptr, FALSE)) { + msg_print(_("そちらには降りられません。", "You cannot go that direction.")); + return FALSE; + } + + if (!pattern_seq(creature_ptr, creature_ptr->y, creature_ptr->x, y, x)) + return FALSE; + + if (g_ptr->m_idx) { + take_turn(creature_ptr, 100); + + msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); + + do_cmd_attack(creature_ptr, y, x, 0); + return FALSE; + } + + creature_ptr->riding = 0; + creature_ptr->pet_extra_flags &= ~(PF_TWO_HANDS); + creature_ptr->riding_ryoute = creature_ptr->old_riding_ryoute = FALSE; + } else { + if (cmd_limit_confused(creature_ptr)) + return FALSE; + + m_ptr = &creature_ptr->current_floor_ptr->m_list[g_ptr->m_idx]; + + if (!g_ptr->m_idx || !m_ptr->ml) { + msg_print(_("その場所にはモンスターはいません。", "There is no monster here.")); + return FALSE; + } + if (!is_pet(m_ptr) && !force) { + msg_print(_("そのモンスターはペットではありません。", "That monster is not a pet.")); + return FALSE; + } + if (!(r_info[m_ptr->r_idx].flags7 & RF7_RIDING)) { + msg_print(_("そのモンスターには乗れなさそうだ。", "This monster doesn't seem suitable for riding.")); + return FALSE; + } + + if (!pattern_seq(creature_ptr, creature_ptr->y, creature_ptr->x, y, x)) + return FALSE; + + if (!can_player_ride_pet(creature_ptr, g_ptr, TRUE)) { + /* Feature code (applying "mimic" field) */ + feature_type *f_ptr = &f_info[get_feat_mimic(g_ptr)]; +#ifdef JP + msg_format("そのモンスターは%sの%sにいる。", f_name + f_ptr->name, + ((!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) + || (!have_flag(f_ptr->flags, FF_LOS) && !have_flag(f_ptr->flags, FF_TREE))) + ? "中" + : "上"); +#else + msg_format("This monster is %s the %s.", + ((!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) + || (!have_flag(f_ptr->flags, FF_LOS) && !have_flag(f_ptr->flags, FF_TREE))) + ? "in" + : "on", + f_name + f_ptr->name); +#endif + + return FALSE; + } + if (r_info[m_ptr->r_idx].level > randint1((creature_ptr->skill_exp[GINOU_RIDING] / 50 + creature_ptr->lev / 2 + 20))) { + msg_print(_("うまく乗れなかった。", "You failed to ride.")); + take_turn(creature_ptr, 100); + return FALSE; + } + + if (monster_csleep_remaining(m_ptr)) { + GAME_TEXT m_name[MAX_NLEN]; + monster_desc(creature_ptr, m_name, m_ptr, 0); + (void)set_monster_csleep(creature_ptr, g_ptr->m_idx, 0); + msg_format(_("%sを起こした。", "You have woken %s up."), m_name); + } + + if (creature_ptr->action == ACTION_KAMAE) + set_action(creature_ptr, ACTION_NONE); + + creature_ptr->riding = g_ptr->m_idx; + + /* Hack -- remove tracked monster */ + if (creature_ptr->riding == creature_ptr->health_who) + health_track(creature_ptr, 0); + } + + take_turn(creature_ptr, 100); + + /* Mega-Hack -- Forget the view and lite */ + creature_ptr->update |= (PU_UN_VIEW | PU_UN_LITE); + creature_ptr->update |= (PU_BONUS); + creature_ptr->redraw |= (PR_MAP | PR_EXTRA); + creature_ptr->redraw |= (PR_UHEALTH); + + (void)move_player_effect(creature_ptr, y, x, MPE_HANDLE_STUFF | MPE_ENERGY_USE | MPE_DONT_PICKUP | MPE_DONT_SWAP_MON); + + return TRUE; +} + +/*! + * @brief ペットに名前をつけるコマンドのメインルーチン + * @return なし + */ +static void do_name_pet(player_type *creature_ptr) +{ + monster_type *m_ptr; + char out_val[20]; + GAME_TEXT m_name[MAX_NLEN]; + bool old_name = FALSE; + bool old_target_pet = target_pet; + + target_pet = TRUE; + if (!target_set(creature_ptr, TARGET_KILL)) { + target_pet = old_target_pet; + return; + } + + target_pet = old_target_pet; + + if (creature_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx) { + m_ptr = &creature_ptr->current_floor_ptr->m_list[creature_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx]; + + if (!is_pet(m_ptr)) { + msg_print(_("そのモンスターはペットではない。", "This monster is not a pet.")); + return; + } + if (r_info[m_ptr->r_idx].flags1 & RF1_UNIQUE) { + msg_print(_("そのモンスターの名前は変えられない!", "You cannot change name of this monster!")); + return; + } + monster_desc(creature_ptr, m_name, m_ptr, 0); + + msg_format(_("%sに名前をつける。", "Name %s."), m_name); + msg_print(NULL); + + /* Start with nothing */ + strcpy(out_val, ""); + + /* Use old inscription */ + if (m_ptr->nickname) { + /* Start with the old inscription */ + strcpy(out_val, quark_str(m_ptr->nickname)); + old_name = TRUE; + } + + /* Get a new inscription (possibly empty) */ + if (get_string(_("名前: ", "Name: "), out_val, 15)) { + if (out_val[0]) { + /* Save the inscription */ + m_ptr->nickname = quark_add(out_val); + if (record_named_pet) { + monster_desc(creature_ptr, m_name, m_ptr, MD_INDEF_VISIBLE); + exe_write_diary(creature_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_NAME, m_name); + } + } else { + if (record_named_pet && old_name) { + monster_desc(creature_ptr, m_name, m_ptr, MD_INDEF_VISIBLE); + exe_write_diary(creature_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_UNNAME, m_name); + } + m_ptr->nickname = 0; + } + } + } +} + +/*! + * @brief ペットに関するコマンドリストのメインルーチン / + * Issue a pet command + * @return なし + */ +void do_cmd_pet(player_type *creature_ptr) +{ + COMMAND_CODE i = 0; + int num; + int powers[36]; + concptr power_desc[36]; + bool flag, redraw; + char choice; + char out_val[160]; + int pet_ctr; + monster_type *m_ptr; + + PET_COMMAND_IDX mode = 0; + + char buf[160]; + char target_buf[160]; + + int menu_line = use_menu ? 1 : 0; + + num = 0; + + if (creature_ptr->wild_mode) + return; + + power_desc[num] = _("ペットを放す", "dismiss pets"); + powers[num++] = PET_DISMISS; + +#ifdef JP + sprintf(target_buf, "ペットのターゲットを指定 (現在:%s)", + (creature_ptr->pet_t_m_idx + ? (creature_ptr->image ? "何か奇妙な物" : (r_name + r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->pet_t_m_idx].ap_r_idx].name)) + : "指定なし")); +#else + sprintf(target_buf, "specify a target of pet (now:%s)", + (creature_ptr->pet_t_m_idx ? ( + creature_ptr->image ? "something strange" : (r_name + r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->pet_t_m_idx].ap_r_idx].name)) + : "nothing")); +#endif + power_desc[num] = target_buf; + powers[num++] = PET_TARGET; + power_desc[num] = _("近くにいろ", "stay close"); + + if (creature_ptr->pet_follow_distance == PET_CLOSE_DIST) + mode = num; + powers[num++] = PET_STAY_CLOSE; + power_desc[num] = _("ついて来い", "follow me"); + + if (creature_ptr->pet_follow_distance == PET_FOLLOW_DIST) + mode = num; + powers[num++] = PET_FOLLOW_ME; + power_desc[num] = _("敵を見つけて倒せ", "seek and destroy"); + + if (creature_ptr->pet_follow_distance == PET_DESTROY_DIST) + mode = num; + powers[num++] = PET_SEEK_AND_DESTROY; + power_desc[num] = _("少し離れていろ", "give me space"); + + if (creature_ptr->pet_follow_distance == PET_SPACE_DIST) + mode = num; + powers[num++] = PET_ALLOW_SPACE; + power_desc[num] = _("離れていろ", "stay away"); + + if (creature_ptr->pet_follow_distance == PET_AWAY_DIST) + mode = num; + powers[num++] = PET_STAY_AWAY; + + if (creature_ptr->pet_extra_flags & PF_OPEN_DOORS) { + power_desc[num] = _("ドアを開ける (現在:ON)", "pets open doors (now On)"); + } else { + power_desc[num] = _("ドアを開ける (現在:OFF)", "pets open doors (now Off)"); + } + powers[num++] = PET_OPEN_DOORS; + + if (creature_ptr->pet_extra_flags & PF_PICKUP_ITEMS) { + power_desc[num] = _("アイテムを拾う (現在:ON)", "pets pick up items (now On)"); + } else { + power_desc[num] = _("アイテムを拾う (現在:OFF)", "pets pick up items (now Off)"); + } + powers[num++] = PET_TAKE_ITEMS; + + if (creature_ptr->pet_extra_flags & PF_TELEPORT) { + power_desc[num] = _("テレポート系魔法を使う (現在:ON)", "allow teleport (now On)"); + } else { + power_desc[num] = _("テレポート系魔法を使う (現在:OFF)", "allow teleport (now Off)"); + } + powers[num++] = PET_TELEPORT; + + if (creature_ptr->pet_extra_flags & PF_ATTACK_SPELL) { + power_desc[num] = _("攻撃魔法を使う (現在:ON)", "allow cast attack spell (now On)"); + } else { + power_desc[num] = _("攻撃魔法を使う (現在:OFF)", "allow cast attack spell (now Off)"); + } + powers[num++] = PET_ATTACK_SPELL; + + if (creature_ptr->pet_extra_flags & PF_SUMMON_SPELL) { + power_desc[num] = _("召喚魔法を使う (現在:ON)", "allow cast summon spell (now On)"); + } else { + power_desc[num] = _("召喚魔法を使う (現在:OFF)", "allow cast summon spell (now Off)"); + } + powers[num++] = PET_SUMMON_SPELL; + + if (creature_ptr->pet_extra_flags & PF_BALL_SPELL) { + power_desc[num] = _("プレイヤーを巻き込む範囲魔法を使う (現在:ON)", "allow involve player in area spell (now On)"); + } else { + power_desc[num] = _("プレイヤーを巻き込む範囲魔法を使う (現在:OFF)", "allow involve player in area spell (now Off)"); + } + powers[num++] = PET_BALL_SPELL; + + if (creature_ptr->riding) { + power_desc[num] = _("ペットから降りる", "get off a pet"); + } else { + power_desc[num] = _("ペットに乗る", "ride a pet"); + } + powers[num++] = PET_RIDING; + power_desc[num] = _("ペットに名前をつける", "name pets"); + powers[num++] = PET_NAME; + + if (creature_ptr->riding) { + if ((have_right_hand_weapon(creature_ptr) && (empty_hands(creature_ptr, FALSE) == EMPTY_HAND_LARM) + && object_allow_two_hands_wielding(&creature_ptr->inventory_list[INVEN_RARM])) + || (have_left_hand_weapon(creature_ptr) && (empty_hands(creature_ptr, FALSE) == EMPTY_HAND_RARM) + && object_allow_two_hands_wielding(&creature_ptr->inventory_list[INVEN_LARM]))) { + if (creature_ptr->pet_extra_flags & PF_TWO_HANDS) { + power_desc[num] = _("武器を片手で持つ", "use one hand to control the pet you are riding"); + } else { + power_desc[num] = _("武器を両手で持つ", "use both hands for a weapon"); + } + + powers[num++] = PET_TWO_HANDS; + } else { + switch (creature_ptr->pclass) { + case CLASS_MONK: + case CLASS_FORCETRAINER: + case CLASS_BERSERKER: + if (empty_hands(creature_ptr, FALSE) == (EMPTY_HAND_RARM | EMPTY_HAND_LARM)) { + if (creature_ptr->pet_extra_flags & PF_TWO_HANDS) { + power_desc[num] = _("片手で格闘する", "use one hand to control the pet you are riding"); + } else { + power_desc[num] = _("両手で格闘する", "use both hands for melee"); + } + + powers[num++] = PET_TWO_HANDS; + } else if ((empty_hands(creature_ptr, FALSE) != EMPTY_HAND_NONE) && !has_melee_weapon(creature_ptr, INVEN_RARM) + && !has_melee_weapon(creature_ptr, INVEN_LARM)) { + if (creature_ptr->pet_extra_flags & PF_TWO_HANDS) { + power_desc[num] = _("格闘を行わない", "use one hand to control the pet you are riding"); + } else { + power_desc[num] = _("格闘を行う", "use one hand for melee"); + } + + powers[num++] = PET_TWO_HANDS; + } + break; + } + } + } + + if (!(repeat_pull(&i) && (i >= 0) && (i < num))) { + flag = FALSE; + redraw = FALSE; + + if (use_menu) { + screen_save(); + strnfmt(out_val, 78, _("(コマンド、ESC=終了) コマンドを選んでください:", "(Command, ESC=exit) Choose command from menu.")); + } else { + strnfmt(out_val, 78, _("(コマンド %c-%c、'*'=一覧、ESC=終了) コマンドを選んでください:", "(Command %c-%c, *=List, ESC=exit) Select a command: "), + I2A(0), I2A(num - 1)); + } + + choice = (always_show_list || use_menu) ? ESCAPE : 1; + + /* Get a command from the user */ + while (!flag) { + int ask = TRUE; + + if (choice == ESCAPE) + choice = ' '; + else if (!get_com(out_val, &choice, TRUE)) + break; + + if (use_menu && (choice != ' ')) { + switch (choice) { + case '0': + screen_load(); + return; + + case '8': + case 'k': + case 'K': + menu_line += (num - 1); + break; + + case '2': + case 'j': + case 'J': + menu_line++; + break; + + case '4': + case 'h': + case 'H': + menu_line = 1; + break; + + case '6': + case 'l': + case 'L': + menu_line = num; + break; + + case 'x': + case 'X': + case '\r': + case '\n': + i = menu_line - 1; + ask = FALSE; + break; + } + if (menu_line > num) + menu_line -= num; + } + + /* Request redraw */ + if ((choice == ' ') || (choice == '*') || (choice == '?') || (use_menu && ask)) { + /* Show the list */ + if (!redraw || use_menu) { + byte y = 1, x = 0; + PET_COMMAND_IDX ctr = 0; + redraw = TRUE; + if (!use_menu) + screen_save(); + + prt("", y++, x); + + /* Print list */ + for (ctr = 0; ctr < num; ctr++) { + /* Letter/number for power selection */ + if (use_menu) + sprintf(buf, "%c%s ", (ctr == mode) ? '*' : ' ', (ctr == (menu_line - 1)) ? _("》", "> ") : " "); + else + sprintf(buf, "%c%c) ", (ctr == mode) ? '*' : ' ', I2A(ctr)); + + strcat(buf, power_desc[ctr]); + + prt(buf, y + ctr, x); + } + + prt("", y + MIN(ctr, 17), x); + } + + /* Hide the list */ + else { + /* Hide list */ + redraw = FALSE; + screen_load(); + } + + /* Redo asking */ + continue; + } + + if (!use_menu) { + /* Note verify */ + ask = (isupper(choice)); + + /* Lowercase */ + if (ask) + choice = (char)tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + } + + /* Totally Illegal */ + if ((i < 0) || (i >= num)) { + bell(); + continue; + } + + /* Verify it */ + if (ask) { + /* Prompt */ + strnfmt(buf, 78, _("%sを使いますか? ", "Use %s? "), power_desc[i]); + + /* Belay that order */ + if (!get_check(buf)) + continue; + } + + /* Stop the loop */ + flag = TRUE; + } + if (redraw) + screen_load(); + + /* Abort if needed */ + if (!flag) { + free_turn(creature_ptr); + return; + } + + repeat_push(i); + } + switch (powers[i]) { + case PET_DISMISS: /* Dismiss pets */ + { + /* Check pets (backwards) */ + for (pet_ctr = creature_ptr->current_floor_ptr->m_max - 1; pet_ctr >= 1; pet_ctr--) { + /* Player has pet */ + if (is_pet(&creature_ptr->current_floor_ptr->m_list[pet_ctr])) + break; + } + + if (!pet_ctr) { + msg_print(_("ペットがいない!", "You have no pets!")); + break; + } + do_cmd_pet_dismiss(creature_ptr); + (void)calculate_upkeep(creature_ptr); + break; + } + case PET_TARGET: { + project_length = -1; + if (!target_set(creature_ptr, TARGET_KILL)) + creature_ptr->pet_t_m_idx = 0; + else { + grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[target_row][target_col]; + if (g_ptr->m_idx && (creature_ptr->current_floor_ptr->m_list[g_ptr->m_idx].ml)) { + creature_ptr->pet_t_m_idx = creature_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx; + creature_ptr->pet_follow_distance = PET_DESTROY_DIST; + } else + creature_ptr->pet_t_m_idx = 0; + } + project_length = 0; + + break; + } + /* Call pets */ + case PET_STAY_CLOSE: { + creature_ptr->pet_follow_distance = PET_CLOSE_DIST; + creature_ptr->pet_t_m_idx = 0; + break; + } + /* "Follow Me" */ + case PET_FOLLOW_ME: { + creature_ptr->pet_follow_distance = PET_FOLLOW_DIST; + creature_ptr->pet_t_m_idx = 0; + break; + } + /* "Seek and destoy" */ + case PET_SEEK_AND_DESTROY: { + creature_ptr->pet_follow_distance = PET_DESTROY_DIST; + break; + } + /* "Give me space" */ + case PET_ALLOW_SPACE: { + creature_ptr->pet_follow_distance = PET_SPACE_DIST; + break; + } + /* "Stay away" */ + case PET_STAY_AWAY: { + creature_ptr->pet_follow_distance = PET_AWAY_DIST; + break; + } + /* flag - allow pets to open doors */ + case PET_OPEN_DOORS: { + if (creature_ptr->pet_extra_flags & PF_OPEN_DOORS) + creature_ptr->pet_extra_flags &= ~(PF_OPEN_DOORS); + else + creature_ptr->pet_extra_flags |= (PF_OPEN_DOORS); + break; + } + /* flag - allow pets to pickup items */ + case PET_TAKE_ITEMS: { + if (creature_ptr->pet_extra_flags & PF_PICKUP_ITEMS) { + creature_ptr->pet_extra_flags &= ~(PF_PICKUP_ITEMS); + for (pet_ctr = creature_ptr->current_floor_ptr->m_max - 1; pet_ctr >= 1; pet_ctr--) { + m_ptr = &creature_ptr->current_floor_ptr->m_list[pet_ctr]; + + if (is_pet(m_ptr)) { + monster_drop_carried_objects(creature_ptr, m_ptr); + } + } + } else + creature_ptr->pet_extra_flags |= (PF_PICKUP_ITEMS); + + break; + } + /* flag - allow pets to teleport */ + case PET_TELEPORT: { + if (creature_ptr->pet_extra_flags & PF_TELEPORT) + creature_ptr->pet_extra_flags &= ~(PF_TELEPORT); + else + creature_ptr->pet_extra_flags |= (PF_TELEPORT); + break; + } + /* flag - allow pets to cast attack spell */ + case PET_ATTACK_SPELL: { + if (creature_ptr->pet_extra_flags & PF_ATTACK_SPELL) + creature_ptr->pet_extra_flags &= ~(PF_ATTACK_SPELL); + else + creature_ptr->pet_extra_flags |= (PF_ATTACK_SPELL); + break; + } + /* flag - allow pets to cast attack spell */ + case PET_SUMMON_SPELL: { + if (creature_ptr->pet_extra_flags & PF_SUMMON_SPELL) + creature_ptr->pet_extra_flags &= ~(PF_SUMMON_SPELL); + else + creature_ptr->pet_extra_flags |= (PF_SUMMON_SPELL); + break; + } + /* flag - allow pets to cast attack spell */ + case PET_BALL_SPELL: { + if (creature_ptr->pet_extra_flags & PF_BALL_SPELL) + creature_ptr->pet_extra_flags &= ~(PF_BALL_SPELL); + else + creature_ptr->pet_extra_flags |= (PF_BALL_SPELL); + break; + } + + case PET_RIDING: { + (void)do_cmd_riding(creature_ptr, FALSE); + break; + } + + case PET_NAME: { + do_name_pet(creature_ptr); + break; + } + + case PET_TWO_HANDS: { + if (creature_ptr->pet_extra_flags & PF_TWO_HANDS) + creature_ptr->pet_extra_flags &= ~(PF_TWO_HANDS); + else + creature_ptr->pet_extra_flags |= (PF_TWO_HANDS); + creature_ptr->update |= (PU_BONUS); + handle_stuff(creature_ptr); + break; + } + } +} diff --git a/src/cmd-action/cmd-pet.h b/src/cmd-action/cmd-pet.h new file mode 100644 index 000000000..96596cce6 --- /dev/null +++ b/src/cmd-action/cmd-pet.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" + +extern int total_friends; + +bool do_cmd_riding(player_type *creature_ptr, bool force); +void do_cmd_pet_dismiss(player_type *creature_pt); +void do_cmd_pet(player_type *creature_ptr); diff --git a/src/cmd-action/cmd-racial.c b/src/cmd-action/cmd-racial.c new file mode 100644 index 000000000..81ed0ff46 --- /dev/null +++ b/src/cmd-action/cmd-racial.c @@ -0,0 +1,313 @@ +#include "cmd-action/cmd-racial.h" +#include "action/action-limited.h" +#include "action/mutation-execution.h" +#include "core/asking-player.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" +#include "game-option/text-display-options.h" +#include "io/command-repeater.h" +#include "io/input-key-requester.h" +#include "main/sound-of-music.h" +#include "mutation/mutation-flag-types.h" +#include "player/attack-defense-types.h" +#include "player/player-damage.h" +#include "player/special-defense-types.h" +#include "racial/class-racial-switcher.h" +#include "racial/mutation-racial-selector.h" +#include "action/racial-execution.h" +#include "racial/race-racial-command-setter.h" +#include "racial/racial-util.h" +#include "status/action-setter.h" +#include "term/screen-processor.h" +#include "util/int-char-converter.h" + +static bool input_racial_power_selection(player_type *creature_ptr, rc_type *rc_ptr) +{ + switch (rc_ptr->choice) { + case '0': + screen_load(); + free_turn(creature_ptr); + return TRUE; + case '8': + case 'k': + case 'K': + rc_ptr->menu_line += (rc_ptr->num - 1); + return FALSE; + case '2': + case 'j': + case 'J': + rc_ptr->menu_line++; + return FALSE; + case '6': + case 'l': + case 'L': + case '4': + case 'h': + case 'H': + if (rc_ptr->menu_line > 18) + rc_ptr->menu_line -= 18; + else if (rc_ptr->menu_line + 18 <= rc_ptr->num) + rc_ptr->menu_line += 18; + + return FALSE; + case 'x': + case 'X': + case '\r': + rc_ptr->command_code = rc_ptr->menu_line - 1; + rc_ptr->ask = FALSE; + return FALSE; + default: + return FALSE; + } +} + +static bool check_input_racial_power(player_type *creature_ptr, rc_type *rc_ptr) +{ + if (!use_menu || rc_ptr->choice == ' ') + return FALSE; + + if (input_racial_power_selection(creature_ptr, rc_ptr)) + return TRUE; + + if (rc_ptr->menu_line > rc_ptr->num) + rc_ptr->menu_line -= rc_ptr->num; + + return FALSE; +} + +static void display_racial_list(rc_type *rc_ptr, char *dummy) +{ + strcpy(dummy, ""); + rc_ptr->redraw = TRUE; + if (!use_menu) + screen_save(); + + if (rc_ptr->num < 18) { + prt(_(" Lv MP 失率", " Lv Cost Fail"), 1, 0); + return; + } + + prt(_(" Lv MP 失率 Lv MP 失率", + " Lv Cost Fail Lv Cost Fail"), + 1, 0); +} + +static void select_racial_power(player_type *creature_ptr, rc_type *rc_ptr) +{ + char dummy[80]; + display_racial_list(rc_ptr, dummy); + byte y = 2; + byte x = 0; + int ctr = 0; + while (ctr < rc_ptr->num) { + TERM_LEN x1 = ((ctr < 18) ? x : x + 40); + TERM_LEN y1 = ((ctr < 18) ? y + ctr : y + ctr - 18); + if (use_menu) { + if (ctr == (rc_ptr->menu_line - 1)) + strcpy(dummy, _(" 》 ", " > ")); + else + strcpy(dummy, " "); + } else { + char letter; + if (ctr < 26) + letter = I2A(ctr); + else + letter = '0' + ctr - 26; + + sprintf(dummy, " %c) ", letter); + } + + strcat(dummy, + format("%-23.23s %2d %4d %3d%%", rc_ptr->power_desc[ctr].racial_name, rc_ptr->power_desc[ctr].min_level, rc_ptr->power_desc[ctr].cost, + 100 - racial_chance(creature_ptr, &rc_ptr->power_desc[ctr]))); + prt(dummy, y1, x1); + ctr++; + } +} + +static bool check_racial_power_choice(player_type *creature_ptr, rc_type *rc_ptr) +{ + if ((rc_ptr->choice != ' ') && (rc_ptr->choice != '*') && (rc_ptr->choice != '?') && (!use_menu || !rc_ptr->ask)) + return FALSE; + + if (!rc_ptr->redraw || use_menu) { + select_racial_power(creature_ptr, rc_ptr); + return TRUE; + } + + rc_ptr->redraw = FALSE; + screen_load(); + return TRUE; +} + +static void decide_racial_command(rc_type *rc_ptr) +{ + if (use_menu) + return; + + if (rc_ptr->choice == '\r' && rc_ptr->num == 1) + rc_ptr->choice = 'a'; + + if (!isalpha(rc_ptr->choice)) { + rc_ptr->ask = FALSE; + rc_ptr->command_code = rc_ptr->choice - '0' + 26; + return; + } + + rc_ptr->ask = (isupper(rc_ptr->choice)); + if (rc_ptr->ask) + rc_ptr->choice = (char)tolower(rc_ptr->choice); + + rc_ptr->command_code = (islower(rc_ptr->choice) ? A2I(rc_ptr->choice) : -1); +} + +static bool ask_invoke_racial_power(rc_type *rc_ptr) +{ + if ((rc_ptr->command_code < 0) || (rc_ptr->command_code >= rc_ptr->num)) { + bell(); + return FALSE; + } + + if (!rc_ptr->ask) + return TRUE; + + char tmp_val[160]; + (void)strnfmt(tmp_val, 78, _("%sを使いますか? ", "Use %s? "), rc_ptr->power_desc[rc_ptr->command_code].racial_name); + return get_check(tmp_val); +} + +static bool process_racial_power_choice(player_type *creature_ptr, rc_type *rc_ptr) +{ + rc_ptr->choice = (always_show_list || use_menu) ? ESCAPE : 1; + while (!rc_ptr->flag) { + if (rc_ptr->choice == ESCAPE) + rc_ptr->choice = ' '; + else if (!get_com(rc_ptr->out_val, &rc_ptr->choice, FALSE)) + break; + + if (check_input_racial_power(creature_ptr, rc_ptr)) + return TRUE; + + if (check_racial_power_choice(creature_ptr, rc_ptr)) + continue; + + decide_racial_command(rc_ptr); + if (!ask_invoke_racial_power(rc_ptr)) + continue; + + rc_ptr->flag = TRUE; + } + + return FALSE; +} + +static bool repeat_racial_power(player_type *creature_ptr, rc_type *rc_ptr) +{ + if (repeat_pull(&rc_ptr->command_code) && (rc_ptr->command_code >= 0) && (rc_ptr->command_code < rc_ptr->num)) + return FALSE; + + if (use_menu) + screen_save(); + + if (process_racial_power_choice(creature_ptr, rc_ptr)) + return TRUE; + + if (rc_ptr->redraw) + screen_load(); + + if (!rc_ptr->flag) { + free_turn(creature_ptr); + return TRUE; + } + + repeat_push(rc_ptr->command_code); + return FALSE; +} + +static void check_cast_racial_power(player_type *creature_ptr, rc_type *rc_ptr) +{ + switch (check_racial_level(creature_ptr, &rc_ptr->power_desc[rc_ptr->command_code])) { + case RACIAL_SUCCESS: + if (rc_ptr->power_desc[rc_ptr->command_code].number < 0) + rc_ptr->cast = exe_racial_power(creature_ptr, rc_ptr->power_desc[rc_ptr->command_code].number); + else + rc_ptr->cast = exe_mutation_power(creature_ptr, rc_ptr->power_desc[rc_ptr->command_code].number); + + break; + case RACIAL_FAILURE: + rc_ptr->cast = TRUE; + break; + case RACIAL_CANCEL: + rc_ptr->cast = FALSE; + break; + } +} + +static bool reduce_mana_by_racial(player_type *creature_ptr, rc_type *rc_ptr) +{ + int racial_cost = rc_ptr->power_desc[rc_ptr->command_code].racial_cost; + if (racial_cost == 0) + return FALSE; + + int actual_racial_cost = racial_cost / 2 + randint1(racial_cost / 2); + if (creature_ptr->csp >= actual_racial_cost) { + creature_ptr->csp -= actual_racial_cost; + return TRUE; + } + + actual_racial_cost -= creature_ptr->csp; + creature_ptr->csp = 0; + take_hit(creature_ptr, DAMAGE_USELIFE, actual_racial_cost, _("過度の集中", "concentrating too hard"), -1); + return TRUE; +} + +/*! + * @brief レイシャル・パワーコマンドのメインルーチン / Allow user to choose a power (racial / mutation) to activate + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void do_cmd_racial_power(player_type *creature_ptr) +{ + if (creature_ptr->wild_mode) + return; + + if (cmd_limit_confused(creature_ptr)) { + free_turn(creature_ptr); + return; + } + + if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) + set_action(creature_ptr, ACTION_NONE); + + rc_type tmp_rc; + rc_type *rc_ptr = initialize_rc_type(creature_ptr, &tmp_rc); + switch_class_racial(creature_ptr, rc_ptr); + if (creature_ptr->mimic_form) + set_mimic_racial_command(creature_ptr, rc_ptr); + else + set_race_racial_command(creature_ptr, rc_ptr); + + select_mutation_racial(creature_ptr, rc_ptr); + rc_ptr->flag = FALSE; + rc_ptr->redraw = FALSE; + + (void)strnfmt(rc_ptr->out_val, 78, + _("(特殊能力 %c-%c, *'で一覧, ESCで中断) どの特殊能力を使いますか?", "(Powers %c-%c, *=List, ESC=exit) Use which power? "), I2A(0), + (rc_ptr->num <= 26) ? I2A(rc_ptr->num - 1) : '0' + rc_ptr->num - 27); + + if (repeat_racial_power(creature_ptr, rc_ptr)) + return; + + check_cast_racial_power(creature_ptr, rc_ptr); + if (!rc_ptr->cast) { + free_turn(creature_ptr); + return; + } + + if (!reduce_mana_by_racial(creature_ptr, rc_ptr)) + return; + + creature_ptr->redraw |= PR_HP | PR_MANA; + creature_ptr->window |= PW_PLAYER | PW_SPELL; +} diff --git a/src/cmd-action/cmd-racial.h b/src/cmd-action/cmd-racial.h new file mode 100644 index 000000000..84e846218 --- /dev/null +++ b/src/cmd-action/cmd-racial.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_racial_power(player_type *creature_ptr); diff --git a/src/cmd-action/cmd-shoot.c b/src/cmd-action/cmd-shoot.c new file mode 100644 index 000000000..2c1c80941 --- /dev/null +++ b/src/cmd-action/cmd-shoot.c @@ -0,0 +1,74 @@ +#include "cmd-action/cmd-shoot.h" +#include "combat/shoot.h" +#include "floor/floor-object.h" +#include "inventory/inventory-slot-types.h" +#include "mind/snipe-types.h" +#include "object/item-use-flags.h" +#include "player/attack-defense-types.h" +#include "player/special-defense-types.h" +#include "spell-kind/spells-teleport.h" +#include "status/action-setter.h" +#include "status/bad-status-setter.h" +#include "sv-definition/sv-bow-types.h" +#include "system/object-type-definition.h" +#include "term/screen-processor.h" +#include "view/display-messages.h" + +/* + * todo Doxygenの加筆求む + * @brief 射撃処理のメインルーチン + * @param creature_ptr プレーヤーへの参照ポインタ + * @param snipe_type ??? + * @return なし + */ +void do_cmd_fire(player_type *creature_ptr, SPELL_IDX snipe_type) +{ + OBJECT_IDX item; + object_type *j_ptr, *ammo_ptr; + if (creature_ptr->wild_mode) + return; + + creature_ptr->is_fired = FALSE; + j_ptr = &creature_ptr->inventory_list[INVEN_BOW]; + if (!j_ptr->tval) { + msg_print(_("射撃用の武器を持っていない。", "You have nothing to fire with.")); + flush(); + return; + } + + if (j_ptr->sval == SV_CRIMSON) { + msg_print(_("この武器は発動して使うもののようだ。", "It's already activated.")); + flush(); + return; + } + + if (j_ptr->sval == SV_HARP) { + msg_print(_("この武器で射撃はできない。", "It's not for firing.")); + flush(); + return; + } + + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + concptr q = _("どれを撃ちますか? ", "Fire which item? "); + concptr s = _("発射されるアイテムがありません。", "You have nothing to fire."); + ammo_ptr = choose_object(creature_ptr, &item, q, s, USE_INVEN | USE_FLOOR, creature_ptr->tval_ammo); + if (!ammo_ptr) { + flush(); + return; + } + + exe_fire(creature_ptr, item, j_ptr, snipe_type); + if (!creature_ptr->is_fired || creature_ptr->pclass != CLASS_SNIPER) + return; + + if (snipe_type == SP_AWAY) + teleport_player(creature_ptr, 10 + (creature_ptr->concent * 2), TELEPORT_SPONTANEOUS); + + if (snipe_type == SP_FINAL) { + msg_print(_("射撃の反動が体を襲った。", "The weapon's recoil stuns you. ")); + (void)set_slow(creature_ptr, creature_ptr->slow + randint0(7) + 7, FALSE); + (void)set_stun(creature_ptr, creature_ptr->stun + randint1(25)); + } +} diff --git a/src/cmd-action/cmd-shoot.h b/src/cmd-action/cmd-shoot.h new file mode 100644 index 000000000..7087aa923 --- /dev/null +++ b/src/cmd-action/cmd-shoot.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_fire(player_type *creature_ptr, SPELL_IDX snipe_type); diff --git a/src/cmd-action/cmd-spell.c b/src/cmd-action/cmd-spell.c new file mode 100644 index 000000000..7fc0c2014 --- /dev/null +++ b/src/cmd-action/cmd-spell.c @@ -0,0 +1,1341 @@ +/*! + * @brief 魔法のインターフェイスと発動 / Purpose: Do everything for each spell + * @date 2013/12/31 + * @author + * 2013 Deskull rearranged comment for Doxygen. + */ + +#include "cmd-action/cmd-spell.h" +#include "action/action-limited.h" +#include "autopick/autopick-reader-writer.h" +#include "cmd-action/cmd-mind.h" +#include "cmd-io/cmd-dump.h" +#include "core/asking-player.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "floor/floor-object.h" +#include "game-option/disturbance-options.h" +#include "game-option/input-options.h" +#include "game-option/text-display-options.h" +#include "grid/grid.h" +#include "inventory/inventory-slot-types.h" +#include "io/command-repeater.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "io/write-diary.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "object-hook/hook-magic.h" +#include "object/item-tester-hooker.h" +#include "object/item-use-flags.h" +#include "player-info/self-info.h" +#include "player/attack-defense-types.h" +#include "player-info/avatar.h" +#include "player/eldritch-horror.h" +#include "player/player-class.h" +#include "player/player-damage.h" +#include "player/player-realm.h" +#include "player/player-skill.h" +#include "player/player-status.h" +#include "player/special-defense-types.h" +#include "realm/realm-names-table.h" +#include "spell-kind/spells-random.h" +#include "spell-kind/spells-sight.h" +#include "spell-realm/spells-hex.h" +#include "spell/range-calc.h" +#include "spell/spell-info.h" +#include "spell/spells-describer.h" +#include "spell/spells-execution.h" +#include "spell/spells-summon.h" +#include "spell/technic-info-table.h" +#include "status/action-setter.h" +#include "status/bad-status-setter.h" +#include "status/base-status.h" +#include "status/experience.h" +#include "system/floor-type-definition.h" +#include "term/screen-processor.h" +#include "util/buffer-shaper.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" +#ifdef JP +#include "locale/japanese.h" +#endif + +/*! + * 魔法領域フラグ管理テーブル / + * Zangband uses this array instead of the spell flags table, as there + * are 5 realms of magic, each with 4 spellbooks and 8 spells per book -- TY + */ +const u32b fake_spell_flags[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; + +/*! + * @brief + * 魔法の効果を「キャプション:ダイス+定数値」のフォーマットで出力する / Generate dice info string such as "foo 2d10" + * @param str キャプション + * @param dice ダイス数 + * @param sides ダイス目 + * @param base 固定値 + * @return フォーマットに従い整形された文字列 + */ +concptr info_string_dice(concptr str, DICE_NUMBER dice, DICE_SID sides, int base) +{ + /* Fix value */ + if (!dice) + return format("%s%d", str, base); + + /* Dice only */ + else if (!base) + return format("%s%dd%d", str, dice, sides); + + /* Dice plus base value */ + else + return format("%s%dd%d%+d", str, dice, sides, base); +} + +/*! + * @brief 魔法によるダメージを出力する / Generate damage-dice info string such as "dam 2d10" + * @param dice ダイス数 + * @param sides ダイス目 + * @param base 固定値 + * @return フォーマットに従い整形された文字列 + */ +concptr info_damage(DICE_NUMBER dice, DICE_SID sides, int base) { return info_string_dice(_("損傷:", "dam "), dice, sides, base); } + +/*! + * @brief 魔法の効果時間を出力する / Generate duration info string such as "dur 20+1d20" + * @param base 固定値 + * @param sides ダイス目 + * @return フォーマットに従い整形された文字列 + */ +concptr info_duration(int base, DICE_SID sides) { return format(_("期間:%d+1d%d", "dur %d+1d%d"), base, sides); } + +/*! + * @brief 魔法の効果範囲を出力する / Generate range info string such as "range 5" + * @param range 効果範囲 + * @return フォーマットに従い整形された文字列 + */ +concptr info_range(POSITION range) { return format(_("範囲:%d", "range %d"), range); } + +/*! + * @brief 魔法による回復量を出力する / Generate heal info string such as "heal 2d8" + * @param dice ダイス数 + * @param sides ダイス目 + * @param base 固定値 + * @return フォーマットに従い整形された文字列 + */ +concptr info_heal(DICE_NUMBER dice, DICE_SID sides, int base) { return info_string_dice(_("回復:", "heal "), dice, sides, base); } + +/*! + * @brief 魔法効果発動までの遅延ターンを出力する / Generate delay info string such as "delay 15+1d15" + * @param base 固定値 + * @param sides ダイス目 + * @return フォーマットに従い整形された文字列 + */ +concptr info_delay(int base, DICE_SID sides) { return format(_("遅延:%d+1d%d", "delay %d+1d%d"), base, sides); } + +/*! + * @brief 魔法によるダメージを出力する(固定値&複数回処理) / Generate multiple-damage info string such as "dam 25 each" + * @param dam 固定値 + * @return フォーマットに従い整形された文字列 + */ +concptr info_multi_damage(HIT_POINT dam) { return format(_("損傷:各%d", "dam %d each"), dam); } + +/*! + * @brief 魔法によるダメージを出力する(ダイスのみ&複数回処理) / Generate multiple-damage-dice info string such as "dam 5d2 each" + * @param dice ダイス数 + * @param sides ダイス目 + * @return フォーマットに従い整形された文字列 + */ +concptr info_multi_damage_dice(DICE_NUMBER dice, DICE_SID sides) { return format(_("損傷:各%dd%d", "dam %dd%d each"), dice, sides); } + +/*! + * @brief 魔法による一般的な効力値を出力する(固定値) / Generate power info string such as "power 100" + * @param power 固定値 + * @return フォーマットに従い整形された文字列 + */ +concptr info_power(int power) { return format(_("効力:%d", "power %d"), power); } + +/*! + * @brief 魔法による一般的な効力値を出力する(ダイス値) / Generate power info string such as "power 100" + * @param dice ダイス数 + * @param sides ダイス目 + * @return フォーマットに従い整形された文字列 + */ +/* + * Generate power info string such as "power 1d100" + */ +concptr info_power_dice(DICE_NUMBER dice, DICE_SID sides) { return format(_("効力:%dd%d", "power %dd%d"), dice, sides); } + +/*! + * @brief 魔法の効果半径を出力する / Generate radius info string such as "rad 100" + * @param rad 効果半径 + * @return フォーマットに従い整形された文字列 + */ +concptr info_radius(POSITION rad) { return format(_("半径:%d", "rad %d"), rad); } + +/*! + * @brief 魔法効果の限界重量を出力する / Generate weight info string such as "max wgt 15" + * @param weight 最大重量 + * @return フォーマットに従い整形された文字列 + */ +concptr info_weight(WEIGHT weight) +{ +#ifdef JP + return format("最大重量:%d.%dkg", lbtokg1(weight), lbtokg2(weight)); +#else + return format("max wgt %d", weight / 10); +#endif +} + +/*! + * @brief 魔法が利用可能かどうかを返す / + * Determine if a spell is "okay" for the player to cast or study + * The spell must be legible, not forgotten, and also, to cast, + * it must be known, and to study, it must not be known. + * @param spell 呪文ID + * @param learned 使用可能な判定ならばTRUE、学習可能かどうかの判定ならばFALSE + * @param study_pray 祈りの学習判定目的ならばTRUE + * @param use_realm 魔法領域ID + * @return 失敗率(%) + */ +static bool spell_okay(player_type *caster_ptr, int spell, bool learned, bool study_pray, int use_realm) +{ + const magic_type *s_ptr; + + /* Access the spell */ + if (!is_magic(use_realm)) { + s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell]; + } else { + s_ptr = &mp_ptr->info[use_realm - 1][spell]; + } + + /* Spell is illegal */ + if (s_ptr->slevel > caster_ptr->lev) + return FALSE; + + /* Spell is forgotten */ + if ((use_realm == caster_ptr->realm2) ? (caster_ptr->spell_forgotten2 & (1L << spell)) : (caster_ptr->spell_forgotten1 & (1L << spell))) { + /* Never okay */ + return FALSE; + } + + if (caster_ptr->pclass == CLASS_SORCERER) + return TRUE; + if (caster_ptr->pclass == CLASS_RED_MAGE) + return TRUE; + + /* Spell is learned */ + if ((use_realm == caster_ptr->realm2) ? (caster_ptr->spell_learned2 & (1L << spell)) : (caster_ptr->spell_learned1 & (1L << spell))) { + /* Always true */ + return (!study_pray); + } + + /* Okay to study, not to cast */ + return (!learned); +} + +/*! + * @brief 領域魔法の閲覧、学習、使用選択するインターフェイス処理 + * Allow user to choose a spell/prayer from the given book. + * @param sn 選択した魔法IDを返す参照ポインタ + * @param prompt 魔法を利用する際の動詞表記 + * @param sval 魔道書のsval + * @param learned 閲覧/使用選択ならばTRUE、学習処理ならFALSE + * @param use_realm 魔法領域ID + * @return + *
+ * If a valid spell is chosen, saves it in '*sn' and returns TRUE
+ * If the user hits escape, returns FALSE, and set '*sn' to -1
+ * If there are no legal choices, returns FALSE, and sets '*sn' to -2
+ * The "prompt" should be "cast", "recite", or "study"
+ * The "known" should be TRUE for cast/pray, FALSE for study
+ * 
+ */ +static int get_spell(player_type *caster_ptr, SPELL_IDX *sn, concptr prompt, OBJECT_SUBTYPE_VALUE sval, bool learned, REALM_IDX use_realm) +{ + int i; + SPELL_IDX spell = -1; + int num = 0; + int ask = TRUE; + MANA_POINT need_mana; + SPELL_IDX spells[64]; + bool flag, redraw, okay; + char choice; + const magic_type *s_ptr; + char out_val[160]; + concptr p; + COMMAND_CODE code; +#ifdef JP + char jverb_buf[128]; +#endif + int menu_line = (use_menu ? 1 : 0); + + /* Get the spell, if available */ + if (repeat_pull(&code)) { + *sn = (SPELL_IDX)code; + /* Verify the spell */ + if (spell_okay(caster_ptr, *sn, learned, FALSE, use_realm)) { + /* Success */ + return TRUE; + } + } + + p = spell_category_name(mp_ptr->spell_book); + + /* Extract spells */ + for (spell = 0; spell < 32; spell++) { + /* Check for this spell */ + if ((fake_spell_flags[sval] & (1L << spell))) { + /* Collect this spell */ + spells[num++] = spell; + } + } + + /* Assume no usable spells */ + okay = FALSE; + + /* Assume no spells available */ + (*sn) = -2; + + /* Check for "okay" spells */ + for (i = 0; i < num; i++) { + /* Look for "okay" spells */ + if (spell_okay(caster_ptr, spells[i], learned, FALSE, use_realm)) + okay = TRUE; + } + + /* No "okay" spells */ + if (!okay) + return FALSE; + if (((use_realm) != caster_ptr->realm1) && ((use_realm) != caster_ptr->realm2) && (caster_ptr->pclass != CLASS_SORCERER) + && (caster_ptr->pclass != CLASS_RED_MAGE)) + return FALSE; + if (((caster_ptr->pclass == CLASS_SORCERER) || (caster_ptr->pclass == CLASS_RED_MAGE)) && !is_magic(use_realm)) + return FALSE; + if ((caster_ptr->pclass == CLASS_RED_MAGE) && ((use_realm) != REALM_ARCANE) && (sval > 1)) + return FALSE; + + /* Assume cancelled */ + *sn = (-1); + + flag = FALSE; + redraw = FALSE; + + caster_ptr->window |= (PW_SPELL); + handle_stuff(caster_ptr); + + /* Build a prompt (accept all spells) */ +#ifdef JP + jverb(prompt, jverb_buf, JVERB_AND); + (void)strnfmt(out_val, 78, "(%^s:%c-%c, '*'で一覧, ESCで中断) どの%sを%^sますか? ", p, I2A(0), I2A(num - 1), p, jverb_buf); +#else + (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) %^s which %s? ", p, I2A(0), I2A(num - 1), prompt, p); +#endif + + choice = (always_show_list || use_menu) ? ESCAPE : 1; + while (!flag) { + if (choice == ESCAPE) + choice = ' '; + else if (!get_com(out_val, &choice, TRUE)) + break; + + if (use_menu && choice != ' ') { + switch (choice) { + case '0': { + screen_load(); + return FALSE; + } + + case '8': + case 'k': + case 'K': { + menu_line += (num - 1); + break; + } + + case '2': + case 'j': + case 'J': { + menu_line++; + break; + } + + case 'x': + case 'X': + case '\r': + case '\n': { + i = menu_line - 1; + ask = FALSE; + break; + } + } + if (menu_line > num) + menu_line -= num; + /* Display a list of spells */ + print_spells(caster_ptr, menu_line, spells, num, 1, 15, use_realm); + if (ask) + continue; + } else { + /* Request redraw */ + if ((choice == ' ') || (choice == '*') || (choice == '?')) { + /* Show the list */ + if (!redraw) { + redraw = TRUE; + screen_save(); + + /* Display a list of spells */ + print_spells(caster_ptr, menu_line, spells, num, 1, 15, use_realm); + } + + /* Hide the list */ + else { + if (use_menu) + continue; + + /* Hide list */ + redraw = FALSE; + screen_load(); + } + + /* Redo asking */ + continue; + } + + /* Note verify */ + ask = (isupper(choice)); + + /* Lowercase */ + if (ask) + choice = (char)tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + } + + /* Totally Illegal */ + if ((i < 0) || (i >= num)) { + bell(); + continue; + } + + /* Save the spell index */ + spell = spells[i]; + + /* Require "okay" spells */ + if (!spell_okay(caster_ptr, spell, learned, FALSE, use_realm)) { + bell(); +#ifdef JP + msg_format("その%sを%sことはできません。", p, prompt); +#else + msg_format("You may not %s that %s.", prompt, p); +#endif + + continue; + } + + /* Verify it */ + if (ask) { + char tmp_val[160]; + + /* Access the spell */ + if (!is_magic(use_realm)) { + s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell]; + } else { + s_ptr = &mp_ptr->info[use_realm - 1][spell]; + } + + /* Extract mana consumption rate */ + if (use_realm == REALM_HISSATSU) { + need_mana = s_ptr->smana; + } else { + need_mana = mod_need_mana(caster_ptr, s_ptr->smana, spell, use_realm); + } + + /* Prompt */ +#ifdef JP + jverb(prompt, jverb_buf, JVERB_AND); + /* 英日切り替え機能に対応 */ + (void)strnfmt(tmp_val, 78, "%s(MP%d, 失敗率%d%%)を%sますか? ", exe_spell(caster_ptr, use_realm, spell, SPELL_NAME), need_mana, + spell_chance(caster_ptr, spell, use_realm), jverb_buf); +#else + (void)strnfmt(tmp_val, 78, "%^s %s (%d mana, %d%% fail)? ", prompt, exe_spell(caster_ptr, use_realm, spell, SPELL_NAME), need_mana, + spell_chance(caster_ptr, spell, use_realm)); +#endif + + /* Belay that order */ + if (!get_check(tmp_val)) + continue; + } + + /* Stop the loop */ + flag = TRUE; + } + + if (redraw) + screen_load(); + + caster_ptr->window |= (PW_SPELL); + handle_stuff(caster_ptr); + + /* Abort if needed */ + if (!flag) + return FALSE; + + /* Save the choice */ + (*sn) = spell; + + repeat_push((COMMAND_CODE)spell); + + /* Success */ + return TRUE; +} + +/*! + * @brief プレイヤーの職業が練気術師の時、領域魔法と練気術を切り換える処理のインターフェイス + * @param browse_only 魔法と技能の閲覧を行うならばTRUE + * @return 魔道書を一冊も持っていないならTRUEを返す + */ +static void confirm_use_force(player_type *caster_ptr, bool browse_only) +{ + char which; + COMMAND_CODE code; + + /* Get the item index */ + if (repeat_pull(&code) && (code == INVEN_FORCE)) { + browse_only ? do_cmd_mind_browse(caster_ptr) : do_cmd_mind(caster_ptr); + return; + } + + /* Show the prompt */ + prt(_("('w'練気術, ESC) 'w'かESCを押してください。 ", "(w for the Force, ESC) Hit 'w' or ESC. "), 0, 0); + + while (TRUE) { + /* Get a key */ + which = inkey(); + + if (which == ESCAPE) + break; + else if (which == 'w') { + repeat_push(INVEN_FORCE); + break; + } + } + + /* Clear the prompt line */ + prt("", 0, 0); + + if (which == 'w') { + browse_only ? do_cmd_mind_browse(caster_ptr) : do_cmd_mind(caster_ptr); + } +} + +/*! + * @brief プレイヤーの魔法と技能を閲覧するコマンドのメインルーチン / + * Peruse the spells/prayers in a book + * @return なし + * @details + *
+ * Note that *all* spells in the book are listed
+ *
+ * Note that browsing is allowed while confused or blind,
+ * and in the dark, primarily to allow browsing in stores.
+ * 
+ */ +void do_cmd_browse(player_type *caster_ptr) +{ + OBJECT_IDX item; + OBJECT_SUBTYPE_VALUE sval; + REALM_IDX use_realm = 0; + int j, line; + SPELL_IDX spell = -1; + int num = 0; + + SPELL_IDX spells[64]; + char temp[62 * 4]; + + object_type *o_ptr; + + concptr q, s; + tval_type tval = 0; + + /* Warriors are illiterate */ + if (!(caster_ptr->realm1 || caster_ptr->realm2) && (caster_ptr->pclass != CLASS_SORCERER) && (caster_ptr->pclass != CLASS_RED_MAGE)) { + msg_print(_("本を読むことができない!", "You cannot read books!")); + return; + } + + if (caster_ptr->special_defense & KATA_MUSOU) { + set_action(caster_ptr, ACTION_NONE); + } + + if (caster_ptr->pclass == CLASS_FORCETRAINER) { + if (player_has_no_spellbooks(caster_ptr)) { + confirm_use_force(caster_ptr, TRUE); + return; + } + } + + /* Restrict choices to "useful" books */ + if (caster_ptr->realm2 == REALM_NONE) + tval = mp_ptr->spell_book; + else + item_tester_hook = item_tester_learn_spell; + + q = _("どの本を読みますか? ", "Browse which book? "); + s = _("読める本がない。", "You have no books that you can read."); + + o_ptr = choose_object(caster_ptr, &item, q, s, (USE_INVEN | USE_FLOOR | (caster_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)), tval); + + item_tester_hook = NULL; + if (!o_ptr) { + if (item == INVEN_FORCE) /* the_force */ + { + do_cmd_mind_browse(caster_ptr); + return; + } + return; + } + + /* Access the item's sval */ + sval = o_ptr->sval; + + use_realm = tval2realm(o_ptr->tval); + + /* Track the object kind */ + object_kind_track(caster_ptr, o_ptr->k_idx); + handle_stuff(caster_ptr); + + /* Extract spells */ + for (spell = 0; spell < 32; spell++) { + /* Check for this spell */ + if ((fake_spell_flags[sval] & (1L << spell))) { + /* Collect this spell */ + spells[num++] = spell; + } + } + + screen_save(); + prt("", 0, 0); + + /* Keep browsing spells. Exit browsing on cancel. */ + while (TRUE) { + /* Ask for a spell, allow cancel */ + if (!get_spell(caster_ptr, &spell, _("読む", "browse"), o_ptr->sval, TRUE, use_realm)) { + /* If cancelled, leave immediately. */ + if (spell == -1) + break; + + /* Display a list of spells */ + print_spells(caster_ptr, 0, spells, num, 1, 15, use_realm); + + /* Notify that there's nothing to see, and wait. */ + if (use_realm == REALM_HISSATSU) + prt(_("読める技がない。", "No techniques to browse."), 0, 0); + else + prt(_("読める呪文がない。", "No spells to browse."), 0, 0); + (void)inkey(); + + screen_load(); + + return; + } + + /* Clear lines, position cursor (really should use strlen here) */ + term_erase(14, 14, 255); + term_erase(14, 13, 255); + term_erase(14, 12, 255); + term_erase(14, 11, 255); + + shape_buffer(exe_spell(caster_ptr, use_realm, spell, SPELL_DESC), 62, temp, sizeof(temp)); + + for (j = 0, line = 11; temp[j]; j += 1 + strlen(&temp[j])) { + prt(&temp[j], line, 15); + line++; + } + } + screen_load(); +} + +/*! + * @brief プレイヤーの第二魔法領域を変更する / + * @param caster_ptr プレーヤーへの参照ポインタ + * @param next_realm 変更先の魔法領域ID + * @return なし + */ +static void change_realm2(player_type *caster_ptr, player_personality_type next_realm) +{ + int i, j = 0; + char tmp[80]; + + for (i = 0; i < 64; i++) { + caster_ptr->spell_order[j] = caster_ptr->spell_order[i]; + if (caster_ptr->spell_order[i] < 32) + j++; + } + for (; j < 64; j++) + caster_ptr->spell_order[j] = 99; + + for (i = 32; i < 64; i++) { + caster_ptr->spell_exp[i] = SPELL_EXP_UNSKILLED; + } + caster_ptr->spell_learned2 = 0L; + caster_ptr->spell_worked2 = 0L; + caster_ptr->spell_forgotten2 = 0L; + + sprintf(tmp, _("魔法の領域を%sから%sに変更した。", "changed magic realm from %s to %s."), realm_names[caster_ptr->realm2], realm_names[next_realm]); + exe_write_diary(caster_ptr, DIARY_DESCRIPTION, 0, tmp); + caster_ptr->old_realm |= 1 << (caster_ptr->realm2 - 1); + caster_ptr->realm2 = next_realm; + + caster_ptr->update |= (PU_REORDER); + caster_ptr->update |= (PU_SPELLS); + handle_stuff(caster_ptr); + + /* Load an autopick preference file */ + autopick_load_pref(caster_ptr, FALSE); +} + +/*! + * @brief 魔法を学習するコマンドのメインルーチン / + * Study a book to gain a new spell/prayer + * @return なし + */ +void do_cmd_study(player_type *caster_ptr) +{ + int i; + OBJECT_IDX item; + OBJECT_SUBTYPE_VALUE sval; + int increment = 0; + bool learned = FALSE; + + /* Spells of realm2 will have an increment of +32 */ + SPELL_IDX spell = -1; + concptr p = spell_category_name(mp_ptr->spell_book); + object_type *o_ptr; + concptr q, s; + tval_type tval = 0; + + if (!caster_ptr->realm1) { + msg_print(_("本を読むことができない!", "You cannot read books!")); + return; + } + + if (cmd_limit_blind(caster_ptr)) + return; + if (cmd_limit_confused(caster_ptr)) + return; + + if (!(caster_ptr->new_spells)) { + msg_format(_("新しい%sを覚えることはできない!", "You cannot learn any new %ss!"), p); + return; + } + + if (caster_ptr->special_defense & KATA_MUSOU) { + set_action(caster_ptr, ACTION_NONE); + } + +#ifdef JP + if (caster_ptr->new_spells < 10) { + msg_format("あと %d つの%sを学べる。", caster_ptr->new_spells, p); + } else { + msg_format("あと %d 個の%sを学べる。", caster_ptr->new_spells, p); + } +#else + msg_format("You can learn %d new %s%s.", caster_ptr->new_spells, p, (caster_ptr->new_spells == 1 ? "" : "s")); +#endif + + msg_print(NULL); + + /* Restrict choices to "useful" books */ + if (caster_ptr->realm2 == REALM_NONE) + tval = mp_ptr->spell_book; + else + item_tester_hook = item_tester_learn_spell; + + q = _("どの本から学びますか? ", "Study which book? "); + s = _("読める本がない。", "You have no books that you can read."); + + o_ptr = choose_object(caster_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), tval); + + if (!o_ptr) + return; + + /* Access the item's sval */ + sval = o_ptr->sval; + + if (o_ptr->tval == get_realm2_book(caster_ptr)) + increment = 32; + else if (o_ptr->tval != get_realm1_book(caster_ptr)) { + if (!get_check(_("本当に魔法の領域を変更しますか?", "Really, change magic realm? "))) + return; + change_realm2(caster_ptr, tval2realm(o_ptr->tval)); + increment = 32; + } + + /* Track the object kind */ + object_kind_track(caster_ptr, o_ptr->k_idx); + handle_stuff(caster_ptr); + + /* Mage -- Learn a selected spell */ + if (mp_ptr->spell_book != TV_LIFE_BOOK) { + /* Ask for a spell, allow cancel */ + if (!get_spell(caster_ptr, &spell, _("学ぶ", "study"), sval, FALSE, o_ptr->tval - TV_LIFE_BOOK + 1) && (spell == -1)) + return; + } + + /* Priest -- Learn a random prayer */ + else { + int k = 0; + int gift = -1; + + /* Extract spells */ + for (spell = 0; spell < 32; spell++) { + /* Check spells in the book */ + if ((fake_spell_flags[sval] & (1L << spell))) { + /* Skip non "okay" prayers */ + if (!spell_okay(caster_ptr, spell, FALSE, TRUE, (increment ? caster_ptr->realm2 : caster_ptr->realm1))) + continue; + + /* Hack -- Prepare the randomizer */ + k++; + + /* Hack -- Apply the randomizer */ + if (one_in_(k)) + gift = spell; + } + } + + /* Accept gift */ + spell = gift; + } + + /* Nothing to study */ + if (spell < 0) { + msg_format(_("その本には学ぶべき%sがない。", "You cannot learn any %ss in that book."), p); + + /* Abort */ + return; + } + + if (increment) + spell += increment; + + /* Learn the spell */ + if (spell < 32) { + if (caster_ptr->spell_learned1 & (1L << spell)) + learned = TRUE; + else + caster_ptr->spell_learned1 |= (1L << spell); + } else { + if (caster_ptr->spell_learned2 & (1L << (spell - 32))) + learned = TRUE; + else + caster_ptr->spell_learned2 |= (1L << (spell - 32)); + } + + if (learned) { + int max_exp = (spell < 32) ? SPELL_EXP_MASTER : SPELL_EXP_EXPERT; + int old_exp = caster_ptr->spell_exp[spell]; + int new_rank = EXP_LEVEL_UNSKILLED; + concptr name = exe_spell(caster_ptr, increment ? caster_ptr->realm2 : caster_ptr->realm1, spell % 32, SPELL_NAME); + + if (old_exp >= max_exp) { + msg_format(_("その%sは完全に使いこなせるので学ぶ必要はない。", "You don't need to study this %s anymore."), p); + return; + } +#ifdef JP + if (!get_check(format("%sの%sをさらに学びます。よろしいですか?", name, p))) +#else + if (!get_check(format("You will study a %s of %s again. Are you sure? ", p, name))) +#endif + { + return; + } else if (old_exp >= SPELL_EXP_EXPERT) { + caster_ptr->spell_exp[spell] = SPELL_EXP_MASTER; + new_rank = EXP_LEVEL_MASTER; + } else if (old_exp >= SPELL_EXP_SKILLED) { + if (spell >= 32) + caster_ptr->spell_exp[spell] = SPELL_EXP_EXPERT; + else + caster_ptr->spell_exp[spell] += SPELL_EXP_EXPERT - SPELL_EXP_SKILLED; + new_rank = EXP_LEVEL_EXPERT; + } else if (old_exp >= SPELL_EXP_BEGINNER) { + caster_ptr->spell_exp[spell] = SPELL_EXP_SKILLED + (old_exp - SPELL_EXP_BEGINNER) * 2 / 3; + new_rank = EXP_LEVEL_SKILLED; + } else { + caster_ptr->spell_exp[spell] = SPELL_EXP_BEGINNER + old_exp / 3; + new_rank = EXP_LEVEL_BEGINNER; + } + msg_format(_("%sの熟練度が%sに上がった。", "Your proficiency of %s is now %s rank."), name, exp_level_str[new_rank]); + } else { + /* Find the next open entry in "caster_ptr->spell_order[]" */ + for (i = 0; i < 64; i++) { + /* Stop at the first empty space */ + if (caster_ptr->spell_order[i] == 99) + break; + } + + /* Add the spell to the known list */ + caster_ptr->spell_order[i++] = spell; + + /* Mention the result */ +#ifdef JP + /* 英日切り替え機能に対応 */ + if (mp_ptr->spell_book == TV_MUSIC_BOOK) { + msg_format("%sを学んだ。", exe_spell(caster_ptr, increment ? caster_ptr->realm2 : caster_ptr->realm1, spell % 32, SPELL_NAME)); + } else { + msg_format("%sの%sを学んだ。", exe_spell(caster_ptr, increment ? caster_ptr->realm2 : caster_ptr->realm1, spell % 32, SPELL_NAME), p); + } +#else + msg_format("You have learned the %s of %s.", p, exe_spell(caster_ptr, increment ? caster_ptr->realm2 : caster_ptr->realm1, spell % 32, SPELL_NAME)); +#endif + } + + take_turn(caster_ptr, 100); + + switch (mp_ptr->spell_book) { + case TV_LIFE_BOOK: + chg_virtue(caster_ptr, V_FAITH, 1); + break; + case TV_DEATH_BOOK: + chg_virtue(caster_ptr, V_UNLIFE, 1); + break; + case TV_NATURE_BOOK: + chg_virtue(caster_ptr, V_NATURE, 1); + break; + default: + chg_virtue(caster_ptr, V_KNOWLEDGE, 1); + break; + } + + sound(SOUND_STUDY); + + /* One less spell available */ + caster_ptr->learned_spells++; + + /* Update Study */ + caster_ptr->update |= (PU_SPELLS); + update_creature(caster_ptr); + + /* Redraw object recall */ + caster_ptr->window |= (PW_OBJECT); +} + +/*! + * @brief 魔法を詠唱するコマンドのメインルーチン / + * Cast a spell + * @param caster_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void do_cmd_cast(player_type *caster_ptr) +{ + OBJECT_IDX item; + OBJECT_SUBTYPE_VALUE sval; + SPELL_IDX spell; + REALM_IDX realm; + int chance; + int increment = 0; + REALM_IDX use_realm; + MANA_POINT need_mana; + + concptr prayer; + object_type *o_ptr; + const magic_type *s_ptr; + concptr q, s; + + bool over_exerted = FALSE; + + /* Require spell ability */ + if (!caster_ptr->realm1 && (caster_ptr->pclass != CLASS_SORCERER) && (caster_ptr->pclass != CLASS_RED_MAGE)) { + msg_print(_("呪文を唱えられない!", "You cannot cast spells!")); + return; + } + + if (caster_ptr->blind || no_lite(caster_ptr)) { + if (caster_ptr->pclass == CLASS_FORCETRAINER) + confirm_use_force(caster_ptr, FALSE); + else { + msg_print(_("目が見えない!", "You cannot see!")); + flush(); + } + return; + } + + if (cmd_limit_confused(caster_ptr)) + return; + if (caster_ptr->realm1 == REALM_HEX) { + if (hex_spell_fully(caster_ptr)) { + bool flag = FALSE; + msg_print(_("これ以上新しい呪文を詠唱することはできない。", "Can not cast more spells.")); + flush(); + if (caster_ptr->lev >= 35) + flag = stop_hex_spell(caster_ptr); + if (!flag) + return; + } + } + + if (caster_ptr->pclass == CLASS_FORCETRAINER) { + if (player_has_no_spellbooks(caster_ptr)) { + confirm_use_force(caster_ptr, FALSE); + return; + } + } + + prayer = spell_category_name(mp_ptr->spell_book); + + q = _("どの呪文書を使いますか? ", "Use which book? "); + s = _("呪文書がない!", "You have no spell books!"); + + o_ptr = choose_object(caster_ptr, &item, q, s, (USE_INVEN | USE_FLOOR | (caster_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0)), mp_ptr->spell_book); + if (!o_ptr) { + if (item == INVEN_FORCE) /* the_force */ + { + do_cmd_mind(caster_ptr); + return; + } + return; + } + + /* Access the item's sval */ + sval = o_ptr->sval; + + if ((caster_ptr->pclass != CLASS_SORCERER) && (caster_ptr->pclass != CLASS_RED_MAGE) && (o_ptr->tval == get_realm2_book(caster_ptr))) + increment = 32; + + /* Track the object kind */ + object_kind_track(caster_ptr, o_ptr->k_idx); + handle_stuff(caster_ptr); + + if ((caster_ptr->pclass == CLASS_SORCERER) || (caster_ptr->pclass == CLASS_RED_MAGE)) + realm = o_ptr->tval - TV_LIFE_BOOK + 1; + else if (increment) + realm = caster_ptr->realm2; + else + realm = caster_ptr->realm1; + + /* Ask for a spell */ +#ifdef JP + if (!get_spell(caster_ptr, &spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_MUSIC_BOOK) ? "歌う" : "唱える"), sval, + TRUE, realm)) { + if (spell == -2) + msg_format("その本には知っている%sがない。", prayer); + return; + } +#else + if (!get_spell(caster_ptr, &spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"), sval, TRUE, realm)) { + if (spell == -2) + msg_format("You don't know any %ss in that book.", prayer); + return; + } +#endif + + use_realm = tval2realm(o_ptr->tval); + if (use_realm == REALM_HEX) { + if (hex_spelling(caster_ptr, spell)) { + msg_print(_("その呪文はすでに詠唱中だ。", "You are already casting it.")); + return; + } + } + + if (!is_magic(use_realm)) { + s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell]; + } else { + s_ptr = &mp_ptr->info[realm - 1][spell]; + } + + /* Extract mana consumption rate */ + need_mana = mod_need_mana(caster_ptr, s_ptr->smana, spell, realm); + + /* Verify "dangerous" spells */ + if (need_mana > caster_ptr->csp) { + if (flush_failure) + flush(); + + /* Warning */ +#ifdef JP + msg_format("その%sを%sのに十分なマジックポイントがない。", prayer, + ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_LIFE_BOOK) ? "歌う" : "唱える")); +#else + msg_format("You do not have enough mana to %s this %s.", ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"), prayer); +#endif + + if (!over_exert) + return; + + /* Verify */ + if (!get_check_strict(caster_ptr, _("それでも挑戦しますか? ", "Attempt it anyway? "), CHECK_OKAY_CANCEL)) + return; + } + + /* Spell failure chance */ + chance = spell_chance(caster_ptr, spell, use_realm); + + /* Sufficient mana */ + if (need_mana <= caster_ptr->csp) { + /* Use some mana */ + caster_ptr->csp -= need_mana; + } else + over_exerted = TRUE; + caster_ptr->redraw |= (PR_MANA); + + /* Failed spell */ + if (randint0(100) < chance) { + if (flush_failure) + flush(); + + msg_format(_("%sをうまく唱えられなかった!", "You failed to get the %s off!"), prayer); + sound(SOUND_FAIL); + + switch (realm) { + case REALM_LIFE: + if (randint1(100) < chance) + chg_virtue(caster_ptr, V_VITALITY, -1); + break; + case REALM_DEATH: + if (randint1(100) < chance) + chg_virtue(caster_ptr, V_UNLIFE, -1); + break; + case REALM_NATURE: + if (randint1(100) < chance) + chg_virtue(caster_ptr, V_NATURE, -1); + break; + case REALM_DAEMON: + if (randint1(100) < chance) + chg_virtue(caster_ptr, V_JUSTICE, 1); + break; + case REALM_CRUSADE: + if (randint1(100) < chance) + chg_virtue(caster_ptr, V_JUSTICE, -1); + break; + case REALM_HEX: + if (randint1(100) < chance) + chg_virtue(caster_ptr, V_COMPASSION, -1); + break; + default: + if (randint1(100) < chance) + chg_virtue(caster_ptr, V_KNOWLEDGE, -1); + break; + } + + /* Failure casting may activate some side effect */ + exe_spell(caster_ptr, realm, spell, SPELL_FAIL); + + if ((o_ptr->tval == TV_CHAOS_BOOK) && (randint1(100) < spell)) { + msg_print(_("カオス的な効果を発生した!", "You produce a chaotic effect!")); + wild_magic(caster_ptr, spell); + } else if ((o_ptr->tval == TV_DEATH_BOOK) && (randint1(100) < spell)) { + if ((sval == 3) && one_in_(2)) { + sanity_blast(caster_ptr, 0, TRUE); + } else { + msg_print(_("痛い!", "It hurts!")); + take_hit(caster_ptr, DAMAGE_LOSELIFE, damroll(o_ptr->sval + 1, 6), _("暗黒魔法の逆流", "a miscast Death spell"), -1); + + if ((spell > 15) && one_in_(6) && !caster_ptr->hold_exp) + lose_exp(caster_ptr, spell * 250); + } + } else if ((o_ptr->tval == TV_MUSIC_BOOK) && (randint1(200) < spell)) { + msg_print(_("いやな音が響いた", "An infernal sound echoed.")); + aggravate_monsters(caster_ptr, 0); + } + if (randint1(100) >= chance) + chg_virtue(caster_ptr, V_CHANCE, -1); + } + + /* Process spell */ + else { + /* Canceled spells cost neither a turn nor mana */ + if (!exe_spell(caster_ptr, realm, spell, SPELL_CAST)) + return; + + if (randint1(100) < chance) + chg_virtue(caster_ptr, V_CHANCE, 1); + + /* A spell was cast */ + if (!(increment ? (caster_ptr->spell_worked2 & (1L << spell)) : (caster_ptr->spell_worked1 & (1L << spell))) && (caster_ptr->pclass != CLASS_SORCERER) + && (caster_ptr->pclass != CLASS_RED_MAGE)) { + int e = s_ptr->sexp; + + /* The spell worked */ + if (realm == caster_ptr->realm1) { + caster_ptr->spell_worked1 |= (1L << spell); + } else { + caster_ptr->spell_worked2 |= (1L << spell); + } + + gain_exp(caster_ptr, e * s_ptr->slevel); + caster_ptr->window |= (PW_OBJECT); + + switch (realm) { + case REALM_LIFE: + chg_virtue(caster_ptr, V_TEMPERANCE, 1); + chg_virtue(caster_ptr, V_COMPASSION, 1); + chg_virtue(caster_ptr, V_VITALITY, 1); + chg_virtue(caster_ptr, V_DILIGENCE, 1); + break; + case REALM_DEATH: + chg_virtue(caster_ptr, V_UNLIFE, 1); + chg_virtue(caster_ptr, V_JUSTICE, -1); + chg_virtue(caster_ptr, V_FAITH, -1); + chg_virtue(caster_ptr, V_VITALITY, -1); + break; + case REALM_DAEMON: + chg_virtue(caster_ptr, V_JUSTICE, -1); + chg_virtue(caster_ptr, V_FAITH, -1); + chg_virtue(caster_ptr, V_HONOUR, -1); + chg_virtue(caster_ptr, V_TEMPERANCE, -1); + break; + case REALM_CRUSADE: + chg_virtue(caster_ptr, V_FAITH, 1); + chg_virtue(caster_ptr, V_JUSTICE, 1); + chg_virtue(caster_ptr, V_SACRIFICE, 1); + chg_virtue(caster_ptr, V_HONOUR, 1); + break; + case REALM_NATURE: + chg_virtue(caster_ptr, V_NATURE, 1); + chg_virtue(caster_ptr, V_HARMONY, 1); + break; + case REALM_HEX: + chg_virtue(caster_ptr, V_JUSTICE, -1); + chg_virtue(caster_ptr, V_FAITH, -1); + chg_virtue(caster_ptr, V_HONOUR, -1); + chg_virtue(caster_ptr, V_COMPASSION, -1); + break; + default: + chg_virtue(caster_ptr, V_KNOWLEDGE, 1); + break; + } + } + switch (realm) { + case REALM_LIFE: + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_TEMPERANCE, 1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_COMPASSION, 1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_VITALITY, 1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_DILIGENCE, 1); + break; + case REALM_DEATH: + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_UNLIFE, 1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_JUSTICE, -1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_FAITH, -1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_VITALITY, -1); + break; + case REALM_DAEMON: + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_JUSTICE, -1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_FAITH, -1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_HONOUR, -1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_TEMPERANCE, -1); + break; + case REALM_CRUSADE: + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_FAITH, 1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_JUSTICE, 1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_SACRIFICE, 1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_HONOUR, 1); + break; + case REALM_NATURE: + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_NATURE, 1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_HARMONY, 1); + break; + case REALM_HEX: + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_JUSTICE, -1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_FAITH, -1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_HONOUR, -1); + if (randint1(100 + caster_ptr->lev) < need_mana) + chg_virtue(caster_ptr, V_COMPASSION, -1); + break; + } + if (mp_ptr->spell_xtra & MAGIC_GAIN_EXP) { + s16b cur_exp = caster_ptr->spell_exp[(increment ? 32 : 0) + spell]; + s16b exp_gain = 0; + + if (cur_exp < SPELL_EXP_BEGINNER) + exp_gain += 60; + else if (cur_exp < SPELL_EXP_SKILLED) { + if ((caster_ptr->current_floor_ptr->dun_level > 4) && ((caster_ptr->current_floor_ptr->dun_level + 10) > caster_ptr->lev)) + exp_gain = 8; + } else if (cur_exp < SPELL_EXP_EXPERT) { + if (((caster_ptr->current_floor_ptr->dun_level + 5) > caster_ptr->lev) && ((caster_ptr->current_floor_ptr->dun_level + 5) > s_ptr->slevel)) + exp_gain = 2; + } else if ((cur_exp < SPELL_EXP_MASTER) && !increment) { + if (((caster_ptr->current_floor_ptr->dun_level + 5) > caster_ptr->lev) && (caster_ptr->current_floor_ptr->dun_level > s_ptr->slevel)) + exp_gain = 1; + } + caster_ptr->spell_exp[(increment ? 32 : 0) + spell] += exp_gain; + } + } + + take_turn(caster_ptr, 100); + + /* Over-exert the player */ + if (over_exerted) { + int oops = need_mana; + + /* No mana left */ + caster_ptr->csp = 0; + caster_ptr->csp_frac = 0; + + msg_print(_("精神を集中しすぎて気を失ってしまった!", "You faint from the effort!")); + + /* Hack -- Bypass free action */ + (void)set_paralyzed(caster_ptr, caster_ptr->paralyzed + randint1(5 * oops + 1)); + + switch (realm) { + case REALM_LIFE: + chg_virtue(caster_ptr, V_VITALITY, -10); + break; + case REALM_DEATH: + chg_virtue(caster_ptr, V_UNLIFE, -10); + break; + case REALM_DAEMON: + chg_virtue(caster_ptr, V_JUSTICE, 10); + break; + case REALM_NATURE: + chg_virtue(caster_ptr, V_NATURE, -10); + break; + case REALM_CRUSADE: + chg_virtue(caster_ptr, V_JUSTICE, -10); + break; + case REALM_HEX: + chg_virtue(caster_ptr, V_COMPASSION, 10); + break; + default: + chg_virtue(caster_ptr, V_KNOWLEDGE, -10); + break; + } + + /* Damage CON (possibly permanently) */ + if (randint0(100) < 50) { + bool perm = (randint0(100) < 25); + + msg_print(_("体を悪くしてしまった!", "You have damaged your health!")); + + /* Reduce constitution */ + (void)dec_stat(caster_ptr, A_CON, 15 + randint1(10), perm); + } + } + + caster_ptr->window |= (PW_PLAYER); + caster_ptr->window |= (PW_SPELL); +} diff --git a/src/cmd-action/cmd-spell.h b/src/cmd-action/cmd-spell.h new file mode 100644 index 000000000..a962b6573 --- /dev/null +++ b/src/cmd-action/cmd-spell.h @@ -0,0 +1,29 @@ +#pragma once + +#include "system/angband.h" + +#define KWD_DAM _("損傷:", "dam ") +#define KWD_RANGE _("射程:", "rng ") +#define KWD_DURATION _("期間:", "dur ") +#define KWD_SPHERE _("範囲:", "range ") +#define KWD_HEAL _("回復:", "heal ") +#define KWD_RANDOM _("ランダム", "random") + +extern const u32b fake_spell_flags[4]; + +concptr info_string_dice(concptr str, DICE_NUMBER dice, DICE_SID sides, int base); +concptr info_damage(DICE_NUMBER dice, DICE_SID sides, int base); +concptr info_duration(int base, DICE_SID sides); +concptr info_range(POSITION range); +concptr info_heal(DICE_NUMBER dice, DICE_SID sides, int base); +concptr info_delay(int base, DICE_SID sides); +concptr info_multi_damage(HIT_POINT dam); +concptr info_multi_damage_dice(DICE_NUMBER dice, DICE_SID sides); +concptr info_power(int power); +concptr info_power_dice(DICE_NUMBER dice, DICE_SID sides); +concptr info_radius(POSITION rad); +concptr info_weight(WEIGHT weight); + +void do_cmd_browse(player_type *caster_ptr); +void do_cmd_study(player_type *caster_ptr); +void do_cmd_cast(player_type *caster_ptr); diff --git a/src/cmd-action/cmd-travel.c b/src/cmd-action/cmd-travel.c new file mode 100644 index 000000000..b55e146b9 --- /dev/null +++ b/src/cmd-action/cmd-travel.c @@ -0,0 +1,175 @@ +#include "cmd-action/cmd-travel.h" +#include "action/travel-execution.h" +#include "core/asking-player.h" +#include "floor/cave.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "player/player-move.h" +#include "system/floor-type-definition.h" +#include "target/grid-selector.h" +#include "view/display-messages.h" +#include "util/bit-flags-calculator.h" + +#define TRAVEL_UNABLE 9999 + +/*! + * @brief トラベル処理中に地形に応じた移動コスト基準を返す + * @param creature_ptr プレーヤーへの参照ポインタ + * @param y 該当地点のY座標 + * @param x 該当地点のX座標 + * @return コスト値 + */ +static int travel_flow_cost(player_type *creature_ptr, POSITION y, POSITION x) +{ + int cost = 1; + feature_type *f_ptr = &f_info[creature_ptr->current_floor_ptr->grid_array[y][x].feat]; + if (have_flag(f_ptr->flags, FF_AVOID_RUN)) + cost += 1; + + if (have_flag(f_ptr->flags, FF_WATER) && have_flag(f_ptr->flags, FF_DEEP) && !creature_ptr->levitation) + cost += 5; + + if (have_flag(f_ptr->flags, FF_LAVA)) { + int lava = 2; + if (!creature_ptr->resist_fire) + lava *= 2; + + if (!creature_ptr->levitation) + lava *= 2; + + if (have_flag(f_ptr->flags, FF_DEEP)) + lava *= 2; + + cost += lava; + } + + if (creature_ptr->current_floor_ptr->grid_array[y][x].info & (CAVE_MARK)) { + if (have_flag(f_ptr->flags, FF_DOOR)) + cost += 1; + + if (have_flag(f_ptr->flags, FF_TRAP)) + cost += 10; + } + + return cost; +} + +/*! + * @brief トラベル処理の到達地点までの行程を得る処理のサブルーチン + * @param creature_ptr プレーヤーへの参照ポインタ + * @param y 目標地点のY座標 + * @param x 目標地点のX座標 + * @param n 現在のコスト + * @param wall プレイヤーが壁の中にいるならばTRUE + * @return なし + */ +static void travel_flow_aux(player_type *creature_ptr, POSITION y, POSITION x, int n, bool wall) +{ + floor_type *floor_ptr = creature_ptr->current_floor_ptr; + grid_type *g_ptr = &floor_ptr->grid_array[y][x]; + feature_type *f_ptr = &f_info[g_ptr->feat]; + if (!in_bounds(floor_ptr, y, x)) + return; + + if (floor_ptr->dun_level > 0 && !(g_ptr->info & CAVE_KNOWN)) + return; + + int add_cost = 1; + int from_wall = (n / TRAVEL_UNABLE); + if (have_flag(f_ptr->flags, FF_WALL) || have_flag(f_ptr->flags, FF_CAN_DIG) || (have_flag(f_ptr->flags, FF_DOOR) && floor_ptr->grid_array[y][x].mimic) + || (!have_flag(f_ptr->flags, FF_MOVE) && have_flag(f_ptr->flags, FF_CAN_FLY) && !creature_ptr->levitation)) { + if (!wall || !from_wall) + return; + + add_cost += TRAVEL_UNABLE; + } else + add_cost = travel_flow_cost(creature_ptr, y, x); + + int base_cost = (n % TRAVEL_UNABLE); + int cost = base_cost + add_cost; + if (travel.cost[y][x] <= cost) + return; + + travel.cost[y][x] = cost; + int old_head = flow_head; + temp2_y[flow_head] = y; + temp2_x[flow_head] = x; + if (++flow_head == MAX_SHORT) + flow_head = 0; + + if (flow_head == flow_tail) + flow_head = old_head; +} + +/*! + * @brief トラベル処理の到達地点までの行程を得る処理のメインルーチン + * @param creature_ptr プレーヤーへの参照ポインタ + * @param ty 目標地点のY座標 + * @param tx 目標地点のX座標 + * @return なし + */ +static void travel_flow(player_type *creature_ptr, POSITION ty, POSITION tx) +{ + flow_head = flow_tail = 0; + bool wall = FALSE; + feature_type *f_ptr = &f_info[creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].feat]; + if (!have_flag(f_ptr->flags, FF_MOVE)) + wall = TRUE; + + travel_flow_aux(creature_ptr, ty, tx, 0, wall); + POSITION x, y; + while (flow_head != flow_tail) { + y = temp2_y[flow_tail]; + x = temp2_x[flow_tail]; + if (++flow_tail == MAX_SHORT) + flow_tail = 0; + + for (DIRECTION d = 0; d < 8; d++) + travel_flow_aux(creature_ptr, y + ddy_ddd[d], x + ddx_ddd[d], travel.cost[y][x], wall); + } + + flow_head = flow_tail = 0; +} + +/*! + * @brief トラベル処理のメインルーチン + * @return なし + */ +void do_cmd_travel(player_type *creature_ptr) +{ + POSITION x, y; + if (travel.x != 0 && travel.y != 0 && get_check(_("トラベルを継続しますか?", "Do you continue to travel?"))) { + y = travel.y; + x = travel.x; + } else if (!tgt_pt(creature_ptr, &x, &y)) + return; + + if ((x == creature_ptr->x) && (y == creature_ptr->y)) { + msg_print(_("すでにそこにいます!", "You are already there!!")); + return; + } + + floor_type *floor_ptr = creature_ptr->current_floor_ptr; + feature_type *f_ptr; + f_ptr = &f_info[floor_ptr->grid_array[y][x].feat]; + if ((floor_ptr->grid_array[y][x].info & CAVE_MARK) + && (have_flag(f_ptr->flags, FF_WALL) || have_flag(f_ptr->flags, FF_CAN_DIG) + || (have_flag(f_ptr->flags, FF_DOOR) && floor_ptr->grid_array[y][x].mimic))) { + msg_print(_("そこには行くことができません!", "You cannot travel there!")); + return; + } + + forget_travel_flow(creature_ptr->current_floor_ptr); + travel_flow(creature_ptr, y, x); + travel.x = x; + travel.y = y; + travel.run = 255; + travel.dir = 0; + POSITION dx = abs(creature_ptr->x - x); + POSITION dy = abs(creature_ptr->y - y); + POSITION sx = ((x == creature_ptr->x) || (dx < dy)) ? 0 : ((x > creature_ptr->x) ? 1 : -1); + POSITION sy = ((y == creature_ptr->y) || (dy < dx)) ? 0 : ((y > creature_ptr->y) ? 1 : -1); + for (int i = 1; i <= 9; i++) + if ((sx == ddx[i]) && (sy == ddy[i])) + travel.dir = i; +} diff --git a/src/cmd-action/cmd-travel.h b/src/cmd-action/cmd-travel.h new file mode 100644 index 000000000..bce4b2c92 --- /dev/null +++ b/src/cmd-action/cmd-travel.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_travel(player_type *creature_ptr); diff --git a/src/cmd-action/cmd-tunnel.c b/src/cmd-action/cmd-tunnel.c new file mode 100644 index 000000000..2d82397ae --- /dev/null +++ b/src/cmd-action/cmd-tunnel.c @@ -0,0 +1,69 @@ +#include "cmd-action/cmd-tunnel.h" +#include "action/tunnel-execution.h" +#include "cmd-action/cmd-attack.h" +#include "core/disturbance.h" +#include "core/player-redraw-types.h" +#include "floor/geometry.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "io/input-key-requester.h" +#include "player/attack-defense-types.h" +#include "player/special-defense-types.h" +#include "status/action-setter.h" +#include "system/floor-type-definition.h" +#include "target/target-getter.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" + +/*! + * @brief 「掘る」動作コマンドのメインルーチン / + * Tunnels through "walls" (including rubble and closed doors) + * @return なし + * @details + *
+ * Note that you must tunnel in order to hit invisible monsters
+ * in walls, though moving into walls still takes a turn anyway.
+ *
+ * Digging is very difficult without a "digger" weapon, but can be
+ * accomplished by strong players using heavy weapons.
+ * 
+ */ +void do_cmd_tunnel(player_type *creature_ptr) +{ + bool more = FALSE; + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + if (command_arg) { + command_rep = command_arg - 1; + creature_ptr->redraw |= PR_STATE; + command_arg = 0; + } + + DIRECTION dir; + if (!get_rep_dir(creature_ptr, &dir, FALSE)) { + if (!more) + disturb(creature_ptr, FALSE, FALSE); + + return; + } + + POSITION y = creature_ptr->y + ddy[dir]; + POSITION x = creature_ptr->x + ddx[dir]; + grid_type *g_ptr; + g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x]; + FEAT_IDX feat = get_feat_mimic(g_ptr); + if (have_flag(f_info[feat].flags, FF_DOOR)) + msg_print(_("ドアは掘れない。", "You cannot tunnel through doors.")); + else if (!have_flag(f_info[feat].flags, FF_TUNNEL)) + msg_print(_("そこは掘れない。", "You can't tunnel through that.")); + else if (g_ptr->m_idx) { + take_turn(creature_ptr, 100); + msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); + do_cmd_attack(creature_ptr, y, x, 0); + } else + more = exe_tunnel(creature_ptr, y, x); + + if (!more) + disturb(creature_ptr, FALSE, FALSE); +} diff --git a/src/cmd-action/cmd-tunnel.h b/src/cmd-action/cmd-tunnel.h new file mode 100644 index 000000000..db5f911ee --- /dev/null +++ b/src/cmd-action/cmd-tunnel.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_tunnel(player_type *creature_ptr); diff --git a/src/cmd-activate.c b/src/cmd-activate.c deleted file mode 100644 index 4cdacc741..000000000 --- a/src/cmd-activate.c +++ /dev/null @@ -1,1780 +0,0 @@ -/*! -* @file cmd-activate.c -* @brief プレイヤーの発動コマンド実装 -* @date 2018/09/07 -* @details -* cmd6.cより分離。 -*/ - -#include "angband.h" -#include "cmd-activate.h" -#include "object-hook.h" -#include "spells-summon.h" -#include "sort.h" -#include "projection.h" -#include "artifact.h" -#include "avatar.h" -#include "spells-status.h" -#include "spells-object.h" -#include "spells-floor.h" -#include "realm-hex.h" -#include "player-status.h" -#include "monster-status.h" - -/*! - * @brief アイテムの発動効果テーブル / - * Define flags, levels, values of activations - */ -const activation_type activation_info[] = -{ - { "SUNLIGHT", ACT_SUNLIGHT, 10, 250, {10, 0}, - _("太陽光線", "beam of sunlight") }, - { "BO_MISS_1", ACT_BO_MISS_1, 10, 250, {2, 0}, - _("マジック・ミサイル(2d6)", "magic missile (2d6)") }, - { "BA_POIS_1", ACT_BA_POIS_1, 10, 300, {4, 0}, - _("悪臭雲(12)", "stinking cloud (12)") }, - { "BO_ELEC_1", ACT_BO_ELEC_1, 20, 250, {5, 0}, - _("サンダー・ボルト(4d8)", "lightning bolt (4d8)") }, - { "BO_ACID_1", ACT_BO_ACID_1, 20, 250, {6, 0}, - _("アシッド・ボルト(5d8)", "acid bolt (5d8)") }, - { "BO_COLD_1", ACT_BO_COLD_1, 20, 250, {7, 0}, - _("アイス・ボルト(6d8)", "frost bolt (6d8)") }, - { "BO_FIRE_1", ACT_BO_FIRE_1, 20, 250, {8, 0}, - _("ファイア・ボルト(9d8)", "fire bolt (9d8)") }, - { "BA_COLD_1", ACT_BA_COLD_1, 30, 750, {6, 0}, - _("アイス・ボール(48)", "ball of cold (48)") }, - { "BA_COLD_2", ACT_BA_COLD_2, 40, 1000, {12, 0}, - _("アイス・ボール(100)", "ball of cold (100)") }, - { "BA_COLD_3", ACT_BA_COLD_3, 70, 2500, {50, 0}, - _("巨大アイス・ボール(400)", "ball of cold (400)") }, - { "BA_FIRE_1", ACT_BA_FIRE_1, 30, 1000, {9, 0}, - _("ファイア・ボール(72)", "ball of fire (72)") }, - { "BA_FIRE_2", ACT_BA_FIRE_2, 40, 1500, {15, 0}, - _("巨大ファイア・ボール(120)", "large fire ball (120)") }, - { "BA_FIRE_3", ACT_BA_FIRE_3, 60, 1750, {40, 0}, - _("巨大ファイア・ボール(300)", "fire ball (300)") }, - { "BA_FIRE_4", ACT_BA_FIRE_4, 40, 1000, {12, 0}, - _("ファイア・ボール(100)", "fire ball (100)") }, - { "BA_ELEC_2", ACT_BA_ELEC_2, 40, 1000, {12, 0}, - _("サンダー・ボール(100)", "ball of lightning (100)") }, - { "BA_ELEC_3", ACT_BA_ELEC_3, 70, 2500, {70, 0}, - _("巨大サンダー・ボール(500)", "ball of lightning (500)") }, - { "BA_ACID_1", ACT_BA_ACID_1, 30, 1000, {12, 0}, - _("アシッド・ボール(100)", "ball of acid (100)") }, - { "BA_NUKE_1", ACT_BA_NUKE_1, 50, 1000, {12, 0}, - _("放射能球(100)", "ball of nuke (100)") }, - { "HYPODYNAMIA_1", ACT_HYPODYNAMIA_1, 30, 500, {12, 0}, - _("窒息攻撃(100)", "a strangling attack (100)") }, - { "HYPODYNAMIA_2", ACT_HYPODYNAMIA_2, 40, 750, {15, 0}, - _("衰弱の矢(120)", "hypodynamic bolt (120)") }, - { "DRAIN_1", ACT_DRAIN_1, 40, 1000, {20, 0}, - _("吸収の矢(3*50)", "drain bolt (3*50)") }, - { "BO_MISS_2", ACT_BO_MISS_2, 40, 1000, {20, 0}, - _("矢(150)", "arrows (150)") }, - { "WHIRLWIND", ACT_WHIRLWIND, 50, 7500, {25, 0}, - _("カマイタチ", "whirlwind attack") }, - { "DRAIN_2", ACT_DRAIN_2, 50, 2500, {40, 0}, - _("吸収の矢(3*100)", "drain bolt (3*100)") }, - { "CALL_CHAOS", ACT_CALL_CHAOS, 70, 5000, {35, 0}, - _("混沌召来", "call chaos") }, - { "ROCKET", ACT_ROCKET, 70, 5000, {20, 0}, - _("ロケット(120+レベル)", "launch rocket (120+level)") }, - { "DISP_EVIL", ACT_DISP_EVIL, 50, 4000, {50, 0}, - _("邪悪退散(x5)", "dispel evil (x5)") }, - { "BA_MISS_3", ACT_BA_MISS_3, 50, 1500, {50, 0}, - _("エレメントのブレス(300)", "elemental breath (300)") }, - { "DISP_GOOD", ACT_DISP_GOOD, 50, 3500, {50, 0}, - _("善良退散(x5)", "dispel good (x5)") }, - { "BO_MANA", ACT_BO_MANA, 40, 1500, {20, 0}, - _("魔法の矢(150)", "a magical arrow (150)") }, - { "BA_WATER", ACT_BA_WATER, 50, 2000, {25, 0}, - _("ウォーター・ボール(200)", "water ball (200)") }, - { "BA_STAR", ACT_BA_STAR, 50, 2200, {25, 0}, - _("巨大スター・ボール(200)", "large star ball (200)") }, - { "BA_DARK", ACT_BA_DARK, 50, 2200, {30, 0}, - _("暗黒の嵐(250)", "darkness storm (250)") }, - { "BA_MANA", ACT_BA_MANA, 70, 2500, {30, 0}, - _("魔力の嵐(250)", "a mana storm (250)") }, - { "PESTICIDE", ACT_PESTICIDE, 10, 500, {10, 0}, - _("害虫の駆除", "dispel small life") }, - { "BLINDING_LIGHT", ACT_BLINDING_LIGHT, 30, 5000, {40, 0}, - _("眩しい光", "blinding light") }, - { "BIZARRE", ACT_BIZARRE, 90, 10000, {50, 0}, - _("信じ難いこと", "bizarre things") }, - { "CAST_BA_STAR", ACT_CAST_BA_STAR, 70, 7500, {100, 0}, - _("スター・ボール・ダスト(150)", "cast star balls (150)") }, - { "BLADETURNER", ACT_BLADETURNER, 80, 20000, {80, 0}, - _("エレメントのブレス(300), 士気高揚、祝福、耐性", "breathe elements (300), hero, bless, and resistance") }, - { "BR_FIRE", ACT_BR_FIRE, 50, 5000, {-1, 0}, - _("火炎のブレス (200)", "fire breath (200)") }, - { "BR_COLD", ACT_BR_COLD, 50, 5000, {-1, 0}, - _("冷気のブレス (200)", "cold breath (200)") }, - { "BR_DRAGON", ACT_BR_DRAGON, 70, 10000, { 30, 0 }, - "" /* built by item_activation_dragon_breath() */ }, - - { "CONFUSE", ACT_CONFUSE, 10, 500, {10, 0}, - _("パニック・モンスター", "confuse monster") }, - { "SLEEP", ACT_SLEEP, 10, 750, {15, 0}, - _("周囲のモンスターを眠らせる", "sleep nearby monsters") }, - { "QUAKE", ACT_QUAKE, 30, 600, {20, 0}, - _("地震", "earthquake") }, - { "TERROR", ACT_TERROR, 20, 2500, {-1, 0}, - _("恐慌", "terror") }, - { "TELE_AWAY", ACT_TELE_AWAY, 20, 2000, {15, 0}, - _("テレポート・アウェイ", "teleport away") }, - { "BANISH_EVIL", ACT_BANISH_EVIL, 40, 2000, {250, 0}, - _("邪悪消滅", "banish evil") }, - { "GENOCIDE", ACT_GENOCIDE, 50, 10000, {500, 0}, - _("抹殺", "genocide") }, - { "MASS_GENO", ACT_MASS_GENO, 50, 10000, {1000, 0}, - _("周辺抹殺", "mass genocide") }, - { "SCARE_AREA", ACT_SCARE_AREA, 20, 2500, {20, 0}, - _("モンスター恐慌", "frighten monsters") }, - { "AGGRAVATE", ACT_AGGRAVATE, 0, 100, {0, 0}, - _("モンスターを怒らせる", "aggravete monsters") }, - - { "CHARM_ANIMAL", ACT_CHARM_ANIMAL, 40, 7500, {200, 0}, - _("動物魅了", "charm animal") }, - { "CHARM_UNDEAD", ACT_CHARM_UNDEAD, 40, 10000, {333, 0}, - _("アンデッド従属", "enslave undead") }, - { "CHARM_OTHER", ACT_CHARM_OTHER, 40, 10000, {400, 0}, - _("モンスター魅了", "charm monster") }, - { "CHARM_ANIMALS", ACT_CHARM_ANIMALS, 40, 12500, {500, 0}, - _("動物友和", "animal friendship") }, - { "CHARM_OTHERS", ACT_CHARM_OTHERS, 40, 17500, {750, 0}, - _("周辺魅了", "mass charm") }, - { "SUMMON_ANIMAL", ACT_SUMMON_ANIMAL, 50, 10000, {200, 300}, - _("動物召喚", "summon animal") }, - { "SUMMON_PHANTOM", ACT_SUMMON_PHANTOM, 50, 12000, {200, 200}, - _("幻霊召喚", "summon phantasmal servant") }, - { "SUMMON_ELEMENTAL", ACT_SUMMON_ELEMENTAL, 50, 15000, {750, 0}, - _("エレメンタル召喚", "summon elemental") }, - { "SUMMON_DEMON", ACT_SUMMON_DEMON, 50, 20000, {666, 0}, - _("悪魔召喚", "summon demon") }, - { "SUMMON_UNDEAD", ACT_SUMMON_UNDEAD, 50, 20000, {666, 0}, - _("アンデッド召喚", "summon undead") }, - { "SUMMON_HOUND", ACT_SUMMON_HOUND, 50, 15000, {300, 0}, - _("ハウンド召喚", "summon hound") }, - { "SUMMON_DAWN", ACT_SUMMON_DAWN, 50, 15000, {500, 0}, - _("暁の師団召喚", "summon the Legion of the Dawn") }, - { "SUMMON_OCTOPUS", ACT_SUMMON_OCTOPUS, 50, 15000, {300, 0}, - _("蛸の大群召喚", "summon octopus") }, - - { "CHOIR_SINGS", ACT_CHOIR_SINGS, 60, 20000, {300, 0}, - _("回復(777)、癒し、士気高揚", "heal 777 hit points, curing and HEROism") }, - { "CURE_LW", ACT_CURE_LW, 10, 500, {10, 0}, - _("恐怖除去/体力回復(30)", "remove fear and heal 30 hp") }, - { "CURE_MW", ACT_CURE_MW, 20, 750, {3, 3}, - _("傷回復(4d8)", "heal 4d8 and wounds") }, - { "CURE_POISON", ACT_CURE_POISON, 10, 1000, {5, 0}, - _("恐怖除去/毒消し", "remove fear and cure poison") }, - { "REST_LIFE", ACT_REST_EXP, 40, 7500, {450, 0}, - _("経験値復活", "restore experience") }, - { "REST_ALL", ACT_REST_ALL, 30, 15000, {750, 0}, - _("全ステータスと経験値復活", "restore stats and experience") }, - { "CURE_700", ACT_CURE_700, 40, 10000, {250, 0}, - _("体力回復(700)", "heal 700 hit points") }, - { "CURE_1000", ACT_CURE_1000, 50, 15000, {888, 0}, - _("体力回復(1000)", "heal 1000 hit points") }, - { "CURING", ACT_CURING, 30, 5000, {100, 0}, - _("癒し", "curing") }, - { "CURE_MANA_FULL", ACT_CURE_MANA_FULL, 60, 20000, {777, 0}, - _("魔力復活", "restore mana") }, - - { "ESP", ACT_ESP, 30, 1500, {100, 0}, - _("テレパシー(期間 25+d30)", "telepathy (dur 25+d30)") }, - { "BERSERK", ACT_BERSERK, 10, 800, {75, 0}, - _("狂戦士化(25+d25ターン)", "berserk (25+d25 turns)") }, - { "PROT_EVIL", ACT_PROT_EVIL, 30, 5000, {100, 0}, - _("対邪悪結界(期間 3*レベル+d25)", "protect evil (dur level*3 + d25)") }, - { "RESIST_ALL", ACT_RESIST_ALL, 30, 5000, {111, 0}, - _("全耐性(期間 20+d20)", "resist elements (dur 20+d20)") }, - { "SPEED", ACT_SPEED, 40, 15000, {250, 0}, - _("加速(期間 20+d20)", "speed (dur 20+d20)") }, - { "XTRA_SPEED", ACT_XTRA_SPEED, 40, 25000, {200, 200}, - _("加速(期間 75+d75)", "speed (dur 75+d75)") }, - { "WRAITH", ACT_WRAITH, 90, 25000, {1000, 0}, - _("幽体化(期間 (レベル/2)+d(レベル/2))", "wraith form (dur level/2 + d(level/2))") }, - { "INVULN", ACT_INVULN, 90, 25000, {1000, 0}, - _("無敵化(期間 8+d8)", "invulnerability (dur 8+d8)") }, - { "HERO", ACT_HERO, 10, 500, {30, 30}, - _("士気高揚", "heroism") }, - { "HERO_SPEED", ACT_HERO_SPEED, 30, 20000, {100, 200}, - _("士気高揚, スピード(期間 50+d50ターン)", "hero and +10 to speed (50)") }, - { "RESIST_ACID", ACT_RESIST_ACID, 20, 2000, {40, 40}, - _("酸への耐性(期間 20+d20)", "resist acid (dur 20+d20)") }, - { "RESIST_FIRE", ACT_RESIST_FIRE, 20, 2000, {40, 40}, - _("火炎への耐性(期間 20+d20)", "resist fire (dur 20+d20)") }, - { "RESIST_COLD", ACT_RESIST_COLD, 20, 2000, {40, 40}, - _("冷気への耐性(期間 20+d20)", "resist cold (dur 20+d20)") }, - { "RESIST_ELEC", ACT_RESIST_ELEC, 20, 2000, {40, 40}, - _("電撃への耐性(期間 20+d20)", "resist elec (dur 20+d20)") }, - { "RESIST_POIS", ACT_RESIST_POIS, 20, 2000, {40, 40}, - _("毒への耐性(期間 20+d20)", "resist poison (dur 20+d20)") }, - - { "LIGHT", ACT_LIGHT, 10, 150, {10, 10}, - _("イルミネーション", "light area (dam 2d15)") }, - { "MAP_LIGHT", ACT_MAP_LIGHT, 30, 500, {50, 50}, - _("魔法の地図と光", "light (dam 2d15) & map area") }, - { "DETECT_ALL", ACT_DETECT_ALL, 30, 1000, {55, 55}, - _("全感知", "detection") }, - { "DETECT_XTRA", ACT_DETECT_XTRA, 50, 12500, {100, 0}, - _("全感知、探索、*鑑定*", "detection, probing and identify true") }, - { "ID_FULL", ACT_ID_FULL, 50, 10000, {75, 0}, - _("*鑑定*", "identify true") }, - { "ID_PLAIN", ACT_ID_PLAIN, 20, 1250, {10, 0}, - _("鑑定", "identify spell") }, - { "RUNE_EXPLO", ACT_RUNE_EXPLO, 40, 4000, {200, 0}, - _("爆発のルーン", "explosive rune") }, - { "RUNE_PROT", ACT_RUNE_PROT, 60, 10000, {400, 0}, - _("守りのルーン", "rune of protection") }, - { "SATIATE", ACT_SATIATE, 10, 2000, {200, 0}, - _("空腹充足", "satisfy hunger") }, - { "DEST_DOOR", ACT_DEST_DOOR, 10, 100, {10, 0}, - _("ドア破壊", "destroy doors") }, - { "STONE_MUD", ACT_STONE_MUD, 20, 1000, {3, 0}, - _("岩石溶解", "stone to mud") }, - { "RECHARGE", ACT_RECHARGE, 30, 1000, {70, 0}, - _("魔力充填", "recharging") }, - { "ALCHEMY", ACT_ALCHEMY, 50, 10000, {500, 0}, - _("錬金術", "alchemy") }, - { "DIM_DOOR", ACT_DIM_DOOR, 50, 10000, {100, 0}, - _("次元の扉", "dimension door") }, - { "TELEPORT", ACT_TELEPORT, 10, 2000, {25, 0}, - _("テレポート", "teleport") }, - { "RECALL", ACT_RECALL, 30, 7500, {200, 0}, - _("帰還の詔", "word of recall") }, - { "JUDGE", ACT_JUDGE, 90, 50000, {20, 20}, - _("体力と引き替えに千里眼と帰還", "a telekinesis (500 lb)") }, - { "TELEKINESIS", ACT_TELEKINESIS, 20, 5500, {25, 25}, - _("物体を引き寄せる(重量25kgまで)", "clairvoyance and recall, draining you") }, - { "DETECT_UNIQUE", ACT_DETECT_UNIQUE, 40, 10000, {200, 0}, - _("この階にいるユニークモンスターを表示", "list of the uniques on the level") }, - { "ESCAPE", ACT_ESCAPE, 10, 3000, {35, 0}, - _("逃走", "a getaway") }, - { "DISP_CURSE_XTRA", ACT_DISP_CURSE_XTRA, 40, 30000, {0, 0}, - _("*解呪*と調査", "dispel curse and probing") }, - { "BRAND_FIRE_BOLTS", ACT_BRAND_FIRE_BOLTS, 40, 20000, {999, 0}, - _("刃先のファイア・ボルト", "fire branding of bolts") }, - { "RECHARGE_XTRA", ACT_RECHARGE_XTRA, 70, 30000, {200, 0}, - _("魔力充填", "recharge item") }, - { "LORE", ACT_LORE, 10, 30000, {0, 0}, - _("危険を伴う鑑定", "perilous identify") }, - { "SHIKOFUMI", ACT_SHIKOFUMI, 10, 10000, {100, 100}, - _("四股踏み", "shiko") }, - { "PHASE_DOOR", ACT_PHASE_DOOR, 10, 1500, {10, 0}, - _("ショート・テレポート", "blink") }, - { "DETECT_ALL_MONS", ACT_DETECT_ALL_MONS, 30, 3000, {150, 0}, - _("全モンスター感知", "detect all monsters") }, - { "ULTIMATE_RESIST", ACT_ULTIMATE_RESIST, 90, 20000, {777, 0}, - _("士気高揚、祝福、究極の耐性", "hero, bless, and ultimate resistance") }, - - { "CAST_OFF", ACT_CAST_OFF, 30, 15000, {100, 0}, - _("脱衣と小宇宙燃焼", "cast it off and cosmic heroism") }, - { "FISHING", ACT_FISHING, 0, 100, {0, 0}, - _("釣りをする", "fishing") }, - { "INROU", ACT_INROU, 40, 15000, {150, 150}, - _("例のアレ", "reveal your identity") }, - { "MURAMASA", ACT_MURAMASA, 0, 0, {-1, 0}, - _("腕力の上昇", "increase STR") }, - { "BLOODY_MOON", ACT_BLOODY_MOON, 0, 0, {3333, 0}, - _("属性変更", "change zokusei") }, - { "CRIMSON", ACT_CRIMSON, 0, 50000, {15, 0}, - _("ファイア!", "fire!") }, - - { "STRAIN_HASTE", ACT_STRAIN_HASTE, 10, 1000, {120, 100}, - _("体力と引き換えに加速", "haste with strain") }, - { "GRAND_CROSS", ACT_GRAND_CROSS, 30, 15000, {250, 200}, - _("グランド・クロス", "grand cross") }, - { "TELEPORT_LEVEL", ACT_TELEPORT_LEVEL, 10, 1500, {100, 200}, - _("テレポート・レベル", "teleort level") }, - { "ARTS_FALLING_STAR", ACT_FALLING_STAR, 20, 5500, {30, 50}, - _("魔剣・流れ星", "blade arts 'falling star'") }, - { NULL, 0, 0, 0, {0, 0}, - "" } -}; - -/*! - * @brief 装備を発動するコマンドのサブルーチン / - * Activate a wielded object. Wielded objects never stack. - * And even if they did, activatable objects never stack. - * @param item 発動するオブジェクトの所持品ID - * @return なし - * @details - *
- * Currently, only (some) artifacts, and Dragon Scale Mail, can be activated.
- * But one could, for example, easily make an activatable "Ring of Plasma".
- * Note that it always takes a current_world_ptr->game_turn to activate an artifact, even if
- * the user hits "escape" at the "direction" prompt.
- * 
- */ -void do_cmd_activate_aux(INVENTORY_IDX item) -{ - DIRECTION dir; - DEPTH lev; - int chance, fail; - object_type *o_ptr; - bool success; - - - /* Get the item (in the pack) */ - if (item >= 0) - { - o_ptr = &inventory[item]; - } - - /* Get the item (on the floor) */ - else - { - o_ptr = ¤t_floor_ptr->o_list[0 - item]; - } - - take_turn(p_ptr, 100); - - /* Extract the item level */ - lev = k_info[o_ptr->k_idx].level; - - /* Hack -- use artifact level instead */ - if (object_is_fixed_artifact(o_ptr)) lev = a_info[o_ptr->name1].level; - else if (object_is_random_artifact(o_ptr)) - { - const activation_type* const act_ptr = find_activation_info(o_ptr); - if (act_ptr) { - lev = act_ptr->level; - } - } - else if (((o_ptr->tval == TV_RING) || (o_ptr->tval == TV_AMULET)) && o_ptr->name2) lev = e_info[o_ptr->name2].level; - - /* Base chance of success */ - chance = p_ptr->skill_dev; - - /* Confusion hurts skill */ - if (p_ptr->confused) chance = chance / 2; - - fail = lev+5; - if (chance > fail) fail -= (chance - fail)*2; - else chance -= (fail - chance)*2; - if (fail < USE_DEVICE) fail = USE_DEVICE; - if (chance < USE_DEVICE) chance = USE_DEVICE; - - if(cmd_limit_time_walk(p_ptr)) return; - - if (p_ptr->pclass == CLASS_BERSERKER) success = FALSE; - else if (chance > fail) - { - if (randint0(chance*2) < fail) success = FALSE; - else success = TRUE; - } - else - { - if (randint0(fail*2) < chance) success = TRUE; - else success = FALSE; - } - - /* Roll for usage */ - if (!success) - { - if (flush_failure) flush(); - msg_print(_("うまく始動させることができなかった。", "You failed to activate it properly.")); - sound(SOUND_FAIL); - return; - } - - /* Check the recharge */ - if (o_ptr->timeout) - { - msg_print(_("それは微かに音を立て、輝き、消えた...", "It whines, glows and fades...")); - return; - } - - /* Some lights need enough fuel for activation */ - if (!o_ptr->xtra4 && (o_ptr->tval == TV_FLASK) && - ((o_ptr->sval == SV_LITE_TORCH) || (o_ptr->sval == SV_LITE_LANTERN))) - { - msg_print(_("燃料がない。", "It has no fuel.")); - free_turn(p_ptr); - return; - } - - /* Activate the artifact */ - msg_print(_("始動させた...", "You activate it...")); - - sound(SOUND_ZAP); - - /* Activate object */ - if (activation_index(o_ptr)) - { - (void)activate_artifact(o_ptr); - - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* Success */ - return; - } - - /* Special items */ - else if (o_ptr->tval == TV_WHISTLE) - { - if (music_singing_any()) stop_singing(p_ptr); - if (hex_spelling_any()) stop_hex_spell_all(); - - { - IDX pet_ctr, i; - MONSTER_IDX *who; - int max_pet = 0; - u16b dummy_why; - - /* Allocate the "who" array */ - C_MAKE(who, current_floor_ptr->max_m_idx, MONSTER_IDX); - - /* Process the monsters (backwards) */ - for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) - { - if (is_pet(¤t_floor_ptr->m_list[pet_ctr]) && (p_ptr->riding != pet_ctr)) - who[max_pet++] = pet_ctr; - } - - ang_sort(who, &dummy_why, max_pet, ang_sort_comp_pet, ang_sort_swap_hook); - - /* Process the monsters (backwards) */ - for (i = 0; i < max_pet; i++) - { - pet_ctr = who[i]; - teleport_monster_to(pet_ctr, p_ptr->y, p_ptr->x, 100, TELEPORT_PASSIVE); - } - - /* Free the "who" array */ - C_KILL(who, current_floor_ptr->max_m_idx, IDX); - } - o_ptr->timeout = 100 + randint1(100); - return; - } - else if (o_ptr->tval == TV_CAPTURE) - { - if(!o_ptr->pval) - { - bool old_target_pet = target_pet; - target_pet = TRUE; - if (!get_aim_dir(&dir)) - { - target_pet = old_target_pet; - return; - } - target_pet = old_target_pet; - - if(fire_ball(GF_CAPTURE, dir, 0, 0)) - { - o_ptr->pval = (PARAMETER_VALUE)cap_mon; - o_ptr->xtra3 = (XTRA8)cap_mspeed; - o_ptr->xtra4 = (XTRA16)cap_hp; - o_ptr->xtra5 = (XTRA16)cap_maxhp; - if (cap_nickname) - { - concptr t; - char *s; - char buf[80] = ""; - - if (o_ptr->inscription) - strcpy(buf, quark_str(o_ptr->inscription)); - s = buf; - for (s = buf;*s && (*s != '#'); s++) - { -#ifdef JP - if (iskanji(*s)) s++; -#endif - } - *s = '#'; - s++; -#ifdef JP - /*nothing*/ -#else - *s++ = '\''; -#endif - t = quark_str(cap_nickname); - while (*t) - { - *s = *t; - s++; - t++; - } -#ifdef JP - /*nothing*/ -#else - *s++ = '\''; -#endif - *s = '\0'; - o_ptr->inscription = quark_add(buf); - } - } - } - else - { - success = FALSE; - if (!get_direction(&dir, FALSE, FALSE)) return; - if (monster_can_enter(p_ptr->y + ddy[dir], p_ptr->x + ddx[dir], &r_info[o_ptr->pval], 0)) - { - if (place_monster_aux(0, p_ptr->y + ddy[dir], p_ptr->x + ddx[dir], o_ptr->pval, (PM_FORCE_PET | PM_NO_KAGE))) - { - if (o_ptr->xtra3) current_floor_ptr->m_list[hack_m_idx_ii].mspeed = o_ptr->xtra3; - if (o_ptr->xtra5) current_floor_ptr->m_list[hack_m_idx_ii].max_maxhp = o_ptr->xtra5; - if (o_ptr->xtra4) current_floor_ptr->m_list[hack_m_idx_ii].hp = o_ptr->xtra4; - current_floor_ptr->m_list[hack_m_idx_ii].maxhp = current_floor_ptr->m_list[hack_m_idx_ii].max_maxhp; - if (o_ptr->inscription) - { - char buf[80]; - concptr t; -#ifndef JP - bool quote = FALSE; -#endif - - t = quark_str(o_ptr->inscription); - for (t = quark_str(o_ptr->inscription);*t && (*t != '#'); t++) - { -#ifdef JP - if (iskanji(*t)) t++; -#endif - } - if (*t) - { - char *s = buf; - t++; -#ifdef JP - /* nothing */ -#else - if (*t =='\'') - { - t++; - quote = TRUE; - } -#endif - while(*t) - { - *s = *t; - t++; - s++; - } -#ifdef JP - /* nothing */ -#else - if (quote && *(s-1) =='\'') - s--; -#endif - *s = '\0'; - current_floor_ptr->m_list[hack_m_idx_ii].nickname = quark_add(buf); - t = quark_str(o_ptr->inscription); - s = buf; - while(*t && (*t != '#')) - { - *s = *t; - t++; - s++; - } - *s = '\0'; - o_ptr->inscription = quark_add(buf); - } - } - o_ptr->pval = 0; - o_ptr->xtra3 = 0; - o_ptr->xtra4 = 0; - o_ptr->xtra5 = 0; - success = TRUE; - } - } - if (!success) - msg_print(_("おっと、解放に失敗した。", "Oops. You failed to release your pet.")); - } - calc_android_exp(); - return; - } - - /* Mistake */ - msg_print(_("おっと、このアイテムは始動できない。", "Oops. That object cannot be activated.")); -} - -/*! - * @brief 装備を発動するコマンドのメインルーチン / - * @return なし - */ -void do_cmd_activate(void) -{ - OBJECT_IDX item; - concptr q, s; - - if (p_ptr->wild_mode) return; - if (cmd_limit_arena(p_ptr)) return; - - if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) - { - set_action(ACTION_NONE); - } - - item_tester_hook = item_tester_hook_activate; - - q = _("どのアイテムを始動させますか? ", "Activate which item? "); - s = _("始動できるアイテムを装備していない。", "You have nothing to activate."); - - if (!choose_object(&item, q, s, (USE_EQUIP | IGNORE_BOTHHAND_SLOT))) return; - - /* Activate the item */ - do_cmd_activate_aux(item); -} - -/*! -* @brief 発動によるブレスの属性をアイテムの耐性から選択し、実行を処理する。/ Dragon breath activation -* @details 対象となる耐性は dragonbreath_info テーブルを参照のこと。 -* @param o_ptr 対象のオブジェクト構造体ポインタ -* @return 発動実行の是非を返す。 -*/ -static bool activate_dragon_breath(object_type *o_ptr) -{ - BIT_FLAGS flgs[TR_FLAG_SIZE]; /* for resistance flags */ - int type[20]; - concptr name[20]; - int i, t, n = 0; - DIRECTION dir; - - if (!get_aim_dir(&dir)) return FALSE; - - object_flags(o_ptr, flgs); - - for (i = 0; dragonbreath_info[i].flag != 0; i++) - { - if (have_flag(flgs, dragonbreath_info[i].flag)) - { - type[n] = dragonbreath_info[i].type; - name[n] = dragonbreath_info[i].name; - n++; - } - } - if (n == 0) return FALSE; - - /* Stop speaking */ - if (music_singing_any()) stop_singing(p_ptr); - if (hex_spelling_any()) stop_hex_spell_all(); - - t = randint0(n); - msg_format(_("あなたは%sのブレスを吐いた。", "You breathe %s."), name[t]); - fire_breath(type[t], dir, 250, 4); - - return TRUE; -} - -/*! - * @brief アイテムの発動効果を処理する。 - * @param o_ptr 対象のオブジェクト構造体ポインタ - * @return 発動実行の是非を返す。 - */ -bool activate_artifact(object_type *o_ptr) -{ - PLAYER_LEVEL plev = p_ptr->lev; - int k, dummy = 0; - DIRECTION dir; - concptr name = k_name + k_info[o_ptr->k_idx].name; - const activation_type* const act_ptr = find_activation_info(o_ptr); - if (!act_ptr) { - /* Maybe forgot adding information to activation_info table ? */ - msg_print("Activation information is not found."); - return FALSE; - } - - /* Activate for attack */ - switch (act_ptr->index) - { - case ACT_SUNLIGHT: - { - if (!get_aim_dir(&dir)) return FALSE; - msg_print(_("太陽光線が放たれた。", "A line of sunlight appears.")); - (void)lite_line(dir, damroll(6, 8)); - break; - } - - case ACT_BO_MISS_1: - { - msg_print(_("それは眩しいくらいに明るく輝いている...", "It glows extremely brightly...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_bolt(GF_MISSILE, dir, damroll(2, 6)); - break; - } - - case ACT_BA_POIS_1: - { - msg_print(_("それは濃緑色に脈動している...", "It throbs deep green...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_POIS, dir, 12, 3); - break; - } - - case ACT_BO_ELEC_1: - { - msg_print(_("それは火花に覆われた...", "It is covered in sparks...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_bolt(GF_ELEC, dir, damroll(4, 8)); - break; - } - - case ACT_BO_ACID_1: - { - msg_print(_("それは酸に覆われた...", "It is covered in acid...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_bolt(GF_ACID, dir, damroll(5, 8)); - break; - } - - case ACT_BO_COLD_1: - { - msg_print(_("それは霜に覆われた...", "It is covered in frost...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_bolt(GF_COLD, dir, damroll(6, 8)); - break; - } - - case ACT_BO_FIRE_1: - { - msg_print(_("それは炎に覆われた...", "It is covered in fire...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_bolt(GF_FIRE, dir, damroll(9, 8)); - break; - } - - case ACT_BA_COLD_1: - { - msg_print(_("それは霜に覆われた...", "It is covered in frost...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_COLD, dir, 48, 2); - break; - } - - case ACT_BA_COLD_2: - { - msg_print(_("それは青く激しく輝いた...", "It glows an intense blue...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_COLD, dir, 100, 2); - break; - } - - case ACT_BA_COLD_3: - { - msg_print(_("明るく白色に輝いている...", "It glows bright white...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_COLD, dir, 400, 3); - break; - } - - case ACT_BA_FIRE_1: - { - msg_print(_("それは赤く激しく輝いた...", "It glows an intense red...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_FIRE, dir, 72, 2); - break; - } - - case ACT_BA_FIRE_2: - { - msg_format(_("%sから炎が吹き出した...", "The %s rages in fire..."), name); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_FIRE, dir, 120, 3); - break; - } - - case ACT_BA_FIRE_3: - { - msg_print(_("深赤色に輝いている...", "It glows deep red...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_FIRE, dir, 300, 3); - break; - } - - case ACT_BA_FIRE_4: - { - msg_print(_("それは赤く激しく輝いた...", "It glows an intense red...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_FIRE, dir, 100, 2); - break; - } - - case ACT_BA_ELEC_2: - { - msg_print(_("電気がパチパチ音を立てた...", "It crackles with electricity...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_ELEC, dir, 100, 3); - break; - } - - case ACT_BA_ELEC_3: - { - msg_print(_("深青色に輝いている...", "It glows deep blue...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_ELEC, dir, 500, 3); - break; - } - - case ACT_BA_ACID_1: - { - msg_print(_("それは黒く激しく輝いた...", "It glows an intense black...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_ACID, dir, 100, 2); - break; - } - - case ACT_BA_NUKE_1: - { - msg_print(_("それは緑に激しく輝いた...", "It glows an intense green...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_NUKE, dir, 100, 2); - break; - } - - case ACT_HYPODYNAMIA_1: - { - msg_format(_("あなたは%sに敵を締め殺すよう命じた。", "You order the %s to strangle your opponent."), name); - if (!get_aim_dir(&dir)) return FALSE; - if (hypodynamic_bolt(dir, 100)) - break; - } - - case ACT_HYPODYNAMIA_2: - { - msg_print(_("黒く輝いている...", "It glows black...")); - if (!get_aim_dir(&dir)) return FALSE; - hypodynamic_bolt(dir, 120); - break; - } - - case ACT_DRAIN_1: - { - if (!get_aim_dir(&dir)) return FALSE; - for (dummy = 0; dummy < 3; dummy++) - { - if (hypodynamic_bolt(dir, 50)) - hp_player(50); - } - break; - } - - case ACT_BO_MISS_2: - { - msg_print(_("魔法のトゲが現れた...", "It grows magical spikes...")); - if (!get_aim_dir(&dir)) return FALSE; - fire_bolt(GF_ARROW, dir, 150); - break; - } - - case ACT_WHIRLWIND: - { - massacre(); - break; - } - - case ACT_DRAIN_2: - { - if (!get_aim_dir(&dir)) return FALSE; - for (dummy = 0; dummy < 3; dummy++) - { - if (hypodynamic_bolt(dir, 100)) - hp_player(100); - } - break; - } - - - case ACT_CALL_CHAOS: - { - msg_print(_("様々な色の火花を発している...", "It glows in scintillating colours...")); - call_chaos(); - break; - } - - case ACT_ROCKET: - { - if (!get_aim_dir(&dir)) return FALSE; - msg_print(_("ロケットを発射した!", "You launch a rocket!")); - fire_ball(GF_ROCKET, dir, 250 + plev * 3, 2); - break; - } - - case ACT_DISP_EVIL: - { - msg_print(_("神聖な雰囲気が充満した...", "It floods the area with goodness...")); - dispel_evil(p_ptr->lev * 5); - break; - } - - case ACT_BA_MISS_3: - { - if (!get_aim_dir(&dir)) return FALSE; - msg_print(_("あなたはエレメントのブレスを吐いた。", "You breathe the elements.")); - fire_breath(GF_MISSILE, dir, 300, 4); - break; - } - - case ACT_DISP_GOOD: - { - msg_print(_("邪悪な雰囲気が充満した...", "It floods the area with evil...")); - dispel_good(p_ptr->lev * 5); - break; - } - - case ACT_BO_MANA: - { - msg_format(_("%sに魔法のトゲが現れた...", "The %s grows magical spikes..."), name); - if (!get_aim_dir(&dir)) return FALSE; - fire_bolt(GF_ARROW, dir, 150); - break; - } - - case ACT_BA_WATER: - { - msg_format(_("%sが深い青色に鼓動している...", "The %s throbs deep blue..."), name); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_WATER, dir, 200, 3); - break; - } - - case ACT_BA_DARK: - { - msg_format(_("%sが深い闇に覆われた...", "The %s is coverd in pitch-darkness..."), name); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_DARK, dir, 250, 4); - break; - } - - case ACT_BA_MANA: - { - msg_format(_("%sが青白く光った...", "The %s glows pale..."), name); - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_MANA, dir, 250, 4); - break; - } - - case ACT_PESTICIDE: - { - msg_print(_("あなたは害虫を一掃した。", "You exterminate small life.")); - (void)dispel_monsters(4); - break; - } - - case ACT_BLINDING_LIGHT: - { - msg_format(_("%sが眩しい光で輝いた...", "The %s gleams with blinding light..."), name); - fire_ball(GF_LITE, 0, 300, 6); - confuse_monsters(3 * p_ptr->lev / 2); - break; - } - - case ACT_BIZARRE: - { - msg_format(_("%sは漆黒に輝いた...", "The %s glows intensely black..."), name); - if (!get_aim_dir(&dir)) return FALSE; - ring_of_power(dir); - break; - } - - case ACT_CAST_BA_STAR: - { - HIT_POINT num = damroll(5, 3); - POSITION y = 0, x = 0; - int attempts; - msg_format(_("%sが稲妻で覆われた...", "The %s is surrounded by lightning..."), name); - for (k = 0; k < num; k++) - { - attempts = 1000; - - while (attempts--) - { - scatter(&y, &x, p_ptr->y, p_ptr->x, 4, 0); - if (!cave_have_flag_bold(y, x, FF_PROJECT)) continue; - if (!player_bold(y, x)) break; - } - - project(0, 3, y, x, 150, GF_ELEC, - (PROJECT_THRU | PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL), -1); - } - - break; - } - - case ACT_BLADETURNER: - { - if (!get_aim_dir(&dir)) return FALSE; - msg_print(_("あなたはエレメントのブレスを吐いた。", "You breathe the elements.")); - fire_breath(GF_MISSILE, dir, 300, 4); - msg_print(_("鎧が様々な色に輝いた...", "Your armor glows many colours...")); - (void)set_afraid(0); - (void)set_hero(randint1(50) + 50, FALSE); - (void)hp_player(10); - (void)set_blessed(randint1(50) + 50, FALSE); - (void)set_oppose_acid(randint1(50) + 50, FALSE); - (void)set_oppose_elec(randint1(50) + 50, FALSE); - (void)set_oppose_fire(randint1(50) + 50, FALSE); - (void)set_oppose_cold(randint1(50) + 50, FALSE); - (void)set_oppose_pois(randint1(50) + 50, FALSE); - break; - } - - case ACT_BR_FIRE: - { - if (!get_aim_dir(&dir)) return FALSE; - fire_breath(GF_FIRE, dir, 200, 2); - if ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_FLAMES)) - { - (void)set_oppose_fire(randint1(20) + 20, FALSE); - } - break; - } - - case ACT_BR_COLD: - { - if (!get_aim_dir(&dir)) return FALSE; - fire_breath(GF_COLD, dir, 200, 2); - if ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_ICE)) - { - (void)set_oppose_cold(randint1(20) + 20, FALSE); - } - break; - } - - case ACT_BR_DRAGON: - { - if (!activate_dragon_breath(o_ptr)) return FALSE; - break; - } - - /* Activate for other offensive action */ - case ACT_CONFUSE: - { - msg_print(_("様々な色の火花を発している...", "It glows in scintillating colours...")); - if (!get_aim_dir(&dir)) return FALSE; - confuse_monster(dir, 20); - break; - } - - case ACT_SLEEP: - { - msg_print(_("深青色に輝いている...", "It glows deep blue...")); - sleep_monsters_touch(); - break; - } - - case ACT_QUAKE: - { - earthquake(p_ptr->y, p_ptr->x, 5); - break; - } - - case ACT_TERROR: - { - turn_monsters(40 + p_ptr->lev); - break; - } - - case ACT_TELE_AWAY: - { - if (!get_aim_dir(&dir)) return FALSE; - (void)fire_beam(GF_AWAY_ALL, dir, plev); - break; - } - - case ACT_BANISH_EVIL: - { - if (banish_evil(100)) - { - msg_print(_("アーティファクトの力が邪悪を打ち払った!", "The power of the artifact banishes evil!")); - } - break; - } - - case ACT_GENOCIDE: - { - msg_print(_("深青色に輝いている...", "It glows deep blue...")); - (void)symbol_genocide(200, TRUE); - break; - } - - case ACT_MASS_GENO: - { - msg_print(_("ひどく鋭い音が流れ出た...", "It lets out a long, shrill note...")); - (void)mass_genocide(200, TRUE); - break; - } - - case ACT_SCARE_AREA: - { - if (music_singing_any()) stop_singing(p_ptr); - if (hex_spelling_any()) stop_hex_spell_all(); - msg_print(_("あなたは力強い突風を吹き鳴らした。周囲の敵が震え上っている!", - "You wind a mighty blast; your enemies tremble!")); - (void)turn_monsters((3 * p_ptr->lev / 2) + 10); - break; - } - - case ACT_AGGRAVATE: - { - if (o_ptr->name1 == ART_HYOUSIGI) - { - msg_print(_("拍子木を打った。", "You beat Your wooden clappers.")); - } - else - { - msg_format(_("%sは不快な物音を立てた。", "The %s sounds an unpleasant noise."), name); - } - aggravate_monsters(0); - break; - } - - /* Activate for summoning / charming */ - - case ACT_CHARM_ANIMAL: - { - if (!get_aim_dir(&dir)) return FALSE; - (void)charm_animal(dir, plev); - break; - } - - case ACT_CHARM_UNDEAD: - { - if (!get_aim_dir(&dir)) return FALSE; - (void)control_one_undead(dir, plev); - break; - } - - case ACT_CHARM_OTHER: - { - if (!get_aim_dir(&dir)) return FALSE; - (void)charm_monster(dir, plev * 2); - break; - } - - case ACT_CHARM_ANIMALS: - { - (void)charm_animals(plev * 2); - break; - } - - case ACT_CHARM_OTHERS: - { - charm_monsters(plev * 2); - break; - } - - case ACT_SUMMON_ANIMAL: - { - (void)summon_specific(-1, p_ptr->y, p_ptr->x, plev, SUMMON_ANIMAL_RANGER, (PM_ALLOW_GROUP | PM_FORCE_PET), '\0'); - break; - } - - case ACT_SUMMON_PHANTOM: - { - msg_print(_("幻霊を召喚した。", "You summon a phantasmal servant.")); - (void)summon_specific(-1, p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, SUMMON_PHANTOM, (PM_ALLOW_GROUP | PM_FORCE_PET), '\0'); - break; - } - - case ACT_SUMMON_ELEMENTAL: - if (!cast_summon_elemental(p_ptr, (plev * 3) / 2)) return FALSE; - break; - - case ACT_SUMMON_DEMON: - { - cast_summon_demon((plev * 3) / 2); - break; - } - - case ACT_SUMMON_UNDEAD: - if (!cast_summon_undead(p_ptr, (plev * 3) / 2)) return FALSE; - break; - - case ACT_SUMMON_HOUND: - if (!cast_summon_hound(p_ptr, (plev * 3) / 2)) return FALSE; - break; - - case ACT_SUMMON_DAWN: - { - msg_print(_("暁の師団を召喚した。", "You summon the Legion of the Dawn.")); - (void)summon_specific(-1, p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, SUMMON_DAWN, (PM_ALLOW_GROUP | PM_FORCE_PET), '\0'); - break; - } - - case ACT_SUMMON_OCTOPUS: - if(!cast_summon_octopus(p_ptr)) return FALSE; - break; - - /* Activate for healing */ - - case ACT_CHOIR_SINGS: - { - msg_print(_("天国の歌が聞こえる...", "A heavenly choir sings...")); - (void)cure_critical_wounds(777); - (void)set_hero(randint1(25) + 25, FALSE); - break; - } - - case ACT_CURE_LW: - { - (void)set_afraid(0); - (void)hp_player(30); - break; - } - - case ACT_CURE_MW: - { - msg_print(_("深紫色の光を発している...", "It radiates deep purple...")); - (void)cure_serious_wounds(4, 8); - break; - } - - case ACT_CURE_POISON: - { - msg_print(_("深青色に輝いている...", "It glows deep blue...")); - (void)set_afraid(0); - (void)set_poisoned(0); - break; - } - - case ACT_REST_EXP: - { - msg_print(_("深紅に輝いている...", "It glows a deep red...")); - restore_level(); - break; - } - - case ACT_REST_ALL: - { - msg_print(_("濃緑色に輝いている...", "It glows a deep green...")); - (void)restore_all_status(); - (void)restore_level(); - break; - } - - case ACT_CURE_700: - { - msg_print(_("深青色に輝いている...", "It glows deep blue...")); - msg_print(_("体内に暖かい鼓動が感じられる...", "You feel a warm tingling inside...")); - (void)cure_critical_wounds(700); - break; - } - - case ACT_CURE_1000: - { - msg_print(_("白く明るく輝いている...", "It glows a bright white...")); - msg_print(_("ひじょうに気分がよい...", "You feel much better...")); - (void)cure_critical_wounds(1000); - break; - } - - case ACT_CURING: - { - msg_format(_("%sの優しさに癒される...", "the %s cures you affectionately ..."), name); - true_healing(0); - break; - } - - case ACT_CURE_MANA_FULL: - { - msg_format(_("%sが青白く光った...", "The %s glows pale..."), name); - restore_mana(TRUE); - break; - } - - /* Activate for timed effect */ - - case ACT_ESP: - { - (void)set_tim_esp(randint1(30) + 25, FALSE); - break; - } - - case ACT_BERSERK: - { - (void)berserk(randint1(25) + 25); - break; - } - - case ACT_PROT_EVIL: - { - msg_format(_("%sから鋭い音が流れ出た...", "The %s lets out a shrill wail..."), name); - k = 3 * p_ptr->lev; - (void)set_protevil(randint1(25) + k, FALSE); - break; - } - - case ACT_RESIST_ALL: - { - msg_print(_("様々な色に輝いている...", "It glows many colours...")); - (void)set_oppose_acid(randint1(40) + 40, FALSE); - (void)set_oppose_elec(randint1(40) + 40, FALSE); - (void)set_oppose_fire(randint1(40) + 40, FALSE); - (void)set_oppose_cold(randint1(40) + 40, FALSE); - (void)set_oppose_pois(randint1(40) + 40, FALSE); - break; - } - - case ACT_SPEED: - { - msg_print(_("明るく緑色に輝いている...", "It glows bright green...")); - (void)set_fast(randint1(20) + 20, FALSE); - break; - } - - case ACT_XTRA_SPEED: - { - msg_print(_("明るく輝いている...", "It glows brightly...")); - (void)set_fast(randint1(75) + 75, FALSE); - break; - } - - case ACT_WRAITH: - { - set_wraith_form(randint1(plev / 2) + (plev / 2), FALSE); - break; - } - - case ACT_INVULN: - { - (void)set_invuln(randint1(8) + 8, FALSE); - break; - } - - case ACT_HERO: - { - (void)heroism(25); - break; - } - - case ACT_HERO_SPEED: - { - (void)set_fast(randint1(50) + 50, FALSE); - (void)heroism(50); - break; - } - - case ACT_RESIST_ACID: - { - msg_format(_("%sが黒く輝いた...", "The %s grows black."), name); - if ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_ACID)) - { - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_ACID, dir, 100, 2); - } - (void)set_oppose_acid(randint1(20) + 20, FALSE); - break; - } - - case ACT_RESIST_FIRE: - { - msg_format(_("%sが赤く輝いた...", "The %s grows red."), name); - if ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_FLAMES)) - { - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_FIRE, dir, 100, 2); - } - (void)set_oppose_fire(randint1(20) + 20, FALSE); - break; - } - - case ACT_RESIST_COLD: - { - msg_format(_("%sが白く輝いた...", "The %s grows white."), name); - if ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_ICE)) - { - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_COLD, dir, 100, 2); - } - (void)set_oppose_cold(randint1(20) + 20, FALSE); - break; - } - - case ACT_RESIST_ELEC: - { - msg_format(_("%sが青く輝いた...", "The %s grows blue."), name); - if ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_ELEC)) - { - if (!get_aim_dir(&dir)) return FALSE; - fire_ball(GF_ELEC, dir, 100, 2); - } - (void)set_oppose_elec(randint1(20) + 20, FALSE); - break; - } - - case ACT_RESIST_POIS: - { - msg_format(_("%sが緑に輝いた...", "The %s grows green."), name); - (void)set_oppose_pois(randint1(20) + 20, FALSE); - break; - } - - /* Activate for general purpose effect (detection etc.) */ - - case ACT_LIGHT: - { - msg_format(_("%sから澄んだ光があふれ出た...", "The %s wells with clear light..."), name); - lite_area(damroll(2, 15), 3); - break; - } - - case ACT_MAP_LIGHT: - { - msg_print(_("眩しく輝いた...", "It shines brightly...")); - map_area(DETECT_RAD_MAP); - lite_area(damroll(2, 15), 3); - break; - } - - case ACT_DETECT_ALL: - { - msg_print(_("白く明るく輝いている...", "It glows bright white...")); - msg_print(_("心にイメージが浮かんできた...", "An image forms in your mind...")); - detect_all(DETECT_RAD_DEFAULT); - break; - } - - case ACT_DETECT_XTRA: - { - msg_print(_("明るく輝いている...", "It glows brightly...")); - detect_all(DETECT_RAD_DEFAULT); - probing(); - identify_fully(FALSE); - break; - } - - case ACT_ID_FULL: - { - msg_print(_("黄色く輝いている...", "It glows yellow...")); - identify_fully(FALSE); - break; - } - - case ACT_ID_PLAIN: - { - if (!ident_spell(FALSE)) return FALSE; - break; - } - - case ACT_RUNE_EXPLO: - { - msg_print(_("明るい赤色に輝いている...", "It glows bright red...")); - explosive_rune(); - break; - } - - case ACT_RUNE_PROT: - { - msg_print(_("ブルーに明るく輝いている...", "It glows light blue...")); - warding_glyph(); - break; - } - - case ACT_SATIATE: - { - (void)set_food(PY_FOOD_MAX - 1); - break; - } - - case ACT_DEST_DOOR: - { - msg_print(_("明るい赤色に輝いている...", "It glows bright red...")); - destroy_doors_touch(); - break; - } - - case ACT_STONE_MUD: - { - msg_print(_("鼓動している...", "It pulsates...")); - if (!get_aim_dir(&dir)) return FALSE; - wall_to_mud(dir, 20 + randint1(30)); - break; - } - - case ACT_RECHARGE: - { - recharge(130); - break; - } - - case ACT_ALCHEMY: - { - msg_print(_("明るい黄色に輝いている...", "It glows bright yellow...")); - (void)alchemy(); - break; - } - - case ACT_DIM_DOOR: - { - msg_print(_("次元の扉が開いた。目的地を選んで下さい。", "You open a dimensional gate. Choose a destination.")); - if (!dimension_door()) return FALSE; - break; - } - - - case ACT_TELEPORT: - { - msg_print(_("周りの空間が歪んでいる...", "It twists space around you...")); - teleport_player(100, 0L); - break; - } - - case ACT_RECALL: - { - msg_print(_("やわらかな白色に輝いている...", "It glows soft white...")); - if (!recall_player(p_ptr, randint0(21) + 15)) return FALSE; - break; - } - - case ACT_JUDGE: - { - msg_format(_("%sは赤く明るく光った!", "The %s flashes bright red!"), name); - chg_virtue(V_KNOWLEDGE, 1); - chg_virtue(V_ENLIGHTEN, 1); - wiz_lite(FALSE); - - msg_format(_("%sはあなたの体力を奪った...", "The %s drains your vitality..."), name); - take_hit(DAMAGE_LOSELIFE, damroll(3, 8), _("審判の宝石", "the Jewel of Judgement"), -1); - - (void)detect_traps(DETECT_RAD_DEFAULT, TRUE); - (void)detect_doors(DETECT_RAD_DEFAULT); - (void)detect_stairs(DETECT_RAD_DEFAULT); - - if (get_check(_("帰還の力を使いますか?", "Activate recall? "))) - { - (void)recall_player(p_ptr, randint0(21) + 15); - } - - break; - } - - case ACT_TELEKINESIS: - { - if (!get_aim_dir(&dir)) return FALSE; - msg_format(_("%sを伸ばした。", "You stretched your %s."), name); - fetch(dir, 500, TRUE); - break; - } - - case ACT_DETECT_UNIQUE: - { - int i; - monster_type *m_ptr; - monster_race *r_ptr; - msg_print(_("奇妙な場所が頭の中に浮かんだ...", "Some strange places show up in your mind. And you see ...")); - /* Process the monsters (backwards) */ - for (i = m_max - 1; i >= 1; i--) - { - /* Access the monster */ - m_ptr = ¤t_floor_ptr->m_list[i]; - - /* Ignore "dead" monsters */ - if (!monster_is_valid(m_ptr)) continue; - - r_ptr = &r_info[m_ptr->r_idx]; - - if (r_ptr->flags1 & RF1_UNIQUE) - { - msg_format(_("%s. ", "%s. "), r_name + r_ptr->name); - } - } - break; - } - - case ACT_ESCAPE: - { - switch (randint1(13)) - { - case 1: case 2: case 3: case 4: case 5: - teleport_player(10, 0L); - break; - case 6: case 7: case 8: case 9: case 10: - teleport_player(222, 0L); - break; - case 11: case 12: - (void)stair_creation(); - break; - default: - if (get_check(_("この階を去りますか?", "Leave this level? "))) - { - if (autosave_l) do_cmd_save_game(TRUE); - p_ptr->leaving = TRUE; - } - } - break; - } - - case ACT_DISP_CURSE_XTRA: - { - msg_format(_("%sが真実を照らし出す...", "The %s exhibits the truth..."), name); - (void)remove_all_curse(); - (void)probing(); - break; - } - - case ACT_BRAND_FIRE_BOLTS: - { - msg_format(_("%sが深紅に輝いた...", "Your %s glows deep red..."), name); - (void)brand_bolts(); - break; - } - - case ACT_RECHARGE_XTRA: - { - msg_format(_("%sが白く輝いた...", "The %s gleams with blinding light..."), name); - if (!recharge(1000)) return FALSE; - break; - } - - case ACT_LORE: - msg_print(_("石が隠された秘密を写し出した...", "The stone reveals hidden mysteries...")); - if(!perilous_secrets(p_ptr)) return FALSE; - break; - - case ACT_SHIKOFUMI: - { - msg_print(_("力強く四股を踏んだ。", "You stamp. (as if you are in a ring.)")); - (void)set_afraid(0); - (void)set_hero(randint1(20) + 20, FALSE); - dispel_evil(p_ptr->lev * 3); - break; - } - - case ACT_PHASE_DOOR: - { - teleport_player(10, 0L); - break; - } - - case ACT_DETECT_ALL_MONS: - { - (void)detect_monsters_invis(255); - (void)detect_monsters_normal(255); - break; - } - - case ACT_ULTIMATE_RESIST: - { - TIME_EFFECT v = randint1(25) + 25; - (void)set_afraid(0); - (void)set_hero(v, FALSE); - (void)hp_player(10); - (void)set_blessed(v, FALSE); - (void)set_oppose_acid(v, FALSE); - (void)set_oppose_elec(v, FALSE); - (void)set_oppose_fire(v, FALSE); - (void)set_oppose_cold(v, FALSE); - (void)set_oppose_pois(v, FALSE); - (void)set_ultimate_res(v, FALSE); - break; - } - - case ACT_CAST_OFF: - cosmic_cast_off(p_ptr, o_ptr); - break; - - case ACT_FALLING_STAR: - { - msg_print(_("あなたは妖刀に魅入られた…", "You are enchanted by cursed blade...")); - msg_print(_("「狂ほしく 血のごとき 月はのぼれり 秘めおきし 魔剣 いずこぞや」", "'Behold the blade arts.'")); - massacre(); - break; - } - - case ACT_GRAND_CROSS: - { - msg_print(_("「闇に還れ!」", "You say, 'Return to darkness!'")); - project(0, 8, p_ptr->y, p_ptr->x, (randint1(100) + 200) * 2, GF_HOLY_FIRE, PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID, -1); - break; - } - - case ACT_TELEPORT_LEVEL: - { - if (!get_check(_("本当に他の階にテレポートしますか?", "Are you sure? (Teleport Level)"))) return FALSE; - teleport_level(0); - break; - } - - case ACT_STRAIN_HASTE: - { - int t; - msg_format(_("%sはあなたの体力を奪った...", "The %s drains your vitality..."), name); - take_hit(DAMAGE_LOSELIFE, damroll(3, 8), _("加速した疲労", "the strain of haste"), -1); - t = 25 + randint1(25); - (void)set_fast(p_ptr->fast + t, FALSE); - break; - } - - case ACT_FISHING: - if(!fishing(p_ptr)) return FALSE; - break; - - case ACT_INROU: - mitokohmon(); - break; - - case ACT_MURAMASA: - { - /* Only for Muramasa */ - if (o_ptr->name1 != ART_MURAMASA) return FALSE; - if (get_check(_("本当に使いますか?", "Are you sure?!"))) - { - msg_print(_("村正が震えた...", "The Muramasa pulsates...")); - do_inc_stat(A_STR); - if (one_in_(2)) - { - msg_print(_("村正は壊れた!", "The Muramasa is destroyed!")); - curse_weapon_object(TRUE, o_ptr); - } - } - break; - } - - case ACT_BLOODY_MOON: - { - /* Only for Bloody Moon */ - if (o_ptr->name1 != ART_BLOOD) return FALSE; - msg_print(_("鎌が明るく輝いた...", "Your scythe glows brightly!")); - get_bloody_moon_flags(o_ptr); - if (p_ptr->prace == RACE_ANDROID) calc_android_exp(); - p_ptr->update |= (PU_BONUS | PU_HP); - break; - } - - case ACT_CRIMSON: - if (o_ptr->name1 != ART_CRIMSON) return FALSE; - msg_print(_("せっかくだから『クリムゾン』をぶっぱなすぜ!", "I'll fire CRIMSON! SEKKAKUDAKARA!")); - if(!fire_crimson()) return FALSE; - break; - - default: - { - msg_format(_("Unknown activation effect: %d.", "Unknown activation effect: %d."), act_ptr->index); - return FALSE; - } - } - - /* Set activation timeout */ - if (act_ptr->timeout.constant >= 0) { - o_ptr->timeout = (s16b)act_ptr->timeout.constant; - if (act_ptr->timeout.dice > 0) { - o_ptr->timeout += randint1(act_ptr->timeout.dice); - } - } - else { - /* Activations that have special timeout */ - switch (act_ptr->index) { - case ACT_BR_FIRE: - o_ptr->timeout = ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_FLAMES)) ? 200 : 250; - break; - case ACT_BR_COLD: - o_ptr->timeout = ((o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_ICE)) ? 200 : 250; - break; - case ACT_TERROR: - o_ptr->timeout = 3 * (p_ptr->lev + 10); - break; - case ACT_MURAMASA: - /* Nothing to do */ - break; - default: - msg_format("Special timeout is not implemented: %d.", act_ptr->index); - return FALSE; - } - } - - return TRUE; -} - diff --git a/src/cmd-activate.h b/src/cmd-activate.h deleted file mode 100644 index 1a683ab1e..000000000 --- a/src/cmd-activate.h +++ /dev/null @@ -1,143 +0,0 @@ -extern void do_cmd_activate(void); -extern void do_cmd_activate_aux(INVENTORY_IDX item); -extern bool activate_artifact(object_type * o_ptr); - -extern const activation_type activation_info[]; - - -/* Activation effects for random artifacts */ -#define ACT_SUNLIGHT 1 -#define ACT_BO_MISS_1 2 -#define ACT_BA_POIS_1 3 -#define ACT_BO_ELEC_1 4 -#define ACT_BO_ACID_1 5 -#define ACT_BO_COLD_1 6 -#define ACT_BO_FIRE_1 7 -#define ACT_BA_COLD_1 8 -#define ACT_BA_FIRE_1 9 -#define ACT_HYPODYNAMIA_1 10 -#define ACT_BA_COLD_2 11 -#define ACT_BA_ELEC_2 12 -#define ACT_HYPODYNAMIA_2 13 -#define ACT_DRAIN_1 14 -#define ACT_BO_MISS_2 15 -#define ACT_BA_FIRE_3 16 -#define ACT_BA_COLD_3 17 -#define ACT_BA_ELEC_3 18 -#define ACT_WHIRLWIND 19 -#define ACT_DRAIN_2 20 -#define ACT_CALL_CHAOS 21 -#define ACT_ROCKET 22 -#define ACT_DISP_EVIL 23 -#define ACT_BA_MISS_3 24 -#define ACT_DISP_GOOD 25 -#define ACT_BO_MANA 26 -#define ACT_BA_FIRE_2 27 -#define ACT_BA_WATER 28 -#define ACT_BA_STAR 29 -#define ACT_BA_DARK 30 -#define ACT_BA_MANA 31 -#define ACT_PESTICIDE 32 -#define ACT_BLINDING_LIGHT 33 -#define ACT_BIZARRE 34 -#define ACT_CAST_BA_STAR 35 -#define ACT_BLADETURNER 36 -#define ACT_BA_ACID_1 37 -#define ACT_BR_FIRE 38 -#define ACT_BR_COLD 39 -#define ACT_BR_DRAGON 40 -#define ACT_BA_FIRE_4 41 -#define ACT_BA_NUKE_1 42 -/* 42 - 50 unused */ -#define ACT_CONFUSE 51 -#define ACT_SLEEP 52 -#define ACT_QUAKE 53 -#define ACT_TERROR 54 -#define ACT_TELE_AWAY 55 -#define ACT_BANISH_EVIL 56 -#define ACT_GENOCIDE 57 -#define ACT_MASS_GENO 58 -#define ACT_SCARE_AREA 59 -#define ACT_AGGRAVATE 60 -/* 59 - 64 unused */ -#define ACT_CHARM_ANIMAL 65 -#define ACT_CHARM_UNDEAD 66 -#define ACT_CHARM_OTHER 67 -#define ACT_CHARM_ANIMALS 68 -#define ACT_CHARM_OTHERS 69 -#define ACT_SUMMON_ANIMAL 70 -#define ACT_SUMMON_PHANTOM 71 -#define ACT_SUMMON_ELEMENTAL 72 -#define ACT_SUMMON_DEMON 73 -#define ACT_SUMMON_UNDEAD 74 -#define ACT_SUMMON_HOUND 75 -#define ACT_SUMMON_DAWN 76 -#define ACT_SUMMON_OCTOPUS 77 -/* 76 - 80 unused */ -#define ACT_CHOIR_SINGS 80 -#define ACT_CURE_LW 81 -#define ACT_CURE_MW 82 -#define ACT_CURE_POISON 83 -#define ACT_REST_EXP 84 -#define ACT_REST_ALL 85 -#define ACT_CURE_700 86 -#define ACT_CURE_1000 87 -#define ACT_CURING 88 -#define ACT_CURE_MANA_FULL 89 -/* 90 unused */ -#define ACT_ESP 91 -#define ACT_BERSERK 92 -#define ACT_PROT_EVIL 93 -#define ACT_RESIST_ALL 94 -#define ACT_SPEED 95 -#define ACT_XTRA_SPEED 96 -#define ACT_WRAITH 97 -#define ACT_INVULN 98 -#define ACT_HERO 99 -#define ACT_HERO_SPEED 100 -#define ACT_RESIST_ACID 101 -#define ACT_RESIST_FIRE 102 -#define ACT_RESIST_COLD 103 -#define ACT_RESIST_ELEC 104 -#define ACT_RESIST_POIS 105 -/* 106 - 110 unused */ -#define ACT_LIGHT 111 -#define ACT_MAP_LIGHT 112 -#define ACT_DETECT_ALL 113 -#define ACT_DETECT_XTRA 114 -#define ACT_ID_FULL 115 -#define ACT_ID_PLAIN 116 -#define ACT_RUNE_EXPLO 117 -#define ACT_RUNE_PROT 118 -#define ACT_SATIATE 119 -#define ACT_DEST_DOOR 120 -#define ACT_STONE_MUD 121 -#define ACT_RECHARGE 122 -#define ACT_ALCHEMY 123 -#define ACT_DIM_DOOR 124 -#define ACT_TELEPORT 125 -#define ACT_RECALL 126 -#define ACT_JUDGE 127 -#define ACT_TELEKINESIS 128 -#define ACT_DETECT_UNIQUE 129 -#define ACT_ESCAPE 130 -#define ACT_DISP_CURSE_XTRA 131 -#define ACT_BRAND_FIRE_BOLTS 132 -#define ACT_RECHARGE_XTRA 133 -#define ACT_LORE 134 -#define ACT_SHIKOFUMI 135 -#define ACT_PHASE_DOOR 136 -#define ACT_DETECT_ALL_MONS 137 -#define ACT_ULTIMATE_RESIST 138 -/* 127 -> unused */ -#define ACT_FALLING_STAR 246 -#define ACT_STRAIN_HASTE 247 -#define ACT_TELEPORT_LEVEL 248 -#define ACT_GRAND_CROSS 249 -#define ACT_CAST_OFF 250 -#define ACT_FISHING 251 -#define ACT_INROU 252 -#define ACT_MURAMASA 253 -#define ACT_BLOODY_MOON 254 -#define ACT_CRIMSON 255 - diff --git a/src/cmd-building/cmd-building.c b/src/cmd-building/cmd-building.c new file mode 100644 index 000000000..8225e31da --- /dev/null +++ b/src/cmd-building/cmd-building.c @@ -0,0 +1,417 @@ +/*! + * @brief 町の施設処理 / Building commands + * @date 2013/12/23 + * @author + * Created by Ken Wigle for Kangband - a variant of Angband 2.8.3 + * -KMW- + * + * Rewritten for Kangband 2.8.3i using Kamband's version of + * building.c as written by Ivan Tkatchev + * + * Changed for ZAngband by Robert Ruehlmann + */ + +#include "cmd-building/cmd-building.h" +#include "cmd-action/cmd-spell.h" +#include "cmd-building/cmd-inn.h" +#include "cmd-io/cmd-dump.h" +#include "core/asking-player.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/scores.h" +#include "core/show-file.h" +#include "core/special-internal-keys.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "floor/cave.h" +#include "floor/floor-mode-changer.h" +#include "floor/floor-events.h" +#include "floor/wild.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "main/music-definitions-table.h" +#include "main/sound-of-music.h" +#include "market/arena.h" +#include "market/bounty.h" +#include "market/building-actions-table.h" +#include "market/building-craft-armor.h" +#include "market/building-craft-fix.h" +#include "market/building-craft-weapon.h" +#include "market/building-enchanter.h" +#include "market/building-monster.h" +#include "market/building-quest.h" +#include "market/building-recharger.h" +#include "market/building-service.h" +#include "market/building-util.h" +#include "market/play-gamble.h" +#include "market/poker.h" +#include "monster-race/monster-race.h" +#include "mutation/mutation-flag-types.h" +#include "mutation/mutation-investor-remover.h" +#include "object-hook/hook-armor.h" +#include "object-hook/hook-bow.h" +#include "object-hook/hook-weapon.h" +#include "object/item-tester-hooker.h" +#include "player-info/avatar.h" +#include "player/player-personalities-types.h" +#include "player/player-status.h" +#include "spell-kind/spells-perception.h" +#include "spell-kind/spells-world.h" +#include "spell/spells-status.h" +#include "system/building-type-definition.h" +#include "system/floor-type-definition.h" +#include "term/screen-processor.h" +#include "util/bit-flags-calculator.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" +#include "world/world.h" + +u32b mon_odds[4]; +int battle_odds; +PRICE kakekin; +int sel_monster; + +bool reinit_wilderness = FALSE; +MONSTER_IDX today_mon; + +/*! + * @brief 町に関するヘルプを表示する / Display town history + * @param player_ptr プレーヤーへの参照ポインタ + * @return なし + */ +static void town_history(player_type *player_ptr) +{ + screen_save(); + (void)show_file(player_ptr, TRUE, _("jbldg.txt", "bldg.txt"), NULL, 0, 0); + screen_load(); +} + +/*! + * @brief 施設の処理実行メインルーチン / Execute a building command + * @param player_ptr プレーヤーへの参照ポインタ + * @param bldg 施設構造体の参照ポインタ + * @param i 実行したい施設のサービステーブルの添字 + * @return なし + */ +static void bldg_process_command(player_type *player_ptr, building_type *bldg, int i) +{ + msg_flag = FALSE; + msg_erase(); + + PRICE bcost; + if (is_owner(player_ptr, bldg)) + bcost = bldg->member_costs[i]; + else + bcost = bldg->other_costs[i]; + + /* action restrictions */ + if (((bldg->action_restr[i] == 1) && !is_member(player_ptr, bldg)) || + ((bldg->action_restr[i] == 2) && !is_owner(player_ptr, bldg))) + { + msg_print(_("それを選択する権利はありません!", "You have no right to choose that!")); + return; + } + + BACT_IDX bact = bldg->actions[i]; + if ((bact != BACT_RECHARGE) && + (((bldg->member_costs[i] > player_ptr->au) && is_owner(player_ptr, bldg)) || + ((bldg->other_costs[i] > player_ptr->au) && !is_owner(player_ptr, bldg)))) + { + msg_print(_("お金が足りません!", "You do not have the gold!")); + return; + } + + bool paid = FALSE; + switch (bact) + { + case BACT_NOTHING: + /* Do nothing */ + break; + case BACT_RESEARCH_ITEM: + paid = identify_fully(player_ptr, FALSE, 0); + break; + case BACT_TOWN_HISTORY: + town_history(player_ptr); + break; + case BACT_RACE_LEGENDS: + race_legends(player_ptr); + break; + case BACT_QUEST: + castle_quest(player_ptr); + break; + case BACT_KING_LEGENDS: + case BACT_ARENA_LEGENDS: + case BACT_LEGENDS: + show_highclass(player_ptr); + break; + case BACT_POSTER: + case BACT_ARENA_RULES: + case BACT_ARENA: + arena_comm(player_ptr, bact); + break; + case BACT_IN_BETWEEN: + case BACT_CRAPS: + case BACT_SPIN_WHEEL: + case BACT_DICE_SLOTS: + case BACT_GAMBLE_RULES: + case BACT_POKER: + gamble_comm(player_ptr, bact); + break; + case BACT_REST: + case BACT_RUMORS: + case BACT_FOOD: + paid = inn_comm(player_ptr, bact); + break; + case BACT_RESEARCH_MONSTER: + paid = research_mon(player_ptr); + break; + case BACT_COMPARE_WEAPONS: + paid = TRUE; + bcost = compare_weapons(player_ptr, bcost); + break; + case BACT_ENCHANT_WEAPON: + item_tester_hook = object_allow_enchant_melee_weapon; + enchant_item(player_ptr, bcost, 1, 1, 0, 0); + break; + case BACT_ENCHANT_ARMOR: + item_tester_hook = object_is_armour; + enchant_item(player_ptr, bcost, 0, 0, 1, 0); + break; + case BACT_RECHARGE: + building_recharge(player_ptr); + break; + case BACT_RECHARGE_ALL: + building_recharge_all(player_ptr); + break; + case BACT_IDENTS: + if (!get_check(_("持ち物を全て鑑定してよろしいですか?", "Do you pay for identify all your possession? "))) break; + identify_pack(player_ptr); + msg_print(_(" 持ち物全てが鑑定されました。", "Your possessions have been identified.")); + paid = TRUE; + break; + case BACT_IDENT_ONE: + paid = ident_spell(player_ptr, FALSE, 0); + break; + case BACT_LEARN: + do_cmd_study(player_ptr); + break; + case BACT_HEALING: + paid = cure_critical_wounds(player_ptr, 200); + break; + case BACT_RESTORE: + paid = restore_all_status(player_ptr); + break; + case BACT_ENCHANT_ARROWS: + item_tester_hook = item_tester_hook_ammo; + enchant_item(player_ptr, bcost, 1, 1, 0, 0); + break; + case BACT_ENCHANT_BOW: + enchant_item(player_ptr, bcost, 1, 1, 0, TV_BOW); + break; + + case BACT_RECALL: + if (recall_player(player_ptr, 1)) paid = TRUE; + break; + + case BACT_TELEPORT_LEVEL: + clear_bldg(4, 20); + paid = free_level_recall(player_ptr); + break; + + case BACT_LOSE_MUTATION: + if (player_ptr->muta1 || player_ptr->muta2 || (player_ptr->muta3 & ~MUT3_GOOD_LUCK) || + (player_ptr->pseikaku != PERSONALITY_LUCKY && (player_ptr->muta3 & MUT3_GOOD_LUCK))) + { + while (!lose_mutation(player_ptr, 0)); + paid = TRUE; + break; + } + + msg_print(_("治すべき突然変異が無い。", "You have no mutations.")); + msg_print(NULL); + break; + + case BACT_BATTLE: + monster_arena_comm(player_ptr); + break; + + case BACT_TSUCHINOKO: + tsuchinoko(); + break; + + case BACT_BOUNTY: + show_bounty(); + break; + + case BACT_TARGET: + today_target(player_ptr); + break; + + case BACT_KANKIN: + exchange_cash(player_ptr); + break; + + case BACT_HEIKOUKA: + msg_print(_("平衡化の儀式を行なった。", "You received an equalization ritual.")); + set_virtue(player_ptr, V_COMPASSION, 0); + set_virtue(player_ptr, V_HONOUR, 0); + set_virtue(player_ptr, V_JUSTICE, 0); + set_virtue(player_ptr, V_SACRIFICE, 0); + set_virtue(player_ptr, V_KNOWLEDGE, 0); + set_virtue(player_ptr, V_FAITH, 0); + set_virtue(player_ptr, V_ENLIGHTEN, 0); + set_virtue(player_ptr, V_ENCHANT, 0); + set_virtue(player_ptr, V_CHANCE, 0); + set_virtue(player_ptr, V_NATURE, 0); + set_virtue(player_ptr, V_HARMONY, 0); + set_virtue(player_ptr, V_VITALITY, 0); + set_virtue(player_ptr, V_UNLIFE, 0); + set_virtue(player_ptr, V_PATIENCE, 0); + set_virtue(player_ptr, V_TEMPERANCE, 0); + set_virtue(player_ptr, V_DILIGENCE, 0); + set_virtue(player_ptr, V_VALOUR, 0); + set_virtue(player_ptr, V_INDIVIDUALISM, 0); + get_virtues(player_ptr); + paid = TRUE; + break; + + case BACT_TELE_TOWN: + paid = tele_town(player_ptr); + break; + + case BACT_EVAL_AC: + paid = eval_ac(player_ptr->dis_ac + player_ptr->dis_to_a); + break; + + case BACT_BROKEN_WEAPON: + paid = TRUE; + bcost = repair_broken_weapon(player_ptr, bcost); + break; + } + + if (paid) player_ptr->au -= bcost; +} + + +/*! + * @brief 施設入り口にプレイヤーが乗った際の処理 / Do building commands + * @param プレーヤーへの参照ポインタ + * @return なし + */ +void do_cmd_building(player_type *player_ptr) +{ + if (player_ptr->wild_mode) return; + + take_turn(player_ptr, 100); + + if (!cave_have_flag_bold(player_ptr->current_floor_ptr, player_ptr->y, player_ptr->x, FF_BLDG)) + { + msg_print(_("ここには建物はない。", "You see no building here.")); + return; + } + + int which = f_info[player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x].feat].subtype; + + building_type *bldg; + bldg = &building[which]; + + reinit_wilderness = FALSE; + + if ((which == 2) && (player_ptr->arena_number < 0)) + { + msg_print(_("「敗者に用はない。」", "'There's no place here for a LOSER like you!'")); + return; + } + else if ((which == 2) && player_ptr->current_floor_ptr->inside_arena) + { + if (!player_ptr->exit_bldg && player_ptr->current_floor_ptr->m_cnt > 0) + { + prt(_("ゲートは閉まっている。モンスターがあなたを待っている!", "The gates are closed. The monster awaits!"), 0, 0); + } + else + { + prepare_change_floor_mode(player_ptr, CFM_SAVE_FLOORS | CFM_NO_RETURN); + player_ptr->current_floor_ptr->inside_arena = FALSE; + player_ptr->leaving = TRUE; + command_new = SPECIAL_KEY_BUILDING; + free_turn(player_ptr); + } + + return; + } + else if (player_ptr->phase_out) + { + prepare_change_floor_mode(player_ptr, CFM_SAVE_FLOORS | CFM_NO_RETURN); + player_ptr->leaving = TRUE; + player_ptr->phase_out = FALSE; + command_new = SPECIAL_KEY_BUILDING; + free_turn(player_ptr); + return; + } + else + { + player_ptr->oldpy = player_ptr->y; + player_ptr->oldpx = player_ptr->x; + } + + forget_lite(player_ptr->current_floor_ptr); + forget_view(player_ptr->current_floor_ptr); + current_world_ptr->character_icky++; + + command_arg = 0; + command_rep = 0; + command_new = 0; + + display_buikding_service(player_ptr, bldg); + player_ptr->leave_bldg = FALSE; + play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_BUILD); + + bool validcmd; + while (!player_ptr->leave_bldg) + { + validcmd = FALSE; + prt("", 1, 0); + + building_prt_gold(player_ptr); + + char command = inkey(); + + if (command == ESCAPE) + { + player_ptr->leave_bldg = TRUE; + player_ptr->current_floor_ptr->inside_arena = FALSE; + player_ptr->phase_out = FALSE; + break; + } + + int i; + for (i = 0; i < 8; i++) + { + if (bldg->letters[i] && (bldg->letters[i] == command)) + { + validcmd = TRUE; + break; + } + } + + if (validcmd) bldg_process_command(player_ptr, bldg, i); + + handle_stuff(player_ptr); + } + + select_floor_music(player_ptr); + + msg_flag = FALSE; + msg_erase(); + + if (reinit_wilderness) player_ptr->leaving = TRUE; + + current_world_ptr->character_icky--; + term_clear(); + + player_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_BONUS | PU_LITE | PU_MON_LITE); + player_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_EQUIPPY | PR_MAP); + player_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); +} diff --git a/src/cmd-building/cmd-building.h b/src/cmd-building/cmd-building.h new file mode 100644 index 000000000..6e95a5c74 --- /dev/null +++ b/src/cmd-building/cmd-building.h @@ -0,0 +1,23 @@ +#pragma once + +#include "system/angband.h" +#include "object/tval-types.h" + +#define BUILDING_NON_MEMBER 0 /*!< 不明(現在未使用) */ +#define BUILDING_MEMBER 1 /*!< 不明(現在未使用) */ +#define BUILDING_OWNER 2 /*!< 施設の種族/職業条件が一致している状態値 */ + +/* + * Arena constants + */ +#define ARENA_DEFEATED_OLD_VER (-(MAX_SHORT)) /*food >= PY_FOOD_FULL) + { + msg_print(_("今は満腹だ。", "You are full now.")); + return FALSE; + } + + msg_print(_("バーテンはいくらかの食べ物とビールをくれた。", "The barkeep gives you some gruel and a beer.")); + (void)set_food(customer_ptr, PY_FOOD_MAX - 1); + return TRUE; +} + + +/*! + * @brief 健康体しか宿屋に泊めない処理 + * @param customer_ptr プレーヤーへの参照ポインタ + * @return 毒でも切り傷でもないならTRUE、そうでないならFALSE + */ +static bool is_healthy_stay(player_type *customer_ptr) +{ + if (!customer_ptr->poisoned && !customer_ptr->cut) return TRUE; + + msg_print(_("あなたに必要なのは部屋ではなく、治療者です。", "You need a healer, not a room.")); + msg_print(NULL); + msg_print(_("すみません、でもうちで誰かに死なれちゃ困りますんで。", "Sorry, but don't want anyone dying in here.")); + return FALSE; +} + + +static bool is_player_undead(player_type *customer_ptr) +{ + bool is_player_undead = is_specific_player_race(customer_ptr, RACE_SKELETON) || + is_specific_player_race(customer_ptr, RACE_ZOMBIE) || + is_specific_player_race(customer_ptr, RACE_VAMPIRE) || + is_specific_player_race(customer_ptr, RACE_SPECTRE); + return is_player_undead; +} + + +/*! + * @brief 宿屋に泊まったことを日記に残す + * @param customer_ptr プレーヤーへの参照ポインタ + * @param prev_hour 宿屋に入った直後のゲーム内時刻 + * @return なし + */ +static void write_diary_stay_inn(player_type *customer_ptr, int prev_hour) +{ + if ((prev_hour >= 6) && (prev_hour < 18)) + { + concptr stay_message = _(is_player_undead(customer_ptr) ? "宿屋に泊まった。" : "日が暮れるまで宿屋で過ごした。", "stayed during the day at the inn."); + exe_write_diary(customer_ptr, DIARY_DESCRIPTION, 0, stay_message); + return; + } + + concptr stay_message = _(is_player_undead(customer_ptr) ? "夜が明けるまで宿屋で過ごした。" : "宿屋に泊まった。", "stayed overnight at the inn."); + exe_write_diary(customer_ptr, DIARY_DESCRIPTION, 0, stay_message); +} + + +/*! + * @brief 宿泊によってゲーム内ターンを経過させる + * @param なし + * @return なし + */ +static void pass_game_turn_by_stay(void) +{ + s32b oldturn = current_world_ptr->game_turn; + current_world_ptr->game_turn = + (current_world_ptr->game_turn / (TURNS_PER_TICK * TOWN_DAWN / 2) + 1) * + (TURNS_PER_TICK * TOWN_DAWN / 2); + if (current_world_ptr->dungeon_turn >= current_world_ptr->dungeon_turn_limit) + return; + + current_world_ptr->dungeon_turn += MIN((current_world_ptr->game_turn - oldturn), TURNS_PER_TICK * 250) * INN_DUNGEON_TURN_ADJ; + if (current_world_ptr->dungeon_turn > current_world_ptr->dungeon_turn_limit) + current_world_ptr->dungeon_turn = current_world_ptr->dungeon_turn_limit; +} + + +/*! + * @brief 悪夢モードなら悪夢を見せる + * @param customer_ptr プレーヤーへの参照ポインタ + * @return 悪夢モードならばTRUE + */ +static bool have_a_nightmare(player_type *customer_ptr) +{ + if (!ironman_nightmare) return FALSE; + + msg_print(_("眠りに就くと恐ろしい光景が心をよぎった。", "Horrible visions flit through your mind as you sleep.")); + + while (TRUE) + { + sanity_blast(customer_ptr, NULL, FALSE); + if (!one_in_(3)) break; + } + + msg_print(_("あなたは絶叫して目を覚ました。", "You awake screaming.")); + exe_write_diary(customer_ptr, DIARY_DESCRIPTION, 0, _("悪夢にうなされてよく眠れなかった。", "had a nightmare.")); + return TRUE; +} + + +/*! + * @brief 体調を元に戻す + * @param customer_ptr プレーヤーへの参照ポインタ + * @return なし + */ +static void back_to_health(player_type *customer_ptr) +{ + set_blind(customer_ptr, 0); + set_confused(customer_ptr, 0); + customer_ptr->stun = 0; + customer_ptr->chp = customer_ptr->mhp; + customer_ptr->csp = customer_ptr->msp; +} + + +/*! + * @brief 魔力喰いの残り回数回復(本当? 要調査) + * @param customer_ptr プレーヤーへの参照ポインタ + * @return なし + */ +static void charge_magic_eating_energy(player_type *customer_ptr) +{ + if (customer_ptr->pclass != CLASS_MAGIC_EATER) + return; + + int i; + for (i = 0; i < 72; i++) + { + customer_ptr->magic_num1[i] = customer_ptr->magic_num2[i] * EATER_CHARGE; + } + + for (; i < MAX_SPELLS; i++) + { + customer_ptr->magic_num1[i] = 0; + } +} + + +/*! + * @brief リフレッシュ結果を画面に表示する + * @param customer_ptr プレーヤーへの参照ポインタ + * @param prev_hour 宿屋に入った直後のゲーム内時刻 + */ +static void display_stay_result(player_type *customer_ptr, int prev_hour) +{ + if ((prev_hour >= 6) && (prev_hour < 18)) + { +#if JP + char refresh_message_jp[50]; + sprintf(refresh_message_jp, "%s%s%s", "あなたはリフレッシュして目覚め、", is_player_undead(customer_ptr) ? "夜" : "夕方", "を迎えた。"); + msg_print(refresh_message_jp); +#else + msg_print("You awake refreshed for the evening."); +#endif + concptr awake_message = _(is_player_undead(customer_ptr) ? "すがすがしい夜を迎えた。" : "夕方を迎えた。", "awoke refreshed."); + exe_write_diary(customer_ptr, DIARY_DESCRIPTION, 0, awake_message); + return; + } + + msg_print(_("あなたはリフレッシュして目覚め、新たな日を迎えた。", "You awake refreshed for the new day.")); + concptr awake_message = _(is_player_undead(customer_ptr) ? "すがすがしい朝を迎えた。" : "朝を迎えた。", "awoke refreshed."); + exe_write_diary(customer_ptr, DIARY_DESCRIPTION, 0, awake_message); +} + + +/*! + * @brief 宿屋への宿泊実行処理 + * @param customer_ptr プレーヤーへの参照ポインタ + * @return 泊まれたらTRUE + */ +static bool stay_inn(player_type *customer_ptr) +{ + if (!is_healthy_stay(customer_ptr)) return FALSE; + + int prev_day, prev_hour, prev_min; + extract_day_hour_min(customer_ptr, &prev_day, &prev_hour, &prev_min); + write_diary_stay_inn(customer_ptr, prev_hour); + + pass_game_turn_by_stay(); + prevent_turn_overflow(customer_ptr); + + if ((prev_hour >= 18) && (prev_hour <= 23)) + exe_write_diary(customer_ptr, DIARY_DIALY, 0, NULL); + + customer_ptr->chp = customer_ptr->mhp; + if (have_a_nightmare(customer_ptr)) return TRUE; + + back_to_health(customer_ptr); + charge_magic_eating_energy(customer_ptr); + + display_stay_result(customer_ptr, prev_hour); + return TRUE; +} + + +/*! + * todo 悪夢を見る前後に全回復しているが、何か意図がある? + * @brief 宿屋を利用する + * @param customer_ptr プレーヤーへの参照ポインタ + * @param cmd 宿屋の利用施設ID + * @return 施設の利用が実際に行われたらTRUE + * @details inn commands + * Note that resting for the night was a perfect way to avoid player + * ghosts in the town *if* you could only make it to the inn in time (-: + * Now that the ghosts are temporarily disabled in 2.8.X, this function + * will not be that useful. I will keep it in the hopes the player + * ghost code does become a reality again. Does help to avoid filthy urchins. + * Resting at night is also a quick way to restock stores -KMW- + */ +bool inn_comm(player_type *customer_ptr, int cmd) +{ + switch (cmd) + { + case BACT_FOOD: + return buy_food(customer_ptr); + case BACT_REST: + return stay_inn(customer_ptr); + case BACT_RUMORS: + display_rumor(customer_ptr, TRUE); + return TRUE; + default: + // todo リファクタリング前のコードもTRUEだった、FALSEにすべきでは. + return TRUE; + } +} diff --git a/src/cmd-building/cmd-inn.h b/src/cmd-building/cmd-inn.h new file mode 100644 index 000000000..ee989a973 --- /dev/null +++ b/src/cmd-building/cmd-inn.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool inn_comm(player_type *customer_ptr, int cmd); diff --git a/src/cmd-building/cmd-store.c b/src/cmd-building/cmd-store.c new file mode 100644 index 000000000..18a0ac9c8 --- /dev/null +++ b/src/cmd-building/cmd-store.c @@ -0,0 +1,201 @@ +#include "cmd-building/cmd-store.h" +#include "cmd-io/macro-util.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "flavor/flavor-describer.h" +#include "floor/cave.h" +#include "floor/floor-events.h" +#include "floor/floor-town.h" +#include "floor/wild.h" +#include "game-option/birth-options.h" +#include "game-option/input-options.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "inventory/inventory-object.h" +#include "inventory/inventory-slot-types.h" +#include "io/input-key-requester.h" +#include "io/store-key-processor.h" +#include "main/music-definitions-table.h" +#include "main/sound-of-music.h" +#include "object/object-generator.h" +#include "object/object-info.h" +#include "store/home.h" +#include "store/store-util.h" +#include "store/store.h" +#include "system/floor-type-definition.h" +#include "term/screen-processor.h" +#include "view/display-messages.h" +#include "view/display-store.h" +#include "world/world.h" + +#define MIN_STOCK 12 + +/*! + * @brief 店舗処理全体のメインルーチン / + * Enter a store, and interact with it. * + * @param player_ptr プレーヤーへの参照ポインタ + * @return なし + * @note + *
+ * Note that we use the standard "request_command()" function
+ * to get a command, allowing us to use "command_arg" and all
+ * command macros and other nifty stuff, but we use the special
+ * "shopping" argument, to force certain commands to be converted
+ * into other commands, normally, we convert "p" (pray) and "m"
+ * (cast magic) into "g" (get), and "s" (search) into "d" (drop).
+ * 
+ */ +void do_cmd_store(player_type *player_ptr) +{ + if (player_ptr->wild_mode) + return; + TERM_LEN w, h; + term_get_size(&w, &h); + + xtra_stock = MIN(14 + 26, ((h > 24) ? (h - 24) : 0)); + store_bottom = MIN_STOCK + xtra_stock; + + grid_type *g_ptr; + g_ptr = &player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x]; + + if (!cave_have_flag_grid(g_ptr, FF_STORE)) { + msg_print(_("ここには店がありません。", "You see no store here.")); + return; + } + + int which = f_info[g_ptr->feat].subtype; + old_town_num = player_ptr->town_num; + if ((which == STORE_HOME) || (which == STORE_MUSEUM)) + player_ptr->town_num = 1; + if (player_ptr->current_floor_ptr->dun_level) + player_ptr->town_num = NO_TOWN; + inner_town_num = player_ptr->town_num; + + if ((town_info[player_ptr->town_num].store[which].store_open >= current_world_ptr->game_turn) || ironman_shops) { + msg_print(_("ドアに鍵がかかっている。", "The doors are locked.")); + player_ptr->town_num = old_town_num; + return; + } + + int maintain_num = (current_world_ptr->game_turn - town_info[player_ptr->town_num].store[which].last_visit) / (TURNS_PER_TICK * STORE_TICKS); + if (maintain_num > 10) + maintain_num = 10; + if (maintain_num) { + for (int i = 0; i < maintain_num; i++) + store_maintenance(player_ptr, player_ptr->town_num, which); + + town_info[player_ptr->town_num].store[which].last_visit = current_world_ptr->game_turn; + } + + forget_lite(player_ptr->current_floor_ptr); + forget_view(player_ptr->current_floor_ptr); + current_world_ptr->character_icky = TRUE; + command_arg = 0; + command_rep = 0; + command_new = 0; + get_com_no_macros = TRUE; + cur_store_num = which; + cur_store_feat = g_ptr->feat; + st_ptr = &town_info[player_ptr->town_num].store[cur_store_num]; + ot_ptr = &owners[cur_store_num][st_ptr->owner]; + store_top = 0; + play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_BUILD); + display_store(player_ptr); + leave_store = FALSE; + + while (!leave_store) { + prt("", 1, 0); + clear_from(20 + xtra_stock); + prt(_(" ESC) 建物から出る", " ESC) Exit from Building."), 21 + xtra_stock, 0); + if (st_ptr->stock_num > store_bottom) { + prt(_(" -)前ページ", " -) Previous page"), 22 + xtra_stock, 0); + prt(_(" スペース) 次ページ", " SPACE) Next page"), 23 + xtra_stock, 0); + } + + if (cur_store_num == STORE_HOME) { + prt(_("g) アイテムを取る", "g) Get an item."), 21 + xtra_stock, 27); + prt(_("d) アイテムを置く", "d) Drop an item."), 22 + xtra_stock, 27); + prt(_("x) 家のアイテムを調べる", "x) eXamine an item in the home."), 23 + xtra_stock, 27); + } else if (cur_store_num == STORE_MUSEUM) { + prt(_("d) アイテムを置く", "d) Drop an item."), 21 + xtra_stock, 27); + prt(_("r) アイテムの展示をやめる", "r) order to Remove an item."), 22 + xtra_stock, 27); + prt(_("x) 博物館のアイテムを調べる", "x) eXamine an item in the museum."), 23 + xtra_stock, 27); + } else { + prt(_("p) 商品を買う", "p) Purchase an item."), 21 + xtra_stock, 30); + prt(_("s) アイテムを売る", "s) Sell an item."), 22 + xtra_stock, 30); + prt(_("x) 商品を調べる", "x) eXamine an item in the shop"), 23 + xtra_stock, 30); + } + + prt(_("i/e) 持ち物/装備の一覧", "i/e) Inventry/Equipment list"), 21 + xtra_stock, 56); + if (rogue_like_commands) + prt(_("w/T) 装備する/はずす", "w/T) Wear/Take off equipment"), 22 + xtra_stock, 56); + else + prt(_("w/t) 装備する/はずす", "w/t) Wear/Take off equipment"), 22 + xtra_stock, 56); + + prt(_("コマンド:", "You may: "), 20 + xtra_stock, 0); + request_command(player_ptr, TRUE); + store_process_command(player_ptr); + + bool need_redraw_store_inv = (player_ptr->update & PU_BONUS) ? TRUE : FALSE; + current_world_ptr->character_icky = TRUE; + handle_stuff(player_ptr); + if (player_ptr->inventory_list[INVEN_PACK].k_idx) { + INVENTORY_IDX item = INVEN_PACK; + object_type *o_ptr = &player_ptr->inventory_list[item]; + if (cur_store_num != STORE_HOME) { + if (cur_store_num == STORE_MUSEUM) + msg_print(_("ザックからアイテムがあふれそうなので、あわてて博物館から出た...", "Your pack is so full that you flee the Museum...")); + else + msg_print(_("ザックからアイテムがあふれそうなので、あわてて店から出た...", "Your pack is so full that you flee the store...")); + + leave_store = TRUE; + } else if (!store_check_num(o_ptr)) { + msg_print(_("ザックからアイテムがあふれそうなので、あわてて家から出た...", "Your pack is so full that you flee your home...")); + leave_store = TRUE; + } else { + int item_pos; + object_type forge; + object_type *q_ptr; + GAME_TEXT o_name[MAX_NLEN]; + msg_print(_("ザックからアイテムがあふれてしまった!", "Your pack overflows!")); + q_ptr = &forge; + object_copy(q_ptr, o_ptr); + describe_flavor(player_ptr, o_name, q_ptr, 0); + msg_format(_("%sが落ちた。(%c)", "You drop %s (%c)."), o_name, index_to_label(item)); + vary_item(player_ptr, item, -255); + handle_stuff(player_ptr); + + item_pos = home_carry(player_ptr, q_ptr); + if (item_pos >= 0) { + store_top = (item_pos / store_bottom) * store_bottom; + display_store_inventory(player_ptr); + } + } + } + + if (need_redraw_store_inv) + display_store_inventory(player_ptr); + + if (st_ptr->store_open >= current_world_ptr->game_turn) + leave_store = TRUE; + } + + select_floor_music(player_ptr); + player_ptr->town_num = old_town_num; + take_turn(player_ptr, 100); + current_world_ptr->character_icky = FALSE; + command_new = 0; + command_see = FALSE; + get_com_no_macros = FALSE; + + msg_erase(); + term_clear(); + + player_ptr->update |= PU_VIEW | PU_LITE | PU_MON_LITE; + player_ptr->update |= PU_MONSTERS; + player_ptr->redraw |= PR_BASIC | PR_EXTRA | PR_EQUIPPY; + player_ptr->redraw |= PR_MAP; + player_ptr->window |= PW_OVERHEAD | PW_DUNGEON; +} diff --git a/src/cmd-building/cmd-store.h b/src/cmd-building/cmd-store.h new file mode 100644 index 000000000..d3d8271a3 --- /dev/null +++ b/src/cmd-building/cmd-store.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_store(player_type *player_ptr); diff --git a/src/cmd-eat.c b/src/cmd-eat.c deleted file mode 100644 index 9a0b7a492..000000000 --- a/src/cmd-eat.c +++ /dev/null @@ -1,519 +0,0 @@ -/*! - * @file cmd-eat.c - * @brief プレイヤーの食べるコマンド実装 - * @date 2018/09/07 - * @details - * cmd6.cより分離。 - */ - - -#include "angband.h" -#include "object-hook.h" -#include "avatar.h" -#include "spells-status.h" -#include "realm-hex.h" -#include "player-status.h" - -/*! - * @brief 食料を食べるコマンドのサブルーチン - * @param item 食べるオブジェクトの所持品ID - * @return なし - */ -void do_cmd_eat_food_aux(INVENTORY_IDX item) -{ - int ident, lev; - object_type *o_ptr; - - if (music_singing_any()) stop_singing(p_ptr); - if (hex_spelling_any()) stop_hex_spell_all(); - - /* Get the item (in the pack) */ - if (item >= 0) - { - o_ptr = &inventory[item]; - } - - /* Get the item (on the floor) */ - else - { - o_ptr = ¤t_floor_ptr->o_list[0 - item]; - } - - sound(SOUND_EAT); - - take_turn(p_ptr, 100); - - /* Identity not known yet */ - ident = FALSE; - - /* Object level */ - lev = k_info[o_ptr->k_idx].level; - - if (o_ptr->tval == TV_FOOD) - { - /* Analyze the food */ - switch (o_ptr->sval) - { - case SV_FOOD_POISON: - { - if (!(p_ptr->resist_pois || IS_OPPOSE_POIS())) - { - if (set_poisoned(p_ptr->poisoned + randint0(10) + 10)) - { - ident = TRUE; - } - } - break; - } - - case SV_FOOD_BLINDNESS: - { - if (!p_ptr->resist_blind) - { - if (set_blind(p_ptr->blind + randint0(200) + 200)) - { - ident = TRUE; - } - } - break; - } - - case SV_FOOD_PARANOIA: - { - if (!p_ptr->resist_fear) - { - if (set_afraid(p_ptr->afraid + randint0(10) + 10)) - { - ident = TRUE; - } - } - break; - } - - case SV_FOOD_CONFUSION: - { - if (!p_ptr->resist_conf) - { - if (set_confused(p_ptr->confused + randint0(10) + 10)) - { - ident = TRUE; - } - } - break; - } - - case SV_FOOD_HALLUCINATION: - { - if (!p_ptr->resist_chaos) - { - if (set_image(p_ptr->image + randint0(250) + 250)) - { - ident = TRUE; - } - } - break; - } - - case SV_FOOD_PARALYSIS: - { - if (!p_ptr->free_act) - { - if (set_paralyzed(p_ptr->paralyzed + randint0(10) + 10)) - { - ident = TRUE; - } - } - break; - } - - case SV_FOOD_WEAKNESS: - { - take_hit(DAMAGE_NOESCAPE, damroll(6, 6), _("毒入り食料", "poisonous food"), -1); - (void)do_dec_stat(A_STR); - ident = TRUE; - break; - } - - case SV_FOOD_SICKNESS: - { - take_hit(DAMAGE_NOESCAPE, damroll(6, 6), _("毒入り食料", "poisonous food"), -1); - (void)do_dec_stat(A_CON); - ident = TRUE; - break; - } - - case SV_FOOD_STUPIDITY: - { - take_hit(DAMAGE_NOESCAPE, damroll(8, 8), _("毒入り食料", "poisonous food"), -1); - (void)do_dec_stat(A_INT); - ident = TRUE; - break; - } - - case SV_FOOD_NAIVETY: - { - take_hit(DAMAGE_NOESCAPE, damroll(8, 8), _("毒入り食料", "poisonous food"), -1); - (void)do_dec_stat(A_WIS); - ident = TRUE; - break; - } - - case SV_FOOD_UNHEALTH: - { - take_hit(DAMAGE_NOESCAPE, damroll(10, 10), _("毒入り食料", "poisonous food"), -1); - (void)do_dec_stat(A_CON); - ident = TRUE; - break; - } - - case SV_FOOD_DISEASE: - { - take_hit(DAMAGE_NOESCAPE, damroll(10, 10), _("毒入り食料", "poisonous food"), -1); - (void)do_dec_stat(A_STR); - ident = TRUE; - break; - } - - case SV_FOOD_CURE_POISON: - { - if (set_poisoned(0)) ident = TRUE; - break; - } - - case SV_FOOD_CURE_BLINDNESS: - { - if (set_blind(0)) ident = TRUE; - break; - } - - case SV_FOOD_CURE_PARANOIA: - { - if (set_afraid(0)) ident = TRUE; - break; - } - - case SV_FOOD_CURE_CONFUSION: - { - if (set_confused(0)) ident = TRUE; - break; - } - - case SV_FOOD_CURE_SERIOUS: - { - ident = cure_serious_wounds(4, 8); - break; - } - - case SV_FOOD_RESTORE_STR: - { - if (do_res_stat(A_STR)) ident = TRUE; - break; - } - - case SV_FOOD_RESTORE_CON: - { - if (do_res_stat(A_CON)) ident = TRUE; - break; - } - - case SV_FOOD_RESTORING: - { - ident = restore_all_status(); - break; - } - - -#ifdef JP - /* それぞれの食べ物の感想をオリジナルより細かく表現 */ - case SV_FOOD_BISCUIT: - { - msg_print("甘くてサクサクしてとてもおいしい。"); - ident = TRUE; - break; - } - - case SV_FOOD_JERKY: - { - msg_print("歯ごたえがあっておいしい。"); - ident = TRUE; - break; - } - - case SV_FOOD_SLIME_MOLD: - { - msg_print("これはなんとも形容しがたい味だ。"); - ident = TRUE; - break; - } - - case SV_FOOD_RATION: - { - msg_print("これはおいしい。"); - ident = TRUE; - break; - } -#else - case SV_FOOD_RATION: - case SV_FOOD_BISCUIT: - case SV_FOOD_JERKY: - case SV_FOOD_SLIME_MOLD: - { - msg_print("That tastes good."); - ident = TRUE; - break; - } -#endif - - - case SV_FOOD_WAYBREAD: - { - msg_print(_("これはひじょうに美味だ。", "That tastes good.")); - (void)set_poisoned(0); - (void)hp_player(damroll(4, 8)); - ident = TRUE; - break; - } - -#ifdef JP - case SV_FOOD_PINT_OF_ALE: - { - msg_print("のどごし爽やかだ。"); - ident = TRUE; - break; - } - - case SV_FOOD_PINT_OF_WINE: - { - msg_print("That tastes good."); - ident = TRUE; - break; - } -#else - case SV_FOOD_PINT_OF_ALE: - case SV_FOOD_PINT_OF_WINE: - { - msg_print("That tastes good."); - ident = TRUE; - break; - } -#endif - - } - } - p_ptr->update |= (PU_COMBINE | PU_REORDER); - - if (!(object_is_aware(o_ptr))) - { - chg_virtue(V_KNOWLEDGE, -1); - chg_virtue(V_PATIENCE, -1); - chg_virtue(V_CHANCE, 1); - } - - /* We have tried it */ - if (o_ptr->tval == TV_FOOD) object_tried(o_ptr); - - /* The player is now aware of the object */ - if (ident && !object_is_aware(o_ptr)) - { - object_aware(o_ptr); - gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); - } - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - - /* Food can feed the player */ - if (prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE)) - { - /* Reduced nutritional benefit */ - (void)set_food(p_ptr->food + (o_ptr->pval / 10)); - msg_print(_("あなたのような者にとって食糧など僅かな栄養にしかならない。", - "Mere victuals hold scant sustenance for a being such as yourself.")); - - if (p_ptr->food < PY_FOOD_ALERT) /* Hungry */ - msg_print(_("あなたの飢えは新鮮な血によってのみ満たされる!", - "Your hunger can only be satisfied with fresh blood!")); - } - else if ((prace_is_(RACE_SKELETON) || - prace_is_(RACE_GOLEM) || - prace_is_(RACE_ZOMBIE) || - prace_is_(RACE_SPECTRE)) && - (o_ptr->tval == TV_STAFF || o_ptr->tval == TV_WAND)) - { - concptr staff; - - if (o_ptr->tval == TV_STAFF && - (item < 0) && (o_ptr->number > 1)) - { - msg_print(_("まずは杖を拾わなければ。", "You must first pick up the staffs.")); - return; - } - staff = (o_ptr->tval == TV_STAFF) ? _("杖", "staff") : _("魔法棒", "wand"); - - /* "Eat" charges */ - if (o_ptr->pval == 0) - { - msg_format(_("この%sにはもう魔力が残っていない。", "The %s has no charges left."), staff); - o_ptr->ident |= (IDENT_EMPTY); - p_ptr->update |= (PU_COMBINE | PU_REORDER); - p_ptr->window |= (PW_INVEN); - - return; - } - msg_format(_("あなたは%sの魔力をエネルギー源として吸収した。", "You absorb mana of the %s as your energy."), staff); - - /* Use a single charge */ - o_ptr->pval--; - - /* Eat a charge */ - set_food(p_ptr->food + 5000); - - /* XXX Hack -- unstack if necessary */ - if (o_ptr->tval == TV_STAFF && - (item >= 0) && (o_ptr->number > 1)) - { - object_type forge; - object_type *q_ptr; - q_ptr = &forge; - - /* Obtain a local object */ - object_copy(q_ptr, o_ptr); - - /* Modify quantity */ - q_ptr->number = 1; - - /* Restore the charges */ - o_ptr->pval++; - - /* Unstack the used item */ - o_ptr->number--; - p_ptr->total_weight -= q_ptr->weight; - item = inven_carry(q_ptr); - - msg_format(_("杖をまとめなおした。", "You unstack your staff.")); - } - - /* Describe charges in the pack */ - if (item >= 0) - { - inven_item_charges(item); - } - - /* Describe charges on the floor */ - else - { - floor_item_charges(0 - item); - } - - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* Don't eat a staff/wand itself */ - return; - } - else if ((prace_is_(RACE_DEMON) || - (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_DEMON)) && - (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_CORPSE && - my_strchr("pht", r_info[o_ptr->pval].d_char))) - { - /* Drain vitality of humanoids */ - GAME_TEXT o_name[MAX_NLEN]; - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - msg_format(_("%sは燃え上り灰になった。精力を吸収した気がする。", "%^s is burnt to ashes. You absorb its vitality!"), o_name); - (void)set_food(PY_FOOD_MAX - 1); - } - else if (prace_is_(RACE_SKELETON)) - { -#if 0 - if (o_ptr->tval == TV_SKELETON || - (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON)) - { - msg_print(_("あなたは骨で自分の体を補った。", "Your body absorbs the bone.")); - set_food(p_ptr->food + 5000); - } - else -#endif - - if (!((o_ptr->sval == SV_FOOD_WAYBREAD) || - (o_ptr->sval < SV_FOOD_BISCUIT))) - { - object_type forge; - object_type *q_ptr = &forge; - - msg_print(_("食べ物がアゴを素通りして落ちた!", "The food falls through your jaws!")); - object_prep(q_ptr, lookup_kind(o_ptr->tval, o_ptr->sval)); - - /* Drop the object from heaven */ - (void)drop_near(q_ptr, -1, p_ptr->y, p_ptr->x); - } - else - { - msg_print(_("食べ物がアゴを素通りして落ち、消えた!", "The food falls through your jaws and vanishes!")); - } - } - else if (prace_is_(RACE_GOLEM) || - prace_is_(RACE_ZOMBIE) || - prace_is_(RACE_ENT) || - prace_is_(RACE_DEMON) || - prace_is_(RACE_ANDROID) || - prace_is_(RACE_SPECTRE) || - (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING)) - { - msg_print(_("生者の食物はあなたにとってほとんど栄養にならない。", "The food of mortals is poor sustenance for you.")); - set_food(p_ptr->food + ((o_ptr->pval) / 20)); - } - else if (o_ptr->tval == TV_FOOD && o_ptr->sval == SV_FOOD_WAYBREAD) - { - /* Waybread is always fully satisfying. */ - set_food(MAX(p_ptr->food, PY_FOOD_MAX - 1)); - } - else - { - /* Food can feed the player */ - (void)set_food(p_ptr->food + o_ptr->pval); - } - - /* Destroy a food in the pack */ - if (item >= 0) - { - inven_item_increase(item, -1); - inven_item_describe(item); - inven_item_optimize(item); - } - - /* Destroy a food on the floor */ - else - { - floor_item_increase(0 - item, -1); - floor_item_describe(0 - item); - floor_item_optimize(0 - item); - } -} - - -/*! - * @brief 食料を食べるコマンドのメインルーチン / - * Eat some food (from the pack or floor) - * @return なし - */ -void do_cmd_eat_food(void) -{ - OBJECT_IDX item; - concptr q, s; - - if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) - { - set_action(ACTION_NONE); - } - - /* Restrict choices to food */ - item_tester_hook = item_tester_hook_eatable; - - q = _("どれを食べますか? ", "Eat which item? "); - s = _("食べ物がない。", "You have nothing to eat."); - - if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Eat the object */ - do_cmd_eat_food_aux(item); -} - diff --git a/src/cmd-eat.h b/src/cmd-eat.h deleted file mode 100644 index 50df11aed..000000000 --- a/src/cmd-eat.h +++ /dev/null @@ -1,3 +0,0 @@ - -extern void do_cmd_eat_food(void); -extern void do_cmd_eat_food_aux(INVENTORY_IDX item); diff --git a/src/cmd-hissatsu.c b/src/cmd-hissatsu.c deleted file mode 100644 index 64e0e6f18..000000000 --- a/src/cmd-hissatsu.c +++ /dev/null @@ -1,436 +0,0 @@ -/*! - * @file hissatsu.c - * @brief 剣術の実装 / Blade arts - * @date 2014/01/17 - * @author - * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n - * This software may be copied and distributed for educational, research,\n - * and not for profit purposes provided that this copyright and statement\n - * are included in all such copies. Other copyrights may also apply.\n - * 2014 Deskull rearranged comment for Doxygen.\n - */ - -#include "angband.h" -#include "monsterrace-hook.h" -#include "player-status.h" - -#define TECHNIC_HISSATSU (REALM_HISSATSU - MIN_TECHNIC) - - -/*! - * @brief 使用可能な剣術を選択する / - * Allow user to choose a blade arts. - * @param sn 選択した特殊技能ID、キャンセルの場合-1、不正な選択の場合-2を返す - * @return 発動可能な魔法を選択した場合TRUE、キャンセル処理か不正な選択が行われた場合FALSEを返す。 - * @details - * If a valid spell is chosen, saves it in '*sn' and returns TRUE\n - * If the user hits escape, returns FALSE, and set '*sn' to -1\n - * If there are no legal choices, returns FALSE, and sets '*sn' to -2\n - *\n - * The "prompt" should be "cast", "recite", or "study"\n - * The "known" should be TRUE for cast/pray, FALSE for study\n - *\n - * nb: This function has a (trivial) display bug which will be obvious\n - * when you run it. It's probably easy to fix but I haven't tried,\n - * sorry.\n - */ -static int get_hissatsu_power(SPELL_IDX *sn) -{ - SPELL_IDX i; - int j = 0; - int num = 0; - POSITION y = 1; - POSITION x = 15; - PLAYER_LEVEL plev = p_ptr->lev; - int ask = TRUE; - char choice; - char out_val[160]; - SPELL_IDX sentaku[32]; - concptr p = _("必殺剣", "special attack"); - COMMAND_CODE code; - magic_type spell; - bool flag, redraw; - int menu_line = (use_menu ? 1 : 0); - - /* Assume cancelled */ - *sn = (-1); - - /* Get the spell, if available */ - if (repeat_pull(&code)) - { - *sn = (SPELL_IDX)code; - /* Verify the spell */ - if (technic_info[TECHNIC_HISSATSU][*sn].slevel <= plev) - { - /* Success */ - return (TRUE); - } - } - - /* Nothing chosen yet */ - flag = FALSE; - - /* No redraw yet */ - redraw = FALSE; - - for (i = 0; i < 32; i++) - { - if (technic_info[TECHNIC_HISSATSU][i].slevel <= PY_MAX_LEVEL) - { - sentaku[num] = i; - num++; - } - } - - /* Build a prompt (accept all spells) */ - (void)strnfmt(out_val, 78, - _("(%^s %c-%c, '*'で一覧, ESC) どの%sを使いますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "), - p, I2A(0), "abcdefghijklmnopqrstuvwxyz012345"[num - 1], p); - - if (use_menu) screen_save(); - choice = always_show_list ? ESCAPE : 1; - - while (!flag) - { - if(choice==ESCAPE) choice = ' '; - else if( !get_com(out_val, &choice, FALSE) )break; - - if (use_menu && choice != ' ') - { - switch(choice) - { - case '0': - { - screen_load(); - return (FALSE); - } - - case '8': - case 'k': - case 'K': - { - do - { - menu_line += 31; - if (menu_line > 32) menu_line -= 32; - } while(!(p_ptr->spell_learned1 & (1L << (menu_line-1)))); - break; - } - - case '2': - case 'j': - case 'J': - { - do - { - menu_line++; - if (menu_line > 32) menu_line -= 32; - } while(!(p_ptr->spell_learned1 & (1L << (menu_line-1)))); - break; - } - - case '4': - case 'h': - case 'H': - case '6': - case 'l': - case 'L': - { - bool reverse = FALSE; - if ((choice == '4') || (choice == 'h') || (choice == 'H')) reverse = TRUE; - if (menu_line > 16) - { - menu_line -= 16; - reverse = TRUE; - } - else menu_line+=16; - while(!(p_ptr->spell_learned1 & (1L << (menu_line-1)))) - { - if (reverse) - { - menu_line--; - if (menu_line < 2) reverse = FALSE; - } - else - { - menu_line++; - if (menu_line > 31) reverse = TRUE; - } - } - break; - } - - case 'x': - case 'X': - case '\r': - case '\n': - { - i = menu_line - 1; - ask = FALSE; - break; - } - } - } - /* Request redraw */ - if ((choice == ' ') || (choice == '*') || (choice == '?') || (use_menu && ask)) - { - /* Show the list */ - if (!redraw || use_menu) - { - char psi_desc[80]; - int line; - redraw = TRUE; - if (!use_menu) screen_save(); - - /* Display a list of spells */ - prt("", y, x); - put_str(_("名前 Lv MP 名前 Lv MP ", - "name Lv SP name Lv SP "), y, x + 5); - prt("", y+1, x); - /* Dump the spells */ - for (i = 0, line = 0; i < 32; i++) - { - spell = technic_info[TECHNIC_HISSATSU][i]; - - if (spell.slevel > PY_MAX_LEVEL) continue; - line++; - if (!(p_ptr->spell_learned1 >> i)) break; - - /* Access the spell */ - if (spell.slevel > plev) continue; - if (!(p_ptr->spell_learned1 & (1L << i))) continue; - if (use_menu) - { - if (i == (menu_line-1)) - strcpy(psi_desc, _(" 》", " > ")); - else strcpy(psi_desc, " "); - - } - else - { - char letter; - if (line <= 26) - letter = I2A(line-1); - else - letter = '0' + line - 27; - sprintf(psi_desc, " %c)",letter); - } - - /* Dump the spell --(-- */ - strcat(psi_desc, format(" %-18s%2d %3d", - do_spell(REALM_HISSATSU, i, SPELL_NAME), - spell.slevel, spell.smana)); - prt(psi_desc, y + (line%17) + (line >= 17), x+(line/17)*30); - prt("", y + (line%17) + (line >= 17) + 1, x+(line/17)*30); - } - } - - /* Hide the list */ - else - { - /* Hide list */ - redraw = FALSE; - screen_load(); - } - - /* Redo asking */ - continue; - } - - if (!use_menu) - { - if (isalpha(choice)) - { - /* Note verify */ - ask = (isupper(choice)); - - /* Lowercase */ - if (ask) choice = (char)tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - } - else - { - ask = FALSE; /* Can't uppercase digits */ - - i = choice - '0' + 26; - } - } - - /* Totally Illegal */ - if ((i < 0) || (i >= 32) || !(p_ptr->spell_learned1 & (1 << sentaku[i]))) - { - bell(); - continue; - } - - j = sentaku[i]; - - /* Verify it */ - if (ask) - { - char tmp_val[160]; - - /* Prompt */ - (void) strnfmt(tmp_val, 78, _("%sを使いますか?", "Use %s? "), do_spell(REALM_HISSATSU, j, SPELL_NAME)); - - /* Belay that order */ - if (!get_check(tmp_val)) continue; - } - - /* Stop the loop */ - flag = TRUE; - } - if (redraw) screen_load(); - - p_ptr->window |= (PW_SPELL); - handle_stuff(); - - /* Abort if needed */ - if (!flag) return (FALSE); - - /* Save the choice */ - (*sn) = j; - - repeat_push((COMMAND_CODE)j); - - /* Success */ - return (TRUE); -} - - -/*! - * @brief 剣術コマンドのメインルーチン - * @return なし - */ -void do_cmd_hissatsu(void) -{ - SPELL_IDX n = 0; - magic_type spell; - - if (cmd_limit_confused(p_ptr)) return; - if (!has_melee_weapon(INVEN_RARM) && !has_melee_weapon(INVEN_LARM)) - { - if (flush_failure) flush(); - msg_print(_("武器を持たないと必殺技は使えない!", "You need to wield a weapon!")); - return; - } - if (!p_ptr->spell_learned1) - { - msg_print(_("何も技を知らない。", "You don't know any special attacks.")); - return; - } - - if (p_ptr->special_defense & KATA_MASK) - { - set_action(ACTION_NONE); - } - - if (!get_hissatsu_power(&n)) return; - - spell = technic_info[TECHNIC_HISSATSU][n]; - - /* Verify "dangerous" spells */ - if (spell.smana > p_ptr->csp) - { - if (flush_failure) flush(); - /* Warning */ - msg_print(_("MPが足りません。", "You do not have enough mana to use this power.")); - msg_print(NULL); - return; - } - - sound(SOUND_ZAP); - - if (!do_spell(REALM_HISSATSU, n, SPELL_CAST)) return; - - take_turn(p_ptr, 100); - - /* Use some mana */ - p_ptr->csp -= spell.smana; - - /* Limit */ - if (p_ptr->csp < 0) p_ptr->csp = 0; - p_ptr->redraw |= (PR_MANA); - p_ptr->window |= (PW_PLAYER | PW_SPELL); -} - - -/*! - * @brief 剣術コマンドの学習 - * @return なし - */ -void do_cmd_gain_hissatsu(void) -{ - OBJECT_IDX item; - int i, j; - - object_type *o_ptr; - concptr q, s; - - bool gain = FALSE; - - if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) - { - set_action(ACTION_NONE); - } - - if (p_ptr->blind || no_lite()) - { - msg_print(_("目が見えない!", "You cannot see!")); - return; - } - - if (cmd_limit_confused(p_ptr)) return; - - if (!(p_ptr->new_spells)) - { - msg_print(_("新しい必殺技を覚えることはできない!", "You cannot learn any new special attacks!")); - return; - } - -#ifdef JP - msg_format("あと %d 種の必殺技を学べる。", p_ptr->new_spells); -#else - msg_format("You can learn %d new special attack%s.", p_ptr->new_spells, (p_ptr->new_spells == 1?"":"s")); -#endif - - item_tester_tval = TV_HISSATSU_BOOK; - - q = _("どの書から学びますか? ", "Study which book? "); - s = _("読める書がない。", "You have no books that you can read."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR)); - if (!o_ptr) return; - - for (i = o_ptr->sval * 8; i < o_ptr->sval * 8 + 8; i++) - { - if (p_ptr->spell_learned1 & (1L << i)) continue; - if (technic_info[TECHNIC_HISSATSU][i].slevel > p_ptr->lev) continue; - - p_ptr->spell_learned1 |= (1L << i); - p_ptr->spell_worked1 |= (1L << i); - msg_format(_("%sの技を覚えた。", "You have learned the special attack of %s."), do_spell(REALM_HISSATSU, i, SPELL_NAME)); - for (j = 0; j < 64; j++) - { - /* Stop at the first empty space */ - if (p_ptr->spell_order[j] == 99) break; - } - p_ptr->spell_order[j] = i; - gain = TRUE; - } - - if (!gain) - { - msg_print(_("何も覚えられなかった。", "You were not able to learn any special attacks.")); - } - else - { - take_turn(p_ptr, 100); - } - - p_ptr->update |= (PU_SPELLS); -} - - diff --git a/src/cmd-hissatsu.h b/src/cmd-hissatsu.h deleted file mode 100644 index fc4cea25f..000000000 --- a/src/cmd-hissatsu.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -/* hissatsu.c */ - -extern void do_cmd_hissatsu(void); -extern void do_cmd_gain_hissatsu(void); diff --git a/src/cmd-io/cmd-autopick.c b/src/cmd-io/cmd-autopick.c new file mode 100644 index 000000000..1febc932a --- /dev/null +++ b/src/cmd-io/cmd-autopick.c @@ -0,0 +1,212 @@ +#include "cmd-io/cmd-autopick.h" +#include "cmd-io/cmd-save.h" +#include "autopick/autopick-util.h" +#include "autopick/autopick-commands-table.h" +#include "autopick/autopick-dirty-flags.h" +#include "autopick/autopick-initializer.h" +#include "autopick/autopick-entry.h" +#include "autopick/autopick-drawer.h" +#include "autopick/autopick-reader-writer.h" +#include "autopick/autopick-command-menu.h" +#include "autopick/autopick-editor-command.h" +#include "autopick/autopick-editor-util.h" +#include "autopick/autopick-inserter-killer.h" +#include "autopick/autopick-pref-processor.h" +#include "io/input-key-acceptor.h" +#include "io/read-pref-file.h" +#include "util/int-char-converter.h" +#include "term/screen-processor.h" +#include "world/world.h" + +/* + * Check special key code and get a movement command id + */ +static int analyze_move_key(text_body_type *tb, int skey) +{ + int com_id; + if (!(skey & SKEY_MASK)) return 0; + + switch (skey & ~SKEY_MOD_MASK) + { + case SKEY_DOWN: com_id = EC_DOWN; break; + case SKEY_LEFT: com_id = EC_LEFT; break; + case SKEY_RIGHT: com_id = EC_RIGHT; break; + case SKEY_UP: com_id = EC_UP; break; + case SKEY_PGUP: com_id = EC_PGUP; break; + case SKEY_PGDOWN: com_id = EC_PGDOWN; break; + case SKEY_TOP: com_id = EC_TOP; break; + case SKEY_BOTTOM: com_id = EC_BOTTOM; break; + default: + return 0; + } + + if (!(skey & SKEY_MOD_SHIFT)) + { + /* + * Un-shifted cursor keys cancells + * selection created by shift+cursor. + */ + if (tb->mark & MARK_BY_SHIFT) + { + tb->mark = 0; + tb->dirty_flags |= DIRTY_ALL; + } + + return com_id; + } + + if (tb->mark) return com_id; + + int len = strlen(tb->lines_list[tb->cy]); + tb->mark = MARK_MARK | MARK_BY_SHIFT; + tb->my = tb->cy; + tb->mx = tb->cx; + if (tb->cx > len) tb->mx = len; + + if (com_id == EC_UP || com_id == EC_DOWN) + { + tb->dirty_flags |= DIRTY_ALL; + } + else + { + tb->dirty_line = tb->cy; + } + + return com_id; +} + +/* + * In-game editor of Object Auto-picker/Destoryer + * @param player_ptr プレーヤーへの参照ポインタ + */ +void do_cmd_edit_autopick(player_type *player_ptr) +{ + static int cx_save = 0; + static int cy_save = 0; + autopick_type an_entry, *entry = &an_entry; + char buf[MAX_LINELEN]; + int i; + int key = -1; + static s32b old_autosave_turn = 0L; + ape_quittance quit = APE_QUIT; + + text_body_type text_body; + text_body_type *tb = &text_body; + tb->changed = FALSE; + tb->cx = cx_save; + tb->cy = cy_save; + tb->upper = tb->left = 0; + tb->mark = 0; + tb->mx = tb->my = 0; + tb->old_cy = tb->old_upper = tb->old_left = -1; + tb->old_wid = tb->old_hgt = -1; + tb->old_com_id = 0; + + tb->yank = NULL; + tb->search_o_ptr = NULL; + tb->search_str = NULL; + tb->last_destroyed = NULL; + tb->dirty_flags = DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION; + tb->dirty_line = -1; + tb->filename_mode = PT_DEFAULT; + + if (current_world_ptr->game_turn < old_autosave_turn) + { + while (old_autosave_turn > current_world_ptr->game_turn) old_autosave_turn -= TURNS_PER_TICK * TOWN_DAWN; + } + + if (current_world_ptr->game_turn > old_autosave_turn + 100L) + { + do_cmd_save_game(player_ptr, TRUE); + old_autosave_turn = current_world_ptr->game_turn; + } + + update_playtime(); + init_autopick(); + if (autopick_last_destroyed_object.k_idx) + { + autopick_entry_from_object(player_ptr, entry, &autopick_last_destroyed_object); + tb->last_destroyed = autopick_line_from_entry_kill(entry); + } + + tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode); + for (i = 0; i < tb->cy; i++) + { + if (!tb->lines_list[i]) + { + tb->cy = tb->cx = 0; + break; + } + } + + screen_save(); + while (quit == APE_QUIT) + { + int com_id = 0; + draw_text_editor(player_ptr, tb); + prt(_("(^Q:終了 ^W:セーブして終了, ESC:メニュー, その他:入力)", + "(^Q:Quit, ^W:Save&Quit, ESC:Menu, Other:Input text)"), 0, 0); + if (!tb->mark) + { + prt(format("(%d,%d)", tb->cx, tb->cy), 0, 60); + } + else + { + prt(format("(%d,%d)-(%d,%d)", tb->mx, tb->my, tb->cx, tb->cy), 0, 60); + } + + term_gotoxy(tb->cx - tb->left, tb->cy - tb->upper + 1); + tb->dirty_flags = 0; + tb->dirty_line = -1; + tb->old_cy = tb->cy; + tb->old_upper = tb->upper; + tb->old_left = tb->left; + tb->old_wid = tb->wid; + tb->old_hgt = tb->hgt; + + key = inkey_special(TRUE); + + if (key & SKEY_MASK) + { + com_id = analyze_move_key(tb, key); + } + else if (key == ESCAPE) + { + com_id = do_command_menu(0, 0); + tb->dirty_flags |= DIRTY_SCREEN; + } + else if (!iscntrl((unsigned char)key)) + { + if (tb->mark) + { + tb->mark = 0; + tb->dirty_flags |= DIRTY_ALL; + } + + insert_single_letter(tb, key); + continue; + } + else + { + com_id = get_com_id((char)key); + } + + if (com_id) quit = do_editor_command(player_ptr, tb, com_id); + } + + screen_load(); + strcpy(buf, pickpref_filename(player_ptr, tb->filename_mode)); + + if (quit == APE_QUIT_AND_SAVE) + write_text_lines(buf, tb->lines_list); + + free_text_lines(tb->lines_list); + string_free(tb->search_str); + string_free(tb->last_destroyed); + kill_yank_chain(tb); + + process_autopick_file(player_ptr, buf, process_autopick_file_command); + current_world_ptr->start_time = (u32b)time(NULL); + cx_save = tb->cx; + cy_save = tb->cy; +} diff --git a/src/cmd-io/cmd-autopick.h b/src/cmd-io/cmd-autopick.h new file mode 100644 index 000000000..f2792a42b --- /dev/null +++ b/src/cmd-io/cmd-autopick.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_edit_autopick(player_type *player_ptr); diff --git a/src/cmd-io/cmd-diary.c b/src/cmd-io/cmd-diary.c new file mode 100644 index 000000000..e54190c4b --- /dev/null +++ b/src/cmd-io/cmd-diary.c @@ -0,0 +1,162 @@ +#include "cmd-io/cmd-diary.h" +#include "cmd-io/diary-subtitle-table.h" +#include "core/asking-player.h" +#include "core/show-file.h" +#include "game-option/play-record-options.h" +#include "main/sound-of-music.h" +#include "io/chuukei.h" +#include "io/files-util.h" +#include "io/input-key-acceptor.h" +#include "io/write-diary.h" +#include "player/player-personality.h" +#include "player/player-realm.h" +#include "term/screen-processor.h" +#include "util/angband-files.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" +#include "world/world.h" + +/*! + * @brief 日記のタイトル表記と内容出力 + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +static void display_diary(player_type *creature_ptr) +{ + char diary_title[256]; + GAME_TEXT file_name[MAX_NLEN]; + char buf[1024]; + char tmp[80]; + sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base); + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name); + + if (creature_ptr->pclass == CLASS_WARRIOR || creature_ptr->pclass == CLASS_MONK || creature_ptr->pclass == CLASS_SAMURAI || creature_ptr->pclass == CLASS_BERSERKER) + strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1)]); + else if (is_wizard_class(creature_ptr)) + strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1) + 1]); + else strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 2) + 1]); + +#ifdef JP + sprintf(diary_title, "「%s%s%sの伝説 -%s-」", ap_ptr->title, ap_ptr->no ? "の" : "", creature_ptr->name, tmp); +#else + sprintf(diary_title, "Legend of %s %s '%s'", ap_ptr->title, creature_ptr->name, tmp); +#endif + + (void)show_file(creature_ptr, FALSE, buf, diary_title, -1, 0); +} + + +/*! + * @brief 日記に任意の内容を表記するコマンドのメインルーチン / + * @return なし + */ +static void add_diary_note(player_type *creature_ptr) +{ + char tmp[80] = "\0"; + char bunshou[80] = "\0"; + if (get_string(_("内容: ", "diary note: "), tmp, 79)) + { + strcpy(bunshou, tmp); + exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 0, bunshou); + } +} + +/*! + * @brief 最後に取得したアイテムの情報を日記に追加するメインルーチン / + * @return なし + */ +static void do_cmd_last_get(player_type *creaute_ptr) +{ + if (record_o_name[0] == '\0') return; + + char buf[256]; + sprintf(buf, _("%sの入手を記録します。", "Do you really want to record getting %s? "), record_o_name); + if (!get_check(buf)) return; + + GAME_TURN turn_tmp = current_world_ptr->game_turn; + current_world_ptr->game_turn = record_turn; + sprintf(buf, _("%sを手に入れた。", "discover %s."), record_o_name); + exe_write_diary(creaute_ptr, DIARY_DESCRIPTION, 0, buf); + current_world_ptr->game_turn = turn_tmp; +} + + +/*! + * @brief ファイル中の全日記記録を消去する / + * @return なし + */ +static void do_cmd_erase_diary(void) +{ + GAME_TEXT file_name[MAX_NLEN]; + char buf[256]; + FILE *fff = NULL; + + if (!get_check(_("本当に記録を消去しますか?", "Do you really want to delete all your record? "))) return; + sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base); + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name); + fd_kill(buf); + + fff = angband_fopen(buf, "w"); + if (fff) + { + angband_fclose(fff); + msg_format(_("記録を消去しました。", "deleted record.")); + } + else + { + msg_format(_("%s の消去に失敗しました。", "failed to delete %s."), buf); + } + + msg_print(NULL); +} + + +/*! + * @brief 日記コマンド + * @param crerature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void do_cmd_diary(player_type *creature_ptr) +{ + screen_save(); + int i; + while (TRUE) + { + term_clear(); + prt(_("[ 記録の設定 ]", "[ Play Record ]"), 2, 0); + prt(_("(1) 記録を見る", "(1) Display your record"), 4, 5); + prt(_("(2) 文章を記録する", "(2) Add record"), 5, 5); + prt(_("(3) 直前に入手又は鑑定したものを記録する", "(3) Record the last item you got or identified"), 6, 5); + prt(_("(4) 記録を消去する", "(4) Delete your record"), 7, 5); + prt(_("(R) プレイ動画を記録する/中止する", "(R) Record playing movie / or stop it"), 9, 5); + prt(_("コマンド:", "Command: "), 18, 0); + i = inkey(); + if (i == ESCAPE) break; + + switch (i) + { + case '1': + display_diary(creature_ptr); + break; + case '2': + add_diary_note(creature_ptr); + break; + case '3': + do_cmd_last_get(creature_ptr); + break; + case '4': + do_cmd_erase_diary(); + break; + case 'r': case 'R': + screen_load(); + prepare_movie_hooks(creature_ptr); + return; + default: + bell(); + } + + msg_erase(); + } + + screen_load(); +} diff --git a/src/cmd-io/cmd-diary.h b/src/cmd-io/cmd-diary.h new file mode 100644 index 000000000..c6ea069f1 --- /dev/null +++ b/src/cmd-io/cmd-diary.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_diary(player_type *creature_ptr); diff --git a/src/cmd-io/cmd-dump.c b/src/cmd-io/cmd-dump.c new file mode 100644 index 000000000..75a8324c1 --- /dev/null +++ b/src/cmd-io/cmd-dump.c @@ -0,0 +1,317 @@ +/*! + * @brief プレイヤーのインターフェイスに関するコマンドの実装 / Interface commands + * @date 2014/01/02 + * @author + * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke + * This software may be copied and distributed for educational, research, + * and not for profit purposes provided that this copyright and statement + * are included in all such copies. Other copyrights may also apply. + * 2020 Hourier Rearranged + */ + +#include "cmd-io/cmd-dump.h" +#include "cmd-io/feeling-table.h" +#include "core/asking-player.h" +#include "dungeon/quest.h" +#include "floor/floor-town.h" +#include "io-dump/dump-remover.h" +#include "io-dump/dump-util.h" +#include "io/chuukei.h" +#include "io/files-util.h" +#include "io/input-key-acceptor.h" +#include "io/interpret-pref-file.h" +#include "io/read-pref-file.h" +#include "locale/english.h" +#include "main/sound-of-music.h" +#include "mutation/mutation-flag-types.h" +#include "player/player-personalities-types.h" +#include "system/angband-version.h" +#include "system/floor-type-definition.h" +#include "term/gameterm.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/angband-files.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" +#include "view/display-player.h" // 暫定。後で消す. +#include "world/world.h" +#include "player/player-status-flags.h" + +/*! + * @brief 画面を再描画するコマンドのメインルーチン + * Hack -- redraw the screen + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + * @details + * Allow absolute file names? + */ +void do_cmd_pref(player_type *creature_ptr) +{ + char buf[80]; + strcpy(buf, ""); + if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return; + + (void)interpret_pref_file(creature_ptr, buf); +} + + +/* + * Interact with "colors" + */ +void do_cmd_colors(player_type *creature_ptr, void(*process_autopick_file_command)(char*)) +{ + int i; + char tmp[160]; + char buf[1024]; + FILE *auto_dump_stream; + screen_save(); + while (TRUE) + { + term_clear(); + prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0); + prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5); + prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5); + prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5); + prt(_("コマンド: ", "Command: "), 8, 0); + i = inkey(); + if (i == ESCAPE) break; + + if (i == '1') + { + prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0); + prt(_("ファイル: ", "File: "), 10, 0); + sprintf(tmp, "%s.prf", creature_ptr->base_name); + if (!askfor(tmp, 70)) continue; + + (void)process_pref_file(creature_ptr, tmp, process_autopick_file_command); + term_xtra(TERM_XTRA_REACT, 0); + term_redraw(); + } + else if (i == '2') + { + static concptr mark = "Colors"; + prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0); + prt(_("ファイル: ", "File: "), 10, 0); + sprintf(tmp, "%s.prf", creature_ptr->base_name); + if (!askfor(tmp, 70)) continue; + + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp); + if (!open_auto_dump(&auto_dump_stream, buf, mark)) continue; + + auto_dump_printf(auto_dump_stream, _("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n")); + for (i = 0; i < 256; i++) + { + int kv = angband_color_table[i][0]; + int rv = angband_color_table[i][1]; + int gv = angband_color_table[i][2]; + int bv = angband_color_table[i][3]; + + concptr name = _("未知", "unknown"); + if (!kv && !rv && !gv && !bv) continue; + + if (i < 16) name = color_names[i]; + + auto_dump_printf(auto_dump_stream, _("# カラー '%s'\n", "# Color '%s'\n"), name); + auto_dump_printf(auto_dump_stream, "V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n", + i, kv, rv, gv, bv); + } + + close_auto_dump(&auto_dump_stream, mark); + msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions.")); + } + else if (i == '3') + { + static byte a = 0; + prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0); + while (TRUE) + { + concptr name; + clear_from(10); + for (byte j = 0; j < 16; j++) + { + term_putstr(j * 4, 20, -1, a, "###"); + term_putstr(j * 4, 22, -1, j, format("%3d", j)); + } + + name = ((a < 16) ? color_names[a] : _("未定義", "undefined")); + term_putstr(5, 10, -1, TERM_WHITE, + format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name)); + term_putstr(5, 12, -1, TERM_WHITE, + format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x", + angband_color_table[a][0], + angband_color_table[a][1], + angband_color_table[a][2], + angband_color_table[a][3])); + term_putstr(0, 14, -1, TERM_WHITE, + _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): ")); + i = inkey(); + if (i == ESCAPE) break; + + if (i == 'n') a = (byte)(a + 1); + if (i == 'N') a = (byte)(a - 1); + if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1); + if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1); + if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1); + if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1); + if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1); + if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1); + if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1); + if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1); + + term_xtra(TERM_XTRA_REACT, 0); + term_redraw(); + } + } + else + { + bell(); + } + + msg_erase(); + } + + screen_load(); +} + + +/* + * Note something in the message recall + */ +void do_cmd_note(void) +{ + char buf[80]; + strcpy(buf, ""); + if (!get_string(_("メモ: ", "Note: "), buf, 60)) return; + if (!buf[0] || (buf[0] == ' ')) return; + + msg_format(_("メモ: %s", "Note: %s"), buf); +} + + +/* + * Mention the current version + */ +void do_cmd_version(void) +{ +#if FAKE_VER_EXTRA > 0 + msg_format(_("馬鹿馬鹿蛮怒(Bakabakaband) %d.%d.%d.%d", "You are playing Bakabakaband %d.%d.%d.%d."), + FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA); +#else + msg_format(_("馬鹿馬鹿蛮怒(Bakabakaband) %d.%d.%d", "You are playing Bakabakaband %d.%d.%d."), + FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH); +#endif +} + + +/* + * Note that "feeling" is set to zero unless some time has passed. + * Note that this is done when the level is GENERATED, not entered. + */ +void do_cmd_feeling(player_type *creature_ptr) +{ + if (creature_ptr->wild_mode) return; + + if (creature_ptr->current_floor_ptr->inside_quest && !random_quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level)) + { + msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level.")); + return; + } + + if (creature_ptr->town_num && !creature_ptr->current_floor_ptr->dun_level) + { + if (!strcmp(town_info[creature_ptr->town_num].name, _("荒野", "wilderness"))) + { + msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness.")); + return; + } + + msg_print(_("典型的な町のようだ。", "Looks like a typical town.")); + return; + } + + if (!creature_ptr->current_floor_ptr->dun_level) + { + msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness.")); + return; + } + + if (have_good_luck(creature_ptr)) + msg_print(do_cmd_feeling_text_lucky[creature_ptr->feeling]); + else if (is_echizen(creature_ptr)) + msg_print(do_cmd_feeling_text_combat[creature_ptr->feeling]); + else + msg_print(do_cmd_feeling_text[creature_ptr->feeling]); +} + + +/* + * Display the time and date + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void do_cmd_time(player_type *creature_ptr) +{ + int day, hour, min; + extract_day_hour_min(creature_ptr, &day, &hour, &min); + + char desc[1024]; + strcpy(desc, _("変な時刻だ。", "It is a strange time.")); + + char day_buf[10]; + if (day < MAX_DAYS) sprintf(day_buf, "%d", day); + else strcpy(day_buf, "*****"); + + msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."), + day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM"); + + char buf[1024]; + if (!randint0(10) || creature_ptr->image) + { + path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt")); + } + else + { + path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt")); + } + + FILE *fff; + fff = angband_fopen(buf, "rt"); + + if (!fff) return; + + int full = hour * 100 + min; + int start = 9999; + int end = -9999; + int num = 0; + while (!angband_fgets(fff, buf, sizeof(buf))) + { + if (!buf[0] || (buf[0] == '#')) continue; + if (buf[1] != ':') continue; + + if (buf[0] == 'S') + { + start = atoi(buf + 2); + end = start + 59; + continue; + } + + if (buf[0] == 'E') + { + end = atoi(buf + 2); + continue; + } + + if ((start > full) || (full > end)) continue; + + if (buf[0] == 'D') + { + num++; + if (!randint0(num)) strcpy(desc, buf + 2); + + continue; + } + } + + msg_print(desc); + angband_fclose(fff); +} diff --git a/src/cmd-io/cmd-dump.h b/src/cmd-io/cmd-dump.h new file mode 100644 index 000000000..1ca4fcf77 --- /dev/null +++ b/src/cmd-io/cmd-dump.h @@ -0,0 +1,10 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_pref(player_type *creature_ptr); +void do_cmd_colors(player_type *creature_ptr, void(*process_autopick_file_command)(char*)); +void do_cmd_note(void); +void do_cmd_version(void); +void do_cmd_feeling(player_type *creature_ptr); +void do_cmd_time(player_type *creature_ptr); diff --git a/src/cmd-io/cmd-floor.c b/src/cmd-io/cmd-floor.c new file mode 100644 index 000000000..987eb0db8 --- /dev/null +++ b/src/cmd-io/cmd-floor.c @@ -0,0 +1,97 @@ +#include "cmd-io/cmd-floor.h" +#include "core/asking-player.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "floor/geometry.h" +#include "game-option/keymap-directory-getter.h" +#include "io/cursor.h" +#include "io/screen-util.h" +#include "main/sound-of-music.h" +#include "target/target-checker.h" +#include "target/target-setter.h" +#include "target/target-types.h" +#include "view/display-messages.h" +#include "window/main-window-util.h" + +/*! + * @brief ƒ^[ƒQƒbƒg‚ðÝ’è‚·‚éƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ + * Target command + * @return ‚È‚µ + */ +void do_cmd_target(player_type *creature_ptr) +{ + if (creature_ptr->wild_mode) + return; + + if (target_set(creature_ptr, TARGET_KILL)) + msg_print(_("ƒ^[ƒQƒbƒgŒˆ’èB", "Target Selected.")); + else + msg_print(_("ƒ^[ƒQƒbƒg‰ðœB", "Target Aborted.")); +} + +/*! + * @brief ŽüˆÍ‚ðŒ©“n‚·ƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ + * Look command + * @return ‚È‚µ + */ +void do_cmd_look(player_type *creature_ptr) +{ + creature_ptr->window |= PW_MONSTER_LIST; + handle_stuff(creature_ptr); + if (target_set(creature_ptr, TARGET_LOOK)) + msg_print(_("ƒ^[ƒQƒbƒgŒˆ’èB", "Target Selected.")); +} + +/*! + * @brief ˆÊ’u‚ðŠm”F‚·‚éƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ + * Allow the player to examine other sectors on the map + * @return ‚È‚µ + */ +void do_cmd_locate(player_type *creature_ptr) +{ + DIRECTION dir; + POSITION y1, x1; + GAME_TEXT tmp_val[80]; + GAME_TEXT out_val[160]; + TERM_LEN wid, hgt; + get_screen_size(&wid, &hgt); + POSITION y2 = y1 = panel_row_min; + POSITION x2 = x1 = panel_col_min; + while (TRUE) { + if ((y2 == y1) && (x2 == x1)) + strcpy(tmp_val, _("^ã", "\0")); + else + sprintf(tmp_val, "%s%s", ((y2 < y1) ? _("–k", " North") : (y2 > y1) ? _("“ì", " South") : ""), + ((x2 < x1) ? _("¼", " West") : (x2 > x1) ? _("“Œ", " East") : "")); + + sprintf(out_val, _("ƒ}ƒbƒvˆÊ’u [%d(%02d),%d(%02d)] (ƒvƒŒƒCƒ„[‚Ì%s) •ûŒü?", "Map sector [%d(%02d),%d(%02d)], which is%s your sector. Direction?"), + y2 / (hgt / 2), y2 % (hgt / 2), x2 / (wid / 2), x2 % (wid / 2), tmp_val); + + dir = 0; + while (!dir) { + char command; + if (!get_com(out_val, &command, TRUE)) + break; + + dir = get_keymap_dir(command); + if (!dir) + bell(); + } + + if (!dir) + break; + + if (change_panel(creature_ptr, ddy[dir], ddx[dir])) { + y2 = panel_row_min; + x2 = panel_col_min; + } + } + + verify_panel(creature_ptr); + creature_ptr->update |= PU_MONSTERS; + creature_ptr->redraw |= PR_MAP; + creature_ptr->window |= PW_OVERHEAD | PW_DUNGEON; + handle_stuff(creature_ptr); +} diff --git a/src/cmd-io/cmd-floor.h b/src/cmd-io/cmd-floor.h new file mode 100644 index 000000000..c48b11a80 --- /dev/null +++ b/src/cmd-io/cmd-floor.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_target(player_type *creature_ptr); +void do_cmd_look(player_type *creature_ptr); +void do_cmd_locate(player_type *creature_ptr); diff --git a/src/cmd-io/cmd-gameoption.c b/src/cmd-io/cmd-gameoption.c new file mode 100644 index 000000000..5511fb343 --- /dev/null +++ b/src/cmd-io/cmd-gameoption.c @@ -0,0 +1,713 @@ +#include "cmd-io/cmd-gameoption.h" +#include "autopick/autopick.h" +#include "cmd-io/cmd-autopick.h" +#include "cmd-io/cmd-dump.h" +#include "core/player-redraw-types.h" +#include "core/show-file.h" +#include "core/window-redrawer.h" +#include "game-option/game-play-options.h" +#include "game-option/keymap-directory-getter.h" +#include "game-option/option-flags.h" +#include "game-option/option-types-table.h" +#include "game-option/special-options.h" +#include "io/input-key-acceptor.h" +#include "io/write-diary.h" +#include "main/sound-of-music.h" +#include "system/game-option-types.h" +#include "term/gameterm.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/int-char-converter.h" +#include "util/string-processor.h" +#include "view/display-messages.h" +#include "world/world.h" + +#define OPT_NUM 15 + +typedef struct { + char key; + concptr name; + int row; +} opts; + +static opts option_fields[OPT_NUM] = { + { '1', _(" キー入力 オプション", "Input Options"), 3 }, + { '2', _(" マップ画面 オプション", "Map Screen Options"), 4 }, + { '3', _(" テキスト表示 オプション", "Text Display Options"), 5 }, + { '4', _(" ゲームプレイ オプション", "Game-Play Options"), 6 }, + { '5', _(" 行動中止関係 オプション", "Disturbance Options"), 7 }, + { '6', _(" 簡易自動破壊 オプション", "Easy Auto-Destroyer Options"), 8 }, + { 'r', _(" プレイ記録 オプション", "Play record Options"), 9 }, + + { 'p', _("自動拾いエディタ", "Auto-picker/destroyer editor"), 11 }, + { 'd', _(" 基本ウェイト量 ", "Base Delay Factor"), 12 }, + { 'h', _("低ヒットポイント", "Hitpoint Warning"), 13 }, + { 'm', _(" 低魔力色閾値 ", "Mana Color Threshold"), 14 }, + { 'a', _(" 自動セーブ オプション", "Autosave Options"), 15 }, + { 'w', _("ウインドウフラグ", "Window Flags"), 16 }, + + { 'b', _(" 初期 オプション (参照のみ)", "Birth Options (Browse Only)"), 18 }, + { 'c', _(" 詐欺 オプション", "Cheat Options"), 19 }, +}; + +/*! + * @brief セーブ頻度ターンの次の値を返す + * @param current 現在のセーブ頻度ターン値 + * @return 次のセーブ頻度ターン値 + */ +static s16b toggle_frequency(s16b current) +{ + switch (current) { + case 0: + return 50; + case 50: + return 100; + case 100: + return 250; + case 250: + return 500; + case 500: + return 1000; + case 1000: + return 2500; + case 2500: + return 5000; + case 5000: + return 10000; + case 10000: + return 25000; + default: + return 0; + } +} + +/*! + * @brief 自動セーブオプションを変更するコマンドのメインルーチン + * @param info 表示メッセージ + * @return なし + */ +static void do_cmd_options_autosave(player_type *player_ptr, concptr info) +{ + char ch; + int i, k = 0, n = 2; + char buf[80]; + term_clear(); + while (TRUE) { + sprintf(buf, + _("%s ( リターンで次へ, y/n でセット, F で頻度を入力, ESC で決定 ) ", "%s (RET to advance, y/n to set, 'F' for frequency, ESC to accept) "), info); + prt(buf, 0, 0); + for (i = 0; i < n; i++) { + byte a = TERM_WHITE; + if (i == k) + a = TERM_L_BLUE; + + sprintf( + buf, "%-48s: %s (%s)", autosave_info[i].o_desc, (*autosave_info[i].o_var ? _("はい ", "yes") : _("いいえ", "no ")), autosave_info[i].o_text); + c_prt(a, buf, i + 2, 0); + } + + prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"), autosave_freq), 5, 0); + move_cursor(k + 2, 50); + ch = inkey(); + switch (ch) { + case ESCAPE: { + return; + } + + case '-': + case '8': { + k = (n + k - 1) % n; + break; + } + + case ' ': + case '\n': + case '\r': + case '2': { + k = (k + 1) % n; + break; + } + + case 'y': + case 'Y': + case '6': { + + (*autosave_info[k].o_var) = TRUE; + k = (k + 1) % n; + break; + } + + case 'n': + case 'N': + case '4': { + (*autosave_info[k].o_var) = FALSE; + k = (k + 1) % n; + break; + } + + case 'f': + case 'F': { + autosave_freq = toggle_frequency(autosave_freq); + prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"), autosave_freq), 5, 0); + break; + } + + case '?': { + (void)show_file(player_ptr, TRUE, _("joption.txt#Autosave", "option.txt#Autosave"), NULL, 0, 0); + term_clear(); + break; + } + + default: { + bell(); + break; + } + } + } +} + +/*! + * @brief ウィンドウオプションを変更するコマンドのメインルーチン / + * Modify the "window" options + * @return なし + */ +static void do_cmd_options_win(player_type *player_ptr) +{ + int i, j, d; + TERM_LEN y = 0; + TERM_LEN x = 0; + char ch; + bool go = TRUE; + u32b old_flag[8]; + + for (j = 0; j < 8; j++) { + old_flag[j] = window_flag[j]; + } + + term_clear(); + while (go) { + prt(_("ウィンドウ・フラグ (<方向>で移動, tでチェンジ, y/n でセット, ESC)", "Window Flags (, t, y, n, ESC) "), 0, 0); + for (j = 0; j < 8; j++) { + byte a = TERM_WHITE; + concptr s = angband_term_name[j]; + if (j == x) + a = TERM_L_BLUE; + + term_putstr(35 + j * 5 - strlen(s) / 2, 2 + j % 2, -1, a, s); + } + + for (i = 0; i < 16; i++) { + byte a = TERM_WHITE; + concptr str = window_flag_desc[i]; + if (i == y) + a = TERM_L_BLUE; + + if (!str) + str = _("(未使用)", "(Unused option)"); + + term_putstr(0, i + 5, -1, a, str); + for (j = 0; j < 8; j++) { + char c = '.'; + a = TERM_WHITE; + if ((i == y) && (j == x)) + a = TERM_L_BLUE; + + if (window_flag[j] & (1L << i)) + c = 'X'; + + term_putch(35 + j * 5, i + 5, a, c); + } + } + + term_gotoxy(35 + x * 5, y + 5); + ch = inkey(); + switch (ch) { + case ESCAPE: { + go = FALSE; + break; + } + case 'T': + case 't': { + for (j = 0; j < 8; j++) { + window_flag[j] &= ~(1L << y); + } + + for (i = 0; i < 16; i++) { + window_flag[x] &= ~(1L << i); + } + } + /* Fall through */ + case 'y': + case 'Y': { + if (x == 0) + break; + + window_flag[x] |= (1L << y); + break; + } + case 'n': + case 'N': { + window_flag[x] &= ~(1L << y); + break; + } + case '?': { + (void)show_file(player_ptr, TRUE, _("joption.txt#Window", "option.txt#Window"), NULL, 0, 0); + term_clear(); + break; + } + default: { + d = get_keymap_dir(ch); + x = (x + ddx[d] + 8) % 8; + y = (y + ddy[d] + 16) % 16; + if (!d) + bell(); + } + } + } + + for (j = 0; j < 8; j++) { + term_type *old = Term; + if (!angband_term[j]) + continue; + + if (window_flag[j] == old_flag[j]) + continue; + + term_activate(angband_term[j]); + term_clear(); + term_fresh(); + term_activate(old); + } +} + +/*! + * @brief チートオプションを変更するコマンドのメインルーチン + * Interact with some options for cheating + * @param info 表示メッセージ + * @return なし + */ +static void do_cmd_options_cheat(player_type *player_ptr, concptr info) +{ + char ch; + int i, k = 0, n = MAX_CHEAT_OPTIONS; + char buf[80]; + term_clear(); + while (TRUE) { + DIRECTION dir; + sprintf(buf, _("%s ( リターンで次へ, y/n でセット, ESC で決定 )", "%s (RET to advance, y/n to set, ESC to accept) "), info); + prt(buf, 0, 0); + +#ifdef JP + /* 詐欺オプションをうっかりいじってしまう人がいるようなので注意 */ + prt(" << 注意 >>", 11, 0); + prt(" 詐欺オプションを一度でも設定すると、スコア記録が残らなくなります!", 12, 0); + prt(" 後に解除してもダメですので、勝利者を目指す方はここのオプションはい", 13, 0); + prt(" じらないようにして下さい。", 14, 0); +#endif + for (i = 0; i < n; i++) { + byte a = TERM_WHITE; + if (i == k) + a = TERM_L_BLUE; + + sprintf(buf, "%-48s: %s (%s)", cheat_info[i].o_desc, (*cheat_info[i].o_var ? _("はい ", "yes") : _("いいえ", "no ")), cheat_info[i].o_text); + c_prt(a, buf, i + 2, 0); + } + + move_cursor(k + 2, 50); + ch = inkey(); + dir = get_keymap_dir(ch); + if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) + ch = I2D(dir); + + switch (ch) { + case ESCAPE: { + return; + } + case '-': + case '8': { + k = (n + k - 1) % n; + break; + } + case ' ': + case '\n': + case '\r': + case '2': { + k = (k + 1) % n; + break; + } + case 'y': + case 'Y': + case '6': { + if (!current_world_ptr->noscore) + exe_write_diary(player_ptr, DIARY_DESCRIPTION, 0, + _("詐欺オプションをONにして、スコアを残せなくなった。", "gave up sending score to use cheating options.")); + + current_world_ptr->noscore |= (cheat_info[k].o_set * 256 + cheat_info[k].o_bit); + (*cheat_info[k].o_var) = TRUE; + k = (k + 1) % n; + break; + } + case 'n': + case 'N': + case '4': { + (*cheat_info[k].o_var) = FALSE; + k = (k + 1) % n; + break; + } + case '?': { + strnfmt(buf, sizeof(buf), _("joption.txt#%s", "option.txt#%s"), cheat_info[k].o_text); + (void)show_file(player_ptr, TRUE, buf, NULL, 0, 0); + term_clear(); + break; + } + default: { + bell(); + break; + } + } + } +} + +/*! + * @brief ビットセットからゲームオプションを展開する / Extract option variables from bit sets + * @return なし + */ +void extract_option_vars(void) +{ + for (int i = 0; option_info[i].o_desc; i++) { + int os = option_info[i].o_set; + int ob = option_info[i].o_bit; + if (option_info[i].o_var) { + if (option_flag[os] & (1L << ob)) { + (*option_info[i].o_var) = TRUE; + } else { + (*option_info[i].o_var) = FALSE; + } + } + } +} + +/*! + * @brief 標準オプションを変更するコマンドのメインルーチン / + * Set or unset various options. + * @return なし + * @details + *
+ * The user must use the "Ctrl-R" command to "adapt" to changes
+ * in any options which control "visual" aspects of the game.
+ * 
+ */ +void do_cmd_options(player_type *player_ptr) +{ + char k; + int d, skey; + TERM_LEN i, y = 0; + screen_save(); + while (TRUE) { + int n = OPT_NUM; + if (!current_world_ptr->noscore && !allow_debug_opts) + n--; + + term_clear(); + prt(_("[ オプションの設定 ]", "Game options"), 1, 0); + while (TRUE) { + for (i = 0; i < n; i++) { + byte a = TERM_WHITE; + if (i == y) + a = TERM_L_BLUE; + term_putstr(5, option_fields[i].row, -1, a, format("(%c) %s", toupper(option_fields[i].key), option_fields[i].name)); + } + + prt(_("<方向>で移動, Enterで決定, ESCでキャンセル, ?でヘルプ: ", "Move to , Select to Enter, Cancel to ESC, ? to help: "), 21, 0); + skey = inkey_special(TRUE); + if (!(skey & SKEY_MASK)) + k = (char)skey; + else + k = 0; + + if (k == ESCAPE) + break; + + if (angband_strchr("\n\r ", k)) { + k = option_fields[y].key; + break; + } + + for (i = 0; i < n; i++) { + if (tolower(k) == option_fields[i].key) + break; + } + + if (i < n) + break; + + if (k == '?') + break; + + d = 0; + if (skey == SKEY_UP) + d = 8; + if (skey == SKEY_DOWN) + d = 2; + y = (y + ddy[d] + n) % n; + if (!d) + bell(); + } + + if (k == ESCAPE) + break; + + switch (k) { + case '1': { + do_cmd_options_aux(player_ptr, OPT_PAGE_INPUT, _("キー入力オプション", "Input Options")); + break; + } + case '2': { + do_cmd_options_aux(player_ptr, OPT_PAGE_MAPSCREEN, _("マップ画面オプション", "Map Screen Options")); + break; + } + case '3': { + do_cmd_options_aux(player_ptr, OPT_PAGE_TEXT, _("テキスト表示オプション", "Text Display Options")); + break; + } + case '4': { + do_cmd_options_aux(player_ptr, OPT_PAGE_GAMEPLAY, _("ゲームプレイ・オプション", "Game-Play Options")); + break; + } + case '5': { + do_cmd_options_aux(player_ptr, OPT_PAGE_DISTURBANCE, _("行動中止関係のオプション", "Disturbance Options")); + break; + } + case '6': { + do_cmd_options_aux(player_ptr, OPT_PAGE_AUTODESTROY, _("簡易自動破壊オプション", "Easy Auto-Destroyer Options")); + break; + } + case 'R': + case 'r': { + do_cmd_options_aux(player_ptr, OPT_PAGE_PLAYRECORD, _("プレイ記録オプション", "Play-record Options")); + break; + } + case 'B': + case 'b': { + do_cmd_options_aux(player_ptr, OPT_PAGE_BIRTH, + (!current_world_ptr->wizard || !allow_debug_opts) ? _("初期オプション(参照のみ)", "Birth Options(browse only)") + : _("初期オプション((*)はスコアに影響)", "Birth Options((*)s effect score)")); + break; + } + case 'C': { + if (!current_world_ptr->noscore && !allow_debug_opts) { + bell(); + break; + } + + do_cmd_options_cheat(player_ptr, _("詐欺師は決して勝利できない!", "Cheaters never win")); + break; + } + case 'a': + case 'A': { + do_cmd_options_autosave(player_ptr, _("自動セーブ", "Autosave")); + break; + } + case 'W': + case 'w': { + do_cmd_options_win(player_ptr); + player_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER | PW_MESSAGE | PW_OVERHEAD | PW_MONSTER | PW_OBJECT | PW_SNAPSHOT | PW_DUNGEON + | PW_MONSTER_LIST); + break; + } + case 'P': + case 'p': { + do_cmd_edit_autopick(player_ptr); + break; + } + case 'D': + case 'd': { + clear_from(18); + prt(_("コマンド: 基本ウェイト量", "Command: Base Delay Factor"), 19, 0); + while (TRUE) { + int msec = delay_factor * delay_factor * delay_factor; + prt(format(_("現在のウェイト: %d (%dミリ秒)", "Current base delay factor: %d (%d msec)"), delay_factor, msec), 22, 0); + prt(_("ウェイト (0-9) ESCで決定: ", "Delay Factor (0-9 or ESC to accept): "), 20, 0); + k = inkey(); + if (k == ESCAPE) + break; + else if (k == '?') { + (void)show_file(player_ptr, TRUE, _("joption.txt#BaseDelay", "option.txt#BaseDelay"), NULL, 0, 0); + term_clear(); + } else if (isdigit(k)) + delay_factor = D2I(k); + else + bell(); + } + + break; + } + case 'H': + case 'h': { + clear_from(18); + prt(_("コマンド: 低ヒットポイント警告", "Command: Hitpoint Warning"), 19, 0); + while (TRUE) { + prt(format(_("現在の低ヒットポイント警告: %d0%%", "Current hitpoint warning: %d0%%"), hitpoint_warn), 22, 0); + prt(_("低ヒットポイント警告 (0-9) ESCで決定: ", "Hitpoint Warning (0-9 or ESC to accept): "), 20, 0); + k = inkey(); + if (k == ESCAPE) + break; + else if (k == '?') { + (void)show_file(player_ptr, TRUE, _("joption.txt#Hitpoint", "option.txt#Hitpoint"), NULL, 0, 0); + term_clear(); + } else if (isdigit(k)) + hitpoint_warn = D2I(k); + else + bell(); + } + + break; + } + case 'M': + case 'm': { + clear_from(18); + prt(_("コマンド: 低魔力色閾値", "Command: Mana Color Threshold"), 19, 0); + while (TRUE) { + prt(format(_("現在の低魔力色閾値: %d0%%", "Current mana color threshold: %d0%%"), mana_warn), 22, 0); + prt(_("低魔力閾値 (0-9) ESCで決定: ", "Mana color Threshold (0-9 or ESC to accept): "), 20, 0); + k = inkey(); + if (k == ESCAPE) + break; + else if (k == '?') { + (void)show_file(player_ptr, TRUE, _("joption.txt#Manapoint", "option.txt#Manapoint"), NULL, 0, 0); + term_clear(); + } else if (isdigit(k)) + mana_warn = D2I(k); + else + bell(); + } + + break; + } + case '?': + (void)show_file(player_ptr, TRUE, _("joption.txt", "option.txt"), NULL, 0, 0); + term_clear(); + break; + default: { + bell(); + break; + } + } + + msg_erase(); + } + + screen_load(); + player_ptr->redraw |= (PR_EQUIPPY); +} + +/*! + * @brief 標準オプションを変更するコマンドのサブルーチン / + * Interact with some options + * @param page オプションページ番号 + * @param info 表示メッセージ + * @return なし + */ +void do_cmd_options_aux(player_type *player_ptr, int page, concptr info) +{ + char ch; + int i, k = 0, n = 0, l; + int opt[24]; + char buf[80]; + bool browse_only = (page == OPT_PAGE_BIRTH) && current_world_ptr->character_generated && (!current_world_ptr->wizard || !allow_debug_opts); + + for (i = 0; i < 24; i++) + opt[i] = 0; + + for (i = 0; option_info[i].o_desc; i++) { + if (option_info[i].o_page == page) + opt[n++] = i; + } + + term_clear(); + while (TRUE) { + DIRECTION dir; + sprintf(buf, _("%s (リターン:次, %sESC:終了, ?:ヘルプ) ", "%s (RET:next, %s, ?:help) "), info, + browse_only ? _("", "ESC:exit") : _("y/n:変更, ", "y/n:change, ESC:accept")); + prt(buf, 0, 0); + if (page == OPT_PAGE_AUTODESTROY) + c_prt(TERM_YELLOW, _("以下のオプションは、簡易自動破壊を使用するときのみ有効", "Following options will protect items from easy auto-destroyer."), 6, + _(6, 3)); + + for (i = 0; i < n; i++) { + byte a = TERM_WHITE; + if (i == k) + a = TERM_L_BLUE; + + sprintf(buf, "%-48s: %s (%.19s)", option_info[opt[i]].o_desc, (*option_info[opt[i]].o_var ? _("はい ", "yes") : _("いいえ", "no ")), + option_info[opt[i]].o_text); + if ((page == OPT_PAGE_AUTODESTROY) && i > 2) + c_prt(a, buf, i + 5, 0); + else + c_prt(a, buf, i + 2, 0); + } + + if ((page == OPT_PAGE_AUTODESTROY) && (k > 2)) + l = 3; + else + l = 0; + + move_cursor(k + 2 + l, 50); + ch = inkey(); + dir = get_keymap_dir(ch); + if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) + ch = I2D(dir); + + switch (ch) { + case ESCAPE: { + return; + } + case '-': + case '8': { + k = (n + k - 1) % n; + break; + } + case ' ': + case '\n': + case '\r': + case '2': { + k = (k + 1) % n; + break; + } + case 'y': + case 'Y': + case '6': { + if (browse_only) + break; + (*option_info[opt[k]].o_var) = TRUE; + k = (k + 1) % n; + break; + } + case 'n': + case 'N': + case '4': { + if (browse_only) + break; + (*option_info[opt[k]].o_var) = FALSE; + k = (k + 1) % n; + break; + } + case 't': + case 'T': { + if (!browse_only) + (*option_info[opt[k]].o_var) = !(*option_info[opt[k]].o_var); + break; + } + case '?': { + strnfmt(buf, sizeof(buf), _("joption.txt#%s", "option.txt#%s"), option_info[opt[k]].o_text); + (void)show_file(player_ptr, TRUE, buf, NULL, 0, 0); + term_clear(); + break; + } + default: { + bell(); + break; + } + } + } +} diff --git a/src/cmd-io/cmd-gameoption.h b/src/cmd-io/cmd-gameoption.h new file mode 100644 index 000000000..f810537c8 --- /dev/null +++ b/src/cmd-io/cmd-gameoption.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +void extract_option_vars(void); +void do_cmd_options_aux(player_type *player_ptr, int page, concptr info); +void do_cmd_options(player_type *player_ptr); diff --git a/src/cmd-io/cmd-help.c b/src/cmd-io/cmd-help.c new file mode 100644 index 000000000..a6c13bc64 --- /dev/null +++ b/src/cmd-io/cmd-help.c @@ -0,0 +1,17 @@ +#include "cmd-io/cmd-help.h" +#include "core/show-file.h" +#include "term/screen-processor.h" + +/*! + * @brief ヘルプを表示するコマンドのメインルーチン + * Peruse the On-Line-Help + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + * @details + */ +void do_cmd_help(player_type *creature_ptr) +{ + screen_save(); + (void)show_file(creature_ptr, TRUE, _("jhelp.hlp", "help.hlp"), NULL, 0, 0); + screen_load(); +} diff --git a/src/cmd-io/cmd-help.h b/src/cmd-io/cmd-help.h new file mode 100644 index 000000000..44d74a81b --- /dev/null +++ b/src/cmd-io/cmd-help.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_help(player_type *creature_ptr); diff --git a/src/cmd-io/cmd-knowledge.c b/src/cmd-io/cmd-knowledge.c new file mode 100644 index 000000000..84324eb25 --- /dev/null +++ b/src/cmd-io/cmd-knowledge.c @@ -0,0 +1,146 @@ +#include "cmd-io/cmd-knowledge.h" +#include "cmd-visual/cmd-draw.h" +#include "game-option/birth-options.h" +#include "grid/feature.h" +#include "io/input-key-acceptor.h" +#include "knowledge/knowledge-autopick.h" +#include "knowledge/knowledge-experiences.h" +#include "knowledge/knowledge-features.h" +#include "knowledge/knowledge-inventory.h" +#include "knowledge/knowledge-items.h" +#include "knowledge/knowledge-monsters.h" +#include "knowledge/knowledge-mutations.h" +#include "knowledge/knowledge-quests.h" +#include "knowledge/knowledge-self.h" +#include "knowledge/knowledge-uniques.h" +#include "main/sound-of-music.h" +#include "term/screen-processor.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" + +/* + * Interact with "knowledge" + */ +void do_cmd_knowledge(player_type *creature_ptr) +{ + int i, p = 0; + bool need_redraw = FALSE; + screen_save(); + while (TRUE) { + term_clear(); + prt(format(_("%d/2 ページ", "page %d/2"), (p + 1)), 2, 65); + prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0); + if (p == 0) { + prt(_("(1) 既知の伝説のアイテム の一覧", "(1) Display known artifacts"), 6, 5); + prt(_("(2) 既知のアイテム の一覧", "(2) Display known objects"), 7, 5); + prt(_("(3) 既知の生きているユニーク・モンスター の一覧", "(3) Display remaining uniques"), 8, 5); + prt(_("(4) 既知の撃破したユニーク・モンスター の一覧", "(3) Display having defeated uniques"), 9, 5); + prt(_("(5) 既知のモンスター の一覧", "(4) Display known monster"), 10, 5); + prt(_("(6) 倒した敵の数 の一覧", "(5) Display kill count"), 11, 5); + if (!vanilla_town) + prt(_("(7) 賞金首 の一覧", "(6) Display wanted monsters"), 12, 5); + prt(_("(8) 現在のペット の一覧", "(7) Display current pets"), 13, 5); + prt(_("(9) 我が家のアイテム の一覧", "(8) Display home inventory"), 14, 5); + prt(_("(0) *鑑定*済み装備の耐性 の一覧", "(9) Display *identified* equip."), 15, 5); + } else { + prt(_("(a) 地形の表示文字/タイル の一覧", "(0) Display terrain symbols"), 6, 5); + prt(_("(b) 自分に関する情報 の一覧", "(a) Display about yourself"), 7, 5); + prt(_("(c) 突然変異 の一覧", "(b) Display mutations"), 8, 5); + prt(_("(d) 武器の経験値 の一覧", "(c) Display weapon proficiency"), 9, 5); + prt(_("(e) 魔法の経験値 の一覧", "(d) Display spell proficiency"), 10, 5); + prt(_("(f) 技能の経験値 の一覧", "(e) Display misc. proficiency"), 11, 5); + prt(_("(g) プレイヤーの徳 の一覧", "(f) Display virtues"), 12, 5); + prt(_("(h) 入ったダンジョン の一覧", "(g) Display dungeons"), 13, 5); + prt(_("(i) 実行中のクエスト の一覧", "(h) Display current quests"), 14, 5); + prt(_("(k) 現在の自動拾い/破壊設定 の一覧", "(i) Display auto pick/destroy"), 15, 5); + } + + prt(_("-続く-", "-more-"), 17, 8); + prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1); + prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30); + prt(_("コマンド:", "Command: "), 20, 0); + i = inkey(); + + if (i == ESCAPE) + break; + switch (i) { + case ' ': /* Page change */ + case '-': + p = 1 - p; + break; + case '1': /* Artifacts */ + do_cmd_knowledge_artifacts(creature_ptr); + break; + case '2': /* Objects */ + do_cmd_knowledge_objects(creature_ptr, &need_redraw, FALSE, -1); + break; + case '3': /* Uniques */ + do_cmd_knowledge_uniques(creature_ptr, TRUE); + break; + case '4': /* Uniques */ + do_cmd_knowledge_uniques(creature_ptr, FALSE); + break; + case '5': /* Monsters */ + do_cmd_knowledge_monsters(creature_ptr, &need_redraw, FALSE, -1); + break; + case '6': /* Kill count */ + do_cmd_knowledge_kill_count(creature_ptr); + break; + case '7': /* wanted */ + if (!vanilla_town) + do_cmd_knowledge_bounty(creature_ptr); + break; + case '8': /* Pets */ + do_cmd_knowledge_pets(creature_ptr); + break; + case '9': /* Home */ + do_cmd_knowledge_home(creature_ptr); + break; + case '0': /* Resist list */ + do_cmd_knowledge_inventory(creature_ptr); + break; + /* Next page */ + case 'a': /* Feature list */ + { + IDX lighting_level = F_LIT_STANDARD; + do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level); + break; + } + case 'b': /* Max stat */ + do_cmd_knowledge_stat(creature_ptr); + break; + case 'c': /* Mutations */ + do_cmd_knowledge_mutations(creature_ptr); + break; + case 'd': /* weapon-exp */ + do_cmd_knowledge_weapon_exp(creature_ptr); + break; + case 'e': /* spell-exp */ + do_cmd_knowledge_spell_exp(creature_ptr); + break; + case 'f': /* skill-exp */ + do_cmd_knowledge_skill_exp(creature_ptr); + break; + case 'g': /* Virtues */ + do_cmd_knowledge_virtues(creature_ptr); + break; + case 'h': /* Dungeon */ + do_cmd_knowledge_dungeon(creature_ptr); + break; + case 'i': /* Quests */ + do_cmd_knowledge_quests(creature_ptr); + break; + case 'k': /* Autopick */ + do_cmd_knowledge_autopick(creature_ptr); + break; + default: /* Unknown option */ + bell(); + } + + msg_erase(); + } + + screen_load(); + if (need_redraw) + do_cmd_redraw(creature_ptr); +} diff --git a/src/cmd-io/cmd-knowledge.h b/src/cmd-io/cmd-knowledge.h new file mode 100644 index 000000000..389dabbf5 --- /dev/null +++ b/src/cmd-io/cmd-knowledge.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_knowledge(player_type *creature_ptr); diff --git a/src/cmd-io/cmd-lore.c b/src/cmd-io/cmd-lore.c new file mode 100644 index 000000000..ba5b8aa79 --- /dev/null +++ b/src/cmd-io/cmd-lore.c @@ -0,0 +1,208 @@ +#include "cmd-io/cmd-lore.h" +#include "core/asking-player.h" +#include "util/sort.h" +#include "core/stuff-handler.h" +#include "game-option/game-play-options.h" +#include "game-option/cheat-options.h" +#include "io/input-key-acceptor.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags7.h" +#include "term/gameterm.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/int-char-converter.h" +#include "util/string-processor.h" +#include "view/display-lore.h" + +/*! + * @brief モンスターの思い出を見るコマンドのメインルーチン + * Identify a character, allow recall of monsters + * @param player_ptr プレーヤーへの参照ポインタ + * @return なし + * @details + *
+ * Several "special" responses recall "multiple" monsters:
+ *   ^A (all monsters)
+ *   ^U (all unique monsters)
+ *   ^N (all non-unique monsters)
+ *
+ * The responses may be sorted in several ways, see below.
+ *
+ * Note that the player ghosts are ignored.
+ * 
+ */ +void do_cmd_query_symbol(player_type *creature_ptr) +{ + IDX i; + int n; + MONRACE_IDX r_idx; + char sym, query; + char buf[128]; + + bool all = FALSE; + bool uniq = FALSE; + bool norm = FALSE; + bool ride = FALSE; + char temp[80] = ""; + + bool recall = FALSE; + + u16b why = 0; + MONRACE_IDX *who; + + if (!get_com(_("知りたい文字を入力して下さい(記号 or ^A全,^Uユ,^N非ユ,^R乗馬,^M名前): ", + "Enter character to be identified(^A:All,^U:Uniqs,^N:Non uniqs,^M:Name): "), + &sym, FALSE)) + return; + + for (i = 0; ident_info[i]; ++i) { + if (sym == ident_info[i][0]) + break; + } + + if (sym == KTRL('A')) { + all = TRUE; + strcpy(buf, _("全モンスターのリスト", "Full monster list.")); + } else if (sym == KTRL('U')) { + all = uniq = TRUE; + strcpy(buf, _("ユニーク・モンスターのリスト", "Unique monster list.")); + } else if (sym == KTRL('N')) { + all = norm = TRUE; + strcpy(buf, _("ユニーク外モンスターのリスト", "Non-unique monster list.")); + } else if (sym == KTRL('R')) { + all = ride = TRUE; + strcpy(buf, _("乗馬可能モンスターのリスト", "Ridable monster list.")); + } else if (sym == KTRL('M')) { + all = TRUE; + if (!get_string(_("名前(英語の場合小文字で可)", "Enter name:"), temp, 70)) { + temp[0] = 0; + return; + } + sprintf(buf, _("名前:%sにマッチ", "Monsters with a name \"%s\""), temp); + } else if (ident_info[i]) { + sprintf(buf, "%c - %s.", sym, ident_info[i] + 2); + } else { + sprintf(buf, "%c - %s", sym, _("無効な文字", "Unknown Symbol")); + } + + prt(buf, 0, 0); + C_MAKE(who, max_r_idx, MONRACE_IDX); + for (n = 0, i = 1; i < max_r_idx; i++) { + monster_race *r_ptr = &r_info[i]; + if (!cheat_know && !r_ptr->r_sights) + continue; + + if (norm && (r_ptr->flags1 & (RF1_UNIQUE))) + continue; + + if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) + continue; + + if (ride && !(r_ptr->flags7 & (RF7_RIDING))) + continue; + + if (temp[0]) { + TERM_LEN xx; + char temp2[80]; + + for (xx = 0; temp[xx] && xx < 80; xx++) { +#ifdef JP + if (iskanji(temp[xx])) { + xx++; + continue; + } +#endif + if (isupper(temp[xx])) + temp[xx] = (char)tolower(temp[xx]); + } + +#ifdef JP + strcpy(temp2, r_name + r_ptr->E_name); +#else + strcpy(temp2, r_name + r_ptr->name); +#endif + for (xx = 0; temp2[xx] && xx < 80; xx++) + if (isupper(temp2[xx])) + temp2[xx] = (char)tolower(temp2[xx]); + +#ifdef JP + if (angband_strstr(temp2, temp) || angband_strstr(r_name + r_ptr->name, temp)) +#else + if (angband_strstr(temp2, temp)) +#endif + who[n++] = i; + } + + else if (all || (r_ptr->d_char == sym)) + who[n++] = i; + } + + if (!n) { + C_KILL(who, max_r_idx, MONRACE_IDX); + return; + } + + put_str(_("思い出を見ますか? (k:殺害順/y/n): ", "Recall details? (k/y/n): "), 0, _(36, 40)); + query = inkey(); + prt(buf, 0, 0); + why = 2; + ang_sort(creature_ptr, who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook); + if (query == 'k') { + why = 4; + query = 'y'; + } + + if (query != 'y') { + C_KILL(who, max_r_idx, MONRACE_IDX); + return; + } + + if (why == 4) { + ang_sort(creature_ptr, who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook); + } + + i = n - 1; + while (TRUE) { + r_idx = who[i]; + monster_race_track(creature_ptr, r_idx); + handle_stuff(creature_ptr); + while (TRUE) { + if (recall) { + screen_save(); + screen_roff(creature_ptr, who[i], 0); + } + + roff_top(r_idx); + term_addstr(-1, TERM_WHITE, _(" ['r'思い出, ESC]", " [(r)ecall, ESC]")); + query = inkey(); + if (recall) { + screen_load(); + } + + if (query != 'r') + break; + recall = !recall; + } + + if (query == ESCAPE) + break; + + if (query == '-') { + if (++i == n) { + i = 0; + if (!expand_list) + break; + } + } else { + if (i-- == 0) { + i = n - 1; + if (!expand_list) + break; + } + } + } + + C_KILL(who, max_r_idx, IDX); + prt(buf, 0, 0); +} diff --git a/src/cmd-io/cmd-lore.h b/src/cmd-io/cmd-lore.h new file mode 100644 index 000000000..4a5e2aaa8 --- /dev/null +++ b/src/cmd-io/cmd-lore.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_query_symbol(player_type *creature_ptr); diff --git a/src/cmd-io/cmd-macro.c b/src/cmd-io/cmd-macro.c new file mode 100644 index 000000000..f573ea660 --- /dev/null +++ b/src/cmd-io/cmd-macro.c @@ -0,0 +1,333 @@ +#include "cmd-io/cmd-macro.h" +#include "cmd-io/cmd-gameoption.h" +#include "cmd-io/macro-util.h" +#include "core/asking-player.h" +#include "game-option/input-options.h" +#include "io/files-util.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "io/read-pref-file.h" +#include "main/sound-of-music.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/angband-files.h" +#include "util/int-char-converter.h" +#include "util/string-processor.h" +#include "view/display-messages.h" + +/*! + * @brief マクロ情報をprefファイルに保存する / + * @param fname ファイル名 + * @return なし + */ +static void macro_dump(FILE **fpp, concptr fname) +{ + static concptr mark = "Macro Dump"; + char buf[1024]; + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); + if (!open_auto_dump(fpp, buf, mark)) return; + + auto_dump_printf(*fpp, _("\n# 自動マクロセーブ\n\n", "\n# Automatic macro dump\n\n")); + + for (int i = 0; i < macro__num; i++) + { + ascii_to_text(buf, macro__act[i]); + auto_dump_printf(*fpp, "A:%s\n", buf); + ascii_to_text(buf, macro__pat[i]); + auto_dump_printf(*fpp, "P:%s\n", buf); + auto_dump_printf(*fpp, "\n"); + } + + close_auto_dump(fpp, mark); +} + + +/*! + * @brief マクロのトリガーキーを取得する / + * Hack -- ask for a "trigger" (see below) + * @param buf キー表記を保管するバッファ + * @return なし + * @details + *
+ * Note the complex use of the "inkey()" function from "util.c".
+ *
+ * Note that both "flush()" calls are extremely important.
+ * 
+ */ +static void do_cmd_macro_aux(char *buf) +{ + flush(); + inkey_base = TRUE; + char i = inkey(); + int n = 0; + while (i) + { + buf[n++] = i; + inkey_base = TRUE; + inkey_scan = TRUE; + i = inkey(); + } + + buf[n] = '\0'; + flush(); + char tmp[1024]; + ascii_to_text(tmp, buf); + term_addstr(-1, TERM_WHITE, tmp); +} + + +/*! + * @brief マクロのキー表記からアスキーコードを得てターミナルに表示する / + * Hack -- ask for a keymap "trigger" (see below) + * @param buf キー表記を取得するバッファ + * @return なし + * @details + *
+ * Note that both "flush()" calls are extremely important.  This may
+ * no longer be true, since "util.c" is much simpler now.
+ * 
+ */ +static void do_cmd_macro_aux_keymap(char *buf) +{ + char tmp[1024]; + flush(); + buf[0] = inkey(); + buf[1] = '\0'; + ascii_to_text(tmp, buf); + term_addstr(-1, TERM_WHITE, tmp); + flush(); +} + + +/*! + * @brief キーマップをprefファイルにダンプする / + * Hack -- append all keymaps to the given file + * @param fname ファイルネーム + * @return エラーコード + * @details + */ +static errr keymap_dump(concptr fname) +{ + FILE *auto_dump_stream; + static concptr mark = "Keymap Dump"; + char key[1024]; + char buf[1024]; + BIT_FLAGS mode; + if (rogue_like_commands) + { + mode = KEYMAP_MODE_ROGUE; + } + else + { + mode = KEYMAP_MODE_ORIG; + } + + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); + if (!open_auto_dump(&auto_dump_stream, buf, mark)) return -1; + + auto_dump_printf(auto_dump_stream, _("\n# 自動キー配置セーブ\n\n", "\n# Automatic keymap dump\n\n")); + for (int i = 0; i < 256; i++) + { + concptr act; + act = keymap_act[mode][i]; + if (!act) continue; + + buf[0] = (char)i; + buf[1] = '\0'; + ascii_to_text(key, buf); + ascii_to_text(buf, act); + auto_dump_printf(auto_dump_stream, "A:%s\n", buf); + auto_dump_printf(auto_dump_stream, "C:%d:%s\n", mode, key); + } + + close_auto_dump(&auto_dump_stream, mark); + return 0; +} + + +/*! + * @brief マクロを設定するコマンドのメインルーチン / + * Interact with "macros" + * @return なし + * @details + *
+ * Note that the macro "action" must be defined before the trigger.
+ *
+ * Could use some helpful instructions on this page.
+ * 
+ */ +void do_cmd_macros(player_type *creature_ptr, void(*process_autopick_file_command)(char*)) +{ + char tmp[1024]; + char buf[1024]; + FILE *auto_dump_stream; + BIT_FLAGS mode = rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG; + screen_save(); + while (TRUE) + { + term_clear(); + prt(_("[ マクロの設定 ]", "Interact with Macros"), 2, 0); + prt(_("マクロ行動が(もしあれば)下に表示されます:", "Current action (if any) shown below:"), 20, 0); + ascii_to_text(buf, macro__buf); + prt(buf, 22, 0); + + prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5); + prt(_("(2) ファイルにマクロを追加", "(2) Append macros to a file"), 5, 5); + prt(_("(3) マクロの確認", "(3) Query a macro"), 6, 5); + prt(_("(4) マクロの作成", "(4) Create a macro"), 7, 5); + prt(_("(5) マクロの削除", "(5) Remove a macro"), 8, 5); + prt(_("(6) ファイルにキー配置を追加", "(6) Append keymaps to a file"), 9, 5); + prt(_("(7) キー配置の確認", "(7) Query a keymap"), 10, 5); + prt(_("(8) キー配置の作成", "(8) Create a keymap"), 11, 5); + prt(_("(9) キー配置の削除", "(9) Remove a keymap"), 12, 5); + prt(_("(0) マクロ行動の入力", "(0) Enter a new action"), 13, 5); + + prt(_("コマンド: ", "Command: "), 16, 0); + int i = inkey(); + if (i == ESCAPE) break; + + else if (i == '1') + { + prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 16, 0); + prt(_("ファイル: ", "File: "), 18, 0); + sprintf(tmp, "%s.prf", creature_ptr->base_name); + if (!askfor(tmp, 80)) continue; + + errr err = process_pref_file(creature_ptr, tmp, process_autopick_file_command); + if (-2 == err) + msg_format(_("標準の設定ファイル'%s'を読み込みました。", "Loaded default '%s'."), tmp); + else if (err) + msg_format(_("'%s'の読み込みに失敗しました!", "Failed to load '%s'!"), tmp); + else + msg_format(_("'%s'を読み込みました。", "Loaded '%s'."), tmp); + } + else if (i == '2') + { + prt(_("コマンド: マクロをファイルに追加する", "Command: Append macros to a file"), 16, 0); + prt(_("ファイル: ", "File: "), 18, 0); + sprintf(tmp, "%s.prf", creature_ptr->base_name); + if (!askfor(tmp, 80)) continue; + + macro_dump(&auto_dump_stream, tmp); + msg_print(_("マクロを追加しました。", "Appended macros.")); + } + else if (i == '3') + { + prt(_("コマンド: マクロの確認", "Command: Query a macro"), 16, 0); + prt(_("トリガーキー: ", "Trigger: "), 18, 0); + do_cmd_macro_aux(buf); + int k = macro_find_exact(buf); + if (k < 0) + { + msg_print(_("そのキーにはマクロは定義されていません。", "Found no macro.")); + } + else + { + strcpy(macro__buf, macro__act[k]); + ascii_to_text(buf, macro__buf); + prt(buf, 22, 0); + msg_print(_("マクロを確認しました。", "Found a macro.")); + } + } + else if (i == '4') + { + prt(_("コマンド: マクロの作成", "Command: Create a macro"), 16, 0); + prt(_("トリガーキー: ", "Trigger: "), 18, 0); + do_cmd_macro_aux(buf); + clear_from(20); + c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。", + "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0); + prt(_("マクロ行動: ", "Action: "), 20, 0); + ascii_to_text(tmp, macro__buf); + if (askfor(tmp, 80)) + { + text_to_ascii(macro__buf, tmp); + macro_add(buf, macro__buf); + msg_print(_("マクロを追加しました。", "Added a macro.")); + } + } + else if (i == '5') + { + prt(_("コマンド: マクロの削除", "Command: Remove a macro"), 16, 0); + prt(_("トリガーキー: ", "Trigger: "), 18, 0); + do_cmd_macro_aux(buf); + macro_add(buf, buf); + msg_print(_("マクロを削除しました。", "Removed a macro.")); + } + else if (i == '6') + { + prt(_("コマンド: キー配置をファイルに追加する", "Command: Append keymaps to a file"), 16, 0); + prt(_("ファイル: ", "File: "), 18, 0); + sprintf(tmp, "%s.prf", creature_ptr->base_name); + if (!askfor(tmp, 80)) continue; + + (void)keymap_dump(tmp); + msg_print(_("キー配置を追加しました。", "Appended keymaps.")); + } + else if (i == '7') + { + prt(_("コマンド: キー配置の確認", "Command: Query a keymap"), 16, 0); + prt(_("押すキー: ", "Keypress: "), 18, 0); + do_cmd_macro_aux_keymap(buf); + concptr act = keymap_act[mode][(byte)(buf[0])]; + if (!act) + { + msg_print(_("キー配置は定義されていません。", "Found no keymap.")); + } + else + { + strcpy(macro__buf, act); + ascii_to_text(buf, macro__buf); + prt(buf, 22, 0); + msg_print(_("キー配置を確認しました。", "Found a keymap.")); + } + } + else if (i == '8') + { + prt(_("コマンド: キー配置の作成", "Command: Create a keymap"), 16, 0); + prt(_("押すキー: ", "Keypress: "), 18, 0); + do_cmd_macro_aux_keymap(buf); + clear_from(20); + c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。", + "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0); + prt(_("行動: ", "Action: "), 20, 0); + ascii_to_text(tmp, macro__buf); + if (askfor(tmp, 80)) + { + text_to_ascii(macro__buf, tmp); + string_free(keymap_act[mode][(byte)(buf[0])]); + keymap_act[mode][(byte)(buf[0])] = string_make(macro__buf); + msg_print(_("キー配置を追加しました。", "Added a keymap.")); + } + } + else if (i == '9') + { + prt(_("コマンド: キー配置の削除", "Command: Remove a keymap"), 16, 0); + prt(_("押すキー: ", "Keypress: "), 18, 0); + do_cmd_macro_aux_keymap(buf); + string_free(keymap_act[mode][(byte)(buf[0])]); + keymap_act[mode][(byte)(buf[0])] = NULL; + msg_print(_("キー配置を削除しました。", "Removed a keymap.")); + } + else if (i == '0') + { + prt(_("コマンド: マクロ行動の入力", "Command: Enter a new action"), 16, 0); + clear_from(20); + c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。", + "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0); + prt(_("マクロ行動: ", "Action: "), 20, 0); + tmp[80] = '\0'; + if (!askfor(buf, 80)) continue; + + text_to_ascii(macro__buf, buf); + } + else + { + bell(); + } + + msg_erase(); + } + + screen_load(); +} diff --git a/src/cmd-io/cmd-macro.h b/src/cmd-io/cmd-macro.h new file mode 100644 index 000000000..02b100d96 --- /dev/null +++ b/src/cmd-io/cmd-macro.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_macros(player_type *creature_ptr, void (*process_autopick_file_command)(char *)); diff --git a/src/cmd-io/cmd-menu-content-table.c b/src/cmd-io/cmd-menu-content-table.c new file mode 100644 index 000000000..dfdf05c01 --- /dev/null +++ b/src/cmd-io/cmd-menu-content-table.c @@ -0,0 +1,131 @@ +#include "cmd-io/cmd-menu-content-table.h" +#include "util/int-char-converter.h" + +special_menu_content special_menu_info[MAX_SPECIAL_MENU_NUM] = { + { _("超能力/特殊能力", "MindCraft/Special"), 0, 0, MENU_CLASS, CLASS_MINDCRAFTER }, + { _("ものまね/特殊能力", "Imitation/Special"), 0, 0, MENU_CLASS, CLASS_IMITATOR }, + { _("歌/特殊能力", "Song/Special"), 0, 0, MENU_CLASS, CLASS_BARD }, + { _("必殺技/特殊能力", "Technique/Special"), 0, 0, MENU_CLASS, CLASS_SAMURAI }, + { _("練気術/魔法/特殊能力", "Mind/Magic/Special"), 0, 0, MENU_CLASS, CLASS_FORCETRAINER }, + { _("技/特殊能力", "BrutalPower/Special"), 0, 0, MENU_CLASS, CLASS_BERSERKER }, + { _("技術/特殊能力", "Technique/Special"), 0, 0, MENU_CLASS, CLASS_SMITH }, + { _("鏡魔法/特殊能力", "MirrorMagic/Special"), 0, 0, MENU_CLASS, CLASS_MIRROR_MASTER }, + { _("忍術/特殊能力", "Ninjutsu/Special"), 0, 0, MENU_CLASS, CLASS_NINJA }, + { _("広域マップ(<)", "Enter global map(<)"), 2, 6, MENU_WILD, FALSE }, + { _("通常マップ(>)", "Enter local map(>)"), 2, 7, MENU_WILD, TRUE }, + { "", 0, 0, 0, 0 }, +}; + +menu_content menu_info[MAX_COMMAND_MENU_NUM][MAX_COMMAND_PER_SCREEN] = { + { + { _("魔法/特殊能力", "Magic/Special"), 1, FALSE }, + { _("行動", "Action"), 2, FALSE }, + { _("道具(使用)", "Items(use)"), 3, FALSE }, + { _("道具(その他)", "Items(other)"), 4, FALSE }, + { _("装備", "Equip"), 5, FALSE }, + { _("扉/箱", "Door/Box"), 6, FALSE }, + { _("情報", "Information"), 7, FALSE }, + { _("設定", "Options"), 8, FALSE }, + { _("その他", "Other commands"), 9, FALSE }, + { "", 0, FALSE }, + }, + + { { _("使う(m)", "Use(m)"), 'm', TRUE }, + { _("調べる(b/P)", "See tips(b/P)"), 'b', TRUE }, + { _("覚える(G)", "Study(G)"), 'G', TRUE }, + { _("特殊能力を使う(U/O)", "Special abilities(U/O)"), 'U', TRUE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE } }, + + { { _("休息する(R)", "Rest(R)"), 'R', TRUE }, + { _("トラップ解除(D)", "Disarm a trap(D)"), 'D', TRUE }, + { _("探す(s)", "Search(s)"), 's', TRUE }, + { _("周りを調べる(l/x)", "Look(l/x)"), 'l', TRUE }, + { _("ターゲット指定(*)", "Target(*)"), '*', TRUE }, + { _("穴を掘る(T/^t)", "Dig(T/^t)"), 'T', TRUE }, + { _("階段を上る(<)", "Go up stairs(<)"), '<', TRUE }, + { _("階段を下りる(>)", "Go down stairs(>)"), '>', TRUE }, + { _("ペットに命令する(p)", "Command pets(p)"), 'p', TRUE }, + { _("探索モードのON/OFF(S/#)", "Search mode ON/OFF(S/#)"), 'S', TRUE } }, + + { { _("読む(r)", "Read a scroll(r)"), 'r', TRUE }, + { _("飲む(q)", "Drink a potion(q)"), 'q', TRUE }, + { _("杖を使う(u/Z)", "Use a staff(u/Z)"), 'u', TRUE }, + { _("魔法棒で狙う(a/z)", "Aim a wand(a/z)"), 'a', TRUE }, + { _("ロッドを振る(z/a)", "Zap a rod(z/a)"), 'z', TRUE }, + { _("始動する(A)", "Activate an equipment(A)"), 'A', TRUE }, + { _("食べる(E)", "Eat(E)"), 'E', TRUE }, + { _("飛び道具で撃つ(f/t)", "Fire missile weapon(f/t)"), 'f', TRUE }, + { _("投げる(v)", "Throw an item(v)"), 'v', TRUE }, + { "", 0, FALSE } }, + + { { _("拾う(g)", "Get items(g)"), 'g', TRUE }, + { _("落とす(d)", "Drop an item(d)"), 'd', TRUE }, + { _("壊す(k/^d)", "Destroy an item(k/^d)"), 'k', TRUE }, + { _("銘を刻む({)", "Inscribe an item({)"), '{', TRUE }, + { _("銘を消す(})", "Uninscribe an item(})"), '}', TRUE }, + { _("調査(I)", "Uninscribe an item(})"), 'I', TRUE }, + { _("アイテム一覧(i)", "Inventory list(i)"), 'i', TRUE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE } }, + + { { _("装備する(w)", "Wear(w)"), 'w', TRUE }, + { _("装備を外す(t/T)", "Take off(t/T)"), 't', TRUE }, + { _("燃料を補給(F)", "Refuel(F)"), 'F', TRUE }, + { _("装備一覧(e)", "Equipment list(e)"), 'e', TRUE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE } }, + + { { _("開ける(o)", "Open(o)"), 'o', TRUE }, + { _("閉じる(c)", "Close(c)"), 'c', TRUE }, + { _("体当たりする(B/f)", "Bash a door(B/f)"), 'B', TRUE }, + { _("くさびを打つ(j/S)", "Jam a door(j/S)"), 'j', TRUE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE } }, + + { { _("ダンジョンの全体図(M)", "Full map(M)"), 'M', TRUE }, + { _("位置を確認(L/W)", "Map(L/W)"), 'L', TRUE }, + { _("階の雰囲気(^f)", "Level feeling(^f)"), KTRL('F'), TRUE }, + { _("ステータス(C)", "Character status(C)"), 'C', TRUE }, + { _("文字の説明(/)", "Identify symbol(/)"), '/', TRUE }, + { _("メッセージ履歴(^p)", "Show prev messages(^p)"), KTRL('P'), TRUE }, + { _("現在の時刻(^t/')", "Current time(^t/')"), KTRL('T'), TRUE }, + { _("現在の知識(~)", "Various information(~)"), '~', TRUE }, + { _("プレイ記録(|)", "Play record menu(|)"), '|', TRUE }, + { "", 0, FALSE } }, + + { { _("オプション(=)", "Set options(=)"), '=', TRUE }, + { _("マクロ(@)", "Interact with macros(@)"), '@', TRUE }, + { _("画面表示(%)", "Interact w/ visuals(%)"), '%', TRUE }, + { _("カラー(&)", "Interact with colors(&)"), '&', TRUE }, + { _("設定変更コマンド(\")", "Enter a user pref(\")"), '\"', TRUE }, + { _("自動拾いをロード($)", "Reload auto-pick pref($)"), '$', TRUE }, + { _("システム(!)", "System(!)"), '!', TRUE }, + { "", 0, FALSE }, + { "", 0, FALSE }, + { "", 0, FALSE } }, + + { { _("セーブ&中断(^x)", "Save and quit(^x)"), KTRL('X'), TRUE }, + { _("セーブ(^s)", "Save(^s)"), KTRL('S'), TRUE }, + { _("ヘルプ(?)", "Help(obsoleted)(?)"), '?', TRUE }, + { _("再描画(^r)", "Redraw(^r)"), KTRL('R'), TRUE }, + { _("メモ(:)", "Take note(:)"), ':', TRUE }, + { _("記念撮影())", "Dump screen dump(()"), ')', TRUE }, + { _("記念撮影の表示(()", "Load screen dump())"), '(', TRUE }, + { _("バージョン情報(V)", "Version info(V)"), 'V', TRUE }, + { _("引退する(Q)", "Quit(Q)"), 'Q', TRUE }, + { "", 0, FALSE } }, +}; diff --git a/src/cmd-io/cmd-menu-content-table.h b/src/cmd-io/cmd-menu-content-table.h new file mode 100644 index 000000000..e0811ae5d --- /dev/null +++ b/src/cmd-io/cmd-menu-content-table.h @@ -0,0 +1,27 @@ +#pragma once + +#include "system/angband.h" + +typedef struct menu_content { + concptr name; + byte cmd; + bool fin; +} menu_content; + +typedef struct special_menu_content { + concptr name; + byte window; + byte number; + byte jouken; + byte jouken_naiyou; +} special_menu_content; + +#define MAX_COMMAND_PER_SCREEN 10 +#define MAX_COMMAND_MENU_NUM 10 + +#define MENU_CLASS 1 +#define MENU_WILD 2 +#define MAX_SPECIAL_MENU_NUM 12 + +extern menu_content menu_info[MAX_COMMAND_MENU_NUM][MAX_COMMAND_PER_SCREEN]; +extern special_menu_content special_menu_info[MAX_SPECIAL_MENU_NUM]; diff --git a/src/cmd-io/cmd-process-screen.c b/src/cmd-io/cmd-process-screen.c new file mode 100644 index 000000000..3d9de31f0 --- /dev/null +++ b/src/cmd-io/cmd-process-screen.c @@ -0,0 +1,486 @@ +/*! + * @brief 記念撮影のセーブとロード + * @date 2020/04/22 + * @Author Hourier + */ + +#include "cmd-io/cmd-process-screen.h" +#include "cmd-visual/cmd-draw.h" +#include "core/asking-player.h" +#include "core/player-redraw-types.h" +#include "core/stuff-handler.h" +#include "core/visuals-reseter.h" +#include "game-option/special-options.h" +#include "io/files-util.h" +#include "io/input-key-acceptor.h" +#include "term/gameterm.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/angband-files.h" +#include "view/display-messages.h" + +// Encode the screen colors +static char hack[17] = "dwsorgbuDWvyRGBU"; + +static concptr tags[4] = { "HEADER_START:", "HEADER_END:", "FOOTER_START:", "FOOTER_END:", }; +static concptr html_head[3] = { "\n\n", "
", 0, };
+static concptr html_foot[3] = { "
\n", "\n\n", 0, }; + +/*! + * todo io/ 以下に移したいところだが、このファイルの行数も大したことがないので一旦保留 + * @brief 一時ファイルを読み込み、ファイルに書き出す + * @param fff ファイルへの参照ポインタ + * @param tempfff 一時ファイルへの参照ポインタ + * @param buf バッファ + * @param buf_size バッファサイズ + * @param num_tag タグ番号 + */ +static void read_temporary_file(FILE *fff, FILE *tmpfff, char buf[], size_t buf_size, int num_tag) +{ + bool is_first_line = TRUE; + int next_tag = num_tag + 1; + while (!angband_fgets(tmpfff, buf, buf_size)) + { + if (is_first_line) + { + if (strncmp(buf, tags[num_tag], strlen(tags[num_tag])) == 0) + is_first_line = FALSE; + + continue; + } + + if (strncmp(buf, tags[next_tag], strlen(tags[next_tag])) == 0) + break; + + fprintf(fff, "%s\n", buf); + } +} + + +/*! + * @brief 記念撮影を1行ダンプする + * @param wid 幅 + * @param y 現在の行位置 + * @param fff 記念撮影ファイルへの参照ポインタ + * @return なし + */ +static void screen_dump_one_line(int wid, int y, FILE *fff) +{ + TERM_COLOR a = 0, old_a = 0; + char c = ' '; + for (TERM_LEN x = 0; x < wid - 1; x++) + { + concptr cc = NULL; + (void)(term_what(x, y, &a, &c)); + switch (c) + { + case '&': cc = "&"; break; + case '<': cc = "<"; break; + case '>': cc = ">"; break; +#ifdef WINDOWS + case 0x1f: c = '.'; break; + case 0x7f: c = (a == 0x09) ? '%' : '#'; break; +#endif + } + + a = a & 0x0F; + if ((y == 0 && x == 0) || a != old_a) + { + int rv = angband_color_table[a][1]; + int gv = angband_color_table[a][2]; + int bv = angband_color_table[a][3]; + fprintf(fff, "%s", + ((y == 0 && x == 0) ? "" : ""), rv, gv, bv); + old_a = a; + } + + if (cc) + fprintf(fff, "%s", cc); + else + fprintf(fff, "%c", c); + } +} + + +/*! + * @brief 記念撮影を行方向にスイープする + * @param wid 幅 + * @param hgt 高さ + * @param fff 記念撮影ファイルへの参照ポインタ + * @return なし + */ +static void screen_dump_lines(int wid, int hgt, FILE *fff) +{ + for (TERM_LEN y = 0; y < hgt; y++) + { + if (y != 0) + fprintf(fff, "\n"); + + screen_dump_one_line(wid, y, fff); + } +} + + +/*! + * @brief ファイルへ書き込めない場合にエラーを表示する + * @param fff ダンプファイルへの参照ポインタ + * @param buf バッファ + * @return ファイルへ書き込めるならTRUE、書き込めないならFALSE + */ +static bool check_screen_html_can_open(FILE *fff, char *filename, int message) +{ + if (fff) return TRUE; + if (message == 0) return FALSE; + + msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename); + msg_print(NULL); + return FALSE; +} + + +/*! + * @brief HTMLヘッダを書き込む + * @param tmpfff 一時ファイルへの参照ポインタ + * @param fff 記念撮影ファイルへの参照ポインタ + * @param buf バッファ + * @param buf_size バッファサイズ + */ +static void write_html_header(FILE *tmpfff, FILE *fff, char buf[], size_t buf_size) +{ + if (tmpfff) + { + read_temporary_file(fff, tmpfff, buf, buf_size, 0); + return; + } + + for (int i = 0; html_head[i]; i++) + fputs(html_head[i], fff); +} + + +/*! + * @brief HTMLフッタを書き込む + * @param tmpfff 一時ファイルへの参照ポインタ + * @param fff 記念撮影ファイルへの参照ポインタ + * @param buf バッファ + * @param buf_size バッファサイズ + */ +static void write_html_footer(FILE *tmpfff, FILE *fff, char buf[], size_t buf_size) +{ + fprintf(fff, ""); + if (!tmpfff) + { + for (int i = 0; html_foot[i]; i++) + fputs(html_foot[i], fff); + } + else + { + rewind(tmpfff); + read_temporary_file(fff, tmpfff, buf, buf_size, 2); + angband_fclose(tmpfff); + } + + fprintf(fff, "\n"); +} + + +void do_cmd_save_screen_html_aux(char *filename, int message) +{ + TERM_LEN wid, hgt; + term_get_size(&wid, &hgt); + FILE *fff; + fff = angband_fopen(filename, "w"); + if (!check_screen_html_can_open(fff, filename, message)) return; + + if (message) screen_save(); + + char buf[2048]; + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf"); + FILE *tmpfff; + tmpfff = angband_fopen(buf, "r"); + write_html_header(tmpfff, fff, buf, sizeof(buf)); + screen_dump_lines(wid, hgt, fff); + write_html_footer(tmpfff, fff, buf, sizeof(buf)); + angband_fclose(fff); + if (message) + { + msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved.")); + msg_print(NULL); + } + + if (message) + screen_load(); +} + + +/*! + * @brief HTML方式で記念撮影する / Save a screen dump to a file + * @param なし + * @return なし + */ +static void do_cmd_save_screen_html(void) +{ + char buf[1024], tmp[256] = "screen.html"; + + if (!get_string(_("ファイル名: ", "File name: "), tmp, 80)) + return; + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp); + + msg_print(NULL); + + do_cmd_save_screen_html_aux(buf, 1); +} + + +/*! + * @brief 記念撮影の方式を問い合わせる + * @param html_dump HTMLダンプするか否か + * @return ダンプするならTRUE、キャンセルならFALSE + */ +static bool ask_html_dump(bool *html_dump) +{ + while (TRUE) + { + char c = inkey(); + if (c == 'Y' || c == 'y') + { + *html_dump = FALSE; + return TRUE; + } + + if (c == 'H' || c == 'h') + { + *html_dump = TRUE; + return TRUE; + } + + prt("", 0, 0); + return FALSE; + } + + // コンパイル警告対応. + return FALSE; +} + + +/*! + * @brief ファイルへ書き込めない場合にエラーを表示する + * @param fff ダンプファイルへの参照ポインタ + * @param buf バッファ + * @return ファイルへ書き込めるならTRUE、書き込めないならFALSE + */ +static bool check_screen_text_can_open(FILE *fff, char buf[]) +{ + if (fff) return TRUE; + + msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf); + msg_print(NULL); + return FALSE; +} + + +/*! + * todo どこかバグっていて、(恐らく初期化されていない)変な文字列まで出力される + * @brief テキスト方式で記念撮影する + * @param wid 幅 + * @param hgt 高さ + * @return 記念撮影に成功したらTRUE、ファイルが開けなかったらFALSE + */ +static bool do_cmd_save_screen_text(int wid, int hgt) +{ + TERM_COLOR a = 0; + SYMBOL_CODE c = ' '; + FILE *fff; + char buf[1024]; + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt"); + fff = angband_fopen(buf, "w"); + if (!check_screen_text_can_open(fff, buf)) return FALSE; + + screen_save(); + for (TERM_LEN y = 0; y < hgt; y++) + { + TERM_LEN x; + for (x = 0; x < wid - 1; x++) + { + (void)(term_what(x, y, &a, &c)); + buf[x] = c; + } + + buf[x] = '\0'; + fprintf(fff, "%s\n", buf); + } + + fprintf(fff, "\n"); + for (TERM_LEN y = 0; y < hgt; y++) + { + TERM_LEN x; + for (x = 0; x < wid - 1; x++) + { + (void)(term_what(x, y, &a, &c)); + buf[x] = hack[a & 0x0F]; + } + + buf[x] = '\0'; + fprintf(fff, "%s\n", buf); + } + + fprintf(fff, "\n"); + angband_fclose(fff); + msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved.")); + msg_print(NULL); + screen_load(); + return TRUE; +} + + +/*! + * @brief 記念撮影のためにグラフィック使用をOFFにする + * @param creature_ptr プレーヤーへの参照ポインタ + * @param handle_stuff 画面更新用の関数ポインタ + * @return 記念撮影直前のグラフィックオプション + */ +static bool update_use_graphics(player_type *creature_ptr, void(*process_autopick_file_command)(char*)) +{ + if (!use_graphics) return TRUE; + + use_graphics = FALSE; + reset_visuals(creature_ptr, process_autopick_file_command); + creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY); + handle_stuff(creature_ptr); + return FALSE; +} + + +/* + * Save a screen dump to a file + * @param creature_ptr プレーヤーへの参照ポインタ + * @param handle_stuff 画面更新用の関数ポインタ + * @return なし + */ +void do_cmd_save_screen(player_type *creature_ptr, void(*process_autopick_file_command)(char*)) +{ + prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0); + bool html_dump; + if (!ask_html_dump(&html_dump)) return; + + int wid, hgt; + term_get_size(&wid, &hgt); + + bool old_use_graphics = update_use_graphics(creature_ptr, process_autopick_file_command); + + if (html_dump) + { + do_cmd_save_screen_html(); + do_cmd_redraw(creature_ptr); + } + else if (!do_cmd_save_screen_text(wid, hgt)) + { + return; + } + + if (old_use_graphics) return; + + use_graphics = TRUE; + reset_visuals(creature_ptr, process_autopick_file_command); + creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY); + handle_stuff(creature_ptr); +} + + +/*! + * @brief 白文字だけ画面に描画する (todo 目的は不明瞭) + * @param buf 描画用バッファ + * @param fff 記念撮影ファイルへの参照ポインタ + * @param wid 幅 + * @param hgt 高さ + * @return ファイルが読み込めなくなったらFALSEで抜ける + */ +static bool draw_white_characters(char buf[], FILE *fff, int wid, int hgt) +{ + bool okay = TRUE; + for (TERM_LEN y = 0; okay; y++) + { + if (!fgets(buf, 1024, fff)) okay = FALSE; + + if (buf[0] == '\n' || buf[0] == '\0') break; + if (y >= hgt) continue; + + for (TERM_LEN x = 0; x < wid - 1; x++) + { + if (buf[x] == '\n' || buf[x] == '\0') break; + + term_draw(x, y, TERM_WHITE, buf[x]); + } + } + + return okay; +} + + +/*! + * @brief 白以外の文字を画面に描画する (todo 目的は不明瞭) + * @param buf 描画用バッファ + * @param fff 記念撮影ファイルへの参照ポインタ + * @param wid 幅 + * @param hgt 高さ + * @param 白文字が途中で読み込めなくなっていたらTRUE + * @return なし + */ +static void draw_colored_characters(char buf[], FILE *fff, int wid, int hgt, bool okay) +{ + TERM_COLOR a = TERM_DARK; + SYMBOL_CODE c = ' '; + for (TERM_LEN y = 0; okay; y++) + { + if (!fgets(buf, 1024, fff)) okay = FALSE; + + if (buf[0] == '\n' || buf[0] == '\0') break; + if (y >= hgt) continue; + + for (TERM_LEN x = 0; x < wid - 1; x++) + { + if (buf[x] == '\n' || buf[x] == '\0') break; + + (void)(term_what(x, y, &a, &c)); + for (int i = 0; i < 16; i++) + { + if (hack[i] == buf[x]) a = (byte)i; + } + + term_draw(x, y, a, c); + } + } +} + + +/* + * @brief Load a screen dump from a file + * @param なし + * @return なし + */ +void do_cmd_load_screen(void) +{ + FILE *fff; + char buf[1024]; + TERM_LEN wid, hgt; + term_get_size(&wid, &hgt); + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt"); + fff = angband_fopen(buf, "r"); + if (!fff) + { + msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf); + msg_print(NULL); + return; + } + + screen_save(); + term_clear(); + bool okay = draw_white_characters(buf, fff, wid, hgt); + draw_colored_characters(buf, fff, wid, hgt, okay); + + angband_fclose(fff); + prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0); + flush(); + inkey(); + screen_load(); +} diff --git a/src/cmd-io/cmd-process-screen.h b/src/cmd-io/cmd-process-screen.h new file mode 100644 index 000000000..20f5e03f8 --- /dev/null +++ b/src/cmd-io/cmd-process-screen.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_save_screen_html_aux(char *filename, int message); +void do_cmd_save_screen(player_type *creature_ptr, void(*process_autopick_file_command)(char*)); +void do_cmd_load_screen(void); diff --git a/src/cmd-io/cmd-save.c b/src/cmd-io/cmd-save.c new file mode 100644 index 000000000..f709dc5a4 --- /dev/null +++ b/src/cmd-io/cmd-save.c @@ -0,0 +1,60 @@ +#include "cmd-io/cmd-save.h" +#include "cmd-io/cmd-dump.h" +#include "core/disturbance.h" +#include "core/stuff-handler.h" +#include "io/signal-handlers.h" +#include "io/write-diary.h" +#include "monster/monster-status.h" // 違和感。要調査. +#include "save/save.h" +#include "term/screen-processor.h" +#include "view/display-messages.h" +#include "world/world.h" + +/*! + * @brief セーブするコマンドのメインルーチン + * Save the game + * @param creature_ptr プレーヤーへの参照ポインタ + * @param is_autosave オートセーブ中の処理ならばTRUE + * @return なし + * @details + */ +void do_cmd_save_game(player_type *creature_ptr, int is_autosave) +{ + if (is_autosave) + msg_print(_("自動セーブ中", "Autosaving the game...")); + else + disturb(creature_ptr, TRUE, TRUE); + + msg_print(NULL); + handle_stuff(creature_ptr); + prt(_("ゲームをセーブしています...", "Saving game..."), 0, 0); + term_fresh(); + (void)strcpy(creature_ptr->died_from, _("(セーブ)", "(saved)")); + signals_ignore_tstp(); + if (save_player(creature_ptr)) + prt(_("ゲームをセーブしています... 終了", "Saving game... done."), 0, 0); + else + prt(_("ゲームをセーブしています... 失敗!", "Saving game... failed!"), 0, 0); + + signals_handle_tstp(); + term_fresh(); + (void)strcpy(creature_ptr->died_from, _("(元気に生きている)", "(alive and well)")); + current_world_ptr->is_loading_now = FALSE; + update_creature(creature_ptr); + mproc_init(creature_ptr->current_floor_ptr); + current_world_ptr->is_loading_now = TRUE; +} + + +/*! + * @brief セーブ後にゲーム中断フラグを立てる/ + * Save the game and exit + * @return なし + * @details + */ +void do_cmd_save_and_exit(player_type *creature_ptr) +{ + creature_ptr->playing = FALSE; + creature_ptr->leaving = TRUE; + exe_write_diary(creature_ptr, DIARY_GAMESTART, 0, _("----ゲーム中断----", "--- Saved and Exited Game ---")); +} diff --git a/src/cmd-io/cmd-save.h b/src/cmd-io/cmd-save.h new file mode 100644 index 000000000..1a5f362dc --- /dev/null +++ b/src/cmd-io/cmd-save.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_save_game(player_type *creature_ptr, int is_autosave); +void do_cmd_save_and_exit(player_type *player_ptr); diff --git a/src/cmd-io/diary-subtitle-table.c b/src/cmd-io/diary-subtitle-table.c new file mode 100644 index 000000000..3270e57d6 --- /dev/null +++ b/src/cmd-io/diary-subtitle-table.c @@ -0,0 +1,79 @@ +/* + * @brief 日記のサブタイトルを表すテキストの配列群 + * @date 2020/03/08 + * @author Hourier + */ + +#include "cmd-io/diary-subtitle-table.h" + +concptr subtitle[MAX_SUBTITLE] = { +#ifdef JP + "最強の肉体を求めて", + "人生それははかない", + "勝てば秩序、負ければ混沌", + "溺れる者は藁をも掴む", + "明日に向かって", + "棚からぼたもち", + "あとの祭り", + "それはいい考えだ", + "何とでも言え", + "兎にも角にも", + "ウソだけど", + "もはやこれまで", + "なんでこうなるの", + "それは無理だ", + "倒すべき敵はゲ○ツ", + "ん~?聞こえんなぁ", + "オレの名を言ってみろ", + "頭が変になっちゃった", + "互換しません", + "せっかくだから", + "まだまだ甘いね", + "むごいむごすぎる", + "こんなもんじゃない", + "だめだこりゃ", + "次いってみよう", + "ちょっとだけよ", + "哀しき冒険者", + "野望の果て", + "無限地獄", + "神に喧嘩を売る者", + "未知の世界へ", + "時は金なり", + "最高の頭脳を求めて" +#else + "Quest of The World's Toughest Body", + "Attack is the best form of defence.", + "Might is right.", + "An unexpected windfall", + "A drowning man will catch at a straw", + "Don't count your chickens before they are hatched.", + "It is no use crying over spilt milk.", + "Seeing is believing.", + "Strike the iron while it is hot.", + "I don't care what follows.", + "To dig a well to put out a house on fire.", + "Tomorrow is another day.", + "Easy come, easy go.", + "The more haste, the less speed.", + "Where there is life, there is hope.", + "There is no royal road to *WINNER*.", + "Danger past, God forgotten.", + "The best thing to do now is to run away.", + "Life is but an empty dream.", + "Dead men tell no tales.", + "A book that remains shut is but a block.", + "Misfortunes never come singly.", + "A little knowledge is a dangerous thing.", + "History repeats itself.", + "*WINNER* was not built in a day.", + "Ignorance is bliss.", + "To lose is to win?", + "No medicine can cure folly.", + "All good things come to an end.", + "M$ Empire strikes back.", + "To see is to believe", + "Time is money.", + "Quest of The World's Greatest Brain" +#endif +}; diff --git a/src/cmd-io/diary-subtitle-table.h b/src/cmd-io/diary-subtitle-table.h new file mode 100644 index 000000000..a98477f99 --- /dev/null +++ b/src/cmd-io/diary-subtitle-table.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +#define MAX_SUBTITLE 33 + +extern concptr subtitle[MAX_SUBTITLE]; diff --git a/src/cmd-io/feeling-table.c b/src/cmd-io/feeling-table.c new file mode 100644 index 000000000..9c686088a --- /dev/null +++ b/src/cmd-io/feeling-table.c @@ -0,0 +1,52 @@ +/* + * @brief 雰囲気を表すテキストの配列群 + * @date 2020/03/08 + * @author Hourier + */ + +#include "cmd-io/feeling-table.h" + +concptr do_cmd_feeling_text[MAX_FEELING_TEXT] = +{ + _("この階の雰囲気を感じとれなかった...", "Looks like any other level."), + _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."), + _("恐ろしい死の幻が目に浮かび、気絶しそうになった!", "You nearly faint as horrible visions of death fill your mind!"), + _("この階はとても危険なようだ。", "This level looks very dangerous."), + _("とても悪い予感がする...", "You have a very bad feeling..."), + _("悪い予感がする...", "You have a bad feeling..."), + _("何か緊張する。", "You feel nervous."), + _("少し不運な気がする...", "You feel your luck is turning..."), + _("この場所は好きになれない。", "You don't like the look of this place."), + _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."), + _("なんて退屈なところだ...", "What a boring place...") +}; + +concptr do_cmd_feeling_text_combat[MAX_FEELING_TEXT] = +{ + _("この階の雰囲気を感じとれなかった...", "Looks like any other level."), + _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."), + _("今夜もまた、誰かが命を落とす...", "You nearly faint as horrible visions of death fill your mind!"), + _("この階はとても危険なようだ。", "This level looks very dangerous."), + _("とても悪い予感がする...", "You have a very bad feeling..."), + _("悪い予感がする...", "You have a bad feeling..."), + _("何か緊張する。", "You feel nervous."), + _("少し不運な気がする...", "You feel your luck is turning..."), + _("この場所は好きになれない。", "You don't like the look of this place."), + _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."), + _("なんて退屈なところだ...", "What a boring place...") +}; + +concptr do_cmd_feeling_text_lucky[MAX_FEELING_TEXT] = +{ + _("この階の雰囲気を感じとれなかった...", "Looks like any other level."), + _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."), + _("この階はこの上なく素晴らしい感じがする。", "You have a superb feeling about this level."), + _("素晴らしい感じがする...", "You have an excellent feeling..."), + _("とても良い感じがする...", "You have a very good feeling..."), + _("良い感じがする...", "You have a good feeling..."), + _("ちょっと幸運な感じがする...", "You feel strangely lucky..."), + _("多少は運が向いてきたか...", "You feel your luck is turning..."), + _("見た感じ悪くはない...", "You like the look of this place..."), + _("全然駄目ということはないが...", "This level can't be all bad..."), + _("なんて退屈なところだ...", "What a boring place...") +}; diff --git a/src/cmd-io/feeling-table.h b/src/cmd-io/feeling-table.h new file mode 100644 index 000000000..5a504f7de --- /dev/null +++ b/src/cmd-io/feeling-table.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" + +#define MAX_FEELING_TEXT 11 + +extern concptr do_cmd_feeling_text[MAX_FEELING_TEXT]; +extern concptr do_cmd_feeling_text_combat[MAX_FEELING_TEXT]; +extern concptr do_cmd_feeling_text_lucky[MAX_FEELING_TEXT]; diff --git a/src/cmd-io/macro-util.c b/src/cmd-io/macro-util.c new file mode 100644 index 000000000..00097a235 --- /dev/null +++ b/src/cmd-io/macro-util.c @@ -0,0 +1,137 @@ +#include "cmd-io/macro-util.h" + +/* Array of macro types [MACRO_MAX] */ +bool *macro__cmd; + +/* Current macro action [1024] */ +char *macro__buf; + +/* Array of macro patterns [MACRO_MAX] */ +concptr *macro__pat; + +/* Array of macro actions [MACRO_MAX] */ +concptr *macro__act; + +/* Number of active macros */ +s16b macro__num; + +/* Expand macros in "get_com" or not */ +bool get_com_no_macros = FALSE; + +/* Determine if any macros have ever started with a given character */ +static bool macro__use[256]; + +/* Find the macro (if any) which exactly matches the given pattern */ +int macro_find_exact(concptr pat) +{ + if (!macro__use[(byte)(pat[0])]) { + return -1; + } + + for (int i = 0; i < macro__num; ++i) { + if (!streq(macro__pat[i], pat)) + continue; + + return (i); + } + + return -1; +} + +/* + * Find the first macro (if any) which contains the given pattern + */ +int macro_find_check(concptr pat) +{ + if (!macro__use[(byte)(pat[0])]) { + return -1; + } + + for (int i = 0; i < macro__num; ++i) { + if (!prefix(macro__pat[i], pat)) + continue; + + return (i); + } + + return -1; +} + +/* + * Find the first macro (if any) which contains the given pattern and more + */ +int macro_find_maybe(concptr pat) +{ + if (!macro__use[(byte)(pat[0])]) { + return -1; + } + + for (int i = 0; i < macro__num; ++i) { + if (!prefix(macro__pat[i], pat)) + continue; + if (streq(macro__pat[i], pat)) + continue; + + return (i); + } + + return -1; +} + +/* + * Find the longest macro (if any) which starts with the given pattern + */ +int macro_find_ready(concptr pat) +{ + int t, n = -1, s = -1; + + if (!macro__use[(byte)(pat[0])]) { + return -1; + } + + for (int i = 0; i < macro__num; ++i) { + if (!prefix(pat, macro__pat[i])) + continue; + + t = strlen(macro__pat[i]); + if ((n >= 0) && (s > t)) + continue; + + n = i; + s = t; + } + + return (n); +} + +/* + * Add a macro definition (or redefinition). + * + * We should use "act == NULL" to "remove" a macro, but this might make it + * impossible to save the "removal" of a macro definition. + * + * We should consider refusing to allow macros which contain existing macros, + * or which are contained in existing macros, because this would simplify the + * macro analysis code. + * + * We should consider removing the "command macro" crap, and replacing it + * with some kind of "powerful keymap" ability, but this might make it hard + * to change the "roguelike" option from inside the game. + */ +errr macro_add(concptr pat, concptr act) +{ + if (!pat || !act) + return -1; + + int n = macro_find_exact(pat); + if (n >= 0) { + string_free(macro__act[n]); + } else { + n = macro__num++; + macro__pat[n] = string_make(pat); + } + + macro__act[n] = string_make(act); + macro__use[(byte)(pat[0])] = TRUE; + return 0; +} diff --git a/src/cmd-io/macro-util.h b/src/cmd-io/macro-util.h new file mode 100644 index 000000000..e12640a93 --- /dev/null +++ b/src/cmd-io/macro-util.h @@ -0,0 +1,18 @@ +#pragma once + +#include "system/angband.h" + +extern bool *macro__cmd; +extern char *macro__buf; + +extern bool get_com_no_macros; + +extern concptr *macro__pat; +extern concptr *macro__act; +extern s16b macro__num; + +int macro_find_exact(concptr pat); +int macro_find_check(concptr pat); +errr macro_add(concptr pat, concptr act); +int macro_find_maybe(concptr pat); +int macro_find_ready(concptr pat); diff --git a/src/cmd-item.c b/src/cmd-item.c deleted file mode 100644 index 7dc6d1e65..000000000 --- a/src/cmd-item.c +++ /dev/null @@ -1,1600 +0,0 @@ -/*! - * @file cmd3.c - * @brief プレイヤーのアイテムに関するコマンドの実装1 / Inventory commands - * @date 2014/01/02 - * @author - * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, - * and not for profit purposes provided that this copyright and statement - * are included in all such copies. Other copyrights may also apply. - */ - - -#include "angband.h" -#include "selfinfo.h" -#include "cmd-activate.h" -#include "cmd-eat.h" -#include "cmd-quaff.h" -#include "cmd-read.h" -#include "cmd-usestaff.h" -#include "cmd-zaprod.h" -#include "cmd-zapwand.h" - -#include "object-hook.h" -#include "sort.h" -#include "quest.h" -#include "artifact.h" -#include "avatar.h" -#include "player-status.h" -#include "monster.h" - - -/*! - * @brief 持ち物一覧を表示するコマンドのメインルーチン / Display inventory - * @return なし - */ -void do_cmd_inven(void) -{ - char out_val[160]; - - /* Note that we are in "inventory" mode */ - command_wrk = FALSE; - - /* Note that we are in "inventory" mode */ - if (easy_floor) command_wrk = (USE_INVEN); - screen_save(); - - /* Display the inventory */ - (void)show_inven(0, USE_FULL); - -#ifdef JP - sprintf(out_val, "持ち物: 合計 %3d.%1d kg (限界の%ld%%) コマンド: ", - (int)lbtokg1(p_ptr->total_weight) , (int)lbtokg2(p_ptr->total_weight) , - (long int)((p_ptr->total_weight * 100) / weight_limit())); -#else - sprintf(out_val, "Inventory: carrying %d.%d pounds (%ld%% of capacity). Command: ", - (int)(p_ptr->total_weight / 10), (int)(p_ptr->total_weight % 10), - (p_ptr->total_weight * 100) / weight_limit()); -#endif - - prt(out_val, 0, 0); - command_new = inkey(); - screen_load(); - - /* Process "Escape" */ - if (command_new == ESCAPE) - { - TERM_LEN wid, hgt; - - Term_get_size(&wid, &hgt); - - /* Reset stuff */ - command_new = 0; - command_gap = wid - 30; - } - - /* Process normal keys */ - else - { - /* Hack -- Use "display" mode */ - command_see = TRUE; - } -} - - -/*! - * @brief 装備一覧を表示するコマンドのメインルーチン / Display equipment - * @return なし - */ -void do_cmd_equip(void) -{ - char out_val[160]; - - /* Note that we are in "equipment" mode */ - command_wrk = TRUE; - - /* Note that we are in "equipment" mode */ - if (easy_floor) command_wrk = (USE_EQUIP); - screen_save(); - - (void)show_equip(0, USE_FULL); - - /* Build a prompt */ -#ifdef JP - sprintf(out_val, "装備: 合計 %3d.%1d kg (限界の%ld%%) コマンド: ", - (int)lbtokg1(p_ptr->total_weight) , (int)lbtokg2(p_ptr->total_weight) , - (long int)((p_ptr->total_weight * 100) / weight_limit())); -#else - sprintf(out_val, "Equipment: carrying %d.%d pounds (%ld%% of capacity). Command: ", - (int)(p_ptr->total_weight / 10), (int)(p_ptr->total_weight % 10), - (long int)((p_ptr->total_weight * 100) / weight_limit())); -#endif - - prt(out_val, 0, 0); - command_new = inkey(); - screen_load(); - - /* Process "Escape" */ - if (command_new == ESCAPE) - { - TERM_LEN wid, hgt; - - Term_get_size(&wid, &hgt); - - /* Reset stuff */ - command_new = 0; - command_gap = wid - 30; - } - - /* Process normal keys */ - else - { - /* Enter "display" mode */ - command_see = TRUE; - } -} - - - - -bool select_ring_slot = FALSE; - -/*! - * @brief 装備するコマンドのメインルーチン / Wield or wear a single item from the pack or floor - * @return なし - */ -void do_cmd_wield(void) -{ - OBJECT_IDX item, slot; - object_type forge; - object_type *q_ptr; - object_type *o_ptr; - - concptr act; - concptr q, s; - - GAME_TEXT o_name[MAX_NLEN]; - - - OBJECT_IDX need_switch_wielding = 0; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Restrict the choices */ - item_tester_hook = item_tester_hook_wear; - - q = _("どれを装備しますか? ", "Wear/Wield which item? "); - s = _("装備可能なアイテムがない。", "You have nothing you can wear or wield."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR)); - if (!o_ptr) return; - - /* Check the slot */ - slot = wield_slot(o_ptr); - - switch (o_ptr->tval) - { - /* Shields and some misc. items */ - case TV_CAPTURE: - case TV_SHIELD: - case TV_CARD: - /* Dual wielding */ - if (has_melee_weapon(INVEN_RARM) && has_melee_weapon(INVEN_LARM)) - { - /* Restrict the choices */ - item_tester_hook = item_tester_hook_melee_weapon; - - /* Choose a weapon from the equipment only */ - q = _("どちらの武器と取り替えますか?", "Replace which weapon? "); - s = _("おっと。", "Oops."); - if (!choose_object(&slot, q, s, (USE_EQUIP | IGNORE_BOTHHAND_SLOT))) return; - if (slot == INVEN_RARM) need_switch_wielding = INVEN_LARM; - } - - else if (has_melee_weapon(INVEN_LARM)) slot = INVEN_RARM; - - /* Both arms are already used by non-weapon */ - else if (inventory[INVEN_RARM].k_idx && !object_is_melee_weapon(&inventory[INVEN_RARM]) && - inventory[INVEN_LARM].k_idx && !object_is_melee_weapon(&inventory[INVEN_LARM])) - { - /* Restrict the choices */ - item_tester_hook = item_tester_hook_mochikae; - - /* Choose a hand */ - q = _("どちらの手に装備しますか?", "Equip which hand? "); - s = _("おっと。", "Oops."); - if (!choose_object(&slot, q, s, (USE_EQUIP))) return; - } - break; - - /* Melee weapons */ - case TV_DIGGING: - case TV_HAFTED: - case TV_POLEARM: - case TV_SWORD: - /* Asking for dual wielding */ - if (slot == INVEN_LARM) - { - if (!get_check(_("二刀流で戦いますか?", "Dual wielding? "))) slot = INVEN_RARM; - } - - else if (!inventory[INVEN_RARM].k_idx && has_melee_weapon(INVEN_LARM)) - { - if (!get_check(_("二刀流で戦いますか?", "Dual wielding? "))) slot = INVEN_LARM; - } - - /* Both arms are already used */ - else if (inventory[INVEN_LARM].k_idx && inventory[INVEN_RARM].k_idx) - { - /* Restrict the choices */ - item_tester_hook = item_tester_hook_mochikae; - - /* Choose a hand */ - q = _("どちらの手に装備しますか?", "Equip which hand? "); - s = _("おっと。", "Oops."); - - if (!choose_object(&slot, q, s, (USE_EQUIP))) return; - if ((slot == INVEN_LARM) && !has_melee_weapon(INVEN_RARM)) - need_switch_wielding = INVEN_RARM; - } - break; - - /* Rings */ - case TV_RING: - /* Choose a ring slot */ - if (inventory[INVEN_LEFT].k_idx && inventory[INVEN_RIGHT].k_idx) - { - q = _("どちらの指輪と取り替えますか?", "Replace which ring? "); - } - else - { - q = _("どちらの手に装備しますか?", "Equip which hand? "); - } - s = _("おっと。", "Oops."); - - /* Restrict the choices */ - select_ring_slot = TRUE; - - if (!choose_object(&slot, q, s, (USE_EQUIP | IGNORE_BOTHHAND_SLOT))) - { - select_ring_slot = FALSE; - return; - } - select_ring_slot = FALSE; - break; - } - - /* Prevent wielding into a cursed slot */ - if (object_is_cursed(&inventory[slot])) - { - object_desc(o_name, &inventory[slot], (OD_OMIT_PREFIX | OD_NAME_ONLY)); - -#ifdef JP - msg_format("%s%sは呪われているようだ。", describe_use(slot) , o_name ); -#else - msg_format("The %s you are %s appears to be cursed.", o_name, describe_use(slot)); -#endif - - /* Cancel the command */ - return; - } - - if (confirm_wear && - ((object_is_cursed(o_ptr) && object_is_known(o_ptr)) || - ((o_ptr->ident & IDENT_SENSE) && - (FEEL_BROKEN <= o_ptr->feeling) && (o_ptr->feeling <= FEEL_CURSED)))) - { - char dummy[MAX_NLEN+80]; - - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - sprintf(dummy, _("本当に%s{呪われている}を使いますか?", "Really use the %s {cursed}? "), o_name); - - if (!get_check(dummy)) return; - } - - if ((o_ptr->name1 == ART_STONEMASK) && object_is_known(o_ptr) && (p_ptr->prace != RACE_VAMPIRE) && (p_ptr->prace != RACE_ANDROID)) - { - char dummy[MAX_NLEN+100]; - - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - - sprintf(dummy, _("%sを装備すると吸血鬼になります。よろしいですか?", - "%s will transforms you into a vampire permanently when equiped. Do you become a vampire?"), o_name); - - if (!get_check(dummy)) return; - } - - if (need_switch_wielding && !object_is_cursed(&inventory[need_switch_wielding])) - { - object_type *slot_o_ptr = &inventory[slot]; - object_type *switch_o_ptr = &inventory[need_switch_wielding]; - object_type object_tmp; - object_type *otmp_ptr = &object_tmp; - GAME_TEXT switch_name[MAX_NLEN]; - - object_desc(switch_name, switch_o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - - object_copy(otmp_ptr, switch_o_ptr); - object_copy(switch_o_ptr, slot_o_ptr); - object_copy(slot_o_ptr, otmp_ptr); - - msg_format(_("%sを%sに構えなおした。", "You wield %s at %s hand."), switch_name, - (slot == INVEN_RARM) ? (left_hander ? _("左手", "left") : _("右手", "right")) : - (left_hander ? _("右手", "right") : _("左手", "left"))); - slot = need_switch_wielding; - } - - check_find_art_quest_completion(o_ptr); - - if (p_ptr->pseikaku == SEIKAKU_MUNCHKIN) - { - identify_item(o_ptr); - - /* Auto-inscription */ - autopick_alter_item(item, FALSE); - } - - take_turn(p_ptr, 100); - q_ptr = &forge; - - /* Obtain local object */ - object_copy(q_ptr, o_ptr); - - /* Modify quantity */ - q_ptr->number = 1; - - /* Decrease the item (from the pack) */ - if (item >= 0) - { - inven_item_increase(item, -1); - inven_item_optimize(item); - } - - /* Decrease the item (from the floor) */ - else - { - floor_item_increase(0 - item, -1); - floor_item_optimize(0 - item); - } - - /* Access the wield slot */ - o_ptr = &inventory[slot]; - - /* Take off existing item */ - if (o_ptr->k_idx) - { - /* Take off existing item */ - (void)inven_takeoff(slot, 255); - } - - /* Wear the new stuff */ - object_copy(o_ptr, q_ptr); - - o_ptr->marked |= OM_TOUCHED; - - p_ptr->total_weight += q_ptr->weight; - - /* Increment the equip counter by hand */ - equip_cnt++; - -#define STR_WIELD_RARM _("%s(%c)を右手に装備した。", "You are wielding %s (%c) in your right hand.") -#define STR_WIELD_LARM _("%s(%c)を左手に装備した。", "You are wielding %s (%c) in your left hand.") -#define STR_WIELD_ARMS _("%s(%c)を両手で構えた。", "You are wielding %s (%c) with both hands.") - - /* Where is the item now */ - switch (slot) - { - case INVEN_RARM: - if (object_allow_two_hands_wielding(o_ptr) && (empty_hands(FALSE) == EMPTY_HAND_LARM) && CAN_TWO_HANDS_WIELDING()) - act = STR_WIELD_ARMS; - else - act = (left_hander ? STR_WIELD_LARM : STR_WIELD_RARM); - break; - - case INVEN_LARM: - if (object_allow_two_hands_wielding(o_ptr) && (empty_hands(FALSE) == EMPTY_HAND_RARM) && CAN_TWO_HANDS_WIELDING()) - act = STR_WIELD_ARMS; - else - act = (left_hander ? STR_WIELD_RARM : STR_WIELD_LARM); - break; - - case INVEN_BOW: - act = _("%s(%c)を射撃用に装備した。", "You are shooting with %s (%c)."); - break; - - case INVEN_LITE: - act = _("%s(%c)を光源にした。", "Your light source is %s (%c)."); - break; - - default: - act = _("%s(%c)を装備した。", "You are wearing %s (%c)."); - break; - } - - object_desc(o_name, o_ptr, 0); - msg_format(act, o_name, index_to_label(slot)); - - /* Cursed! */ - if (object_is_cursed(o_ptr)) - { - msg_print(_("うわ! すさまじく冷たい!", "Oops! It feels deathly cold!")); - chg_virtue(V_HARMONY, -1); - - /* Note the curse */ - o_ptr->ident |= (IDENT_SENSE); - } - - /* The Stone Mask make the player current_world_ptr->game_turn into a vampire! */ - if ((o_ptr->name1 == ART_STONEMASK) && (p_ptr->prace != RACE_VAMPIRE) && (p_ptr->prace != RACE_ANDROID)) - { - /* Turn into a vampire */ - change_race(RACE_VAMPIRE, ""); - } - - p_ptr->update |= (PU_BONUS | PU_TORCH | PU_MANA); - p_ptr->redraw |= (PR_EQUIPPY); - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - calc_android_exp(); -} - -/*! - * @brief 持ち替え処理 - * @param item 持ち替えを行いたい装備部位ID - * @return なし - */ -void kamaenaoshi(INVENTORY_IDX item) -{ - object_type *o_ptr, *new_o_ptr; - GAME_TEXT o_name[MAX_NLEN]; - - if (item == INVEN_RARM) - { - if (has_melee_weapon(INVEN_LARM)) - { - o_ptr = &inventory[INVEN_LARM]; - object_desc(o_name, o_ptr, 0); - - if (!object_is_cursed(o_ptr)) - { - new_o_ptr = &inventory[INVEN_RARM]; - object_copy(new_o_ptr, o_ptr); - p_ptr->total_weight += o_ptr->weight; - inven_item_increase(INVEN_LARM, -((int)o_ptr->number)); - inven_item_optimize(INVEN_LARM); - if (object_allow_two_hands_wielding(o_ptr) && CAN_TWO_HANDS_WIELDING()) - msg_format(_("%sを両手で構えた。", "You are wielding %s with both hands."), o_name); - else - msg_format(_("%sを%sで構えた。", "You are wielding %s in your %s hand."), o_name, - (left_hander ? _("左手", "left") : _("右手", "right"))); - } - else - { - if (object_allow_two_hands_wielding(o_ptr) && CAN_TWO_HANDS_WIELDING()) - msg_format(_("%sを両手で構えた。", "You are wielding %s with both hands."), o_name); - } - } - } - else if (item == INVEN_LARM) - { - o_ptr = &inventory[INVEN_RARM]; - if (o_ptr->k_idx) object_desc(o_name, o_ptr, 0); - - if (has_melee_weapon(INVEN_RARM)) - { - if (object_allow_two_hands_wielding(o_ptr) && CAN_TWO_HANDS_WIELDING()) - msg_format(_("%sを両手で構えた。", "You are wielding %s with both hands."), o_name); - } - else if (!(empty_hands(FALSE) & EMPTY_HAND_RARM) && !object_is_cursed(o_ptr)) - { - new_o_ptr = &inventory[INVEN_LARM]; - object_copy(new_o_ptr, o_ptr); - p_ptr->total_weight += o_ptr->weight; - inven_item_increase(INVEN_RARM, -((int)o_ptr->number)); - inven_item_optimize(INVEN_RARM); - msg_format(_("%sを持ち替えた。", "You switched hand of %s."), o_name); - } - } -} - - -/*! - * @brief 装備を外すコマンドのメインルーチン / Take off an item - * @return なし - */ -void do_cmd_takeoff(void) -{ - OBJECT_IDX item; - object_type *o_ptr; - concptr q, s; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - q = _("どれを装備からはずしますか? ", "Take off which item? "); - s = _("はずせる装備がない。", "You are not wearing anything to take off."); - - o_ptr = choose_object(&item, q, s, (USE_EQUIP | IGNORE_BOTHHAND_SLOT)); - if (!o_ptr) return; - - /* Item is cursed */ - if (object_is_cursed(o_ptr)) - { - if ((o_ptr->curse_flags & TRC_PERMA_CURSE) || (p_ptr->pclass != CLASS_BERSERKER)) - { - msg_print(_("ふーむ、どうやら呪われているようだ。", "Hmmm, it seems to be cursed.")); - - return; - } - - if (((o_ptr->curse_flags & TRC_HEAVY_CURSE) && one_in_(7)) || one_in_(4)) - { - msg_print(_("呪われた装備を力づくで剥がした!", "You teared a cursed equipment off by sheer strength!")); - - o_ptr->ident |= (IDENT_SENSE); - o_ptr->curse_flags = 0L; - o_ptr->feeling = FEEL_NONE; - - p_ptr->update |= (PU_BONUS); - p_ptr->window |= (PW_EQUIP); - - msg_print(_("呪いを打ち破った。", "You break the curse.")); - } - else - { - msg_print(_("装備を外せなかった。", "You couldn't remove the equipment.")); - take_turn(p_ptr, 50); - return; - } - } - - take_turn(p_ptr, 50); - - /* Take off the item */ - (void)inven_takeoff(item, 255); - kamaenaoshi(item); - calc_android_exp(); - p_ptr->redraw |= (PR_EQUIPPY); -} - - -/*! - * @brief アイテムを落とすコマンドのメインルーチン / Drop an item - * @return なし - */ -void do_cmd_drop(void) -{ - OBJECT_IDX item; - int amt = 1; - - object_type *o_ptr; - - concptr q, s; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - q = _("どのアイテムを落としますか? ", "Drop which item? "); - s = _("落とせるアイテムを持っていない。", "You have nothing to drop."); - - o_ptr = choose_object(&item, q, s, (USE_EQUIP | USE_INVEN | IGNORE_BOTHHAND_SLOT)); - if (!o_ptr) return; - - /* Hack -- Cannot remove cursed items */ - if ((item >= INVEN_RARM) && object_is_cursed(o_ptr)) - { - msg_print(_("ふーむ、どうやら呪われているようだ。", "Hmmm, it seems to be cursed.")); - return; - } - - if (o_ptr->number > 1) - { - amt = get_quantity(NULL, o_ptr->number); - if (amt <= 0) return; - } - - take_turn(p_ptr, 50); - - /* Drop (some of) the item */ - inven_drop(item, amt); - - if (item >= INVEN_RARM) - { - kamaenaoshi(item); - calc_android_exp(); - } - - p_ptr->redraw |= (PR_EQUIPPY); -} - - -/*! - * @brief アイテムを破壊するコマンドのメインルーチン / Destroy an item - * @return なし - */ -void do_cmd_destroy(void) -{ - OBJECT_IDX item; - QUANTITY amt = 1; - QUANTITY old_number; - - bool force = FALSE; - - object_type *o_ptr; - object_type forge; - object_type *q_ptr = &forge; - - GAME_TEXT o_name[MAX_NLEN]; - char out_val[MAX_NLEN+40]; - - concptr q, s; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Hack -- force destruction */ - if (command_arg > 0) force = TRUE; - - q = _("どのアイテムを壊しますか? ", "Destroy which item? "); - s = _("壊せるアイテムを持っていない。", "You have nothing to destroy."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR)); - if (!o_ptr) return; - - /* Verify unless quantity given beforehand */ - if (!force && (confirm_destroy || (object_value(o_ptr) > 0))) - { - object_desc(o_name, o_ptr, OD_OMIT_PREFIX); - - /* Make a verification */ - sprintf(out_val, _("本当に%sを壊しますか? [y/n/Auto]", "Really destroy %s? [y/n/Auto]"), o_name); - msg_print(NULL); - - /* HACK : Add the line to message buffer */ - message_add(out_val); - p_ptr->window |= (PW_MESSAGE); - handle_stuff(); - - /* Get an acceptable answer */ - while (TRUE) - { - char i; - - /* Prompt */ - prt(out_val, 0, 0); - - i = inkey(); - - /* Erase the prompt */ - prt("", 0, 0); - - - if (i == 'y' || i == 'Y') - { - break; - } - if (i == ESCAPE || i == 'n' || i == 'N') - { - /* Cancel */ - return; - } - if (i == 'A') - { - /* Add an auto-destroy preference line */ - if (autopick_autoregister(o_ptr)) - { - /* Auto-destroy it */ - autopick_alter_item(item, TRUE); - } - - /* The object is already destroyed. */ - return; - } - } /* while (TRUE) */ - } - - if (o_ptr->number > 1) - { - amt = get_quantity(NULL, o_ptr->number); - if (amt <= 0) return; - } - - - old_number = o_ptr->number; - o_ptr->number = amt; - object_desc(o_name, o_ptr, 0); - o_ptr->number = old_number; - - take_turn(p_ptr, 100); - - /* Artifacts cannot be destroyed */ - if (!can_player_destroy_object(o_ptr)) - { - free_turn(p_ptr); - - msg_format(_("%sは破壊不可能だ。", "You cannot destroy %s."), o_name); - return; - } - - object_copy(q_ptr, o_ptr); - - msg_format(_("%sを壊した。", "You destroy %s."), o_name); - sound(SOUND_DESTITEM); - - /* Reduce the charges of rods/wands */ - reduce_charges(o_ptr, amt); - - /* Eliminate the item (from the pack) */ - if (item >= 0) - { - inven_item_increase(item, -amt); - inven_item_describe(item); - inven_item_optimize(item); - } - - /* Eliminate the item (from the floor) */ - else - { - floor_item_increase(0 - item, -amt); - floor_item_describe(0 - item); - floor_item_optimize(0 - item); - } - - if (item_tester_high_level_book(q_ptr)) - { - bool gain_expr = FALSE; - - if (p_ptr->prace == RACE_ANDROID) - { - } - else if ((p_ptr->pclass == CLASS_WARRIOR) || (p_ptr->pclass == CLASS_BERSERKER)) - { - gain_expr = TRUE; - } - else if (p_ptr->pclass == CLASS_PALADIN) - { - if (is_good_realm(p_ptr->realm1)) - { - if (!is_good_realm(tval2realm(q_ptr->tval))) gain_expr = TRUE; - } - else - { - if (is_good_realm(tval2realm(q_ptr->tval))) gain_expr = TRUE; - } - } - - if (gain_expr && (p_ptr->exp < PY_MAX_EXP)) - { - s32b tester_exp = p_ptr->max_exp / 20; - if (tester_exp > 10000) tester_exp = 10000; - if (q_ptr->sval < 3) tester_exp /= 4; - if (tester_exp<1) tester_exp = 1; - - msg_print(_("更に経験を積んだような気がする。", "You feel more experienced.")); - gain_exp(tester_exp * amt); - } - if (item_tester_high_level_book(q_ptr) && q_ptr->tval == TV_LIFE_BOOK) - { - chg_virtue(V_UNLIFE, 1); - chg_virtue(V_VITALITY, -1); - } - else if (item_tester_high_level_book(q_ptr) && q_ptr->tval == TV_DEATH_BOOK) - { - chg_virtue(V_UNLIFE, -1); - chg_virtue(V_VITALITY, 1); - } - - if (q_ptr->to_a || q_ptr->to_h || q_ptr->to_d) - chg_virtue(V_ENCHANT, -1); - - if (object_value_real(q_ptr) > 30000) - chg_virtue(V_SACRIFICE, 2); - - else if (object_value_real(q_ptr) > 10000) - chg_virtue(V_SACRIFICE, 1); - } - - if (q_ptr->to_a != 0 || q_ptr->to_d != 0 || q_ptr->to_h != 0) - chg_virtue(V_HARMONY, 1); - - if (item >= INVEN_RARM) calc_android_exp(); -} - - -/*! - * @brief アイテムを調査するコマンドのメインルーチン / Observe an item which has been *identify*-ed - * @return なし - */ -void do_cmd_observe(void) -{ - OBJECT_IDX item; - object_type *o_ptr; - GAME_TEXT o_name[MAX_NLEN]; - concptr q, s; - - q = _("どのアイテムを調べますか? ", "Examine which item? "); - s = _("調べられるアイテムがない。", "You have nothing to examine."); - - o_ptr = choose_object(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT)); - if (!o_ptr) return; - - /* Require full knowledge */ - if (!(o_ptr->ident & IDENT_MENTAL)) - { - msg_print(_("このアイテムについて特に知っていることはない。", "You have no special knowledge about that item.")); - return; - } - - object_desc(o_name, o_ptr, 0); - msg_format(_("%sを調べている...", "Examining %s..."), o_name); - if (!screen_object(o_ptr, SCROBJ_FORCE_DETAIL)) msg_print(_("特に変わったところはないようだ。", "You see nothing special.")); -} - - - -/*! - * @brief アイテムの銘を消すコマンドのメインルーチン - * Remove the inscription from an object XXX Mention item (when done)? - * @return なし - */ -void do_cmd_uninscribe(void) -{ - OBJECT_IDX item; - object_type *o_ptr; - concptr q, s; - - q = _("どのアイテムの銘を消しますか? ", "Un-inscribe which item? "); - s = _("銘を消せるアイテムがない。", "You have nothing to un-inscribe."); - - o_ptr = choose_object(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT)); - if (!o_ptr) return; - - /* Nothing to remove */ - if (!o_ptr->inscription) - { - msg_print(_("このアイテムには消すべき銘がない。", "That item had no inscription to remove.")); - return; - } - - msg_print(_("銘を消した。", "Inscription removed.")); - - /* Remove the incription */ - o_ptr->inscription = 0; - p_ptr->update |= (PU_COMBINE); - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* .や$の関係で, 再計算が必要なはず -- henkma */ - p_ptr->update |= (PU_BONUS); - -} - - -/*! - * @brief アイテムの銘を刻むコマンドのメインルーチン - * Inscribe an object with a comment - * @return なし - */ -void do_cmd_inscribe(void) -{ - OBJECT_IDX item; - object_type *o_ptr; - GAME_TEXT o_name[MAX_NLEN]; - char out_val[80]; - concptr q, s; - - q = _("どのアイテムに銘を刻みますか? ", "Inscribe which item? "); - s = _("銘を刻めるアイテムがない。", "You have nothing to inscribe."); - - o_ptr = choose_object(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT)); - if (!o_ptr) return; - - /* Describe the activity */ - object_desc(o_name, o_ptr, OD_OMIT_INSCRIPTION); - - msg_format(_("%sに銘を刻む。", "Inscribing %s."), o_name); - msg_print(NULL); - - /* Start with nothing */ - strcpy(out_val, ""); - - /* Use old inscription */ - if (o_ptr->inscription) - { - /* Start with the old inscription */ - strcpy(out_val, quark_str(o_ptr->inscription)); - } - - /* Get a new inscription (possibly empty) */ - if (get_string(_("銘: ", "Inscription: "), out_val, 80)) - { - /* Save the inscription */ - o_ptr->inscription = quark_add(out_val); - p_ptr->update |= (PU_COMBINE); - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* .や$の関係で, 再計算が必要なはず -- henkma */ - p_ptr->update |= (PU_BONUS); - } -} - - -/*! - * @brief ランタンに燃料を加えるコマンドのメインルーチン - * Refill the players lamp (from the pack or floor) - * @return なし - */ -static void do_cmd_refill_lamp(void) -{ - OBJECT_IDX item; - object_type *o_ptr; - object_type *j_ptr; - concptr q, s; - - /* Restrict the choices */ - item_tester_hook = item_tester_refill_lantern; - - q = _("どの油つぼから注ぎますか? ", "Refill with which flask? "); - s = _("油つぼがない。", "You have no flasks of oil."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR)); - if (!o_ptr) return; - - take_turn(p_ptr, 50); - - /* Access the lantern */ - j_ptr = &inventory[INVEN_LITE]; - - /* Refuel */ - j_ptr->xtra4 += o_ptr->xtra4; - msg_print(_("ランプに油を注いだ。", "You fuel your lamp.")); - - if ((o_ptr->name2 == EGO_LITE_DARKNESS) && (j_ptr->xtra4 > 0)) - { - j_ptr->xtra4 = 0; - msg_print(_("ランプが消えてしまった!", "Your lamp has gone out!")); - } - else if ((o_ptr->name2 == EGO_LITE_DARKNESS) || (j_ptr->name2 == EGO_LITE_DARKNESS)) - { - j_ptr->xtra4 = 0; - msg_print(_("しかしランプは全く光らない。", "Curiously, your lamp doesn't light.")); - } - else if (j_ptr->xtra4 >= FUEL_LAMP) - { - j_ptr->xtra4 = FUEL_LAMP; - msg_print(_("ランプの油は一杯だ。", "Your lamp is full.")); - } - - /* Decrease the item (from the pack) */ - if (item >= 0) - { - inven_item_increase(item, -1); - inven_item_describe(item); - inven_item_optimize(item); - } - - /* Decrease the item (from the floor) */ - else - { - floor_item_increase(0 - item, -1); - floor_item_describe(0 - item); - floor_item_optimize(0 - item); - } - - p_ptr->update |= (PU_TORCH); -} - -/*! - * @brief 松明を束ねるコマンドのメインルーチン - * Refuel the players torch (from the pack or floor) - * @return なし - */ -static void do_cmd_refill_torch(void) -{ - OBJECT_IDX item; - - object_type *o_ptr; - object_type *j_ptr; - - concptr q, s; - - /* Restrict the choices */ - item_tester_hook = object_can_refill_torch; - - q = _("どの松明で明かりを強めますか? ", "Refuel with which torch? "); - s = _("他に松明がない。", "You have no extra torches."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR)); - if (!o_ptr) return; - - take_turn(p_ptr, 50); - - /* Access the primary torch */ - j_ptr = &inventory[INVEN_LITE]; - - /* Refuel */ - j_ptr->xtra4 += o_ptr->xtra4 + 5; - - msg_print(_("松明を結合した。", "You combine the torches.")); - - if ((o_ptr->name2 == EGO_LITE_DARKNESS) && (j_ptr->xtra4 > 0)) - { - j_ptr->xtra4 = 0; - msg_print(_("松明が消えてしまった!", "Your torch has gone out!")); - } - else if ((o_ptr->name2 == EGO_LITE_DARKNESS) || (j_ptr->name2 == EGO_LITE_DARKNESS)) - { - j_ptr->xtra4 = 0; - msg_print(_("しかし松明は全く光らない。", "Curiously, your torche don't light.")); - } - /* Over-fuel message */ - else if (j_ptr->xtra4 >= FUEL_TORCH) - { - j_ptr->xtra4 = FUEL_TORCH; - msg_print(_("松明の寿命は十分だ。", "Your torch is fully fueled.")); - } - - /* Refuel message */ - else - { - msg_print(_("松明はいっそう明るく輝いた。", "Your torch glows more brightly.")); - } - - /* Decrease the item (from the pack) */ - if (item >= 0) - { - inven_item_increase(item, -1); - inven_item_describe(item); - inven_item_optimize(item); - } - - /* Decrease the item (from the floor) */ - else - { - floor_item_increase(0 - item, -1); - floor_item_describe(0 - item); - floor_item_optimize(0 - item); - } - - p_ptr->update |= (PU_TORCH); -} - - -/*! - * @brief 燃料を補充するコマンドのメインルーチン - * Refill the players lamp, or restock his torches - * @return なし - */ -void do_cmd_refill(void) -{ - object_type *o_ptr; - - /* Get the light */ - o_ptr = &inventory[INVEN_LITE]; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* It is nothing */ - if (o_ptr->tval != TV_LITE) - { - msg_print(_("光源を装備していない。", "You are not wielding a light.")); - } - - /* It's a lamp */ - else if (o_ptr->sval == SV_LITE_LANTERN) - { - do_cmd_refill_lamp(); - } - - /* It's a torch */ - else if (o_ptr->sval == SV_LITE_TORCH) - { - do_cmd_refill_torch(); - } - - /* No torch to refill */ - else - { - msg_print(_("この光源は寿命を延ばせない。", "Your light cannot be refilled.")); - } -} - - -/*! - * @brief ターゲットを設定するコマンドのメインルーチン - * Target command - * @return なし - */ -void do_cmd_target(void) -{ - if (p_ptr->wild_mode) return; - - /* Target set */ - if (target_set(TARGET_KILL)) - { - msg_print(_("ターゲット決定。", "Target Selected.")); - } - - /* Target aborted */ - else - { - msg_print(_("ターゲット解除。", "Target Aborted.")); - } -} - - - -/*! - * @brief 周囲を見渡すコマンドのメインルーチン - * Look command - * @return なし - */ -void do_cmd_look(void) -{ - p_ptr->window |= PW_MONSTER_LIST; - handle_stuff(); - - /* Look around */ - if (target_set(TARGET_LOOK)) - { - msg_print(_("ターゲット決定。", "Target Selected.")); - } -} - - -/*! - * @brief 位置を確認するコマンドのメインルーチン - * Allow the player to examine other sectors on the map - * @return なし - */ -void do_cmd_locate(void) -{ - DIRECTION dir; - POSITION y1, x1, y2, x2; - GAME_TEXT tmp_val[80]; - GAME_TEXT out_val[160]; - TERM_LEN wid, hgt; - - get_screen_size(&wid, &hgt); - - /* Start at current panel */ - y2 = y1 = panel_row_min; - x2 = x1 = panel_col_min; - - /* Show panels until done */ - while (1) - { - /* Describe the location */ - if ((y2 == y1) && (x2 == x1)) - { - strcpy(tmp_val, _("真上", "\0")); - } - else - { - sprintf(tmp_val, "%s%s", - ((y2 < y1) ? _("北", " North") : (y2 > y1) ? _("南", " South") : ""), - ((x2 < x1) ? _("西", " West") : (x2 > x1) ? _("東", " East") : "")); - } - - /* Prepare to ask which way to look */ - sprintf(out_val, _("マップ位置 [%d(%02d),%d(%02d)] (プレイヤーの%s) 方向?", - "Map sector [%d(%02d),%d(%02d)], which is%s your sector. Direction?"), - y2 / (hgt / 2), y2 % (hgt / 2), - x2 / (wid / 2), x2 % (wid / 2), tmp_val); - - /* Assume no direction */ - dir = 0; - - /* Get a direction */ - while (!dir) - { - char command; - - /* Get a command (or Cancel) */ - if (!get_com(out_val, &command, TRUE)) break; - - /* Extract the action (if any) */ - dir = get_keymap_dir(command); - - /* Error */ - if (!dir) bell(); - } - - /* No direction */ - if (!dir) break; - - /* Apply the motion */ - if (change_panel(ddy[dir], ddx[dir])) - { - y2 = panel_row_min; - x2 = panel_col_min; - } - } - - - /* Recenter the map around the player */ - verify_panel(); - - p_ptr->update |= (PU_MONSTERS); - p_ptr->redraw |= (PR_MAP); - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); - handle_stuff(); -} - - -/*! - * @brief モンスターの思い出を見るコマンドのメインルーチン - * Identify a character, allow recall of monsters - * @return なし - * @details - *
- * Several "special" responses recall "multiple" monsters:
- *   ^A (all monsters)
- *   ^U (all unique monsters)
- *   ^N (all non-unique monsters)
- *
- * The responses may be sorted in several ways, see below.
- *
- * Note that the player ghosts are ignored. 
- * 
- */ -void do_cmd_query_symbol(void) -{ - IDX i; - int n; - MONRACE_IDX r_idx; - char sym, query; - char buf[128]; - - bool all = FALSE; - bool uniq = FALSE; - bool norm = FALSE; - bool ride = FALSE; - char temp[80] = ""; - - bool recall = FALSE; - - u16b why = 0; - MONRACE_IDX *who; - - /* Get a character, or abort */ - if (!get_com(_("知りたい文字を入力して下さい(記号 or ^A全,^Uユ,^N非ユ,^R乗馬,^M名前): ", - "Enter character to be identified(^A:All,^U:Uniqs,^N:Non uniqs,^M:Name): "), &sym, FALSE)) return; - - /* Find that character info, and describe it */ - for (i = 0; ident_info[i]; ++i) - { - if (sym == ident_info[i][0]) break; - } - if (sym == KTRL('A')) - { - all = TRUE; - strcpy(buf, _("全モンスターのリスト", "Full monster list.")); - } - else if (sym == KTRL('U')) - { - all = uniq = TRUE; - strcpy(buf, _("ユニーク・モンスターのリスト", "Unique monster list.")); - } - else if (sym == KTRL('N')) - { - all = norm = TRUE; - strcpy(buf, _("ユニーク外モンスターのリスト", "Non-unique monster list.")); - } - else if (sym == KTRL('R')) - { - all = ride = TRUE; - strcpy(buf, _("乗馬可能モンスターのリスト", "Ridable monster list.")); - } - /* XTRA HACK WHATSEARCH */ - else if (sym == KTRL('M')) - { - all = TRUE; - if (!get_string(_("名前(英語の場合小文字で可)", "Enter name:"),temp, 70)) - { - temp[0]=0; - return; - } - sprintf(buf, _("名前:%sにマッチ", "Monsters with a name \"%s\""),temp); - } - else if (ident_info[i]) - { - sprintf(buf, "%c - %s.", sym, ident_info[i] + 2); - } - else - { - sprintf(buf, "%c - %s", sym, _("無効な文字", "Unknown Symbol")); - } - - /* Display the result */ - prt(buf, 0, 0); - - /* Allocate the "who" array */ - C_MAKE(who, max_r_idx, MONRACE_IDX); - - /* Collect matching monsters */ - for (n = 0, i = 1; i < max_r_idx; i++) - { - monster_race *r_ptr = &r_info[i]; - - /* Nothing to recall */ - if (!cheat_know && !r_ptr->r_sights) continue; - - /* Require non-unique monsters if needed */ - if (norm && (r_ptr->flags1 & (RF1_UNIQUE))) continue; - - /* Require unique monsters if needed */ - if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) continue; - - /* Require ridable monsters if needed */ - if (ride && !(r_ptr->flags7 & (RF7_RIDING))) continue; - - /* XTRA HACK WHATSEARCH */ - if (temp[0]) - { - TERM_LEN xx; - char temp2[80]; - - for (xx = 0; temp[xx] && xx < 80; xx++) - { -#ifdef JP - if (iskanji(temp[xx])) { xx++; continue; } -#endif - if (isupper(temp[xx])) temp[xx] = (char)tolower(temp[xx]); - } - -#ifdef JP - strcpy(temp2, r_name + r_ptr->E_name); -#else - strcpy(temp2, r_name + r_ptr->name); -#endif - for (xx = 0; temp2[xx] && xx < 80; xx++) - if (isupper(temp2[xx])) temp2[xx] = (char)tolower(temp2[xx]); - -#ifdef JP - if (my_strstr(temp2, temp) || my_strstr(r_name + r_ptr->name, temp)) -#else - if (my_strstr(temp2, temp)) -#endif - who[n++] = i; - } - - /* Collect "appropriate" monsters */ - else if (all || (r_ptr->d_char == sym)) who[n++] = i; - } - - /* Nothing to recall */ - if (!n) - { - C_KILL(who, max_r_idx, MONRACE_IDX); - return; - } - - /* Prompt */ - put_str(_("思い出を見ますか? (k:殺害順/y/n): ", "Recall details? (k/y/n): "), 0, _(36, 40)); - - /* Query */ - query = inkey(); - prt(buf, 0, 0); - - why = 2; - - /* Sort the array */ - ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook); - - /* Sort by kills (and level) */ - if (query == 'k') - { - why = 4; - query = 'y'; - } - - /* Catch "escape" */ - if (query != 'y') - { - C_KILL(who, max_r_idx, MONRACE_IDX); - return; - } - - /* Sort if needed */ - if (why == 4) - { - ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook); - } - - - /* Start at the end */ - i = n - 1; - - /* Scan the monster memory */ - while (1) - { - /* Extract a race */ - r_idx = who[i]; - - /* Hack -- Auto-recall */ - monster_race_track(r_idx); - handle_stuff(); - - /* Interact */ - while (1) - { - /* Recall */ - if (recall) - { - screen_save(); - - /* Recall on screen */ - screen_roff(who[i], 0); - } - - /* Hack -- Begin the prompt */ - roff_top(r_idx); - - /* Hack -- Complete the prompt */ - Term_addstr(-1, TERM_WHITE, _(" ['r'思い出, ESC]", " [(r)ecall, ESC]")); - - /* Command */ - query = inkey(); - - /* Unrecall */ - if (recall) - { - screen_load(); - } - - /* Normal commands */ - if (query != 'r') break; - - /* Toggle recall */ - recall = !recall; - } - - /* Stop scanning */ - if (query == ESCAPE) break; - - /* Move to "prev" monster */ - if (query == '-') - { - if (++i == n) - { - i = 0; - if (!expand_list) break; - } - } - - /* Move to "next" monster */ - else - { - if (i-- == 0) - { - i = n - 1; - if (!expand_list) break; - } - } - } - - /* Free the "who" array */ - C_KILL(who, max_r_idx, IDX); - - /* Re-display the identity */ - prt(buf, 0, 0); -} - -/*! - * @brief アイテムを汎用的に「使う」コマンドのメインルーチン / - * Use an item - * @return なし - * @details - * XXX - Add actions for other item types - */ -void do_cmd_use(void) -{ - OBJECT_IDX item; - object_type *o_ptr; - concptr q, s; - - if (p_ptr->wild_mode) - { - return; - } - - if (cmd_limit_arena(p_ptr)) return; - - if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) - { - set_action(ACTION_NONE); - } - - item_tester_hook = item_tester_hook_use; - - q = _("どれを使いますか?", "Use which item? "); - s = _("使えるものがありません。", "You have nothing to use."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_EQUIP | USE_FLOOR | IGNORE_BOTHHAND_SLOT)); - if (!o_ptr) return; - - switch (o_ptr->tval) - { - /* Spike a door */ - case TV_SPIKE: - { - do_cmd_spike(); - break; - } - - /* Eat some food */ - case TV_FOOD: - { - do_cmd_eat_food_aux(item); - break; - } - - /* Aim a wand */ - case TV_WAND: - { - do_cmd_aim_wand_aux(item); - break; - } - - /* Use a staff */ - case TV_STAFF: - { - do_cmd_use_staff_aux(item); - break; - } - - /* Zap a rod */ - case TV_ROD: - { - do_cmd_zap_rod_aux(item); - break; - } - - /* Quaff a potion */ - case TV_POTION: - { - do_cmd_quaff_potion_aux(item); - break; - } - - /* Read a scroll */ - case TV_SCROLL: - { - if (cmd_limit_blind(p_ptr)) return; - if (cmd_limit_confused(p_ptr)) return; - - do_cmd_read_scroll_aux(item, TRUE); - break; - } - - /* Fire ammo */ - case TV_SHOT: - case TV_ARROW: - case TV_BOLT: - { - exe_fire(item, &inventory[INVEN_BOW], SP_NONE); - break; - } - - /* Activate an artifact */ - default: - { - do_cmd_activate_aux(item); - break; - } - } -} - diff --git a/src/cmd-item.h b/src/cmd-item.h deleted file mode 100644 index e205349a5..000000000 --- a/src/cmd-item.h +++ /dev/null @@ -1,17 +0,0 @@ -/* cmd3-item.h */ - -extern void do_cmd_inven(void); -extern void do_cmd_equip(void); -extern void do_cmd_wield(void); -extern void do_cmd_takeoff(void); -extern void do_cmd_drop(void); -extern void do_cmd_destroy(void); -extern void do_cmd_observe(void); -extern void do_cmd_uninscribe(void); -extern void do_cmd_inscribe(void); -extern void do_cmd_refill(void); -extern void do_cmd_target(void); -extern void do_cmd_look(void); -extern void do_cmd_locate(void); -extern void do_cmd_query_symbol(void); -extern void do_cmd_use(void); \ No newline at end of file diff --git a/src/cmd-item/cmd-destroy.c b/src/cmd-item/cmd-destroy.c new file mode 100644 index 000000000..a89ae7aee --- /dev/null +++ b/src/cmd-item/cmd-destroy.c @@ -0,0 +1,221 @@ +#include "cmd-item/cmd-destroy.h" +#include "autopick/autopick-registry.h" +#include "autopick/autopick.h" +#include "core/asking-player.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "floor/floor-object.h" +#include "game-option/input-options.h" +#include "inventory/inventory-object.h" +#include "inventory/inventory-slot-types.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "object-hook/hook-expendable.h" +#include "object-hook/hook-magic.h" +#include "object/item-use-flags.h" +#include "object/object-generator.h" +#include "object/object-stack.h" +#include "object/object-value.h" +#include "player/attack-defense-types.h" +#include "player-info/avatar.h" +#include "player/special-defense-types.h" +#include "racial/racial-android.h" +#include "realm/realm-names-table.h" +#include "status/action-setter.h" +#include "status/experience.h" +#include "system/object-type-definition.h" +#include "term/screen-processor.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" + +typedef struct destroy_type { + OBJECT_IDX item; + QUANTITY amt; + QUANTITY old_number; + bool force; + object_type *o_ptr; + object_type *q_ptr; + GAME_TEXT o_name[MAX_NLEN]; + char out_val[MAX_NLEN + 40]; +} destroy_type; + +static destroy_type *initialize_destroy_type(destroy_type *destroy_ptr, object_type *o_ptr) +{ + destroy_ptr->amt = 1; + destroy_ptr->force = FALSE; + destroy_ptr->q_ptr = o_ptr; + return destroy_ptr; +} + +static bool check_destory_item(player_type *creature_ptr, destroy_type *destroy_ptr) +{ + if (destroy_ptr->force || (!confirm_destroy && (object_value(creature_ptr, destroy_ptr->o_ptr) <= 0))) + return TRUE; + + describe_flavor(creature_ptr, destroy_ptr->o_name, destroy_ptr->o_ptr, OD_OMIT_PREFIX); + sprintf(destroy_ptr->out_val, _("–{“–‚É%s‚ð‰ó‚µ‚Ü‚·‚©? [y/n/Auto]", "Really destroy %s? [y/n/Auto]"), destroy_ptr->o_name); + msg_print(NULL); + message_add(destroy_ptr->out_val); + creature_ptr->window |= PW_MESSAGE; + handle_stuff(creature_ptr); + while (TRUE) { + prt(destroy_ptr->out_val, 0, 0); + char i = inkey(); + prt("", 0, 0); + if (i == 'y' || i == 'Y') + return TRUE; + + if (i == ESCAPE || i == 'n' || i == 'N') + return FALSE; + + if (i != 'A') + continue; + + if (autopick_autoregister(creature_ptr, destroy_ptr->o_ptr)) + autopick_alter_item(creature_ptr, destroy_ptr->item, TRUE); + + return FALSE; + } +} + +static bool select_destroying_item(player_type *creature_ptr, destroy_type *destroy_ptr) +{ + concptr q = _("‚ǂ̃AƒCƒeƒ€‚ð‰ó‚µ‚Ü‚·‚©? ", "Destroy which item? "); + concptr s = _("‰ó‚¹‚éƒAƒCƒeƒ€‚ðŽ‚Á‚Ä‚¢‚È‚¢B", "You have nothing to destroy."); + destroy_ptr->o_ptr = choose_object(creature_ptr, &destroy_ptr->item, q, s, USE_INVEN | USE_FLOOR, 0); + if (destroy_ptr->o_ptr == NULL) + return FALSE; + + if (!check_destory_item(creature_ptr, destroy_ptr)) + return FALSE; + + if (destroy_ptr->o_ptr->number <= 1) + return TRUE; + + destroy_ptr->amt = get_quantity(NULL, destroy_ptr->o_ptr->number); + return destroy_ptr->amt > 0; +} + +/*! + * @brief ˆê•”E‹Æ‚ō‚ˆÊ–‚–@‘‚Ì”j‰ó‚É‚æ‚éŒoŒ±’lã¸‚Ì”»’è + * @param creature_ptr ƒvƒŒ[ƒ„[‚Ö‚ÌŽQÆƒ|ƒCƒ“ƒ^ + * @param destory_ptr ƒAƒCƒeƒ€”j‰ó\‘¢‘Ì‚Ö‚ÌŽQÆƒ|ƒCƒ“ƒ^ + * return –‚–@‘‚Ì”j‰ó‚É‚æ‚Á‚ÄŒoŒ±’l‚ª“ü‚é‚È‚ç‚ÎTRUE + */ +static bool decide_magic_book_exp(player_type *creature_ptr, destroy_type *destroy_ptr) +{ + if (creature_ptr->prace == RACE_ANDROID) + return FALSE; + + if ((creature_ptr->pclass == CLASS_WARRIOR) || (creature_ptr->pclass == CLASS_BERSERKER)) + return TRUE; + + if (creature_ptr->pclass != CLASS_PALADIN) + return FALSE; + + bool gain_expr = FALSE; + if (is_good_realm(creature_ptr->realm1)) { + if (!is_good_realm(tval2realm(destroy_ptr->q_ptr->tval))) + gain_expr = TRUE; + } else { + if (is_good_realm(tval2realm(destroy_ptr->q_ptr->tval))) + gain_expr = TRUE; + } + + return gain_expr; +} + +static void gain_exp_by_destroying_magic_book(player_type *creature_ptr, destroy_type *destroy_ptr) +{ + bool gain_expr = decide_magic_book_exp(creature_ptr, destroy_ptr); + if (!gain_expr || (creature_ptr->exp >= PY_MAX_EXP)) + return; + + s32b tester_exp = creature_ptr->max_exp / 20; + if (tester_exp > 10000) + tester_exp = 10000; + + if (destroy_ptr->q_ptr->sval < 3) + tester_exp /= 4; + + if (tester_exp < 1) + tester_exp = 1; + + msg_print(_("X‚ÉŒoŒ±‚ðÏ‚ñ‚¾‚悤‚È‹C‚ª‚·‚éB", "You feel more experienced.")); + gain_exp(creature_ptr, tester_exp * destroy_ptr->amt); +} + +static void process_destroy_magic_book(player_type *creature_ptr, destroy_type *destroy_ptr) +{ + if (!item_tester_high_level_book(destroy_ptr->q_ptr)) + return; + + gain_exp_by_destroying_magic_book(creature_ptr, destroy_ptr); + if (item_tester_high_level_book(destroy_ptr->q_ptr) && destroy_ptr->q_ptr->tval == TV_LIFE_BOOK) { + chg_virtue(creature_ptr, V_UNLIFE, 1); + chg_virtue(creature_ptr, V_VITALITY, -1); + } else if (item_tester_high_level_book(destroy_ptr->q_ptr) && destroy_ptr->q_ptr->tval == TV_DEATH_BOOK) { + chg_virtue(creature_ptr, V_UNLIFE, -1); + chg_virtue(creature_ptr, V_VITALITY, 1); + } + + if ((destroy_ptr->q_ptr->to_a != 0) || (destroy_ptr->q_ptr->to_h != 0) || (destroy_ptr->q_ptr->to_d != 0)) + chg_virtue(creature_ptr, V_ENCHANT, -1); + + if (object_value_real(creature_ptr, destroy_ptr->q_ptr) > 30000) + chg_virtue(creature_ptr, V_SACRIFICE, 2); + else if (object_value_real(creature_ptr, destroy_ptr->q_ptr) > 10000) + chg_virtue(creature_ptr, V_SACRIFICE, 1); +} + +static void exe_destroy_item(player_type *creature_ptr, destroy_type *destroy_ptr) +{ + object_copy(destroy_ptr->q_ptr, destroy_ptr->o_ptr); + msg_format(_("%s‚ð‰ó‚µ‚½B", "You destroy %s."), destroy_ptr->o_name); + sound(SOUND_DESTITEM); + reduce_charges(destroy_ptr->o_ptr, destroy_ptr->amt); + vary_item(creature_ptr, destroy_ptr->item, -destroy_ptr->amt); + process_destroy_magic_book(creature_ptr, destroy_ptr); + if ((destroy_ptr->q_ptr->to_a != 0) || (destroy_ptr->q_ptr->to_d != 0) || (destroy_ptr->q_ptr->to_h != 0)) + chg_virtue(creature_ptr, V_HARMONY, 1); + + if (destroy_ptr->item >= INVEN_RARM) + calc_android_exp(creature_ptr); +} + +/*! + * @brief ƒAƒCƒeƒ€‚ð”j‰ó‚·‚éƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ / Destroy an item + * @param creature_ptr ƒvƒŒ[ƒ„[‚Ö‚ÌŽQÆƒ|ƒCƒ“ƒ^ + * @return ‚È‚µ + */ +void do_cmd_destroy(player_type *creature_ptr) +{ + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + object_type forge; + destroy_type tmp_destroy; + destroy_type *destroy_ptr = initialize_destroy_type(&tmp_destroy, &forge); + if (command_arg > 0) + destroy_ptr->force = TRUE; + + if (!select_destroying_item(creature_ptr, destroy_ptr)) + return; + + destroy_ptr->old_number = destroy_ptr->o_ptr->number; + destroy_ptr->o_ptr->number = destroy_ptr->amt; + describe_flavor(creature_ptr, destroy_ptr->o_name, destroy_ptr->o_ptr, 0); + destroy_ptr->o_ptr->number = destroy_ptr->old_number; + take_turn(creature_ptr, 100); + if (!can_player_destroy_object(creature_ptr, destroy_ptr->o_ptr)) { + free_turn(creature_ptr); + msg_format(_("%s‚Í”j‰ó•s‰Â”\‚¾B", "You cannot destroy %s."), destroy_ptr->o_name); + return; + } + + exe_destroy_item(creature_ptr, destroy_ptr); +} diff --git a/src/cmd-item/cmd-destroy.h b/src/cmd-item/cmd-destroy.h new file mode 100644 index 000000000..0d22a3111 --- /dev/null +++ b/src/cmd-item/cmd-destroy.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_destroy(player_type *creature_ptr); diff --git a/src/cmd-item/cmd-eat.c b/src/cmd-item/cmd-eat.c new file mode 100644 index 000000000..ce745b77d --- /dev/null +++ b/src/cmd-item/cmd-eat.c @@ -0,0 +1,441 @@ +/*! + * @brief プレイヤーの食べるコマンド実装 + * @date 2018/09/07 + @ @author deskull + */ + +#include "cmd-item/cmd-eat.h" +#include "core/hp-mp-processor.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "floor/floor-object.h" +#include "inventory/inventory-object.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-race/monster-race.h" +#include "object-enchant/special-object-flags.h" +#include "object-hook/hook-expendable.h" +#include "object/item-tester-hooker.h" +#include "object/item-use-flags.h" +#include "object/object-generator.h" +#include "object/object-info.h" +#include "object/object-kind-hook.h" +#include "object/object-kind.h" +#include "perception/object-perception.h" +#include "player/attack-defense-types.h" +#include "player-info/avatar.h" +#include "player/digestion-processor.h" +#include "player/mimic-info-table.h" +#include "player/player-class.h" +#include "player/player-damage.h" +#include "player/player-race-types.h" +#include "player/special-defense-types.h" +#include "spell-realm/spells-hex.h" +#include "spell/spells-status.h" +#include "status/action-setter.h" +#include "status/bad-status-setter.h" +#include "status/base-status.h" +#include "status/element-resistance.h" +#include "status/experience.h" +#include "sv-definition/sv-food-types.h" +#include "sv-definition/sv-other-types.h" +#include "util/string-processor.h" +#include "view/display-messages.h" +#include "view/object-describer.h" + +/*! + * @brief 食料を食べるコマンドのサブルーチン + * @param item 食べるオブジェクトの所持品ID + * @return なし + */ +void exe_eat_food(player_type *creature_ptr, INVENTORY_IDX item) +{ + int ident, lev; + object_type *o_ptr; + + if (music_singing_any(creature_ptr)) + stop_singing(creature_ptr); + if (hex_spelling_any(creature_ptr)) + stop_hex_spell_all(creature_ptr); + o_ptr = ref_item(creature_ptr, item); + + sound(SOUND_EAT); + + take_turn(creature_ptr, 100); + + /* Identity not known yet */ + ident = FALSE; + + /* Object level */ + lev = k_info[o_ptr->k_idx].level; + + if (o_ptr->tval == TV_FOOD) { + /* Analyze the food */ + switch (o_ptr->sval) { + case SV_FOOD_POISON: { + if (!(creature_ptr->resist_pois || is_oppose_pois(creature_ptr))) { + if (set_poisoned(creature_ptr, creature_ptr->poisoned + randint0(10) + 10)) { + ident = TRUE; + } + } + break; + } + + case SV_FOOD_BLINDNESS: { + if (!creature_ptr->resist_blind) { + if (set_blind(creature_ptr, creature_ptr->blind + randint0(200) + 200)) { + ident = TRUE; + } + } + break; + } + + case SV_FOOD_PARANOIA: { + if (!creature_ptr->resist_fear) { + if (set_afraid(creature_ptr, creature_ptr->afraid + randint0(10) + 10)) { + ident = TRUE; + } + } + break; + } + + case SV_FOOD_CONFUSION: { + if (!creature_ptr->resist_conf) { + if (set_confused(creature_ptr, creature_ptr->confused + randint0(10) + 10)) { + ident = TRUE; + } + } + break; + } + + case SV_FOOD_HALLUCINATION: { + if (!creature_ptr->resist_chaos) { + if (set_image(creature_ptr, creature_ptr->image + randint0(250) + 250)) { + ident = TRUE; + } + } + break; + } + + case SV_FOOD_PARALYSIS: { + if (!creature_ptr->free_act) { + if (set_paralyzed(creature_ptr, creature_ptr->paralyzed + randint0(10) + 10)) { + ident = TRUE; + } + } + break; + } + + case SV_FOOD_WEAKNESS: { + take_hit(creature_ptr, DAMAGE_NOESCAPE, damroll(6, 6), _("毒入り食料", "poisonous food"), -1); + (void)do_dec_stat(creature_ptr, A_STR); + ident = TRUE; + break; + } + + case SV_FOOD_SICKNESS: { + take_hit(creature_ptr, DAMAGE_NOESCAPE, damroll(6, 6), _("毒入り食料", "poisonous food"), -1); + (void)do_dec_stat(creature_ptr, A_CON); + ident = TRUE; + break; + } + + case SV_FOOD_STUPIDITY: { + take_hit(creature_ptr, DAMAGE_NOESCAPE, damroll(8, 8), _("毒入り食料", "poisonous food"), -1); + (void)do_dec_stat(creature_ptr, A_INT); + ident = TRUE; + break; + } + + case SV_FOOD_NAIVETY: { + take_hit(creature_ptr, DAMAGE_NOESCAPE, damroll(8, 8), _("毒入り食料", "poisonous food"), -1); + (void)do_dec_stat(creature_ptr, A_WIS); + ident = TRUE; + break; + } + + case SV_FOOD_UNHEALTH: { + take_hit(creature_ptr, DAMAGE_NOESCAPE, damroll(10, 10), _("毒入り食料", "poisonous food"), -1); + (void)do_dec_stat(creature_ptr, A_CON); + ident = TRUE; + break; + } + + case SV_FOOD_DISEASE: { + take_hit(creature_ptr, DAMAGE_NOESCAPE, damroll(10, 10), _("毒入り食料", "poisonous food"), -1); + (void)do_dec_stat(creature_ptr, A_STR); + ident = TRUE; + break; + } + + case SV_FOOD_CURE_POISON: { + if (set_poisoned(creature_ptr, 0)) + ident = TRUE; + break; + } + + case SV_FOOD_CURE_BLINDNESS: { + if (set_blind(creature_ptr, 0)) + ident = TRUE; + break; + } + + case SV_FOOD_CURE_PARANOIA: { + if (set_afraid(creature_ptr, 0)) + ident = TRUE; + break; + } + + case SV_FOOD_CURE_CONFUSION: { + if (set_confused(creature_ptr, 0)) + ident = TRUE; + break; + } + + case SV_FOOD_CURE_SERIOUS: { + ident = cure_serious_wounds(creature_ptr, 4, 8); + break; + } + + case SV_FOOD_RESTORE_STR: { + if (do_res_stat(creature_ptr, A_STR)) + ident = TRUE; + break; + } + + case SV_FOOD_RESTORE_CON: { + if (do_res_stat(creature_ptr, A_CON)) + ident = TRUE; + break; + } + + case SV_FOOD_RESTORING: { + ident = restore_all_status(creature_ptr); + break; + } + +#ifdef JP + /* それぞれの食べ物の感想をオリジナルより細かく表現 */ + case SV_FOOD_BISCUIT: { + msg_print("甘くてサクサクしてとてもおいしい。"); + ident = TRUE; + break; + } + + case SV_FOOD_JERKY: { + msg_print("歯ごたえがあっておいしい。"); + ident = TRUE; + break; + } + + case SV_FOOD_SLIME_MOLD: { + msg_print("これはなんとも形容しがたい味だ。"); + ident = TRUE; + break; + } + + case SV_FOOD_RATION: { + msg_print("これはおいしい。"); + ident = TRUE; + break; + } +#else + case SV_FOOD_RATION: + case SV_FOOD_BISCUIT: + case SV_FOOD_JERKY: + case SV_FOOD_SLIME_MOLD: { + msg_print("That tastes good."); + ident = TRUE; + break; + } +#endif + + case SV_FOOD_WAYBREAD: { + msg_print(_("これはひじょうに美味だ。", "That tastes good.")); + (void)set_poisoned(creature_ptr, 0); + (void)hp_player(creature_ptr, damroll(4, 8)); + ident = TRUE; + break; + } + + case SV_FOOD_PINT_OF_ALE: { + msg_print(_("のどごし爽やかだ。", "That tastes good.")); + ident = TRUE; + break; + } + + case SV_FOOD_PINT_OF_WINE: { + msg_print(_("のどごし爽やかだ。", "That tastes good.")); + ident = TRUE; + break; + } + } + } + + /* + * Store what may have to be updated for the inventory (including + * autodestroy if set by something else). Then turn off those flags + * so that updates triggered by calling gain_exp() or set_food() below + * do not rearrange the inventory before the food item is destroyed in + * the pack. + */ + BIT_FLAGS inventory_flags = (PU_COMBINE | PU_REORDER | (creature_ptr->update & PU_AUTODESTROY)); + creature_ptr->update &= ~(PU_COMBINE | PU_REORDER | PU_AUTODESTROY); + + if (!(object_is_aware(o_ptr))) { + chg_virtue(creature_ptr, V_KNOWLEDGE, -1); + chg_virtue(creature_ptr, V_PATIENCE, -1); + chg_virtue(creature_ptr, V_CHANCE, 1); + } + + /* We have tried it */ + if (o_ptr->tval == TV_FOOD) + object_tried(o_ptr); + + /* The player is now aware of the object */ + if (ident && !object_is_aware(o_ptr)) { + object_aware(creature_ptr, o_ptr); + gain_exp(creature_ptr, (lev + (creature_ptr->lev >> 1)) / creature_ptr->lev); + } + + creature_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + /* Food can feed the player */ + if (is_specific_player_race(creature_ptr, RACE_VAMPIRE) || (creature_ptr->mimic_form == MIMIC_VAMPIRE)) { + /* Reduced nutritional benefit */ + (void)set_food(creature_ptr, creature_ptr->food + (o_ptr->pval / 10)); + msg_print(_("あなたのような者にとって食糧など僅かな栄養にしかならない。", "Mere victuals hold scant sustenance for a being such as yourself.")); + + if (creature_ptr->food < PY_FOOD_ALERT) /* Hungry */ + msg_print(_("あなたの飢えは新鮮な血によってのみ満たされる!", "Your hunger can only be satisfied with fresh blood!")); + } else if ((is_specific_player_race(creature_ptr, RACE_SKELETON) || is_specific_player_race(creature_ptr, RACE_GOLEM) + || is_specific_player_race(creature_ptr, RACE_ZOMBIE) || is_specific_player_race(creature_ptr, RACE_SPECTRE)) + && (o_ptr->tval == TV_STAFF || o_ptr->tval == TV_WAND)) { + concptr staff; + + if (o_ptr->tval == TV_STAFF && (item < 0) && (o_ptr->number > 1)) { + creature_ptr->update |= inventory_flags; + msg_print(_("まずは杖を拾わなければ。", "You must first pick up the staffs.")); + return; + } + staff = (o_ptr->tval == TV_STAFF) ? _("杖", "staff") : _("魔法棒", "wand"); + + /* "Eat" charges */ + if (o_ptr->pval == 0) { + msg_format(_("この%sにはもう魔力が残っていない。", "The %s has no charges left."), staff); + o_ptr->ident |= (IDENT_EMPTY); + creature_ptr->update |= inventory_flags; + creature_ptr->window |= (PW_INVEN); + + return; + } + msg_format(_("あなたは%sの魔力をエネルギー源として吸収した。", "You absorb mana of the %s as your energy."), staff); + + /* Use a single charge */ + o_ptr->pval--; + + /* Eat a charge */ + set_food(creature_ptr, creature_ptr->food + 5000); + + /* XXX Hack -- unstack if necessary */ + if (o_ptr->tval == TV_STAFF && (item >= 0) && (o_ptr->number > 1)) { + object_type forge; + object_type *q_ptr; + q_ptr = &forge; + object_copy(q_ptr, o_ptr); + + /* Modify quantity */ + q_ptr->number = 1; + + /* Restore the charges */ + o_ptr->pval++; + + /* Unstack the used item */ + o_ptr->number--; + creature_ptr->total_weight -= q_ptr->weight; + item = store_item_to_inventory(creature_ptr, q_ptr); + + msg_format(_("杖をまとめなおした。", "You unstack your staff.")); + } + + /* Describe charges in the pack */ + if (item >= 0) { + inven_item_charges(creature_ptr, item); + } + + /* Describe charges on the floor */ + else { + floor_item_charges(creature_ptr->current_floor_ptr, 0 - item); + } + + creature_ptr->window |= (PW_INVEN | PW_EQUIP); + creature_ptr->update |= inventory_flags; + + /* Don't eat a staff/wand itself */ + return; + } + + if ((is_specific_player_race(creature_ptr, RACE_BALROG) || (mimic_info[creature_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_DEMON)) + && (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_CORPSE && angband_strchr("pht", r_info[o_ptr->pval].d_char))) { + /* Drain vitality of humanoids */ + GAME_TEXT o_name[MAX_NLEN]; + describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); + msg_format(_("%sは燃え上り灰になった。精力を吸収した気がする。", "%^s is burnt to ashes. You absorb its vitality!"), o_name); + (void)set_food(creature_ptr, PY_FOOD_MAX - 1); + } else if (is_specific_player_race(creature_ptr, RACE_SKELETON)) { + if (!((o_ptr->sval == SV_FOOD_WAYBREAD) || (o_ptr->sval < SV_FOOD_BISCUIT))) { + object_type forge; + object_type *q_ptr = &forge; + + msg_print(_("食べ物がアゴを素通りして落ちた!", "The food falls through your jaws!")); + object_prep(creature_ptr, q_ptr, lookup_kind(o_ptr->tval, o_ptr->sval)); + + /* Drop the object from heaven */ + (void)drop_near(creature_ptr, q_ptr, -1, creature_ptr->y, creature_ptr->x); + } else { + msg_print(_("食べ物がアゴを素通りして落ち、消えた!", "The food falls through your jaws and vanishes!")); + } + } else if (is_specific_player_race(creature_ptr, RACE_GOLEM) || is_specific_player_race(creature_ptr, RACE_ZOMBIE) + || is_specific_player_race(creature_ptr, RACE_ENT) || is_specific_player_race(creature_ptr, RACE_BALROG) + || is_specific_player_race(creature_ptr, RACE_ANDROID) || is_specific_player_race(creature_ptr, RACE_SPECTRE) + || (mimic_info[creature_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING)) { + msg_print(_("生者の食物はあなたにとってほとんど栄養にならない。", "The food of mortals is poor sustenance for you.")); + set_food(creature_ptr, creature_ptr->food + ((o_ptr->pval) / 20)); + } else if (o_ptr->tval == TV_FOOD && o_ptr->sval == SV_FOOD_WAYBREAD) { + /* Waybread is always fully satisfying. */ + set_food(creature_ptr, MAX(creature_ptr->food, PY_FOOD_MAX - 1)); + } else { + /* Food can feed the player */ + (void)set_food(creature_ptr, creature_ptr->food + o_ptr->pval); + } + + creature_ptr->update |= inventory_flags; + vary_item(creature_ptr, item, -1); +} + +/*! + * @brief 食料を食べるコマンドのメインルーチン / + * Eat some food (from the pack or floor) + * @return なし + */ +void do_cmd_eat_food(player_type *creature_ptr) +{ + OBJECT_IDX item; + concptr q, s; + + if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) { + set_action(creature_ptr, ACTION_NONE); + } + + item_tester_hook = item_tester_hook_eatable; + + q = _("どれを食べますか? ", "Eat which item? "); + s = _("食べ物がない。", "You have nothing to eat."); + + if (!choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), 0)) + return; + + exe_eat_food(creature_ptr, item); +} diff --git a/src/cmd-item/cmd-eat.h b/src/cmd-item/cmd-eat.h new file mode 100644 index 000000000..e95486d5a --- /dev/null +++ b/src/cmd-item/cmd-eat.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_eat_food(player_type *creature_ptr); +void exe_eat_food(player_type *creature_ptr, INVENTORY_IDX item); diff --git a/src/cmd-item/cmd-equipment.c b/src/cmd-item/cmd-equipment.c new file mode 100644 index 000000000..688bebc77 --- /dev/null +++ b/src/cmd-item/cmd-equipment.c @@ -0,0 +1,337 @@ +#include "cmd-item/cmd-equipment.h" +#include "action/weapon-shield.h" +#include "art-definition/art-protector-types.h" +#include "autopick/autopick.h" +#include "core/asking-player.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" +#include "dungeon/quest.h" // todo ˆá˜aŠ´A‰½ŒÌƒAƒCƒeƒ€‚ð‘•”õ‚·‚é‚ƃNƒGƒXƒg‚̐¬Œ÷”»’肪‘–‚é‚Ì‚©H. +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "floor/floor-object.h" +#include "game-option/birth-options.h" +#include "game-option/input-options.h" +#include "inventory/inventory-describer.h" +#include "inventory/inventory-object.h" +#include "inventory/inventory-slot-types.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "object-enchant/item-feeling.h" +#include "object-enchant/special-object-flags.h" +#include "object-enchant/trc-types.h" +#include "object-hook/hook-armor.h" +#include "object-hook/hook-checker.h" +#include "object-hook/hook-weapon.h" +#include "object/item-tester-hooker.h" +#include "object/item-use-flags.h" +#include "object/object-generator.h" +#include "object/object-info.h" +#include "object/object-mark-types.h" +#include "perception/object-perception.h" +#include "player/attack-defense-types.h" +#include "player-info/avatar.h" +#include "player/special-defense-types.h" +#include "racial/racial-android.h" +#include "spell-kind/spells-perception.h" +#include "status/action-setter.h" +#include "status/shape-changer.h" +#include "system/object-type-definition.h" +#include "term/screen-processor.h" +#include "util/int-char-converter.h" +#include "view/display-inventory.h" +#include "view/display-messages.h" + +/*! + * @brief ‘•”õˆê——‚ð•\Ž¦‚·‚éƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ / Display equipment + * @return ‚È‚µ + */ +void do_cmd_equip(player_type *creature_ptr) +{ + char out_val[160]; + command_wrk = TRUE; + if (easy_floor) + command_wrk = USE_EQUIP; + + screen_save(); + (void)show_equipment(creature_ptr, 0, USE_FULL, 0); +#ifdef JP + sprintf(out_val, "‘•”õF ‡Œv %3d.%1d kg (ŒÀŠE‚Ì%ld%%) ƒRƒ}ƒ“ƒh: ", (int)lbtokg1(creature_ptr->total_weight), (int)lbtokg2(creature_ptr->total_weight), + (long int)((creature_ptr->total_weight * 100) / weight_limit(creature_ptr))); +#else + sprintf(out_val, "Equipment: carrying %d.%d pounds (%ld%% of capacity). Command: ", (int)(creature_ptr->total_weight / 10), + (int)(creature_ptr->total_weight % 10), (long int)((creature_ptr->total_weight * 100) / weight_limit(creature_ptr))); +#endif + + prt(out_val, 0, 0); + command_new = inkey(); + screen_load(); + + if (command_new != ESCAPE) { + command_see = TRUE; + return; + } + + TERM_LEN wid, hgt; + term_get_size(&wid, &hgt); + command_new = 0; + command_gap = wid - 30; +} + +bool select_ring_slot = FALSE; + +/*! + * @brief ‘•”õ‚·‚éƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ / Wield or wear a single item from the pack or floor + * @param creature_ptr ƒvƒŒ[ƒ„[‚Ö‚ÌŽQÆƒ|ƒCƒ“ƒ^ + * @return ‚È‚µ + */ +void do_cmd_wield(player_type *creature_ptr) +{ + OBJECT_IDX item, slot; + object_type forge; + object_type *q_ptr; + object_type *o_ptr; + concptr act; + GAME_TEXT o_name[MAX_NLEN]; + OBJECT_IDX need_switch_wielding = 0; + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + item_tester_hook = item_tester_hook_wear; + concptr q = _("‚Ç‚ê‚ð‘•”õ‚µ‚Ü‚·‚©? ", "Wear/Wield which item? "); + concptr s = _("‘•”õ‰Â”\‚ȃAƒCƒeƒ€‚ª‚È‚¢B", "You have nothing you can wear or wield."); + o_ptr = choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), 0); + if (!o_ptr) + return; + + slot = wield_slot(creature_ptr, o_ptr); + + switch (o_ptr->tval) { + case TV_CAPTURE: + case TV_SHIELD: + case TV_CARD: + if (has_melee_weapon(creature_ptr, INVEN_RARM) && has_melee_weapon(creature_ptr, INVEN_LARM)) { + item_tester_hook = item_tester_hook_melee_weapon; + q = _("‚Ç‚¿‚ç‚Ì•Ší‚ÆŽæ‚è‘Ö‚¦‚Ü‚·‚©?", "Replace which weapon? "); + s = _("‚¨‚Á‚ƁB", "Oops."); + if (!choose_object(creature_ptr, &slot, q, s, (USE_EQUIP | IGNORE_BOTHHAND_SLOT), 0)) + return; + + if (slot == INVEN_RARM) + need_switch_wielding = INVEN_LARM; + } else if (has_melee_weapon(creature_ptr, INVEN_LARM)) + slot = INVEN_RARM; + else if (creature_ptr->inventory_list[INVEN_RARM].k_idx && !object_is_melee_weapon(&creature_ptr->inventory_list[INVEN_RARM]) + && creature_ptr->inventory_list[INVEN_LARM].k_idx && !object_is_melee_weapon(&creature_ptr->inventory_list[INVEN_LARM])) { + item_tester_hook = item_tester_hook_mochikae; + q = _("‚Ç‚¿‚ç‚ÌŽè‚É‘•”õ‚µ‚Ü‚·‚©?", "Equip which hand? "); + s = _("‚¨‚Á‚ƁB", "Oops."); + if (!choose_object(creature_ptr, &slot, q, s, (USE_EQUIP), 0)) + return; + } + + break; + case TV_DIGGING: + case TV_HAFTED: + case TV_POLEARM: + case TV_SWORD: + if (slot == INVEN_LARM) { + if (!get_check(_("“ñ“—¬‚Ő킢‚Ü‚·‚©H", "Dual wielding? "))) + slot = INVEN_RARM; + } else if (!creature_ptr->inventory_list[INVEN_RARM].k_idx && has_melee_weapon(creature_ptr, INVEN_LARM)) { + if (!get_check(_("“ñ“—¬‚Ő킢‚Ü‚·‚©H", "Dual wielding? "))) + slot = INVEN_LARM; + } else if (creature_ptr->inventory_list[INVEN_LARM].k_idx && creature_ptr->inventory_list[INVEN_RARM].k_idx) { + item_tester_hook = item_tester_hook_mochikae; + q = _("‚Ç‚¿‚ç‚ÌŽè‚É‘•”õ‚µ‚Ü‚·‚©?", "Equip which hand? "); + s = _("‚¨‚Á‚ƁB", "Oops."); + if (!choose_object(creature_ptr, &slot, q, s, (USE_EQUIP), 0)) + return; + + if ((slot == INVEN_LARM) && !has_melee_weapon(creature_ptr, INVEN_RARM)) + need_switch_wielding = INVEN_RARM; + } + + break; + case TV_RING: + if (creature_ptr->inventory_list[INVEN_LEFT].k_idx && creature_ptr->inventory_list[INVEN_RIGHT].k_idx) + q = _("‚Ç‚¿‚ç‚ÌŽw—Ö‚ÆŽæ‚è‘Ö‚¦‚Ü‚·‚©?", "Replace which ring? "); + else + q = _("‚Ç‚¿‚ç‚ÌŽè‚É‘•”õ‚µ‚Ü‚·‚©?", "Equip which hand? "); + + s = _("‚¨‚Á‚ƁB", "Oops."); + select_ring_slot = TRUE; + if (!choose_object(creature_ptr, &slot, q, s, (USE_EQUIP | IGNORE_BOTHHAND_SLOT), 0)) { + select_ring_slot = FALSE; + return; + } + + select_ring_slot = FALSE; + break; + } + + if (object_is_cursed(&creature_ptr->inventory_list[slot])) { + describe_flavor(creature_ptr, o_name, &creature_ptr->inventory_list[slot], OD_OMIT_PREFIX | OD_NAME_ONLY); +#ifdef JP + msg_format("%s%s‚ÍŽô‚í‚ê‚Ä‚¢‚é‚悤‚¾B", describe_use(creature_ptr, slot), o_name); +#else + msg_format("The %s you are %s appears to be cursed.", o_name, describe_use(creature_ptr, slot)); +#endif + return; + } + + if (confirm_wear + && ((object_is_cursed(o_ptr) && object_is_known(o_ptr)) + || ((o_ptr->ident & IDENT_SENSE) && (FEEL_BROKEN <= o_ptr->feeling) && (o_ptr->feeling <= FEEL_CURSED)))) { + char dummy[MAX_NLEN + 80]; + describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); + sprintf(dummy, _("–{“–‚É%s{Žô‚í‚ê‚Ä‚¢‚é}‚ðŽg‚¢‚Ü‚·‚©H", "Really use the %s {cursed}? "), o_name); + + if (!get_check(dummy)) + return; + } + + if ((o_ptr->name1 == ART_STONEMASK) && object_is_known(o_ptr) && (creature_ptr->prace != RACE_VAMPIRE) && (creature_ptr->prace != RACE_ANDROID)) { + char dummy[MAX_NLEN + 100]; + describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); + sprintf(dummy, + _("%s‚ð‘•”õ‚·‚é‚Æ‹zŒŒ‹S‚É‚È‚è‚Ü‚·B‚æ‚낵‚¢‚Å‚·‚©H", "%s will transforms you into a vampire permanently when equiped. Do you become a vampire?"), + o_name); + + if (!get_check(dummy)) + return; + } + + if (need_switch_wielding && !object_is_cursed(&creature_ptr->inventory_list[need_switch_wielding])) { + object_type *slot_o_ptr = &creature_ptr->inventory_list[slot]; + object_type *switch_o_ptr = &creature_ptr->inventory_list[need_switch_wielding]; + object_type object_tmp; + object_type *otmp_ptr = &object_tmp; + GAME_TEXT switch_name[MAX_NLEN]; + describe_flavor(creature_ptr, switch_name, switch_o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); + object_copy(otmp_ptr, switch_o_ptr); + object_copy(switch_o_ptr, slot_o_ptr); + object_copy(slot_o_ptr, otmp_ptr); + msg_format(_("%s‚ð%s‚ɍ\‚¦‚È‚¨‚µ‚½B", "You wield %s at %s hand."), switch_name, + (slot == INVEN_RARM) ? (left_hander ? _("¶Žè", "left") : _("‰EŽè", "right")) : (left_hander ? _("‰EŽè", "right") : _("¶Žè", "left"))); + slot = need_switch_wielding; + } + + check_find_art_quest_completion(creature_ptr, o_ptr); + if (creature_ptr->pseikaku == PERSONALITY_MUNCHKIN) { + identify_item(creature_ptr, o_ptr); + autopick_alter_item(creature_ptr, item, FALSE); + } + + take_turn(creature_ptr, 100); + q_ptr = &forge; + object_copy(q_ptr, o_ptr); + q_ptr->number = 1; + if (item >= 0) { + inven_item_increase(creature_ptr, item, -1); + inven_item_optimize(creature_ptr, item); + } else { + floor_item_increase(creature_ptr->current_floor_ptr, 0 - item, -1); + floor_item_optimize(creature_ptr, 0 - item); + } + + o_ptr = &creature_ptr->inventory_list[slot]; + if (o_ptr->k_idx) + (void)inven_takeoff(creature_ptr, slot, 255); + + object_copy(o_ptr, q_ptr); + o_ptr->marked |= OM_TOUCHED; + creature_ptr->total_weight += q_ptr->weight; + creature_ptr->equip_cnt++; + +#define STR_WIELD_RARM _("%s(%c)‚ð‰EŽè‚É‘•”õ‚µ‚½B", "You are wielding %s (%c) in your right hand.") +#define STR_WIELD_LARM _("%s(%c)‚ð¶Žè‚É‘•”õ‚µ‚½B", "You are wielding %s (%c) in your left hand.") +#define STR_WIELD_ARMS _("%s(%c)‚𗼎è‚ō\‚¦‚½B", "You are wielding %s (%c) with both hands.") + + switch (slot) { + case INVEN_RARM: + if (object_allow_two_hands_wielding(o_ptr) && (empty_hands(creature_ptr, FALSE) == EMPTY_HAND_LARM) && can_two_hands_wielding(creature_ptr)) + act = STR_WIELD_ARMS; + else + act = (left_hander ? STR_WIELD_LARM : STR_WIELD_RARM); + + break; + case INVEN_LARM: + if (object_allow_two_hands_wielding(o_ptr) && (empty_hands(creature_ptr, FALSE) == EMPTY_HAND_RARM) && can_two_hands_wielding(creature_ptr)) + act = STR_WIELD_ARMS; + else + act = (left_hander ? STR_WIELD_RARM : STR_WIELD_LARM); + + break; + case INVEN_BOW: + act = _("%s(%c)‚ðŽËŒ‚—p‚É‘•”õ‚µ‚½B", "You are shooting with %s (%c)."); + break; + case INVEN_LITE: + act = _("%s(%c)‚ðŒõŒ¹‚É‚µ‚½B", "Your light source is %s (%c)."); + break; + default: + act = _("%s(%c)‚ð‘•”õ‚µ‚½B", "You are wearing %s (%c)."); + break; + } + + describe_flavor(creature_ptr, o_name, o_ptr, 0); + msg_format(act, o_name, index_to_label(slot)); + if (object_is_cursed(o_ptr)) { + msg_print(_("‚¤‚íI ‚·‚³‚Ü‚¶‚­—₽‚¢I", "Oops! It feels deathly cold!")); + chg_virtue(creature_ptr, V_HARMONY, -1); + o_ptr->ident |= (IDENT_SENSE); + } + + if ((o_ptr->name1 == ART_STONEMASK) && (creature_ptr->prace != RACE_VAMPIRE) && (creature_ptr->prace != RACE_ANDROID)) + change_race(creature_ptr, RACE_VAMPIRE, ""); + + creature_ptr->update |= PU_BONUS | PU_TORCH | PU_MANA; + creature_ptr->redraw |= PR_EQUIPPY; + creature_ptr->window |= PW_INVEN | PW_EQUIP | PW_PLAYER; + calc_android_exp(creature_ptr); +} + +/*! + * @brief ‘•”õ‚ðŠO‚·ƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ / Take off an item + * @return ‚È‚µ + */ +void do_cmd_takeoff(player_type *creature_ptr) +{ + OBJECT_IDX item; + object_type *o_ptr; + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + concptr q = _("‚Ç‚ê‚ð‘•”õ‚©‚ç‚Í‚¸‚µ‚Ü‚·‚©? ", "Take off which item? "); + concptr s = _("‚Í‚¸‚¹‚é‘•”õ‚ª‚È‚¢B", "You are not wearing anything to take off."); + o_ptr = choose_object(creature_ptr, &item, q, s, (USE_EQUIP | IGNORE_BOTHHAND_SLOT), 0); + if (!o_ptr) + return; + + if (object_is_cursed(o_ptr)) { + if ((o_ptr->curse_flags & TRC_PERMA_CURSE) || (creature_ptr->pclass != CLASS_BERSERKER)) { + msg_print(_("‚Ӂ[‚ށA‚Ç‚¤‚â‚çŽô‚í‚ê‚Ä‚¢‚é‚悤‚¾B", "Hmmm, it seems to be cursed.")); + return; + } + + if (((o_ptr->curse_flags & TRC_HEAVY_CURSE) && one_in_(7)) || one_in_(4)) { + msg_print(_("Žô‚í‚ꂽ‘•”õ‚ð—͂­‚Å”‚ª‚µ‚½I", "You tore off a piece of cursed equipment by sheer strength!")); + o_ptr->ident |= (IDENT_SENSE); + o_ptr->curse_flags = 0L; + o_ptr->feeling = FEEL_NONE; + creature_ptr->update |= PU_BONUS; + creature_ptr->window |= PW_EQUIP; + msg_print(_("Žô‚¢‚ð‘Å‚¿”j‚Á‚½B", "You break the curse.")); + } else { + msg_print(_("‘•”õ‚ðŠO‚¹‚È‚©‚Á‚½B", "You couldn't remove the equipment.")); + take_turn(creature_ptr, 50); + return; + } + } + + take_turn(creature_ptr, 50); + (void)inven_takeoff(creature_ptr, item, 255); + verify_equip_slot(creature_ptr, item); + calc_android_exp(creature_ptr); + creature_ptr->redraw |= PR_EQUIPPY; +} diff --git a/src/cmd-item/cmd-equipment.h b/src/cmd-item/cmd-equipment.h new file mode 100644 index 000000000..4b84ad3f4 --- /dev/null +++ b/src/cmd-item/cmd-equipment.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_equip(player_type *creature_ptr); +void do_cmd_wield(player_type *creature_ptr); +void do_cmd_takeoff(player_type *creature_ptr); diff --git a/src/cmd-item/cmd-item.c b/src/cmd-item/cmd-item.c new file mode 100644 index 000000000..085ba40b9 --- /dev/null +++ b/src/cmd-item/cmd-item.c @@ -0,0 +1,305 @@ +/*! + * @brief プレイヤーのアイテムに関するコマンドの実装1 / Inventory and equipment commands + * @date 2014/01/02 + * @author + * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke + * + * This software may be copied and distributed for educational, research, + * and not for profit purposes provided that this copyright and statement + * are included in all such copies. Other copyrights may also apply. + */ + +#include "cmd-item/cmd-item.h" +#include "action/action-limited.h" +#include "action/activation-execution.h" +#include "action/weapon-shield.h" +#include "cmd-action/cmd-open-close.h" +#include "cmd-action/cmd-pet.h" +#include "cmd-item/cmd-eat.h" +#include "cmd-item/cmd-quaff.h" +#include "cmd-item/cmd-read.h" +#include "cmd-item/cmd-usestaff.h" +#include "cmd-item/cmd-zaprod.h" +#include "cmd-item/cmd-zapwand.h" +#include "combat/shoot.h" +#include "core/asking-player.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "floor/floor-object.h" +#include "game-option/input-options.h" +#include "inventory/inventory-object.h" +#include "inventory/inventory-slot-types.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "mind/snipe-types.h" +#include "object-activation/activation-switcher.h" +#include "object-hook/hook-checker.h" +#include "object-hook/hook-magic.h" +#include "object-use/quaff-execution.h" +#include "object-use/read-execution.h" +#include "object/item-tester-hooker.h" +#include "object/item-use-flags.h" +#include "perception/identification.h" +#include "perception/object-perception.h" +#include "player-info/self-info.h" +#include "player/attack-defense-types.h" +#include "player/player-class.h" +#include "player/player-personalities-types.h" +#include "player/player-race-types.h" +#include "player/player-status.h" +#include "player/special-defense-types.h" +#include "racial/racial-android.h" +#include "realm/realm-hex-numbers.h" +#include "realm/realm-types.h" +#include "status/action-setter.h" +#include "term/screen-processor.h" +#include "util/int-char-converter.h" +#include "util/quarks.h" +#include "view/display-inventory.h" +#include "view/display-messages.h" + +/*! + * @brief 持ち物一覧を表示するコマンドのメインルーチン / Display inventory_list + * @return なし + */ +void do_cmd_inven(player_type *creature_ptr) +{ + char out_val[160]; + command_wrk = FALSE; + if (easy_floor) + command_wrk = USE_INVEN; + + screen_save(); + (void)show_inventory(creature_ptr, 0, USE_FULL, 0); +#ifdef JP + sprintf(out_val, "持ち物: 合計 %3d.%1d kg (限界の%ld%%) コマンド: ", (int)lbtokg1(creature_ptr->total_weight), (int)lbtokg2(creature_ptr->total_weight), +#else + sprintf(out_val, "Inventory: carrying %d.%d pounds (%ld%% of capacity). Command: ", (int)(creature_ptr->total_weight / 10), + (int)(creature_ptr->total_weight % 10), +#endif + (long int)(creature_ptr->total_weight * 100) / weight_limit(creature_ptr)); + + prt(out_val, 0, 0); + command_new = inkey(); + screen_load(); + if (command_new != ESCAPE) { + command_see = TRUE; + return; + } + + TERM_LEN wid, hgt; + term_get_size(&wid, &hgt); + command_new = 0; + command_gap = wid - 30; +} + +/*! + * @brief アイテムを落とすコマンドのメインルーチン / Drop an item + * @return なし + */ +void do_cmd_drop(player_type *creature_ptr) +{ + OBJECT_IDX item; + int amt = 1; + object_type *o_ptr; + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + concptr q = _("どのアイテムを落としますか? ", "Drop which item? "); + concptr s = _("落とせるアイテムを持っていない。", "You have nothing to drop."); + o_ptr = choose_object(creature_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | IGNORE_BOTHHAND_SLOT), 0); + if (!o_ptr) + return; + + if ((item >= INVEN_RARM) && object_is_cursed(o_ptr)) { + msg_print(_("ふーむ、どうやら呪われているようだ。", "Hmmm, it seems to be cursed.")); + return; + } + + if (o_ptr->number > 1) { + amt = get_quantity(NULL, o_ptr->number); + if (amt <= 0) + return; + } + + take_turn(creature_ptr, 50); + drop_from_inventory(creature_ptr, item, amt); + if (item >= INVEN_RARM) { + verify_equip_slot(creature_ptr, item); + calc_android_exp(creature_ptr); + } + + creature_ptr->redraw |= (PR_EQUIPPY); +} + +/*! + * @brief アイテムを調査するコマンドのメインルーチン / Observe an item which has been *identify*-ed + * @return なし + */ +void do_cmd_observe(player_type *creature_ptr) +{ + OBJECT_IDX item; + object_type *o_ptr; + GAME_TEXT o_name[MAX_NLEN]; + concptr q = _("どのアイテムを調べますか? ", "Examine which item? "); + concptr s = _("調べられるアイテムがない。", "You have nothing to examine."); + o_ptr = choose_object(creature_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0); + if (!o_ptr) + return; + + if (!object_is_fully_known(o_ptr)) { + msg_print(_("このアイテムについて特に知っていることはない。", "You have no special knowledge about that item.")); + return; + } + + describe_flavor(creature_ptr, o_name, o_ptr, 0); + msg_format(_("%sを調べている...", "Examining %s..."), o_name); + if (!screen_object(creature_ptr, o_ptr, SCROBJ_FORCE_DETAIL)) + msg_print(_("特に変わったところはないようだ。", "You see nothing special.")); +} + +/*! + * @brief アイテムの銘を消すコマンドのメインルーチン + * Remove the inscription from an object XXX Mention item (when done)? + * @return なし + */ +void do_cmd_uninscribe(player_type *creature_ptr) +{ + OBJECT_IDX item; + object_type *o_ptr; + concptr q = _("どのアイテムの銘を消しますか? ", "Un-inscribe which item? "); + concptr s = _("銘を消せるアイテムがない。", "You have nothing to un-inscribe."); + o_ptr = choose_object(creature_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0); + if (!o_ptr) + return; + + if (!o_ptr->inscription) { + msg_print(_("このアイテムには消すべき銘がない。", "That item had no inscription to remove.")); + return; + } + + msg_print(_("銘を消した。", "Inscription removed.")); + o_ptr->inscription = 0; + creature_ptr->update |= (PU_COMBINE); + creature_ptr->window |= (PW_INVEN | PW_EQUIP); + creature_ptr->update |= (PU_BONUS); +} + +/*! + * @brief アイテムの銘を刻むコマンドのメインルーチン + * Inscribe an object with a comment + * @return なし + */ +void do_cmd_inscribe(player_type *creature_ptr) +{ + OBJECT_IDX item; + object_type *o_ptr; + GAME_TEXT o_name[MAX_NLEN]; + char out_val[80]; + concptr q = _("どのアイテムに銘を刻みますか? ", "Inscribe which item? "); + concptr s = _("銘を刻めるアイテムがない。", "You have nothing to inscribe."); + o_ptr = choose_object(creature_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0); + if (!o_ptr) + return; + + describe_flavor(creature_ptr, o_name, o_ptr, OD_OMIT_INSCRIPTION); + msg_format(_("%sに銘を刻む。", "Inscribing %s."), o_name); + msg_print(NULL); + strcpy(out_val, ""); + if (o_ptr->inscription) + strcpy(out_val, quark_str(o_ptr->inscription)); + + if (get_string(_("銘: ", "Inscription: "), out_val, 80)) { + o_ptr->inscription = quark_add(out_val); + creature_ptr->update |= (PU_COMBINE); + creature_ptr->window |= (PW_INVEN | PW_EQUIP); + creature_ptr->update |= (PU_BONUS); + } +} + +/*! + * @brief アイテムを汎用的に「使う」コマンドのメインルーチン / + * Use an item + * @return なし + * @details + * XXX - Add actions for other item types + */ +void do_cmd_use(player_type *creature_ptr) +{ + OBJECT_IDX item; + object_type *o_ptr; + if (creature_ptr->wild_mode || cmd_limit_arena(creature_ptr)) + return; + + if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) + set_action(creature_ptr, ACTION_NONE); + + item_tester_hook = item_tester_hook_use; + concptr q = _("どれを使いますか?", "Use which item? "); + concptr s = _("使えるものがありません。", "You have nothing to use."); + o_ptr = choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_EQUIP | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0); + if (!o_ptr) + return; + + switch (o_ptr->tval) { + case TV_SPIKE: + do_cmd_spike(creature_ptr); + break; + case TV_FOOD: + exe_eat_food(creature_ptr, item); + break; + case TV_WAND: + exe_aim_wand(creature_ptr, item); + break; + case TV_STAFF: + exe_use_staff(creature_ptr, item); + break; + case TV_ROD: + exe_zap_rod(creature_ptr, item); + break; + case TV_POTION: + exe_quaff_potion(creature_ptr, item); + break; + case TV_SCROLL: + if (cmd_limit_blind(creature_ptr) || cmd_limit_confused(creature_ptr)) + return; + + exe_read(creature_ptr, item, TRUE); + break; + case TV_SHOT: + case TV_ARROW: + case TV_BOLT: + exe_fire(creature_ptr, item, &creature_ptr->inventory_list[INVEN_BOW], SP_NONE); + break; + default: + exe_activate(creature_ptr, item); + break; + } +} + +/*! + * @brief 装備を発動するコマンドのメインルーチン / + * @param user_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void do_cmd_activate(player_type *user_ptr) +{ + OBJECT_IDX item; + if (user_ptr->wild_mode || cmd_limit_arena(user_ptr)) + return; + + if (user_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) + set_action(user_ptr, ACTION_NONE); + + item_tester_hook = item_tester_hook_activate; + + concptr q = _("どのアイテムを始動させますか? ", "Activate which item? "); + concptr s = _("始動できるアイテムを装備していない。", "You have nothing to activate."); + if (!choose_object(user_ptr, &item, q, s, (USE_EQUIP | IGNORE_BOTHHAND_SLOT), 0)) + return; + + exe_activate(user_ptr, item); +} diff --git a/src/cmd-item/cmd-item.h b/src/cmd-item/cmd-item.h new file mode 100644 index 000000000..e93e4c586 --- /dev/null +++ b/src/cmd-item/cmd-item.h @@ -0,0 +1,11 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_inven(player_type *creature_ptr); +void do_cmd_drop(player_type *creature_ptr); +void do_cmd_observe(player_type *creature_ptr); +void do_cmd_uninscribe(player_type *creature_ptr); +void do_cmd_inscribe(player_type *creature_ptr); +void do_cmd_use(player_type *creature_ptr); +void do_cmd_activate(player_type *user_ptr); diff --git a/src/cmd-item/cmd-magiceat.c b/src/cmd-item/cmd-magiceat.c new file mode 100644 index 000000000..625893722 --- /dev/null +++ b/src/cmd-item/cmd-magiceat.c @@ -0,0 +1,607 @@ +/*! + * @brief プレイヤーのアイテムに関するコマンドの実装2 / Spell/Prayer commands + * @date 2014/01/27 + * @author + *
+ * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
+ * This software may be copied and distributed for educational, research,
+ * and not for profit purposes provided that this copyright and statement
+ * are included in all such copies.  Other copyrights may also apply.
+ * 2014 Deskull rearranged comment for Doxygen.\n
+ * 
+ * @details + *
+ * This file includes code for eating food, drinking potions,
+ * reading scrolls, aiming wands, using staffs, zapping rods,
+ * and activating artifacts.
+ *
+ * In all cases, if the player becomes "aware" of the item's use
+ * by testing it, mark it as "aware" and reward some experience
+ * based on the object's level, always rounding up.  If the player
+ * remains "unaware", mark that object "kind" as "tried".
+ *
+ * This code now correctly handles the unstacking of wands, staffs,
+ * and rods.  Note the overly paranoid warning about potential pack
+ * overflow, which allows the player to use and drop a stacked item.
+ *
+ * In all "unstacking" scenarios, the "used" object is "carried" as if
+ * the player had just picked it up.  In particular, this means that if
+ * the use of an item induces pack overflow, that item will be dropped.
+ *
+ * For simplicity, these routines induce a full "pack reorganization"
+ * which not only combines similar items, but also reorganizes various
+ * items to obey the current "sorting" method.  This may require about
+ * 400 item comparisons, but only occasionally.
+ *
+ * There may be a BIG problem with any "effect" that can cause "changes"
+ * to the inventory.  For example, a "scroll of recharging" can cause
+ * a wand/staff to "disappear", moving the inventory up.  Luckily, the
+ * scrolls all appear BEFORE the staffs/wands, so this is not a problem.
+ * But, for example, a "staff of recharging" could cause MAJOR problems.
+ * In such a case, it will be best to either (1) "postpone" the effect
+ * until the end of the function, or (2) "change" the effect, say, into
+ * giving a staff "negative" charges, or "turning a staff into a stick".
+ * It seems as though a "rod of recharging" might in fact cause problems.
+ * The basic problem is that the act of recharging (and destroying) an
+ * item causes the inducer of that action to "move", causing "o_ptr" to
+ * no longer point at the correct item, with horrifying results.
+ *
+ * Note that food/potions/scrolls no longer use bit-flags for effects,
+ * but instead use the "sval" (which is also used to sort the objects).
+ * 
+ */ + +#include "cmd-item/cmd-magiceat.h" +#include "action/action-limited.h" +#include "cmd-item/cmd-usestaff.h" +#include "cmd-item/cmd-zaprod.h" +#include "cmd-item/cmd-zapwand.h" +#include "core/asking-player.h" +#include "game-option/disturbance-options.h" +#include "game-option/text-display-options.h" +#include "io/command-repeater.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "object/object-kind-hook.h" +#include "object/object-kind.h" +#include "sv-definition/sv-other-types.h" +#include "sv-definition/sv-rod-types.h" +#include "player-info/avatar.h" +#include "player/player-class.h" +#include "player/player-status.h" +#include "player/player-status-table.h" +#include "spell/spell-info.h" +#include "target/target-getter.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/buffer-shaper.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" + +/*! + * @brief 魔道具術師の取り込んだ魔力一覧から選択/閲覧する / + * @param only_browse 閲覧するだけならばTRUE + * @return 選択した魔力のID、キャンセルならば-1を返す + */ +static OBJECT_SUBTYPE_VALUE select_magic_eater(player_type *creature_ptr, bool only_browse) +{ + OBJECT_SUBTYPE_VALUE ext = 0; + char choice; + bool flag, request_list; + tval_type tval = 0; + int ask = TRUE; + OBJECT_SUBTYPE_VALUE i = 0; + char out_val[160]; + + int menu_line = (use_menu ? 1 : 0); + + COMMAND_CODE sn; + if (repeat_pull(&sn)) + { + /* Verify the spell */ + if (sn >= EATER_EXT*2 && !(creature_ptr->magic_num1[sn] > k_info[lookup_kind(TV_ROD, sn-EATER_EXT*2)].pval * (creature_ptr->magic_num2[sn] - 1) * EATER_ROD_CHARGE)) + return sn; + else if (sn < EATER_EXT*2 && !(creature_ptr->magic_num1[sn] < EATER_CHARGE)) + return sn; + } + + for (i = 0; i < MAX_SPELLS; i++) + { + if (creature_ptr->magic_num2[i]) break; + } + + if (i == MAX_SPELLS) + { + msg_print(_("魔法を覚えていない!", "You don't have any magic!")); + return -1; + } + + if (use_menu) + { + screen_save(); + + while(!tval) + { +#ifdef JP + prt(format(" %s 杖", (menu_line == 1) ? "》" : " "), 2, 14); + prt(format(" %s 魔法棒", (menu_line == 2) ? "》" : " "), 3, 14); + prt(format(" %s ロッド", (menu_line == 3) ? "》" : " "), 4, 14); +#else + prt(format(" %s staff", (menu_line == 1) ? "> " : " "), 2, 14); + prt(format(" %s wand", (menu_line == 2) ? "> " : " "), 3, 14); + prt(format(" %s rod", (menu_line == 3) ? "> " : " "), 4, 14); +#endif + + if (only_browse) prt(_("どの種類の魔法を見ますか?", "Which type of magic do you browse?"), 0, 0); + else prt(_("どの種類の魔法を使いますか?", "Which type of magic do you use?"), 0, 0); + + choice = inkey(); + switch(choice) + { + case ESCAPE: + case 'z': + case 'Z': + screen_load(); + return -1; + case '2': + case 'j': + case 'J': + menu_line++; + break; + case '8': + case 'k': + case 'K': + menu_line+= 2; + break; + case '\r': + case 'x': + case 'X': + ext = (menu_line-1)*EATER_EXT; + if (menu_line == 1) tval = TV_STAFF; + else if (menu_line == 2) tval = TV_WAND; + else tval = TV_ROD; + break; + } + if (menu_line > 3) menu_line -= 3; + } + screen_load(); + } + else + { + while (TRUE) + { + if (!get_com(_("[A] 杖, [B] 魔法棒, [C] ロッド:", "[A] staff, [B] wand, [C] rod:"), &choice, TRUE)) + { + return -1; + } + if (choice == 'A' || choice == 'a') + { + ext = 0; + tval = TV_STAFF; + break; + } + if (choice == 'B' || choice == 'b') + { + ext = EATER_EXT; + tval = TV_WAND; + break; + } + if (choice == 'C' || choice == 'c') + { + ext = EATER_EXT*2; + tval = TV_ROD; + break; + } + } + } + for (i = ext; i < ext + EATER_EXT; i++) + { + if (creature_ptr->magic_num2[i]) + { + if (use_menu) menu_line = i-ext+1; + break; + } + } + if (i == ext+EATER_EXT) + { + msg_print(_("その種類の魔法は覚えていない!", "You don't have that type of magic!")); + return -1; + } + + /* Nothing chosen yet */ + flag = FALSE; + + if (only_browse) strnfmt(out_val, 78, _("('*'で一覧, ESCで中断) どの魔力を見ますか?", + "(*=List, ESC=exit) Browse which power? ")); + else strnfmt(out_val, 78, _("('*'で一覧, ESCで中断) どの魔力を使いますか?", + "(*=List, ESC=exit) Use which power? ")); + screen_save(); + + request_list = always_show_list; + + while (!flag) + { + /* Show the list */ + if (request_list || use_menu) + { + byte y, x = 0; + OBJECT_SUBTYPE_VALUE ctr; + PERCENTAGE chance; + KIND_OBJECT_IDX k_idx; + char dummy[80]; + POSITION x1, y1; + DEPTH level; + byte col; + + strcpy(dummy, ""); + + for (y = 1; y < 20; y++) + prt("", y, x); + + y = 1; + + /* Print header(s) */ +#ifdef JP + prt(format(" %s 失率 %s 失率", (tval == TV_ROD ? " 状態 " : "使用回数"), (tval == TV_ROD ? " 状態 " : "使用回数")), y++, x); +#else + prt(format(" %s Fail %s Fail", (tval == TV_ROD ? " Stat " : " Charges"), (tval == TV_ROD ? " Stat " : " Charges")), y++, x); +#endif + + /* Print list */ + for (ctr = 0; ctr < EATER_EXT; ctr++) + { + if (!creature_ptr->magic_num2[ctr+ext]) continue; + + k_idx = lookup_kind(tval, ctr); + + if (use_menu) + { + if (ctr == (menu_line-1)) + strcpy(dummy, _("》", "> ")); + else + strcpy(dummy, " "); + } + /* letter/number for power selection */ + else + { + char letter; + if (ctr < 26) + letter = I2A(ctr); + else + letter = '0' + ctr - 26; + sprintf(dummy, "%c)",letter); + } + x1 = ((ctr < EATER_EXT/2) ? x : x + 40); + y1 = ((ctr < EATER_EXT/2) ? y + ctr : y + ctr - EATER_EXT/2); + level = (tval == TV_ROD ? k_info[k_idx].level * 5 / 6 - 5 : k_info[k_idx].level); + chance = level * 4 / 5 + 20; + chance -= 3 * (adj_mag_stat[creature_ptr->stat_ind[mp_ptr->spell_stat]] - 1); + level /= 2; + if (creature_ptr->lev > level) + { + chance -= 3 * (creature_ptr->lev - level); + } + chance = mod_spell_chance_1(creature_ptr, chance); + chance = MAX(chance, adj_mag_fail[creature_ptr->stat_ind[mp_ptr->spell_stat]]); + /* Stunning makes spells harder */ + if (creature_ptr->stun > 50) chance += 25; + else if (creature_ptr->stun) chance += 15; + + if (chance > 95) chance = 95; + + chance = mod_spell_chance_2(creature_ptr, chance); + + col = TERM_WHITE; + + if (k_idx) + { + if (tval == TV_ROD) + { + strcat(dummy, format( + _(" %-22.22s 充填:%2d/%2d%3d%%", " %-22.22s (%2d/%2d) %3d%%"), + k_name + k_info[k_idx].name, + creature_ptr->magic_num1[ctr+ext] ? + (creature_ptr->magic_num1[ctr+ext] - 1) / (EATER_ROD_CHARGE * k_info[k_idx].pval) +1 : 0, + creature_ptr->magic_num2[ctr+ext], chance)); + if (creature_ptr->magic_num1[ctr+ext] > k_info[k_idx].pval * (creature_ptr->magic_num2[ctr+ext]-1) * EATER_ROD_CHARGE) col = TERM_RED; + } + else + { + strcat(dummy, format(" %-22.22s %2d/%2d %3d%%", k_name + k_info[k_idx].name, (s16b)(creature_ptr->magic_num1[ctr+ext]/EATER_CHARGE), creature_ptr->magic_num2[ctr+ext], chance)); + if (creature_ptr->magic_num1[ctr+ext] < EATER_CHARGE) col = TERM_RED; + } + } + else + strcpy(dummy, ""); + c_prt(col, dummy, y1, x1); + } + } + + if (!get_com(out_val, &choice, FALSE)) break; + + if (use_menu && choice != ' ') + { + switch (choice) + { + case '0': + { + screen_load(); + return 0; + } + + case '8': + case 'k': + case 'K': + { + do + { + menu_line += EATER_EXT - 1; + if (menu_line > EATER_EXT) menu_line -= EATER_EXT; + } while(!creature_ptr->magic_num2[menu_line+ext-1]); + break; + } + + case '2': + case 'j': + case 'J': + { + do + { + menu_line++; + if (menu_line > EATER_EXT) menu_line -= EATER_EXT; + } while(!creature_ptr->magic_num2[menu_line+ext-1]); + break; + } + + case '4': + case 'h': + case 'H': + case '6': + case 'l': + case 'L': + { + bool reverse = FALSE; + if ((choice == '4') || (choice == 'h') || (choice == 'H')) reverse = TRUE; + if (menu_line > EATER_EXT/2) + { + menu_line -= EATER_EXT/2; + reverse = TRUE; + } + else menu_line+=EATER_EXT/2; + while(!creature_ptr->magic_num2[menu_line+ext-1]) + { + if (reverse) + { + menu_line--; + if (menu_line < 2) reverse = FALSE; + } + else + { + menu_line++; + if (menu_line > EATER_EXT-1) reverse = TRUE; + } + } + break; + } + + case 'x': + case 'X': + case '\r': + { + i = menu_line - 1; + ask = FALSE; + break; + } + } + } + + /* Request redraw */ + if (use_menu && ask) continue; + + /* Request redraw */ + if (!use_menu && ((choice == ' ') || (choice == '*') || (choice == '?'))) + { + /* Hide the list */ + if (request_list) + { + /* Hide list */ + request_list = FALSE; + screen_load(); + screen_save(); + } + else + request_list = TRUE; + + /* Redo asking */ + continue; + } + + if (!use_menu) + { + if (isalpha(choice)) + { + /* Note verify */ + ask = (isupper(choice)); + + /* Lowercase */ + if (ask) choice = (char)tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + } + else + { + ask = FALSE; /* Can't uppercase digits */ + + i = choice - '0' + 26; + } + } + + /* Totally Illegal */ + if ((i < 0) || (i > EATER_EXT) || !creature_ptr->magic_num2[i+ext]) + { + bell(); + continue; + } + + if (!only_browse) + { + /* Verify it */ + if (ask) + { + char tmp_val[160]; + + /* Prompt */ + (void) strnfmt(tmp_val, 78, _("%sを使いますか? ", "Use %s?"), k_name + k_info[lookup_kind(tval ,i)].name); + + /* Belay that order */ + if (!get_check(tmp_val)) continue; + } + if (tval == TV_ROD) + { + if (creature_ptr->magic_num1[ext+i] > k_info[lookup_kind(tval, i)].pval * (creature_ptr->magic_num2[ext+i] - 1) * EATER_ROD_CHARGE) + { + msg_print(_("その魔法はまだ充填している最中だ。", "The magic is still charging.")); + msg_print(NULL); + if (use_menu) ask = TRUE; + continue; + } + } + else + { + if (creature_ptr->magic_num1[ext+i] < EATER_CHARGE) + { + msg_print(_("その魔法は使用回数が切れている。", "The magic has no charges left.")); + msg_print(NULL); + if (use_menu) ask = TRUE; + continue; + } + } + } + + /* Browse */ + else + { + int line, j; + char temp[70 * 20]; + + /* Clear lines, position cursor (really should use strlen here) */ + term_erase(7, 23, 255); + term_erase(7, 22, 255); + term_erase(7, 21, 255); + term_erase(7, 20, 255); + + shape_buffer(k_text + k_info[lookup_kind(tval, i)].text, 62, temp, sizeof(temp)); + for (j = 0, line = 21; temp[j]; j += 1 + strlen(&temp[j])) + { + prt(&temp[j], line, 10); + line++; + } + + continue; + } + + /* Stop the loop */ + flag = TRUE; + } + screen_load(); + + if (!flag) return -1; + + repeat_push(ext+i); + return ext+i; +} + + +/*! + * @brief 取り込んだ魔力を利用するコマンドのメインルーチン / + * Use eaten rod, wand or staff + * @param only_browse 閲覧するだけならばTRUE + * @param powerful 強力発動中の処理ならばTRUE + * @return 実際にコマンドを実行したならばTRUEを返す。 + */ +bool do_cmd_magic_eater(player_type *creature_ptr, bool only_browse, bool powerful) +{ + OBJECT_SUBTYPE_VALUE item; + PERCENTAGE chance; + DEPTH level; + KIND_OBJECT_IDX k_idx; + tval_type tval; + OBJECT_SUBTYPE_VALUE sval; + bool use_charge = TRUE; + + if (cmd_limit_confused(creature_ptr)) return FALSE; + + item = select_magic_eater(creature_ptr, only_browse); + if (item == -1) + { + free_turn(creature_ptr); + return FALSE; + } + if (item >= EATER_EXT*2) {tval = TV_ROD;sval = item - EATER_EXT*2;} + else if (item >= EATER_EXT) {tval = TV_WAND;sval = item - EATER_EXT;} + else {tval = TV_STAFF; sval = item;} + k_idx = lookup_kind(tval, sval); + + level = (tval == TV_ROD ? k_info[k_idx].level * 5 / 6 - 5 : k_info[k_idx].level); + chance = level * 4 / 5 + 20; + chance -= 3 * (adj_mag_stat[creature_ptr->stat_ind[mp_ptr->spell_stat]] - 1); + level /= 2; + if (creature_ptr->lev > level) + { + chance -= 3 * (creature_ptr->lev - level); + } + chance = mod_spell_chance_1(creature_ptr, chance); + chance = MAX(chance, adj_mag_fail[creature_ptr->stat_ind[mp_ptr->spell_stat]]); + /* Stunning makes spells harder */ + if (creature_ptr->stun > 50) chance += 25; + else if (creature_ptr->stun) chance += 15; + + if (chance > 95) chance = 95; + + chance = mod_spell_chance_2(creature_ptr, chance); + + if (randint0(100) < chance) + { + if (flush_failure) flush(); + + msg_print(_("呪文をうまく唱えられなかった!", "You failed to get the magic off!")); + sound(SOUND_FAIL); + if (randint1(100) >= chance) + chg_virtue(creature_ptr, V_CHANCE,-1); + take_turn(creature_ptr, 100); + + return TRUE; + } + else + { + DIRECTION dir = 0; + + if (tval == TV_ROD) + { + if ((sval >= SV_ROD_MIN_DIRECTION) && (sval != SV_ROD_HAVOC) && (sval != SV_ROD_AGGRAVATE) && (sval != SV_ROD_PESTICIDE)) + if (!get_aim_dir(creature_ptr, &dir)) return FALSE; + rod_effect(creature_ptr, sval, dir, &use_charge, powerful, TRUE); + if (!use_charge) return FALSE; + } + else if (tval == TV_WAND) + { + if (!get_aim_dir(creature_ptr, &dir)) return FALSE; + wand_effect(creature_ptr, sval, dir, powerful, TRUE); + } + else + { + staff_effect(creature_ptr, sval, &use_charge, powerful, TRUE, TRUE); + if (!use_charge) return FALSE; + } + if (randint1(100) < chance) + chg_virtue(creature_ptr, V_CHANCE,1); + } + take_turn(creature_ptr, 100); + if (tval == TV_ROD) creature_ptr->magic_num1[item] += k_info[k_idx].pval * EATER_ROD_CHARGE; + else creature_ptr->magic_num1[item] -= EATER_CHARGE; + + return TRUE; +} diff --git a/src/cmd-item/cmd-magiceat.h b/src/cmd-item/cmd-magiceat.h new file mode 100644 index 000000000..6a9a1693a --- /dev/null +++ b/src/cmd-item/cmd-magiceat.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" + +#define EATER_EXT 36 +#define EATER_CHARGE 0x10000L +#define EATER_ROD_CHARGE 0x10L + +extern bool do_cmd_magic_eater(player_type *creature_ptr, bool only_browse, bool powerful); diff --git a/src/cmd-item/cmd-quaff.c b/src/cmd-item/cmd-quaff.c new file mode 100644 index 000000000..499e7c013 --- /dev/null +++ b/src/cmd-item/cmd-quaff.c @@ -0,0 +1,43 @@ +/*! + * @brief プレイヤーの飲むコマンド実装 + * @date 2018/09/07 + * @author deskull + */ + +#include "cmd-item/cmd-quaff.h" +#include "action/action-limited.h" +#include "floor/floor-object.h" +#include "object-hook/hook-expendable.h" +#include "object-use/quaff-execution.h" +#include "object/item-tester-hooker.h" +#include "object/item-use-flags.h" +#include "player/attack-defense-types.h" +#include "player/special-defense-types.h" +#include "status/action-setter.h" + +/*! + * @brief 薬を飲むコマンドのメインルーチン / + * Quaff some potion (from the pack or floor) + * @return なし + */ +void do_cmd_quaff_potion(player_type *creature_ptr) +{ + if (creature_ptr->wild_mode) + return; + + if (cmd_limit_arena(creature_ptr)) + return; + + if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) + set_action(creature_ptr, ACTION_NONE); + + item_tester_hook = item_tester_hook_quaff; + concptr q = _("どの薬を飲みますか? ", "Quaff which potion? "); + concptr s = _("飲める薬がない。", "You have no potions to quaff."); + + OBJECT_IDX item; + if (!choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), 0)) + return; + + exe_quaff_potion(creature_ptr, item); +} diff --git a/src/cmd-item/cmd-quaff.h b/src/cmd-item/cmd-quaff.h new file mode 100644 index 000000000..022dbfa4c --- /dev/null +++ b/src/cmd-item/cmd-quaff.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_quaff_potion(player_type *creature_ptr); diff --git a/src/cmd-item/cmd-read.c b/src/cmd-item/cmd-read.c new file mode 100644 index 000000000..42a25eae5 --- /dev/null +++ b/src/cmd-item/cmd-read.c @@ -0,0 +1,46 @@ +/*! + * @todo いずれcmd-item.c/h に統合したい + * @brief プレイヤーの読むコマンド実装 + * @date 2018/09/07 + * @author deskull + */ + +#include "cmd-item/cmd-read.h" +#include "action/action-limited.h" +#include "floor/floor-object.h" +#include "object-hook/hook-expendable.h" +#include "object-use/read-execution.h" +#include "object/item-tester-hooker.h" +#include "object/item-use-flags.h" +#include "perception/object-perception.h" +#include "player/attack-defense-types.h" +#include "player/special-defense-types.h" +#include "status/action-setter.h" + +/*! + * @brief 読むコマンドのメインルーチン / + * Eat some food (from the pack or floor) + * @return なし + */ +void do_cmd_read_scroll(player_type *creature_ptr) +{ + if (creature_ptr->wild_mode || cmd_limit_arena(creature_ptr)) + return; + + if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) + set_action(creature_ptr, ACTION_NONE); + + if (cmd_limit_blind(creature_ptr) || cmd_limit_confused(creature_ptr)) + return; + + item_tester_hook = item_tester_hook_readable; + concptr q = _("どの巻物を読みますか? ", "Read which scroll? "); + concptr s = _("読める巻物がない。", "You have no scrolls to read."); + object_type *o_ptr; + OBJECT_IDX item; + o_ptr = choose_object(creature_ptr, &item, q, s, USE_INVEN | USE_FLOOR, 0); + if (!o_ptr) + return; + + exe_read(creature_ptr, item, object_is_aware(o_ptr)); +} diff --git a/src/cmd-item/cmd-read.h b/src/cmd-item/cmd-read.h new file mode 100644 index 000000000..680acd527 --- /dev/null +++ b/src/cmd-item/cmd-read.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_read_scroll(player_type *creature_ptr); diff --git a/src/cmd-item/cmd-refill.c b/src/cmd-item/cmd-refill.c new file mode 100644 index 000000000..77ebd522c --- /dev/null +++ b/src/cmd-item/cmd-refill.c @@ -0,0 +1,110 @@ +#include "cmd-item/cmd-refill.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "floor/floor-object.h" +#include "inventory/inventory-object.h" +#include "inventory/inventory-slot-types.h" +#include "object-enchant/object-ego.h" +#include "object-hook/hook-expendable.h" +#include "object/item-tester-hooker.h" +#include "object/item-use-flags.h" +#include "player/attack-defense-types.h" +#include "player/special-defense-types.h" +#include "status/action-setter.h" +#include "sv-definition/sv-lite-types.h" +#include "view/display-messages.h" + +/*! + * @brief ƒ‰ƒ“ƒ^ƒ“‚É”R—¿‚ð‰Á‚¦‚éƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ + * Refill the players lamp (from the pack or floor) + * @return ‚È‚µ + */ +static void do_cmd_refill_lamp(player_type *user_ptr) +{ + OBJECT_IDX item; + object_type *o_ptr; + object_type *j_ptr; + item_tester_hook = item_tester_refill_lantern; + concptr q = _("‚Ç‚Ì–û‚‚ڂ©‚璍‚¬‚Ü‚·‚©? ", "Refill with which flask? "); + concptr s = _("–û‚‚ڂª‚È‚¢B", "You have no flasks of oil."); + o_ptr = choose_object(user_ptr, &item, q, s, USE_INVEN | USE_FLOOR, 0); + if (!o_ptr) + return; + + take_turn(user_ptr, 50); + j_ptr = &user_ptr->inventory_list[INVEN_LITE]; + j_ptr->xtra4 += o_ptr->xtra4; + msg_print(_("ƒ‰ƒ“ƒv‚É–û‚𒍂¢‚¾B", "You fuel your lamp.")); + if ((o_ptr->name2 == EGO_LITE_DARKNESS) && (j_ptr->xtra4 > 0)) { + j_ptr->xtra4 = 0; + msg_print(_("ƒ‰ƒ“ƒv‚ªÁ‚¦‚Ä‚µ‚Ü‚Á‚½I", "Your lamp has gone out!")); + } else if ((o_ptr->name2 == EGO_LITE_DARKNESS) || (j_ptr->name2 == EGO_LITE_DARKNESS)) { + j_ptr->xtra4 = 0; + msg_print(_("‚µ‚©‚µƒ‰ƒ“ƒv‚Í‘S‚­Œõ‚ç‚È‚¢B", "Curiously, your lamp doesn't light.")); + } else if (j_ptr->xtra4 >= FUEL_LAMP) { + j_ptr->xtra4 = FUEL_LAMP; + msg_print(_("ƒ‰ƒ“ƒv‚Ì–û‚͈ê”t‚¾B", "Your lamp is full.")); + } + + vary_item(user_ptr, item, -1); + user_ptr->update |= PU_TORCH; +} + +/*! + * @brief ¼–¾‚ð‘©‚Ë‚éƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ + * Refuel the players torch (from the pack or floor) + * @return ‚È‚µ + */ +static void do_cmd_refill_torch(player_type *creature_ptr) +{ + OBJECT_IDX item; + object_type *o_ptr; + object_type *j_ptr; + item_tester_hook = object_can_refill_torch; + concptr q = _("‚ǂ̏¼–¾‚Å–¾‚©‚è‚ð‹­‚ß‚Ü‚·‚©? ", "Refuel with which torch? "); + concptr s = _("‘¼‚ɏ¼–¾‚ª‚È‚¢B", "You have no extra torches."); + o_ptr = choose_object(creature_ptr, &item, q, s, USE_INVEN | USE_FLOOR, 0); + if (!o_ptr) + return; + + take_turn(creature_ptr, 50); + j_ptr = &creature_ptr->inventory_list[INVEN_LITE]; + j_ptr->xtra4 += o_ptr->xtra4 + 5; + msg_print(_("¼–¾‚ðŒ‹‡‚µ‚½B", "You combine the torches.")); + if ((o_ptr->name2 == EGO_LITE_DARKNESS) && (j_ptr->xtra4 > 0)) { + j_ptr->xtra4 = 0; + msg_print(_("¼–¾‚ªÁ‚¦‚Ä‚µ‚Ü‚Á‚½I", "Your torch has gone out!")); + } else if ((o_ptr->name2 == EGO_LITE_DARKNESS) || (j_ptr->name2 == EGO_LITE_DARKNESS)) { + j_ptr->xtra4 = 0; + msg_print(_("‚µ‚©‚µ¼–¾‚Í‘S‚­Œõ‚ç‚È‚¢B", "Curiously, your torch doesn't light.")); + } else if (j_ptr->xtra4 >= FUEL_TORCH) { + j_ptr->xtra4 = FUEL_TORCH; + msg_print(_("¼–¾‚ÌŽõ–½‚͏\•ª‚¾B", "Your torch is fully fueled.")); + } else + msg_print(_("¼–¾‚Í‚¢‚Á‚»‚¤–¾‚é‚­‹P‚¢‚½B", "Your torch glows more brightly.")); + + vary_item(creature_ptr, item, -1); + creature_ptr->update |= PU_TORCH; +} + +/*! + * @brief ”R—¿‚ð•â[‚·‚éƒRƒ}ƒ“ƒh‚̃ƒCƒ“ƒ‹[ƒ`ƒ“ + * Refill the players lamp, or restock his torches + * @return ‚È‚µ + */ +void do_cmd_refill(player_type *creature_ptr) +{ + object_type *o_ptr; + o_ptr = &creature_ptr->inventory_list[INVEN_LITE]; + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + if (o_ptr->tval != TV_LITE) + msg_print(_("ŒõŒ¹‚ð‘•”õ‚µ‚Ä‚¢‚È‚¢B", "You are not wielding a light.")); + else if (o_ptr->sval == SV_LITE_LANTERN) + do_cmd_refill_lamp(creature_ptr); + else if (o_ptr->sval == SV_LITE_TORCH) + do_cmd_refill_torch(creature_ptr); + else + msg_print(_("‚±‚ÌŒõŒ¹‚ÍŽõ–½‚ð‰„‚Î‚¹‚È‚¢B", "Your light cannot be refilled.")); +} diff --git a/src/cmd-item/cmd-refill.h b/src/cmd-item/cmd-refill.h new file mode 100644 index 000000000..ff6af6f4b --- /dev/null +++ b/src/cmd-item/cmd-refill.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_refill(player_type *creature_ptr); diff --git a/src/cmd-item/cmd-smith.c b/src/cmd-item/cmd-smith.c new file mode 100644 index 000000000..f105e6237 --- /dev/null +++ b/src/cmd-item/cmd-smith.c @@ -0,0 +1,1196 @@ +/*! + * @brief プレイヤーの鍛冶コマンド実装 + * @date 2019/03/11 + * @author deskull + */ + +#include "cmd-item/cmd-smith.h" +#include "action/action-limited.h" +#include "autopick/autopick.h" +#include "core/asking-player.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "floor/floor-object.h" +#include "game-option/text-display-options.h" +#include "io/command-repeater.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" +#include "main/sound-of-music.h" +#include "mind/mind-weaponsmith.h" +#include "object-enchant/object-ego.h" +#include "object-enchant/special-object-flags.h" +#include "object-enchant/tr-types.h" +#include "object-enchant/trc-types.h" +#include "object-hook/hook-armor.h" +#include "object-hook/hook-enchant.h" +#include "object-hook/hook-weapon.h" +#include "object/item-tester-hooker.h" +#include "object/item-use-flags.h" +#include "object/object-flags.h" // todo 相互参照している. +#include "object/object-generator.h" +#include "perception/object-perception.h" +#include "player/player-status.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/bit-flags-calculator.h" +#include "util/buffer-shaper.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" + +/*! + * エッセンス情報の構造体 / A structure for smithing + */ +typedef struct { + int add; /* TR flag number or special essence id */ + concptr add_name; /* Name of this ability */ + ESSENCE_IDX type; /* Menu number */ + int essence; /* Index for carrying essences */ + int value; /* Needed value to add this ability */ +} essence_type; + +/*! + * エッセンス情報テーブル Smithing type data for Weapon smith + */ +#ifdef JP +static essence_type essence_info[] = { { TR_STR, "腕力", 4, TR_STR, 20 }, { TR_INT, "知能", 4, TR_INT, 20 }, { TR_WIS, "賢さ", 4, TR_WIS, 20 }, + { TR_DEX, "器用さ", 4, TR_DEX, 20 }, { TR_CON, "耐久力", 4, TR_CON, 20 }, { TR_CHR, "魅力", 4, TR_CHR, 20 }, + { TR_MAGIC_MASTERY, "魔力支配", 4, TR_MAGIC_MASTERY, 20 }, { TR_STEALTH, "隠密", 4, TR_STEALTH, 40 }, { TR_SEARCH, "探索", 4, TR_SEARCH, 15 }, + { TR_INFRA, "赤外線視力", 4, TR_INFRA, 15 }, { TR_TUNNEL, "採掘", 4, TR_TUNNEL, 15 }, { TR_SPEED, "スピード", 4, TR_SPEED, 12 }, + { TR_BLOWS, "追加攻撃", 1, TR_BLOWS, 20 }, { TR_CHAOTIC, "カオス攻撃", 1, TR_CHAOTIC, 15 }, { TR_VAMPIRIC, "吸血攻撃", 1, TR_VAMPIRIC, 60 }, + { TR_IMPACT, "地震発動", 7, TR_IMPACT, 15 }, { TR_BRAND_POIS, "毒殺", 1, TR_BRAND_POIS, 20 }, { TR_BRAND_ACID, "溶解", 1, TR_BRAND_ACID, 20 }, + { TR_BRAND_ELEC, "電撃", 1, TR_BRAND_ELEC, 20 }, { TR_BRAND_FIRE, "焼棄", 1, TR_BRAND_FIRE, 20 }, { TR_BRAND_COLD, "凍結", 1, TR_BRAND_COLD, 20 }, + { TR_SUST_STR, "腕力維持", 3, TR_SUST_STR, 15 }, { TR_SUST_INT, "知能維持", 3, TR_SUST_STR, 15 }, { TR_SUST_WIS, "賢さ維持", 3, TR_SUST_STR, 15 }, + { TR_SUST_DEX, "器用さ維持", 3, TR_SUST_STR, 15 }, { TR_SUST_CON, "耐久力維持", 3, TR_SUST_STR, 15 }, { TR_SUST_CHR, "魅力維持", 3, TR_SUST_STR, 15 }, + { TR_IM_ACID, "酸免疫", 2, TR_IM_ACID, 20 }, { TR_IM_ELEC, "電撃免疫", 2, TR_IM_ACID, 20 }, { TR_IM_FIRE, "火炎免疫", 2, TR_IM_ACID, 20 }, + { TR_IM_COLD, "冷気免疫", 2, TR_IM_ACID, 20 }, { TR_REFLECT, "反射", 2, TR_REFLECT, 20 }, { TR_FREE_ACT, "麻痺知らず", 3, TR_FREE_ACT, 20 }, + { TR_HOLD_EXP, "経験値維持", 3, TR_HOLD_EXP, 20 }, { TR_RES_ACID, "耐酸", 2, TR_RES_ACID, 15 }, { TR_RES_ELEC, "耐電撃", 2, TR_RES_ELEC, 15 }, + { TR_RES_FIRE, "耐火炎", 2, TR_RES_FIRE, 15 }, { TR_RES_COLD, "耐冷気", 2, TR_RES_COLD, 15 }, { TR_RES_POIS, "耐毒", 2, TR_RES_POIS, 25 }, + { TR_RES_FEAR, "耐恐怖", 2, TR_RES_FEAR, 20 }, { TR_RES_LITE, "耐閃光", 2, TR_RES_LITE, 20 }, { TR_RES_DARK, "耐暗黒", 2, TR_RES_DARK, 20 }, + { TR_RES_BLIND, "耐盲目", 2, TR_RES_BLIND, 20 }, { TR_RES_CONF, "耐混乱", 2, TR_RES_CONF, 20 }, { TR_RES_SOUND, "耐轟音", 2, TR_RES_SOUND, 20 }, + { TR_RES_SHARDS, "耐破片", 2, TR_RES_SHARDS, 20 }, { TR_RES_NETHER, "耐地獄", 2, TR_RES_NETHER, 20 }, { TR_RES_NEXUS, "耐因果混乱", 2, TR_RES_NEXUS, 20 }, + { TR_RES_CHAOS, "耐カオス", 2, TR_RES_CHAOS, 20 }, { TR_RES_DISEN, "耐劣化", 2, TR_RES_DISEN, 20 }, { TR_SH_FIRE, "", 0, -2, 0 }, + { TR_SH_ELEC, "", 0, -2, 0 }, { TR_SH_COLD, "", 0, -2, 0 }, { TR_NO_MAGIC, "反魔法", 3, TR_NO_MAGIC, 15 }, { TR_WARNING, "警告", 3, TR_WARNING, 20 }, + { TR_LEVITATION, "浮遊", 3, TR_LEVITATION, 20 }, { TR_LITE_1, "永久光源", 3, TR_LITE_1, 15 }, { TR_LITE_2, "", 0, -2, 0 }, { TR_LITE_3, "", 0, -2, 0 }, + { TR_SEE_INVIS, "可視透明", 3, TR_SEE_INVIS, 20 }, { TR_TELEPATHY, "テレパシー", 6, TR_TELEPATHY, 15 }, { TR_SLOW_DIGEST, "遅消化", 3, TR_SLOW_DIGEST, 15 }, + { TR_REGEN, "急速回復", 3, TR_REGEN, 20 }, { TR_TELEPORT, "テレポート", 3, TR_TELEPORT, 25 }, + + { TR_SLAY_EVIL, "邪悪倍打", 5, TR_SLAY_EVIL, 100 }, { TR_KILL_EVIL, "邪悪倍倍打", 0, TR_SLAY_EVIL, 60 }, + { TR_SLAY_ANIMAL, "動物倍打", 5, TR_SLAY_ANIMAL, 20 }, { TR_KILL_ANIMAL, "動物倍倍打", 5, TR_SLAY_ANIMAL, 60 }, + { TR_SLAY_UNDEAD, "不死倍打", 5, TR_SLAY_UNDEAD, 20 }, { TR_KILL_UNDEAD, "不死倍倍打", 5, TR_SLAY_UNDEAD, 60 }, + { TR_SLAY_DEMON, "悪魔倍打", 5, TR_SLAY_DEMON, 20 }, { TR_KILL_DEMON, "悪魔倍倍打", 5, TR_SLAY_DEMON, 60 }, + { TR_SLAY_ORC, "オーク倍打", 5, TR_SLAY_ORC, 15 }, { TR_KILL_ORC, "オーク倍倍打", 5, TR_SLAY_ORC, 60 }, + { TR_SLAY_TROLL, "トロル倍打", 5, TR_SLAY_TROLL, 15 }, { TR_KILL_TROLL, "トロル倍倍打", 5, TR_SLAY_TROLL, 60 }, + { TR_SLAY_GIANT, "巨人倍打", 5, TR_SLAY_GIANT, 20 }, { TR_KILL_GIANT, "巨人倍倍打", 5, TR_SLAY_GIANT, 60 }, + { TR_SLAY_DRAGON, "竜倍打", 5, TR_SLAY_DRAGON, 20 }, { TR_KILL_DRAGON, "竜倍倍打", 5, TR_SLAY_DRAGON, 60 }, + { TR_SLAY_HUMAN, "人間倍打", 5, TR_SLAY_HUMAN, 20 }, { TR_KILL_HUMAN, "人間倍倍打", 5, TR_SLAY_HUMAN, 60 }, + + { TR_ESP_ANIMAL, "動物ESP", 6, TR_SLAY_ANIMAL, 40 }, { TR_ESP_UNDEAD, "不死ESP", 6, TR_SLAY_UNDEAD, 40 }, { TR_ESP_DEMON, "悪魔ESP", 6, TR_SLAY_DEMON, 40 }, + { TR_ESP_ORC, "オークESP", 6, TR_SLAY_ORC, 40 }, { TR_ESP_TROLL, "トロルESP", 6, TR_SLAY_TROLL, 40 }, { TR_ESP_GIANT, "巨人ESP", 6, TR_SLAY_GIANT, 40 }, + { TR_ESP_DRAGON, "竜ESP", 6, TR_SLAY_DRAGON, 40 }, { TR_ESP_HUMAN, "人間ESP", 6, TR_SLAY_HUMAN, 40 }, + + { ESSENCE_ATTACK, "攻撃", 10, TR_ES_ATTACK, 30 }, { ESSENCE_AC, "防御", 10, TR_ES_AC, 15 }, { ESSENCE_TMP_RES_ACID, "酸耐性発動", 7, TR_RES_ACID, 50 }, + { ESSENCE_TMP_RES_ELEC, "電撃耐性発動", 7, TR_RES_ELEC, 50 }, { ESSENCE_TMP_RES_FIRE, "火炎耐性発動", 7, TR_RES_FIRE, 50 }, + { ESSENCE_TMP_RES_COLD, "冷気耐性発動", 7, TR_RES_COLD, 50 }, { ESSENCE_SH_FIRE, "火炎オーラ", 7, -1, 50 }, { ESSENCE_SH_ELEC, "電撃オーラ", 7, -1, 50 }, + { ESSENCE_SH_COLD, "冷気オーラ", 7, -1, 50 }, { ESSENCE_RESISTANCE, "全耐性", 2, -1, 150 }, { ESSENCE_SUSTAIN, "装備保持", 10, -1, 10 }, + { ESSENCE_SLAY_GLOVE, "殺戮の小手", 1, TR_ES_ATTACK, 200 }, + + { -1, NULL, 0, -1, 0 } }; +#else +static essence_type essence_info[] = { { TR_STR, "strength", 4, TR_STR, 20 }, { TR_INT, "intelligence", 4, TR_INT, 20 }, { TR_WIS, "wisdom", 4, TR_WIS, 20 }, + { TR_DEX, "dexterity", 4, TR_DEX, 20 }, { TR_CON, "constitution", 4, TR_CON, 20 }, { TR_CHR, "charisma", 4, TR_CHR, 20 }, + { TR_MAGIC_MASTERY, "magic mastery", 4, TR_MAGIC_MASTERY, 20 }, { TR_STEALTH, "stealth", 4, TR_STEALTH, 40 }, { TR_SEARCH, "serching", 4, TR_SEARCH, 15 }, + { TR_INFRA, "infravision", 4, TR_INFRA, 15 }, { TR_TUNNEL, "digging", 4, TR_TUNNEL, 15 }, { TR_SPEED, "speed", 4, TR_SPEED, 12 }, + { TR_BLOWS, "extra attack", 1, TR_BLOWS, 20 }, { TR_CHAOTIC, "chaos brand", 1, TR_CHAOTIC, 15 }, { TR_VAMPIRIC, "vampiric brand", 1, TR_VAMPIRIC, 60 }, + { TR_IMPACT, "quake activation", 7, TR_IMPACT, 15 }, { TR_BRAND_POIS, "poison brand", 1, TR_BRAND_POIS, 20 }, + { TR_BRAND_ACID, "acid brand", 1, TR_BRAND_ACID, 20 }, { TR_BRAND_ELEC, "electric brand", 1, TR_BRAND_ELEC, 20 }, + { TR_BRAND_FIRE, "fire brand", 1, TR_BRAND_FIRE, 20 }, { TR_BRAND_COLD, "cold brand", 1, TR_BRAND_COLD, 20 }, + { TR_SUST_STR, "sustain strength", 3, TR_SUST_STR, 15 }, { TR_SUST_INT, "sustain intelligence", 3, TR_SUST_STR, 15 }, + { TR_SUST_WIS, "sustain wisdom", 3, TR_SUST_STR, 15 }, { TR_SUST_DEX, "sustain dexterity", 3, TR_SUST_STR, 15 }, + { TR_SUST_CON, "sustain constitution", 3, TR_SUST_STR, 15 }, { TR_SUST_CHR, "sustain charisma", 3, TR_SUST_STR, 15 }, + { TR_IM_ACID, "acid immunity", 2, TR_IM_ACID, 20 }, { TR_IM_ELEC, "electric immunity", 2, TR_IM_ACID, 20 }, + { TR_IM_FIRE, "fire immunity", 2, TR_IM_ACID, 20 }, { TR_IM_COLD, "cold immunity", 2, TR_IM_ACID, 20 }, { TR_REFLECT, "reflection", 2, TR_REFLECT, 20 }, + { TR_FREE_ACT, "free action", 3, TR_FREE_ACT, 20 }, { TR_HOLD_EXP, "hold experience", 3, TR_HOLD_EXP, 20 }, + { TR_RES_ACID, "resistance to acid", 2, TR_RES_ACID, 15 }, { TR_RES_ELEC, "resistance to electric", 2, TR_RES_ELEC, 15 }, + { TR_RES_FIRE, "resistance to fire", 2, TR_RES_FIRE, 15 }, { TR_RES_COLD, "resistance to cold", 2, TR_RES_COLD, 15 }, + { TR_RES_POIS, "resistance to poison", 2, TR_RES_POIS, 25 }, { TR_RES_FEAR, "resistance to fear", 2, TR_RES_FEAR, 20 }, + { TR_RES_LITE, "resistance to light", 2, TR_RES_LITE, 20 }, { TR_RES_DARK, "resistance to dark", 2, TR_RES_DARK, 20 }, + { TR_RES_BLIND, "resistance to blind", 2, TR_RES_BLIND, 20 }, { TR_RES_CONF, "resistance to confusion", 2, TR_RES_CONF, 20 }, + { TR_RES_SOUND, "resistance to sound", 2, TR_RES_SOUND, 20 }, { TR_RES_SHARDS, "resistance to shard", 2, TR_RES_SHARDS, 20 }, + { TR_RES_NETHER, "resistance to nether", 2, TR_RES_NETHER, 20 }, { TR_RES_NEXUS, "resistance to nexus", 2, TR_RES_NEXUS, 20 }, + { TR_RES_CHAOS, "resistance to chaos", 2, TR_RES_CHAOS, 20 }, { TR_RES_DISEN, "resistance to disenchantment", 2, TR_RES_DISEN, 20 }, + { TR_SH_FIRE, "", 0, -2, 0 }, { TR_SH_ELEC, "", 0, -2, 0 }, { TR_SH_COLD, "", 0, -2, 0 }, { TR_NO_MAGIC, "anti magic", 3, TR_NO_MAGIC, 15 }, + { TR_WARNING, "warning", 3, TR_WARNING, 20 }, { TR_LEVITATION, "levitation", 3, TR_LEVITATION, 20 }, { TR_LITE_1, "permanent light", 3, TR_LITE_1, 15 }, + { TR_LITE_2, "", 0, -2, 0 }, { TR_LITE_3, "", 0, -2, 0 }, { TR_SEE_INVIS, "see invisible", 3, TR_SEE_INVIS, 20 }, + { TR_TELEPATHY, "telepathy", 6, TR_TELEPATHY, 15 }, { TR_SLOW_DIGEST, "slow digestion", 3, TR_SLOW_DIGEST, 15 }, + { TR_REGEN, "regeneration", 3, TR_REGEN, 20 }, { TR_TELEPORT, "teleport", 3, TR_TELEPORT, 25 }, + + { TR_SLAY_EVIL, "slay evil", 5, TR_SLAY_EVIL, 100 }, { TR_SLAY_ANIMAL, "slay animal", 5, TR_SLAY_ANIMAL, 20 }, + { TR_KILL_ANIMAL, "kill animal", 5, TR_SLAY_ANIMAL, 60 }, { TR_KILL_EVIL, "kill evil", 0, TR_SLAY_EVIL, 60 }, + { TR_SLAY_UNDEAD, "slay undead", 5, TR_SLAY_UNDEAD, 20 }, { TR_KILL_UNDEAD, "kill undead", 5, TR_SLAY_UNDEAD, 60 }, + { TR_SLAY_DEMON, "slay demon", 5, TR_SLAY_DEMON, 20 }, { TR_KILL_DEMON, "kill demon", 5, TR_SLAY_DEMON, 60 }, + { TR_SLAY_ORC, "slay orc", 5, TR_SLAY_ORC, 15 }, { TR_KILL_ORC, "kill orc", 5, TR_SLAY_ORC, 60 }, { TR_SLAY_TROLL, "slay troll", 5, TR_SLAY_TROLL, 15 }, + { TR_KILL_TROLL, "kill troll", 5, TR_SLAY_TROLL, 60 }, { TR_SLAY_GIANT, "slay giant", 5, TR_SLAY_GIANT, 20 }, + { TR_KILL_GIANT, "kill giant", 5, TR_SLAY_GIANT, 60 }, { TR_SLAY_DRAGON, "slay dragon", 5, TR_SLAY_DRAGON, 20 }, + { TR_KILL_DRAGON, "kill dragon", 5, TR_SLAY_DRAGON, 60 }, { TR_SLAY_HUMAN, "slay human", 5, TR_SLAY_HUMAN, 20 }, + { TR_KILL_HUMAN, "kill human", 5, TR_SLAY_HUMAN, 60 }, + + { TR_ESP_ANIMAL, "sense animal", 6, TR_SLAY_ANIMAL, 40 }, { TR_ESP_UNDEAD, "sense undead", 6, TR_SLAY_UNDEAD, 40 }, + { TR_ESP_DEMON, "sense demon", 6, TR_SLAY_DEMON, 40 }, { TR_ESP_ORC, "sense orc", 6, TR_SLAY_ORC, 40 }, + { TR_ESP_TROLL, "sense troll", 6, TR_SLAY_TROLL, 40 }, { TR_ESP_GIANT, "sense giant", 6, TR_SLAY_GIANT, 40 }, + { TR_ESP_DRAGON, "sense dragon", 6, TR_SLAY_DRAGON, 40 }, { TR_ESP_HUMAN, "sense human", 6, TR_SLAY_HUMAN, 40 }, + + { ESSENCE_ATTACK, "weapon enchant", 10, TR_ES_ATTACK, 30 }, { ESSENCE_AC, "armor enchant", 10, TR_ES_AC, 15 }, + { ESSENCE_TMP_RES_ACID, "resist acid activation", 7, TR_RES_ACID, 50 }, { ESSENCE_TMP_RES_ELEC, "resist electricity activation", 7, TR_RES_ELEC, 50 }, + { ESSENCE_TMP_RES_FIRE, "resist fire activation", 7, TR_RES_FIRE, 50 }, { ESSENCE_TMP_RES_COLD, "resist cold activation", 7, TR_RES_COLD, 50 }, + { ESSENCE_SH_FIRE, "fiery sheath", 7, -1, 50 }, { ESSENCE_SH_ELEC, "electric sheath", 7, -1, 50 }, { ESSENCE_SH_COLD, "sheath of coldness", 7, -1, 50 }, + { ESSENCE_RESISTANCE, "resistance", 2, -1, 150 }, { ESSENCE_SUSTAIN, "elements proof", 10, -1, 10 }, + { ESSENCE_SLAY_GLOVE, "gauntlets of slaying", 1, TR_ES_ATTACK, 200 }, + + { -1, NULL, 0, -1, 0 } }; +#endif + +/*! + * エッセンス名テーブル / Essense names for Weapon smith + */ +#ifdef JP +concptr essence_name[] = { "腕力", "知能", "賢さ", "器用さ", "耐久力", "魅力", "魔力支配", "", "隠密", "探索", "赤外線視力", "採掘", "スピード", "追加攻撃", + "カオス攻撃", "吸血攻撃", "動物倍打", "邪悪倍打", "不死倍打", "悪魔倍打", "オーク倍打", "トロル倍打", "巨人倍打", "竜倍打", "", "", "地震", "毒殺", "溶解", + "電撃", "焼棄", "凍結", "能力維持", "", "", "", "", "", "", "", "免疫", "", "", "", "", "反射", "麻痺知らず", "経験値維持", "耐酸", "耐電撃", "耐火炎", + "耐冷気", "耐毒", "耐恐怖", "耐閃光", "耐暗黒", "耐盲目", "耐混乱", "耐轟音", "耐破片", "耐地獄", "耐因果混乱", "耐カオス", "耐劣化", "", "", "人間倍打", + "", "", "反魔法", "", "", "警告", "", "", "", "浮遊", "永久光源", "可視透明", "テレパシー", "遅消化", "急速回復", "", "", "", "", "", "", "", "", + "テレポート", "", "", "攻撃", "防御", + + NULL }; + +#else + +concptr essence_name[] = { "strength", "intelligen.", "wisdom", "dexterity", "constitut.", "charisma", "magic mast.", "", "stealth", "serching", "infravision", + "digging", "speed", "extra atk", "chaos brand", "vampiric", "slay animal", "slay evil", "slay undead", "slay demon", "slay orc", "slay troll", "slay giant", + "slay dragon", "", "", "quake", "pois. brand", "acid brand", "elec. brand", "fire brand", "cold brand", "sustain", "", "", "", "", "", "", "", "immunity", + "", "", "", "", "reflection", "free action", "hold exp", "res. acid", "res. elec.", "res. fire", "res. cold", "res. poison", "res. fear", "res. light", + "res. dark", "res. blind", "res.confuse", "res. sound", "res. shard", "res. nether", "res. nexus", "res. chaos", "res. disen.", "", "", "slay human", "", + "", "anti magic", "", "", "warning", "", "", "", "levitation", "perm. light", "see invis.", "telepathy", "slow dige.", "regen.", "", "", "", "", "", "", "", + "", "teleport", "", "", "weapon enc.", "armor enc.", + + NULL }; +#endif + +static concptr const kaji_tips[5] = { +#ifdef JP + "現在持っているエッセンスの一覧を表示する。", + "アイテムからエッセンスを取り出す。エッセンスを取られたアイテムは全く魔法がかかっていない初期状態に戻る。", + "既にエッセンスが付加されたアイテムからエッセンスのみ消し去る。エッセンスは手に入らない。", + "アイテムにエッセンスを付加する。既にエッセンスが付加されたアイテムやアーティファクトには付加できない。", + "武器や防具を強化したり、攻撃で傷つかないようにしたりする。エッセンスが付加されたアイテムやアーティファクトに対しても使用できる。", +#else + "Display essences you have.", + "Extract essences from an item. The item become non magical.", + "Remove added essences from an equipment which was improved before. The removed essence will be ruined.", + "Add essences to an item. The improved items or artifacts cannot be reimprove.", + "Enchant an equipment or make an equiment element-proofed. The improved items and artifacts can be enchanted too.", +#endif +}; + +/*! + * @brief 所持しているエッセンス一覧を表示する + * @return なし + */ +static void display_essence(player_type *creature_ptr) +{ + int i, num = 0; + + screen_save(); + for (i = 1; i < 22; i++) { + prt("", i, 0); + } + prt(_("エッセンス 個数 エッセンス 個数 エッセンス 個数", "Essence Num Essence Num Essence Num "), 1, 8); + for (i = 0; essence_name[i]; i++) { + if (!essence_name[i][0]) + continue; + prt(format("%-11s %5d", essence_name[i], creature_ptr->magic_num1[i]), 2 + num % 21, 8 + num / 21 * 22); + num++; + } + prt(_("現在所持しているエッセンス", "List of all essences you have."), 0, 0); + (void)inkey(); + screen_load(); + return; +} + +/*! + * @brief エッセンスの抽出処理 + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +static void drain_essence(player_type *creature_ptr) +{ + int drain_value[sizeof(creature_ptr->magic_num1) / sizeof(s32b)]; + size_t i; + OBJECT_IDX item; + int dec = 4; + bool observe = FALSE; + int old_ds, old_dd, old_to_h, old_to_d, old_ac, old_to_a, old_pval, old_name2; + TIME_EFFECT old_timeout; + BIT_FLAGS old_flgs[TR_FLAG_SIZE], new_flgs[TR_FLAG_SIZE]; + object_type *o_ptr; + concptr q, s; + POSITION iy, ix; + byte marked; + ITEM_NUMBER number; + OBJECT_IDX next_o_idx; + WEIGHT weight; + + for (i = 0; i < sizeof(drain_value) / sizeof(int); i++) + drain_value[i] = 0; + + item_tester_hook = object_is_weapon_armour_ammo; + + q = _("どのアイテムから抽出しますか?", "Extract from which item? "); + s = _("抽出できるアイテムがありません。", "You have nothing you can extract from."); + + o_ptr = choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0); + if (!o_ptr) + return; + + if (object_is_known(o_ptr) && !object_is_nameless(creature_ptr, o_ptr)) { + GAME_TEXT o_name[MAX_NLEN]; + describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); + if (!get_check(format(_("本当に%sから抽出してよろしいですか?", "Really extract from %s? "), o_name))) + return; + } + + take_turn(creature_ptr, 100); + + object_flags(creature_ptr, o_ptr, old_flgs); + if (have_flag(old_flgs, TR_KILL_DRAGON)) + add_flag(old_flgs, TR_SLAY_DRAGON); + if (have_flag(old_flgs, TR_KILL_ANIMAL)) + add_flag(old_flgs, TR_SLAY_ANIMAL); + if (have_flag(old_flgs, TR_KILL_EVIL)) + add_flag(old_flgs, TR_SLAY_EVIL); + if (have_flag(old_flgs, TR_KILL_UNDEAD)) + add_flag(old_flgs, TR_SLAY_UNDEAD); + if (have_flag(old_flgs, TR_KILL_DEMON)) + add_flag(old_flgs, TR_SLAY_DEMON); + if (have_flag(old_flgs, TR_KILL_ORC)) + add_flag(old_flgs, TR_SLAY_ORC); + if (have_flag(old_flgs, TR_KILL_TROLL)) + add_flag(old_flgs, TR_SLAY_TROLL); + if (have_flag(old_flgs, TR_KILL_GIANT)) + add_flag(old_flgs, TR_SLAY_GIANT); + if (have_flag(old_flgs, TR_KILL_HUMAN)) + add_flag(old_flgs, TR_SLAY_HUMAN); + + old_to_a = o_ptr->to_a; + old_ac = o_ptr->ac; + old_to_h = o_ptr->to_h; + old_to_d = o_ptr->to_d; + old_ds = o_ptr->ds; + old_dd = o_ptr->dd; + old_pval = o_ptr->pval; + old_name2 = o_ptr->name2; + old_timeout = o_ptr->timeout; + if (o_ptr->curse_flags & (TRC_CURSED | TRC_HEAVY_CURSE | TRC_PERMA_CURSE)) + dec--; + if (have_flag(old_flgs, TR_ADD_L_CURSE)) + dec--; + if (have_flag(old_flgs, TR_ADD_H_CURSE)) + dec--; + if (have_flag(old_flgs, TR_AGGRAVATE)) + dec--; + if (have_flag(old_flgs, TR_NO_TELE)) + dec--; + if (have_flag(old_flgs, TR_DRAIN_EXP)) + dec--; + if (have_flag(old_flgs, TR_DRAIN_HP)) + dec--; + if (have_flag(old_flgs, TR_DRAIN_MANA)) + dec--; + if (have_flag(old_flgs, TR_CALL_ANIMAL)) + dec--; + if (have_flag(old_flgs, TR_CALL_DEMON)) + dec--; + if (have_flag(old_flgs, TR_CALL_DRAGON)) + dec--; + if (have_flag(old_flgs, TR_CALL_UNDEAD)) + dec--; + if (have_flag(old_flgs, TR_COWARDICE)) + dec--; + if (have_flag(old_flgs, TR_LOW_MELEE)) + dec--; + if (have_flag(old_flgs, TR_LOW_AC)) + dec--; + if (have_flag(old_flgs, TR_LOW_MAGIC)) + dec--; + if (have_flag(old_flgs, TR_FAST_DIGEST)) + dec--; + if (have_flag(old_flgs, TR_SLOW_REGEN)) + dec--; + if (have_flag(old_flgs, TR_TY_CURSE)) + dec--; + + iy = o_ptr->iy; + ix = o_ptr->ix; + next_o_idx = o_ptr->next_o_idx; + marked = o_ptr->marked; + weight = o_ptr->weight; + number = o_ptr->number; + + object_prep(creature_ptr, o_ptr, o_ptr->k_idx); + + o_ptr->iy = iy; + o_ptr->ix = ix; + o_ptr->next_o_idx = next_o_idx; + o_ptr->marked = marked; + o_ptr->number = number; + if (o_ptr->tval == TV_DRAG_ARMOR) + o_ptr->timeout = old_timeout; + if (item >= 0) + creature_ptr->total_weight += (o_ptr->weight * o_ptr->number - weight * number); + o_ptr->ident |= (IDENT_FULL_KNOWN); + object_aware(creature_ptr, o_ptr); + object_known(o_ptr); + + object_flags(creature_ptr, o_ptr, new_flgs); + + for (i = 0; essence_info[i].add_name; i++) { + essence_type *es_ptr = &essence_info[i]; + PARAMETER_VALUE pval = 0; + + if (es_ptr->add < TR_FLAG_MAX && is_pval_flag(es_ptr->add) && old_pval) + pval = (have_flag(new_flgs, es_ptr->add)) ? old_pval - o_ptr->pval : old_pval; + + if (es_ptr->add < TR_FLAG_MAX && (!have_flag(new_flgs, es_ptr->add) || pval) && have_flag(old_flgs, es_ptr->add)) { + if (pval) { + drain_value[es_ptr->essence] += 10 * pval; + } else if (es_ptr->essence != -2) { + drain_value[es_ptr->essence] += 10; + } else if (es_ptr->add == TR_SH_FIRE) { + drain_value[TR_BRAND_FIRE] += 10; + drain_value[TR_RES_FIRE] += 10; + } else if (es_ptr->add == TR_SH_ELEC) { + drain_value[TR_BRAND_ELEC] += 10; + drain_value[TR_RES_ELEC] += 10; + } else if (es_ptr->add == TR_SH_COLD) { + drain_value[TR_BRAND_COLD] += 10; + drain_value[TR_RES_COLD] += 10; + } else if (es_ptr->add == TR_LITE_2) { + drain_value[TR_LITE_1] += 20; + } else if (es_ptr->add == TR_LITE_3) { + drain_value[TR_LITE_1] += 30; + } + } + } + + if ((have_flag(old_flgs, TR_FORCE_WEAPON)) && !(have_flag(new_flgs, TR_FORCE_WEAPON))) { + drain_value[TR_INT] += 5; + drain_value[TR_WIS] += 5; + } + if ((have_flag(old_flgs, TR_VORPAL)) && !(have_flag(new_flgs, TR_VORPAL))) { + drain_value[TR_BRAND_POIS] += 5; + drain_value[TR_BRAND_ACID] += 5; + drain_value[TR_BRAND_ELEC] += 5; + drain_value[TR_BRAND_FIRE] += 5; + drain_value[TR_BRAND_COLD] += 5; + } + if ((have_flag(old_flgs, TR_DEC_MANA)) && !(have_flag(new_flgs, TR_DEC_MANA))) { + drain_value[TR_INT] += 10; + } + if ((have_flag(old_flgs, TR_XTRA_MIGHT)) && !(have_flag(new_flgs, TR_XTRA_MIGHT))) { + drain_value[TR_STR] += 10; + } + if ((have_flag(old_flgs, TR_XTRA_SHOTS)) && !(have_flag(new_flgs, TR_XTRA_SHOTS))) { + drain_value[TR_DEX] += 10; + } + if (old_name2 == EGO_2WEAPON) { + drain_value[TR_DEX] += 20; + } + if (object_is_weapon_ammo(o_ptr)) { + if (old_ds > o_ptr->ds) + drain_value[TR_ES_ATTACK] += (old_ds - o_ptr->ds) * 10; + + if (old_dd > o_ptr->dd) + drain_value[TR_ES_ATTACK] += (old_dd - o_ptr->dd) * 10; + } + if (old_to_h > o_ptr->to_h) + drain_value[TR_ES_ATTACK] += (old_to_h - o_ptr->to_h) * 10; + if (old_to_d > o_ptr->to_d) + drain_value[TR_ES_ATTACK] += (old_to_d - o_ptr->to_d) * 10; + if (old_ac > o_ptr->ac) + drain_value[TR_ES_AC] += (old_ac - o_ptr->ac) * 10; + if (old_to_a > o_ptr->to_a) + drain_value[TR_ES_AC] += (old_to_a - o_ptr->to_a) * 10; + + for (i = 0; i < sizeof(drain_value) / sizeof(int); i++) { + drain_value[i] *= number; + drain_value[i] = drain_value[i] * dec / 4; + drain_value[i] = MAX(drain_value[i], 0); + if ((o_ptr->tval >= TV_SHOT) && (o_ptr->tval <= TV_BOLT)) + drain_value[i] /= 10; + if (drain_value[i]) { + observe = TRUE; + } + } + if (!observe) { + msg_print(_("エッセンスは抽出できませんでした。", "You were not able to extract any essence.")); + } else { + msg_print(_("抽出したエッセンス:", "Extracted essences:")); + + for (i = 0; essence_name[i]; i++) { + if (!essence_name[i][0]) + continue; + if (!drain_value[i]) + continue; + + creature_ptr->magic_num1[i] += drain_value[i]; + creature_ptr->magic_num1[i] = MIN(20000, creature_ptr->magic_num1[i]); + msg_print(NULL); + msg_format("%s...%d%s", essence_name[i], drain_value[i], _("。", ". ")); + } + } + + /* Apply autodestroy/inscription to the drained item */ + autopick_alter_item(creature_ptr, item, TRUE); + creature_ptr->update |= (PU_COMBINE | PU_REORDER); + creature_ptr->window |= (PW_INVEN); +} + +/*! + * @brief 付加するエッセンスの大別を選択する + * @return 選んだエッセンスの大別ID + */ +static COMMAND_CODE choose_essence(void) +{ + COMMAND_CODE mode = 0; + char choice; + COMMAND_CODE menu_line = (use_menu ? 1 : 0); + +#ifdef JP + concptr menu_name[] = { "武器属性", "耐性", "能力", "数値", "スレイ", "ESP", "その他" }; +#else + concptr menu_name[] = { "Brand weapon", "Resistance", "Ability", "Magic number", "Slay", "ESP", "Others" }; +#endif + const COMMAND_CODE mode_max = 7; + + if (repeat_pull(&mode) && 1 <= mode && mode <= mode_max) + return mode; + mode = 0; + if (use_menu) { + screen_save(); + + while (!mode) { + int i; + for (i = 0; i < mode_max; i++) +#ifdef JP + prt(format(" %s %s", (menu_line == 1 + i) ? "》" : " ", menu_name[i]), 2 + i, 14); + prt("どの種類のエッセンス付加を行いますか?", 0, 0); +#else + prt(format(" %s %s", (menu_line == 1 + i) ? "> " : " ", menu_name[i]), 2 + i, 14); + prt("Choose from menu.", 0, 0); +#endif + + choice = inkey(); + switch (choice) { + case ESCAPE: + case 'z': + case 'Z': + screen_load(); + return 0; + case '2': + case 'j': + case 'J': + menu_line++; + break; + case '8': + case 'k': + case 'K': + menu_line += mode_max - 1; + break; + case '\r': + case '\n': + case 'x': + case 'X': + mode = menu_line; + break; + } + if (menu_line > mode_max) + menu_line -= mode_max; + } + screen_load(); + } else { + screen_save(); + while (!mode) { + int i; + + for (i = 0; i < mode_max; i++) + prt(format(" %c) %s", 'a' + i, menu_name[i]), 2 + i, 14); + + if (!get_com(_("何を付加しますか:", "Command :"), &choice, TRUE)) { + screen_load(); + return 0; + } + + if (isupper(choice)) + choice = (char)tolower(choice); + + if ('a' <= choice && choice <= 'a' + (char)mode_max - 1) + mode = (int)choice - 'a' + 1; + } + screen_load(); + } + + repeat_push(mode); + return mode; +} + +/*! + * @brief エッセンスを実際に付加する + * @param mode エッセンスの大別ID + * @return なし + */ +static void add_essence(player_type *creature_ptr, ESSENCE_IDX mode) +{ + OBJECT_IDX item; + int max_num = 0; + COMMAND_CODE i; + bool flag, redraw; + char choice; + concptr q, s; + object_type *o_ptr; + int ask = TRUE; + char out_val[160]; + int num[22]; + GAME_TEXT o_name[MAX_NLEN]; + int use_essence; + essence_type *es_ptr; + bool able[22] = { 0 }; + tval_type tval = 0; + int menu_line = (use_menu ? 1 : 0); + + for (i = 0; essence_info[i].add_name; i++) { + es_ptr = &essence_info[i]; + + if (es_ptr->type != mode) + continue; + num[max_num++] = i; + } + + if (!repeat_pull(&i) || i < 0 || i >= max_num) { + flag = FALSE; + redraw = FALSE; + + (void)strnfmt(out_val, 78, _("('*'で一覧, ESCで中断) どの能力を付加しますか?", "(*=List, ESC=exit) Add which ability? ")); + if (use_menu) + screen_save(); + + choice = (always_show_list || use_menu) ? ESCAPE : 1; + while (!flag) { + if (choice == ESCAPE) + choice = ' '; + else if (!get_com(out_val, &choice, FALSE)) + break; + + if (use_menu && choice != ' ') { + switch (choice) { + case '0': { + screen_load(); + return; + } + + case '8': + case 'k': + case 'K': { + menu_line += (max_num - 1); + break; + } + + case '2': + case 'j': + case 'J': { + menu_line++; + break; + } + + case '4': + case 'h': + case 'H': { + menu_line = 1; + break; + } + case '6': + case 'l': + case 'L': { + menu_line = max_num; + break; + } + + case 'x': + case 'X': + case '\r': + case '\n': { + i = menu_line - 1; + ask = FALSE; + break; + } + } + if (menu_line > max_num) + menu_line -= max_num; + } + /* Request redraw */ + if ((choice == ' ') || (choice == '*') || (choice == '?') || (use_menu && ask)) { + /* Show the list */ + if (!redraw || use_menu) { + byte y, x = 10; + int ctr; + char dummy[80], dummy2[80]; + byte col; + + strcpy(dummy, ""); + redraw = TRUE; + if (!use_menu) + screen_save(); + + for (y = 1; y < 24; y++) + prt("", y, x); + + /* Print header(s) */ +#ifdef JP + prt(format(" %-43s %6s/%s", "能力(必要エッセンス)", "必要数", "所持数"), 1, x); + +#else + prt(format(" %-43s %6s/%s", "Ability (needed essence)", "Needs", "Possess"), 1, x); +#endif + /* Print list */ + for (ctr = 0; ctr < max_num; ctr++) { + es_ptr = &essence_info[num[ctr]]; + + if (use_menu) { + if (ctr == (menu_line - 1)) + strcpy(dummy, _("》 ", "> ")); + else + strcpy(dummy, " "); + + } + /* letter/number for power selection */ + else { + sprintf(dummy, "%c) ", I2A(ctr)); + } + + strcat(dummy, es_ptr->add_name); + + col = TERM_WHITE; + able[ctr] = TRUE; + + if (es_ptr->essence != -1) { + strcat(dummy, format("(%s)", essence_name[es_ptr->essence])); + if (creature_ptr->magic_num1[es_ptr->essence] < es_ptr->value) + able[ctr] = FALSE; + } else { + switch (es_ptr->add) { + case ESSENCE_SH_FIRE: + strcat(dummy, _("(焼棄+耐火炎)", "(brand fire + res.fire)")); + if (creature_ptr->magic_num1[TR_BRAND_FIRE] < es_ptr->value) + able[ctr] = FALSE; + if (creature_ptr->magic_num1[TR_RES_FIRE] < es_ptr->value) + able[ctr] = FALSE; + break; + case ESSENCE_SH_ELEC: + strcat(dummy, _("(電撃+耐電撃)", "(brand elec. + res. elec.)")); + if (creature_ptr->magic_num1[TR_BRAND_ELEC] < es_ptr->value) + able[ctr] = FALSE; + if (creature_ptr->magic_num1[TR_RES_ELEC] < es_ptr->value) + able[ctr] = FALSE; + break; + case ESSENCE_SH_COLD: + strcat(dummy, _("(凍結+耐冷気)", "(brand cold + res. cold)")); + if (creature_ptr->magic_num1[TR_BRAND_COLD] < es_ptr->value) + able[ctr] = FALSE; + if (creature_ptr->magic_num1[TR_RES_COLD] < es_ptr->value) + able[ctr] = FALSE; + break; + case ESSENCE_RESISTANCE: + strcat(dummy, _("(耐火炎+耐冷気+耐電撃+耐酸)", "(r.fire+r.cold+r.elec+r.acid)")); + if (creature_ptr->magic_num1[TR_RES_FIRE] < es_ptr->value) + able[ctr] = FALSE; + if (creature_ptr->magic_num1[TR_RES_COLD] < es_ptr->value) + able[ctr] = FALSE; + if (creature_ptr->magic_num1[TR_RES_ELEC] < es_ptr->value) + able[ctr] = FALSE; + if (creature_ptr->magic_num1[TR_RES_ACID] < es_ptr->value) + able[ctr] = FALSE; + break; + case ESSENCE_SUSTAIN: + strcat(dummy, _("(耐火炎+耐冷気+耐電撃+耐酸)", "(r.fire+r.cold+r.elec+r.acid)")); + if (creature_ptr->magic_num1[TR_RES_FIRE] < es_ptr->value) + able[ctr] = FALSE; + if (creature_ptr->magic_num1[TR_RES_COLD] < es_ptr->value) + able[ctr] = FALSE; + if (creature_ptr->magic_num1[TR_RES_ELEC] < es_ptr->value) + able[ctr] = FALSE; + if (creature_ptr->magic_num1[TR_RES_ACID] < es_ptr->value) + able[ctr] = FALSE; + break; + } + } + + if (!able[ctr]) + col = TERM_RED; + + if (es_ptr->essence != -1) { + sprintf(dummy2, "%-49s %3d/%d", dummy, es_ptr->value, (int)creature_ptr->magic_num1[es_ptr->essence]); + } else { + sprintf(dummy2, "%-49s %3d/(\?\?)", dummy, es_ptr->value); + } + + c_prt(col, dummy2, ctr + 2, x); + } + } + + /* Hide the list */ + else { + /* Hide list */ + redraw = FALSE; + screen_load(); + } + + /* Redo asking */ + continue; + } + + if (!use_menu) { + /* Note verify */ + ask = (isupper(choice)); + + /* Lowercase */ + if (ask) + choice = (char)tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + } + + /* Totally Illegal */ + if ((i < 0) || (i >= max_num) || !able[i]) { + bell(); + continue; + } + + /* Verify it */ + if (ask) { + char tmp_val[160]; + + /* Prompt */ + (void)strnfmt(tmp_val, 78, _("%sを付加しますか? ", "Add the abilitiy of %s? "), essence_info[num[i]].add_name); + + /* Belay that order */ + if (!get_check(tmp_val)) + continue; + } + + /* Stop the loop */ + flag = TRUE; + } + if (redraw) + screen_load(); + + if (!flag) + return; + + repeat_push(i); + } + es_ptr = &essence_info[num[i]]; + + if (es_ptr->add == ESSENCE_SLAY_GLOVE) + tval = TV_GLOVES; + else if (mode == 1 || mode == 5) + item_tester_hook = item_tester_hook_melee_ammo; + else if (es_ptr->add == ESSENCE_ATTACK) + item_tester_hook = object_allow_enchant_weapon; + else if (es_ptr->add == ESSENCE_AC) + item_tester_hook = object_is_armour; + else + item_tester_hook = object_is_weapon_armour_ammo; + + q = _("どのアイテムを改良しますか?", "Improve which item? "); + s = _("改良できるアイテムがありません。", "You have nothing to improve."); + + o_ptr = choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), tval); + if (!o_ptr) + return; + + if ((mode != 10) && (object_is_artifact(o_ptr) || object_is_smith(creature_ptr, o_ptr))) { + msg_print(_("そのアイテムはこれ以上改良できない。", "This item can not be improved any further.")); + return; + } + + describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); + + use_essence = es_ptr->value; + if ((o_ptr->tval >= TV_SHOT) && (o_ptr->tval <= TV_BOLT)) + use_essence = (use_essence + 9) / 10; + if (o_ptr->number > 1) { + use_essence *= o_ptr->number; + msg_format(_("%d個あるのでエッセンスは%d必要です。", "For %d items, it will take %d essences."), o_ptr->number, use_essence); + } + + if (es_ptr->essence != -1) { + if (creature_ptr->magic_num1[es_ptr->essence] < use_essence) { + msg_print(_("エッセンスが足りない。", "You don't have enough essences.")); + return; + } + if (is_pval_flag(es_ptr->add)) { + if (o_ptr->pval < 0) { + msg_print(_("このアイテムの能力修正を強化することはできない。", "You cannot increase magic number of this item.")); + return; + } else if (es_ptr->add == TR_BLOWS) { + if (o_ptr->pval > 1) { + if (!get_check(_("修正値は1になります。よろしいですか?", "The magic number of this weapon will become 1. Are you sure? "))) + return; + } + + o_ptr->pval = 1; + msg_format(_("エッセンスを%d個使用します。", "It will take %d essences."), use_essence); + } else if (o_ptr->pval > 0) { + use_essence *= o_ptr->pval; + msg_format(_("エッセンスを%d個使用します。", "It will take %d essences."), use_essence); + } else { + char tmp[80]; + char tmp_val[160]; + PARAMETER_VALUE pval; + PARAMETER_VALUE limit = MIN(5, creature_ptr->magic_num1[es_ptr->essence] / es_ptr->value); + + sprintf(tmp, _("いくつ付加しますか? (1-%d): ", "Enchant how many? (1-%d): "), limit); + strcpy(tmp_val, "1"); + + if (!get_string(tmp, tmp_val, 1)) + return; + pval = (PARAMETER_VALUE)atoi(tmp_val); + if (pval > limit) + pval = limit; + else if (pval < 1) + pval = 1; + o_ptr->pval += pval; + use_essence *= pval; + msg_format(_("エッセンスを%d個使用します。", "It will take %d essences."), use_essence); + } + + if (creature_ptr->magic_num1[es_ptr->essence] < use_essence) { + msg_print(_("エッセンスが足りない。", "You don't have enough essences.")); + return; + } + } else if (es_ptr->add == ESSENCE_SLAY_GLOVE) { + char tmp_val[160]; + int val; + HIT_PROB get_to_h; + HIT_POINT get_to_d; + + strcpy(tmp_val, "1"); + if (!get_string(format(_("いくつ付加しますか? (1-%d):", "Enchant how many? (1-%d):"), creature_ptr->lev / 7 + 3), tmp_val, 2)) + return; + val = atoi(tmp_val); + if (val > creature_ptr->lev / 7 + 3) + val = creature_ptr->lev / 7 + 3; + else if (val < 1) + val = 1; + use_essence *= val; + msg_format(_("エッセンスを%d個使用します。", "It will take %d essences."), use_essence); + if (creature_ptr->magic_num1[es_ptr->essence] < use_essence) { + msg_print(_("エッセンスが足りない。", "You don't have enough essences.")); + return; + } + get_to_h = ((val + 1) / 2 + randint0(val / 2 + 1)); + get_to_d = ((val + 1) / 2 + randint0(val / 2 + 1)); + o_ptr->xtra4 = (get_to_h << 8) + get_to_d; + o_ptr->to_h += get_to_h; + o_ptr->to_d += get_to_d; + } + creature_ptr->magic_num1[es_ptr->essence] -= use_essence; + if (es_ptr->add == ESSENCE_ATTACK) { + if ((o_ptr->to_h >= creature_ptr->lev / 5 + 5) && (o_ptr->to_d >= creature_ptr->lev / 5 + 5)) { + msg_print(_("改良に失敗した。", "You failed to enchant.")); + take_turn(creature_ptr, 100); + return; + } else { + if (o_ptr->to_h < creature_ptr->lev / 5 + 5) + o_ptr->to_h++; + if (o_ptr->to_d < creature_ptr->lev / 5 + 5) + o_ptr->to_d++; + } + } else if (es_ptr->add == ESSENCE_AC) { + if (o_ptr->to_a >= creature_ptr->lev / 5 + 5) { + msg_print(_("改良に失敗した。", "You failed to enchant.")); + take_turn(creature_ptr, 100); + return; + } else { + if (o_ptr->to_a < creature_ptr->lev / 5 + 5) + o_ptr->to_a++; + } + } else { + o_ptr->xtra3 = es_ptr->add + 1; + } + } else { + bool success = TRUE; + + switch (es_ptr->add) { + case ESSENCE_SH_FIRE: + if ((creature_ptr->magic_num1[TR_BRAND_FIRE] < use_essence) || (creature_ptr->magic_num1[TR_RES_FIRE] < use_essence)) { + success = FALSE; + break; + } + creature_ptr->magic_num1[TR_BRAND_FIRE] -= use_essence; + creature_ptr->magic_num1[TR_RES_FIRE] -= use_essence; + break; + case ESSENCE_SH_ELEC: + if ((creature_ptr->magic_num1[TR_BRAND_ELEC] < use_essence) || (creature_ptr->magic_num1[TR_RES_ELEC] < use_essence)) { + success = FALSE; + break; + } + creature_ptr->magic_num1[TR_BRAND_ELEC] -= use_essence; + creature_ptr->magic_num1[TR_RES_ELEC] -= use_essence; + break; + case ESSENCE_SH_COLD: + if ((creature_ptr->magic_num1[TR_BRAND_COLD] < use_essence) || (creature_ptr->magic_num1[TR_RES_COLD] < use_essence)) { + success = FALSE; + break; + } + creature_ptr->magic_num1[TR_BRAND_COLD] -= use_essence; + creature_ptr->magic_num1[TR_RES_COLD] -= use_essence; + break; + case ESSENCE_RESISTANCE: + case ESSENCE_SUSTAIN: + if ((creature_ptr->magic_num1[TR_RES_ACID] < use_essence) || (creature_ptr->magic_num1[TR_RES_ELEC] < use_essence) + || (creature_ptr->magic_num1[TR_RES_FIRE] < use_essence) || (creature_ptr->magic_num1[TR_RES_COLD] < use_essence)) { + success = FALSE; + break; + } + creature_ptr->magic_num1[TR_RES_ACID] -= use_essence; + creature_ptr->magic_num1[TR_RES_ELEC] -= use_essence; + creature_ptr->magic_num1[TR_RES_FIRE] -= use_essence; + creature_ptr->magic_num1[TR_RES_COLD] -= use_essence; + break; + } + if (!success) { + msg_print(_("エッセンスが足りない。", "You don't have enough essences.")); + return; + } + if (es_ptr->add == ESSENCE_SUSTAIN) { + add_flag(o_ptr->art_flags, TR_IGNORE_ACID); + add_flag(o_ptr->art_flags, TR_IGNORE_ELEC); + add_flag(o_ptr->art_flags, TR_IGNORE_FIRE); + add_flag(o_ptr->art_flags, TR_IGNORE_COLD); + } else { + o_ptr->xtra3 = es_ptr->add + 1; + } + } + + take_turn(creature_ptr, 100); + _(msg_format("%sに%sの能力を付加しました。", o_name, es_ptr->add_name), msg_format("You have added ability of %s to %s.", es_ptr->add_name, o_name)); + creature_ptr->update |= (PU_COMBINE | PU_REORDER); + creature_ptr->window |= (PW_INVEN); +} + +/*! + * @brief エッセンスを消去する + * @return なし + */ +static void erase_essence(player_type *creature_ptr) +{ + OBJECT_IDX item; + concptr q, s; + object_type *o_ptr; + GAME_TEXT o_name[MAX_NLEN]; + BIT_FLAGS flgs[TR_FLAG_SIZE]; + + item_tester_hook = object_is_smith; + + q = _("どのアイテムのエッセンスを消去しますか?", "Remove from which item? "); + s = _("エッセンスを付加したアイテムがありません。", "You have nothing to remove essence."); + + o_ptr = choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), 0); + if (!o_ptr) + return; + + describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); + if (!get_check(format(_("よろしいですか? [%s]", "Are you sure? [%s]"), o_name))) + return; + + take_turn(creature_ptr, 100); + + if (o_ptr->xtra3 == 1 + ESSENCE_SLAY_GLOVE) { + o_ptr->to_h -= (o_ptr->xtra4 >> 8); + o_ptr->to_d -= (o_ptr->xtra4 & 0x000f); + o_ptr->xtra4 = 0; + if (o_ptr->to_h < 0) + o_ptr->to_h = 0; + if (o_ptr->to_d < 0) + o_ptr->to_d = 0; + } + o_ptr->xtra3 = 0; + object_flags(creature_ptr, o_ptr, flgs); + if (!(have_pval_flags(flgs))) + o_ptr->pval = 0; + msg_print(_("エッセンスを取り去った。", "You removed all essence you have added.")); + creature_ptr->update |= (PU_COMBINE | PU_REORDER); + creature_ptr->window |= (PW_INVEN); +} + +/*! + * @brief 鍛冶コマンドのメインルーチン + * @param only_browse TRUEならばエッセンス一覧の表示のみを行う + * @return なし + */ +void do_cmd_kaji(player_type *creature_ptr, bool only_browse) +{ + COMMAND_CODE mode = 0; + char choice; + + COMMAND_CODE menu_line = (use_menu ? 1 : 0); + + if (!only_browse) { + if (cmd_limit_confused(creature_ptr)) + return; + if (cmd_limit_blind(creature_ptr)) + return; + if (cmd_limit_image(creature_ptr)) + return; + } + + if (!(repeat_pull(&mode) && 1 <= mode && mode <= 5)) { + if (only_browse) + screen_save(); + do { + if (!only_browse) + screen_save(); + if (use_menu) { + while (!mode) { +#ifdef JP + prt(format(" %s エッセンス一覧", (menu_line == 1) ? "》" : " "), 2, 14); + prt(format(" %s エッセンス抽出", (menu_line == 2) ? "》" : " "), 3, 14); + prt(format(" %s エッセンス消去", (menu_line == 3) ? "》" : " "), 4, 14); + prt(format(" %s エッセンス付加", (menu_line == 4) ? "》" : " "), 5, 14); + prt(format(" %s 武器/防具強化", (menu_line == 5) ? "》" : " "), 6, 14); + prt(format("どの種類の技術を%sますか?", only_browse ? "調べ" : "使い"), 0, 0); +#else + prt(format(" %s List essences", (menu_line == 1) ? "> " : " "), 2, 14); + prt(format(" %s Extract essence", (menu_line == 2) ? "> " : " "), 3, 14); + prt(format(" %s Remove essence", (menu_line == 3) ? "> " : " "), 4, 14); + prt(format(" %s Add essence", (menu_line == 4) ? "> " : " "), 5, 14); + prt(format(" %s Enchant weapon/armor", (menu_line == 5) ? "> " : " "), 6, 14); + prt(format("Choose command from menu."), 0, 0); +#endif + choice = inkey(); + switch (choice) { + case ESCAPE: + case 'z': + case 'Z': + screen_load(); + return; + case '2': + case 'j': + case 'J': + menu_line++; + break; + case '8': + case 'k': + case 'K': + menu_line += 4; + break; + case '\r': + case '\n': + case 'x': + case 'X': + mode = menu_line; + break; + } + if (menu_line > 5) + menu_line -= 5; + } + } + + else { + while (!mode) { + prt(_(" a) エッセンス一覧", " a) List essences"), 2, 14); + prt(_(" b) エッセンス抽出", " b) Extract essence"), 3, 14); + prt(_(" c) エッセンス消去", " c) Remove essence"), 4, 14); + prt(_(" d) エッセンス付加", " d) Add essence"), 5, 14); + prt(_(" e) 武器/防具強化", " e) Enchant weapon/armor"), 6, 14); +#ifdef JP + if (!get_com(format("どの能力を%sますか:", only_browse ? "調べ" : "使い"), &choice, TRUE)) +#else + if (!get_com("Command :", &choice, TRUE)) +#endif + { + screen_load(); + return; + } + switch (choice) { + case 'A': + case 'a': + mode = 1; + break; + case 'B': + case 'b': + mode = 2; + break; + case 'C': + case 'c': + mode = 3; + break; + case 'D': + case 'd': + mode = 4; + break; + case 'E': + case 'e': + mode = 5; + break; + } + } + } + + if (only_browse) { + char temp[62 * 5]; + int line, j; + + /* Clear lines, position cursor (really should use strlen here) */ + term_erase(14, 21, 255); + term_erase(14, 20, 255); + term_erase(14, 19, 255); + term_erase(14, 18, 255); + term_erase(14, 17, 255); + term_erase(14, 16, 255); + + shape_buffer(kaji_tips[mode - 1], 62, temp, sizeof(temp)); + for (j = 0, line = 17; temp[j]; j += (1 + strlen(&temp[j]))) { + prt(&temp[j], line, 15); + line++; + } + mode = 0; + } + if (!only_browse) + screen_load(); + } while (only_browse); + repeat_push(mode); + } + switch (mode) { + case 1: + display_essence(creature_ptr); + break; + case 2: + drain_essence(creature_ptr); + break; + case 3: + erase_essence(creature_ptr); + break; + case 4: + mode = choose_essence(); + if (mode == 0) + break; + add_essence(creature_ptr, mode); + break; + case 5: + add_essence(creature_ptr, 10); + break; + } +} diff --git a/src/cmd-item/cmd-smith.h b/src/cmd-item/cmd-smith.h new file mode 100644 index 000000000..be36bc934 --- /dev/null +++ b/src/cmd-item/cmd-smith.h @@ -0,0 +1,24 @@ +#pragma once + +#include "system/angband.h" + +/* + * Special essence id for Weapon smith + */ +#define MIN_SPECIAL_ESSENCE 200 + +#define ESSENCE_ATTACK (MIN_SPECIAL_ESSENCE + 0) +#define ESSENCE_AC (MIN_SPECIAL_ESSENCE + 1) +#define ESSENCE_TMP_RES_ACID (MIN_SPECIAL_ESSENCE + 2) +#define ESSENCE_TMP_RES_ELEC (MIN_SPECIAL_ESSENCE + 3) +#define ESSENCE_TMP_RES_FIRE (MIN_SPECIAL_ESSENCE + 4) +#define ESSENCE_TMP_RES_COLD (MIN_SPECIAL_ESSENCE + 5) +#define ESSENCE_SH_FIRE (MIN_SPECIAL_ESSENCE + 6) +#define ESSENCE_SH_ELEC (MIN_SPECIAL_ESSENCE + 7) +#define ESSENCE_SH_COLD (MIN_SPECIAL_ESSENCE + 8) +#define ESSENCE_RESISTANCE (MIN_SPECIAL_ESSENCE + 9) +#define ESSENCE_SUSTAIN (MIN_SPECIAL_ESSENCE + 10) +#define ESSENCE_SLAY_GLOVE (MIN_SPECIAL_ESSENCE + 11) + +extern concptr essence_name[]; +void do_cmd_kaji(player_type *creature_ptr, bool only_browse); diff --git a/src/cmd-item/cmd-throw.c b/src/cmd-item/cmd-throw.c new file mode 100644 index 000000000..b5549df56 --- /dev/null +++ b/src/cmd-item/cmd-throw.c @@ -0,0 +1,556 @@ +#include "cmd-item/cmd-throw.h" +#include "action/throw-util.h" +#include "action/weapon-shield.h" +#include "art-definition/art-weapon-types.h" +#include "combat/attack-power-table.h" +#include "combat/shoot.h" +#include "combat/slaying.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "effect/spells-effect-util.h" +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "floor/cave.h" +#include "floor/floor-object.h" +#include "floor/geometry.h" +#include "game-option/cheat-types.h" +#include "game-option/special-options.h" +#include "grid/feature-flag-types.h" +#include "grid/grid.h" +#include "inventory/inventory-object.h" +#include "inventory/inventory-slot-types.h" +#include "io/cursor.h" +#include "io/screen-util.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-floor/monster-death.h" +#include "monster-floor/monster-summon.h" +#include "monster-floor/place-monster-types.h" +#include "monster/monster-describer.h" +#include "monster/monster-info.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "object-enchant/tr-types.h" +#include "object-hook/hook-checker.h" +#include "object-hook/hook-expendable.h" +#include "object-hook/hook-weapon.h" +#include "object/item-tester-hooker.h" +#include "object/item-use-flags.h" +#include "object/object-broken.h" +#include "object/object-flags.h" +#include "object/object-generator.h" +#include "object/object-info.h" +#include "object/object-kind.h" +#include "object/object-stack.h" +#include "player/attack-defense-types.h" +#include "player/special-defense-types.h" +#include "player/player-status-table.h" +#include "racial/racial-android.h" +#include "specific-object/torch.h" +#include "status/action-setter.h" +#include "system/floor-type-definition.h" +#include "system/object-type-definition.h" +#include "target/target-checker.h" +#include "target/target-getter.h" +#include "term/screen-processor.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" +#include "view/object-describer.h" +#include "wizard/wizard-messages.h" + +static bool check_throw_boomerang(player_type *creature_ptr, it_type *it_ptr, concptr *q, concptr *s) +{ + if (!it_ptr->boomerang) + return TRUE; + + if (has_melee_weapon(creature_ptr, INVEN_RARM) && has_melee_weapon(creature_ptr, INVEN_LARM)) { + item_tester_hook = item_tester_hook_boomerang; + *q = _("どの武器を投げますか? ", "Throw which it_ptr->item? "); + *s = _("投げる武器がない。", "You have nothing to throw."); + it_ptr->o_ptr = choose_object(creature_ptr, &it_ptr->item, *q, *s, USE_EQUIP, 0); + if (!it_ptr->o_ptr) { + flush(); + return FALSE; + } + + return TRUE; + } + + if (has_melee_weapon(creature_ptr, INVEN_LARM)) { + it_ptr->item = INVEN_LARM; + it_ptr->o_ptr = &creature_ptr->inventory_list[it_ptr->item]; + return TRUE; + } + + it_ptr->item = INVEN_RARM; + it_ptr->o_ptr = &creature_ptr->inventory_list[it_ptr->item]; + return TRUE; +} + +static bool check_what_throw(player_type *creature_ptr, it_type *it_ptr) +{ + if (it_ptr->shuriken >= 0) { + it_ptr->item = it_ptr->shuriken; + it_ptr->o_ptr = &creature_ptr->inventory_list[it_ptr->item]; + return TRUE; + } + + concptr q, s; + if (!check_throw_boomerang(creature_ptr, it_ptr, &q, &s)) + return FALSE; + + q = _("どのアイテムを投げますか? ", "Throw which it_ptr->item? "); + s = _("投げるアイテムがない。", "You have nothing to throw."); + it_ptr->o_ptr = choose_object(creature_ptr, &it_ptr->item, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP, 0); + if (!it_ptr->o_ptr) { + flush(); + return FALSE; + } + + return TRUE; +} + +static bool check_can_throw(player_type *creature_ptr, it_type *it_ptr) +{ + if (!check_what_throw(creature_ptr, it_ptr)) + return FALSE; + + if (object_is_cursed(it_ptr->o_ptr) && (it_ptr->item >= INVEN_RARM)) { + msg_print(_("ふーむ、どうやら呪われているようだ。", "Hmmm, it seems to be cursed.")); + return FALSE; + } + + if (creature_ptr->current_floor_ptr->inside_arena && !it_ptr->boomerang && (it_ptr->o_ptr->tval != TV_SPIKE)) { + msg_print(_("アリーナではアイテムを使えない!", "You're in the arena now. This is hand-to-hand!")); + msg_print(NULL); + return FALSE; + } + + return TRUE; +} + +static void calc_throw_range(player_type *creature_ptr, it_type *it_ptr) +{ + object_copy(it_ptr->q_ptr, it_ptr->o_ptr); + object_flags(creature_ptr, it_ptr->q_ptr, it_ptr->obj_flags); + torch_flags(it_ptr->q_ptr, it_ptr->obj_flags); + distribute_charges(it_ptr->o_ptr, it_ptr->q_ptr, 1); + it_ptr->q_ptr->number = 1; + describe_flavor(creature_ptr, it_ptr->o_name, it_ptr->q_ptr, OD_OMIT_PREFIX); + if (creature_ptr->mighty_throw) + it_ptr->mult += 3; + + int mul = 10 + 2 * (it_ptr->mult - 1); + int div = ((it_ptr->q_ptr->weight > 10) ? it_ptr->q_ptr->weight : 10); + if ((have_flag(it_ptr->obj_flags, TR_THROW)) || it_ptr->boomerang) + div /= 2; + + it_ptr->tdis = (adj_str_blow[creature_ptr->stat_ind[A_STR]] + 20) * mul / div; + if (it_ptr->tdis > mul) + it_ptr->tdis = mul; +} + +static bool calc_throw_grid(player_type *creature_ptr, it_type *it_ptr) +{ + if (it_ptr->shuriken >= 0) { + it_ptr->ty = randint0(101) - 50 + creature_ptr->y; + it_ptr->tx = randint0(101) - 50 + creature_ptr->x; + return TRUE; + } + + project_length = it_ptr->tdis + 1; + DIRECTION dir; + if (!get_aim_dir(creature_ptr, &dir)) + return FALSE; + + it_ptr->tx = creature_ptr->x + 99 * ddx[dir]; + it_ptr->ty = creature_ptr->y + 99 * ddy[dir]; + if ((dir == 5) && target_okay(creature_ptr)) { + it_ptr->tx = target_col; + it_ptr->ty = target_row; + } + + project_length = 0; + return TRUE; +} + +static void reflect_inventory_by_throw(player_type *creature_ptr, it_type *it_ptr) +{ + if ((it_ptr->q_ptr->name1 == ART_MJOLLNIR) || (it_ptr->q_ptr->name1 == ART_AEGISFANG) || it_ptr->boomerang) + it_ptr->return_when_thrown = TRUE; + + if (it_ptr->item < 0) { + floor_item_increase(creature_ptr->current_floor_ptr, 0 - it_ptr->item, -1); + floor_item_optimize(creature_ptr, 0 - it_ptr->item); + return; + } + + inven_item_increase(creature_ptr, it_ptr->item, -1); + if (!it_ptr->return_when_thrown) + inven_item_describe(creature_ptr, it_ptr->item); + + inven_item_optimize(creature_ptr, it_ptr->item); +} + +static void set_class_specific_throw_params(player_type *creature_ptr, it_type *it_ptr) +{ + take_turn(creature_ptr, 100); + if ((creature_ptr->pclass == CLASS_ROGUE) || (creature_ptr->pclass == CLASS_NINJA)) + creature_ptr->energy_use -= creature_ptr->lev; + + it_ptr->y = creature_ptr->y; + it_ptr->x = creature_ptr->x; + handle_stuff(creature_ptr); + it_ptr->shuriken = (creature_ptr->pclass == CLASS_NINJA) + && ((it_ptr->q_ptr->tval == TV_SPIKE) || ((have_flag(it_ptr->obj_flags, TR_THROW)) && (it_ptr->q_ptr->tval == TV_SWORD))); +} + +static void set_racial_chance(player_type *creature_ptr, it_type *it_ptr) +{ + if (have_flag(it_ptr->obj_flags, TR_THROW)) + it_ptr->chance = ((creature_ptr->skill_tht) + ((creature_ptr->to_h_b + it_ptr->q_ptr->to_h) * BTH_PLUS_ADJ)); + else + it_ptr->chance = (creature_ptr->skill_tht + (creature_ptr->to_h_b * BTH_PLUS_ADJ)); + + if (it_ptr->shuriken != 0) + it_ptr->chance *= 2; +} + +static bool check_racial_target_bold(player_type *creature_ptr, it_type *it_ptr) +{ + it_ptr->ny[it_ptr->cur_dis] = it_ptr->y; + it_ptr->nx[it_ptr->cur_dis] = it_ptr->x; + mmove2(&it_ptr->ny[it_ptr->cur_dis], &it_ptr->nx[it_ptr->cur_dis], creature_ptr->y, creature_ptr->x, it_ptr->ty, it_ptr->tx); + if (cave_have_flag_bold(creature_ptr->current_floor_ptr, it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis], FF_PROJECT)) + return FALSE; + + it_ptr->hit_wall = TRUE; + return (it_ptr->q_ptr->tval == TV_FIGURINE) || object_is_potion(it_ptr->q_ptr) + || (creature_ptr->current_floor_ptr->grid_array[it_ptr->ny[it_ptr->cur_dis]][it_ptr->nx[it_ptr->cur_dis]].m_idx == 0); +} + +static void check_racial_target_seen(player_type *creature_ptr, it_type *it_ptr) +{ + if (!panel_contains(it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis]) + || !player_can_see_bold(creature_ptr, it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis])) { + term_xtra(TERM_XTRA_DELAY, it_ptr->msec); + return; + } + + SYMBOL_CODE c = object_char(it_ptr->q_ptr); + TERM_COLOR a = object_attr(it_ptr->q_ptr); + print_rel(creature_ptr, c, a, it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis]); + move_cursor_relative(it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis]); + term_fresh(); + term_xtra(TERM_XTRA_DELAY, it_ptr->msec); + lite_spot(creature_ptr, it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis]); + term_fresh(); +} + +static bool check_racial_target_monster(player_type *creature_ptr, it_type *it_ptr) +{ + it_ptr->prev_y = it_ptr->y; + it_ptr->prev_x = it_ptr->x; + it_ptr->x = it_ptr->nx[it_ptr->cur_dis]; + it_ptr->y = it_ptr->ny[it_ptr->cur_dis]; + it_ptr->cur_dis++; + return creature_ptr->current_floor_ptr->grid_array[it_ptr->y][it_ptr->x].m_idx == 0; +} + +static void display_attack_racial_power(player_type *creature_ptr, it_type *it_ptr) +{ + if (!it_ptr->visible) { + msg_format(_("%sが敵を捕捉した。", "The %s finds a mark."), it_ptr->o_name); + return; + } + + msg_format(_("%sが%sに命中した。", "The %s hits %s."), it_ptr->o_name, it_ptr->m_name); + if (!it_ptr->m_ptr->ml) + return; + + if (!creature_ptr->image) + monster_race_track(creature_ptr, it_ptr->m_ptr->ap_r_idx); + + health_track(creature_ptr, it_ptr->g_ptr->m_idx); +} + +static void calc_racial_power_damage(player_type *creature_ptr, it_type *it_ptr) +{ + int dd = it_ptr->q_ptr->dd; + int ds = it_ptr->q_ptr->ds; + torch_dice(it_ptr->q_ptr, &dd, &ds); + it_ptr->tdam = damroll(dd, ds); + it_ptr->tdam = calc_attack_damage_with_slay(creature_ptr, it_ptr->q_ptr, it_ptr->tdam, it_ptr->m_ptr, 0, TRUE); + it_ptr->tdam = critical_shot(creature_ptr, it_ptr->q_ptr->weight, it_ptr->q_ptr->to_h, 0, it_ptr->tdam); + if (it_ptr->q_ptr->to_d > 0) + it_ptr->tdam += it_ptr->q_ptr->to_d; + else + it_ptr->tdam += -it_ptr->q_ptr->to_d; + + if (it_ptr->boomerang) { + it_ptr->tdam *= (it_ptr->mult + creature_ptr->num_blow[it_ptr->item - INVEN_RARM]); + it_ptr->tdam += creature_ptr->to_d_m; + } else if (have_flag(it_ptr->obj_flags, TR_THROW)) { + it_ptr->tdam *= (3 + it_ptr->mult); + it_ptr->tdam += creature_ptr->to_d_m; + } else { + it_ptr->tdam *= it_ptr->mult; + } + + if (it_ptr->shuriken != 0) + it_ptr->tdam += ((creature_ptr->lev + 30) * (creature_ptr->lev + 30) - 900) / 55; + + if (it_ptr->tdam < 0) + it_ptr->tdam = 0; + + it_ptr->tdam = mon_damage_mod(creature_ptr, it_ptr->m_ptr, it_ptr->tdam, FALSE); +} + +static void attack_racial_power(player_type *creature_ptr, it_type *it_ptr) +{ + if (!test_hit_fire(creature_ptr, it_ptr->chance - it_ptr->cur_dis, it_ptr->m_ptr, it_ptr->m_ptr->ml, it_ptr->o_name)) + return; + + display_attack_racial_power(creature_ptr, it_ptr); + calc_racial_power_damage(creature_ptr, it_ptr); + msg_format_wizard(creature_ptr, CHEAT_MONSTER, _("%dのダメージを与えた。(残りHP %d/%d(%d))", "You do %d damage. (left HP %d/%d(%d))"), it_ptr->tdam, + it_ptr->m_ptr->hp - it_ptr->tdam, it_ptr->m_ptr->maxhp, it_ptr->m_ptr->max_maxhp); + + bool fear = FALSE; + if (mon_take_hit(creature_ptr, it_ptr->g_ptr->m_idx, it_ptr->tdam, &fear, extract_note_dies(real_r_idx(it_ptr->m_ptr)))) + return; + + message_pain(creature_ptr, it_ptr->g_ptr->m_idx, it_ptr->tdam); + if ((it_ptr->tdam > 0) && !object_is_potion(it_ptr->q_ptr)) + anger_monster(creature_ptr, it_ptr->m_ptr); + + if (fear && it_ptr->m_ptr->ml) { + sound(SOUND_FLEE); + msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), it_ptr->m_name); + } +} + +static void exe_throw(player_type *creature_ptr, it_type *it_ptr) +{ + it_ptr->cur_dis = 0; + while (it_ptr->cur_dis <= it_ptr->tdis) { + if ((it_ptr->y == it_ptr->ty) && (it_ptr->x == it_ptr->tx)) + break; + + if (check_racial_target_bold(creature_ptr, it_ptr)) + break; + + check_racial_target_seen(creature_ptr, it_ptr); + if (check_racial_target_monster(creature_ptr, it_ptr)) + continue; + + it_ptr->g_ptr = &creature_ptr->current_floor_ptr->grid_array[it_ptr->y][it_ptr->x]; + it_ptr->m_ptr = &creature_ptr->current_floor_ptr->m_list[it_ptr->g_ptr->m_idx]; + monster_name(creature_ptr, it_ptr->g_ptr->m_idx, it_ptr->m_name); + it_ptr->visible = it_ptr->m_ptr->ml; + it_ptr->hit_body = TRUE; + attack_racial_power(creature_ptr, it_ptr); + break; + } +} + +void display_figurine_throw(player_type *creature_ptr, it_type *it_ptr) +{ + if ((it_ptr->q_ptr->tval != TV_FIGURINE) || creature_ptr->current_floor_ptr->inside_arena) + return; + + it_ptr->corruption_possibility = 100; + if (!(summon_named_creature(creature_ptr, 0, it_ptr->y, it_ptr->x, it_ptr->q_ptr->pval, !(object_is_cursed(it_ptr->q_ptr)) ? PM_FORCE_PET : 0L))) { + msg_print(_("人形は捻じ曲がり砕け散ってしまった!", "The Figurine writhes and then shatters.")); + return; + } + + if (object_is_cursed(it_ptr->q_ptr)) + msg_print(_("これはあまり良くない気がする。", "You have a bad feeling about this.")); +} + +void display_potion_throw(player_type *creature_ptr, it_type *it_ptr) +{ + if (!object_is_potion(it_ptr->q_ptr)) + return; + + if (it_ptr->hit_body || it_ptr->hit_wall || (randint1(100) < it_ptr->corruption_possibility)) { + it_ptr->corruption_possibility = 0; + return; + } + + msg_format(_("%sは砕け散った!", "The %s shatters!"), it_ptr->o_name); + if (!potion_smash_effect(creature_ptr, 0, it_ptr->y, it_ptr->x, it_ptr->q_ptr->k_idx)) { + it_ptr->do_drop = FALSE; + return; + } + + monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[creature_ptr->current_floor_ptr->grid_array[it_ptr->y][it_ptr->x].m_idx]; + if ((creature_ptr->current_floor_ptr->grid_array[it_ptr->y][it_ptr->x].m_idx == 0) || !is_friendly(m_ptr) || monster_invulner_remaining(m_ptr)) { + it_ptr->do_drop = FALSE; + return; + } + + GAME_TEXT m_name[MAX_NLEN]; + monster_desc(creature_ptr, m_name, m_ptr, 0); + msg_format(_("%sは怒った!", "%^s gets angry!"), m_name); + set_hostile(creature_ptr, &creature_ptr->current_floor_ptr->m_list[creature_ptr->current_floor_ptr->grid_array[it_ptr->y][it_ptr->x].m_idx]); + it_ptr->do_drop = FALSE; +} + +static void display_boomerang_throw(player_type *creature_ptr, it_type *it_ptr) +{ + if ((it_ptr->back_chance > 37) && !creature_ptr->blind && (it_ptr->item >= 0)) { + msg_format(_("%sが手元に返ってきた。", "%s comes back to you."), it_ptr->o2_name); + it_ptr->come_back = TRUE; + return; + } + + if (it_ptr->item >= 0) + msg_format(_("%sを受け損ねた!", "%s comes back, but you can't catch!"), it_ptr->o2_name); + else + msg_format(_("%sが返ってきた。", "%s comes back."), it_ptr->o2_name); + + it_ptr->y = creature_ptr->y; + it_ptr->x = creature_ptr->x; +} + +static void process_boomerang_throw(player_type *creature_ptr, it_type *it_ptr) +{ + if ((it_ptr->back_chance <= 30) || (one_in_(100) && !it_ptr->super_boomerang)) { + msg_format(_("%sが返ってこなかった!", "%s doesn't come back!"), it_ptr->o2_name); + return; + } + + for (int i = it_ptr->cur_dis - 1; i > 0; i--) { + if (!panel_contains(it_ptr->ny[i], it_ptr->nx[i]) || !player_can_see_bold(creature_ptr, it_ptr->ny[i], it_ptr->nx[i])) { + term_xtra(TERM_XTRA_DELAY, it_ptr->msec); + continue; + } + + SYMBOL_CODE c = object_char(it_ptr->q_ptr); + byte a = object_attr(it_ptr->q_ptr); + print_rel(creature_ptr, c, a, it_ptr->ny[i], it_ptr->nx[i]); + move_cursor_relative(it_ptr->ny[i], it_ptr->nx[i]); + term_fresh(); + term_xtra(TERM_XTRA_DELAY, it_ptr->msec); + lite_spot(creature_ptr, it_ptr->ny[i], it_ptr->nx[i]); + term_fresh(); + } + + display_boomerang_throw(creature_ptr, it_ptr); +} + +static void check_boomerang_throw(player_type *creature_ptr, it_type *it_ptr) +{ + if (!it_ptr->return_when_thrown) + return; + + it_ptr->back_chance = randint1(30) + 20 + ((int)(adj_dex_th[creature_ptr->stat_ind[A_DEX]]) - 128); + it_ptr->super_boomerang = (((it_ptr->q_ptr->name1 == ART_MJOLLNIR) || (it_ptr->q_ptr->name1 == ART_AEGISFANG)) && it_ptr->boomerang); + it_ptr->corruption_possibility = -1; + if (it_ptr->boomerang) + it_ptr->back_chance += 4 + randint1(5); + + if (it_ptr->super_boomerang) + it_ptr->back_chance += 100; + + describe_flavor(creature_ptr, it_ptr->o2_name, it_ptr->q_ptr, OD_OMIT_PREFIX | OD_NAME_ONLY); + process_boomerang_throw(creature_ptr, it_ptr); +} + +static void process_boomerang_back(player_type *creature_ptr, it_type *it_ptr) +{ + if (it_ptr->come_back) { + if ((it_ptr->item != INVEN_RARM) && (it_ptr->item != INVEN_LARM)) { + store_item_to_inventory(creature_ptr, it_ptr->q_ptr); + it_ptr->do_drop = FALSE; + return; + } + + it_ptr->o_ptr = &creature_ptr->inventory_list[it_ptr->item]; + object_copy(it_ptr->o_ptr, it_ptr->q_ptr); + creature_ptr->total_weight += it_ptr->q_ptr->weight; + creature_ptr->equip_cnt++; + creature_ptr->update |= PU_BONUS | PU_TORCH | PU_MANA; + creature_ptr->window |= PW_EQUIP; + it_ptr->do_drop = FALSE; + return; + } + + if (it_ptr->equiped_item) { + verify_equip_slot(creature_ptr, it_ptr->item); + calc_android_exp(creature_ptr); + } +} + +static void drop_thrown_item(player_type *creature_ptr, it_type *it_ptr) +{ + if (!it_ptr->do_drop) + return; + + if (cave_have_flag_bold(creature_ptr->current_floor_ptr, it_ptr->y, it_ptr->x, FF_PROJECT)) + (void)drop_near(creature_ptr, it_ptr->q_ptr, it_ptr->corruption_possibility, it_ptr->y, it_ptr->x); + else + (void)drop_near(creature_ptr, it_ptr->q_ptr, it_ptr->corruption_possibility, it_ptr->prev_y, it_ptr->prev_x); +} + +/*! + * @brief 投射処理メインルーチン / + * Throw an object from the pack or floor. + * @param mult 威力の倍率 + * @param creature_ptr プレーヤーへの参照ポインタ + * @param boomerang ブーメラン処理ならばTRUE + * @param shuriken 忍者の手裏剣処理ならばTRUE ← 間違い、-1が渡されてくることがある。要調査. + * @return ターンを消費した場合TRUEを返す + * @details + *
+ * Note: "unseen" monsters are very hard to hit.
+ *
+ * Should throwing a weapon do full damage?  Should it allow the magic
+ * to hit bonus of the weapon to have an effect?  Should it ever cause
+ * the item to be destroyed?  Should it do any damage at all?
+ * 
+ */ +bool do_cmd_throw(player_type *creature_ptr, int mult, bool boomerang, OBJECT_IDX shuriken) +{ + if (creature_ptr->wild_mode) + return FALSE; + + if (creature_ptr->special_defense & KATA_MUSOU) + set_action(creature_ptr, ACTION_NONE); + + it_type tmp_it; + object_type tmp_object; + it_type *it_ptr = initialize_it_type(&tmp_it, &tmp_object, delay_factor, mult, boomerang, shuriken); + if (!check_can_throw(creature_ptr, it_ptr)) + return FALSE; + + calc_throw_range(creature_ptr, it_ptr); + if (!calc_throw_grid(creature_ptr, it_ptr)) + return FALSE; + + reflect_inventory_by_throw(creature_ptr, it_ptr); + if (it_ptr->item >= INVEN_RARM) { + it_ptr->equiped_item = TRUE; + creature_ptr->redraw |= PR_EQUIPPY; + } + + set_class_specific_throw_params(creature_ptr, it_ptr); + set_racial_chance(creature_ptr, it_ptr); + it_ptr->prev_y = it_ptr->y; + it_ptr->prev_x = it_ptr->x; + exe_throw(creature_ptr, it_ptr); + if (it_ptr->hit_body) + torch_lost_fuel(it_ptr->q_ptr); + + it_ptr->corruption_possibility = (it_ptr->hit_body ? breakage_chance(creature_ptr, it_ptr->q_ptr, creature_ptr->pclass == CLASS_ARCHER, 0) : 0); + display_figurine_throw(creature_ptr, it_ptr); + display_potion_throw(creature_ptr, it_ptr); + check_boomerang_throw(creature_ptr, it_ptr); + process_boomerang_back(creature_ptr, it_ptr); + drop_thrown_item(creature_ptr, it_ptr); + return TRUE; +} diff --git a/src/cmd-item/cmd-throw.h b/src/cmd-item/cmd-throw.h new file mode 100644 index 000000000..67692d200 --- /dev/null +++ b/src/cmd-item/cmd-throw.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool do_cmd_throw(player_type *creature_ptr, int mult, bool boomerang, OBJECT_IDX shuriken); diff --git a/src/cmd-item/cmd-usestaff.c b/src/cmd-item/cmd-usestaff.c new file mode 100644 index 000000000..e2ba84d12 --- /dev/null +++ b/src/cmd-item/cmd-usestaff.c @@ -0,0 +1,455 @@ +#include "cmd-item/cmd-usestaff.h" +#include "action/action-limited.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" +#include "floor/floor-object.h" +#include "game-option/disturbance-options.h" +#include "inventory/inventory-object.h" +#include "inventory/player-inventory.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-floor/monster-summon.h" +#include "monster-floor/place-monster-types.h" +#include "object-enchant/special-object-flags.h" +#include "object/item-use-flags.h" +#include "object/object-generator.h" +#include "object/object-info.h" +#include "object/object-kind.h" +#include "perception/object-perception.h" +#include "player/attack-defense-types.h" +#include "player-info/avatar.h" +#include "player/player-class.h" +#include "player/player-race-types.h" +#include "player/player-race.h" +#include "player/player-status.h" +#include "player/special-defense-types.h" +#include "spell-kind/earthquake.h" +#include "spell-kind/spells-curse-removal.h" +#include "spell-kind/spells-detection.h" +#include "spell-kind/spells-floor.h" +#include "spell-kind/spells-genocide.h" +#include "spell-kind/spells-lite.h" +#include "spell-kind/spells-neighbor.h" +#include "spell-kind/spells-perception.h" +#include "spell-kind/spells-sight.h" +#include "spell-kind/spells-teleport.h" +#include "spell/spells-staff-only.h" +#include "spell/spells-status.h" +#include "spell/spells-summon.h" +#include "status/action-setter.h" +#include "status/bad-status-setter.h" +#include "status/base-status.h" +#include "status/buff-setter.h" +#include "status/experience.h" +#include "status/shape-changer.h" +#include "sv-definition/sv-staff-types.h" +#include "system/floor-type-definition.h" +#include "term/screen-processor.h" +#include "view/display-messages.h" +#include "view/object-describer.h" + +/*! + * @brief 杖の効果を発動する + * @param creature_ptr プレーヤーへの参照ポインタ + * @param sval オブジェクトのsval + * @param use_charge 使用回数を消費したかどうかを返す参照ポインタ + * @param powerful 強力発動上の処理ならばTRUE + * @param magic 魔道具術上の処理ならばTRUE + * @param known 判明済ならばTRUE + * @return 発動により効果内容が確定したならばTRUEを返す + */ +int staff_effect(player_type *creature_ptr, OBJECT_SUBTYPE_VALUE sval, bool *use_charge, bool powerful, bool magic, bool known) +{ + int k; + int ident = FALSE; + PLAYER_LEVEL lev = powerful ? creature_ptr->lev * 2 : creature_ptr->lev; + POSITION detect_rad = powerful ? DETECT_RAD_DEFAULT * 3 / 2 : DETECT_RAD_DEFAULT; + + /* Analyze the staff */ + switch (sval) { + case SV_STAFF_DARKNESS: { + if (!(creature_ptr->resist_blind) && !(creature_ptr->resist_dark)) { + if (set_blind(creature_ptr, creature_ptr->blind + 3 + randint1(5))) + ident = TRUE; + } + if (unlite_area(creature_ptr, 10, (powerful ? 6 : 3))) + ident = TRUE; + break; + } + + case SV_STAFF_SLOWNESS: { + if (set_slow(creature_ptr, creature_ptr->slow + randint1(30) + 15, FALSE)) + ident = TRUE; + break; + } + + case SV_STAFF_HASTE_MONSTERS: { + if (speed_monsters(creature_ptr)) + ident = TRUE; + break; + } + + case SV_STAFF_SUMMONING: { + const int times = randint1(powerful ? 8 : 4); + for (k = 0; k < times; k++) { + if (summon_specific(creature_ptr, 0, creature_ptr->y, creature_ptr->x, creature_ptr->current_floor_ptr->dun_level, 0, + (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET))) { + ident = TRUE; + } + } + break; + } + + case SV_STAFF_TELEPORTATION: { + teleport_player(creature_ptr, (powerful ? 150 : 100), 0L); + ident = TRUE; + break; + } + + case SV_STAFF_IDENTIFY: { + if (powerful) { + if (!identify_fully(creature_ptr, FALSE, 0)) + *use_charge = FALSE; + } else { + if (!ident_spell(creature_ptr, FALSE, 0)) + *use_charge = FALSE; + } + ident = TRUE; + break; + } + + case SV_STAFF_REMOVE_CURSE: { + bool result = powerful ? remove_all_curse(creature_ptr) : remove_curse(creature_ptr); + if (result) { + ident = TRUE; + } + break; + } + + case SV_STAFF_STARLITE: + ident = starlight(creature_ptr, magic); + break; + + case SV_STAFF_LITE: { + if (lite_area(creature_ptr, damroll(2, 8), (powerful ? 4 : 2))) + ident = TRUE; + break; + } + + case SV_STAFF_MAPPING: { + map_area(creature_ptr, powerful ? DETECT_RAD_MAP * 3 / 2 : DETECT_RAD_MAP); + ident = TRUE; + break; + } + + case SV_STAFF_DETECT_GOLD: { + if (detect_treasure(creature_ptr, detect_rad)) + ident = TRUE; + if (detect_objects_gold(creature_ptr, detect_rad)) + ident = TRUE; + break; + } + + case SV_STAFF_DETECT_ITEM: { + if (detect_objects_normal(creature_ptr, detect_rad)) + ident = TRUE; + break; + } + + case SV_STAFF_DETECT_TRAP: { + if (detect_traps(creature_ptr, detect_rad, known)) + ident = TRUE; + break; + } + + case SV_STAFF_DETECT_DOOR: { + if (detect_doors(creature_ptr, detect_rad)) + ident = TRUE; + if (detect_stairs(creature_ptr, detect_rad)) + ident = TRUE; + break; + } + + case SV_STAFF_DETECT_INVIS: { + if (detect_monsters_invis(creature_ptr, detect_rad)) + ident = TRUE; + break; + } + + case SV_STAFF_DETECT_EVIL: { + if (detect_monsters_evil(creature_ptr, detect_rad)) + ident = TRUE; + break; + } + + case SV_STAFF_CURE_LIGHT: { + ident = cure_light_wounds(creature_ptr, (powerful ? 4 : 2), 8); + break; + } + + case SV_STAFF_CURING: { + ident = true_healing(creature_ptr, 0); + if (set_shero(creature_ptr, 0, TRUE)) + ident = TRUE; + break; + } + + case SV_STAFF_HEALING: { + if (cure_critical_wounds(creature_ptr, powerful ? 500 : 300)) + ident = TRUE; + break; + } + + case SV_STAFF_THE_MAGI: { + if (do_res_stat(creature_ptr, A_INT)) + ident = TRUE; + ident |= restore_mana(creature_ptr, FALSE); + if (set_shero(creature_ptr, 0, TRUE)) + ident = TRUE; + break; + } + + case SV_STAFF_SLEEP_MONSTERS: { + if (sleep_monsters(creature_ptr, lev)) + ident = TRUE; + break; + } + + case SV_STAFF_SLOW_MONSTERS: { + if (slow_monsters(creature_ptr, lev)) + ident = TRUE; + break; + } + + case SV_STAFF_SPEED: { + if (set_fast(creature_ptr, randint1(30) + (powerful ? 30 : 15), FALSE)) + ident = TRUE; + break; + } + + case SV_STAFF_PROBING: { + ident = probing(creature_ptr); + break; + } + + case SV_STAFF_DISPEL_EVIL: { + ident = dispel_evil(creature_ptr, powerful ? 120 : 80); + break; + } + + case SV_STAFF_POWER: { + ident = dispel_monsters(creature_ptr, powerful ? 225 : 150); + break; + } + + case SV_STAFF_HOLINESS: { + ident = cleansing_nova(creature_ptr, magic, powerful); + break; + } + + case SV_STAFF_GENOCIDE: { + ident = symbol_genocide(creature_ptr, (magic ? lev + 50 : 200), TRUE); + break; + } + + case SV_STAFF_EARTHQUAKES: { + if (earthquake(creature_ptr, creature_ptr->y, creature_ptr->x, (powerful ? 15 : 10), 0)) + ident = TRUE; + else + msg_print(_("ダンジョンが揺れた。", "The dungeon trembles.")); + + break; + } + + case SV_STAFF_DESTRUCTION: { + ident = destroy_area(creature_ptr, creature_ptr->y, creature_ptr->x, (powerful ? 18 : 13) + randint0(5), FALSE); + break; + } + + case SV_STAFF_ANIMATE_DEAD: { + ident = animate_dead(creature_ptr, 0, creature_ptr->y, creature_ptr->x); + break; + } + + case SV_STAFF_MSTORM: { + ident = unleash_mana_storm(creature_ptr, powerful); + break; + } + + case SV_STAFF_NOTHING: { + msg_print(_("何も起らなかった。", "Nothing happen.")); + if (is_specific_player_race(creature_ptr, RACE_SKELETON) || is_specific_player_race(creature_ptr, RACE_GOLEM) + || is_specific_player_race(creature_ptr, RACE_ZOMBIE) || is_specific_player_race(creature_ptr, RACE_SPECTRE)) + msg_print(_("もったいない事をしたような気がする。食べ物は大切にしなくては。", "What a waste. It's your food!")); + break; + } + } + return ident; +} + +/*! + * @brief 杖を使うコマンドのサブルーチン / + * Use a staff. -RAK- + * @param item 使うオブジェクトの所持品ID + * @return なし + * @details + * One charge of one staff disappears. + * Hack -- staffs of identify can be "cancelled". + */ +void exe_use_staff(player_type *creature_ptr, INVENTORY_IDX item) +{ + int ident, chance, lev; + object_type *o_ptr; + + /* Hack -- let staffs of identify get aborted */ + bool use_charge = TRUE; + + o_ptr = ref_item(creature_ptr, item); + + /* Mega-Hack -- refuse to use a pile from the ground */ + if ((item < 0) && (o_ptr->number > 1)) { + msg_print(_("まずは杖を拾わなければ。", "You must first pick up the staffs.")); + return; + } + + take_turn(creature_ptr, 100); + + lev = k_info[o_ptr->k_idx].level; + if (lev > 50) + lev = 50 + (lev - 50) / 2; + + /* Base chance of success */ + chance = creature_ptr->skill_dev; + + /* Confusion hurts skill */ + if (creature_ptr->confused) + chance = chance / 2; + + /* Hight level objects are harder */ + chance = chance - lev; + + /* Give everyone a (slight) chance */ + if ((chance < USE_DEVICE) && one_in_(USE_DEVICE - chance + 1)) { + chance = USE_DEVICE; + } + + if (cmd_limit_time_walk(creature_ptr)) + return; + + /* Roll for usage */ + if ((chance < USE_DEVICE) || (randint1(chance) < USE_DEVICE) || (creature_ptr->pclass == CLASS_BERSERKER)) { + if (flush_failure) + flush(); + msg_print(_("杖をうまく使えなかった。", "You failed to use the staff properly.")); + sound(SOUND_FAIL); + return; + } + + /* Notice empty staffs */ + if (o_ptr->pval <= 0) { + if (flush_failure) + flush(); + msg_print(_("この杖にはもう魔力が残っていない。", "The staff has no charges left.")); + o_ptr->ident |= (IDENT_EMPTY); + creature_ptr->update |= (PU_COMBINE | PU_REORDER); + creature_ptr->window |= (PW_INVEN); + + return; + } + + sound(SOUND_ZAP); + + ident = staff_effect(creature_ptr, o_ptr->sval, &use_charge, FALSE, FALSE, object_is_aware(o_ptr)); + + if (!(object_is_aware(o_ptr))) { + chg_virtue(creature_ptr, V_PATIENCE, -1); + chg_virtue(creature_ptr, V_CHANCE, 1); + chg_virtue(creature_ptr, V_KNOWLEDGE, -1); + } + + /* + * Temporarily remove the flags for updating the inventory so + * gain_exp() does not reorder the inventory before the charge + * is deducted from the staff. + */ + BIT_FLAGS inventory_flags = (PU_COMBINE | PU_REORDER | (creature_ptr->update & PU_AUTODESTROY)); + creature_ptr->update &= ~(PU_COMBINE | PU_REORDER | PU_AUTODESTROY); + + /* Tried the item */ + object_tried(o_ptr); + + /* An identification was made */ + if (ident && !object_is_aware(o_ptr)) { + object_aware(creature_ptr, o_ptr); + gain_exp(creature_ptr, (lev + (creature_ptr->lev >> 1)) / creature_ptr->lev); + } + + creature_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + creature_ptr->update |= inventory_flags; + + /* Hack -- some uses are "free" */ + if (!use_charge) + return; + + /* Use a single charge */ + o_ptr->pval--; + + /* XXX Hack -- unstack if necessary */ + if ((item >= 0) && (o_ptr->number > 1)) { + object_type forge; + object_type *q_ptr; + q_ptr = &forge; + object_copy(q_ptr, o_ptr); + + /* Modify quantity */ + q_ptr->number = 1; + + /* Restore the charges */ + o_ptr->pval++; + + /* Unstack the used item */ + o_ptr->number--; + creature_ptr->total_weight -= q_ptr->weight; + item = store_item_to_inventory(creature_ptr, q_ptr); + + msg_print(_("杖をまとめなおした。", "You unstack your staff.")); + } + + /* Describe charges in the pack */ + if (item >= 0) { + inven_item_charges(creature_ptr, item); + } + + /* Describe charges on the floor */ + else { + floor_item_charges(creature_ptr->current_floor_ptr, 0 - item); + } +} + +/*! + * @brief 杖を使うコマンドのメインルーチン / + * @return なし + */ +void do_cmd_use_staff(player_type *creature_ptr) +{ + OBJECT_IDX item; + concptr q, s; + + if (creature_ptr->wild_mode) { + return; + } + + if (cmd_limit_arena(creature_ptr)) + return; + + if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) { + set_action(creature_ptr, ACTION_NONE); + } + + q = _("どの杖を使いますか? ", "Use which staff? "); + s = _("使える杖がない。", "You have no staff to use."); + if (!choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), TV_STAFF)) + return; + + exe_use_staff(creature_ptr, item); +} diff --git a/src/cmd-item/cmd-usestaff.h b/src/cmd-item/cmd-usestaff.h new file mode 100644 index 000000000..29fcd87d5 --- /dev/null +++ b/src/cmd-item/cmd-usestaff.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +int staff_effect(player_type *creature_ptr, OBJECT_SUBTYPE_VALUE sval, bool *use_charge, bool powerful, bool magic, bool known); +void exe_use_staff(player_type *creature_ptr, INVENTORY_IDX item); +void do_cmd_use_staff(player_type *creature_ptr); diff --git a/src/cmd-item/cmd-zaprod.c b/src/cmd-item/cmd-zaprod.c new file mode 100644 index 000000000..914c8b876 --- /dev/null +++ b/src/cmd-item/cmd-zaprod.c @@ -0,0 +1,435 @@ +#include "cmd-item/cmd-zaprod.h" +#include "action/action-limited.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" +#include "floor/floor-object.h" +#include "game-option/disturbance-options.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "object-enchant/special-object-flags.h" +#include "object/item-use-flags.h" +#include "object/object-info.h" +#include "object/object-kind.h" +#include "perception/object-perception.h" +#include "player/attack-defense-types.h" +#include "player-info/avatar.h" +#include "player/player-class.h" +#include "player/player-status.h" +#include "player/special-defense-types.h" +#include "spell-kind/spells-beam.h" +#include "spell-kind/spells-detection.h" +#include "spell-kind/spells-floor.h" +#include "spell-kind/spells-launcher.h" +#include "spell-kind/spells-lite.h" +#include "spell-kind/spells-neighbor.h" +#include "spell-kind/spells-perception.h" +#include "spell-kind/spells-random.h" +#include "spell-kind/spells-sight.h" +#include "spell-kind/spells-specific-bolt.h" +#include "spell-kind/spells-teleport.h" +#include "spell-kind/spells-world.h" +#include "spell/spell-types.h" +#include "spell/spells-status.h" +#include "status/action-setter.h" +#include "status/buff-setter.h" +#include "status/experience.h" +#include "status/shape-changer.h" +#include "sv-definition/sv-other-types.h" +#include "sv-definition/sv-rod-types.h" +#include "target/target-getter.h" +#include "term/screen-processor.h" +#include "view/display-messages.h" + +/*! + * @brief ロッドの効果を発動する + * @param creature_ptr プレーヤーへの参照ポインタ + * @param sval オブジェクトのsval + * @param dir 発動目標の方向ID + * @param use_charge チャージを消費したかどうかを返す参照ポインタ + * @param powerful 強力発動上の処理ならばTRUE + * @param magic 魔道具術上の処理ならばTRUE + * @return 発動により効果内容が確定したならばTRUEを返す + */ +int rod_effect(player_type *creature_ptr, OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool *use_charge, bool powerful, bool magic) +{ + int ident = FALSE; + PLAYER_LEVEL lev = powerful ? creature_ptr->lev * 2 : creature_ptr->lev; + POSITION detect_rad = powerful ? DETECT_RAD_DEFAULT * 3 / 2 : DETECT_RAD_DEFAULT; + POSITION rad = powerful ? 3 : 2; + + /* Unused */ + (void)magic; + + /* Analyze the rod */ + switch (sval) { + case SV_ROD_DETECT_TRAP: { + if (detect_traps(creature_ptr, detect_rad, (bool)(dir ? FALSE : TRUE))) + ident = TRUE; + break; + } + + case SV_ROD_DETECT_DOOR: { + if (detect_doors(creature_ptr, detect_rad)) + ident = TRUE; + if (detect_stairs(creature_ptr, detect_rad)) + ident = TRUE; + break; + } + + case SV_ROD_IDENTIFY: { + if (powerful) { + if (!identify_fully(creature_ptr, FALSE, 0)) + *use_charge = FALSE; + } else { + if (!ident_spell(creature_ptr, FALSE, 0)) + *use_charge = FALSE; + } + ident = TRUE; + break; + } + + case SV_ROD_RECALL: { + if (!recall_player(creature_ptr, randint0(21) + 15)) + *use_charge = FALSE; + ident = TRUE; + break; + } + + case SV_ROD_ILLUMINATION: { + if (lite_area(creature_ptr, damroll(2, 8), (powerful ? 4 : 2))) + ident = TRUE; + break; + } + + case SV_ROD_MAPPING: { + map_area(creature_ptr, powerful ? DETECT_RAD_MAP * 3 / 2 : DETECT_RAD_MAP); + ident = TRUE; + break; + } + + case SV_ROD_DETECTION: { + detect_all(creature_ptr, detect_rad); + ident = TRUE; + break; + } + + case SV_ROD_PROBING: { + probing(creature_ptr); + ident = TRUE; + break; + } + + case SV_ROD_CURING: { + if (true_healing(creature_ptr, 0)) + ident = TRUE; + if (set_shero(creature_ptr, 0, TRUE)) + ident = TRUE; + break; + } + + case SV_ROD_HEALING: { + if (cure_critical_wounds(creature_ptr, powerful ? 750 : 500)) + ident = TRUE; + break; + } + + case SV_ROD_RESTORATION: { + if (restore_level(creature_ptr)) + ident = TRUE; + if (restore_all_status(creature_ptr)) + ident = TRUE; + break; + } + + case SV_ROD_SPEED: { + if (set_fast(creature_ptr, randint1(30) + (powerful ? 30 : 15), FALSE)) + ident = TRUE; + break; + } + + case SV_ROD_PESTICIDE: { + if (dispel_monsters(creature_ptr, powerful ? 8 : 4)) + ident = TRUE; + break; + } + + case SV_ROD_TELEPORT_AWAY: { + int distance = MAX_SIGHT * (powerful ? 8 : 5); + if (teleport_monster(creature_ptr, dir, distance)) + ident = TRUE; + break; + } + + case SV_ROD_DISARMING: { + if (disarm_trap(creature_ptr, dir)) + ident = TRUE; + if (powerful && disarm_traps_touch(creature_ptr)) + ident = TRUE; + break; + } + + case SV_ROD_LITE: { + HIT_POINT dam = damroll((powerful ? 12 : 6), 8); + msg_print(_("青く輝く光線が放たれた。", "A line of blue shimmering light appears.")); + (void)lite_line(creature_ptr, dir, dam); + ident = TRUE; + break; + } + + case SV_ROD_SLEEP_MONSTER: { + if (sleep_monster(creature_ptr, dir, lev)) + ident = TRUE; + break; + } + + case SV_ROD_SLOW_MONSTER: { + if (slow_monster(creature_ptr, dir, lev)) + ident = TRUE; + break; + } + + case SV_ROD_HYPODYNAMIA: { + if (hypodynamic_bolt(creature_ptr, dir, 70 + 3 * lev / 2)) + ident = TRUE; + break; + } + + case SV_ROD_POLYMORPH: { + if (poly_monster(creature_ptr, dir, lev)) + ident = TRUE; + break; + } + + case SV_ROD_ACID_BOLT: { + fire_bolt_or_beam(creature_ptr, 10, GF_ACID, dir, damroll(6 + lev / 7, 8)); + ident = TRUE; + break; + } + + case SV_ROD_ELEC_BOLT: { + fire_bolt_or_beam(creature_ptr, 10, GF_ELEC, dir, damroll(4 + lev / 9, 8)); + ident = TRUE; + break; + } + + case SV_ROD_FIRE_BOLT: { + fire_bolt_or_beam(creature_ptr, 10, GF_FIRE, dir, damroll(7 + lev / 6, 8)); + ident = TRUE; + break; + } + + case SV_ROD_COLD_BOLT: { + fire_bolt_or_beam(creature_ptr, 10, GF_COLD, dir, damroll(5 + lev / 8, 8)); + ident = TRUE; + break; + } + + case SV_ROD_ACID_BALL: { + fire_ball(creature_ptr, GF_ACID, dir, 60 + lev, rad); + ident = TRUE; + break; + } + + case SV_ROD_ELEC_BALL: { + fire_ball(creature_ptr, GF_ELEC, dir, 40 + lev, rad); + ident = TRUE; + break; + } + + case SV_ROD_FIRE_BALL: { + fire_ball(creature_ptr, GF_FIRE, dir, 70 + lev, rad); + ident = TRUE; + break; + } + + case SV_ROD_COLD_BALL: { + fire_ball(creature_ptr, GF_COLD, dir, 50 + lev, rad); + ident = TRUE; + break; + } + + case SV_ROD_HAVOC: { + call_chaos(creature_ptr); + ident = TRUE; + break; + } + + case SV_ROD_STONE_TO_MUD: { + HIT_POINT dam = powerful ? 40 + randint1(60) : 20 + randint1(30); + if (wall_to_mud(creature_ptr, dir, dam)) + ident = TRUE; + break; + } + + case SV_ROD_AGGRAVATE: { + aggravate_monsters(creature_ptr, 0); + ident = TRUE; + break; + } + } + return ident; +} + +/*! + * @brief ロッドを使うコマンドのサブルーチン / + * Activate (zap) a Rod + * @param creature_ptr プレーヤーへの参照ポインタ + * @param item 使うオブジェクトの所持品ID + * @return なし + * @details + *
+ * Unstack fully charged rods as needed.
+ * Hack -- rods of perception/genocide can be "cancelled"
+ * All rods can be cancelled at the "Direction?" prompt
+ * pvals are defined for each rod in k_info. -LM-
+ * 
+ */ +void exe_zap_rod(player_type *creature_ptr, INVENTORY_IDX item) +{ + int ident, chance, lev, fail; + DIRECTION dir = 0; + object_type *o_ptr; + bool success; + + /* Hack -- let perception get aborted */ + bool use_charge = TRUE; + + object_kind *k_ptr; + + o_ptr = ref_item(creature_ptr, item); + + /* Mega-Hack -- refuse to zap a pile from the ground */ + if ((item < 0) && (o_ptr->number > 1)) { + msg_print(_("まずはロッドを拾わなければ。", "You must first pick up the rods.")); + return; + } + + /* Get a direction (unless KNOWN not to need it) */ + if (((o_ptr->sval >= SV_ROD_MIN_DIRECTION) && (o_ptr->sval != SV_ROD_HAVOC) && (o_ptr->sval != SV_ROD_AGGRAVATE) && (o_ptr->sval != SV_ROD_PESTICIDE)) + || !object_is_aware(o_ptr)) { + /* Get a direction, allow cancel */ + if (!get_aim_dir(creature_ptr, &dir)) + return; + } + + take_turn(creature_ptr, 100); + + lev = k_info[o_ptr->k_idx].level; + + /* Base chance of success */ + chance = creature_ptr->skill_dev; + + /* Confusion hurts skill */ + if (creature_ptr->confused) + chance = chance / 2; + + fail = lev + 5; + if (chance > fail) + fail -= (chance - fail) * 2; + else + chance -= (fail - chance) * 2; + if (fail < USE_DEVICE) + fail = USE_DEVICE; + if (chance < USE_DEVICE) + chance = USE_DEVICE; + + if (cmd_limit_time_walk(creature_ptr)) + return; + + if (creature_ptr->pclass == CLASS_BERSERKER) + success = FALSE; + else if (chance > fail) { + if (randint0(chance * 2) < fail) + success = FALSE; + else + success = TRUE; + } else { + if (randint0(fail * 2) < chance) + success = TRUE; + else + success = FALSE; + } + + /* Roll for usage */ + if (!success) { + if (flush_failure) + flush(); + msg_print(_("うまくロッドを使えなかった。", "You failed to use the rod properly.")); + sound(SOUND_FAIL); + return; + } + + k_ptr = &k_info[o_ptr->k_idx]; + + /* A single rod is still charging */ + if ((o_ptr->number == 1) && (o_ptr->timeout)) { + if (flush_failure) + flush(); + msg_print(_("このロッドはまだ魔力を充填している最中だ。", "The rod is still charging.")); + return; + } + /* A stack of rods lacks enough energy. */ + else if ((o_ptr->number > 1) && (o_ptr->timeout > k_ptr->pval * (o_ptr->number - 1))) { + if (flush_failure) + flush(); + msg_print(_("そのロッドはまだ充填中です。", "The rods are all still charging.")); + return; + } + + sound(SOUND_ZAP); + + ident = rod_effect(creature_ptr, o_ptr->sval, dir, &use_charge, FALSE, FALSE); + + /* Increase the timeout by the rod kind's pval. -LM- */ + if (use_charge) + o_ptr->timeout += k_ptr->pval; + creature_ptr->update |= (PU_COMBINE | PU_REORDER); + + if (!(object_is_aware(o_ptr))) { + chg_virtue(creature_ptr, V_PATIENCE, -1); + chg_virtue(creature_ptr, V_CHANCE, 1); + chg_virtue(creature_ptr, V_KNOWLEDGE, -1); + } + + /* Tried the object */ + object_tried(o_ptr); + + /* Successfully determined the object function */ + if (ident && !object_is_aware(o_ptr)) { + object_aware(creature_ptr, o_ptr); + gain_exp(creature_ptr, (lev + (creature_ptr->lev >> 1)) / creature_ptr->lev); + } + + creature_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); +} + +/*! + * @brief ロッドを使うコマンドのメインルーチン / + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void do_cmd_zap_rod(player_type *creature_ptr) +{ + OBJECT_IDX item; + concptr q, s; + + if (creature_ptr->wild_mode) { + return; + } + + if (cmd_limit_arena(creature_ptr)) + return; + + if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) { + set_action(creature_ptr, ACTION_NONE); + } + + q = _("どのロッドを振りますか? ", "Zap which rod? "); + s = _("使えるロッドがない。", "You have no rod to zap."); + + if (!choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), TV_ROD)) + return; + + /* Zap the rod */ + exe_zap_rod(creature_ptr, item); +} diff --git a/src/cmd-item/cmd-zaprod.h b/src/cmd-item/cmd-zaprod.h new file mode 100644 index 000000000..26b1d0be9 --- /dev/null +++ b/src/cmd-item/cmd-zaprod.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +int rod_effect(player_type *creature_ptr, OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool *use_charge, bool powerful, bool magic); +void exe_zap_rod(player_type *creature_ptr, INVENTORY_IDX item); +void do_cmd_zap_rod(player_type *creature_ptr); diff --git a/src/cmd-item/cmd-zapwand.c b/src/cmd-item/cmd-zapwand.c new file mode 100644 index 000000000..952890400 --- /dev/null +++ b/src/cmd-item/cmd-zapwand.c @@ -0,0 +1,467 @@ +#include "cmd-item/cmd-zapwand.h" +#include "action/action-limited.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" +#include "floor/floor-object.h" +#include "game-option/disturbance-options.h" +#include "game-option/input-options.h" +#include "inventory/player-inventory.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "object-enchant/special-object-flags.h" +#include "object/item-use-flags.h" +#include "object/object-info.h" +#include "object/object-kind.h" +#include "perception/object-perception.h" +#include "player/attack-defense-types.h" +#include "player-info/avatar.h" +#include "player/player-class.h" +#include "player/player-status.h" +#include "player/special-defense-types.h" +#include "spell-kind/spells-beam.h" +#include "spell-kind/spells-charm.h" +#include "spell-kind/spells-launcher.h" +#include "spell-kind/spells-lite.h" +#include "spell-kind/spells-neighbor.h" +#include "spell-kind/spells-specific-bolt.h" +#include "spell-kind/spells-teleport.h" +#include "spell/spell-types.h" +#include "spell/spells-status.h" +#include "status/action-setter.h" +#include "status/experience.h" +#include "sv-definition/sv-wand-types.h" +#include "target/target-getter.h" +#include "term/screen-processor.h" +#include "view/display-messages.h" +#include "view/object-describer.h" + +/*! + * @brief 魔法棒の効果を発動する + * @param creature_ptr プレーヤーへの参照ポインタ + * @param sval オブジェクトのsval + * @param dir 発動の方向ID + * @param powerful 強力発動上の処理ならばTRUE + * @param magic 魔道具術上の処理ならばTRUE + * @return 発動により効果内容が確定したならばTRUEを返す + */ +bool wand_effect(player_type *creature_ptr, OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool powerful, bool magic) +{ + bool ident = FALSE; + PLAYER_LEVEL lev = powerful ? creature_ptr->lev * 2 : creature_ptr->lev; + POSITION rad = powerful ? 3 : 2; + + /* XXX Hack -- Wand of wonder can do anything before it */ + if (sval == SV_WAND_WONDER) { + int vir = virtue_number(creature_ptr, V_CHANCE); + sval = (OBJECT_SUBTYPE_VALUE)randint0(SV_WAND_WONDER); + + if (vir) { + if (creature_ptr->virtues[vir - 1] > 0) { + while (randint1(300) < creature_ptr->virtues[vir - 1]) + sval++; + if (sval > SV_WAND_COLD_BALL) + sval = randint0(4) + SV_WAND_ACID_BALL; + } else { + while (randint1(300) < (0 - creature_ptr->virtues[vir - 1])) + sval--; + if (sval < SV_WAND_HEAL_MONSTER) + sval = randint0(3) + SV_WAND_HEAL_MONSTER; + } + } + if (sval < SV_WAND_TELEPORT_AWAY) + chg_virtue(creature_ptr, V_CHANCE, 1); + } + + /* Analyze the wand */ + switch (sval) { + case SV_WAND_HEAL_MONSTER: { + HIT_POINT dam = damroll((powerful ? 20 : 10), 10); + if (heal_monster(creature_ptr, dir, dam)) + ident = TRUE; + break; + } + + case SV_WAND_HASTE_MONSTER: { + if (speed_monster(creature_ptr, dir, lev)) + ident = TRUE; + break; + } + + case SV_WAND_CLONE_MONSTER: { + if (clone_monster(creature_ptr, dir)) + ident = TRUE; + break; + } + + case SV_WAND_TELEPORT_AWAY: { + int distance = MAX_SIGHT * (powerful ? 8 : 5); + if (teleport_monster(creature_ptr, dir, distance)) + ident = TRUE; + break; + } + + case SV_WAND_DISARMING: { + if (disarm_trap(creature_ptr, dir)) + ident = TRUE; + if (powerful && disarm_traps_touch(creature_ptr)) + ident = TRUE; + break; + } + + case SV_WAND_TRAP_DOOR_DEST: { + if (destroy_door(creature_ptr, dir)) + ident = TRUE; + if (powerful && destroy_doors_touch(creature_ptr)) + ident = TRUE; + break; + } + + case SV_WAND_STONE_TO_MUD: { + HIT_POINT dam = powerful ? 40 + randint1(60) : 20 + randint1(30); + if (wall_to_mud(creature_ptr, dir, dam)) + ident = TRUE; + break; + } + + case SV_WAND_LITE: { + HIT_POINT dam = damroll((powerful ? 12 : 6), 8); + msg_print(_("青く輝く光線が放たれた。", "A line of blue shimmering light appears.")); + (void)lite_line(creature_ptr, dir, dam); + ident = TRUE; + break; + } + + case SV_WAND_SLEEP_MONSTER: { + if (sleep_monster(creature_ptr, dir, lev)) + ident = TRUE; + break; + } + + case SV_WAND_SLOW_MONSTER: { + if (slow_monster(creature_ptr, dir, lev)) + ident = TRUE; + break; + } + + case SV_WAND_CONFUSE_MONSTER: { + if (confuse_monster(creature_ptr, dir, lev)) + ident = TRUE; + break; + } + + case SV_WAND_FEAR_MONSTER: { + if (fear_monster(creature_ptr, dir, lev)) + ident = TRUE; + break; + } + + case SV_WAND_HYPODYNAMIA: { + if (hypodynamic_bolt(creature_ptr, dir, 80 + lev)) + ident = TRUE; + break; + } + + case SV_WAND_POLYMORPH: { + if (poly_monster(creature_ptr, dir, lev)) + ident = TRUE; + break; + } + + case SV_WAND_STINKING_CLOUD: { + fire_ball(creature_ptr, GF_POIS, dir, 12 + lev / 4, rad); + ident = TRUE; + break; + } + + case SV_WAND_MAGIC_MISSILE: { + fire_bolt_or_beam(creature_ptr, 20, GF_MISSILE, dir, damroll(2 + lev / 10, 6)); + ident = TRUE; + break; + } + + case SV_WAND_ACID_BOLT: { + fire_bolt_or_beam(creature_ptr, 20, GF_ACID, dir, damroll(6 + lev / 7, 8)); + ident = TRUE; + break; + } + + case SV_WAND_CHARM_MONSTER: { + if (charm_monster(creature_ptr, dir, MAX(20, lev))) + ident = TRUE; + break; + } + + case SV_WAND_FIRE_BOLT: { + fire_bolt_or_beam(creature_ptr, 20, GF_FIRE, dir, damroll(7 + lev / 6, 8)); + ident = TRUE; + break; + } + + case SV_WAND_COLD_BOLT: { + fire_bolt_or_beam(creature_ptr, 20, GF_COLD, dir, damroll(5 + lev / 8, 8)); + ident = TRUE; + break; + } + + case SV_WAND_ACID_BALL: { + fire_ball(creature_ptr, GF_ACID, dir, 60 + 3 * lev / 4, rad); + ident = TRUE; + break; + } + + case SV_WAND_ELEC_BALL: { + fire_ball(creature_ptr, GF_ELEC, dir, 40 + 3 * lev / 4, rad); + ident = TRUE; + break; + } + + case SV_WAND_FIRE_BALL: { + fire_ball(creature_ptr, GF_FIRE, dir, 70 + 3 * lev / 4, rad); + ident = TRUE; + break; + } + + case SV_WAND_COLD_BALL: { + fire_ball(creature_ptr, GF_COLD, dir, 50 + 3 * lev / 4, rad); + ident = TRUE; + break; + } + + case SV_WAND_WONDER: { + msg_print(_("おっと、謎の魔法棒を始動させた。", "Oops. Wand of wonder activated.")); + break; + } + + case SV_WAND_DRAGON_FIRE: { + fire_breath(creature_ptr, GF_FIRE, dir, (powerful ? 300 : 200), 3); + ident = TRUE; + break; + } + + case SV_WAND_DRAGON_COLD: { + fire_breath(creature_ptr, GF_COLD, dir, (powerful ? 270 : 180), 3); + ident = TRUE; + break; + } + + case SV_WAND_DRAGON_BREATH: { + HIT_POINT dam; + EFFECT_ID typ; + + switch (randint1(5)) { + case 1: + dam = 240; + typ = GF_ACID; + break; + case 2: + dam = 210; + typ = GF_ELEC; + break; + case 3: + dam = 240; + typ = GF_FIRE; + break; + case 4: + dam = 210; + typ = GF_COLD; + break; + default: + dam = 180; + typ = GF_POIS; + break; + } + + if (powerful) + dam = (dam * 3) / 2; + + fire_breath(creature_ptr, typ, dir, dam, 3); + + ident = TRUE; + break; + } + + case SV_WAND_DISINTEGRATE: { + fire_ball(creature_ptr, GF_DISINTEGRATE, dir, 200 + randint1(lev * 2), rad); + ident = TRUE; + break; + } + + case SV_WAND_ROCKETS: { + msg_print(_("ロケットを発射した!", "You launch a rocket!")); + fire_rocket(creature_ptr, GF_ROCKET, dir, 250 + lev * 3, rad); + ident = TRUE; + break; + } + + case SV_WAND_STRIKING: { + fire_bolt(creature_ptr, GF_METEOR, dir, damroll(15 + lev / 3, 13)); + ident = TRUE; + break; + } + + case SV_WAND_GENOCIDE: { + fire_ball_hide(creature_ptr, GF_GENOCIDE, dir, magic ? lev + 50 : 250, 0); + ident = TRUE; + break; + } + } + return ident; +} + +/*! + * @brief 魔法棒を使うコマンドのサブルーチン / + * Aim a wand (from the pack or floor). + * @param item 使うオブジェクトの所持品ID + * @return なし + * @details + *
+ * Use a single charge from a single item.
+ * Handle "unstacking" in a logical manner.
+ * For simplicity, you cannot use a stack of items from the
+ * ground.  This would require too much nasty code.
+ * There are no wands which can "destroy" themselves, in the inventory
+ * or on the ground, so we can ignore this possibility.  Note that this
+ * required giving "wand of wonder" the ability to ignore destruction
+ * by electric balls.
+ * All wands can be "cancelled" at the "Direction?" prompt for free.
+ * Note that the basic "bolt" wands do slightly less damage than the
+ * basic "bolt" rods, but the basic "ball" wands do the same damage
+ * as the basic "ball" rods.
+ * 
+ */ +void exe_aim_wand(player_type *creature_ptr, INVENTORY_IDX item) +{ + DEPTH lev; + int ident, chance; + DIRECTION dir; + object_type *o_ptr; + bool old_target_pet = target_pet; + + o_ptr = ref_item(creature_ptr, item); + + /* Mega-Hack -- refuse to aim a pile from the ground */ + if ((item < 0) && (o_ptr->number > 1)) { + msg_print(_("まずは魔法棒を拾わなければ。", "You must first pick up the wands.")); + return; + } + + /* Allow direction to be cancelled for free */ + if (object_is_aware(o_ptr) && (o_ptr->sval == SV_WAND_HEAL_MONSTER || o_ptr->sval == SV_WAND_HASTE_MONSTER)) + target_pet = TRUE; + if (!get_aim_dir(creature_ptr, &dir)) { + target_pet = old_target_pet; + return; + } + target_pet = old_target_pet; + + take_turn(creature_ptr, 100); + + /* Get the level */ + lev = k_info[o_ptr->k_idx].level; + if (lev > 50) + lev = 50 + (lev - 50) / 2; + + /* Base chance of success */ + chance = creature_ptr->skill_dev; + + /* Confusion hurts skill */ + if (creature_ptr->confused) + chance = chance / 2; + + /* Hight level objects are harder */ + chance = chance - lev; + + /* Give everyone a (slight) chance */ + if ((chance < USE_DEVICE) && one_in_(USE_DEVICE - chance + 1)) { + chance = USE_DEVICE; + } + + if (cmd_limit_time_walk(creature_ptr)) + return; + + /* Roll for usage */ + if ((chance < USE_DEVICE) || (randint1(chance) < USE_DEVICE) || (creature_ptr->pclass == CLASS_BERSERKER)) { + if (flush_failure) + flush(); + msg_print(_("魔法棒をうまく使えなかった。", "You failed to use the wand properly.")); + sound(SOUND_FAIL); + return; + } + + /* The wand is already empty! */ + if (o_ptr->pval <= 0) { + if (flush_failure) + flush(); + msg_print(_("この魔法棒にはもう魔力が残っていない。", "The wand has no charges left.")); + o_ptr->ident |= (IDENT_EMPTY); + creature_ptr->update |= (PU_COMBINE | PU_REORDER); + creature_ptr->window |= (PW_INVEN); + + return; + } + + sound(SOUND_ZAP); + + ident = wand_effect(creature_ptr, o_ptr->sval, dir, FALSE, FALSE); + + /* + * Temporarily remove the flags for updating the inventory so + * gain_exp() does not reorder the inventory before the charge + * is deducted from the wand. + */ + BIT_FLAGS inventory_flags = (PU_COMBINE | PU_REORDER | (creature_ptr->update & PU_AUTODESTROY)); + creature_ptr->update &= ~(PU_COMBINE | PU_REORDER | PU_AUTODESTROY); + + if (!(object_is_aware(o_ptr))) { + chg_virtue(creature_ptr, V_PATIENCE, -1); + chg_virtue(creature_ptr, V_CHANCE, 1); + chg_virtue(creature_ptr, V_KNOWLEDGE, -1); + } + + /* Mark it as tried */ + object_tried(o_ptr); + + /* Apply identification */ + if (ident && !object_is_aware(o_ptr)) { + object_aware(creature_ptr, o_ptr); + gain_exp(creature_ptr, (lev + (creature_ptr->lev >> 1)) / creature_ptr->lev); + } + + creature_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + creature_ptr->update |= inventory_flags; + + /* Use a single charge */ + o_ptr->pval--; + + if (item >= 0) { + inven_item_charges(creature_ptr, item); + return; + } + + floor_item_charges(creature_ptr->current_floor_ptr, 0 - item); +} + +/*! + * @brief 魔法棒を使うコマンドのメインルーチン / + * @return なし + */ +void do_cmd_aim_wand(player_type *creature_ptr) +{ + OBJECT_IDX item; + concptr q, s; + + if (creature_ptr->wild_mode) + return; + if (cmd_limit_arena(creature_ptr)) + return; + if (creature_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) { + set_action(creature_ptr, ACTION_NONE); + } + + q = _("どの魔法棒で狙いますか? ", "Aim which wand? "); + s = _("使える魔法棒がない。", "You have no wand to aim."); + if (!choose_object(creature_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), TV_WAND)) + return; + + exe_aim_wand(creature_ptr, item); +} diff --git a/src/cmd-item/cmd-zapwand.h b/src/cmd-item/cmd-zapwand.h new file mode 100644 index 000000000..c0d469e5b --- /dev/null +++ b/src/cmd-item/cmd-zapwand.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +bool wand_effect(player_type *creature_ptr, OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool powerful, bool magic); +void exe_aim_wand(player_type *creature_ptr, INVENTORY_IDX item); +void do_cmd_aim_wand(player_type *creature_ptr); diff --git a/src/cmd-magiceat.c b/src/cmd-magiceat.c deleted file mode 100644 index 3ae7aaef9..000000000 --- a/src/cmd-magiceat.c +++ /dev/null @@ -1,587 +0,0 @@ -/*! - * @file cmd6.c - * @brief プレイヤーのアイテムに関するコマンドの実装2 / Spell/Prayer commands - * @date 2014/01/27 - * @author - *
- * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
- * This software may be copied and distributed for educational, research,
- * and not for profit purposes provided that this copyright and statement
- * are included in all such copies.  Other copyrights may also apply.
- * 2014 Deskull rearranged comment for Doxygen.\n
- * 
- * @details - *
- * This file includes code for eating food, drinking potions,
- * reading scrolls, aiming wands, using staffs, zapping rods,
- * and activating artifacts.
- *
- * In all cases, if the player becomes "aware" of the item's use
- * by testing it, mark it as "aware" and reward some experience
- * based on the object's level, always rounding up.  If the player
- * remains "unaware", mark that object "kind" as "tried".
- *
- * This code now correctly handles the unstacking of wands, staffs,
- * and rods.  Note the overly paranoid warning about potential pack
- * overflow, which allows the player to use and drop a stacked item.
- *
- * In all "unstacking" scenarios, the "used" object is "carried" as if
- * the player had just picked it up.  In particular, this means that if
- * the use of an item induces pack overflow, that item will be dropped.
- *
- * For simplicity, these routines induce a full "pack reorganization"
- * which not only combines similar items, but also reorganizes various
- * items to obey the current "sorting" method.  This may require about
- * 400 item comparisons, but only occasionally.
- *
- * There may be a BIG problem with any "effect" that can cause "changes"
- * to the inventory.  For example, a "scroll of recharging" can cause
- * a wand/staff to "disappear", moving the inventory up.  Luckily, the
- * scrolls all appear BEFORE the staffs/wands, so this is not a problem.
- * But, for example, a "staff of recharging" could cause MAJOR problems.
- * In such a case, it will be best to either (1) "postpone" the effect
- * until the end of the function, or (2) "change" the effect, say, into
- * giving a staff "negative" charges, or "turning a staff into a stick".
- * It seems as though a "rod of recharging" might in fact cause problems.
- * The basic problem is that the act of recharging (and destroying) an
- * item causes the inducer of that action to "move", causing "o_ptr" to
- * no longer point at the correct item, with horrifying results.
- *
- * Note that food/potions/scrolls no longer use bit-flags for effects,
- * but instead use the "sval" (which is also used to sort the objects).
- * 
- */ - -#include "angband.h" -#include "cmd-usestaff.h" -#include "cmd-zaprod.h" -#include "cmd-zapwand.h" -#include "avatar.h" -#include "player-status.h" - - -/*! - * @brief 魔道具術師の取り込んだ魔力一覧から選択/閲覧する / - * @param only_browse 閲覧するだけならばTRUE - * @return 選択した魔力のID、キャンセルならば-1を返す - */ -static OBJECT_SUBTYPE_VALUE select_magic_eater(bool only_browse) -{ - OBJECT_SUBTYPE_VALUE ext = 0; - char choice; - bool flag, request_list; - OBJECT_TYPE_VALUE tval = 0; - int ask = TRUE; - OBJECT_SUBTYPE_VALUE i = 0; - char out_val[160]; - - int menu_line = (use_menu ? 1 : 0); - - COMMAND_CODE sn; - if (repeat_pull(&sn)) - { - /* Verify the spell */ - if (sn >= EATER_EXT*2 && !(p_ptr->magic_num1[sn] > k_info[lookup_kind(TV_ROD, sn-EATER_EXT*2)].pval * (p_ptr->magic_num2[sn] - 1) * EATER_ROD_CHARGE)) - return sn; - else if (sn < EATER_EXT*2 && !(p_ptr->magic_num1[sn] < EATER_CHARGE)) - return sn; - } - - for (i = 0; i < 108; i++) - { - if (p_ptr->magic_num2[i]) break; - } - if (i == 108) - { - msg_print(_("魔法を覚えていない!", "You don't have any magic!")); - return -1; - } - - if (use_menu) - { - screen_save(); - - while(!tval) - { -#ifdef JP - prt(format(" %s 杖", (menu_line == 1) ? "》" : " "), 2, 14); - prt(format(" %s 魔法棒", (menu_line == 2) ? "》" : " "), 3, 14); - prt(format(" %s ロッド", (menu_line == 3) ? "》" : " "), 4, 14); -#else - prt(format(" %s staff", (menu_line == 1) ? "> " : " "), 2, 14); - prt(format(" %s wand", (menu_line == 2) ? "> " : " "), 3, 14); - prt(format(" %s rod", (menu_line == 3) ? "> " : " "), 4, 14); -#endif - - if (only_browse) prt(_("どの種類の魔法を見ますか?", "Which type of magic do you browse?"), 0, 0); - else prt(_("どの種類の魔法を使いますか?", "Which type of magic do you use?"), 0, 0); - - choice = inkey(); - switch(choice) - { - case ESCAPE: - case 'z': - case 'Z': - screen_load(); - return -1; - case '2': - case 'j': - case 'J': - menu_line++; - break; - case '8': - case 'k': - case 'K': - menu_line+= 2; - break; - case '\r': - case 'x': - case 'X': - ext = (menu_line-1)*EATER_EXT; - if (menu_line == 1) tval = TV_STAFF; - else if (menu_line == 2) tval = TV_WAND; - else tval = TV_ROD; - break; - } - if (menu_line > 3) menu_line -= 3; - } - screen_load(); - } - else - { - while (TRUE) - { - if (!get_com(_("[A] 杖, [B] 魔法棒, [C] ロッド:", "[A] staff, [B] wand, [C] rod:"), &choice, TRUE)) - { - return -1; - } - if (choice == 'A' || choice == 'a') - { - ext = 0; - tval = TV_STAFF; - break; - } - if (choice == 'B' || choice == 'b') - { - ext = EATER_EXT; - tval = TV_WAND; - break; - } - if (choice == 'C' || choice == 'c') - { - ext = EATER_EXT*2; - tval = TV_ROD; - break; - } - } - } - for (i = ext; i < ext + EATER_EXT; i++) - { - if (p_ptr->magic_num2[i]) - { - if (use_menu) menu_line = i-ext+1; - break; - } - } - if (i == ext+EATER_EXT) - { - msg_print(_("その種類の魔法は覚えていない!", "You don't have that type of magic!")); - return -1; - } - - /* Nothing chosen yet */ - flag = FALSE; - - /* Build a prompt */ - if (only_browse) strnfmt(out_val, 78, _("('*'で一覧, ESCで中断) どの魔力を見ますか?", - "(*=List, ESC=exit) Browse which power? ")); - else strnfmt(out_val, 78, _("('*'で一覧, ESCで中断) どの魔力を使いますか?", - "(*=List, ESC=exit) Use which power? ")); - screen_save(); - - request_list = always_show_list; - - while (!flag) - { - /* Show the list */ - if (request_list || use_menu) - { - byte y, x = 0; - OBJECT_SUBTYPE_VALUE ctr; - PERCENTAGE chance; - KIND_OBJECT_IDX k_idx; - char dummy[80]; - POSITION x1, y1; - DEPTH level; - byte col; - - strcpy(dummy, ""); - - for (y = 1; y < 20; y++) - prt("", y, x); - - y = 1; - - /* Print header(s) */ -#ifdef JP - prt(format(" %s 失率 %s 失率", (tval == TV_ROD ? " 状態 " : "使用回数"), (tval == TV_ROD ? " 状態 " : "使用回数")), y++, x); -#else - prt(format(" %s Fail %s Fail", (tval == TV_ROD ? " Stat " : " Charges"), (tval == TV_ROD ? " Stat " : " Charges")), y++, x); -#endif - - /* Print list */ - for (ctr = 0; ctr < EATER_EXT; ctr++) - { - if (!p_ptr->magic_num2[ctr+ext]) continue; - - k_idx = lookup_kind(tval, ctr); - - if (use_menu) - { - if (ctr == (menu_line-1)) - strcpy(dummy, _("》", "> ")); - else - strcpy(dummy, " "); - } - /* letter/number for power selection */ - else - { - char letter; - if (ctr < 26) - letter = I2A(ctr); - else - letter = '0' + ctr - 26; - sprintf(dummy, "%c)",letter); - } - x1 = ((ctr < EATER_EXT/2) ? x : x + 40); - y1 = ((ctr < EATER_EXT/2) ? y + ctr : y + ctr - EATER_EXT/2); - level = (tval == TV_ROD ? k_info[k_idx].level * 5 / 6 - 5 : k_info[k_idx].level); - chance = level * 4 / 5 + 20; - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[mp_ptr->spell_stat]] - 1); - level /= 2; - if (p_ptr->lev > level) - { - chance -= 3 * (p_ptr->lev - level); - } - chance = mod_spell_chance_1(chance); - chance = MAX(chance, adj_mag_fail[p_ptr->stat_ind[mp_ptr->spell_stat]]); - /* Stunning makes spells harder */ - if (p_ptr->stun > 50) chance += 25; - else if (p_ptr->stun) chance += 15; - - if (chance > 95) chance = 95; - - chance = mod_spell_chance_2(chance); - - col = TERM_WHITE; - - if (k_idx) - { - if (tval == TV_ROD) - { - strcat(dummy, format( - _(" %-22.22s 充填:%2d/%2d%3d%%", " %-22.22s (%2d/%2d) %3d%%"), - k_name + k_info[k_idx].name, - p_ptr->magic_num1[ctr+ext] ? - (p_ptr->magic_num1[ctr+ext] - 1) / (EATER_ROD_CHARGE * k_info[k_idx].pval) +1 : 0, - p_ptr->magic_num2[ctr+ext], chance)); - if (p_ptr->magic_num1[ctr+ext] > k_info[k_idx].pval * (p_ptr->magic_num2[ctr+ext]-1) * EATER_ROD_CHARGE) col = TERM_RED; - } - else - { - strcat(dummy, format(" %-22.22s %2d/%2d %3d%%", k_name + k_info[k_idx].name, (s16b)(p_ptr->magic_num1[ctr+ext]/EATER_CHARGE), p_ptr->magic_num2[ctr+ext], chance)); - if (p_ptr->magic_num1[ctr+ext] < EATER_CHARGE) col = TERM_RED; - } - } - else - strcpy(dummy, ""); - c_prt(col, dummy, y1, x1); - } - } - - if (!get_com(out_val, &choice, FALSE)) break; - - if (use_menu && choice != ' ') - { - switch (choice) - { - case '0': - { - screen_load(); - return 0; - } - - case '8': - case 'k': - case 'K': - { - do - { - menu_line += EATER_EXT - 1; - if (menu_line > EATER_EXT) menu_line -= EATER_EXT; - } while(!p_ptr->magic_num2[menu_line+ext-1]); - break; - } - - case '2': - case 'j': - case 'J': - { - do - { - menu_line++; - if (menu_line > EATER_EXT) menu_line -= EATER_EXT; - } while(!p_ptr->magic_num2[menu_line+ext-1]); - break; - } - - case '4': - case 'h': - case 'H': - case '6': - case 'l': - case 'L': - { - bool reverse = FALSE; - if ((choice == '4') || (choice == 'h') || (choice == 'H')) reverse = TRUE; - if (menu_line > EATER_EXT/2) - { - menu_line -= EATER_EXT/2; - reverse = TRUE; - } - else menu_line+=EATER_EXT/2; - while(!p_ptr->magic_num2[menu_line+ext-1]) - { - if (reverse) - { - menu_line--; - if (menu_line < 2) reverse = FALSE; - } - else - { - menu_line++; - if (menu_line > EATER_EXT-1) reverse = TRUE; - } - } - break; - } - - case 'x': - case 'X': - case '\r': - { - i = menu_line - 1; - ask = FALSE; - break; - } - } - } - - /* Request redraw */ - if (use_menu && ask) continue; - - /* Request redraw */ - if (!use_menu && ((choice == ' ') || (choice == '*') || (choice == '?'))) - { - /* Hide the list */ - if (request_list) - { - /* Hide list */ - request_list = FALSE; - screen_load(); - screen_save(); - } - else - request_list = TRUE; - - /* Redo asking */ - continue; - } - - if (!use_menu) - { - if (isalpha(choice)) - { - /* Note verify */ - ask = (isupper(choice)); - - /* Lowercase */ - if (ask) choice = (char)tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - } - else - { - ask = FALSE; /* Can't uppercase digits */ - - i = choice - '0' + 26; - } - } - - /* Totally Illegal */ - if ((i < 0) || (i > EATER_EXT) || !p_ptr->magic_num2[i+ext]) - { - bell(); - continue; - } - - if (!only_browse) - { - /* Verify it */ - if (ask) - { - char tmp_val[160]; - - /* Prompt */ - (void) strnfmt(tmp_val, 78, _("%sを使いますか? ", "Use %s?"), k_name + k_info[lookup_kind(tval ,i)].name); - - /* Belay that order */ - if (!get_check(tmp_val)) continue; - } - if (tval == TV_ROD) - { - if (p_ptr->magic_num1[ext+i] > k_info[lookup_kind(tval, i)].pval * (p_ptr->magic_num2[ext+i] - 1) * EATER_ROD_CHARGE) - { - msg_print(_("その魔法はまだ充填している最中だ。", "The magic are still charging.")); - msg_print(NULL); - if (use_menu) ask = TRUE; - continue; - } - } - else - { - if (p_ptr->magic_num1[ext+i] < EATER_CHARGE) - { - msg_print(_("その魔法は使用回数が切れている。", "The magic has no charges left.")); - msg_print(NULL); - if (use_menu) ask = TRUE; - continue; - } - } - } - - /* Browse */ - else - { - int line, j; - char temp[70 * 20]; - - /* Clear lines, position cursor (really should use strlen here) */ - Term_erase(7, 23, 255); - Term_erase(7, 22, 255); - Term_erase(7, 21, 255); - Term_erase(7, 20, 255); - - roff_to_buf(k_text + k_info[lookup_kind(tval, i)].text, 62, temp, sizeof(temp)); - for (j = 0, line = 21; temp[j]; j += 1 + strlen(&temp[j])) - { - prt(&temp[j], line, 10); - line++; - } - - continue; - } - - /* Stop the loop */ - flag = TRUE; - } - screen_load(); - - if (!flag) return -1; - - repeat_push(ext+i); - return ext+i; -} - - -/*! - * @brief 取り込んだ魔力を利用するコマンドのメインルーチン / - * Use eaten rod, wand or staff - * @param only_browse 閲覧するだけならばTRUE - * @param powerful 強力発動中の処理ならばTRUE - * @return 実際にコマンドを実行したならばTRUEを返す。 - */ -bool do_cmd_magic_eater(bool only_browse, bool powerful) -{ - OBJECT_SUBTYPE_VALUE item; - PERCENTAGE chance; - DEPTH level; - KIND_OBJECT_IDX k_idx; - OBJECT_TYPE_VALUE tval; - OBJECT_SUBTYPE_VALUE sval; - bool use_charge = TRUE; - - if (cmd_limit_confused(p_ptr)) return FALSE; - - item = select_magic_eater(only_browse); - if (item == -1) - { - free_turn(p_ptr); - return FALSE; - } - if (item >= EATER_EXT*2) {tval = TV_ROD;sval = item - EATER_EXT*2;} - else if (item >= EATER_EXT) {tval = TV_WAND;sval = item - EATER_EXT;} - else {tval = TV_STAFF; sval = item;} - k_idx = lookup_kind(tval, sval); - - level = (tval == TV_ROD ? k_info[k_idx].level * 5 / 6 - 5 : k_info[k_idx].level); - chance = level * 4 / 5 + 20; - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[mp_ptr->spell_stat]] - 1); - level /= 2; - if (p_ptr->lev > level) - { - chance -= 3 * (p_ptr->lev - level); - } - chance = mod_spell_chance_1(chance); - chance = MAX(chance, adj_mag_fail[p_ptr->stat_ind[mp_ptr->spell_stat]]); - /* Stunning makes spells harder */ - if (p_ptr->stun > 50) chance += 25; - else if (p_ptr->stun) chance += 15; - - if (chance > 95) chance = 95; - - chance = mod_spell_chance_2(chance); - - if (randint0(100) < chance) - { - if (flush_failure) flush(); - - msg_print(_("呪文をうまく唱えられなかった!", "You failed to get the magic off!")); - sound(SOUND_FAIL); - if (randint1(100) >= chance) - chg_virtue(V_CHANCE,-1); - take_turn(p_ptr, 100); - - return TRUE; - } - else - { - DIRECTION dir = 0; - - if (tval == TV_ROD) - { - if ((sval >= SV_ROD_MIN_DIRECTION) && (sval != SV_ROD_HAVOC) && (sval != SV_ROD_AGGRAVATE) && (sval != SV_ROD_PESTICIDE)) - if (!get_aim_dir(&dir)) return FALSE; - rod_effect(sval, dir, &use_charge, powerful, TRUE); - if (!use_charge) return FALSE; - } - else if (tval == TV_WAND) - { - if (!get_aim_dir(&dir)) return FALSE; - wand_effect(sval, dir, powerful, TRUE); - } - else - { - staff_effect(sval, &use_charge, powerful, TRUE, TRUE); - if (!use_charge) return FALSE; - } - if (randint1(100) < chance) - chg_virtue(V_CHANCE,1); - } - take_turn(p_ptr, 100); - if (tval == TV_ROD) p_ptr->magic_num1[item] += k_info[k_idx].pval * EATER_ROD_CHARGE; - else p_ptr->magic_num1[item] -= EATER_CHARGE; - - return TRUE; -} diff --git a/src/cmd-magiceat.h b/src/cmd-magiceat.h deleted file mode 100644 index 5e4cd0b2c..000000000 --- a/src/cmd-magiceat.h +++ /dev/null @@ -1 +0,0 @@ -extern bool do_cmd_magic_eater(bool only_browse, bool powerful); diff --git a/src/cmd-mane.c b/src/cmd-mane.c deleted file mode 100644 index 6a7b5dca5..000000000 --- a/src/cmd-mane.c +++ /dev/null @@ -1,985 +0,0 @@ -/*! - * @file mane.c - * @brief ものまねの処理実装 / Imitation code - * @date 2014/01/14 - * @author - * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n - * This software may be copied and distributed for educational, research,\n - * and not for profit purposes provided that this copyright and statement\n - * are included in all such copies. Other copyrights may also apply.\n - * 2014 Deskull rearranged comment for Doxygen.\n - */ - -#include "angband.h" -#include "spells-summon.h" -#include "spells-status.h" -#include "cmd-spell.h" -#include "player-status.h" - -static int damage; - -/*! - * @brief 受け取ったパラメータに応じてものまねの効果情報をまとめたフォーマットを返す - * @param p 情報を返す文字列参照ポインタ - * @param power ものまねの効力の種類 - * @param dam ものまねの威力 - * @return なし - */ -static void mane_info(char *p, int power, HIT_POINT dam) -{ - PLAYER_LEVEL plev = p_ptr->lev; - - strcpy(p, ""); - - if ((power > 2 && power < 41) || (power > 41 && power < 59) || (power == 75)) - sprintf(p, " %s%d", KWD_DAM, (int)dam); - else - { - switch (power) - { - case 41: - sprintf(p, " %sd%d+%d", KWD_HEAL, plev * 3, plev); - break; - case 64: - sprintf(p, " %sd%d+%d", KWD_DURATION, 20+plev, plev); - break; - case 66: - sprintf(p, " %s%d", KWD_HEAL, plev*6); - break; - case 67: - sprintf(p, " %sd7+7", KWD_DURATION); - break; - case 68: - sprintf(p, " %s10", KWD_SPHERE); - break; - case 69: - sprintf(p, " %s%d", KWD_SPHERE, plev * 5); - break; - case 79: - sprintf(p, " %s5", KWD_SPHERE); - break; - default: - break; - } - } -} - - -/*! - * @brief どのものまねを発動するか選択する処理 / - * Allow user to choose a imitation. - * @param sn 実行したものまねのIDを返す参照ポインタ(キャンセルなどの場合-1を返す) - * @param baigaesi TRUEならば倍返し上の処理として行う - * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。 - * @details - * If a valid spell is chosen, saves it in '*sn' and returns TRUE - * If the user hits escape, returns FALSE, and set '*sn' to -1 - * If there are no legal choices, returns FALSE, and sets '*sn' to -2 - * - * The "prompt" should be "cast", "recite", or "study" - * The "known" should be TRUE for cast/pray, FALSE for study - * - * nb: This function has a (trivial) display bug which will be obvious - * when you run it. It's probably easy to fix but I haven't tried, - * sorry. - */ -static int get_mane_power(int *sn, bool baigaesi) -{ - int i = 0; - int num = 0; - TERM_LEN y = 1; - TERM_LEN x = 18; - PERCENTAGE minfail = 0; - PLAYER_LEVEL plev = p_ptr->lev; - PERCENTAGE chance = 0; - int ask; - char choice; - char out_val[160]; - char comment[80]; - concptr p = _("能力", "power"); - - monster_power spell; - bool flag, redraw; - - /* Assume cancelled */ - *sn = (-1); - - /* Nothing chosen yet */ - flag = FALSE; - - /* No redraw yet */ - redraw = FALSE; - - num = p_ptr->mane_num; - - /* Build a prompt (accept all spells) */ - (void)strnfmt(out_val, 78, - _("(%c-%c, '*'で一覧, ESC) どの%sをまねますか?", "(%c-%c, *=List, ESC=exit) Use which %s? "), - I2A(0), I2A(num - 1), p); - - choice= always_show_list ? ESCAPE:1 ; - while (!flag) - { - if(choice==ESCAPE) choice = ' '; - else if( !get_com(out_val, &choice, TRUE) )break; - - /* Request redraw */ - if ((choice == ' ') || (choice == '*') || (choice == '?')) - { - /* Show the list */ - if (!redraw) - { - char psi_desc[80]; - redraw = TRUE; - screen_save(); - - /* Display a list of spells */ - prt("", y, x); - put_str(_("名前", "Name"), y, x + 5); - put_str(_("失率 効果", "Fail Info"), y, x + 36); - - - /* Dump the spells */ - for (i = 0; i < num; i++) - { - /* Access the spell */ - spell = monster_powers[p_ptr->mane_spell[i]]; - - chance = spell.manefail; - - /* Reduce failure rate by "effective" level adjustment */ - if (plev > spell.level) chance -= 3 * (plev - spell.level); - - /* Reduce failure rate by INT/WIS adjustment */ - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[spell.use_stat]] + adj_mag_stat[p_ptr->stat_ind[A_DEX]] - 2) / 2; - - if (spell.manedam) chance = chance * (baigaesi ? p_ptr->mane_dam[i] * 2 : p_ptr->mane_dam[i]) / spell.manedam; - - chance += p_ptr->to_m_chance; - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[spell.use_stat]]; - - /* Minimum failure rate */ - if (chance < minfail) chance = minfail; - - /* Stunning makes spells harder */ - if (p_ptr->stun > 50) chance += 25; - else if (p_ptr->stun) chance += 15; - - /* Always a 5 percent chance of working */ - if (chance > 95) chance = 95; - - /* Get info */ - mane_info(comment, p_ptr->mane_spell[i], (baigaesi ? p_ptr->mane_dam[i]*2 : p_ptr->mane_dam[i])); - - /* Dump the spell --(-- */ - sprintf(psi_desc, " %c) %-30s %3d%%%s", - I2A(i), spell.name, - chance, comment); - prt(psi_desc, y + i + 1, x); - } - - /* Clear the bottom line */ - prt("", y + i + 1, x); - } - - /* Hide the list */ - else - { - /* Hide list */ - redraw = FALSE; - screen_load(); - } - - /* Redo asking */ - continue; - } - - /* Note verify */ - ask = isupper(choice); - - /* Lowercase */ - if (ask) choice = (char)tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - - /* Totally Illegal */ - if ((i < 0) || (i >= num)) - { - bell(); - continue; - } - - /* Save the spell index */ - spell = monster_powers[p_ptr->mane_spell[i]]; - - /* Verify it */ - if (ask) - { - char tmp_val[160]; - - /* Prompt */ - (void) strnfmt(tmp_val, 78, _("%sをまねますか?", "Use %s? "), monster_powers[p_ptr->mane_spell[i]].name); - - /* Belay that order */ - if (!get_check(tmp_val)) continue; - } - - /* Stop the loop */ - flag = TRUE; - } - if (redraw) screen_load(); - - p_ptr->window |= (PW_SPELL); - handle_stuff(); - - /* Abort if needed */ - if (!flag) return (FALSE); - - /* Save the choice */ - (*sn) = i; - - damage = (baigaesi ? p_ptr->mane_dam[i]*2 : p_ptr->mane_dam[i]); - - /* Success */ - return (TRUE); -} - - -/*! - * @brief ものまね処理の発動 / - * do_cmd_cast calls this function if the player's class is 'imitator'. - * @param spell 発動するモンスター攻撃のID - * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。 - */ -static bool use_mane(int spell) -{ - DIRECTION dir; - PLAYER_LEVEL plev = p_ptr->lev; - BIT_FLAGS mode = (PM_ALLOW_GROUP | PM_FORCE_PET); - BIT_FLAGS u_mode = 0L; - - if (randint1(50+plev) < plev/10) u_mode = PM_ALLOW_UNIQUE; - - - /* spell code */ - switch (spell) - { - - case MS_SHRIEK: - msg_print(_("かん高い金切り声をあげた。", "You make a high pitched shriek.")); - aggravate_monsters(0); - break; - - case MS_XXX1: - break; - - case MS_DISPEL: - { - MONSTER_IDX m_idx; - - if (!target_set(TARGET_KILL)) return FALSE; - m_idx = current_floor_ptr->grid_array[target_row][target_col].m_idx; - if (!m_idx) break; - if (!player_has_los_bold(target_row, target_col)) break; - if (!projectable(p_ptr->y, p_ptr->x, target_row, target_col)) break; - dispel_monster_status(m_idx); - break; - } - - case MS_ROCKET: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("ロケットを発射した。", "You fire a rocket.")); - fire_rocket(GF_ROCKET, dir, damage, 2); - break; - - case MS_SHOOT: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("矢を放った。", "You fire an arrow.")); - fire_bolt(GF_ARROW, dir, damage); - break; - - case MS_XXX2: - break; - - case MS_XXX3: - break; - - case MS_XXX4: - break; - - case MS_BR_ACID: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("酸のブレスを吐いた。", "You breathe acid.")); - fire_breath(GF_ACID, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_ELEC: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("稲妻のブレスを吐いた。", "You breathe lightning.")); - fire_breath(GF_ELEC, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_FIRE: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("火炎のブレスを吐いた。", "You breathe fire.")); - fire_breath(GF_FIRE, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_COLD: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("冷気のブレスを吐いた。", "You breathe frost.")); - fire_breath(GF_COLD, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_POIS: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("ガスのブレスを吐いた。", "You breathe gas.")); - fire_breath(GF_POIS, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_NETHER: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("地獄のブレスを吐いた。", "You breathe nether.")); - fire_breath(GF_NETHER, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_LITE: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("閃光のブレスを吐いた。", "You breathe light.")); - fire_breath(GF_LITE, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_DARK: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("暗黒のブレスを吐いた。", "You breathe darkness.")); - fire_breath(GF_DARK, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_CONF: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("混乱のブレスを吐いた。", "You breathe confusion.")); - fire_breath(GF_CONFUSION, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_SOUND: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("轟音のブレスを吐いた。", "You breathe sound.")); - fire_breath(GF_SOUND, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_CHAOS: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("カオスのブレスを吐いた。", "You breathe chaos.")); - fire_breath(GF_CHAOS, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_DISEN: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("劣化のブレスを吐いた。", "You breathe disenchantment.")); - fire_breath(GF_DISENCHANT, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_NEXUS: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("因果混乱のブレスを吐いた。", "You breathe nexus.")); - fire_breath(GF_NEXUS, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_TIME: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("時間逆転のブレスを吐いた。", "You breathe time.")); - fire_breath(GF_TIME, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_INERTIA: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("遅鈍のブレスを吐いた。", "You breathe inertia.")); - fire_breath(GF_INERTIAL, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_GRAVITY: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("重力のブレスを吐いた。", "You breathe gravity.")); - fire_breath(GF_GRAVITY, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_SHARDS: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("破片のブレスを吐いた。", "You breathe shards.")); - fire_breath(GF_SHARDS, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_PLASMA: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("プラズマのブレスを吐いた。", "You breathe plasma.")); - - fire_breath(GF_PLASMA, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_FORCE: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("フォースのブレスを吐いた。", "You breathe force.")); - - fire_breath(GF_FORCE, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BR_MANA: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("魔力のブレスを吐いた。", "You breathe mana.")); - - fire_breath(GF_MANA, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BALL_NUKE: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("放射能球を放った。", "You cast a ball of radiation.")); - - fire_ball(GF_NUKE, dir, damage, 2); - break; - - case MS_BR_NUKE: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("放射性廃棄物のブレスを吐いた。", "You breathe toxic waste.")); - - fire_breath(GF_NUKE, dir, damage, (plev > 35 ? 3 : 2)); - break; - - case MS_BALL_CHAOS: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("純ログルスを放った。", "You invoke a raw Logrus.")); - - fire_ball(GF_CHAOS, dir, damage, 4); - break; - case MS_BR_DISI: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("分解のブレスを吐いた。", "You breathe disintegration.")); - - fire_breath(GF_DISINTEGRATE, dir, damage, (plev > 35 ? 3 : 2)); - break; - case MS_BALL_ACID: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("アシッド・ボールの呪文を唱えた。", "You cast an acid ball.")); - - fire_ball(GF_ACID, dir, damage, 2); - break; - case MS_BALL_ELEC: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("サンダー・ボールの呪文を唱えた。", "You cast a lightning ball.")); - - fire_ball(GF_ELEC, dir, damage, 2); - break; - case MS_BALL_FIRE: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("ファイア・ボールの呪文を唱えた。", "You cast a fire ball.")); - - fire_ball(GF_FIRE, dir, damage, 2); - break; - case MS_BALL_COLD: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("アイス・ボールの呪文を唱えた。", "You cast a frost ball.")); - - fire_ball(GF_COLD, dir, damage, 2); - break; - case MS_BALL_POIS: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("悪臭雲の呪文を唱えた。", "You cast a stinking cloud.")); - - fire_ball(GF_POIS, dir, damage, 2); - break; - case MS_BALL_NETHER: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("地獄球の呪文を唱えた。", "You cast a nether ball.")); - - fire_ball(GF_NETHER, dir, damage, 2); - break; - case MS_BALL_WATER: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("流れるような身振りをした。", "You gesture fluidly.")); - - fire_ball(GF_WATER, dir, damage, 4); - break; - case MS_BALL_MANA: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("魔力の嵐の呪文を念じた。", "You invoke a mana storm.")); - - fire_ball(GF_MANA, dir, damage, 4); - break; - case MS_BALL_DARK: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("暗黒の嵐の呪文を念じた。", "You invoke a darkness storm.")); - - fire_ball(GF_DARK, dir, damage, 4); - break; - case MS_DRAIN_MANA: - if (!get_aim_dir(&dir)) return FALSE; - fire_ball_hide(GF_DRAIN_MANA, dir, randint1(plev*3)+plev, 0); - break; - case MS_MIND_BLAST: - if (!get_aim_dir(&dir)) return FALSE; - fire_ball_hide(GF_MIND_BLAST, dir, damage, 0); - break; - case MS_BRAIN_SMASH: - if (!get_aim_dir(&dir)) return FALSE; - fire_ball_hide(GF_BRAIN_SMASH, dir, damage, 0); - break; - case MS_CAUSE_1: - if (!get_aim_dir(&dir)) return FALSE; - fire_ball_hide(GF_CAUSE_1, dir, damage, 0); - break; - case MS_CAUSE_2: - if (!get_aim_dir(&dir)) return FALSE; - fire_ball_hide(GF_CAUSE_2, dir, damage, 0); - break; - case MS_CAUSE_3: - if (!get_aim_dir(&dir)) return FALSE; - fire_ball_hide(GF_CAUSE_3, dir, damage, 0); - break; - case MS_CAUSE_4: - if (!get_aim_dir(&dir)) return FALSE; - fire_ball_hide(GF_CAUSE_4, dir, damage, 0); - break; - case MS_BOLT_ACID: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("アシッド・ボルトの呪文を唱えた。", "You cast an acid bolt.")); - - fire_bolt(GF_ACID, dir, damage); - break; - case MS_BOLT_ELEC: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("サンダー・ボルトの呪文を唱えた。", "You cast a lightning bolt.")); - - fire_bolt(GF_ELEC, dir, damage); - break; - case MS_BOLT_FIRE: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("ファイア・ボルトの呪文を唱えた。", "You cast a fire bolt.")); - - fire_bolt(GF_FIRE, dir, damage); - break; - case MS_BOLT_COLD: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("アイス・ボルトの呪文を唱えた。", "You cast a frost bolt.")); - - fire_bolt(GF_COLD, dir, damage); - break; - case MS_STARBURST: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("スターバーストの呪文を念じた。", "You invoke a starburst.")); - - fire_ball(GF_LITE, dir, damage, 4); - break; - case MS_BOLT_NETHER: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("地獄の矢の呪文を唱えた。", "You cast a nether bolt.")); - - fire_bolt(GF_NETHER, dir, damage); - break; - case MS_BOLT_WATER: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("ウォーター・ボルトの呪文を唱えた。", "You cast a water bolt.")); - - fire_bolt(GF_WATER, dir, damage); - break; - case MS_BOLT_MANA: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("魔力の矢の呪文を唱えた。", "You cast a mana bolt.")); - - fire_bolt(GF_MANA, dir, damage); - break; - case MS_BOLT_PLASMA: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("プラズマ・ボルトの呪文を唱えた。", "You cast a plasma bolt.")); - - fire_bolt(GF_PLASMA, dir, damage); - break; - case MS_BOLT_ICE: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("極寒の矢の呪文を唱えた。", "You cast a ice bolt.")); - - fire_bolt(GF_ICE, dir, damage); - break; - case MS_MAGIC_MISSILE: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("マジック・ミサイルの呪文を唱えた。", "You cast a magic missile.")); - - fire_bolt(GF_MISSILE, dir, damage); - break; - case MS_SCARE: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("恐ろしげな幻覚を作り出した。", "You cast a fearful illusion.")); - - fear_monster(dir, plev+10); - break; - case MS_BLIND: - if (!get_aim_dir(&dir)) return FALSE; - confuse_monster(dir, plev * 2); - break; - case MS_CONF: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("誘惑的な幻覚をつくり出した。", "You cast a mesmerizing illusion.")); - - confuse_monster(dir, plev * 2); - break; - case MS_SLOW: - if (!get_aim_dir(&dir)) return FALSE; - slow_monster(dir, plev); - break; - case MS_SLEEP: - if (!get_aim_dir(&dir)) return FALSE; - sleep_monster(dir, plev); - break; - case MS_SPEED: - (void)set_fast(randint1(20 + plev) + plev, FALSE); - break; - case MS_HAND_DOOM: - { - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("<破滅の手>を放った!", "You invoke the Hand of Doom!")); - - fire_ball_hide(GF_HAND_DOOM, dir, 200, 0); - break; - } - case MS_HEAL: - msg_print(_("自分の傷に念を集中した。", "You concentrate on your wounds!")); - (void)hp_player(plev*6); - (void)set_stun(0); - (void)set_cut(0); - break; - case MS_INVULNER: - msg_print(_("無傷の球の呪文を唱えた。", "You cast a Globe of Invulnerability.")); - (void)set_invuln(randint1(7) + 7, FALSE); - break; - case MS_BLINK: - teleport_player(10, 0L); - break; - case MS_TELEPORT: - teleport_player(plev * 5, 0L); - break; - case MS_WORLD: - (void)time_walk(p_ptr); - break; - case MS_SPECIAL: - break; - case MS_TELE_TO: - { - monster_type *m_ptr; - monster_race *r_ptr; - GAME_TEXT m_name[MAX_NLEN]; - - if (!target_set(TARGET_KILL)) return FALSE; - if (!current_floor_ptr->grid_array[target_row][target_col].m_idx) break; - if (!player_has_los_bold(target_row, target_col)) break; - if (!projectable(p_ptr->y, p_ptr->x, target_row, target_col)) break; - m_ptr = ¤t_floor_ptr->m_list[current_floor_ptr->grid_array[target_row][target_col].m_idx]; - r_ptr = &r_info[m_ptr->r_idx]; - monster_desc(m_name, m_ptr, 0); - if (r_ptr->flagsr & RFR_RES_TELE) - { - if ((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flagsr & RFR_RES_ALL)) - { - if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; - msg_format(_("%sには効果がなかった!", "%s is unaffected!"), m_name); - - break; - } - else if (r_ptr->level > randint1(100)) - { - if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE; - msg_format(_("%sには耐性がある!", "%s resists!"), m_name); - - break; - } - } - msg_format(_("%sを引き戻した。", "You command %s to return."), m_name); - - teleport_monster_to(current_floor_ptr->grid_array[target_row][target_col].m_idx, p_ptr->y, p_ptr->x, 100, TELEPORT_PASSIVE); - break; - } - case MS_TELE_AWAY: - if (!get_aim_dir(&dir)) return FALSE; - - (void)fire_beam(GF_AWAY_ALL, dir, plev); - break; - - case MS_TELE_LEVEL: - return teleport_level_other(p_ptr); - break; - - case MS_PSY_SPEAR: - if (!get_aim_dir(&dir)) return FALSE; - else msg_print(_("光の剣を放った。", "You throw a psycho-spear.")); - (void)fire_beam(GF_PSY_SPEAR, dir, damage); - break; - - case MS_DARKNESS: - msg_print(_("暗闇の中で手を振った。", "You gesture in shadow.")); - (void)unlite_area(10, 3); - break; - - case MS_MAKE_TRAP: - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("呪文を唱えて邪悪に微笑んだ。", "You cast a spell and cackles evilly.")); - trap_creation(target_row, target_col); - break; - case MS_FORGET: - msg_print(_("しかし何も起きなかった。", "Nothing happen.")); - break; - case MS_RAISE_DEAD: - msg_print(_("死者復活の呪文を唱えた。", "You cast a animate dead.")); - (void)animate_dead(0, p_ptr->y, p_ptr->x); - break; - case MS_S_KIN: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - - msg_print(_("援軍を召喚した。", "You summon minions.")); - for (k = 0;k < 4; k++) - { - (void)summon_kin_player(plev, target_row, target_col, (PM_FORCE_PET | PM_ALLOW_GROUP)); - } - break; - } - case MS_S_CYBER: - { - int k; - int max_cyber = (current_floor_ptr->dun_level / 50) + randint1(3); - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("サイバーデーモンを召喚した!", "You summon Cyberdemons!")); - if (max_cyber > 4) max_cyber = 4; - for (k = 0;k < max_cyber; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_CYBER, mode, '\0'); - break; - } - case MS_S_MONSTER: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("仲間を召喚した。", "You summon help.")); - for (k = 0;k < 1; k++) - summon_specific(-1, target_row, target_col, plev, 0, (mode | u_mode), '\0'); - break; - } - case MS_S_MONSTERS: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("モンスターを召喚した!", "You summon monsters!")); - for (k = 0; k < 6; k++) - summon_specific(-1, target_row, target_col, plev, 0, (mode | u_mode), '\0'); - break; - } - case MS_S_ANT: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("アリを召喚した。", "You summon ants.")); - for (k = 0; k < 6; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_ANT, mode, '\0'); - break; - } - case MS_S_SPIDER: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("蜘蛛を召喚した。", "You summon spiders.")); - for (k = 0; k < 6; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_SPIDER, mode, '\0'); - break; - } - case MS_S_HOUND: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("ハウンドを召喚した。", "You summon hounds.")); - for (k = 0; k < 4; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_HOUND, mode, '\0'); - break; - } - case MS_S_HYDRA: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("ヒドラを召喚した。", "You summon hydras.")); - for (k = 0; k < 4; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_HYDRA, mode, '\0'); - break; - } - case MS_S_ANGEL: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("天使を召喚した!", "You summon angel!")); - for (k = 0; k < 1; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_ANGEL, mode, '\0'); - break; - } - case MS_S_DEMON: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("混沌の宮廷から悪魔を召喚した!", "You summon a demon from the Courts of Chaos!")); - for (k = 0; k < 1; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_DEMON, (mode | u_mode), '\0'); - break; - } - case MS_S_UNDEAD: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("アンデッドの強敵を召喚した!", "You summon an undead adversary!")); - for (k = 0; k < 1; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_UNDEAD, (mode | u_mode), '\0'); - break; - } - case MS_S_DRAGON: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("ドラゴンを召喚した!", "You summon dragon!")); - for (k = 0; k < 1; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_DRAGON, (mode | u_mode), '\0'); - break; - } - case MS_S_HI_UNDEAD: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("強力なアンデッドを召喚した!", "You summon greater undead!")); - for (k = 0; k < 6; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_HI_UNDEAD, (mode | u_mode), '\0'); - break; - } - case MS_S_HI_DRAGON: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("古代ドラゴンを召喚した!", "You summon ancient dragons!")); - for (k = 0; k < 4; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_HI_DRAGON, (mode | u_mode), '\0'); - break; - } - case MS_S_AMBERITE: - { - int k; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("アンバーの王族を召喚した!", "You summon Lords of Amber!")); - for (k = 0; k < 4; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_AMBERITES, (mode | PM_ALLOW_UNIQUE), '\0'); - break; - } - case MS_S_UNIQUE: - { - int k, count = 0; - if (!target_set(TARGET_KILL)) return FALSE; - msg_print(_("特別な強敵を召喚した!", "You summon special opponents!")); - for (k = 0;k < 4; k++) - if (summon_specific(-1, target_row, target_col, plev, SUMMON_UNIQUE, (mode | PM_ALLOW_UNIQUE), '\0')) count++; - for (k = count;k < 4; k++) - summon_specific(-1, target_row, target_col, plev, SUMMON_HI_UNDEAD, (mode | u_mode), '\0'); - break; - } - default: - msg_print("hoge?"); - } - - return TRUE; -} - - -/*! - * @brief ものまねコマンドのメインルーチン / - * do_cmd_cast calls this function if the player's class is 'imitator'. - * @param baigaesi TRUEならば倍返し上の処理として行う - * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。 - * @details - * If a valid spell is chosen, saves it in '*sn' and returns TRUE - * If the user hits escape, returns FALSE, and set '*sn' to -1 - * If there are no legal choices, returns FALSE, and sets '*sn' to -2 - * - * The "prompt" should be "cast", "recite", or "study" - * The "known" should be TRUE for cast/pray, FALSE for study - * - * nb: This function has a (trivial) display bug which will be obvious - * when you run it. It's probably easy to fix but I haven't tried, - * sorry. - */ -bool do_cmd_mane(bool baigaesi) -{ - int n = 0, j; - PERCENTAGE chance; - PERCENTAGE minfail = 0; - PLAYER_LEVEL plev = p_ptr->lev; - monster_power spell; - bool cast; - - if (cmd_limit_confused(p_ptr)) return FALSE; - - if (!p_ptr->mane_num) - { - msg_print(_("まねられるものが何もない!", "You don't remember any action!")); - return FALSE; - } - - if (!get_mane_power(&n, baigaesi)) return FALSE; - - spell = monster_powers[p_ptr->mane_spell[n]]; - - /* Spell failure chance */ - chance = spell.manefail; - - /* Reduce failure rate by "effective" level adjustment */ - if (plev > spell.level) chance -= 3 * (plev - spell.level); - - /* Reduce failure rate by 1 stat and DEX adjustment */ - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[spell.use_stat]] + adj_mag_stat[p_ptr->stat_ind[A_DEX]] - 2) / 2; - - if (spell.manedam) chance = chance * damage / spell.manedam; - - chance += p_ptr->to_m_chance; - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[spell.use_stat]]; - - /* Minimum failure rate */ - if (chance < minfail) chance = minfail; - - /* Stunning makes spells harder */ - if (p_ptr->stun > 50) chance += 25; - else if (p_ptr->stun) chance += 15; - - /* Always a 5 percent chance of working */ - if (chance > 95) chance = 95; - - /* Failed spell */ - if (randint0(100) < chance) - { - if (flush_failure) flush(); - msg_print(_("ものまねに失敗した!", "You failed to concentrate hard enough!")); - sound(SOUND_FAIL); - } - else - { - sound(SOUND_ZAP); - cast = use_mane(p_ptr->mane_spell[n]); - if (!cast) return FALSE; - } - - p_ptr->mane_num--; - for (j = n; j < p_ptr->mane_num;j++) - { - p_ptr->mane_spell[j] = p_ptr->mane_spell[j+1]; - p_ptr->mane_dam[j] = p_ptr->mane_dam[j+1]; - } - - take_turn(p_ptr, 100); - - p_ptr->redraw |= (PR_IMITATION); - p_ptr->window |= (PW_PLAYER); - p_ptr->window |= (PW_SPELL); - - return TRUE; -} diff --git a/src/cmd-mane.h b/src/cmd-mane.h deleted file mode 100644 index 80a71fb2d..000000000 --- a/src/cmd-mane.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -/* mane.c */ -extern bool do_cmd_mane(bool baigaesi); diff --git a/src/cmd-pet.c b/src/cmd-pet.c deleted file mode 100644 index a9013652b..000000000 --- a/src/cmd-pet.c +++ /dev/null @@ -1,1089 +0,0 @@ -#include "angband.h" -#include "melee.h" -#include "sort.h" -#include "player-status.h" -#include "object-hook.h" -#include "monster.h" -#include "monster-status.h" - -/*! -* @brief プレイヤーの騎乗/下馬処理判定 -* @param g_ptr プレイヤーの移動先マスの構造体参照ポインタ -* @param now_riding TRUEなら下馬処理、FALSEならば騎乗処理 -* @return 可能ならばTRUEを返す -*/ -bool player_can_ride_aux(grid_type *g_ptr, bool now_riding) -{ - bool p_can_enter; - bool old_character_xtra = character_xtra; - MONSTER_IDX old_riding = p_ptr->riding; - bool old_riding_ryoute = p_ptr->riding_ryoute; - bool old_old_riding_ryoute = p_ptr->old_riding_ryoute; - bool old_pf_ryoute = (p_ptr->pet_extra_flags & PF_RYOUTE) ? TRUE : FALSE; - - /* Hack -- prevent "icky" message */ - character_xtra = TRUE; - - if (now_riding) p_ptr->riding = g_ptr->m_idx; - else - { - p_ptr->riding = 0; - p_ptr->pet_extra_flags &= ~(PF_RYOUTE); - p_ptr->riding_ryoute = p_ptr->old_riding_ryoute = FALSE; - } - - p_ptr->update |= PU_BONUS; - handle_stuff(); - - p_can_enter = player_can_enter(g_ptr->feat, CEM_P_CAN_ENTER_PATTERN); - - p_ptr->riding = old_riding; - if (old_pf_ryoute) p_ptr->pet_extra_flags |= (PF_RYOUTE); - else p_ptr->pet_extra_flags &= ~(PF_RYOUTE); - p_ptr->riding_ryoute = old_riding_ryoute; - p_ptr->old_riding_ryoute = old_old_riding_ryoute; - - p_ptr->update |= PU_BONUS; - handle_stuff(); - - character_xtra = old_character_xtra; - - return p_can_enter; -} - - -/*! -* @brief ペットの維持コスト計算 -* @return 維持コスト(%) -*/ -PERCENTAGE calculate_upkeep(void) -{ - MONSTER_IDX m_idx; - bool have_a_unique = FALSE; - DEPTH total_friend_levels = 0; - - total_friends = 0; - - for (m_idx = m_max - 1; m_idx >= 1; m_idx--) - { - monster_type *m_ptr; - monster_race *r_ptr; - - m_ptr = ¤t_floor_ptr->m_list[m_idx]; - if (!monster_is_valid(m_ptr)) continue; - r_ptr = &r_info[m_ptr->r_idx]; - - if (is_pet(m_ptr)) - { - total_friends++; - if (r_ptr->flags1 & RF1_UNIQUE) - { - if (p_ptr->pclass == CLASS_CAVALRY) - { - if (p_ptr->riding == m_idx) - total_friend_levels += (r_ptr->level + 5) * 2; - else if (!have_a_unique && (r_info[m_ptr->r_idx].flags7 & RF7_RIDING)) - total_friend_levels += (r_ptr->level + 5) * 7 / 2; - else - total_friend_levels += (r_ptr->level + 5) * 10; - have_a_unique = TRUE; - } - else - total_friend_levels += (r_ptr->level + 5) * 10; - } - else - total_friend_levels += r_ptr->level; - - } - } - - if (total_friends) - { - int upkeep_factor; - upkeep_factor = (total_friend_levels - (p_ptr->lev * 80 / (cp_ptr->pet_upkeep_div))); - if (upkeep_factor < 0) upkeep_factor = 0; - if (upkeep_factor > 1000) upkeep_factor = 1000; - return upkeep_factor; - } - else - return 0; -} - -/*! -* @brief ペットを開放するコマンドのメインルーチン -* @return なし -*/ -void do_cmd_pet_dismiss(void) -{ - monster_type *m_ptr; - bool all_pets = FALSE; - MONSTER_IDX pet_ctr; - int i; - int Dismissed = 0; - - MONSTER_IDX *who; - u16b dummy_why; - int max_pet = 0; - bool_hack cu, cv; - - cu = Term->scr->cu; - cv = Term->scr->cv; - Term->scr->cu = 0; - Term->scr->cv = 1; - - /* Allocate the "who" array */ - C_MAKE(who, current_floor_ptr->max_m_idx, MONSTER_IDX); - - /* Process the monsters (backwards) */ - for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) - { - if (is_pet(¤t_floor_ptr->m_list[pet_ctr])) - who[max_pet++] = pet_ctr; - } - - ang_sort(who, &dummy_why, max_pet, ang_sort_comp_pet_dismiss, ang_sort_swap_hook); - - /* Process the monsters (backwards) */ - for (i = 0; i < max_pet; i++) - { - bool delete_this; - GAME_TEXT friend_name[MAX_NLEN]; - bool kakunin; - - /* Access the monster */ - pet_ctr = who[i]; - m_ptr = ¤t_floor_ptr->m_list[pet_ctr]; - - delete_this = FALSE; - kakunin = ((pet_ctr == p_ptr->riding) || (m_ptr->nickname)); - monster_desc(friend_name, m_ptr, MD_ASSUME_VISIBLE); - - if (!all_pets) - { - /* Hack -- health bar for this monster */ - health_track(pet_ctr); - handle_stuff(); - - msg_format(_("%sを放しますか? [Yes/No/Unnamed (%d体)]", "Dismiss %s? [Yes/No/Unnamed (%d remain)]"), friend_name, max_pet - i); - - if (m_ptr->ml) - move_cursor_relative(m_ptr->fy, m_ptr->fx); - - while (TRUE) - { - char ch = inkey(); - - if (ch == 'Y' || ch == 'y') - { - delete_this = TRUE; - - if (kakunin) - { - msg_format(_("本当によろしいですか? (%s) ", "Are you sure? (%s) "), friend_name); - ch = inkey(); - if (ch != 'Y' && ch != 'y') - delete_this = FALSE; - } - break; - } - - if (ch == 'U' || ch == 'u') - { - all_pets = TRUE; - break; - } - - if (ch == ESCAPE || ch == 'N' || ch == 'n') - break; - - bell(); - } - } - - if ((all_pets && !kakunin) || (!all_pets && delete_this)) - { - if (record_named_pet && m_ptr->nickname) - { - GAME_TEXT m_name[MAX_NLEN]; - - monster_desc(m_name, m_ptr, MD_INDEF_VISIBLE); - do_cmd_write_nikki(NIKKI_NAMED_PET, RECORD_NAMED_PET_DISMISS, m_name); - } - - if (pet_ctr == p_ptr->riding) - { - msg_format(_("%sから降りた。", "You have got off %s. "), friend_name); - - p_ptr->riding = 0; - - p_ptr->update |= (PU_MONSTERS); - p_ptr->redraw |= (PR_EXTRA | PR_UHEALTH); - } - - /* HACK : Add the line to message buffer */ - msg_format(_("%s を放した。", "Dismissed %s."), friend_name); - p_ptr->update |= (PU_BONUS); - p_ptr->window |= (PW_MESSAGE); - - delete_monster_idx(pet_ctr); - Dismissed++; - } - } - - Term->scr->cu = cu; - Term->scr->cv = cv; - Term_fresh(); - - C_KILL(who, current_floor_ptr->max_m_idx, MONSTER_IDX); - -#ifdef JP - msg_format("%d 体のペットを放しました。", Dismissed); -#else - msg_format("You have dismissed %d pet%s.", Dismissed, - (Dismissed == 1 ? "" : "s")); -#endif - if (Dismissed == 0 && all_pets) - msg_print(_("'U'nnamed は、乗馬以外の名前のないペットだけを全て解放します。", "'U'nnamed means all your pets except named pets and your mount.")); - - handle_stuff(); -} - - - -/*! -* @brief ペットから騎乗/下馬するコマンドのメインルーチン / -* @param force 強制的に騎乗/下馬するならばTRUE -* @return 騎乗/下馬できたらTRUE -*/ -bool do_riding(bool force) -{ - POSITION x, y; - DIRECTION dir = 0; - grid_type *g_ptr; - monster_type *m_ptr; - - if (!get_direction(&dir, FALSE, FALSE)) return FALSE; - y = p_ptr->y + ddy[dir]; - x = p_ptr->x + ddx[dir]; - g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - if (p_ptr->special_defense & KATA_MUSOU) set_action(ACTION_NONE); - - if (p_ptr->riding) - { - /* Skip non-empty grids */ - if (!player_can_ride_aux(g_ptr, FALSE)) - { - msg_print(_("そちらには降りられません。", "You cannot go to that direction.")); - return FALSE; - } - - if (!pattern_seq(p_ptr->y, p_ptr->x, y, x)) return FALSE; - - if (g_ptr->m_idx) - { - take_turn(p_ptr, 100); - - msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); - - py_attack(y, x, 0); - return FALSE; - } - - p_ptr->riding = 0; - p_ptr->pet_extra_flags &= ~(PF_RYOUTE); - p_ptr->riding_ryoute = p_ptr->old_riding_ryoute = FALSE; - } - else - { - if (cmd_limit_confused(p_ptr)) return FALSE; - - m_ptr = ¤t_floor_ptr->m_list[g_ptr->m_idx]; - - if (!g_ptr->m_idx || !m_ptr->ml) - { - msg_print(_("その場所にはモンスターはいません。", "Here is no monster.")); - return FALSE; - } - if (!is_pet(m_ptr) && !force) - { - msg_print(_("そのモンスターはペットではありません。", "That monster is not a pet.")); - return FALSE; - } - if (!(r_info[m_ptr->r_idx].flags7 & RF7_RIDING)) - { - msg_print(_("そのモンスターには乗れなさそうだ。", "This monster doesn't seem suitable for riding.")); - return FALSE; - } - - if (!pattern_seq(p_ptr->y, p_ptr->x, y, x)) return FALSE; - - if (!player_can_ride_aux(g_ptr, TRUE)) - { - /* Feature code (applying "mimic" field) */ - feature_type *f_ptr = &f_info[get_feat_mimic(g_ptr)]; -#ifdef JP - msg_format("そのモンスターは%sの%sにいる。", f_name + f_ptr->name, - ((!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) || - (!have_flag(f_ptr->flags, FF_LOS) && !have_flag(f_ptr->flags, FF_TREE))) ? - "中" : "上"); -#else - msg_format("This monster is %s the %s.", - ((!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) || - (!have_flag(f_ptr->flags, FF_LOS) && !have_flag(f_ptr->flags, FF_TREE))) ? - "in" : "on", f_name + f_ptr->name); -#endif - - return FALSE; - } - if (r_info[m_ptr->r_idx].level > randint1((p_ptr->skill_exp[GINOU_RIDING] / 50 + p_ptr->lev / 2 + 20))) - { - msg_print(_("うまく乗れなかった。", "You failed to ride.")); - take_turn(p_ptr, 100); - return FALSE; - } - - if (MON_CSLEEP(m_ptr)) - { - GAME_TEXT m_name[MAX_NLEN]; - monster_desc(m_name, m_ptr, 0); - (void)set_monster_csleep(g_ptr->m_idx, 0); - msg_format(_("%sを起こした。", "You have waked %s up."), m_name); - } - - if (p_ptr->action == ACTION_KAMAE) set_action(ACTION_NONE); - - p_ptr->riding = g_ptr->m_idx; - - /* Hack -- remove tracked monster */ - if (p_ptr->riding == p_ptr->health_who) health_track(0); - } - - take_turn(p_ptr, 100); - - /* Mega-Hack -- Forget the view and lite */ - p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE); - p_ptr->update |= (PU_BONUS); - p_ptr->redraw |= (PR_MAP | PR_EXTRA); - p_ptr->redraw |= (PR_UHEALTH); - - (void)move_player_effect(y, x, MPE_HANDLE_STUFF | MPE_ENERGY_USE | MPE_DONT_PICKUP | MPE_DONT_SWAP_MON); - - return TRUE; -} - -/*! -* @brief ペットに名前をつけるコマンドのメインルーチン -* @return なし -*/ -static void do_name_pet(void) -{ - monster_type *m_ptr; - char out_val[20]; - GAME_TEXT m_name[MAX_NLEN]; - bool old_name = FALSE; - bool old_target_pet = target_pet; - - target_pet = TRUE; - if (!target_set(TARGET_KILL)) - { - target_pet = old_target_pet; - return; - } - target_pet = old_target_pet; - - if (current_floor_ptr->grid_array[target_row][target_col].m_idx) - { - m_ptr = ¤t_floor_ptr->m_list[current_floor_ptr->grid_array[target_row][target_col].m_idx]; - - if (!is_pet(m_ptr)) - { - msg_print(_("そのモンスターはペットではない。", "This monster is not a pet.")); - return; - } - if (r_info[m_ptr->r_idx].flags1 & RF1_UNIQUE) - { - msg_print(_("そのモンスターの名前は変えられない!", "You cannot change name of this monster!")); - return; - } - monster_desc(m_name, m_ptr, 0); - - msg_format(_("%sに名前をつける。", "Name %s."), m_name); - msg_print(NULL); - - /* Start with nothing */ - strcpy(out_val, ""); - - /* Use old inscription */ - if (m_ptr->nickname) - { - /* Start with the old inscription */ - strcpy(out_val, quark_str(m_ptr->nickname)); - old_name = TRUE; - } - - /* Get a new inscription (possibly empty) */ - if (get_string(_("名前: ", "Name: "), out_val, 15)) - { - if (out_val[0]) - { - /* Save the inscription */ - m_ptr->nickname = quark_add(out_val); - if (record_named_pet) - { - monster_desc(m_name, m_ptr, MD_INDEF_VISIBLE); - do_cmd_write_nikki(NIKKI_NAMED_PET, RECORD_NAMED_PET_NAME, m_name); - } - } - else - { - if (record_named_pet && old_name) - { - monster_desc(m_name, m_ptr, MD_INDEF_VISIBLE); - do_cmd_write_nikki(NIKKI_NAMED_PET, RECORD_NAMED_PET_UNNAME, m_name); - } - m_ptr->nickname = 0; - } - } - } -} - - -/*! -* @brief ペットに関するコマンドリストのメインルーチン / -* Issue a pet command -* @return なし -*/ -void do_cmd_pet(void) -{ - COMMAND_CODE i = 0; - int num; - int powers[36]; - concptr power_desc[36]; - bool flag, redraw; - char choice; - char out_val[160]; - int pet_ctr; - monster_type *m_ptr; - - PET_COMMAND_IDX mode = 0; - - char buf[160]; - char target_buf[160]; - - int menu_line = use_menu ? 1 : 0; - - num = 0; - - if(p_ptr->wild_mode) return; - - power_desc[num] = _("ペットを放す", "dismiss pets"); - powers[num++] = PET_DISMISS; - -#ifdef JP - sprintf(target_buf, "ペットのターゲットを指定 (現在:%s)", - (pet_t_m_idx ? (p_ptr->image ? "何か奇妙な物" : (r_name + r_info[current_floor_ptr->m_list[pet_t_m_idx].ap_r_idx].name)) : "指定なし")); -#else - sprintf(target_buf, "specify a target of pet (now:%s)", - (pet_t_m_idx ? (p_ptr->image ? "something strange" : (r_name + r_info[current_floor_ptr->m_list[pet_t_m_idx].ap_r_idx].name)) : "nothing")); -#endif - power_desc[num] = target_buf; - powers[num++] = PET_TARGET; - power_desc[num] = _("近くにいろ", "stay close"); - - if (p_ptr->pet_follow_distance == PET_CLOSE_DIST) mode = num; - powers[num++] = PET_STAY_CLOSE; - power_desc[num] = _("ついて来い", "follow me"); - - if (p_ptr->pet_follow_distance == PET_FOLLOW_DIST) mode = num; - powers[num++] = PET_FOLLOW_ME; - power_desc[num] = _("敵を見つけて倒せ", "seek and destroy"); - - if (p_ptr->pet_follow_distance == PET_DESTROY_DIST) mode = num; - powers[num++] = PET_SEEK_AND_DESTROY; - power_desc[num] = _("少し離れていろ", "give me space"); - - if (p_ptr->pet_follow_distance == PET_SPACE_DIST) mode = num; - powers[num++] = PET_ALLOW_SPACE; - power_desc[num] = _("離れていろ", "stay away"); - - if (p_ptr->pet_follow_distance == PET_AWAY_DIST) mode = num; - powers[num++] = PET_STAY_AWAY; - - if (p_ptr->pet_extra_flags & PF_OPEN_DOORS) - { - power_desc[num] = _("ドアを開ける (現在:ON)", "pets open doors (now On)"); - } - else - { - power_desc[num] = _("ドアを開ける (現在:OFF)", "pets open doors (now Off)"); - } - powers[num++] = PET_OPEN_DOORS; - - if (p_ptr->pet_extra_flags & PF_PICKUP_ITEMS) - { - power_desc[num] = _("アイテムを拾う (現在:ON)", "pets pick up items (now On)"); - } - else - { - power_desc[num] = _("アイテムを拾う (現在:OFF)", "pets pick up items (now Off)"); - } - powers[num++] = PET_TAKE_ITEMS; - - if (p_ptr->pet_extra_flags & PF_TELEPORT) - { - power_desc[num] = _("テレポート系魔法を使う (現在:ON)", "allow teleport (now On)"); - } - else - { - power_desc[num] = _("テレポート系魔法を使う (現在:OFF)", "allow teleport (now Off)"); - } - powers[num++] = PET_TELEPORT; - - if (p_ptr->pet_extra_flags & PF_ATTACK_SPELL) - { - power_desc[num] = _("攻撃魔法を使う (現在:ON)", "allow cast attack spell (now On)"); - } - else - { - power_desc[num] = _("攻撃魔法を使う (現在:OFF)", "allow cast attack spell (now Off)"); - } - powers[num++] = PET_ATTACK_SPELL; - - if (p_ptr->pet_extra_flags & PF_SUMMON_SPELL) - { - power_desc[num] = _("召喚魔法を使う (現在:ON)", "allow cast summon spell (now On)"); - } - else - { - power_desc[num] = _("召喚魔法を使う (現在:OFF)", "allow cast summon spell (now Off)"); - } - powers[num++] = PET_SUMMON_SPELL; - - if (p_ptr->pet_extra_flags & PF_BALL_SPELL) - { - power_desc[num] = _("プレイヤーを巻き込む範囲魔法を使う (現在:ON)", "allow involve player in area spell (now On)"); - } - else - { - power_desc[num] = _("プレイヤーを巻き込む範囲魔法を使う (現在:OFF)", "allow involve player in area spell (now Off)"); - } - powers[num++] = PET_BALL_SPELL; - - if (p_ptr->riding) - { - power_desc[num] = _("ペットから降りる", "get off a pet"); - } - else - { - power_desc[num] = _("ペットに乗る", "ride a pet"); - } - powers[num++] = PET_RIDING; - power_desc[num] = _("ペットに名前をつける", "name pets"); - powers[num++] = PET_NAME; - - if (p_ptr->riding) - { - if ((p_ptr->migite && (empty_hands(FALSE) == EMPTY_HAND_LARM) && - object_allow_two_hands_wielding(&inventory[INVEN_RARM])) || - (p_ptr->hidarite && (empty_hands(FALSE) == EMPTY_HAND_RARM) && - object_allow_two_hands_wielding(&inventory[INVEN_LARM]))) - { - if (p_ptr->pet_extra_flags & PF_RYOUTE) - { - power_desc[num] = _("武器を片手で持つ", "use one hand to control a riding pet"); - } - else - { - power_desc[num] = _("武器を両手で持つ", "use both hands for a weapon"); - } - - powers[num++] = PET_RYOUTE; - } - else - { - switch (p_ptr->pclass) - { - case CLASS_MONK: - case CLASS_FORCETRAINER: - case CLASS_BERSERKER: - if (empty_hands(FALSE) == (EMPTY_HAND_RARM | EMPTY_HAND_LARM)) - { - if (p_ptr->pet_extra_flags & PF_RYOUTE) - { - power_desc[num] = _("片手で格闘する", "use one hand to control a riding pet"); - } - else - { - power_desc[num] = _("両手で格闘する", "use both hands for melee"); - } - - powers[num++] = PET_RYOUTE; - } - else if ((empty_hands(FALSE) != EMPTY_HAND_NONE) && !has_melee_weapon(INVEN_RARM) && !has_melee_weapon(INVEN_LARM)) - { - if (p_ptr->pet_extra_flags & PF_RYOUTE) - { - power_desc[num] = _("格闘を行わない", "use one hand to control a riding pet"); - } - else - { - power_desc[num] = _("格闘を行う", "use one hand for melee"); - } - - powers[num++] = PET_RYOUTE; - } - break; - } - } - } - - if (!(repeat_pull(&i) && (i >= 0) && (i < num))) - { - /* Nothing chosen yet */ - flag = FALSE; - - /* No redraw yet */ - redraw = FALSE; - - if (use_menu) - { - screen_save(); - - /* Build a prompt */ - strnfmt(out_val, 78, _("(コマンド、ESC=終了) コマンドを選んでください:", "(Command, ESC=exit) Choose command from menu.")); - } - else - { - /* Build a prompt */ - strnfmt(out_val, 78, - _("(コマンド %c-%c、'*'=一覧、ESC=終了) コマンドを選んでください:", "(Command %c-%c, *=List, ESC=exit) Select a command: "), - I2A(0), I2A(num - 1)); - } - - choice = (always_show_list || use_menu) ? ESCAPE : 1; - - /* Get a command from the user */ - while (!flag) - { - int ask = TRUE; - - if (choice == ESCAPE) choice = ' '; - else if (!get_com(out_val, &choice, TRUE)) break; - - if (use_menu && (choice != ' ')) - { - switch (choice) - { - case '0': - screen_load(); - return; - - case '8': - case 'k': - case 'K': - menu_line += (num - 1); - break; - - case '2': - case 'j': - case 'J': - menu_line++; - break; - - case '4': - case 'h': - case 'H': - menu_line = 1; - break; - - case '6': - case 'l': - case 'L': - menu_line = num; - break; - - case 'x': - case 'X': - case '\r': - case '\n': - i = menu_line - 1; - ask = FALSE; - break; - } - if (menu_line > num) menu_line -= num; - } - - /* Request redraw */ - if ((choice == ' ') || (choice == '*') || (choice == '?') || (use_menu && ask)) - { - /* Show the list */ - if (!redraw || use_menu) - { - byte y = 1, x = 0; - PET_COMMAND_IDX ctr = 0; - redraw = TRUE; - if (!use_menu) screen_save(); - - prt("", y++, x); - - /* Print list */ - for (ctr = 0; ctr < num; ctr++) - { - /* Letter/number for power selection */ - if (use_menu) - sprintf(buf, "%c%s ", (ctr == mode) ? '*' : ' ', (ctr == (menu_line - 1)) ? _("》", "> ") : " "); - else - sprintf(buf, "%c%c) ", (ctr == mode) ? '*' : ' ', I2A(ctr)); - - strcat(buf, power_desc[ctr]); - - prt(buf, y + ctr, x); - } - - prt("", y + MIN(ctr, 17), x); - } - - /* Hide the list */ - else - { - /* Hide list */ - redraw = FALSE; - screen_load(); - } - - /* Redo asking */ - continue; - } - - if (!use_menu) - { - /* Note verify */ - ask = (isupper(choice)); - - /* Lowercase */ - if (ask) choice = (char)tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - } - - /* Totally Illegal */ - if ((i < 0) || (i >= num)) - { - bell(); - continue; - } - - /* Verify it */ - if (ask) - { - /* Prompt */ - strnfmt(buf, 78, _("%sを使いますか? ", "Use %s? "), power_desc[i]); - - /* Belay that order */ - if (!get_check(buf)) continue; - } - - /* Stop the loop */ - flag = TRUE; - } - if (redraw) screen_load(); - - /* Abort if needed */ - if (!flag) - { - free_turn(p_ptr); - return; - } - - repeat_push(i); - } - switch (powers[i]) - { - case PET_DISMISS: /* Dismiss pets */ - { - /* Check pets (backwards) */ - for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) - { - /* Player has pet */ - if (is_pet(¤t_floor_ptr->m_list[pet_ctr])) break; - } - - if (!pet_ctr) - { - msg_print(_("ペットがいない!", "You have no pets!")); - break; - } - do_cmd_pet_dismiss(); - (void)calculate_upkeep(); - break; - } - case PET_TARGET: - { - project_length = -1; - if (!target_set(TARGET_KILL)) pet_t_m_idx = 0; - else - { - grid_type *g_ptr = ¤t_floor_ptr->grid_array[target_row][target_col]; - if (g_ptr->m_idx && (current_floor_ptr->m_list[g_ptr->m_idx].ml)) - { - pet_t_m_idx = current_floor_ptr->grid_array[target_row][target_col].m_idx; - p_ptr->pet_follow_distance = PET_DESTROY_DIST; - } - else pet_t_m_idx = 0; - } - project_length = 0; - - break; - } - /* Call pets */ - case PET_STAY_CLOSE: - { - p_ptr->pet_follow_distance = PET_CLOSE_DIST; - pet_t_m_idx = 0; - break; - } - /* "Follow Me" */ - case PET_FOLLOW_ME: - { - p_ptr->pet_follow_distance = PET_FOLLOW_DIST; - pet_t_m_idx = 0; - break; - } - /* "Seek and destoy" */ - case PET_SEEK_AND_DESTROY: - { - p_ptr->pet_follow_distance = PET_DESTROY_DIST; - break; - } - /* "Give me space" */ - case PET_ALLOW_SPACE: - { - p_ptr->pet_follow_distance = PET_SPACE_DIST; - break; - } - /* "Stay away" */ - case PET_STAY_AWAY: - { - p_ptr->pet_follow_distance = PET_AWAY_DIST; - break; - } - /* flag - allow pets to open doors */ - case PET_OPEN_DOORS: - { - if (p_ptr->pet_extra_flags & PF_OPEN_DOORS) p_ptr->pet_extra_flags &= ~(PF_OPEN_DOORS); - else p_ptr->pet_extra_flags |= (PF_OPEN_DOORS); - break; - } - /* flag - allow pets to pickup items */ - case PET_TAKE_ITEMS: - { - if (p_ptr->pet_extra_flags & PF_PICKUP_ITEMS) - { - p_ptr->pet_extra_flags &= ~(PF_PICKUP_ITEMS); - for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) - { - /* Access the monster */ - m_ptr = ¤t_floor_ptr->m_list[pet_ctr]; - - if (is_pet(m_ptr)) - { - monster_drop_carried_objects(m_ptr); - } - } - } - else p_ptr->pet_extra_flags |= (PF_PICKUP_ITEMS); - - break; - } - /* flag - allow pets to teleport */ - case PET_TELEPORT: - { - if (p_ptr->pet_extra_flags & PF_TELEPORT) p_ptr->pet_extra_flags &= ~(PF_TELEPORT); - else p_ptr->pet_extra_flags |= (PF_TELEPORT); - break; - } - /* flag - allow pets to cast attack spell */ - case PET_ATTACK_SPELL: - { - if (p_ptr->pet_extra_flags & PF_ATTACK_SPELL) p_ptr->pet_extra_flags &= ~(PF_ATTACK_SPELL); - else p_ptr->pet_extra_flags |= (PF_ATTACK_SPELL); - break; - } - /* flag - allow pets to cast attack spell */ - case PET_SUMMON_SPELL: - { - if (p_ptr->pet_extra_flags & PF_SUMMON_SPELL) p_ptr->pet_extra_flags &= ~(PF_SUMMON_SPELL); - else p_ptr->pet_extra_flags |= (PF_SUMMON_SPELL); - break; - } - /* flag - allow pets to cast attack spell */ - case PET_BALL_SPELL: - { - if (p_ptr->pet_extra_flags & PF_BALL_SPELL) p_ptr->pet_extra_flags &= ~(PF_BALL_SPELL); - else p_ptr->pet_extra_flags |= (PF_BALL_SPELL); - break; - } - - case PET_RIDING: - { - (void)do_riding(FALSE); - break; - } - - case PET_NAME: - { - do_name_pet(); - break; - } - - case PET_RYOUTE: - { - if (p_ptr->pet_extra_flags & PF_RYOUTE) p_ptr->pet_extra_flags &= ~(PF_RYOUTE); - else p_ptr->pet_extra_flags |= (PF_RYOUTE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - break; - } - } -} - - -/*! -* @brief プレイヤーの落馬判定処理 -* @param dam 落馬判定を発した際に受けたダメージ量 -* @param force TRUEならば強制的に落馬する -* @return 実際に落馬したらTRUEを返す -*/ -bool rakuba(HIT_POINT dam, bool force) -{ - int i, y, x, oy, ox; - int sn = 0, sy = 0, sx = 0; - GAME_TEXT m_name[MAX_NLEN]; - monster_type *m_ptr = ¤t_floor_ptr->m_list[p_ptr->riding]; - monster_race *r_ptr = &r_info[m_ptr->r_idx]; - bool fall_dam = FALSE; - - if (!p_ptr->riding) return FALSE; - if (p_ptr->wild_mode) return FALSE; - - if (dam >= 0 || force) - { - if (!force) - { - int cur = p_ptr->skill_exp[GINOU_RIDING]; - int max = s_info[p_ptr->pclass].s_max[GINOU_RIDING]; - int ridinglevel = r_ptr->level; - - /* 落馬のしやすさ */ - int rakubalevel = r_ptr->level; - if (p_ptr->riding_ryoute) rakubalevel += 20; - - if ((cur < max) && (max > 1000) && - (dam / 2 + ridinglevel) > (cur / 30 + 10)) - { - int inc = 0; - - if (ridinglevel > (cur / 100 + 15)) - inc += 1 + (ridinglevel - cur / 100 - 15); - else - inc += 1; - - p_ptr->skill_exp[GINOU_RIDING] = MIN(max, cur + inc); - } - - /* レベルの低い乗馬からは落馬しにくい */ - if (randint0(dam / 2 + rakubalevel * 2) < cur / 30 + 10) - { - if ((((p_ptr->pclass == CLASS_BEASTMASTER) || (p_ptr->pclass == CLASS_CAVALRY)) && !p_ptr->riding_ryoute) || !one_in_(p_ptr->lev*(p_ptr->riding_ryoute ? 2 : 3) + 30)) - { - return FALSE; - } - } - } - - /* Check around the player */ - for (i = 0; i < 8; i++) - { - grid_type *g_ptr; - - y = p_ptr->y + ddy_ddd[i]; - x = p_ptr->x + ddx_ddd[i]; - - g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - if (g_ptr->m_idx) continue; - - /* Skip non-empty grids */ - if (!cave_have_flag_grid(g_ptr, FF_MOVE) && !cave_have_flag_grid(g_ptr, FF_CAN_FLY)) - { - if (!player_can_ride_aux(g_ptr, FALSE)) continue; - } - - if (cave_have_flag_grid(g_ptr, FF_PATTERN)) continue; - - /* Count "safe" grids */ - sn++; - - /* Randomize choice */ - if (randint0(sn) > 0) continue; - - /* Save the safe location */ - sy = y; sx = x; - } - if (!sn) - { - monster_desc(m_name, m_ptr, 0); - msg_format(_("%sから振り落とされそうになって、壁にぶつかった。", "You have nearly fallen from %s, but bumped into wall."), m_name); - take_hit(DAMAGE_NOESCAPE, r_ptr->level + 3, _("壁への衝突", "bumping into wall"), -1); - return FALSE; - } - - oy = p_ptr->y; - ox = p_ptr->x; - - p_ptr->y = sy; - p_ptr->x = sx; - - /* Redraw the old spot */ - lite_spot(oy, ox); - - /* Redraw the new spot */ - lite_spot(p_ptr->y, p_ptr->x); - - /* Check for new panel */ - verify_panel(); - } - - p_ptr->riding = 0; - p_ptr->pet_extra_flags &= ~(PF_RYOUTE); - p_ptr->riding_ryoute = p_ptr->old_riding_ryoute = FALSE; - - p_ptr->update |= (PU_BONUS | PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE | PU_MONSTERS); - handle_stuff(); - - - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); - p_ptr->redraw |= (PR_EXTRA); - - /* Update health track of mount */ - p_ptr->redraw |= (PR_UHEALTH); - - if (p_ptr->levitation && !force) - { - monster_desc(m_name, m_ptr, 0); - msg_format(_("%sから落ちたが、空中でうまく体勢を立て直して着地した。", "You are thrown from %s, but make a good landing."), m_name); - } - else - { - take_hit(DAMAGE_NOESCAPE, r_ptr->level + 3, _("落馬", "Falling from riding"), -1); - fall_dam = TRUE; - } - - if (sy && !p_ptr->is_dead) - (void)move_player_effect(p_ptr->y, p_ptr->x, MPE_DONT_PICKUP | MPE_DONT_SWAP_MON); - - return fall_dam; -} - diff --git a/src/cmd-pet.h b/src/cmd-pet.h deleted file mode 100644 index aa750314d..000000000 --- a/src/cmd-pet.h +++ /dev/null @@ -1,8 +0,0 @@ -extern bool do_riding(bool force); -extern PERCENTAGE calculate_upkeep(void); -extern void do_cmd_pet_dismiss(void); -extern void do_cmd_pet(void); -extern bool player_can_ride_aux(grid_type *g_ptr, bool now_riding); -extern bool rakuba(HIT_POINT dam, bool force); - - diff --git a/src/cmd-quaff.c b/src/cmd-quaff.c deleted file mode 100644 index 45953a281..000000000 --- a/src/cmd-quaff.c +++ /dev/null @@ -1,615 +0,0 @@ -/*! - * @file cmd-quaff.c - * @brief プレイヤーの飲むコマンド実装 - * @date 2018/09/07 - * @details - * cmd6.cより分離。 - */ - -#include "angband.h" -#include "selfinfo.h" -#include "object-hook.h" -#include "mutation.h" -#include "avatar.h" -#include "spells-status.h" -#include "player-status.h" -#include "realm-hex.h" -#include "spells-floor.h" -#include "object-broken.h" - -/*! - * @brief 薬を飲むコマンドのサブルーチン / - * Quaff a potion (from the pack or the floor) - * @param item 飲む薬オブジェクトの所持品ID - * @return なし - */ -void do_cmd_quaff_potion_aux(INVENTORY_IDX item) -{ - bool ident; - DEPTH lev; - object_type *o_ptr; - object_type forge; - object_type *q_ptr; - - take_turn(p_ptr, 100); - - if (p_ptr->timewalk) - { - if (flush_failure) flush(); - msg_print(_("瓶から水が流れ出てこない!", "The potion doesn't flow out from a bottle.")); - - sound(SOUND_FAIL); - return; - } - - if (music_singing_any()) stop_singing(p_ptr); - if (hex_spelling_any()) - { - if (!hex_spelling(HEX_INHAIL)) stop_hex_spell_all(); - } - - /* Get the item (in the pack) */ - if (item >= 0) - { - o_ptr = &inventory[item]; - } - - /* Get the item (on the floor) */ - else - { - o_ptr = ¤t_floor_ptr->o_list[0 - item]; - } - q_ptr = &forge; - - /* Obtain a local object */ - object_copy(q_ptr, o_ptr); - - /* Single object */ - q_ptr->number = 1; - - /* Reduce and describe inventory */ - if (item >= 0) - { - inven_item_increase(item, -1); - inven_item_describe(item); - inven_item_optimize(item); - } - - /* Reduce and describe floor item */ - else - { - floor_item_increase(0 - item, -1); - floor_item_describe(0 - item); - floor_item_optimize(0 - item); - } - - sound(SOUND_QUAFF); - - - /* Not identified yet */ - ident = FALSE; - - /* Object level */ - lev = k_info[q_ptr->k_idx].level; - - /* Analyze the potion */ - if (q_ptr->tval == TV_POTION) - { - switch (q_ptr->sval) - { - /* 飲みごたえをオリジナルより細かく表現 */ - case SV_POTION_WATER: - msg_print(_("口の中がさっぱりした。", "")); - msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty.")); - ident = TRUE; - break; - - case SV_POTION_APPLE_JUICE: - msg_print(_("甘くてサッパリとしていて、とてもおいしい。", "")); - msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty.")); - ident = TRUE; - break; - - case SV_POTION_SLIME_MOLD: - msg_print(_("なんとも不気味な味だ。", "")); - msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty.")); - ident = TRUE; - break; - - case SV_POTION_SLOWNESS: - if (set_slow(randint1(25) + 15, FALSE)) ident = TRUE; - break; - - case SV_POTION_SALT_WATER: - msg_print(_("うぇ!思わず吐いてしまった。", "The potion makes you vomit!")); - - if (!(prace_is_(RACE_GOLEM) || - prace_is_(RACE_ZOMBIE) || - prace_is_(RACE_DEMON) || - prace_is_(RACE_ANDROID) || - prace_is_(RACE_SPECTRE) || - (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING))) - { - /* Only living creatures get thirsty */ - (void)set_food(PY_FOOD_STARVE - 1); - } - - (void)set_poisoned(0); - (void)set_paralyzed(p_ptr->paralyzed + 4); - ident = TRUE; - break; - - case SV_POTION_POISON: - if (!(p_ptr->resist_pois || IS_OPPOSE_POIS())) - { - if (set_poisoned(p_ptr->poisoned + randint0(15) + 10)) - { - ident = TRUE; - } - } - break; - - case SV_POTION_BLINDNESS: - if (!p_ptr->resist_blind) - { - if (set_blind(p_ptr->blind + randint0(100) + 100)) - { - ident = TRUE; - } - } - break; - - case SV_POTION_BOOZE: - ident = booze(p_ptr); - break; - - case SV_POTION_SLEEP: - if (!p_ptr->free_act) - { - msg_print(_("あなたは眠ってしまった。", "You fall asleep.")); - - if (ironman_nightmare) - { - msg_print(_("恐ろしい光景が頭に浮かんできた。", "A horrible vision enters your mind.")); - - /* Have some nightmares */ - sanity_blast(NULL, FALSE); - } - if (set_paralyzed(p_ptr->paralyzed + randint0(4) + 4)) - { - ident = TRUE; - } - } - break; - - case SV_POTION_LOSE_MEMORIES: - if (!p_ptr->hold_exp && (p_ptr->exp > 0)) - { - msg_print(_("過去の記憶が薄れていく気がする。", "You feel your memories fade.")); - chg_virtue(V_KNOWLEDGE, -5); - - lose_exp(p_ptr->exp / 4); - ident = TRUE; - } - break; - - case SV_POTION_RUINATION: - msg_print(_("身も心も弱ってきて、精気が抜けていくようだ。", "Your nerves and muscles feel weak and lifeless!")); - take_hit(DAMAGE_LOSELIFE, damroll(10, 10), _("破滅の薬", "a potion of Ruination"), -1); - - (void)dec_stat(A_DEX, 25, TRUE); - (void)dec_stat(A_WIS, 25, TRUE); - (void)dec_stat(A_CON, 25, TRUE); - (void)dec_stat(A_STR, 25, TRUE); - (void)dec_stat(A_CHR, 25, TRUE); - (void)dec_stat(A_INT, 25, TRUE); - ident = TRUE; - break; - - case SV_POTION_DEC_STR: - if (do_dec_stat(A_STR)) ident = TRUE; - break; - - case SV_POTION_DEC_INT: - if (do_dec_stat(A_INT)) ident = TRUE; - break; - - case SV_POTION_DEC_WIS: - if (do_dec_stat(A_WIS)) ident = TRUE; - break; - - case SV_POTION_DEC_DEX: - if (do_dec_stat(A_DEX)) ident = TRUE; - break; - - case SV_POTION_DEC_CON: - if (do_dec_stat(A_CON)) ident = TRUE; - break; - - case SV_POTION_DEC_CHR: - if (do_dec_stat(A_CHR)) ident = TRUE; - break; - - case SV_POTION_DETONATIONS: - ident = detonation(p_ptr); - break; - - case SV_POTION_DEATH: - chg_virtue(V_VITALITY, -1); - chg_virtue(V_UNLIFE, 5); - msg_print(_("死の予感が体中を駆けめぐった。", "A feeling of Death flows through your body.")); - take_hit(DAMAGE_LOSELIFE, 5000, _("死の薬", "a potion of Death"), -1); - ident = TRUE; - break; - - case SV_POTION_INFRAVISION: - if (set_tim_infra(p_ptr->tim_infra + 100 + randint1(100), FALSE)) - { - ident = TRUE; - } - break; - - case SV_POTION_DETECT_INVIS: - if (set_tim_invis(p_ptr->tim_invis + 12 + randint1(12), FALSE)) - { - ident = TRUE; - } - break; - - case SV_POTION_SLOW_POISON: - if (set_poisoned(p_ptr->poisoned / 2)) ident = TRUE; - break; - - case SV_POTION_CURE_POISON: - if (set_poisoned(0)) ident = TRUE; - break; - - case SV_POTION_BOLDNESS: - if (set_afraid(0)) ident = TRUE; - break; - - case SV_POTION_SPEED: - if (!p_ptr->fast) - { - if (set_fast(randint1(25) + 15, FALSE)) ident = TRUE; - } - else - { - (void)set_fast(p_ptr->fast + 5, FALSE); - } - break; - - case SV_POTION_RESIST_HEAT: - if (set_oppose_fire(p_ptr->oppose_fire + randint1(10) + 10, FALSE)) - { - ident = TRUE; - } - break; - - case SV_POTION_RESIST_COLD: - if (set_oppose_cold(p_ptr->oppose_cold + randint1(10) + 10, FALSE)) - { - ident = TRUE; - } - break; - - case SV_POTION_HEROISM: - ident = heroism(25); - break; - - case SV_POTION_BESERK_STRENGTH: - ident = berserk(randint1(25) + 25); - break; - - case SV_POTION_CURE_LIGHT: - ident = cure_light_wounds(2, 8); - break; - - case SV_POTION_CURE_SERIOUS: - ident = cure_serious_wounds(4, 8); - break; - - case SV_POTION_CURE_CRITICAL: - ident = cure_critical_wounds(damroll(6, 8)); - break; - - case SV_POTION_HEALING: - ident = cure_critical_wounds(300); - break; - - case SV_POTION_STAR_HEALING: - ident = cure_critical_wounds(1200); - break; - - case SV_POTION_LIFE: - ident = life_stream(TRUE, TRUE); - break; - - case SV_POTION_RESTORE_MANA: - ident = restore_mana(TRUE); - break; - - case SV_POTION_RESTORE_EXP: - if (restore_level()) ident = TRUE; - break; - - case SV_POTION_RES_STR: - if (do_res_stat(A_STR)) ident = TRUE; - break; - - case SV_POTION_RES_INT: - if (do_res_stat(A_INT)) ident = TRUE; - break; - - case SV_POTION_RES_WIS: - if (do_res_stat(A_WIS)) ident = TRUE; - break; - - case SV_POTION_RES_DEX: - if (do_res_stat(A_DEX)) ident = TRUE; - break; - - case SV_POTION_RES_CON: - if (do_res_stat(A_CON)) ident = TRUE; - break; - - case SV_POTION_RES_CHR: - if (do_res_stat(A_CHR)) ident = TRUE; - break; - - case SV_POTION_INC_STR: - if (do_inc_stat(A_STR)) ident = TRUE; - break; - - case SV_POTION_INC_INT: - if (do_inc_stat(A_INT)) ident = TRUE; - break; - - case SV_POTION_INC_WIS: - if (do_inc_stat(A_WIS)) ident = TRUE; - break; - - case SV_POTION_INC_DEX: - if (do_inc_stat(A_DEX)) ident = TRUE; - break; - - case SV_POTION_INC_CON: - if (do_inc_stat(A_CON)) ident = TRUE; - break; - - case SV_POTION_INC_CHR: - if (do_inc_stat(A_CHR)) ident = TRUE; - break; - - case SV_POTION_AUGMENTATION: - if (do_inc_stat(A_STR)) ident = TRUE; - if (do_inc_stat(A_INT)) ident = TRUE; - if (do_inc_stat(A_WIS)) ident = TRUE; - if (do_inc_stat(A_DEX)) ident = TRUE; - if (do_inc_stat(A_CON)) ident = TRUE; - if (do_inc_stat(A_CHR)) ident = TRUE; - break; - - case SV_POTION_ENLIGHTENMENT: - msg_print(_("自分の置かれている状況が脳裏に浮かんできた...", "An image of your surroundings forms in your mind...")); - chg_virtue(V_KNOWLEDGE, 1); - chg_virtue(V_ENLIGHTEN, 1); - wiz_lite(FALSE); - ident = TRUE; - break; - - case SV_POTION_STAR_ENLIGHTENMENT: - msg_print(_("更なる啓蒙を感じた...", "You begin to feel more enlightened...")); - chg_virtue(V_KNOWLEDGE, 1); - chg_virtue(V_ENLIGHTEN, 2); - msg_print(NULL); - wiz_lite(FALSE); - (void)do_inc_stat(A_INT); - (void)do_inc_stat(A_WIS); - (void)detect_traps(DETECT_RAD_DEFAULT, TRUE); - (void)detect_doors(DETECT_RAD_DEFAULT); - (void)detect_stairs(DETECT_RAD_DEFAULT); - (void)detect_treasure(DETECT_RAD_DEFAULT); - (void)detect_objects_gold(DETECT_RAD_DEFAULT); - (void)detect_objects_normal(DETECT_RAD_DEFAULT); - identify_pack(); - self_knowledge(); - ident = TRUE; - break; - - case SV_POTION_SELF_KNOWLEDGE: - msg_print(_("自分自身のことが少しは分かった気がする...", "You begin to know yourself a little better...")); - msg_print(NULL); - self_knowledge(); - ident = TRUE; - break; - - case SV_POTION_EXPERIENCE: - if (p_ptr->prace == RACE_ANDROID) break; - chg_virtue(V_ENLIGHTEN, 1); - if (p_ptr->exp < PY_MAX_EXP) - { - EXP ee = (p_ptr->exp / 2) + 10; - if (ee > 100000L) ee = 100000L; - msg_print(_("更に経験を積んだような気がする。", "You feel more experienced.")); - gain_exp(ee); - ident = TRUE; - } - break; - - case SV_POTION_RESISTANCE: - (void)set_oppose_acid(p_ptr->oppose_acid + randint1(20) + 20, FALSE); - (void)set_oppose_elec(p_ptr->oppose_elec + randint1(20) + 20, FALSE); - (void)set_oppose_fire(p_ptr->oppose_fire + randint1(20) + 20, FALSE); - (void)set_oppose_cold(p_ptr->oppose_cold + randint1(20) + 20, FALSE); - (void)set_oppose_pois(p_ptr->oppose_pois + randint1(20) + 20, FALSE); - ident = TRUE; - break; - - case SV_POTION_CURING: - if (true_healing(50)) ident = TRUE; - break; - - case SV_POTION_INVULNERABILITY: - (void)set_invuln(p_ptr->invuln + randint1(4) + 4, FALSE); - ident = TRUE; - break; - - case SV_POTION_NEW_LIFE: - roll_hitdice(p_ptr, 0L); - get_max_stats(); - p_ptr->update |= PU_BONUS; - lose_all_mutations(); - ident = TRUE; - break; - - case SV_POTION_NEO_TSUYOSHI: - (void)set_image(0); - (void)set_tsuyoshi(p_ptr->tsuyoshi + randint1(100) + 100, FALSE); - ident = TRUE; - break; - - case SV_POTION_TSUYOSHI: - msg_print(_("「オクレ兄さん!」", "Brother OKURE!")); - msg_print(NULL); - p_ptr->tsuyoshi = 1; - (void)set_tsuyoshi(0, TRUE); - if (!p_ptr->resist_chaos) - { - (void)set_image(50 + randint1(50)); - } - ident = TRUE; - break; - - case SV_POTION_POLYMORPH: - if ((p_ptr->muta1 || p_ptr->muta2 || p_ptr->muta3) && one_in_(23)) - { - lose_all_mutations(); - } - else - { - do - { - if (one_in_(2)) - { - if(gain_mutation(p_ptr, 0)) ident = TRUE; - } - else if (lose_mutation(0)) ident = TRUE; - } while(!ident || one_in_(2)); - } - break; - } - } - - if (prace_is_(RACE_SKELETON)) - { - msg_print(_("液体の一部はあなたのアゴを素通りして落ちた!", "Some of the fluid falls through your jaws!")); - (void)potion_smash_effect(0, p_ptr->y, p_ptr->x, q_ptr->k_idx); - } - p_ptr->update |= (PU_COMBINE | PU_REORDER); - - if (!(object_is_aware(q_ptr))) - { - chg_virtue(V_PATIENCE, -1); - chg_virtue(V_CHANCE, 1); - chg_virtue(V_KNOWLEDGE, -1); - } - - /* The item has been tried */ - object_tried(q_ptr); - - /* An identification was made */ - if (ident && !object_is_aware(q_ptr)) - { - object_aware(q_ptr); - gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); - } - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - /* Potions can feed the player */ - switch (p_ptr->mimic_form) - { - case MIMIC_NONE: - switch (p_ptr->prace) - { - case RACE_VAMPIRE: - (void)set_food(p_ptr->food + (q_ptr->pval / 10)); - break; - case RACE_SKELETON: - /* Do nothing */ - break; - case RACE_GOLEM: - case RACE_ZOMBIE: - case RACE_DEMON: - case RACE_SPECTRE: - set_food(p_ptr->food + ((q_ptr->pval) / 20)); - break; - case RACE_ANDROID: - if (q_ptr->tval == TV_FLASK) - { - msg_print(_("オイルを補給した。", "You replenish yourself with the oil.")); - set_food(p_ptr->food + 5000); - } - else - { - set_food(p_ptr->food + ((q_ptr->pval) / 20)); - } - break; - case RACE_ENT: - msg_print(_("水分を取り込んだ。", "You are moistened.")); - set_food(MIN(p_ptr->food + q_ptr->pval + MAX(0, q_ptr->pval * 10) + 2000, PY_FOOD_MAX - 1)); - break; - default: - (void)set_food(p_ptr->food + q_ptr->pval); - break; - } - break; - case MIMIC_DEMON: - case MIMIC_DEMON_LORD: - set_food(p_ptr->food + ((q_ptr->pval) / 20)); - break; - case MIMIC_VAMPIRE: - (void)set_food(p_ptr->food + (q_ptr->pval / 10)); - break; - default: - (void)set_food(p_ptr->food + q_ptr->pval); - break; - } -} - - - -/*! - * @brief 薬を飲むコマンドのメインルーチン / - * Quaff some potion (from the pack or floor) - * @return なし - */ -void do_cmd_quaff_potion(void) -{ - OBJECT_IDX item; - concptr q, s; - - if (p_ptr->wild_mode) - { - return; - } - - if (cmd_limit_arena(p_ptr)) return; - - if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) - { - set_action(ACTION_NONE); - } - - /* Restrict choices to potions */ - item_tester_hook = item_tester_hook_quaff; - - q = _("どの薬を飲みますか? ", "Quaff which potion? "); - s = _("飲める薬がない。", "You have no potions to quaff."); - - if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Quaff the potion */ - do_cmd_quaff_potion_aux(item); -} diff --git a/src/cmd-quaff.h b/src/cmd-quaff.h deleted file mode 100644 index b797d93d3..000000000 --- a/src/cmd-quaff.h +++ /dev/null @@ -1,4 +0,0 @@ - -extern void do_cmd_quaff_potion(void); -extern void do_cmd_quaff_potion_aux(INVENTORY_IDX item); - diff --git a/src/cmd-read.c b/src/cmd-read.c deleted file mode 100644 index 91c70a5e5..000000000 --- a/src/cmd-read.c +++ /dev/null @@ -1,640 +0,0 @@ -/*! - * @file cmd-read.c - * @brief プレイヤーの読むコマンド実装 - * @date 2018/09/07 - * @details - * cmd6.cより分離。 - */ - -#include "angband.h" -#include "object-hook.h" -#include "artifact.h" -#include "avatar.h" -#include "player-status.h" -#include "rumor.h" -#include "realm-hex.h" - -#include "spells-object.h" -#include "spells-floor.h" -#include "spells-summon.h" -#include "spells-status.h" - -/*! - * @brief 巻物を読むコマンドのサブルーチン - * Read a scroll (from the pack or floor). - * @param item 読むオブジェクトの所持品ID - * @param known 判明済ならばTRUE - * @return なし - * @details - *
- * Certain scrolls can be "aborted" without losing the scroll.  These
- * include scrolls with no effects but recharge or identify, which are
- * cancelled before use.  XXX Reading them still takes a current_world_ptr->game_turn, though.
- * 
- */ -void do_cmd_read_scroll_aux(INVENTORY_IDX item, bool known) -{ - int k, used_up, ident, lev; - object_type *o_ptr; - - - /* Get the item (in the pack) */ - if (item >= 0) - { - o_ptr = &inventory[item]; - } - - /* Get the item (on the floor) */ - else - { - o_ptr = ¤t_floor_ptr->o_list[0 - item]; - } - - take_turn(p_ptr, 100); - if (cmd_limit_time_walk(p_ptr)) return; - - if (p_ptr->pclass == CLASS_BERSERKER) - { - msg_print(_("巻物なんて読めない。", "You cannot read.")); - return; - } - - if (music_singing_any()) stop_singing(p_ptr); - - /* Hex */ - if (hex_spelling_any() && ((p_ptr->lev < 35) || hex_spell_fully())) stop_hex_spell_all(); - - /* Not identified yet */ - ident = FALSE; - - /* Object level */ - lev = k_info[o_ptr->k_idx].level; - - /* Assume the scroll will get used up */ - used_up = TRUE; - - if (o_ptr->tval == TV_SCROLL) - { - /* Analyze the scroll */ - switch (o_ptr->sval) - { - case SV_SCROLL_DARKNESS: - { - if (!(p_ptr->resist_blind) && !(p_ptr->resist_dark)) - { - (void)set_blind(p_ptr->blind + 3 + randint1(5)); - } - if (unlite_area(10, 3)) ident = TRUE; - break; - } - - case SV_SCROLL_AGGRAVATE_MONSTER: - { - msg_print(_("カン高くうなる様な音が辺りを覆った。", "There is a high pitched humming noise.")); - aggravate_monsters(0); - ident = TRUE; - break; - } - - case SV_SCROLL_CURSE_ARMOR: - { - if (curse_armor()) ident = TRUE; - break; - } - - case SV_SCROLL_CURSE_WEAPON: - { - k = 0; - if (has_melee_weapon(INVEN_RARM)) - { - k = INVEN_RARM; - if (has_melee_weapon(INVEN_LARM) && one_in_(2)) k = INVEN_LARM; - } - else if (has_melee_weapon(INVEN_LARM)) k = INVEN_LARM; - if (k && curse_weapon(FALSE, k)) ident = TRUE; - break; - } - - case SV_SCROLL_SUMMON_MONSTER: - { - for (k = 0; k < randint1(3); k++) - { - if (summon_specific(0, p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0')) - { - ident = TRUE; - } - } - break; - } - - case SV_SCROLL_SUMMON_UNDEAD: - { - for (k = 0; k < randint1(3); k++) - { - if (summon_specific(0, p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, SUMMON_UNDEAD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0')) - { - ident = TRUE; - } - } - break; - } - - case SV_SCROLL_SUMMON_PET: - { - if (summon_specific(-1, p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, 0, (PM_ALLOW_GROUP | PM_FORCE_PET), '\0')) - { - ident = TRUE; - } - break; - } - - case SV_SCROLL_SUMMON_KIN: - { - if (summon_kin_player(p_ptr->lev, p_ptr->y, p_ptr->x, (PM_FORCE_PET | PM_ALLOW_GROUP))) - { - ident = TRUE; - } - break; - } - - case SV_SCROLL_TRAP_CREATION: - { - if (trap_creation(p_ptr->y, p_ptr->x)) ident = TRUE; - break; - } - - case SV_SCROLL_PHASE_DOOR: - { - teleport_player(10, 0L); - ident = TRUE; - break; - } - - case SV_SCROLL_TELEPORT: - { - teleport_player(100, 0L); - ident = TRUE; - break; - } - - case SV_SCROLL_TELEPORT_LEVEL: - { - (void)teleport_level(0); - ident = TRUE; - break; - } - - case SV_SCROLL_WORD_OF_RECALL: - { - if (!recall_player(p_ptr, randint0(21) + 15)) used_up = FALSE; - ident = TRUE; - break; - } - - case SV_SCROLL_IDENTIFY: - { - if (!ident_spell(FALSE)) used_up = FALSE; - ident = TRUE; - break; - } - - case SV_SCROLL_STAR_IDENTIFY: - { - if (!identify_fully(FALSE)) used_up = FALSE; - ident = TRUE; - break; - } - - case SV_SCROLL_REMOVE_CURSE: - { - if (remove_curse()) - { - ident = TRUE; - } - break; - } - - case SV_SCROLL_STAR_REMOVE_CURSE: - { - if (remove_all_curse()) - { - ident = TRUE; - } - break; - } - - case SV_SCROLL_ENCHANT_ARMOR: - { - ident = TRUE; - if (!enchant_spell(0, 0, 1)) used_up = FALSE; - break; - } - - case SV_SCROLL_ENCHANT_WEAPON_TO_HIT: - { - if (!enchant_spell(1, 0, 0)) used_up = FALSE; - ident = TRUE; - break; - } - - case SV_SCROLL_ENCHANT_WEAPON_TO_DAM: - { - if (!enchant_spell(0, 1, 0)) used_up = FALSE; - ident = TRUE; - break; - } - - case SV_SCROLL_STAR_ENCHANT_ARMOR: - { - if (!enchant_spell(0, 0, randint1(3) + 2)) used_up = FALSE; - ident = TRUE; - break; - } - - case SV_SCROLL_STAR_ENCHANT_WEAPON: - { - if (!enchant_spell(randint1(3), randint1(3), 0)) used_up = FALSE; - ident = TRUE; - break; - } - - case SV_SCROLL_RECHARGING: - { - if (!recharge(130)) used_up = FALSE; - ident = TRUE; - break; - } - - case SV_SCROLL_MUNDANITY: - { - ident = TRUE; - if (!mundane_spell(FALSE)) used_up = FALSE; - break; - } - - case SV_SCROLL_LIGHT: - { - if (lite_area(damroll(2, 8), 2)) ident = TRUE; - break; - } - - case SV_SCROLL_MAPPING: - { - map_area(DETECT_RAD_MAP); - ident = TRUE; - break; - } - - case SV_SCROLL_DETECT_GOLD: - { - if (detect_treasure(DETECT_RAD_DEFAULT)) ident = TRUE; - if (detect_objects_gold(DETECT_RAD_DEFAULT)) ident = TRUE; - break; - } - - case SV_SCROLL_DETECT_ITEM: - { - if (detect_objects_normal(DETECT_RAD_DEFAULT)) ident = TRUE; - break; - } - - case SV_SCROLL_DETECT_TRAP: - { - if (detect_traps(DETECT_RAD_DEFAULT, known)) ident = TRUE; - break; - } - - case SV_SCROLL_DETECT_DOOR: - { - if (detect_doors(DETECT_RAD_DEFAULT)) ident = TRUE; - if (detect_stairs(DETECT_RAD_DEFAULT)) ident = TRUE; - break; - } - - case SV_SCROLL_DETECT_INVIS: - { - if (detect_monsters_invis(DETECT_RAD_DEFAULT)) ident = TRUE; - break; - } - - case SV_SCROLL_SATISFY_HUNGER: - { - if (set_food(PY_FOOD_MAX - 1)) ident = TRUE; - break; - } - - case SV_SCROLL_BLESSING: - { - if (set_blessed(p_ptr->blessed + randint1(12) + 6, FALSE)) ident = TRUE; - break; - } - - case SV_SCROLL_HOLY_CHANT: - { - if (set_blessed(p_ptr->blessed + randint1(24) + 12, FALSE)) ident = TRUE; - break; - } - - case SV_SCROLL_HOLY_PRAYER: - { - if (set_blessed(p_ptr->blessed + randint1(48) + 24, FALSE)) ident = TRUE; - break; - } - - case SV_SCROLL_MONSTER_CONFUSION: - { - if (!(p_ptr->special_attack & ATTACK_CONFUSE)) - { - msg_print(_("手が輝き始めた。", "Your hands begin to glow.")); - p_ptr->special_attack |= ATTACK_CONFUSE; - p_ptr->redraw |= (PR_STATUS); - ident = TRUE; - } - break; - } - - case SV_SCROLL_PROTECTION_FROM_EVIL: - { - k = 3 * p_ptr->lev; - if (set_protevil(p_ptr->protevil + randint1(25) + k, FALSE)) ident = TRUE; - break; - } - - case SV_SCROLL_RUNE_OF_PROTECTION: - { - warding_glyph(); - ident = TRUE; - break; - } - - case SV_SCROLL_TRAP_DOOR_DESTRUCTION: - { - if (destroy_doors_touch()) ident = TRUE; - break; - } - - case SV_SCROLL_STAR_DESTRUCTION: - { - if (destroy_area(p_ptr->y, p_ptr->x, 13 + randint0(5), FALSE)) - ident = TRUE; - else - msg_print(_("ダンジョンが揺れた...", "The dungeon trembles...")); - - break; - } - - case SV_SCROLL_DISPEL_UNDEAD: - { - if (dispel_undead(80)) ident = TRUE; - break; - } - - case SV_SCROLL_SPELL: - { - if ((p_ptr->pclass == CLASS_WARRIOR) || - (p_ptr->pclass == CLASS_IMITATOR) || - (p_ptr->pclass == CLASS_MINDCRAFTER) || - (p_ptr->pclass == CLASS_SORCERER) || - (p_ptr->pclass == CLASS_ARCHER) || - (p_ptr->pclass == CLASS_MAGIC_EATER) || - (p_ptr->pclass == CLASS_RED_MAGE) || - (p_ptr->pclass == CLASS_SAMURAI) || - (p_ptr->pclass == CLASS_BLUE_MAGE) || - (p_ptr->pclass == CLASS_CAVALRY) || - (p_ptr->pclass == CLASS_BERSERKER) || - (p_ptr->pclass == CLASS_SMITH) || - (p_ptr->pclass == CLASS_MIRROR_MASTER) || - (p_ptr->pclass == CLASS_NINJA) || - (p_ptr->pclass == CLASS_SNIPER)) break; - p_ptr->add_spells++; - p_ptr->update |= (PU_SPELLS); - ident = TRUE; - break; - } - - case SV_SCROLL_GENOCIDE: - { - (void)symbol_genocide(300, TRUE); - ident = TRUE; - break; - } - - case SV_SCROLL_MASS_GENOCIDE: - { - (void)mass_genocide(300, TRUE); - ident = TRUE; - break; - } - - case SV_SCROLL_ACQUIREMENT: - { - acquirement(p_ptr->y, p_ptr->x, 1, TRUE, FALSE, FALSE); - ident = TRUE; - break; - } - - case SV_SCROLL_STAR_ACQUIREMENT: - { - acquirement(p_ptr->y, p_ptr->x, randint1(2) + 1, TRUE, FALSE, FALSE); - ident = TRUE; - break; - } - - /* New Hengband scrolls */ - case SV_SCROLL_FIRE: - { - fire_ball(GF_FIRE, 0, 666, 4); - /* Note: "Double" damage since it is centered on the player ... */ - if (!(IS_OPPOSE_FIRE() || p_ptr->resist_fire || p_ptr->immune_fire)) - take_hit(DAMAGE_NOESCAPE, 50+randint1(50), _("炎の巻物", "a Scroll of Fire"), -1); - - ident = TRUE; - break; - } - - - case SV_SCROLL_ICE: - { - fire_ball(GF_ICE, 0, 777, 4); - if (!(IS_OPPOSE_COLD() || p_ptr->resist_cold || p_ptr->immune_cold)) - take_hit(DAMAGE_NOESCAPE, 100+randint1(100), _("氷の巻物", "a Scroll of Ice"), -1); - - ident = TRUE; - break; - } - - case SV_SCROLL_CHAOS: - { - fire_ball(GF_CHAOS, 0, 1000, 4); - if (!p_ptr->resist_chaos) - take_hit(DAMAGE_NOESCAPE, 111+randint1(111), _("ログルスの巻物", "a Scroll of Logrus"), -1); - - ident = TRUE; - break; - } - - case SV_SCROLL_RUMOR: - { - msg_print(_("巻物にはメッセージが書かれている:", "There is message on the scroll. It says:")); - msg_print(NULL); - display_rumor(TRUE); - msg_print(NULL); - msg_print(_("巻物は煙を立てて消え去った!", "The scroll disappears in a puff of smoke!")); - - ident = TRUE; - break; - } - - case SV_SCROLL_ARTIFACT: - { - ident = TRUE; - if (!artifact_scroll()) used_up = FALSE; - break; - } - - case SV_SCROLL_RESET_RECALL: - { - ident = TRUE; - if (!reset_recall()) used_up = FALSE; - break; - } - - case SV_SCROLL_AMUSEMENT: - { - ident = TRUE; - amusement(p_ptr->y, p_ptr->x, 1, FALSE); - break; - } - - case SV_SCROLL_STAR_AMUSEMENT: - { - ident = TRUE; - amusement(p_ptr->y, p_ptr->x, randint1(2) + 1, FALSE); - break; - } - } - } - else if (o_ptr->name1 == ART_GHB) - { - msg_print(_("私は苦労して『グレーター・ヘル=ビースト』を倒した。", "I had a very hard time to kill the Greater hell-beast, ")); - msg_print(_("しかし手に入ったのはこのきたないTシャツだけだった。", "but all I got was this lousy t-shirt!")); - used_up = FALSE; - } - else if (o_ptr->name1 == ART_POWER) - { - msg_print(_("「一つの指輪は全てを統べ、", "'One Ring to rule them all, ")); - msg_print(NULL); - msg_print(_("一つの指輪は全てを見つけ、", "One Ring to find them, ")); - msg_print(NULL); - msg_print(_("一つの指輪は全てを捕らえて", "One Ring to bring them all ")); - msg_print(NULL); - msg_print(_("暗闇の中に繋ぎとめる。」", "and in the darkness bind them.'")); - used_up = FALSE; - } - else if (o_ptr->tval==TV_PARCHMENT) - { - concptr q; - GAME_TEXT o_name[MAX_NLEN]; - char buf[1024]; - screen_save(); - - q=format("book-%d_jp.txt",o_ptr->sval); - - /* Display object description */ - object_desc(o_name, o_ptr, OD_NAME_ONLY); - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, q); - - /* Peruse the help file */ - (void)show_file(TRUE, buf, o_name, 0, 0); - screen_load(); - - used_up=FALSE; - } - - p_ptr->update |= (PU_COMBINE | PU_REORDER); - - if (!(object_is_aware(o_ptr))) - { - chg_virtue(V_PATIENCE, -1); - chg_virtue(V_CHANCE, 1); - chg_virtue(V_KNOWLEDGE, -1); - } - - /* The item was tried */ - object_tried(o_ptr); - - /* An identification was made */ - if (ident && !object_is_aware(o_ptr)) - { - object_aware(o_ptr); - gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); - } - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - - /* Hack -- allow certain scrolls to be "preserved" */ - if (!used_up) - { - return; - } - - sound(SOUND_SCROLL); - - /* Destroy a scroll in the pack */ - if (item >= 0) - { - inven_item_increase(item, -1); - inven_item_describe(item); - inven_item_optimize(item); - } - - /* Destroy a scroll on the floor */ - else - { - floor_item_increase(0 - item, -1); - floor_item_describe(0 - item); - floor_item_optimize(0 - item); - } -} - -/*! - * @brief 読むコマンドのメインルーチン / - * Eat some food (from the pack or floor) - * @return なし - */ -void do_cmd_read_scroll(void) -{ - object_type *o_ptr; - OBJECT_IDX item; - concptr q, s; - - if (p_ptr->wild_mode) - { - return; - } - - if (cmd_limit_arena(p_ptr)) return; - - if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) - { - set_action(ACTION_NONE); - } - - if (cmd_limit_blind(p_ptr)) return; - if (cmd_limit_confused(p_ptr)) return; - - /* Restrict choices to scrolls */ - item_tester_hook = item_tester_hook_readable; - - q = _("どの巻物を読みますか? ", "Read which scroll? "); - s = _("読める巻物がない。", "You have no scrolls to read."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR)); - if (!o_ptr) return; - - /* Read the scroll */ - do_cmd_read_scroll_aux(item, object_is_aware(o_ptr)); -} diff --git a/src/cmd-read.h b/src/cmd-read.h deleted file mode 100644 index 9f4eae65c..000000000 --- a/src/cmd-read.h +++ /dev/null @@ -1,4 +0,0 @@ - - -extern void do_cmd_read_scroll_aux(INVENTORY_IDX item, bool known); -extern void do_cmd_read_scroll(void); diff --git a/src/cmd-smith.c b/src/cmd-smith.c deleted file mode 100644 index 9c8948f4c..000000000 --- a/src/cmd-smith.c +++ /dev/null @@ -1,1517 +0,0 @@ -#include "angband.h" -#include "object-hook.h" -#include "player-status.h" - - - -/*! - * エッセンス情報の構造体 / A structure for smithing - */ -typedef struct { - int add; /* TR flag number or special essence id */ - concptr add_name; /* Name of this ability */ - ESSENCE_IDX type; /* Menu number */ - int essence; /* Index for carrying essences */ - int value; /* Needed value to add this ability */ -} essence_type; - - -/*! - * エッセンス情報テーブル Smithing type data for Weapon smith - */ -#ifdef JP -static essence_type essence_info[] = -{ - {TR_STR, "腕力", 4, TR_STR, 20}, - {TR_INT, "知能", 4, TR_INT, 20}, - {TR_WIS, "賢さ", 4, TR_WIS, 20}, - {TR_DEX, "器用さ", 4, TR_DEX, 20}, - {TR_CON, "耐久力", 4, TR_CON, 20}, - {TR_CHR, "魅力", 4, TR_CHR, 20}, - {TR_MAGIC_MASTERY, "魔力支配", 4, TR_MAGIC_MASTERY, 20}, - {TR_STEALTH, "隠密", 4, TR_STEALTH, 40}, - {TR_SEARCH, "探索", 4, TR_SEARCH, 15}, - {TR_INFRA, "赤外線視力", 4, TR_INFRA, 15}, - {TR_TUNNEL, "採掘", 4, TR_TUNNEL, 15}, - {TR_SPEED, "スピード", 4, TR_SPEED, 12}, - {TR_BLOWS, "追加攻撃", 1, TR_BLOWS, 20}, - {TR_CHAOTIC, "カオス攻撃", 1, TR_CHAOTIC, 15}, - {TR_VAMPIRIC, "吸血攻撃", 1, TR_VAMPIRIC, 60}, - {TR_IMPACT, "地震発動", 7, TR_IMPACT, 15}, - {TR_BRAND_POIS, "毒殺", 1, TR_BRAND_POIS, 20}, - {TR_BRAND_ACID, "溶解", 1, TR_BRAND_ACID, 20}, - {TR_BRAND_ELEC, "電撃", 1, TR_BRAND_ELEC, 20}, - {TR_BRAND_FIRE, "焼棄", 1, TR_BRAND_FIRE, 20}, - {TR_BRAND_COLD, "凍結", 1, TR_BRAND_COLD, 20}, - {TR_SUST_STR, "腕力維持", 3, TR_SUST_STR, 15}, - {TR_SUST_INT, "知能維持", 3, TR_SUST_STR, 15}, - {TR_SUST_WIS, "賢さ維持", 3, TR_SUST_STR, 15}, - {TR_SUST_DEX, "器用さ維持", 3, TR_SUST_STR, 15}, - {TR_SUST_CON, "耐久力維持", 3, TR_SUST_STR, 15}, - {TR_SUST_CHR, "魅力維持", 3, TR_SUST_STR, 15}, - {TR_IM_ACID, "酸免疫", 2, TR_IM_ACID, 20}, - {TR_IM_ELEC, "電撃免疫", 2, TR_IM_ACID, 20}, - {TR_IM_FIRE, "火炎免疫", 2, TR_IM_ACID, 20}, - {TR_IM_COLD, "冷気免疫", 2, TR_IM_ACID, 20}, - {TR_REFLECT, "反射", 2, TR_REFLECT, 20}, - {TR_FREE_ACT, "麻痺知らず", 3, TR_FREE_ACT, 20}, - {TR_HOLD_EXP, "経験値維持", 3, TR_HOLD_EXP, 20}, - {TR_RES_ACID, "耐酸", 2, TR_RES_ACID, 15}, - {TR_RES_ELEC, "耐電撃", 2, TR_RES_ELEC, 15}, - {TR_RES_FIRE, "耐火炎", 2, TR_RES_FIRE, 15}, - {TR_RES_COLD, "耐冷気", 2, TR_RES_COLD, 15}, - {TR_RES_POIS, "耐毒", 2, TR_RES_POIS, 25}, - {TR_RES_FEAR, "耐恐怖", 2, TR_RES_FEAR, 20}, - {TR_RES_LITE, "耐閃光", 2, TR_RES_LITE, 20}, - {TR_RES_DARK, "耐暗黒", 2, TR_RES_DARK, 20}, - {TR_RES_BLIND, "耐盲目", 2, TR_RES_BLIND, 20}, - {TR_RES_CONF, "耐混乱", 2, TR_RES_CONF, 20}, - {TR_RES_SOUND, "耐轟音", 2, TR_RES_SOUND, 20}, - {TR_RES_SHARDS, "耐破片", 2, TR_RES_SHARDS, 20}, - {TR_RES_NETHER, "耐地獄", 2, TR_RES_NETHER, 20}, - {TR_RES_NEXUS, "耐因果混乱", 2, TR_RES_NEXUS, 20}, - {TR_RES_CHAOS, "耐カオス", 2, TR_RES_CHAOS, 20}, - {TR_RES_DISEN, "耐劣化", 2, TR_RES_DISEN, 20}, - {TR_SH_FIRE, "", 0, -2, 0}, - {TR_SH_ELEC, "", 0, -2, 0}, - {TR_SH_COLD, "", 0, -2, 0}, - {TR_NO_MAGIC, "反魔法", 3, TR_NO_MAGIC, 15}, - {TR_WARNING, "警告", 3, TR_WARNING, 20}, - {TR_LEVITATION, "浮遊", 3, TR_LEVITATION, 20}, - {TR_LITE_1, "永久光源", 3, TR_LITE_1, 15}, - {TR_LITE_2, "", 0, -2, 0}, - {TR_LITE_3, "", 0, -2, 0}, - {TR_SEE_INVIS, "可視透明", 3, TR_SEE_INVIS, 20}, - {TR_TELEPATHY, "テレパシー", 6, TR_TELEPATHY, 15}, - {TR_SLOW_DIGEST, "遅消化", 3, TR_SLOW_DIGEST, 15}, - {TR_REGEN, "急速回復", 3, TR_REGEN, 20}, - {TR_TELEPORT, "テレポート", 3, TR_TELEPORT, 25}, - - {TR_SLAY_EVIL, "邪悪倍打", 5, TR_SLAY_EVIL, 100}, - {TR_KILL_EVIL, "邪悪倍倍打", 0, TR_SLAY_EVIL, 60}, - {TR_SLAY_ANIMAL, "動物倍打", 5, TR_SLAY_ANIMAL, 20}, - {TR_KILL_ANIMAL, "動物倍倍打", 5, TR_SLAY_ANIMAL, 60}, - {TR_SLAY_UNDEAD, "不死倍打", 5, TR_SLAY_UNDEAD, 20}, - {TR_KILL_UNDEAD, "不死倍倍打", 5, TR_SLAY_UNDEAD, 60}, - {TR_SLAY_DEMON, "悪魔倍打", 5, TR_SLAY_DEMON, 20}, - {TR_KILL_DEMON, "悪魔倍倍打", 5, TR_SLAY_DEMON, 60}, - {TR_SLAY_ORC, "オーク倍打", 5, TR_SLAY_ORC, 15}, - {TR_KILL_ORC, "オーク倍倍打", 5, TR_SLAY_ORC, 60}, - {TR_SLAY_TROLL, "トロル倍打", 5, TR_SLAY_TROLL, 15}, - {TR_KILL_TROLL, "トロル倍倍打", 5, TR_SLAY_TROLL, 60}, - {TR_SLAY_GIANT, "巨人倍打", 5, TR_SLAY_GIANT, 20}, - {TR_KILL_GIANT, "巨人倍倍打", 5, TR_SLAY_GIANT, 60}, - {TR_SLAY_DRAGON, "竜倍打", 5, TR_SLAY_DRAGON, 20}, - {TR_KILL_DRAGON, "竜倍倍打", 5, TR_SLAY_DRAGON, 60}, - {TR_SLAY_HUMAN, "人間倍打", 5, TR_SLAY_HUMAN, 20}, - {TR_KILL_HUMAN, "人間倍倍打", 5, TR_SLAY_HUMAN, 60}, - - {TR_ESP_ANIMAL, "動物ESP", 6, TR_SLAY_ANIMAL, 40}, - {TR_ESP_UNDEAD, "不死ESP", 6, TR_SLAY_UNDEAD, 40}, - {TR_ESP_DEMON, "悪魔ESP", 6, TR_SLAY_DEMON, 40}, - {TR_ESP_ORC, "オークESP", 6, TR_SLAY_ORC, 40}, - {TR_ESP_TROLL, "トロルESP", 6, TR_SLAY_TROLL, 40}, - {TR_ESP_GIANT, "巨人ESP", 6, TR_SLAY_GIANT, 40}, - {TR_ESP_DRAGON, "竜ESP", 6, TR_SLAY_DRAGON, 40}, - {TR_ESP_HUMAN, "人間ESP", 6, TR_SLAY_HUMAN, 40}, - - {ESSENCE_ATTACK, "攻撃", 10, TR_ES_ATTACK, 30}, - {ESSENCE_AC, "防御", 10, TR_ES_AC, 15}, - {ESSENCE_TMP_RES_ACID, "酸耐性発動", 7, TR_RES_ACID, 50}, - {ESSENCE_TMP_RES_ELEC, "電撃耐性発動", 7, TR_RES_ELEC, 50}, - {ESSENCE_TMP_RES_FIRE, "火炎耐性発動", 7, TR_RES_FIRE, 50}, - {ESSENCE_TMP_RES_COLD, "冷気耐性発動", 7, TR_RES_COLD, 50}, - {ESSENCE_SH_FIRE, "火炎オーラ", 7, -1, 50}, - {ESSENCE_SH_ELEC, "電撃オーラ", 7, -1, 50}, - {ESSENCE_SH_COLD, "冷気オーラ", 7, -1, 50}, - {ESSENCE_RESISTANCE, "全耐性", 2, -1, 150}, - {ESSENCE_SUSTAIN, "装備保持", 10, -1, 10}, - {ESSENCE_SLAY_GLOVE, "殺戮の小手", 1, TR_ES_ATTACK, 200}, - - {-1, NULL, 0, -1, 0} -}; -#else -static essence_type essence_info[] = -{ - {TR_STR, "strength", 4, TR_STR, 20}, - {TR_INT, "intelligence", 4, TR_INT, 20}, - {TR_WIS, "wisdom", 4, TR_WIS, 20}, - {TR_DEX, "dexterity", 4, TR_DEX, 20}, - {TR_CON, "constitution", 4, TR_CON, 20}, - {TR_CHR, "charisma", 4, TR_CHR, 20}, - {TR_MAGIC_MASTERY, "magic mastery", 4, TR_MAGIC_MASTERY, 20}, - {TR_STEALTH, "stealth", 4, TR_STEALTH, 40}, - {TR_SEARCH, "serching", 4, TR_SEARCH, 15}, - {TR_INFRA, "infravision", 4, TR_INFRA, 15}, - {TR_TUNNEL, "digging", 4, TR_TUNNEL, 15}, - {TR_SPEED, "speed", 4, TR_SPEED, 12}, - {TR_BLOWS, "extra attack", 1, TR_BLOWS, 20}, - {TR_CHAOTIC, "chaos brand", 1, TR_CHAOTIC, 15}, - {TR_VAMPIRIC, "vampiric brand", 1, TR_VAMPIRIC, 60}, - {TR_IMPACT, "quake activation", 7, TR_IMPACT, 15}, - {TR_BRAND_POIS, "poison brand", 1, TR_BRAND_POIS, 20}, - {TR_BRAND_ACID, "acid brand", 1, TR_BRAND_ACID, 20}, - {TR_BRAND_ELEC, "electric brand", 1, TR_BRAND_ELEC, 20}, - {TR_BRAND_FIRE, "fire brand", 1, TR_BRAND_FIRE, 20}, - {TR_BRAND_COLD, "cold brand", 1, TR_BRAND_COLD, 20}, - {TR_SUST_STR, "sustain strength", 3, TR_SUST_STR, 15}, - {TR_SUST_INT, "sustain intelligence", 3, TR_SUST_STR, 15}, - {TR_SUST_WIS, "sustain wisdom", 3, TR_SUST_STR, 15}, - {TR_SUST_DEX, "sustain dexterity", 3, TR_SUST_STR, 15}, - {TR_SUST_CON, "sustain constitution", 3, TR_SUST_STR, 15}, - {TR_SUST_CHR, "sustain charisma", 3, TR_SUST_STR, 15}, - {TR_IM_ACID, "acid immunity", 2, TR_IM_ACID, 20}, - {TR_IM_ELEC, "electric immunity", 2, TR_IM_ACID, 20}, - {TR_IM_FIRE, "fire immunity", 2, TR_IM_ACID, 20}, - {TR_IM_COLD, "cold immunity", 2, TR_IM_ACID, 20}, - {TR_REFLECT, "reflection", 2, TR_REFLECT, 20}, - {TR_FREE_ACT, "free action", 3, TR_FREE_ACT, 20}, - {TR_HOLD_EXP, "hold experience", 3, TR_HOLD_EXP, 20}, - {TR_RES_ACID, "resistance to acid", 2, TR_RES_ACID, 15}, - {TR_RES_ELEC, "resistance to electric", 2, TR_RES_ELEC, 15}, - {TR_RES_FIRE, "resistance to fire", 2, TR_RES_FIRE, 15}, - {TR_RES_COLD, "resistance to cold", 2, TR_RES_COLD, 15}, - {TR_RES_POIS, "resistance to poison", 2, TR_RES_POIS, 25}, - {TR_RES_FEAR, "resistance to fear", 2, TR_RES_FEAR, 20}, - {TR_RES_LITE, "resistance to light", 2, TR_RES_LITE, 20}, - {TR_RES_DARK, "resistance to dark", 2, TR_RES_DARK, 20}, - {TR_RES_BLIND, "resistance to blind", 2, TR_RES_BLIND, 20}, - {TR_RES_CONF, "resistance to confusion", 2, TR_RES_CONF, 20}, - {TR_RES_SOUND, "resistance to sound", 2, TR_RES_SOUND, 20}, - {TR_RES_SHARDS, "resistance to shard", 2, TR_RES_SHARDS, 20}, - {TR_RES_NETHER, "resistance to nether", 2, TR_RES_NETHER, 20}, - {TR_RES_NEXUS, "resistance to nexus", 2, TR_RES_NEXUS, 20}, - {TR_RES_CHAOS, "resistance to chaos", 2, TR_RES_CHAOS, 20}, - {TR_RES_DISEN, "resistance to disenchantment", 2, TR_RES_DISEN, 20}, - {TR_SH_FIRE, "", 0, -2, 0}, - {TR_SH_ELEC, "", 0, -2, 0}, - {TR_SH_COLD, "", 0, -2, 0}, - {TR_NO_MAGIC, "anti magic", 3, TR_NO_MAGIC, 15}, - {TR_WARNING, "warning", 3, TR_WARNING, 20}, - {TR_LEVITATION, "levitation", 3, TR_LEVITATION, 20}, - {TR_LITE_1, "permanent light", 3, TR_LITE_1, 15}, - {TR_LITE_2, "", 0, -2, 0}, - {TR_LITE_3, "", 0, -2, 0}, - {TR_SEE_INVIS, "see invisible", 3, TR_SEE_INVIS, 20}, - {TR_TELEPATHY, "telepathy", 6, TR_TELEPATHY, 15}, - {TR_SLOW_DIGEST, "slow digestion", 3, TR_SLOW_DIGEST, 15}, - {TR_REGEN, "regeneration", 3, TR_REGEN, 20}, - {TR_TELEPORT, "teleport", 3, TR_TELEPORT, 25}, - - {TR_SLAY_EVIL, "slay evil", 5, TR_SLAY_EVIL, 100}, - {TR_SLAY_ANIMAL, "slay animal", 5, TR_SLAY_ANIMAL, 20}, - {TR_KILL_ANIMAL, "kill animal", 5, TR_SLAY_ANIMAL, 60}, - {TR_KILL_EVIL, "kill evil", 0, TR_SLAY_EVIL, 60}, - {TR_SLAY_UNDEAD, "slay undead", 5, TR_SLAY_UNDEAD, 20}, - {TR_KILL_UNDEAD, "kill undead", 5, TR_SLAY_UNDEAD, 60}, - {TR_SLAY_DEMON, "slay demon", 5, TR_SLAY_DEMON, 20}, - {TR_KILL_DEMON, "kill demon", 5, TR_SLAY_DEMON, 60}, - {TR_SLAY_ORC, "slay orc", 5, TR_SLAY_ORC, 15}, - {TR_KILL_ORC, "kill orc", 5, TR_SLAY_ORC, 60}, - {TR_SLAY_TROLL, "slay troll", 5, TR_SLAY_TROLL, 15}, - {TR_KILL_TROLL, "kill troll", 5, TR_SLAY_TROLL, 60}, - {TR_SLAY_GIANT, "slay giant", 5, TR_SLAY_GIANT, 20}, - {TR_KILL_GIANT, "kill giant", 5, TR_SLAY_GIANT, 60}, - {TR_SLAY_DRAGON, "slay dragon", 5, TR_SLAY_DRAGON, 20}, - {TR_KILL_DRAGON, "kill dragon", 5, TR_SLAY_DRAGON, 60}, - {TR_SLAY_HUMAN, "slay human", 5, TR_SLAY_HUMAN, 20}, - {TR_KILL_HUMAN, "kill human", 5, TR_SLAY_HUMAN, 60}, - - {TR_ESP_ANIMAL, "sense animal", 6, TR_SLAY_ANIMAL, 40}, - {TR_ESP_UNDEAD, "sense undead", 6, TR_SLAY_UNDEAD, 40}, - {TR_ESP_DEMON, "sense demon", 6, TR_SLAY_DEMON, 40}, - {TR_ESP_ORC, "sense orc", 6, TR_SLAY_ORC, 40}, - {TR_ESP_TROLL, "sense troll", 6, TR_SLAY_TROLL, 40}, - {TR_ESP_GIANT, "sense giant", 6, TR_SLAY_GIANT, 40}, - {TR_ESP_DRAGON, "sense dragon", 6, TR_SLAY_DRAGON, 40}, - {TR_ESP_HUMAN, "sense human", 6, TR_SLAY_HUMAN, 40}, - - {ESSENCE_ATTACK, "weapon enchant", 10, TR_ES_ATTACK, 30}, - {ESSENCE_AC, "armor enchant", 10, TR_ES_AC, 15}, - {ESSENCE_TMP_RES_ACID, "resist acid activation", 7, TR_RES_ACID, 50}, - {ESSENCE_TMP_RES_ELEC, "resist electricity activation", 7, TR_RES_ELEC, 50}, - {ESSENCE_TMP_RES_FIRE, "resist fire activation", 7, TR_RES_FIRE, 50}, - {ESSENCE_TMP_RES_COLD, "resist cold activation", 7, TR_RES_COLD, 50}, - {ESSENCE_SH_FIRE, "fiery sheath", 7, -1, 50}, - {ESSENCE_SH_ELEC, "electric sheath", 7, -1, 50}, - {ESSENCE_SH_COLD, "sheath of coldness", 7, -1, 50}, - {ESSENCE_RESISTANCE, "resistance", 2, -1, 150}, - {ESSENCE_SUSTAIN, "elements proof", 10, -1, 10}, - {ESSENCE_SLAY_GLOVE, "gauntlets of slaying", 1, TR_ES_ATTACK, 200}, - - {-1, NULL, 0, -1, 0} -}; -#endif - - -/*! - * エッセンス名テーブル / Essense names for Weapon smith - */ -#ifdef JP -concptr essence_name[] = -{ - "腕力", - "知能", - "賢さ", - "器用さ", - "耐久力", - "魅力", - "魔力支配", - "", - "隠密", - "探索", - "赤外線視力", - "採掘", - "スピード", - "追加攻撃", - "カオス攻撃", - "吸血攻撃", - "動物倍打", - "邪悪倍打", - "不死倍打", - "悪魔倍打", - "オーク倍打", - "トロル倍打", - "巨人倍打", - "竜倍打", - "", - "", - "地震", - "毒殺", - "溶解", - "電撃", - "焼棄", - "凍結", - "能力維持", - "", - "", - "", - "", - "", - "", - "", - "免疫", - "", - "", - "", - "", - "反射", - "麻痺知らず", - "経験値維持", - "耐酸", - "耐電撃", - "耐火炎", - "耐冷気", - "耐毒", - "耐恐怖", - "耐閃光", - "耐暗黒", - "耐盲目", - "耐混乱", - "耐轟音", - "耐破片", - "耐地獄", - "耐因果混乱", - "耐カオス", - "耐劣化", - "", - "", - "人間倍打", - "", - "", - "反魔法", - "", - "", - "警告", - "", - "", - "", - "浮遊", - "永久光源", - "可視透明", - "テレパシー", - "遅消化", - "急速回復", - "", - "", - "", - "", - "", - "", - "", - "", - "テレポート", - "", - "", - "攻撃", - "防御", - - NULL -}; - -#else - -concptr essence_name[] = -{ - "strength", - "intelligen.", - "wisdom", - "dexterity", - "constitut.", - "charisma", - "magic mast.", - "", - "stealth", - "serching", - "infravision", - "digging", - "speed", - "extra atk", - "chaos brand", - "vampiric", - "slay animal", - "slay evil", - "slay undead", - "slay demon", - "slay orc", - "slay troll", - "slay giant", - "slay dragon", - "", - "", - "quake", - "pois. brand", - "acid brand", - "elec. brand", - "fire brand", - "cold brand", - "sustain", - "", - "", - "", - "", - "", - "", - "", - "immunity", - "", - "", - "", - "", - "reflection", - "free action", - "hold exp", - "res. acid", - "res. elec.", - "res. fire", - "res. cold", - "res. poison", - "res. fear", - "res. light", - "res. dark", - "res. blind", - "res.confuse", - "res. sound", - "res. shard", - "res. nether", - "res. nexus", - "res. chaos", - "res. disen.", - "", - "", - "slay human", - "", - "", - "anti magic", - "", - "", - "warning", - "", - "", - "", - "levitation", - "perm. light", - "see invis.", - "telepathy", - "slow dige.", - "regen.", - "", - "", - "", - "", - "", - "", - "", - "", - "teleport", - "", - "", - "weapon enc.", - "armor enc.", - - NULL -}; -#endif - -static concptr const kaji_tips[5] = -{ -#ifdef JP - "現在持っているエッセンスの一覧を表示する。", - "アイテムからエッセンスを取り出す。エッセンスを取られたアイテムは全く魔法がかかっていない初期状態に戻る。", - "既にエッセンスが付加されたアイテムからエッセンスのみ消し去る。エッセンスは手に入らない。", - "アイテムにエッセンスを付加する。既にエッセンスが付加されたアイテムやアーティファクトには付加できない。", - "武器や防具を強化したり、攻撃で傷つかないようにしたりする。エッセンスが付加されたアイテムやアーティファクトに対しても使用できる。", -#else - "Display essences you have.", - "Extract essences from an item. The item become non magical.", - "Remove added essences from an equipment which was improved before. The removed essence will be ruined.", - "Add essences to an item. The improved items or artifacts cannot be reimprove.", - "Enchant an equipment or make an equiment element-proofed. The improved items and artifacts can be enchanted too.", -#endif -}; - - -/*! - * @brief 所持しているエッセンス一覧を表示する - * @return なし - */ -static void display_essence(void) -{ - int i, num = 0; - - screen_save(); - for (i = 1; i < 22; i++) - { - prt("", i, 0); - } - prt(_("エッセンス 個数 エッセンス 個数 エッセンス 個数", - "Essence Num Essence Num Essence Num "), 1, 8); - for (i = 0; essence_name[i]; i++) - { - if (!essence_name[i][0]) continue; - prt(format("%-11s %5d", essence_name[i], p_ptr->magic_num1[i]), 2 + num % 21, 8 + num / 21 * 22); - num++; - } - prt(_("現在所持しているエッセンス", "List of all essences you have."), 0, 0); - (void)inkey(); - screen_load(); - return; -} - -/*! - * @brief エッセンスの抽出処理 - * @return なし - */ -static void drain_essence(void) -{ - int drain_value[sizeof(p_ptr->magic_num1) / sizeof(s32b)]; - int i; - OBJECT_IDX item; - int dec = 4; - bool observe = FALSE; - int old_ds, old_dd, old_to_h, old_to_d, old_ac, old_to_a, old_pval, old_name2; - TIME_EFFECT old_timeout; - BIT_FLAGS old_flgs[TR_FLAG_SIZE], new_flgs[TR_FLAG_SIZE]; - object_type *o_ptr; - concptr q, s; - POSITION iy, ix; - byte_hack marked; - ITEM_NUMBER number; - OBJECT_IDX next_o_idx; - WEIGHT weight; - - for (i = 0; i < sizeof(drain_value) / sizeof(int); i++) - drain_value[i] = 0; - - item_tester_hook = object_is_weapon_armour_ammo; - - q = _("どのアイテムから抽出しますか?", "Extract from which item? "); - s = _("抽出できるアイテムがありません。", "You have nothing you can extract from."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT)); - if (!o_ptr) return; - - if (object_is_known(o_ptr) && !object_is_nameless(o_ptr)) - { - GAME_TEXT o_name[MAX_NLEN]; - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - if (!get_check(format(_("本当に%sから抽出してよろしいですか?", "Really extract from %s? "), o_name))) return; - } - - take_turn(p_ptr, 100); - - object_flags(o_ptr, old_flgs); - if (have_flag(old_flgs, TR_KILL_DRAGON)) add_flag(old_flgs, TR_SLAY_DRAGON); - if (have_flag(old_flgs, TR_KILL_ANIMAL)) add_flag(old_flgs, TR_SLAY_ANIMAL); - if (have_flag(old_flgs, TR_KILL_EVIL)) add_flag(old_flgs, TR_SLAY_EVIL); - if (have_flag(old_flgs, TR_KILL_UNDEAD)) add_flag(old_flgs, TR_SLAY_UNDEAD); - if (have_flag(old_flgs, TR_KILL_DEMON)) add_flag(old_flgs, TR_SLAY_DEMON); - if (have_flag(old_flgs, TR_KILL_ORC)) add_flag(old_flgs, TR_SLAY_ORC); - if (have_flag(old_flgs, TR_KILL_TROLL)) add_flag(old_flgs, TR_SLAY_TROLL); - if (have_flag(old_flgs, TR_KILL_GIANT)) add_flag(old_flgs, TR_SLAY_GIANT); - if (have_flag(old_flgs, TR_KILL_HUMAN)) add_flag(old_flgs, TR_SLAY_HUMAN); - - old_to_a = o_ptr->to_a; - old_ac = o_ptr->ac; - old_to_h = o_ptr->to_h; - old_to_d = o_ptr->to_d; - old_ds = o_ptr->ds; - old_dd = o_ptr->dd; - old_pval = o_ptr->pval; - old_name2 = o_ptr->name2; - old_timeout = o_ptr->timeout; - if (o_ptr->curse_flags & (TRC_CURSED | TRC_HEAVY_CURSE | TRC_PERMA_CURSE)) dec--; - if (have_flag(old_flgs, TR_ADD_L_CURSE)) dec--; - if (have_flag(old_flgs, TR_ADD_H_CURSE)) dec--; - if (have_flag(old_flgs, TR_AGGRAVATE)) dec--; - if (have_flag(old_flgs, TR_NO_TELE)) dec--; - if (have_flag(old_flgs, TR_DRAIN_EXP)) dec--; - if (have_flag(old_flgs, TR_DRAIN_HP)) dec--; - if (have_flag(old_flgs, TR_DRAIN_MANA)) dec--; - if (have_flag(old_flgs, TR_CALL_ANIMAL)) dec--; - if (have_flag(old_flgs, TR_CALL_DEMON)) dec--; - if (have_flag(old_flgs, TR_CALL_DRAGON)) dec--; - if (have_flag(old_flgs, TR_CALL_UNDEAD)) dec--; - if (have_flag(old_flgs, TR_COWARDICE)) dec--; - if (have_flag(old_flgs, TR_LOW_MELEE)) dec--; - if (have_flag(old_flgs, TR_LOW_AC)) dec--; - if (have_flag(old_flgs, TR_LOW_MAGIC)) dec--; - if (have_flag(old_flgs, TR_FAST_DIGEST)) dec--; - if (have_flag(old_flgs, TR_SLOW_REGEN)) dec--; - if (have_flag(old_flgs, TR_TY_CURSE)) dec--; - - iy = o_ptr->iy; - ix = o_ptr->ix; - next_o_idx = o_ptr->next_o_idx; - marked = o_ptr->marked; - weight = o_ptr->weight; - number = o_ptr->number; - - object_prep(o_ptr, o_ptr->k_idx); - - o_ptr->iy = iy; - o_ptr->ix = ix; - o_ptr->next_o_idx = next_o_idx; - o_ptr->marked = marked; - o_ptr->number = number; - if (o_ptr->tval == TV_DRAG_ARMOR) o_ptr->timeout = old_timeout; - if (item >= 0) p_ptr->total_weight += (o_ptr->weight*o_ptr->number - weight * number); - o_ptr->ident |= (IDENT_MENTAL); - object_aware(o_ptr); - object_known(o_ptr); - - object_flags(o_ptr, new_flgs); - - for (i = 0; essence_info[i].add_name; i++) - { - essence_type *es_ptr = &essence_info[i]; - PARAMETER_VALUE pval = 0; - - if (es_ptr->add < TR_FLAG_MAX && is_pval_flag(es_ptr->add) && old_pval) - pval = (have_flag(new_flgs, es_ptr->add)) ? old_pval - o_ptr->pval : old_pval; - - if (es_ptr->add < TR_FLAG_MAX && - (!have_flag(new_flgs, es_ptr->add) || pval) && - have_flag(old_flgs, es_ptr->add)) - { - if (pval) - { - drain_value[es_ptr->essence] += 10 * pval; - } - else if (es_ptr->essence != -2) - { - drain_value[es_ptr->essence] += 10; - } - else if (es_ptr->add == TR_SH_FIRE) - { - drain_value[TR_BRAND_FIRE] += 10; - drain_value[TR_RES_FIRE] += 10; - } - else if (es_ptr->add == TR_SH_ELEC) - { - drain_value[TR_BRAND_ELEC] += 10; - drain_value[TR_RES_ELEC] += 10; - } - else if (es_ptr->add == TR_SH_COLD) - { - drain_value[TR_BRAND_COLD] += 10; - drain_value[TR_RES_COLD] += 10; - } - else if (es_ptr->add == TR_LITE_2) - { - drain_value[TR_LITE_1] += 20; - } - else if (es_ptr->add == TR_LITE_3) - { - drain_value[TR_LITE_1] += 30; - } - } - } - - if ((have_flag(old_flgs, TR_FORCE_WEAPON)) && !(have_flag(new_flgs, TR_FORCE_WEAPON))) - { - drain_value[TR_INT] += 5; - drain_value[TR_WIS] += 5; - } - if ((have_flag(old_flgs, TR_VORPAL)) && !(have_flag(new_flgs, TR_VORPAL))) - { - drain_value[TR_BRAND_POIS] += 5; - drain_value[TR_BRAND_ACID] += 5; - drain_value[TR_BRAND_ELEC] += 5; - drain_value[TR_BRAND_FIRE] += 5; - drain_value[TR_BRAND_COLD] += 5; - } - if ((have_flag(old_flgs, TR_DEC_MANA)) && !(have_flag(new_flgs, TR_DEC_MANA))) - { - drain_value[TR_INT] += 10; - } - if ((have_flag(old_flgs, TR_XTRA_MIGHT)) && !(have_flag(new_flgs, TR_XTRA_MIGHT))) - { - drain_value[TR_STR] += 10; - } - if ((have_flag(old_flgs, TR_XTRA_SHOTS)) && !(have_flag(new_flgs, TR_XTRA_SHOTS))) - { - drain_value[TR_DEX] += 10; - } - if (old_name2 == EGO_2WEAPON) - { - drain_value[TR_DEX] += 20; - } - if (object_is_weapon_ammo(o_ptr)) - { - if (old_ds > o_ptr->ds) drain_value[TR_ES_ATTACK] += (old_ds - o_ptr->ds) * 10; - - if (old_dd > o_ptr->dd) drain_value[TR_ES_ATTACK] += (old_dd - o_ptr->dd) * 10; - } - if (old_to_h > o_ptr->to_h) drain_value[TR_ES_ATTACK] += (old_to_h - o_ptr->to_h) * 10; - if (old_to_d > o_ptr->to_d) drain_value[TR_ES_ATTACK] += (old_to_d - o_ptr->to_d) * 10; - if (old_ac > o_ptr->ac) drain_value[TR_ES_AC] += (old_ac - o_ptr->ac) * 10; - if (old_to_a > o_ptr->to_a) drain_value[TR_ES_AC] += (old_to_a - o_ptr->to_a) * 10; - - for (i = 0; i < sizeof(drain_value) / sizeof(int); i++) - { - drain_value[i] *= number; - drain_value[i] = drain_value[i] * dec / 4; - drain_value[i] = MAX(drain_value[i], 0); - if ((o_ptr->tval >= TV_SHOT) && (o_ptr->tval <= TV_BOLT)) drain_value[i] /= 10; - if (drain_value[i]) - { - observe = TRUE; - } - } - if (!observe) - { - msg_print(_("エッセンスは抽出できませんでした。", "You were not able to extract any essence.")); - } - else - { - msg_print(_("抽出したエッセンス:", "Extracted essences:")); - - for (i = 0; essence_name[i]; i++) - { - if (!essence_name[i][0]) continue; - if (!drain_value[i]) continue; - - p_ptr->magic_num1[i] += drain_value[i]; - p_ptr->magic_num1[i] = MIN(20000, p_ptr->magic_num1[i]); - msg_print(NULL); - msg_format("%s...%d%s", essence_name[i], drain_value[i], _("。", ". ")); - } - } - - /* Apply autodestroy/inscription to the drained item */ - autopick_alter_item(item, TRUE); - p_ptr->update |= (PU_COMBINE | PU_REORDER); - p_ptr->window |= (PW_INVEN); -} - -/*! - * @brief 付加するエッセンスの大別を選択する - * @return 選んだエッセンスの大別ID - */ -static COMMAND_CODE choose_essence(void) -{ - COMMAND_CODE mode = 0; - char choice; - COMMAND_CODE menu_line = (use_menu ? 1 : 0); - -#ifdef JP - concptr menu_name[] = { - "武器属性", - "耐性", - "能力", - "数値", - "スレイ", - "ESP", - "その他" - }; -#else - concptr menu_name[] = { - "Brand weapon", - "Resistance", - "Ability", - "Magic number", - "Slay", - "ESP", - "Others" - }; -#endif - const COMMAND_CODE mode_max = 7; - - if (repeat_pull(&mode) && 1 <= mode && mode <= mode_max) - return mode; - mode = 0; - if (use_menu) - { - screen_save(); - - while (!mode) - { - int i; - for (i = 0; i < mode_max; i++) -#ifdef JP - prt(format(" %s %s", (menu_line == 1 + i) ? "》" : " ", menu_name[i]), 2 + i, 14); - prt("どの種類のエッセンス付加を行いますか?", 0, 0); -#else - prt(format(" %s %s", (menu_line == 1 + i) ? "> " : " ", menu_name[i]), 2 + i, 14); - prt("Choose from menu.", 0, 0); -#endif - - choice = inkey(); - switch (choice) - { - case ESCAPE: - case 'z': - case 'Z': - screen_load(); - return 0; - case '2': - case 'j': - case 'J': - menu_line++; - break; - case '8': - case 'k': - case 'K': - menu_line += mode_max - 1; - break; - case '\r': - case '\n': - case 'x': - case 'X': - mode = menu_line; - break; - } - if (menu_line > mode_max) menu_line -= mode_max; - } - screen_load(); - } - else - { - screen_save(); - while (!mode) - { - int i; - - for (i = 0; i < mode_max; i++) - prt(format(" %c) %s", 'a' + i, menu_name[i]), 2 + i, 14); - - if (!get_com(_("何を付加しますか:", "Command :"), &choice, TRUE)) - { - screen_load(); - return 0; - } - - if (isupper(choice)) choice = (char)tolower(choice); - - if ('a' <= choice && choice <= 'a' + (char)mode_max - 1) - mode = (int)choice - 'a' + 1; - } - screen_load(); - } - - repeat_push(mode); - return mode; -} - -/*! - * @brief エッセンスを実際に付加する - * @param mode エッセンスの大別ID - * @return なし - */ -static void add_essence(ESSENCE_IDX mode) -{ - OBJECT_IDX item; - int max_num = 0; - COMMAND_CODE i; - bool flag, redraw; - char choice; - concptr q, s; - object_type *o_ptr; - int ask = TRUE; - char out_val[160]; - int num[22]; - GAME_TEXT o_name[MAX_NLEN]; - int use_essence; - essence_type *es_ptr; - bool able[22] = { 0 }; - - int menu_line = (use_menu ? 1 : 0); - - for (i = 0; essence_info[i].add_name; i++) - { - es_ptr = &essence_info[i]; - - if (es_ptr->type != mode) continue; - num[max_num++] = i; - } - - if (!repeat_pull(&i) || i < 0 || i >= max_num) - { - - /* Nothing chosen yet */ - flag = FALSE; - - /* No redraw yet */ - redraw = FALSE; - - /* Build a prompt */ - (void)strnfmt(out_val, 78, _("('*'で一覧, ESCで中断) どの能力を付加しますか?", "(*=List, ESC=exit) Add which ability? ")); - if (use_menu) screen_save(); - - choice = (always_show_list || use_menu) ? ESCAPE : 1; - while (!flag) - { - if (choice == ESCAPE) choice = ' '; - else if (!get_com(out_val, &choice, FALSE))break; - - if (use_menu && choice != ' ') - { - switch (choice) - { - case '0': - { - screen_load(); - return; - } - - case '8': - case 'k': - case 'K': - { - menu_line += (max_num - 1); - break; - } - - case '2': - case 'j': - case 'J': - { - menu_line++; - break; - } - - case '4': - case 'h': - case 'H': - { - menu_line = 1; - break; - } - case '6': - case 'l': - case 'L': - { - menu_line = max_num; - break; - } - - case 'x': - case 'X': - case '\r': - case '\n': - { - i = menu_line - 1; - ask = FALSE; - break; - } - } - if (menu_line > max_num) menu_line -= max_num; - } - /* Request redraw */ - if ((choice == ' ') || (choice == '*') || (choice == '?') || (use_menu && ask)) - { - /* Show the list */ - if (!redraw || use_menu) - { - byte y, x = 10; - int ctr; - char dummy[80], dummy2[80]; - byte col; - - strcpy(dummy, ""); - redraw = TRUE; - if (!use_menu) screen_save(); - - for (y = 1; y < 24; y++) - prt("", y, x); - - /* Print header(s) */ -#ifdef JP - prt(format(" %-43s %6s/%s", "能力(必要エッセンス)", "必要数", "所持数"), 1, x); - -#else - prt(format(" %-43s %6s/%s", "Ability (needed essence)", "Needs", "Possess"), 1, x); -#endif - /* Print list */ - for (ctr = 0; ctr < max_num; ctr++) - { - es_ptr = &essence_info[num[ctr]]; - - if (use_menu) - { - if (ctr == (menu_line - 1)) - strcpy(dummy, _("》 ", "> ")); - else strcpy(dummy, " "); - - } - /* letter/number for power selection */ - else - { - sprintf(dummy, "%c) ", I2A(ctr)); - } - - strcat(dummy, es_ptr->add_name); - - col = TERM_WHITE; - able[ctr] = TRUE; - - if (es_ptr->essence != -1) - { - strcat(dummy, format("(%s)", essence_name[es_ptr->essence])); - if (p_ptr->magic_num1[es_ptr->essence] < es_ptr->value) able[ctr] = FALSE; - } - else - { - switch (es_ptr->add) - { - case ESSENCE_SH_FIRE: - strcat(dummy, _("(焼棄+耐火炎)", "(brand fire + res.fire)")); - if (p_ptr->magic_num1[TR_BRAND_FIRE] < es_ptr->value) able[ctr] = FALSE; - if (p_ptr->magic_num1[TR_RES_FIRE] < es_ptr->value) able[ctr] = FALSE; - break; - case ESSENCE_SH_ELEC: - strcat(dummy, _("(電撃+耐電撃)", "(brand elec. + res. elec.)")); - if (p_ptr->magic_num1[TR_BRAND_ELEC] < es_ptr->value) able[ctr] = FALSE; - if (p_ptr->magic_num1[TR_RES_ELEC] < es_ptr->value) able[ctr] = FALSE; - break; - case ESSENCE_SH_COLD: - strcat(dummy, _("(凍結+耐冷気)", "(brand cold + res. cold)")); - if (p_ptr->magic_num1[TR_BRAND_COLD] < es_ptr->value) able[ctr] = FALSE; - if (p_ptr->magic_num1[TR_RES_COLD] < es_ptr->value) able[ctr] = FALSE; - break; - case ESSENCE_RESISTANCE: - strcat(dummy, _("(耐火炎+耐冷気+耐電撃+耐酸)", "(r.fire+r.cold+r.elec+r.acid)")); - if (p_ptr->magic_num1[TR_RES_FIRE] < es_ptr->value) able[ctr] = FALSE; - if (p_ptr->magic_num1[TR_RES_COLD] < es_ptr->value) able[ctr] = FALSE; - if (p_ptr->magic_num1[TR_RES_ELEC] < es_ptr->value) able[ctr] = FALSE; - if (p_ptr->magic_num1[TR_RES_ACID] < es_ptr->value) able[ctr] = FALSE; - break; - case ESSENCE_SUSTAIN: - strcat(dummy, _("(耐火炎+耐冷気+耐電撃+耐酸)", "(r.fire+r.cold+r.elec+r.acid)")); - if (p_ptr->magic_num1[TR_RES_FIRE] < es_ptr->value) able[ctr] = FALSE; - if (p_ptr->magic_num1[TR_RES_COLD] < es_ptr->value) able[ctr] = FALSE; - if (p_ptr->magic_num1[TR_RES_ELEC] < es_ptr->value) able[ctr] = FALSE; - if (p_ptr->magic_num1[TR_RES_ACID] < es_ptr->value) able[ctr] = FALSE; - break; - } - } - - if (!able[ctr]) col = TERM_RED; - - if (es_ptr->essence != -1) - { - sprintf(dummy2, "%-49s %3d/%d", dummy, es_ptr->value, (int)p_ptr->magic_num1[es_ptr->essence]); - } - else - { - sprintf(dummy2, "%-49s %3d/(\?\?)", dummy, es_ptr->value); - } - - c_prt(col, dummy2, ctr + 2, x); - } - } - - /* Hide the list */ - else - { - /* Hide list */ - redraw = FALSE; - screen_load(); - } - - /* Redo asking */ - continue; - } - - if (!use_menu) - { - /* Note verify */ - ask = (isupper(choice)); - - /* Lowercase */ - if (ask) choice = (char)tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - } - - /* Totally Illegal */ - if ((i < 0) || (i >= max_num) || !able[i]) - { - bell(); - continue; - } - - /* Verify it */ - if (ask) - { - char tmp_val[160]; - - /* Prompt */ - (void)strnfmt(tmp_val, 78, _("%sを付加しますか? ", "Add the abilitiy of %s? "), essence_info[num[i]].add_name); - - /* Belay that order */ - if (!get_check(tmp_val)) continue; - } - - /* Stop the loop */ - flag = TRUE; - } - if (redraw) screen_load(); - - if (!flag) return; - - repeat_push(i); - } - es_ptr = &essence_info[num[i]]; - - if (es_ptr->add == ESSENCE_SLAY_GLOVE) - item_tester_tval = TV_GLOVES; - else if (mode == 1 || mode == 5) - item_tester_hook = item_tester_hook_melee_ammo; - else if (es_ptr->add == ESSENCE_ATTACK) - item_tester_hook = object_allow_enchant_weapon; - else if (es_ptr->add == ESSENCE_AC) - item_tester_hook = object_is_armour; - else - item_tester_hook = object_is_weapon_armour_ammo; - - q = _("どのアイテムを改良しますか?", "Improve which item? "); - s = _("改良できるアイテムがありません。", "You have nothing to improve."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT)); - if (!o_ptr) return; - - if ((mode != 10) && (object_is_artifact(o_ptr) || object_is_smith(o_ptr))) - { - msg_print(_("そのアイテムはこれ以上改良できない。", "This item is no more able to be improved.")); - return; - } - - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - - use_essence = es_ptr->value; - if ((o_ptr->tval >= TV_SHOT) && (o_ptr->tval <= TV_BOLT)) use_essence = (use_essence + 9) / 10; - if (o_ptr->number > 1) - { - use_essence *= o_ptr->number; - msg_format(_("%d個あるのでエッセンスは%d必要です。", "It will take %d essences."), o_ptr->number, use_essence); - } - - if (es_ptr->essence != -1) - { - if (p_ptr->magic_num1[es_ptr->essence] < use_essence) - { - msg_print(_("エッセンスが足りない。", "You don't have enough essences.")); - return; - } - if (is_pval_flag(es_ptr->add)) - { - if (o_ptr->pval < 0) - { - msg_print(_("このアイテムの能力修正を強化することはできない。", "You cannot increase magic number of this item.")); - return; - } - else if (es_ptr->add == TR_BLOWS) - { - if (o_ptr->pval > 1) - { - if (!get_check(_("修正値は1になります。よろしいですか?", "The magic number of this weapon will become 1. Are you sure? "))) return; - } - - o_ptr->pval = 1; - msg_format(_("エッセンスを%d個使用します。", "It will take %d essences."), use_essence); - } - else if (o_ptr->pval > 0) - { - use_essence *= o_ptr->pval; - msg_format(_("エッセンスを%d個使用します。", "It will take %d essences."), use_essence); - } - else - { - char tmp[80]; - char tmp_val[160]; - PARAMETER_VALUE pval; - PARAMETER_VALUE limit = MIN(5, p_ptr->magic_num1[es_ptr->essence] / es_ptr->value); - - sprintf(tmp, _("いくつ付加しますか? (1-%d): ", "Enchant how many? (1-%d): "), limit); - strcpy(tmp_val, "1"); - - if (!get_string(tmp, tmp_val, 1)) return; - pval = (PARAMETER_VALUE)atoi(tmp_val); - if (pval > limit) pval = limit; - else if (pval < 1) pval = 1; - o_ptr->pval += pval; - use_essence *= pval; - msg_format(_("エッセンスを%d個使用します。", "It will take %d essences."), use_essence); - } - - if (p_ptr->magic_num1[es_ptr->essence] < use_essence) - { - msg_print(_("エッセンスが足りない。", "You don't have enough essences.")); - return; - } - } - else if (es_ptr->add == ESSENCE_SLAY_GLOVE) - { - char tmp_val[160]; - int val; - HIT_PROB get_to_h; - HIT_POINT get_to_d; - - strcpy(tmp_val, "1"); - if (!get_string(format(_("いくつ付加しますか? (1-%d):", "Enchant how many? (1-%d):"), p_ptr->lev / 7 + 3), tmp_val, 2)) return; - val = atoi(tmp_val); - if (val > p_ptr->lev / 7 + 3) val = p_ptr->lev / 7 + 3; - else if (val < 1) val = 1; - use_essence *= val; - msg_format(_("エッセンスを%d個使用します。", "It will take %d essences."), use_essence); - if (p_ptr->magic_num1[es_ptr->essence] < use_essence) - { - msg_print(_("エッセンスが足りない。", "You don't have enough essences.")); - return; - } - get_to_h = ((val + 1) / 2 + randint0(val / 2 + 1)); - get_to_d = ((val + 1) / 2 + randint0(val / 2 + 1)); - o_ptr->xtra4 = (get_to_h << 8) + get_to_d; - o_ptr->to_h += get_to_h; - o_ptr->to_d += get_to_d; - } - p_ptr->magic_num1[es_ptr->essence] -= use_essence; - if (es_ptr->add == ESSENCE_ATTACK) - { - if ((o_ptr->to_h >= p_ptr->lev / 5 + 5) && (o_ptr->to_d >= p_ptr->lev / 5 + 5)) - { - msg_print(_("改良に失敗した。", "You failed to enchant.")); - take_turn(p_ptr, 100); - return; - } - else - { - if (o_ptr->to_h < p_ptr->lev / 5 + 5) o_ptr->to_h++; - if (o_ptr->to_d < p_ptr->lev / 5 + 5) o_ptr->to_d++; - } - } - else if (es_ptr->add == ESSENCE_AC) - { - if (o_ptr->to_a >= p_ptr->lev / 5 + 5) - { - msg_print(_("改良に失敗した。", "You failed to enchant.")); - take_turn(p_ptr, 100); - return; - } - else - { - if (o_ptr->to_a < p_ptr->lev / 5 + 5) o_ptr->to_a++; - } - } - else - { - o_ptr->xtra3 = es_ptr->add + 1; - } - } - else - { - bool success = TRUE; - - switch (es_ptr->add) - { - case ESSENCE_SH_FIRE: - if ((p_ptr->magic_num1[TR_BRAND_FIRE] < use_essence) || (p_ptr->magic_num1[TR_RES_FIRE] < use_essence)) - { - success = FALSE; - break; - } - p_ptr->magic_num1[TR_BRAND_FIRE] -= use_essence; - p_ptr->magic_num1[TR_RES_FIRE] -= use_essence; - break; - case ESSENCE_SH_ELEC: - if ((p_ptr->magic_num1[TR_BRAND_ELEC] < use_essence) || (p_ptr->magic_num1[TR_RES_ELEC] < use_essence)) - { - success = FALSE; - break; - } - p_ptr->magic_num1[TR_BRAND_ELEC] -= use_essence; - p_ptr->magic_num1[TR_RES_ELEC] -= use_essence; - break; - case ESSENCE_SH_COLD: - if ((p_ptr->magic_num1[TR_BRAND_COLD] < use_essence) || (p_ptr->magic_num1[TR_RES_COLD] < use_essence)) - { - success = FALSE; - break; - } - p_ptr->magic_num1[TR_BRAND_COLD] -= use_essence; - p_ptr->magic_num1[TR_RES_COLD] -= use_essence; - break; - case ESSENCE_RESISTANCE: - case ESSENCE_SUSTAIN: - if ((p_ptr->magic_num1[TR_RES_ACID] < use_essence) || (p_ptr->magic_num1[TR_RES_ELEC] < use_essence) || (p_ptr->magic_num1[TR_RES_FIRE] < use_essence) || (p_ptr->magic_num1[TR_RES_COLD] < use_essence)) - { - success = FALSE; - break; - } - p_ptr->magic_num1[TR_RES_ACID] -= use_essence; - p_ptr->magic_num1[TR_RES_ELEC] -= use_essence; - p_ptr->magic_num1[TR_RES_FIRE] -= use_essence; - p_ptr->magic_num1[TR_RES_COLD] -= use_essence; - break; - } - if (!success) - { - msg_print(_("エッセンスが足りない。", "You don't have enough essences.")); - return; - } - if (es_ptr->add == ESSENCE_SUSTAIN) - { - add_flag(o_ptr->art_flags, TR_IGNORE_ACID); - add_flag(o_ptr->art_flags, TR_IGNORE_ELEC); - add_flag(o_ptr->art_flags, TR_IGNORE_FIRE); - add_flag(o_ptr->art_flags, TR_IGNORE_COLD); - } - else - { - o_ptr->xtra3 = es_ptr->add + 1; - } - } - - take_turn(p_ptr, 100); - msg_format(_("%sに%sの能力を付加しました。", "You have added ability of %s to %s."), o_name, es_ptr->add_name); - p_ptr->update |= (PU_COMBINE | PU_REORDER); - p_ptr->window |= (PW_INVEN); -} - -/*! - * @brief エッセンスを消去する - * @return なし - */ -static void erase_essence(void) -{ - OBJECT_IDX item; - concptr q, s; - object_type *o_ptr; - GAME_TEXT o_name[MAX_NLEN]; - BIT_FLAGS flgs[TR_FLAG_SIZE]; - - item_tester_hook = object_is_smith; - - q = _("どのアイテムのエッセンスを消去しますか?", "Remove from which item? "); - s = _("エッセンスを付加したアイテムがありません。", "You have nothing to remove essence."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR)); - if (!o_ptr) return; - - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - if (!get_check(format(_("よろしいですか? [%s]", "Are you sure? [%s]"), o_name))) return; - - take_turn(p_ptr, 100); - - if (o_ptr->xtra3 == 1 + ESSENCE_SLAY_GLOVE) - { - o_ptr->to_h -= (o_ptr->xtra4 >> 8); - o_ptr->to_d -= (o_ptr->xtra4 & 0x000f); - o_ptr->xtra4 = 0; - if (o_ptr->to_h < 0) o_ptr->to_h = 0; - if (o_ptr->to_d < 0) o_ptr->to_d = 0; - } - o_ptr->xtra3 = 0; - object_flags(o_ptr, flgs); - if (!(have_pval_flags(flgs))) o_ptr->pval = 0; - msg_print(_("エッセンスを取り去った。", "You removed all essence you have added.")); - p_ptr->update |= (PU_COMBINE | PU_REORDER); - p_ptr->window |= (PW_INVEN); -} - -/*! - * @brief 鍛冶コマンドのメインルーチン - * @param only_browse TRUEならばエッセンス一覧の表示のみを行う - * @return なし - */ -void do_cmd_kaji(bool only_browse) -{ - COMMAND_CODE mode = 0; - char choice; - - COMMAND_CODE menu_line = (use_menu ? 1 : 0); - - if (!only_browse) - { - if (cmd_limit_confused(p_ptr)) return; - if (p_ptr->blind) - { - msg_print(_("目が見えなくて作業できない!", "You are blind!")); - return; - } - if (p_ptr->image) - { - msg_print(_("うまく見えなくて作業できない!", "You are hallucinating!")); - return; - } - } - - if (!(repeat_pull(&mode) && 1 <= mode && mode <= 5)) - { - if (only_browse) screen_save(); - do { - if (!only_browse) screen_save(); - if (use_menu) - { - while (!mode) - { -#ifdef JP - prt(format(" %s エッセンス一覧", (menu_line == 1) ? "》" : " "), 2, 14); - prt(format(" %s エッセンス抽出", (menu_line == 2) ? "》" : " "), 3, 14); - prt(format(" %s エッセンス消去", (menu_line == 3) ? "》" : " "), 4, 14); - prt(format(" %s エッセンス付加", (menu_line == 4) ? "》" : " "), 5, 14); - prt(format(" %s 武器/防具強化", (menu_line == 5) ? "》" : " "), 6, 14); - prt(format("どの種類の技術を%sますか?", only_browse ? "調べ" : "使い"), 0, 0); -#else - prt(format(" %s List essences", (menu_line == 1) ? "> " : " "), 2, 14); - prt(format(" %s Extract essence", (menu_line == 2) ? "> " : " "), 3, 14); - prt(format(" %s Remove essence", (menu_line == 3) ? "> " : " "), 4, 14); - prt(format(" %s Add essence", (menu_line == 4) ? "> " : " "), 5, 14); - prt(format(" %s Enchant weapon/armor", (menu_line == 5) ? "> " : " "), 6, 14); - prt(format("Choose command from menu."), 0, 0); -#endif - choice = inkey(); - switch (choice) - { - case ESCAPE: - case 'z': - case 'Z': - screen_load(); - return; - case '2': - case 'j': - case 'J': - menu_line++; - break; - case '8': - case 'k': - case 'K': - menu_line += 4; - break; - case '\r': - case '\n': - case 'x': - case 'X': - mode = menu_line; - break; - } - if (menu_line > 5) menu_line -= 5; - } - } - - else - { - while (!mode) - { - prt(_(" a) エッセンス一覧", " a) List essences"), 2, 14); - prt(_(" b) エッセンス抽出", " b) Extract essence"), 3, 14); - prt(_(" c) エッセンス消去", " c) Remove essence"), 4, 14); - prt(_(" d) エッセンス付加", " d) Add essence"), 5, 14); - prt(_(" e) 武器/防具強化", " e) Enchant weapon/armor"), 6, 14); -#ifdef JP - if (!get_com(format("どの能力を%sますか:", only_browse ? "調べ" : "使い"), &choice, TRUE)) -#else - if (!get_com("Command :", &choice, TRUE)) -#endif - { - screen_load(); - return; - } - switch (choice) - { - case 'A': - case 'a': - mode = 1; - break; - case 'B': - case 'b': - mode = 2; - break; - case 'C': - case 'c': - mode = 3; - break; - case 'D': - case 'd': - mode = 4; - break; - case 'E': - case 'e': - mode = 5; - break; - } - } - } - - if (only_browse) - { - char temp[62 * 5]; - int line, j; - - /* Clear lines, position cursor (really should use strlen here) */ - Term_erase(14, 21, 255); - Term_erase(14, 20, 255); - Term_erase(14, 19, 255); - Term_erase(14, 18, 255); - Term_erase(14, 17, 255); - Term_erase(14, 16, 255); - - roff_to_buf(kaji_tips[mode - 1], 62, temp, sizeof(temp)); - for (j = 0, line = 17; temp[j]; j += (1 + strlen(&temp[j]))) - { - prt(&temp[j], line, 15); - line++; - } - mode = 0; - } - if (!only_browse) screen_load(); - } while (only_browse); - repeat_push(mode); - } - switch (mode) - { - case 1: display_essence(); break; - case 2: drain_essence(); break; - case 3: erase_essence(); break; - case 4: - mode = choose_essence(); - if (mode == 0) - break; - add_essence(mode); - break; - case 5: add_essence(10); break; - } -} diff --git a/src/cmd-smith.h b/src/cmd-smith.h deleted file mode 100644 index 8348c5903..000000000 --- a/src/cmd-smith.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -extern void do_cmd_kaji(bool only_browse); diff --git a/src/cmd-spell.c b/src/cmd-spell.c deleted file mode 100644 index 99e92360f..000000000 --- a/src/cmd-spell.c +++ /dev/null @@ -1,1446 +0,0 @@ -/*! - @file cmd-spell.c - @brief 魔法のインターフェイスと発動 / Purpose: Do everything for each spell - @date 2013/12/31 - @author - 2013 Deskull rearranged comment for Doxygen. - */ - -#include "angband.h" -#include "selfinfo.h" -#include "spells-summon.h" -#include "realm-arcane.h" -#include "realm-chaos.h" -#include "realm-craft.h" -#include "realm-crusade.h" -#include "realm-daemon.h" -#include "realm-death.h" -#include "realm-hex.h" -#include "realm-hissatsu.h" -#include "realm-life.h" -#include "realm-nature.h" -#include "realm-song.h" -#include "realm-sorcery.h" -#include "realm-trump.h" -#include "angband.h" -#include "avatar.h" -#include "player-status.h" -#include "object-hook.h" - -/*! - * @brief - * 魔法の効果を「キャプション:ダイス+定数値」のフォーマットで出力する / Generate dice info string such as "foo 2d10" - * @param str キャプション - * @param dice ダイス数 - * @param sides ダイス目 - * @param base 固定値 - * @return フォーマットに従い整形された文字列 - */ -concptr info_string_dice(concptr str, DICE_NUMBER dice, DICE_SID sides, int base) -{ - /* Fix value */ - if (!dice) - return format("%s%d", str, base); - - /* Dice only */ - else if (!base) - return format("%s%dd%d", str, dice, sides); - - /* Dice plus base value */ - else - return format("%s%dd%d%+d", str, dice, sides, base); -} - - -/*! - * @brief 魔法によるダメージを出力する / Generate damage-dice info string such as "dam 2d10" - * @param dice ダイス数 - * @param sides ダイス目 - * @param base 固定値 - * @return フォーマットに従い整形された文字列 - */ -concptr info_damage(DICE_NUMBER dice, DICE_SID sides, int base) -{ - return info_string_dice(_("損傷:", "dam "), dice, sides, base); -} - -/*! - * @brief 魔法の効果時間を出力する / Generate duration info string such as "dur 20+1d20" - * @param base 固定値 - * @param sides ダイス目 - * @return フォーマットに従い整形された文字列 - */ -concptr info_duration(int base, DICE_SID sides) -{ - return format(_("期間:%d+1d%d", "dur %d+1d%d"), base, sides); -} - -/*! - * @brief 魔法の効果範囲を出力する / Generate range info string such as "range 5" - * @param range 効果範囲 - * @return フォーマットに従い整形された文字列 - */ -concptr info_range(POSITION range) -{ - return format(_("範囲:%d", "range %d"), range); -} - -/*! - * @brief 魔法による回復量を出力する / Generate heal info string such as "heal 2d8" - * @param dice ダイス数 - * @param sides ダイス目 - * @param base 固定値 - * @return フォーマットに従い整形された文字列 - */ -concptr info_heal(DICE_NUMBER dice, DICE_SID sides, int base) -{ - return info_string_dice(_("回復:", "heal "), dice, sides, base); -} - -/*! - * @brief 魔法効果発動までの遅延ターンを出力する / Generate delay info string such as "delay 15+1d15" - * @param base 固定値 - * @param sides ダイス目 - * @return フォーマットに従い整形された文字列 - */ -concptr info_delay(int base, DICE_SID sides) -{ - return format(_("遅延:%d+1d%d", "delay %d+1d%d"), base, sides); -} - - -/*! - * @brief 魔法によるダメージを出力する(固定値&複数回処理) / Generate multiple-damage info string such as "dam 25 each" - * @param dam 固定値 - * @return フォーマットに従い整形された文字列 - */ -concptr info_multi_damage(HIT_POINT dam) -{ - return format(_("損傷:各%d", "dam %d each"), dam); -} - - -/*! - * @brief 魔法によるダメージを出力する(ダイスのみ&複数回処理) / Generate multiple-damage-dice info string such as "dam 5d2 each" - * @param dice ダイス数 - * @param sides ダイス目 - * @return フォーマットに従い整形された文字列 - */ -concptr info_multi_damage_dice(DICE_NUMBER dice, DICE_SID sides) -{ - return format(_("損傷:各%dd%d", "dam %dd%d each"), dice, sides); -} - -/*! - * @brief 魔法による一般的な効力値を出力する(固定値) / Generate power info string such as "power 100" - * @param power 固定値 - * @return フォーマットに従い整形された文字列 - */ -concptr info_power(int power) -{ - return format(_("効力:%d", "power %d"), power); -} - - -/*! - * @brief 魔法による一般的な効力値を出力する(ダイス値) / Generate power info string such as "power 100" - * @param dice ダイス数 - * @param sides ダイス目 - * @return フォーマットに従い整形された文字列 - */ -/* - * Generate power info string such as "power 1d100" - */ -concptr info_power_dice(DICE_NUMBER dice, DICE_SID sides) -{ - return format(_("効力:%dd%d", "power %dd%d"), dice, sides); -} - - -/*! - * @brief 魔法の効果半径を出力する / Generate radius info string such as "rad 100" - * @param rad 効果半径 - * @return フォーマットに従い整形された文字列 - */ -concptr info_radius(POSITION rad) -{ - return format(_("半径:%d", "rad %d"), rad); -} - - -/*! - * @brief 魔法効果の限界重量を出力する / Generate weight info string such as "max wgt 15" - * @param weight 最大重量 - * @return フォーマットに従い整形された文字列 - */ -concptr info_weight(WEIGHT weight) -{ -#ifdef JP - return format("最大重量:%d.%dkg", lbtokg1(weight), lbtokg2(weight)); -#else - return format("max wgt %d", weight/10); -#endif -} - -/*! - * @brief 魔法が利用可能かどうかを返す / - * Determine if a spell is "okay" for the player to cast or study - * The spell must be legible, not forgotten, and also, to cast, - * it must be known, and to study, it must not be known. - * @param spell 呪文ID - * @param learned 使用可能な判定ならばTRUE、学習可能かどうかの判定ならばFALSE - * @param study_pray 祈りの学習判定目的ならばTRUE - * @param use_realm 魔法領域ID - * @return 失敗率(%) - */ -static bool spell_okay(int spell, bool learned, bool study_pray, int use_realm) -{ - const magic_type *s_ptr; - - /* Access the spell */ - if (!is_magic(use_realm)) - { - s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell]; - } - else - { - s_ptr = &mp_ptr->info[use_realm - 1][spell]; - } - - /* Spell is illegal */ - if (s_ptr->slevel > p_ptr->lev) return (FALSE); - - /* Spell is forgotten */ - if ((use_realm == p_ptr->realm2) ? - (p_ptr->spell_forgotten2 & (1L << spell)) : - (p_ptr->spell_forgotten1 & (1L << spell))) - { - /* Never okay */ - return (FALSE); - } - - if (p_ptr->pclass == CLASS_SORCERER) return (TRUE); - if (p_ptr->pclass == CLASS_RED_MAGE) return (TRUE); - - /* Spell is learned */ - if ((use_realm == p_ptr->realm2) ? - (p_ptr->spell_learned2 & (1L << spell)) : - (p_ptr->spell_learned1 & (1L << spell))) - { - /* Always true */ - return (!study_pray); - } - - /* Okay to study, not to cast */ - return (!learned); -} - - -/*! - * @brief 魔法処理のメインルーチン - * @param realm 魔法領域のID - * @param spell 各領域の魔法ID - * @param mode 求める処理 - * @return 各領域魔法に各種テキストを求めた場合は文字列参照ポインタ、そうでない場合はNULLポインタを返す。 - */ -concptr do_spell(REALM_IDX realm, SPELL_IDX spell, BIT_FLAGS mode) -{ - switch (realm) - { - case REALM_LIFE: return do_life_spell(spell, mode); - case REALM_SORCERY: return do_sorcery_spell(spell, mode); - case REALM_NATURE: return do_nature_spell(spell, mode); - case REALM_CHAOS: return do_chaos_spell(spell, mode); - case REALM_DEATH: return do_death_spell(spell, mode); - case REALM_TRUMP: return do_trump_spell(spell, mode); - case REALM_ARCANE: return do_arcane_spell(spell, mode); - case REALM_CRAFT: return do_craft_spell(spell, mode); - case REALM_DAEMON: return do_daemon_spell(spell, mode); - case REALM_CRUSADE: return do_crusade_spell(spell, mode); - case REALM_MUSIC: return do_music_spell(spell, mode); - case REALM_HISSATSU: return do_hissatsu_spell(spell, mode); - case REALM_HEX: return do_hex_spell(spell, mode); - } - - return NULL; -} - - -/*! - * @brief 領域魔法の閲覧、学習、使用選択するインターフェイス処理 - * Allow user to choose a spell/prayer from the given book. - * @param sn 選択した魔法IDを返す参照ポインタ - * @param prompt 魔法を利用する際の動詞表記 - * @param sval 魔道書のsval - * @param learned 閲覧/使用選択ならばTRUE、学習処理ならFALSE - * @param use_realm 魔法領域ID - * @return - *
- * If a valid spell is chosen, saves it in '*sn' and returns TRUE
- * If the user hits escape, returns FALSE, and set '*sn' to -1
- * If there are no legal choices, returns FALSE, and sets '*sn' to -2
- * The "prompt" should be "cast", "recite", or "study"
- * The "known" should be TRUE for cast/pray, FALSE for study
- * 
- */ -static int get_spell(SPELL_IDX *sn, concptr prompt, OBJECT_SUBTYPE_VALUE sval, bool learned, REALM_IDX use_realm) -{ - int i; - SPELL_IDX spell = -1; - int num = 0; - int ask = TRUE; - MANA_POINT need_mana; - SPELL_IDX spells[64]; - bool flag, redraw, okay; - char choice; - const magic_type *s_ptr; - char out_val[160]; - concptr p; - COMMAND_CODE code; -#ifdef JP - char jverb_buf[128]; -#endif - int menu_line = (use_menu ? 1 : 0); - - /* Get the spell, if available */ - if (repeat_pull(&code)) - { - *sn = (SPELL_IDX)code; - /* Verify the spell */ - if (spell_okay(*sn, learned, FALSE, use_realm)) - { - /* Success */ - return (TRUE); - } - } - - p = spell_category_name(mp_ptr->spell_book); - - /* Extract spells */ - for (spell = 0; spell < 32; spell++) - { - /* Check for this spell */ - if ((fake_spell_flags[sval] & (1L << spell))) - { - /* Collect this spell */ - spells[num++] = spell; - } - } - - /* Assume no usable spells */ - okay = FALSE; - - /* Assume no spells available */ - (*sn) = -2; - - /* Check for "okay" spells */ - for (i = 0; i < num; i++) - { - /* Look for "okay" spells */ - if (spell_okay(spells[i], learned, FALSE, use_realm)) okay = TRUE; - } - - /* No "okay" spells */ - if (!okay) return (FALSE); - if (((use_realm) != p_ptr->realm1) && ((use_realm) != p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE)) return FALSE; - if (((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE)) && !is_magic(use_realm)) return FALSE; - if ((p_ptr->pclass == CLASS_RED_MAGE) && ((use_realm) != REALM_ARCANE) && (sval > 1)) return FALSE; - - /* Assume cancelled */ - *sn = (-1); - - /* Nothing chosen yet */ - flag = FALSE; - - /* No redraw yet */ - redraw = FALSE; - - p_ptr->window |= (PW_SPELL); - handle_stuff(); - - /* Build a prompt (accept all spells) */ -#ifdef JP - jverb(prompt, jverb_buf, JVERB_AND); - (void)strnfmt(out_val, 78, "(%^s:%c-%c, '*'で一覧, ESCで中断) どの%sを%^sますか? ", - p, I2A(0), I2A(num - 1), p, jverb_buf); -#else - (void)strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit) %^s which %s? ", - p, I2A(0), I2A(num - 1), prompt, p); -#endif - - choice = (always_show_list || use_menu) ? ESCAPE : 1; - while (!flag) - { - if (choice == ESCAPE) choice = ' '; - else if (!get_com(out_val, &choice, TRUE))break; - - if (use_menu && choice != ' ') - { - switch (choice) - { - case '0': - { - screen_load(); - return FALSE; - } - - case '8': - case 'k': - case 'K': - { - menu_line += (num - 1); - break; - } - - case '2': - case 'j': - case 'J': - { - menu_line++; - break; - } - - case 'x': - case 'X': - case '\r': - case '\n': - { - i = menu_line - 1; - ask = FALSE; - break; - } - } - if (menu_line > num) menu_line -= num; - /* Display a list of spells */ - print_spells(menu_line, spells, num, 1, 15, use_realm); - if (ask) continue; - } - else - { - /* Request redraw */ - if ((choice == ' ') || (choice == '*') || (choice == '?')) - { - /* Show the list */ - if (!redraw) - { - redraw = TRUE; - screen_save(); - - /* Display a list of spells */ - print_spells(menu_line, spells, num, 1, 15, use_realm); - } - - /* Hide the list */ - else - { - if (use_menu) continue; - - /* Hide list */ - redraw = FALSE; - screen_load(); - } - - /* Redo asking */ - continue; - } - - - /* Note verify */ - ask = (isupper(choice)); - - /* Lowercase */ - if (ask) choice = (char)tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - } - - /* Totally Illegal */ - if ((i < 0) || (i >= num)) - { - bell(); - continue; - } - - /* Save the spell index */ - spell = spells[i]; - - /* Require "okay" spells */ - if (!spell_okay(spell, learned, FALSE, use_realm)) - { - bell(); -#ifdef JP - msg_format("その%sを%sことはできません。", p, prompt); -#else - msg_format("You may not %s that %s.", prompt, p); -#endif - - continue; - } - - /* Verify it */ - if (ask) - { - char tmp_val[160]; - - /* Access the spell */ - if (!is_magic(use_realm)) - { - s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell]; - } - else - { - s_ptr = &mp_ptr->info[use_realm - 1][spell]; - } - - /* Extract mana consumption rate */ - if (use_realm == REALM_HISSATSU) - { - need_mana = s_ptr->smana; - } - else - { - need_mana = mod_need_mana(s_ptr->smana, spell, use_realm); - } - - /* Prompt */ -#ifdef JP - jverb(prompt, jverb_buf, JVERB_AND); - /* 英日切り替え機能に対応 */ - (void)strnfmt(tmp_val, 78, "%s(MP%d, 失敗率%d%%)を%sますか? ", - do_spell(use_realm, spell, SPELL_NAME), need_mana, - spell_chance(spell, use_realm), jverb_buf); -#else - (void)strnfmt(tmp_val, 78, "%^s %s (%d mana, %d%% fail)? ", - prompt, do_spell(use_realm, spell, SPELL_NAME), need_mana, - spell_chance(spell, use_realm)); -#endif - - - /* Belay that order */ - if (!get_check(tmp_val)) continue; - } - - /* Stop the loop */ - flag = TRUE; - } - - if (redraw) screen_load(); - - p_ptr->window |= (PW_SPELL); - handle_stuff(); - - /* Abort if needed */ - if (!flag) return FALSE; - - /* Save the choice */ - (*sn) = spell; - - repeat_push((COMMAND_CODE)spell); - - /* Success */ - return TRUE; -} - -/*! - * @brief プレイヤーの職業が練気術師の時、領域魔法と練気術を切り換える処理のインターフェイス - * @param browse_only 魔法と技能の閲覧を行うならばTRUE - * @return 魔道書を一冊も持っていないならTRUEを返す - */ -static void confirm_use_force(bool browse_only) -{ - char which; - COMMAND_CODE code; - - /* Get the item index */ - if (repeat_pull(&code) && (code == INVEN_FORCE)) - { - browse_only ? do_cmd_mind_browse() : do_cmd_mind(); - return; - } - - /* Show the prompt */ - prt(_("('w'練気術, ESC) 'w'かESCを押してください。 ", "(w for the Force, ESC) Hit 'w' or ESC. "), 0, 0); - - while (1) - { - /* Get a key */ - which = inkey(); - - if (which == ESCAPE) break; - else if (which == 'w') - { - repeat_push(INVEN_FORCE); - break; - } - } - - /* Clear the prompt line */ - prt("", 0, 0); - - if (which == 'w') - { - browse_only ? do_cmd_mind_browse() : do_cmd_mind(); - } -} - - -/*! - * @brief プレイヤーの魔法と技能を閲覧するコマンドのメインルーチン / - * Peruse the spells/prayers in a book - * @return なし - * @details - *
- * Note that *all* spells in the book are listed
- *
- * Note that browsing is allowed while confused or blind,
- * and in the dark, primarily to allow browsing in stores.
- * 
- */ -void do_cmd_browse(void) -{ - OBJECT_IDX item; - OBJECT_SUBTYPE_VALUE sval; - REALM_IDX use_realm = 0; - int j, line; - SPELL_IDX spell = -1; - int num = 0; - - SPELL_IDX spells[64]; - char temp[62 * 4]; - - object_type *o_ptr; - - concptr q, s; - - /* Warriors are illiterate */ - if (!(p_ptr->realm1 || p_ptr->realm2) && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE)) - { - msg_print(_("本を読むことができない!", "You cannot read books!")); - return; - } - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - if (p_ptr->pclass == CLASS_FORCETRAINER) - { - if (player_has_no_spellbooks()) - { - confirm_use_force(TRUE); - return; - } - } - - /* Restrict choices to "useful" books */ - if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book; - else item_tester_hook = item_tester_learn_spell; - - q = _("どの本を読みますか? ", "Browse which book? "); - s = _("読める本がない。", "You have no books that you can read."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0))); - if (!o_ptr) - { - if (item == INVEN_FORCE) /* the_force */ - { - do_cmd_mind_browse(); - return; - } - return; - } - - /* Access the item's sval */ - sval = o_ptr->sval; - - use_realm = tval2realm(o_ptr->tval); - - /* Track the object kind */ - object_kind_track(o_ptr->k_idx); - handle_stuff(); - - /* Extract spells */ - for (spell = 0; spell < 32; spell++) - { - /* Check for this spell */ - if ((fake_spell_flags[sval] & (1L << spell))) - { - /* Collect this spell */ - spells[num++] = spell; - } - } - - screen_save(); - prt("", 0, 0); - - /* Keep browsing spells. Exit browsing on cancel. */ - while (TRUE) - { - /* Ask for a spell, allow cancel */ - if (!get_spell(&spell, _("読む", "browse"), o_ptr->sval, TRUE, use_realm)) - { - /* If cancelled, leave immediately. */ - if (spell == -1) break; - - /* Display a list of spells */ - print_spells(0, spells, num, 1, 15, use_realm); - - /* Notify that there's nothing to see, and wait. */ - if (use_realm == REALM_HISSATSU) - prt(_("読める技がない。", "No techniques to browse."), 0, 0); - else - prt(_("読める呪文がない。", "No spells to browse."), 0, 0); - (void)inkey(); - - screen_load(); - - return; - } - - /* Clear lines, position cursor (really should use strlen here) */ - Term_erase(14, 14, 255); - Term_erase(14, 13, 255); - Term_erase(14, 12, 255); - Term_erase(14, 11, 255); - - roff_to_buf(do_spell(use_realm, spell, SPELL_DESC), 62, temp, sizeof(temp)); - - for (j = 0, line = 11; temp[j]; j += 1 + strlen(&temp[j])) - { - prt(&temp[j], line, 15); - line++; - } - } - screen_load(); -} - -/*! - * @brief プレイヤーの第二魔法領域を変更する / - * @param next_realm 変更先の魔法領域ID - * @return なし - */ -static void change_realm2(CHARACTER_IDX next_realm) -{ - int i, j = 0; - char tmp[80]; - - for (i = 0; i < 64; i++) - { - p_ptr->spell_order[j] = p_ptr->spell_order[i]; - if (p_ptr->spell_order[i] < 32) j++; - } - for (; j < 64; j++) - p_ptr->spell_order[j] = 99; - - for (i = 32; i < 64; i++) - { - p_ptr->spell_exp[i] = SPELL_EXP_UNSKILLED; - } - p_ptr->spell_learned2 = 0L; - p_ptr->spell_worked2 = 0L; - p_ptr->spell_forgotten2 = 0L; - - sprintf(tmp, _("魔法の領域を%sから%sに変更した。", "change magic realm from %s to %s."), realm_names[p_ptr->realm2], realm_names[next_realm]); - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp); - p_ptr->old_realm |= 1 << (p_ptr->realm2 - 1); - p_ptr->realm2 = next_realm; - - p_ptr->update |= (PU_REORDER); - p_ptr->update |= (PU_SPELLS); - handle_stuff(); - - /* Load an autopick preference file */ - autopick_load_pref(FALSE); -} - - -/*! - * @brief 魔法を学習するコマンドのメインルーチン / - * Study a book to gain a new spell/prayer - * @return なし - */ -void do_cmd_study(void) -{ - int i; - OBJECT_IDX item; - OBJECT_SUBTYPE_VALUE sval; - int increment = 0; - bool learned = FALSE; - - /* Spells of realm2 will have an increment of +32 */ - SPELL_IDX spell = -1; - - concptr p = spell_category_name(mp_ptr->spell_book); - - object_type *o_ptr; - - concptr q, s; - - if (!p_ptr->realm1) - { - msg_print(_("本を読むことができない!", "You cannot read books!")); - return; - } - - if (p_ptr->blind || no_lite()) - { - msg_print(_("目が見えない!", "You cannot see!")); - return; - } - - if (cmd_limit_confused(p_ptr)) return; - - if (!(p_ptr->new_spells)) - { - msg_format(_("新しい%sを覚えることはできない!", "You cannot learn any new %ss!"), p); - return; - } - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - -#ifdef JP - if (p_ptr->new_spells < 10) { - msg_format("あと %d つの%sを学べる。", p_ptr->new_spells, p); - } - else { - msg_format("あと %d 個の%sを学べる。", p_ptr->new_spells, p); - } -#else - msg_format("You can learn %d new %s%s.", p_ptr->new_spells, p, - (p_ptr->new_spells == 1 ? "" : "s")); -#endif - - msg_print(NULL); - - - /* Restrict choices to "useful" books */ - if (p_ptr->realm2 == REALM_NONE) item_tester_tval = mp_ptr->spell_book; - else item_tester_hook = item_tester_learn_spell; - - q = _("どの本から学びますか? ", "Study which book? "); - s = _("読める本がない。", "You have no books that you can read."); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR)); - if (!o_ptr) return; - - /* Access the item's sval */ - sval = o_ptr->sval; - - if (o_ptr->tval == REALM2_BOOK) increment = 32; - else if (o_ptr->tval != REALM1_BOOK) - { - if (!get_check(_("本当に魔法の領域を変更しますか?", "Really, change magic realm? "))) return; - change_realm2(tval2realm(o_ptr->tval)); - increment = 32; - } - - /* Track the object kind */ - object_kind_track(o_ptr->k_idx); - handle_stuff(); - - /* Mage -- Learn a selected spell */ - if (mp_ptr->spell_book != TV_LIFE_BOOK) - { - /* Ask for a spell, allow cancel */ - if (!get_spell(&spell, _("学ぶ", "study"), sval, FALSE, o_ptr->tval - TV_LIFE_BOOK + 1) && (spell == -1)) return; - } - - /* Priest -- Learn a random prayer */ - else - { - int k = 0; - int gift = -1; - - /* Extract spells */ - for (spell = 0; spell < 32; spell++) - { - /* Check spells in the book */ - if ((fake_spell_flags[sval] & (1L << spell))) - { - /* Skip non "okay" prayers */ - if (!spell_okay(spell, FALSE, TRUE, - (increment ? p_ptr->realm2 : p_ptr->realm1))) continue; - - /* Hack -- Prepare the randomizer */ - k++; - - /* Hack -- Apply the randomizer */ - if (one_in_(k)) gift = spell; - } - } - - /* Accept gift */ - spell = gift; - } - - /* Nothing to study */ - if (spell < 0) - { - msg_format(_("その本には学ぶべき%sがない。", "You cannot learn any %ss in that book."), p); - - /* Abort */ - return; - } - - if (increment) spell += increment; - - /* Learn the spell */ - if (spell < 32) - { - if (p_ptr->spell_learned1 & (1L << spell)) learned = TRUE; - else p_ptr->spell_learned1 |= (1L << spell); - } - else - { - if (p_ptr->spell_learned2 & (1L << (spell - 32))) learned = TRUE; - else p_ptr->spell_learned2 |= (1L << (spell - 32)); - } - - if (learned) - { - int max_exp = (spell < 32) ? SPELL_EXP_MASTER : SPELL_EXP_EXPERT; - int old_exp = p_ptr->spell_exp[spell]; - int new_rank = EXP_LEVEL_UNSKILLED; - concptr name = do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME); - - if (old_exp >= max_exp) - { - msg_format(_("その%sは完全に使いこなせるので学ぶ必要はない。", "You don't need to study this %s anymore."), p); - return; - } -#ifdef JP - if (!get_check(format("%sの%sをさらに学びます。よろしいですか?", name, p))) -#else - if (!get_check(format("You will study a %s of %s again. Are you sure? ", p, name))) -#endif - { - return; - } - else if (old_exp >= SPELL_EXP_EXPERT) - { - p_ptr->spell_exp[spell] = SPELL_EXP_MASTER; - new_rank = EXP_LEVEL_MASTER; - } - else if (old_exp >= SPELL_EXP_SKILLED) - { - if (spell >= 32) p_ptr->spell_exp[spell] = SPELL_EXP_EXPERT; - else p_ptr->spell_exp[spell] += SPELL_EXP_EXPERT - SPELL_EXP_SKILLED; - new_rank = EXP_LEVEL_EXPERT; - } - else if (old_exp >= SPELL_EXP_BEGINNER) - { - p_ptr->spell_exp[spell] = SPELL_EXP_SKILLED + (old_exp - SPELL_EXP_BEGINNER) * 2 / 3; - new_rank = EXP_LEVEL_SKILLED; - } - else - { - p_ptr->spell_exp[spell] = SPELL_EXP_BEGINNER + old_exp / 3; - new_rank = EXP_LEVEL_BEGINNER; - } - msg_format(_("%sの熟練度が%sに上がった。", "Your proficiency of %s is now %s rank."), name, exp_level_str[new_rank]); - } - else - { - /* Find the next open entry in "p_ptr->spell_order[]" */ - for (i = 0; i < 64; i++) - { - /* Stop at the first empty space */ - if (p_ptr->spell_order[i] == 99) break; - } - - /* Add the spell to the known list */ - p_ptr->spell_order[i++] = spell; - - /* Mention the result */ -#ifdef JP - /* 英日切り替え機能に対応 */ - if (mp_ptr->spell_book == TV_MUSIC_BOOK) - { - msg_format("%sを学んだ。", - do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME)); - } - else - { - msg_format("%sの%sを学んだ。", - do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME), p); - } -#else - msg_format("You have learned the %s of %s.", - p, do_spell(increment ? p_ptr->realm2 : p_ptr->realm1, spell % 32, SPELL_NAME)); -#endif - } - - take_turn(p_ptr, 100); - - switch (mp_ptr->spell_book) - { - case TV_LIFE_BOOK: - chg_virtue(V_FAITH, 1); - break; - case TV_DEATH_BOOK: - chg_virtue(V_UNLIFE, 1); - break; - case TV_NATURE_BOOK: - chg_virtue(V_NATURE, 1); - break; - default: - chg_virtue(V_KNOWLEDGE, 1); - break; - } - - sound(SOUND_STUDY); - - /* One less spell available */ - p_ptr->learned_spells++; - - /* Update Study */ - p_ptr->update |= (PU_SPELLS); - update_creature(p_ptr); - - /* Redraw object recall */ - p_ptr->window |= (PW_OBJECT); -} - - -/*! - * @brief 魔法を詠唱するコマンドのメインルーチン / - * Cast a spell - * @return なし - */ -void do_cmd_cast(void) -{ - OBJECT_IDX item; - OBJECT_SUBTYPE_VALUE sval; - SPELL_IDX spell; - REALM_IDX realm; - int chance; - int increment = 0; - REALM_IDX use_realm; - MANA_POINT need_mana; - - concptr prayer; - object_type *o_ptr; - const magic_type *s_ptr; - concptr q, s; - - bool over_exerted = FALSE; - - /* Require spell ability */ - if (!p_ptr->realm1 && (p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE)) - { - msg_print(_("呪文を唱えられない!", "You cannot cast spells!")); - return; - } - - /* Require lite */ - if (p_ptr->blind || no_lite()) - { - if (p_ptr->pclass == CLASS_FORCETRAINER) confirm_use_force(FALSE); - else - { - msg_print(_("目が見えない!", "You cannot see!")); - flush(); - } - return; - } - - if (cmd_limit_confused(p_ptr)) return; - - /* Hex */ - if (p_ptr->realm1 == REALM_HEX) - { - if (hex_spell_fully()) - { - bool flag = FALSE; - msg_print(_("これ以上新しい呪文を詠唱することはできない。", "Can not spell new spells more.")); - flush(); - if (p_ptr->lev >= 35) flag = stop_hex_spell(); - if (!flag) return; - } - } - - if (p_ptr->pclass == CLASS_FORCETRAINER) - { - if (player_has_no_spellbooks()) - { - confirm_use_force(FALSE); - return; - } - } - - prayer = spell_category_name(mp_ptr->spell_book); - - /* Restrict choices to spell books */ - item_tester_tval = mp_ptr->spell_book; - - q = _("どの呪文書を使いますか? ", "Use which book? "); - s = _("呪文書がない!", "You have no spell books!"); - - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | (p_ptr->pclass == CLASS_FORCETRAINER ? USE_FORCE : 0))); - if (!o_ptr) - { - if (item == INVEN_FORCE) /* the_force */ - { - do_cmd_mind(); - return; - } - return; - } - - /* Access the item's sval */ - sval = o_ptr->sval; - - if ((p_ptr->pclass != CLASS_SORCERER) && (p_ptr->pclass != CLASS_RED_MAGE) && (o_ptr->tval == REALM2_BOOK)) increment = 32; - - /* Track the object kind */ - object_kind_track(o_ptr->k_idx); - handle_stuff(); - - if ((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE)) - realm = o_ptr->tval - TV_LIFE_BOOK + 1; - else if (increment) realm = p_ptr->realm2; - else realm = p_ptr->realm1; - - /* Ask for a spell */ -#ifdef JP - if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_MUSIC_BOOK) ? "歌う" : "唱える"), - sval, TRUE, realm)) - { - if (spell == -2) msg_format("その本には知っている%sがない。", prayer); - return; - } -#else - if (!get_spell(&spell, ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"), - sval, TRUE, realm)) - { - if (spell == -2) - msg_format("You don't know any %ss in that book.", prayer); - return; - } -#endif - - - use_realm = tval2realm(o_ptr->tval); - - /* Hex */ - if (use_realm == REALM_HEX) - { - if (hex_spelling(spell)) - { - msg_print(_("その呪文はすでに詠唱中だ。", "You are already casting it.")); - return; - } - } - - if (!is_magic(use_realm)) - { - s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell]; - } - else - { - s_ptr = &mp_ptr->info[realm - 1][spell]; - } - - /* Extract mana consumption rate */ - need_mana = mod_need_mana(s_ptr->smana, spell, realm); - - /* Verify "dangerous" spells */ - if (need_mana > p_ptr->csp) - { - if (flush_failure) flush(); - - /* Warning */ -#ifdef JP - msg_format("その%sを%sのに十分なマジックポイントがない。", prayer, - ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "詠唱する" : (mp_ptr->spell_book == TV_LIFE_BOOK) ? "歌う" : "唱える")); -#else - msg_format("You do not have enough mana to %s this %s.", - ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"), - prayer); -#endif - - - if (!over_exert) return; - - /* Verify */ - if (!get_check_strict(_("それでも挑戦しますか? ", "Attempt it anyway? "), CHECK_OKAY_CANCEL)) return; - } - - /* Spell failure chance */ - chance = spell_chance(spell, use_realm); - - /* Sufficient mana */ - if (need_mana <= p_ptr->csp) - { - /* Use some mana */ - p_ptr->csp -= need_mana; - } - else over_exerted = TRUE; - p_ptr->redraw |= (PR_MANA); - - /* Failed spell */ - if (randint0(100) < chance) - { - if (flush_failure) flush(); - - msg_format(_("%sをうまく唱えられなかった!", "You failed to get the %s off!"), prayer); - sound(SOUND_FAIL); - - switch (realm) - { - case REALM_LIFE: - if (randint1(100) < chance) chg_virtue(V_VITALITY, -1); - break; - case REALM_DEATH: - if (randint1(100) < chance) chg_virtue(V_UNLIFE, -1); - break; - case REALM_NATURE: - if (randint1(100) < chance) chg_virtue(V_NATURE, -1); - break; - case REALM_DAEMON: - if (randint1(100) < chance) chg_virtue(V_JUSTICE, 1); - break; - case REALM_CRUSADE: - if (randint1(100) < chance) chg_virtue(V_JUSTICE, -1); - break; - case REALM_HEX: - if (randint1(100) < chance) chg_virtue(V_COMPASSION, -1); - break; - default: - if (randint1(100) < chance) chg_virtue(V_KNOWLEDGE, -1); - break; - } - - /* Failure casting may activate some side effect */ - do_spell(realm, spell, SPELL_FAIL); - - - if ((o_ptr->tval == TV_CHAOS_BOOK) && (randint1(100) < spell)) - { - msg_print(_("カオス的な効果を発生した!", "You produce a chaotic effect!")); - wild_magic(spell); - } - else if ((o_ptr->tval == TV_DEATH_BOOK) && (randint1(100) < spell)) - { - if ((sval == 3) && one_in_(2)) - { - sanity_blast(0, TRUE); - } - else - { - msg_print(_("痛い!", "It hurts!")); - take_hit(DAMAGE_LOSELIFE, damroll(o_ptr->sval + 1, 6), _("暗黒魔法の逆流", "a miscast Death spell"), -1); - - if ((spell > 15) && one_in_(6) && !p_ptr->hold_exp) - lose_exp(spell * 250); - } - } - else if ((o_ptr->tval == TV_MUSIC_BOOK) && (randint1(200) < spell)) - { - msg_print(_("いやな音が響いた", "An infernal sound echoed.")); - aggravate_monsters(0); - } - if (randint1(100) >= chance) - chg_virtue(V_CHANCE, -1); - } - - /* Process spell */ - else - { - /* Canceled spells cost neither a current_world_ptr->game_turn nor mana */ - if (!do_spell(realm, spell, SPELL_CAST)) return; - - if (randint1(100) < chance) - chg_virtue(V_CHANCE, 1); - - /* A spell was cast */ - if (!(increment ? - (p_ptr->spell_worked2 & (1L << spell)) : - (p_ptr->spell_worked1 & (1L << spell))) - && (p_ptr->pclass != CLASS_SORCERER) - && (p_ptr->pclass != CLASS_RED_MAGE)) - { - int e = s_ptr->sexp; - - /* The spell worked */ - if (realm == p_ptr->realm1) - { - p_ptr->spell_worked1 |= (1L << spell); - } - else - { - p_ptr->spell_worked2 |= (1L << spell); - } - - /* Gain experience */ - gain_exp(e * s_ptr->slevel); - - /* Redraw object recall */ - p_ptr->window |= (PW_OBJECT); - - switch (realm) - { - case REALM_LIFE: - chg_virtue(V_TEMPERANCE, 1); - chg_virtue(V_COMPASSION, 1); - chg_virtue(V_VITALITY, 1); - chg_virtue(V_DILIGENCE, 1); - break; - case REALM_DEATH: - chg_virtue(V_UNLIFE, 1); - chg_virtue(V_JUSTICE, -1); - chg_virtue(V_FAITH, -1); - chg_virtue(V_VITALITY, -1); - break; - case REALM_DAEMON: - chg_virtue(V_JUSTICE, -1); - chg_virtue(V_FAITH, -1); - chg_virtue(V_HONOUR, -1); - chg_virtue(V_TEMPERANCE, -1); - break; - case REALM_CRUSADE: - chg_virtue(V_FAITH, 1); - chg_virtue(V_JUSTICE, 1); - chg_virtue(V_SACRIFICE, 1); - chg_virtue(V_HONOUR, 1); - break; - case REALM_NATURE: - chg_virtue(V_NATURE, 1); - chg_virtue(V_HARMONY, 1); - break; - case REALM_HEX: - chg_virtue(V_JUSTICE, -1); - chg_virtue(V_FAITH, -1); - chg_virtue(V_HONOUR, -1); - chg_virtue(V_COMPASSION, -1); - break; - default: - chg_virtue(V_KNOWLEDGE, 1); - break; - } - } - switch (realm) - { - case REALM_LIFE: - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, 1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, 1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, 1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_DILIGENCE, 1); - break; - case REALM_DEATH: - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_UNLIFE, 1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_VITALITY, -1); - break; - case REALM_DAEMON: - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_TEMPERANCE, -1); - break; - case REALM_CRUSADE: - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, 1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, 1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_SACRIFICE, 1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, 1); - break; - case REALM_NATURE: - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_NATURE, 1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HARMONY, 1); - break; - case REALM_HEX: - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_JUSTICE, -1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_FAITH, -1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_HONOUR, -1); - if (randint1(100 + p_ptr->lev) < need_mana) chg_virtue(V_COMPASSION, -1); - break; - } - if (mp_ptr->spell_xtra & MAGIC_GAIN_EXP) - { - s16b cur_exp = p_ptr->spell_exp[(increment ? 32 : 0) + spell]; - s16b exp_gain = 0; - - if (cur_exp < SPELL_EXP_BEGINNER) - exp_gain += 60; - else if (cur_exp < SPELL_EXP_SKILLED) - { - if ((current_floor_ptr->dun_level > 4) && ((current_floor_ptr->dun_level + 10) > p_ptr->lev)) - exp_gain = 8; - } - else if (cur_exp < SPELL_EXP_EXPERT) - { - if (((current_floor_ptr->dun_level + 5) > p_ptr->lev) && ((current_floor_ptr->dun_level + 5) > s_ptr->slevel)) - exp_gain = 2; - } - else if ((cur_exp < SPELL_EXP_MASTER) && !increment) - { - if (((current_floor_ptr->dun_level + 5) > p_ptr->lev) && (current_floor_ptr->dun_level > s_ptr->slevel)) - exp_gain = 1; - } - p_ptr->spell_exp[(increment ? 32 : 0) + spell] += exp_gain; - } - } - - take_turn(p_ptr, 100); - - - /* Over-exert the player */ - if (over_exerted) - { - int oops = need_mana; - - /* No mana left */ - p_ptr->csp = 0; - p_ptr->csp_frac = 0; - - msg_print(_("精神を集中しすぎて気を失ってしまった!", "You faint from the effort!")); - - /* Hack -- Bypass free action */ - (void)set_paralyzed(p_ptr->paralyzed + randint1(5 * oops + 1)); - - switch (realm) - { - case REALM_LIFE: - chg_virtue(V_VITALITY, -10); - break; - case REALM_DEATH: - chg_virtue(V_UNLIFE, -10); - break; - case REALM_DAEMON: - chg_virtue(V_JUSTICE, 10); - break; - case REALM_NATURE: - chg_virtue(V_NATURE, -10); - break; - case REALM_CRUSADE: - chg_virtue(V_JUSTICE, -10); - break; - case REALM_HEX: - chg_virtue(V_COMPASSION, 10); - break; - default: - chg_virtue(V_KNOWLEDGE, -10); - break; - } - - /* Damage CON (possibly permanently) */ - if (randint0(100) < 50) - { - bool perm = (randint0(100) < 25); - - msg_print(_("体を悪くしてしまった!", "You have damaged your health!")); - - /* Reduce constitution */ - (void)dec_stat(A_CON, 15 + randint1(10), perm); - } - } - - p_ptr->window |= (PW_PLAYER); - p_ptr->window |= (PW_SPELL); -} diff --git a/src/cmd-spell.h b/src/cmd-spell.h deleted file mode 100644 index 9e1ebefc2..000000000 --- a/src/cmd-spell.h +++ /dev/null @@ -1,24 +0,0 @@ -#define KWD_DAM _("損傷:", "dam ") -#define KWD_RANGE _("射程:", "rng ") -#define KWD_DURATION _("期間:", "dur ") -#define KWD_SPHERE _("範囲:", "range ") -#define KWD_HEAL _("回復:", "heal ") -#define KWD_RANDOM _("ランダム", "random") - -extern concptr info_string_dice(concptr str, DICE_NUMBER dice, DICE_SID sides, int base); -extern concptr info_damage(DICE_NUMBER dice, DICE_SID sides, int base); -extern concptr info_duration(int base, DICE_SID sides); -extern concptr info_range(POSITION range); -extern concptr info_heal(DICE_NUMBER dice, DICE_SID sides, int base); -extern concptr info_delay(int base, DICE_SID sides); -extern concptr info_multi_damage(HIT_POINT dam); -extern concptr info_multi_damage_dice(DICE_NUMBER dice, DICE_SID sides); -extern concptr info_power(int power); -extern concptr info_power_dice(DICE_NUMBER dice, DICE_SID sides); -extern concptr info_radius(POSITION rad); -extern concptr info_weight(WEIGHT weight); - -/* cmd5.c */ -extern void do_cmd_browse(void); -extern void do_cmd_study(void); -extern void do_cmd_cast(void); diff --git a/src/cmd-usestaff.c b/src/cmd-usestaff.c deleted file mode 100644 index 4ab7403f4..000000000 --- a/src/cmd-usestaff.c +++ /dev/null @@ -1,447 +0,0 @@ -#include "angband.h" -#include "projection.h" -#include "spells-summon.h" -#include "avatar.h" -#include "player-status.h" -#include "spells-status.h" - - - -/*! -* @brief 杖の効果を発動する -* @param sval オブジェクトのsval -* @param use_charge 使用回数を消費したかどうかを返す参照ポインタ -* @param powerful 強力発動上の処理ならばTRUE -* @param magic 魔道具術上の処理ならばTRUE -* @param known 判明済ならばTRUE -* @return 発動により効果内容が確定したならばTRUEを返す -*/ -int staff_effect(OBJECT_SUBTYPE_VALUE sval, bool *use_charge, bool powerful, bool magic, bool known) -{ - int k; - int ident = FALSE; - PLAYER_LEVEL lev = powerful ? p_ptr->lev * 2 : p_ptr->lev; - POSITION detect_rad = powerful ? DETECT_RAD_DEFAULT * 3 / 2 : DETECT_RAD_DEFAULT; - - /* Analyze the staff */ - switch (sval) - { - case SV_STAFF_DARKNESS: - { - if (!(p_ptr->resist_blind) && !(p_ptr->resist_dark)) - { - if (set_blind(p_ptr->blind + 3 + randint1(5))) ident = TRUE; - } - if (unlite_area(10, (powerful ? 6 : 3))) ident = TRUE; - break; - } - - case SV_STAFF_SLOWNESS: - { - if (set_slow(p_ptr->slow + randint1(30) + 15, FALSE)) ident = TRUE; - break; - } - - case SV_STAFF_HASTE_MONSTERS: - { - if (speed_monsters()) ident = TRUE; - break; - } - - case SV_STAFF_SUMMONING: - { - const int times = randint1(powerful ? 8 : 4); - for (k = 0; k < times; k++) - { - if (summon_specific(0, p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0')) - { - ident = TRUE; - } - } - break; - } - - case SV_STAFF_TELEPORTATION: - { - teleport_player((powerful ? 150 : 100), 0L); - ident = TRUE; - break; - } - - case SV_STAFF_IDENTIFY: - { - if (powerful) { - if (!identify_fully(FALSE)) *use_charge = FALSE; - } - else { - if (!ident_spell(FALSE)) *use_charge = FALSE; - } - ident = TRUE; - break; - } - - case SV_STAFF_REMOVE_CURSE: - { - bool result = powerful ? remove_all_curse() : remove_curse(); - if (result) - { - ident = TRUE; - } - break; - } - - case SV_STAFF_STARLITE: - ident = starlight(magic); - break; - - case SV_STAFF_LITE: - { - if (lite_area(damroll(2, 8), (powerful ? 4 : 2))) ident = TRUE; - break; - } - - case SV_STAFF_MAPPING: - { - map_area(powerful ? DETECT_RAD_MAP * 3 / 2 : DETECT_RAD_MAP); - ident = TRUE; - break; - } - - case SV_STAFF_DETECT_GOLD: - { - if (detect_treasure(detect_rad)) ident = TRUE; - if (detect_objects_gold(detect_rad)) ident = TRUE; - break; - } - - case SV_STAFF_DETECT_ITEM: - { - if (detect_objects_normal(detect_rad)) ident = TRUE; - break; - } - - case SV_STAFF_DETECT_TRAP: - { - if (detect_traps(detect_rad, known)) ident = TRUE; - break; - } - - case SV_STAFF_DETECT_DOOR: - { - if (detect_doors(detect_rad)) ident = TRUE; - if (detect_stairs(detect_rad)) ident = TRUE; - break; - } - - case SV_STAFF_DETECT_INVIS: - { - if (detect_monsters_invis(detect_rad)) ident = TRUE; - break; - } - - case SV_STAFF_DETECT_EVIL: - { - if (detect_monsters_evil(detect_rad)) ident = TRUE; - break; - } - - case SV_STAFF_CURE_LIGHT: - { - ident = cure_light_wounds((powerful ? 4 : 2), 8); - break; - } - - case SV_STAFF_CURING: - { - ident = true_healing(0); - if (set_shero(0, TRUE)) ident = TRUE; - break; - } - - case SV_STAFF_HEALING: - { - if (cure_critical_wounds(powerful ? 500 : 300)) ident = TRUE; - break; - } - - case SV_STAFF_THE_MAGI: - { - if (do_res_stat(A_INT)) ident = TRUE; - ident |= restore_mana(FALSE); - if (set_shero(0, TRUE)) ident = TRUE; - break; - } - - case SV_STAFF_SLEEP_MONSTERS: - { - if (sleep_monsters(lev)) ident = TRUE; - break; - } - - case SV_STAFF_SLOW_MONSTERS: - { - if (slow_monsters(lev)) ident = TRUE; - break; - } - - case SV_STAFF_SPEED: - { - if (set_fast(randint1(30) + (powerful ? 30 : 15), FALSE)) ident = TRUE; - break; - } - - case SV_STAFF_PROBING: - { - ident = probing(); - break; - } - - case SV_STAFF_DISPEL_EVIL: - { - ident = dispel_evil(powerful ? 120 : 80); - break; - } - - case SV_STAFF_POWER: - { - ident = dispel_monsters(powerful ? 225 : 150) ; - break; - } - - case SV_STAFF_HOLINESS: - { - ident = cleansing_nova(p_ptr, magic, powerful); - break; - } - - case SV_STAFF_GENOCIDE: - { - ident = symbol_genocide((magic ? lev + 50 : 200), TRUE); - break; - } - - case SV_STAFF_EARTHQUAKES: - { - if (earthquake(p_ptr->y, p_ptr->x, (powerful ? 15 : 10))) - ident = TRUE; - else - msg_print(_("ダンジョンが揺れた。", "The dungeon trembles.")); - - break; - } - - case SV_STAFF_DESTRUCTION: - { - ident = destroy_area(p_ptr->y, p_ptr->x, (powerful ? 18 : 13) + randint0(5), FALSE); - break; - } - - case SV_STAFF_ANIMATE_DEAD: - { - ident = animate_dead(0, p_ptr->y, p_ptr->x); - break; - } - - case SV_STAFF_MSTORM: - { - ident = unleash_mana_storm(p_ptr, powerful); - break; - } - - case SV_STAFF_NOTHING: - { - msg_print(_("何も起らなかった。", "Nothing happen.")); - if (prace_is_(RACE_SKELETON) || prace_is_(RACE_GOLEM) || - prace_is_(RACE_ZOMBIE) || prace_is_(RACE_SPECTRE)) - msg_print(_("もったいない事をしたような気がする。食べ物は大切にしなくては。", "What a waste. It's your food!")); - break; - } - } - return ident; -} - -/*! - * @brief 杖を使うコマンドのサブルーチン / - * Use a staff. -RAK- - * @param item 使うオブジェクトの所持品ID - * @return なし - * @details - * One charge of one staff disappears. - * Hack -- staffs of identify can be "cancelled". - */ -void do_cmd_use_staff_aux(INVENTORY_IDX item) -{ - int ident, chance, lev; - object_type *o_ptr; - - - /* Hack -- let staffs of identify get aborted */ - bool use_charge = TRUE; - - - /* Get the item (in the pack) */ - if (item >= 0) - { - o_ptr = &inventory[item]; - } - - /* Get the item (on the floor) */ - else - { - o_ptr = ¤t_floor_ptr->o_list[0 - item]; - } - - - /* Mega-Hack -- refuse to use a pile from the ground */ - if ((item < 0) && (o_ptr->number > 1)) - { - msg_print(_("まずは杖を拾わなければ。", "You must first pick up the staffs.")); - return; - } - - - take_turn(p_ptr, 100); - - /* Extract the item level */ - lev = k_info[o_ptr->k_idx].level; - if (lev > 50) lev = 50 + (lev - 50) / 2; - - /* Base chance of success */ - chance = p_ptr->skill_dev; - - /* Confusion hurts skill */ - if (p_ptr->confused) chance = chance / 2; - - /* Hight level objects are harder */ - chance = chance - lev; - - /* Give everyone a (slight) chance */ - if ((chance < USE_DEVICE) && one_in_(USE_DEVICE - chance + 1)) - { - chance = USE_DEVICE; - } - - if (cmd_limit_time_walk(p_ptr)) return; - - /* Roll for usage */ - if ((chance < USE_DEVICE) || (randint1(chance) < USE_DEVICE) || (p_ptr->pclass == CLASS_BERSERKER)) - { - if (flush_failure) flush(); - msg_print(_("杖をうまく使えなかった。", "You failed to use the staff properly.")); - sound(SOUND_FAIL); - return; - } - - /* Notice empty staffs */ - if (o_ptr->pval <= 0) - { - if (flush_failure) flush(); - msg_print(_("この杖にはもう魔力が残っていない。", "The staff has no charges left.")); - o_ptr->ident |= (IDENT_EMPTY); - p_ptr->update |= (PU_COMBINE | PU_REORDER); - p_ptr->window |= (PW_INVEN); - - return; - } - - - sound(SOUND_ZAP); - - ident = staff_effect(o_ptr->sval, &use_charge, FALSE, FALSE, object_is_aware(o_ptr)); - - if (!(object_is_aware(o_ptr))) - { - chg_virtue(V_PATIENCE, -1); - chg_virtue(V_CHANCE, 1); - chg_virtue(V_KNOWLEDGE, -1); - } - p_ptr->update |= (PU_COMBINE | PU_REORDER); - - /* Tried the item */ - object_tried(o_ptr); - - /* An identification was made */ - if (ident && !object_is_aware(o_ptr)) - { - object_aware(o_ptr); - gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); - } - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - - /* Hack -- some uses are "free" */ - if (!use_charge) return; - - - /* Use a single charge */ - o_ptr->pval--; - - /* XXX Hack -- unstack if necessary */ - if ((item >= 0) && (o_ptr->number > 1)) - { - object_type forge; - object_type *q_ptr; - q_ptr = &forge; - - /* Obtain a local object */ - object_copy(q_ptr, o_ptr); - - /* Modify quantity */ - q_ptr->number = 1; - - /* Restore the charges */ - o_ptr->pval++; - - /* Unstack the used item */ - o_ptr->number--; - p_ptr->total_weight -= q_ptr->weight; - item = inven_carry(q_ptr); - - msg_print(_("杖をまとめなおした。", "You unstack your staff.")); - } - - /* Describe charges in the pack */ - if (item >= 0) - { - inven_item_charges(item); - } - - /* Describe charges on the floor */ - else - { - floor_item_charges(0 - item); - } -} - -/*! -* @brief 杖を使うコマンドのメインルーチン / -* @return なし -*/ -void do_cmd_use_staff(void) -{ - OBJECT_IDX item; - concptr q, s; - - if (p_ptr->wild_mode) - { - return; - } - - if (cmd_limit_arena(p_ptr)) return; - - if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) - { - set_action(ACTION_NONE); - } - - /* Restrict choices to wands */ - item_tester_tval = TV_STAFF; - - q = _("どの杖を使いますか? ", "Use which staff? "); - s = _("使える杖がない。", "You have no staff to use."); - - if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - do_cmd_use_staff_aux(item); -} diff --git a/src/cmd-usestaff.h b/src/cmd-usestaff.h deleted file mode 100644 index 79bf8bfd0..000000000 --- a/src/cmd-usestaff.h +++ /dev/null @@ -1,3 +0,0 @@ -extern int staff_effect(OBJECT_SUBTYPE_VALUE sval, bool *use_charge, bool powerful, bool magic, bool known); -extern void do_cmd_use_staff_aux(INVENTORY_IDX item); -extern void do_cmd_use_staff(void); diff --git a/src/cmd-visual/cmd-draw.c b/src/cmd-visual/cmd-draw.c new file mode 100644 index 000000000..0393f85a6 --- /dev/null +++ b/src/cmd-visual/cmd-draw.c @@ -0,0 +1,287 @@ +#include "cmd-visual/cmd-draw.h" +#include "core/asking-player.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "io/files-util.h" +#include "io/input-key-acceptor.h" +#include "main/sound-of-music.h" +#include "player/player-race-types.h" +#include "player/process-name.h" +#include "racial/racial-android.h" +#include "term/gameterm.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/int-char-converter.h" +#include "util/string-processor.h" +#include "view/display-messages.h" +#include "view/display-player.h" // 暫定。後で消す. +#include "world/world.h" + +/*! + * @brief 画面を再描画するコマンドのメインルーチン + * Hack -- redraw the screen + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + * @details + *
+ * This command performs various low level updates, clears all the "extra"
+ * windows, does a total redraw of the main window, and requests all of the
+ * interesting updates and redraws that I can think of.
+ *
+ * This command is also used to "instantiate" the results of the user
+ * selecting various things, such as graphics mode, so it must call
+ * the "TERM_XTRA_REACT" hook before redrawing the windows.
+ * 
+ */ +void do_cmd_redraw(player_type *creature_ptr) +{ + term_xtra(TERM_XTRA_REACT, 0); + + creature_ptr->update |= (PU_COMBINE | PU_REORDER); + creature_ptr->update |= (PU_TORCH); + creature_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS); + creature_ptr->update |= (PU_UN_VIEW | PU_UN_LITE); + creature_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE); + creature_ptr->update |= (PU_MONSTERS); + + creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY); + + creature_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER); + creature_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_DUNGEON | PW_MONSTER | PW_OBJECT); + + update_playtime(); + handle_stuff(creature_ptr); + if (creature_ptr->prace == RACE_ANDROID) calc_android_exp(creature_ptr); + + term_type *old = Term; + for (int j = 0; j < 8; j++) + { + if (!angband_term[j]) continue; + + term_activate(angband_term[j]); + term_redraw(); + term_fresh(); + term_activate(old); + } +} + + +/*! + * @brief プレイヤーのステータス表示 + * @return なし + */ +void do_cmd_player_status(player_type *creature_ptr) +{ + int mode = 0; + char tmp[160]; + screen_save(); + while (TRUE) + { + update_playtime(); + display_player(creature_ptr, mode); + + if (mode == 4) + { + mode = 0; + display_player(creature_ptr, mode); + } + + term_putstr(2, 23, -1, TERM_WHITE, + _("['c'で名前変更, 'f'でファイルへ書出, 'h'でモード変更, ESCで終了]", "['c' to change name, 'f' to file, 'h' to change mode, or ESC]")); + char c = inkey(); + if (c == ESCAPE) break; + + if (c == 'c') + { + get_name(creature_ptr); + process_player_name(creature_ptr, FALSE); + } + else if (c == 'f') + { + sprintf(tmp, "%s.txt", creature_ptr->base_name); + if (get_string(_("ファイル名: ", "File name: "), tmp, 80)) + { + if (tmp[0] && (tmp[0] != ' ')) + { + file_character(creature_ptr, tmp, update_playtime, display_player); + } + } + } + else if (c == 'h') + { + mode++; + } + else + { + bell(); + } + + msg_erase(); + } + + screen_load(); + creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY); + handle_stuff(creature_ptr); +} + + +/*! + * @brief 最近表示されたメッセージを再表示するコマンドのメインルーチン + * Recall the most recent message + * @return なし + */ +void do_cmd_message_one(void) +{ + prt(format("> %s", message_str(0)), 0, 0); +} + + +/*! + * @brief メッセージのログを表示するコマンドのメインルーチン + * Recall the most recent message + * @return なし + * @details + *
+ * Show previous messages to the user	-BEN-
+ *
+ * The screen format uses line 0 and 23 for headers and prompts,
+ * skips line 1 and 22, and uses line 2 thru 21 for old messages.
+ *
+ * This command shows you which commands you are viewing, and allows
+ * you to "search" for strings in the recall.
+ *
+ * Note that messages may be longer than 80 characters, but they are
+ * displayed using "infinite" length, with a special sub-command to
+ * "slide" the virtual display to the left or right.
+ *
+ * Attempt to only hilite the matching portions of the string.
+ * 
+ */ +void do_cmd_messages(int num_now) +{ + char shower_str[81]; + char finder_str[81]; + char back_str[81]; + concptr shower = NULL; + int wid, hgt; + term_get_size(&wid, &hgt); + int num_lines = hgt - 4; + strcpy(finder_str, ""); + strcpy(shower_str, ""); + int n = message_num(); + int i = 0; + screen_save(); + term_clear(); + while (TRUE) + { + int j; + int skey; + for (j = 0; (j < num_lines) && (i + j < n); j++) + { + concptr msg = message_str(i + j); + c_prt((i + j < num_now ? TERM_WHITE : TERM_SLATE), msg, num_lines + 1 - j, 0); + if (!shower || !shower[0]) continue; + + concptr str = msg; + while ((str = angband_strstr(str, shower)) != NULL) + { + int len = strlen(shower); + term_putstr(str - msg, num_lines + 1 - j, len, TERM_YELLOW, shower); + str += len; + } + } + + for (; j < num_lines; j++) + term_erase(0, num_lines + 1 - j, 255); + + prt(format(_("以前のメッセージ %d-%d 全部で(%d)", "Message Recall (%d-%d of %d)"), + i, i + j - 1, n), 0, 0); + prt(_("[ 'p' で更に古いもの, 'n' で更に新しいもの, '/' で検索, ESC で中断 ]", + "[Press 'p' for older, 'n' for newer, ..., or ESCAPE]"), hgt - 1, 0); + skey = inkey_special(TRUE); + if (skey == ESCAPE) break; + + j = i; + switch (skey) + { + case '=': + prt(_("強調: ", "Show: "), hgt - 1, 0); + strcpy(back_str, shower_str); + if (askfor(shower_str, 80)) + shower = shower_str[0] ? shower_str : NULL; + else + strcpy(shower_str, back_str); + + continue; + case '/': + case KTRL('s'): + { + prt(_("検索: ", "Find: "), hgt - 1, 0); + strcpy(back_str, finder_str); + if (!askfor(finder_str, 80)) + { + strcpy(finder_str, back_str); + continue; + } + else if (!finder_str[0]) + { + shower = NULL; + continue; + } + + shower = finder_str; + for (int z = i + 1; z < n; z++) + { + concptr msg = message_str(z); + if (angband_strstr(msg, finder_str)) + { + i = z; + break; + } + } + } + + break; + + case SKEY_TOP: + i = n - num_lines; + break; + case SKEY_BOTTOM: + i = 0; + break; + case '8': + case SKEY_UP: + case '\n': + case '\r': + i = MIN(i + 1, n - num_lines); + break; + case '+': + i = MIN(i + 10, n - num_lines); + break; + case 'p': + case KTRL('P'): + case ' ': + case SKEY_PGUP: + i = MIN(i + num_lines, n - num_lines); + break; + case 'n': + case KTRL('N'): + case SKEY_PGDOWN: + i = MAX(0, i - num_lines); + break; + case '-': + i = MAX(0, i - 10); + break; + case '2': + case SKEY_DOWN: + i = MAX(0, i - 1); + break; + } + + if (i == j) bell(); + } + + screen_load(); +} diff --git a/src/cmd-visual/cmd-draw.h b/src/cmd-visual/cmd-draw.h new file mode 100644 index 000000000..dda5a86a2 --- /dev/null +++ b/src/cmd-visual/cmd-draw.h @@ -0,0 +1,8 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_redraw(player_type *creature_ptr); +void do_cmd_player_status(player_type *creature_ptr); +void do_cmd_message_one(void); +void do_cmd_messages(int num_now); diff --git a/src/cmd-visual/cmd-map.c b/src/cmd-visual/cmd-map.c new file mode 100644 index 000000000..f38620af4 --- /dev/null +++ b/src/cmd-visual/cmd-map.c @@ -0,0 +1,65 @@ +#include "cmd-visual/cmd-map.h" +#include "autopick/autopick-methods-table.h" +#include "autopick/autopick-util.h" +#include "io/input-key-acceptor.h" +#include "term/screen-processor.h" +#include "view/display-map.h" +#include "window/main-window-util.h" + +/* + * Display a "small-scale" map of the dungeon for the player + * + * Currently, the "player" is displayed on the map. + */ +void do_cmd_view_map(player_type *player_ptr) +{ + screen_save(); + prt(_("お待ち下さい...", "Please wait..."), 0, 0); + term_fresh(); + term_clear(); + display_autopick = 0; + + int cy, cx; + display_map(player_ptr, &cy, &cx); + if ((max_autopick == 0) || player_ptr->wild_mode) { + put_str(_("何かキーを押すとゲームに戻ります", "Hit any key to continue"), 23, 30); + move_cursor(cy, cx); + inkey(); + screen_load(); + return; + } + + display_autopick = ITEM_DISPLAY; + while (TRUE) { + int wid, hgt; + term_get_size(&wid, &hgt); + int row_message = hgt - 1; + put_str(_("何かキーを押してください('M':拾う 'N':放置 'D':M+N 'K':壊すアイテムを表示)", + " Hit M, N(for ~), K(for !), or D(same as M+N) to display auto-picker items."), + row_message, 1); + move_cursor(cy, cx); + int i = inkey(); + byte flag; + if ('M' == i) + flag = (DO_AUTOPICK | DO_QUERY_AUTOPICK); + else if ('N' == i) + flag = DONT_AUTOPICK; + else if ('K' == i) + flag = DO_AUTODESTROY; + else if ('D' == i) + flag = (DO_AUTOPICK | DO_QUERY_AUTOPICK | DONT_AUTOPICK); + else + break; + + term_fresh(); + if (~display_autopick & flag) + display_autopick |= flag; + else + display_autopick &= ~flag; + + display_map(player_ptr, &cy, &cx); + } + + display_autopick = 0; + screen_load(); +} diff --git a/src/cmd-visual/cmd-map.h b/src/cmd-visual/cmd-map.h new file mode 100644 index 000000000..4b4bd2482 --- /dev/null +++ b/src/cmd-visual/cmd-map.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_view_map(player_type *player_ptr); diff --git a/src/cmd-visual/cmd-visuals.c b/src/cmd-visual/cmd-visuals.c new file mode 100644 index 000000000..26241ec70 --- /dev/null +++ b/src/cmd-visual/cmd-visuals.c @@ -0,0 +1,443 @@ +#include "cmd-visual/cmd-visuals.h" +#include "cmd-visual/cmd-draw.h" +#include "core/asking-player.h" +#include "core/visuals-reseter.h" +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "flavor/object-flavor.h" +#include "game-option/special-options.h" +#include "io/files-util.h" +#include "io/input-key-acceptor.h" +#include "io/read-pref-file.h" +#include "knowledge/knowledge-features.h" +#include "knowledge/knowledge-items.h" +#include "knowledge/knowledge-monsters.h" +#include "knowledge/lighting-level-table.h" +#include "main/sound-of-music.h" +#include "monster-race/monster-race.h" +#include "object/object-generator.h" +#include "object/object-kind.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/angband-files.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" + +/*! + * @brief キャラクタのビジュアルIDを変更する際の対象指定関数 + * @param i 指定対象となるキャラクタコード + * @param num 指定されたビジュアルIDを返す参照ポインタ + * @param max ビジュアルIDの最大数 + * @return 指定が実際に行われた場合TRUE、キャンセルされた場合FALSE + */ +static bool cmd_visuals_aux(int i, IDX *num, IDX max) +{ + if (iscntrl(i)) { + char str[10] = ""; + sprintf(str, "%d", *num); + if (!get_string(format("Input new number(0-%d): ", max - 1), str, 4)) + return FALSE; + + IDX tmp = (IDX)strtol(str, NULL, 0); + if (tmp >= 0 && tmp < max) + *num = tmp; + } else if (isupper(i)) + *num = (*num + max - 1) % max; + else + *num = (*num + 1) % max; + + return TRUE; +} + +/*! + * @brief キャラクタの変更メニュー表示 + * @param choice_msg 選択メッセージ + * @return なし + */ +static void print_visuals_menu(concptr choice_msg) +{ + prt(_("[ 画面表示の設定 ]", "Interact with Visuals"), 1, 0); + prt(_("(0) ユーザー設定ファイルのロード", "(0) Load a user pref file"), 3, 5); + prt(_("(1) モンスターの 色/文字 をファイルに書き出す", "(1) Dump monster attr/chars"), 4, 5); + prt(_("(2) アイテムの 色/文字 をファイルに書き出す", "(2) Dump object attr/chars"), 5, 5); + prt(_("(3) 地形の 色/文字 をファイルに書き出す", "(3) Dump feature attr/chars"), 6, 5); + prt(_("(4) モンスターの 色/文字 を変更する (数値操作)", "(4) Change monster attr/chars (numeric operation)"), 7, 5); + prt(_("(5) アイテムの 色/文字 を変更する (数値操作)", "(5) Change object attr/chars (numeric operation)"), 8, 5); + prt(_("(6) 地形の 色/文字 を変更する (数値操作)", "(6) Change feature attr/chars (numeric operation)"), 9, 5); + prt(_("(7) モンスターの 色/文字 を変更する (シンボルエディタ)", "(7) Change monster attr/chars (visual mode)"), 10, 5); + prt(_("(8) アイテムの 色/文字 を変更する (シンボルエディタ)", "(8) Change object attr/chars (visual mode)"), 11, 5); + prt(_("(9) 地形の 色/文字 を変更する (シンボルエディタ)", "(9) Change feature attr/chars (visual mode)"), 12, 5); + prt(_("(R) 画面表示方法の初期化", "(R) Reset visuals"), 13, 5); + prt(format("コマンド: %s", choice_msg ? choice_msg : _("", "")), 15, 0); +} + +/* + * Interact with "visuals" + */ +void do_cmd_visuals(player_type *creature_ptr, void (*process_autopick_file_command)(char *)) +{ + FILE *auto_dump_stream; + char tmp[160]; + char buf[1024]; + bool need_redraw = FALSE; + concptr empty_symbol = "<< ? >>"; + if (use_bigtile) + empty_symbol = "<< ?? >>"; + + screen_save(); + while (TRUE) { + term_clear(); + print_visuals_menu(NULL); + int i = inkey(); + if (i == ESCAPE) + break; + + switch (i) { + case '0': { + prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 15, 0); + prt(_("ファイル: ", "File: "), 17, 0); + sprintf(tmp, "%s.prf", creature_ptr->base_name); + if (!askfor(tmp, 70)) + continue; + + (void)process_pref_file(creature_ptr, tmp, process_autopick_file_command); + need_redraw = TRUE; + break; + } + case '1': { + static concptr mark = "Monster attr/chars"; + prt(_("コマンド: モンスターの[色/文字]をファイルに書き出します", "Command: Dump monster attr/chars"), 15, 0); + prt(_("ファイル: ", "File: "), 17, 0); + sprintf(tmp, "%s.prf", creature_ptr->base_name); + if (!askfor(tmp, 70)) + continue; + + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp); + if (!open_auto_dump(&auto_dump_stream, buf, mark)) + continue; + + auto_dump_printf(auto_dump_stream, _("\n# モンスターの[色/文字]の設定\n\n", "\n# Monster attr/char definitions\n\n")); + for (i = 0; i < max_r_idx; i++) { + monster_race *r_ptr = &r_info[i]; + if (!r_ptr->name) + continue; + + auto_dump_printf(auto_dump_stream, "# %s\n", (r_name + r_ptr->name)); + auto_dump_printf(auto_dump_stream, "R:%d:0x%02X/0x%02X\n\n", i, (byte)(r_ptr->x_attr), (byte)(r_ptr->x_char)); + } + + close_auto_dump(&auto_dump_stream, mark); + msg_print(_("モンスターの[色/文字]をファイルに書き出しました。", "Dumped monster attr/chars.")); + break; + } + case '2': { + static concptr mark = "Object attr/chars"; + prt(_("コマンド: アイテムの[色/文字]をファイルに書き出します", "Command: Dump object attr/chars"), 15, 0); + prt(_("ファイル: ", "File: "), 17, 0); + sprintf(tmp, "%s.prf", creature_ptr->base_name); + if (!askfor(tmp, 70)) + continue; + + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp); + if (!open_auto_dump(&auto_dump_stream, buf, mark)) + continue; + + auto_dump_printf(auto_dump_stream, _("\n# アイテムの[色/文字]の設定\n\n", "\n# Object attr/char definitions\n\n")); + for (KIND_OBJECT_IDX k_idx = 0; k_idx < max_k_idx; k_idx++) { + GAME_TEXT o_name[MAX_NLEN]; + object_kind *k_ptr = &k_info[k_idx]; + if (!k_ptr->name) + continue; + + if (!k_ptr->flavor) { + strip_name(o_name, k_idx); + } else { + object_type forge; + object_prep(creature_ptr, &forge, k_idx); + describe_flavor(creature_ptr, o_name, &forge, OD_FORCE_FLAVOR); + } + + auto_dump_printf(auto_dump_stream, "# %s\n", o_name); + auto_dump_printf(auto_dump_stream, "K:%d:0x%02X/0x%02X\n\n", (int)k_idx, (byte)(k_ptr->x_attr), (byte)(k_ptr->x_char)); + } + + close_auto_dump(&auto_dump_stream, mark); + msg_print(_("アイテムの[色/文字]をファイルに書き出しました。", "Dumped object attr/chars.")); + break; + } + case '3': { + static concptr mark = "Feature attr/chars"; + prt(_("コマンド: 地形の[色/文字]をファイルに書き出します", "Command: Dump feature attr/chars"), 15, 0); + prt(_("ファイル: ", "File: "), 17, 0); + sprintf(tmp, "%s.prf", creature_ptr->base_name); + if (!askfor(tmp, 70)) + continue; + + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp); + if (!open_auto_dump(&auto_dump_stream, buf, mark)) + continue; + + auto_dump_printf(auto_dump_stream, _("\n# 地形の[色/文字]の設定\n\n", "\n# Feature attr/char definitions\n\n")); + for (i = 0; i < max_f_idx; i++) { + feature_type *f_ptr = &f_info[i]; + if (!f_ptr->name) + continue; + if (f_ptr->mimic != i) + continue; + + auto_dump_printf(auto_dump_stream, "# %s\n", (f_name + f_ptr->name)); + auto_dump_printf(auto_dump_stream, "F:%d:0x%02X/0x%02X:0x%02X/0x%02X:0x%02X/0x%02X\n\n", i, (byte)(f_ptr->x_attr[F_LIT_STANDARD]), + (byte)(f_ptr->x_char[F_LIT_STANDARD]), (byte)(f_ptr->x_attr[F_LIT_LITE]), (byte)(f_ptr->x_char[F_LIT_LITE]), + (byte)(f_ptr->x_attr[F_LIT_DARK]), (byte)(f_ptr->x_char[F_LIT_DARK])); + } + + close_auto_dump(&auto_dump_stream, mark); + msg_print(_("地形の[色/文字]をファイルに書き出しました。", "Dumped feature attr/chars.")); + break; + } + case '4': { + static concptr choice_msg = _("モンスターの[色/文字]を変更します", "Change monster attr/chars"); + static MONRACE_IDX r = 0; + prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0); + while (TRUE) { + monster_race *r_ptr = &r_info[r]; + int c; + IDX t; + + TERM_COLOR da = r_ptr->d_attr; + byte dc = r_ptr->d_char; + TERM_COLOR ca = r_ptr->x_attr; + byte cc = r_ptr->x_char; + + term_putstr(5, 17, -1, TERM_WHITE, format(_("モンスター = %d, 名前 = %-40.40s", "Monster = %d, Name = %-40.40s"), r, (r_name + r_ptr->name))); + term_putstr(10, 19, -1, TERM_WHITE, format(_("初期値 色 / 文字 = %3u / %3u", "Default attr/char = %3u / %3u"), da, dc)); + term_putstr(40, 19, -1, TERM_WHITE, empty_symbol); + term_queue_bigchar(43, 19, da, dc, 0, 0); + term_putstr(10, 20, -1, TERM_WHITE, format(_("現在値 色 / 文字 = %3u / %3u", "Current attr/char = %3u / %3u"), ca, cc)); + term_putstr(40, 20, -1, TERM_WHITE, empty_symbol); + term_queue_bigchar(43, 20, ca, cc, 0, 0); + term_putstr(0, 22, -1, TERM_WHITE, _("コマンド (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ")); + i = inkey(); + if (i == ESCAPE) + break; + + if (iscntrl(i)) + c = 'a' + i - KTRL('A'); + else if (isupper(i)) + c = 'a' + i - 'A'; + else + c = i; + + switch (c) { + case 'n': { + IDX prev_r = r; + do { + if (!cmd_visuals_aux(i, &r, max_r_idx)) { + r = prev_r; + break; + } + } while (!r_info[r].name); + } + + break; + case 'a': + t = (int)r_ptr->x_attr; + (void)cmd_visuals_aux(i, &t, 256); + r_ptr->x_attr = (byte)t; + need_redraw = TRUE; + break; + case 'c': + t = (int)r_ptr->x_char; + (void)cmd_visuals_aux(i, &t, 256); + r_ptr->x_char = (byte)t; + need_redraw = TRUE; + break; + case 'v': + do_cmd_knowledge_monsters(creature_ptr, &need_redraw, TRUE, r); + term_clear(); + print_visuals_menu(choice_msg); + break; + } + } + + break; + } + case '5': { + static concptr choice_msg = _("アイテムの[色/文字]を変更します", "Change object attr/chars"); + static IDX k = 0; + prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0); + while (TRUE) { + object_kind *k_ptr = &k_info[k]; + int c; + IDX t; + + TERM_COLOR da = k_ptr->d_attr; + SYMBOL_CODE dc = k_ptr->d_char; + TERM_COLOR ca = k_ptr->x_attr; + SYMBOL_CODE cc = k_ptr->x_char; + + term_putstr(5, 17, -1, TERM_WHITE, + format( + _("アイテム = %d, 名前 = %-40.40s", "Object = %d, Name = %-40.40s"), k, k_name + (!k_ptr->flavor ? k_ptr->name : k_ptr->flavor_name))); + term_putstr(10, 19, -1, TERM_WHITE, format(_("初期値 色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc)); + term_putstr(40, 19, -1, TERM_WHITE, empty_symbol); + term_queue_bigchar(43, 19, da, dc, 0, 0); + term_putstr(10, 20, -1, TERM_WHITE, format(_("現在値 色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc)); + term_putstr(40, 20, -1, TERM_WHITE, empty_symbol); + term_queue_bigchar(43, 20, ca, cc, 0, 0); + term_putstr(0, 22, -1, TERM_WHITE, _("コマンド (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ")); + + i = inkey(); + if (i == ESCAPE) + break; + + if (iscntrl(i)) + c = 'a' + i - KTRL('A'); + else if (isupper(i)) + c = 'a' + i - 'A'; + else + c = i; + + switch (c) { + case 'n': { + IDX prev_k = k; + do { + if (!cmd_visuals_aux(i, &k, max_k_idx)) { + k = prev_k; + break; + } + } while (!k_info[k].name); + } + + break; + case 'a': + t = (int)k_ptr->x_attr; + (void)cmd_visuals_aux(i, &t, 256); + k_ptr->x_attr = (byte)t; + need_redraw = TRUE; + break; + case 'c': + t = (int)k_ptr->x_char; + (void)cmd_visuals_aux(i, &t, 256); + k_ptr->x_char = (byte)t; + need_redraw = TRUE; + break; + case 'v': + do_cmd_knowledge_objects(creature_ptr, &need_redraw, TRUE, k); + term_clear(); + print_visuals_menu(choice_msg); + break; + } + } + + break; + } + case '6': { + static concptr choice_msg = _("地形の[色/文字]を変更します", "Change feature attr/chars"); + static IDX f = 0; + static IDX lighting_level = F_LIT_STANDARD; + prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0); + while (TRUE) { + feature_type *f_ptr = &f_info[f]; + int c; + IDX t; + + TERM_COLOR da = f_ptr->d_attr[lighting_level]; + byte dc = f_ptr->d_char[lighting_level]; + TERM_COLOR ca = f_ptr->x_attr[lighting_level]; + byte cc = f_ptr->x_char[lighting_level]; + + prt("", 17, 5); + term_putstr(5, 17, -1, TERM_WHITE, + format(_("地形 = %d, 名前 = %s, 明度 = %s", "Terrain = %d, Name = %s, Lighting = %s"), f, (f_name + f_ptr->name), + lighting_level_str[lighting_level])); + term_putstr(10, 19, -1, TERM_WHITE, format(_("初期値 色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc)); + term_putstr(40, 19, -1, TERM_WHITE, empty_symbol); + term_queue_bigchar(43, 19, da, dc, 0, 0); + term_putstr(10, 20, -1, TERM_WHITE, format(_("現在値 色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc)); + term_putstr(40, 20, -1, TERM_WHITE, empty_symbol); + term_queue_bigchar(43, 20, ca, cc, 0, 0); + term_putstr(0, 22, -1, TERM_WHITE, + _("コマンド (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ")); + + i = inkey(); + if (i == ESCAPE) + break; + + if (iscntrl(i)) + c = 'a' + i - KTRL('A'); + else if (isupper(i)) + c = 'a' + i - 'A'; + else + c = i; + + switch (c) { + case 'n': { + IDX prev_f = f; + do { + if (!cmd_visuals_aux(i, &f, max_f_idx)) { + f = prev_f; + break; + } + } while (!f_info[f].name || (f_info[f].mimic != f)); + } + + break; + case 'a': + t = (int)f_ptr->x_attr[lighting_level]; + (void)cmd_visuals_aux(i, &t, 256); + f_ptr->x_attr[lighting_level] = (byte)t; + need_redraw = TRUE; + break; + case 'c': + t = (int)f_ptr->x_char[lighting_level]; + (void)cmd_visuals_aux(i, &t, 256); + f_ptr->x_char[lighting_level] = (byte)t; + need_redraw = TRUE; + break; + case 'l': + (void)cmd_visuals_aux(i, &lighting_level, F_LIT_MAX); + break; + case 'd': + apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char); + need_redraw = TRUE; + break; + case 'v': + do_cmd_knowledge_features(&need_redraw, TRUE, f, &lighting_level); + term_clear(); + print_visuals_menu(choice_msg); + break; + } + } + + break; + } + case '7': + do_cmd_knowledge_monsters(creature_ptr, &need_redraw, TRUE, -1); + break; + case '8': + do_cmd_knowledge_objects(creature_ptr, &need_redraw, TRUE, -1); + break; + case '9': { + IDX lighting_level = F_LIT_STANDARD; + do_cmd_knowledge_features(&need_redraw, TRUE, -1, &lighting_level); + break; + } + case 'R': + case 'r': + reset_visuals(creature_ptr, process_autopick_file_command); + msg_print(_("画面上の[色/文字]を初期値にリセットしました。", "Visual attr/char tables reset.")); + need_redraw = TRUE; + break; + default: + bell(); + break; + } + + msg_erase(); + } + + screen_load(); + if (need_redraw) + do_cmd_redraw(creature_ptr); +} diff --git a/src/cmd-visual/cmd-visuals.h b/src/cmd-visual/cmd-visuals.h new file mode 100644 index 000000000..3ab18bac2 --- /dev/null +++ b/src/cmd-visual/cmd-visuals.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void do_cmd_visuals(player_type *creature_ptr, void(*process_autopick_file_command)(char*)); diff --git a/src/cmd-zaprod.c b/src/cmd-zaprod.c deleted file mode 100644 index f7a546688..000000000 --- a/src/cmd-zaprod.c +++ /dev/null @@ -1,417 +0,0 @@ -#include "angband.h" -#include "avatar.h" -#include "spells-status.h" -#include "player-status.h" - -/*! - * @brief ロッドの効果を発動する - * @param sval オブジェクトのsval - * @param dir 発動目標の方向ID - * @param use_charge チャージを消費したかどうかを返す参照ポインタ - * @param powerful 強力発動上の処理ならばTRUE - * @param magic 魔道具術上の処理ならばTRUE - * @return 発動により効果内容が確定したならばTRUEを返す - */ -int rod_effect(OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool *use_charge, bool powerful, bool magic) -{ - int ident = FALSE; - PLAYER_LEVEL lev = powerful ? p_ptr->lev * 2 : p_ptr->lev; - POSITION detect_rad = powerful ? DETECT_RAD_DEFAULT * 3 / 2 : DETECT_RAD_DEFAULT; - POSITION rad = powerful ? 3 : 2; - - /* Unused */ - (void)magic; - - /* Analyze the rod */ - switch (sval) - { - case SV_ROD_DETECT_TRAP: - { - if (detect_traps(detect_rad, (bool)(dir ? FALSE : TRUE))) ident = TRUE; - break; - } - - case SV_ROD_DETECT_DOOR: - { - if (detect_doors(detect_rad)) ident = TRUE; - if (detect_stairs(detect_rad)) ident = TRUE; - break; - } - - case SV_ROD_IDENTIFY: - { - if (powerful) { - if (!identify_fully(FALSE)) *use_charge = FALSE; - } - else { - if (!ident_spell(FALSE)) *use_charge = FALSE; - } - ident = TRUE; - break; - } - - case SV_ROD_RECALL: - { - if (!recall_player(p_ptr, randint0(21) + 15)) *use_charge = FALSE; - ident = TRUE; - break; - } - - case SV_ROD_ILLUMINATION: - { - if (lite_area(damroll(2, 8), (powerful ? 4 : 2))) ident = TRUE; - break; - } - - case SV_ROD_MAPPING: - { - map_area(powerful ? DETECT_RAD_MAP * 3 / 2 : DETECT_RAD_MAP); - ident = TRUE; - break; - } - - case SV_ROD_DETECTION: - { - detect_all(detect_rad); - ident = TRUE; - break; - } - - case SV_ROD_PROBING: - { - probing(); - ident = TRUE; - break; - } - - case SV_ROD_CURING: - { - if (true_healing(0)) ident = TRUE; - if (set_shero(0, TRUE)) ident = TRUE; - break; - } - - case SV_ROD_HEALING: - { - if(cure_critical_wounds(powerful ? 750 : 500)) ident = TRUE; - break; - } - - case SV_ROD_RESTORATION: - { - if(restore_level()) ident = TRUE; - if(restore_all_status()) ident = TRUE; - break; - } - - case SV_ROD_SPEED: - { - if (set_fast(randint1(30) + (powerful ? 30 : 15), FALSE)) ident = TRUE; - break; - } - - case SV_ROD_PESTICIDE: - { - if (dispel_monsters(powerful ? 8 : 4)) ident = TRUE; - break; - } - - case SV_ROD_TELEPORT_AWAY: - { - int distance = MAX_SIGHT * (powerful ? 8 : 5); - if (teleport_monster(dir, distance)) ident = TRUE; - break; - } - - case SV_ROD_DISARMING: - { - if (disarm_trap(dir)) ident = TRUE; - if (powerful && disarm_traps_touch()) ident = TRUE; - break; - } - - case SV_ROD_LITE: - { - HIT_POINT dam = damroll((powerful ? 12 : 6), 8); - msg_print(_("青く輝く光線が放たれた。", "A line of blue shimmering light appears.")); - (void)lite_line(dir, dam); - ident = TRUE; - break; - } - - case SV_ROD_SLEEP_MONSTER: - { - if (sleep_monster(dir, lev)) ident = TRUE; - break; - } - - case SV_ROD_SLOW_MONSTER: - { - if (slow_monster(dir, lev)) ident = TRUE; - break; - } - - case SV_ROD_HYPODYNAMIA: - { - if (hypodynamic_bolt(dir, 70 + 3 * lev / 2)) ident = TRUE; - break; - } - - case SV_ROD_POLYMORPH: - { - if (poly_monster(dir, lev)) ident = TRUE; - break; - } - - case SV_ROD_ACID_BOLT: - { - fire_bolt_or_beam(10, GF_ACID, dir, damroll(6 + lev / 7, 8)); - ident = TRUE; - break; - } - - case SV_ROD_ELEC_BOLT: - { - fire_bolt_or_beam(10, GF_ELEC, dir, damroll(4 + lev / 9, 8)); - ident = TRUE; - break; - } - - case SV_ROD_FIRE_BOLT: - { - fire_bolt_or_beam(10, GF_FIRE, dir, damroll(7 + lev / 6, 8)); - ident = TRUE; - break; - } - - case SV_ROD_COLD_BOLT: - { - fire_bolt_or_beam(10, GF_COLD, dir, damroll(5 + lev / 8, 8)); - ident = TRUE; - break; - } - - case SV_ROD_ACID_BALL: - { - fire_ball(GF_ACID, dir, 60 + lev, rad); - ident = TRUE; - break; - } - - case SV_ROD_ELEC_BALL: - { - fire_ball(GF_ELEC, dir, 40 + lev, rad); - ident = TRUE; - break; - } - - case SV_ROD_FIRE_BALL: - { - fire_ball(GF_FIRE, dir, 70 + lev, rad); - ident = TRUE; - break; - } - - case SV_ROD_COLD_BALL: - { - fire_ball(GF_COLD, dir, 50 + lev, rad); - ident = TRUE; - break; - } - - case SV_ROD_HAVOC: - { - call_chaos(); - ident = TRUE; - break; - } - - case SV_ROD_STONE_TO_MUD: - { - HIT_POINT dam = powerful ? 40 + randint1(60) : 20 + randint1(30); - if (wall_to_mud(dir, dam)) ident = TRUE; - break; - } - - case SV_ROD_AGGRAVATE: - { - aggravate_monsters(0); - ident = TRUE; - break; - } - } - return ident; -} - -/*! -* @brief ロッドを使うコマンドのサブルーチン / -* Activate (zap) a Rod -* @param item 使うオブジェクトの所持品ID -* @return なし -* @details -*
-* Unstack fully charged rods as needed.
-* Hack -- rods of perception/genocide can be "cancelled"
-* All rods can be cancelled at the "Direction?" prompt
-* pvals are defined for each rod in k_info. -LM-
-* 
-*/ -void do_cmd_zap_rod_aux(INVENTORY_IDX item) -{ - int ident, chance, lev, fail; - DIRECTION dir = 0; - object_type *o_ptr; - bool success; - - /* Hack -- let perception get aborted */ - bool use_charge = TRUE; - - object_kind *k_ptr; - - /* Get the item (in the pack) */ - if (item >= 0) - { - o_ptr = &inventory[item]; - } - - /* Get the item (on the floor) */ - else - { - o_ptr = ¤t_floor_ptr->o_list[0 - item]; - } - - - /* Mega-Hack -- refuse to zap a pile from the ground */ - if ((item < 0) && (o_ptr->number > 1)) - { - msg_print(_("まずはロッドを拾わなければ。", "You must first pick up the rods.")); - return; - } - - - /* Get a direction (unless KNOWN not to need it) */ - if (((o_ptr->sval >= SV_ROD_MIN_DIRECTION) && (o_ptr->sval != SV_ROD_HAVOC) && (o_ptr->sval != SV_ROD_AGGRAVATE) && (o_ptr->sval != SV_ROD_PESTICIDE)) || - !object_is_aware(o_ptr)) - { - /* Get a direction, allow cancel */ - if (!get_aim_dir(&dir)) return; - } - - - take_turn(p_ptr, 100); - - /* Extract the item level */ - lev = k_info[o_ptr->k_idx].level; - - /* Base chance of success */ - chance = p_ptr->skill_dev; - - /* Confusion hurts skill */ - if (p_ptr->confused) chance = chance / 2; - - fail = lev + 5; - if (chance > fail) fail -= (chance - fail) * 2; - else chance -= (fail - chance) * 2; - if (fail < USE_DEVICE) fail = USE_DEVICE; - if (chance < USE_DEVICE) chance = USE_DEVICE; - - if (cmd_limit_time_walk(p_ptr)) return; - - if (p_ptr->pclass == CLASS_BERSERKER) success = FALSE; - else if (chance > fail) - { - if (randint0(chance * 2) < fail) success = FALSE; - else success = TRUE; - } - else - { - if (randint0(fail * 2) < chance) success = TRUE; - else success = FALSE; - } - - /* Roll for usage */ - if (!success) - { - if (flush_failure) flush(); - msg_print(_("うまくロッドを使えなかった。", "You failed to use the rod properly.")); - sound(SOUND_FAIL); - return; - } - - k_ptr = &k_info[o_ptr->k_idx]; - - /* A single rod is still charging */ - if ((o_ptr->number == 1) && (o_ptr->timeout)) - { - if (flush_failure) flush(); - msg_print(_("このロッドはまだ魔力を充填している最中だ。", "The rod is still charging.")); - return; - } - /* A stack of rods lacks enough energy. */ - else if ((o_ptr->number > 1) && (o_ptr->timeout > k_ptr->pval * (o_ptr->number - 1))) - { - if (flush_failure) flush(); - msg_print(_("そのロッドはまだ充填中です。", "The rods are all still charging.")); - return; - } - - sound(SOUND_ZAP); - - ident = rod_effect(o_ptr->sval, dir, &use_charge, FALSE, FALSE); - - /* Increase the timeout by the rod kind's pval. -LM- */ - if (use_charge) o_ptr->timeout += k_ptr->pval; - p_ptr->update |= (PU_COMBINE | PU_REORDER); - - if (!(object_is_aware(o_ptr))) - { - chg_virtue(V_PATIENCE, -1); - chg_virtue(V_CHANCE, 1); - chg_virtue(V_KNOWLEDGE, -1); - } - - /* Tried the object */ - object_tried(o_ptr); - - /* Successfully determined the object function */ - if (ident && !object_is_aware(o_ptr)) - { - object_aware(o_ptr); - gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); - } - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); -} - -/*! -* @brief ロッドを使うコマンドのメインルーチン / -* @return なし -*/ -void do_cmd_zap_rod(void) -{ - OBJECT_IDX item; - concptr q, s; - - if (p_ptr->wild_mode) - { - return; - } - - if (cmd_limit_arena(p_ptr)) return; - - if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) - { - set_action(ACTION_NONE); - } - - /* Restrict choices to rods */ - item_tester_tval = TV_ROD; - - q = _("どのロッドを振りますか? ", "Zap which rod? "); - s = _("使えるロッドがない。", "You have no rod to zap."); - - if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Zap the rod */ - do_cmd_zap_rod_aux(item); -} diff --git a/src/cmd-zaprod.h b/src/cmd-zaprod.h deleted file mode 100644 index 2da9499ec..000000000 --- a/src/cmd-zaprod.h +++ /dev/null @@ -1,3 +0,0 @@ -extern int rod_effect(OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool *use_charge, bool powerful, bool magic); -extern void do_cmd_zap_rod_aux(INVENTORY_IDX item); -extern void do_cmd_zap_rod(void); diff --git a/src/cmd-zapwand.c b/src/cmd-zapwand.c deleted file mode 100644 index 8396a446e..000000000 --- a/src/cmd-zapwand.c +++ /dev/null @@ -1,468 +0,0 @@ -#include "angband.h" -#include "avatar.h" -#include "spells-status.h" -#include "player-status.h" - - -/*! -* @brief 魔法棒の効果を発動する -* @param sval オブジェクトのsval -* @param dir 発動の方向ID -* @param powerful 強力発動上の処理ならばTRUE -* @param magic 魔道具術上の処理ならばTRUE -* @return 発動により効果内容が確定したならばTRUEを返す -*/ -bool wand_effect(OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool powerful, bool magic) -{ - bool ident = FALSE; - PLAYER_LEVEL lev = powerful ? p_ptr->lev * 2 : p_ptr->lev; - POSITION rad = powerful ? 3 : 2; - - /* XXX Hack -- Wand of wonder can do anything before it */ - if (sval == SV_WAND_WONDER) - { - int vir = virtue_number(V_CHANCE); - sval = (OBJECT_SUBTYPE_VALUE)randint0(SV_WAND_WONDER); - - if (vir) - { - if (p_ptr->virtues[vir - 1] > 0) - { - while (randint1(300) < p_ptr->virtues[vir - 1]) sval++; - if (sval > SV_WAND_COLD_BALL) sval = randint0(4) + SV_WAND_ACID_BALL; - } - else - { - while (randint1(300) < (0 - p_ptr->virtues[vir - 1])) sval--; - if (sval < SV_WAND_HEAL_MONSTER) sval = randint0(3) + SV_WAND_HEAL_MONSTER; - } - } - if (sval < SV_WAND_TELEPORT_AWAY) - chg_virtue(V_CHANCE, 1); - } - - /* Analyze the wand */ - switch (sval) - { - case SV_WAND_HEAL_MONSTER: - { - HIT_POINT dam = damroll((powerful ? 20 : 10), 10); - if (heal_monster(dir, dam)) ident = TRUE; - break; - } - - case SV_WAND_HASTE_MONSTER: - { - if (speed_monster(dir, lev)) ident = TRUE; - break; - } - - case SV_WAND_CLONE_MONSTER: - { - if (clone_monster(dir)) ident = TRUE; - break; - } - - case SV_WAND_TELEPORT_AWAY: - { - int distance = MAX_SIGHT * (powerful ? 8 : 5); - if (teleport_monster(dir, distance)) ident = TRUE; - break; - } - - case SV_WAND_DISARMING: - { - if (disarm_trap(dir)) ident = TRUE; - if (powerful && disarm_traps_touch()) ident = TRUE; - break; - } - - case SV_WAND_TRAP_DOOR_DEST: - { - if (destroy_door(dir)) ident = TRUE; - if (powerful && destroy_doors_touch()) ident = TRUE; - break; - } - - case SV_WAND_STONE_TO_MUD: - { - HIT_POINT dam = powerful ? 40 + randint1(60) : 20 + randint1(30); - if (wall_to_mud(dir, dam)) ident = TRUE; - break; - } - - case SV_WAND_LITE: - { - HIT_POINT dam = damroll((powerful ? 12 : 6), 8); - msg_print(_("青く輝く光線が放たれた。", "A line of blue shimmering light appears.")); - (void)lite_line(dir, dam); - ident = TRUE; - break; - } - - case SV_WAND_SLEEP_MONSTER: - { - if (sleep_monster(dir, lev)) ident = TRUE; - break; - } - - case SV_WAND_SLOW_MONSTER: - { - if (slow_monster(dir, lev)) ident = TRUE; - break; - } - - case SV_WAND_CONFUSE_MONSTER: - { - if (confuse_monster(dir, lev)) ident = TRUE; - break; - } - - case SV_WAND_FEAR_MONSTER: - { - if (fear_monster(dir, lev)) ident = TRUE; - break; - } - - case SV_WAND_HYPODYNAMIA: - { - if (hypodynamic_bolt(dir, 80 + lev)) ident = TRUE; - break; - } - - case SV_WAND_POLYMORPH: - { - if (poly_monster(dir, lev)) ident = TRUE; - break; - } - - case SV_WAND_STINKING_CLOUD: - { - fire_ball(GF_POIS, dir, 12 + lev / 4, rad); - ident = TRUE; - break; - } - - case SV_WAND_MAGIC_MISSILE: - { - fire_bolt_or_beam(20, GF_MISSILE, dir, damroll(2 + lev / 10, 6)); - ident = TRUE; - break; - } - - case SV_WAND_ACID_BOLT: - { - fire_bolt_or_beam(20, GF_ACID, dir, damroll(6 + lev / 7, 8)); - ident = TRUE; - break; - } - - case SV_WAND_CHARM_MONSTER: - { - if (charm_monster(dir, MAX(20, lev))) - ident = TRUE; - break; - } - - case SV_WAND_FIRE_BOLT: - { - fire_bolt_or_beam(20, GF_FIRE, dir, damroll(7 + lev / 6, 8)); - ident = TRUE; - break; - } - - case SV_WAND_COLD_BOLT: - { - fire_bolt_or_beam(20, GF_COLD, dir, damroll(5 + lev / 8, 8)); - ident = TRUE; - break; - } - - case SV_WAND_ACID_BALL: - { - fire_ball(GF_ACID, dir, 60 + 3 * lev / 4, rad); - ident = TRUE; - break; - } - - case SV_WAND_ELEC_BALL: - { - fire_ball(GF_ELEC, dir, 40 + 3 * lev / 4, rad); - ident = TRUE; - break; - } - - case SV_WAND_FIRE_BALL: - { - fire_ball(GF_FIRE, dir, 70 + 3 * lev / 4, rad); - ident = TRUE; - break; - } - - case SV_WAND_COLD_BALL: - { - fire_ball(GF_COLD, dir, 50 + 3 * lev / 4, rad); - ident = TRUE; - break; - } - - case SV_WAND_WONDER: - { - msg_print(_("おっと、謎の魔法棒を始動させた。", "Oops. Wand of wonder activated.")); - break; - } - - case SV_WAND_DRAGON_FIRE: - { - fire_breath(GF_FIRE, dir, (powerful ? 300 : 200), 3); - ident = TRUE; - break; - } - - case SV_WAND_DRAGON_COLD: - { - fire_breath(GF_COLD, dir, (powerful ? 270 : 180), 3); - ident = TRUE; - break; - } - - case SV_WAND_DRAGON_BREATH: - { - HIT_POINT dam; - EFFECT_ID typ; - - switch (randint1(5)) - { - case 1: - dam = 240; - typ = GF_ACID; - break; - case 2: - dam = 210; - typ = GF_ELEC; - break; - case 3: - dam = 240; - typ = GF_FIRE; - break; - case 4: - dam = 210; - typ = GF_COLD; - break; - default: - dam = 180; - typ = GF_POIS; - break; - } - - if (powerful) dam = (dam * 3) / 2; - - fire_breath(typ, dir, dam, 3); - - ident = TRUE; - break; - } - - case SV_WAND_DISINTEGRATE: - { - fire_ball(GF_DISINTEGRATE, dir, 200 + randint1(lev * 2), rad); - ident = TRUE; - break; - } - - case SV_WAND_ROCKETS: - { - msg_print(_("ロケットを発射した!", "You launch a rocket!")); - fire_rocket(GF_ROCKET, dir, 250 + lev * 3, rad); - ident = TRUE; - break; - } - - case SV_WAND_STRIKING: - { - fire_bolt(GF_METEOR, dir, damroll(15 + lev / 3, 13)); - ident = TRUE; - break; - } - - case SV_WAND_GENOCIDE: - { - fire_ball_hide(GF_GENOCIDE, dir, magic ? lev + 50 : 250, 0); - ident = TRUE; - break; - } - } - return ident; -} - -/*! -* @brief 魔法棒を使うコマンドのサブルーチン / -* Aim a wand (from the pack or floor). -* @param item 使うオブジェクトの所持品ID -* @return なし -* @details -*
-* Use a single charge from a single item.
-* Handle "unstacking" in a logical manner.
-* For simplicity, you cannot use a stack of items from the
-* ground.  This would require too much nasty code.
-* There are no wands which can "destroy" themselves, in the inventory
-* or on the ground, so we can ignore this possibility.  Note that this
-* required giving "wand of wonder" the ability to ignore destruction
-* by electric balls.
-* All wands can be "cancelled" at the "Direction?" prompt for free.
-* Note that the basic "bolt" wands do slightly less damage than the
-* basic "bolt" rods, but the basic "ball" wands do the same damage
-* as the basic "ball" rods.
-* 
-*/ -void do_cmd_aim_wand_aux(INVENTORY_IDX item) -{ - DEPTH lev; - int ident, chance; - DIRECTION dir; - object_type *o_ptr; - bool old_target_pet = target_pet; - - /* Get the item (in the pack) */ - if (item >= 0) - { - o_ptr = &inventory[item]; - } - - /* Get the item (on the floor) */ - else - { - o_ptr = ¤t_floor_ptr->o_list[0 - item]; - } - - /* Mega-Hack -- refuse to aim a pile from the ground */ - if ((item < 0) && (o_ptr->number > 1)) - { - msg_print(_("まずは魔法棒を拾わなければ。", "You must first pick up the wands.")); - return; - } - - - /* Allow direction to be cancelled for free */ - if (object_is_aware(o_ptr) && (o_ptr->sval == SV_WAND_HEAL_MONSTER - || o_ptr->sval == SV_WAND_HASTE_MONSTER)) - target_pet = TRUE; - if (!get_aim_dir(&dir)) - { - target_pet = old_target_pet; - return; - } - target_pet = old_target_pet; - - take_turn(p_ptr, 100); - - /* Get the level */ - lev = k_info[o_ptr->k_idx].level; - if (lev > 50) lev = 50 + (lev - 50) / 2; - - /* Base chance of success */ - chance = p_ptr->skill_dev; - - /* Confusion hurts skill */ - if (p_ptr->confused) chance = chance / 2; - - /* Hight level objects are harder */ - chance = chance - lev; - - /* Give everyone a (slight) chance */ - if ((chance < USE_DEVICE) && one_in_(USE_DEVICE - chance + 1)) - { - chance = USE_DEVICE; - } - - if (cmd_limit_time_walk(p_ptr)) return; - - /* Roll for usage */ - if ((chance < USE_DEVICE) || (randint1(chance) < USE_DEVICE) || (p_ptr->pclass == CLASS_BERSERKER)) - { - if (flush_failure) flush(); - msg_print(_("魔法棒をうまく使えなかった。", "You failed to use the wand properly.")); - sound(SOUND_FAIL); - return; - } - - /* The wand is already empty! */ - if (o_ptr->pval <= 0) - { - if (flush_failure) flush(); - msg_print(_("この魔法棒にはもう魔力が残っていない。", "The wand has no charges left.")); - o_ptr->ident |= (IDENT_EMPTY); - p_ptr->update |= (PU_COMBINE | PU_REORDER); - p_ptr->window |= (PW_INVEN); - - return; - } - - sound(SOUND_ZAP); - - ident = wand_effect(o_ptr->sval, dir, FALSE, FALSE); - p_ptr->update |= (PU_COMBINE | PU_REORDER); - - if (!(object_is_aware(o_ptr))) - { - chg_virtue(V_PATIENCE, -1); - chg_virtue(V_CHANCE, 1); - chg_virtue(V_KNOWLEDGE, -1); - } - - /* Mark it as tried */ - object_tried(o_ptr); - - /* Apply identification */ - if (ident && !object_is_aware(o_ptr)) - { - object_aware(o_ptr); - gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); - } - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - - /* Use a single charge */ - o_ptr->pval--; - - /* Describe the charges in the pack */ - if (item >= 0) - { - inven_item_charges(item); - } - - /* Describe the charges on the floor */ - else - { - floor_item_charges(0 - item); - } -} - -/*! -* @brief 魔法棒を使うコマンドのメインルーチン / -* @return なし -*/ -void do_cmd_aim_wand(void) -{ - OBJECT_IDX item; - concptr q, s; - - if (p_ptr->wild_mode) return; - if (cmd_limit_arena(p_ptr)) return; - - /* Restrict choices to wands */ - item_tester_tval = TV_WAND; - - if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN)) - { - set_action(ACTION_NONE); - } - - q = _("どの魔法棒で狙いますか? ", "Aim which wand? "); - s = _("使える魔法棒がない。", "You have no wand to aim."); - if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - do_cmd_aim_wand_aux(item); -} diff --git a/src/cmd-zapwand.h b/src/cmd-zapwand.h deleted file mode 100644 index 5949073ea..000000000 --- a/src/cmd-zapwand.h +++ /dev/null @@ -1,3 +0,0 @@ -extern bool wand_effect(OBJECT_SUBTYPE_VALUE sval, DIRECTION dir, bool powerful, bool magic); -extern void do_cmd_aim_wand_aux(INVENTORY_IDX item); -extern void do_cmd_aim_wand(void); diff --git a/src/cmd2.c b/src/cmd2.c deleted file mode 100644 index 6ff147fb3..000000000 --- a/src/cmd2.c +++ /dev/null @@ -1,2923 +0,0 @@ -/*! - * @file cmd2.c - * @brief プレイヤーのコマンド処理2 / Movement commands (part 2) - * @date 2014/01/02 - * @author - * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, - * and not for profit purposes provided that this copyright and statement - * are included in all such copies. Other copyrights may also apply. - */ - -#include "angband.h" -#include "chest.h" -#include "trap.h" -#include "floor.h" -#include "melee.h" -#include "object-hook.h" -#include "projection.h" -#include "spells-summon.h" -#include "spells-status.h" -#include "monster-status.h" -#include "quest.h" -#include "artifact.h" -#include "avatar.h" -#include "player-status.h" -#include "realm-hex.h" -#include "geometry.h" -#include "wild.h" -#include "grid.h" -#include "feature.h" -#include "player-move.h" -#include "object-broken.h" - -/*! - * @brief フロア脱出時に出戻りが不可能だった場合に警告を加える処理 - * @param down_stair TRUEならば階段を降りる処理、FALSEなら階段を昇る処理による内容 - * @return フロア移動を実際に行うならTRUE、キャンセルする場合はFALSE - */ -static bool confirm_leave_level(bool down_stair) -{ - quest_type *q_ptr = &quest[p_ptr->inside_quest]; - - /* Confirm leaving from once only quest */ - if (confirm_quest && p_ptr->inside_quest && - (q_ptr->type == QUEST_TYPE_RANDOM || - (q_ptr->flags & QUEST_FLAG_ONCE && - q_ptr->status != QUEST_STATUS_COMPLETED) || - (q_ptr->flags & QUEST_FLAG_TOWER && - ((q_ptr->status != QUEST_STATUS_STAGE_COMPLETED) || - (down_stair && (quest[QUEST_TOWER1].status != QUEST_STATUS_COMPLETED)))))) - { - msg_print(_("この階を一度去ると二度と戻って来られません。", "You can't come back here once you leave this floor.")); - if (get_check(_("本当にこの階を去りますか?", "Really leave this floor? "))) return TRUE; - } - else - { - return TRUE; - } - return FALSE; -} - -/*! - * @brief 魔法系コマンドが制限されているかを返す。 - * @return 魔法系コマンドを使用可能ならFALSE、不可能ならば理由をメッセージ表示してTRUEを返す。 - */ -bool cmd_limit_cast(player_type *creature_ptr) -{ - if (current_floor_ptr->dun_level && (d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_MAGIC)) - { - msg_print(_("ダンジョンが魔法を吸収した!", "The dungeon absorbs all attempted magic!")); - msg_print(NULL); - return TRUE; - } - else if (creature_ptr->anti_magic) - { - msg_print(_("反魔法バリアが魔法を邪魔した!", "An anti-magic shell disrupts your magic!")); - return TRUE; - } - else if (creature_ptr->shero) - { - msg_format(_("狂戦士化していて頭が回らない!", "You cannot think directly!")); - return TRUE; - } - else - return FALSE; -} - -bool cmd_limit_confused(player_type *creature_ptr) -{ - if (creature_ptr->confused) - { - msg_print(_("混乱していてできない!", "You are too confused!")); - return TRUE; - } - return FALSE; -} - -bool cmd_limit_image(player_type *creature_ptr) -{ - if (creature_ptr->image) - { - msg_print(_("幻覚が見えて集中できない!", "You are too hallucinated!")); - return TRUE; - } - return FALSE; -} - -bool cmd_limit_stun(player_type *creature_ptr) -{ - if (creature_ptr->stun) - { - msg_print(_("頭が朦朧としていて集中できない!", "You are too stuned!")); - return TRUE; - } - return FALSE; -} - -bool cmd_limit_arena(player_type *creature_ptr) -{ - if (creature_ptr->inside_arena) - { - msg_print(_("アリーナが魔法を吸収した!", "The arena absorbs all attempted magic!")); - msg_print(NULL); - return TRUE; - } - return FALSE; -} - -bool cmd_limit_blind(player_type *creature_ptr) -{ - if (creature_ptr->blind) - { - msg_print(_("目が見えない。", "You can't see anything.")); - return TRUE; - } - if (no_lite()) - { - msg_print(_("明かりがないので、暗くて読めない。", "You have no light to read by.")); - return TRUE; - } - return FALSE; -} - -bool cmd_limit_time_walk(player_type *creature_ptr) -{ - if (creature_ptr->timewalk) - { - if (flush_failure) flush(); - msg_print(_("止まった時の中ではうまく働かないようだ。", "It shows no reaction.")); - sound(SOUND_FAIL); - return TRUE; - } - return FALSE; -} - -/*! - * @brief 階段を使って階層を昇る処理 / Go up one level - * @return なし - */ -void do_cmd_go_up(void) -{ - bool go_up = FALSE; - - /* Player grid */ - grid_type *g_ptr = ¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x]; - feature_type *f_ptr = &f_info[g_ptr->feat]; - - int up_num = 0; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Verify stairs */ - if (!have_flag(f_ptr->flags, FF_LESS)) - { - msg_print(_("ここには上り階段が見当たらない。", "I see no up staircase here.")); - return; - } - - /* Quest up stairs */ - if (have_flag(f_ptr->flags, FF_QUEST)) - { - /* Cancel the command */ - if (!confirm_leave_level(FALSE)) return; - - - /* Success */ - if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) - msg_print(_("なんだこの階段は!", "What's this STAIRWAY!")); - else - msg_print(_("上の階に登った。", "You enter the up staircase.")); - - leave_quest_check(); - - p_ptr->inside_quest = g_ptr->special; - - /* Activate the quest */ - if (!quest[p_ptr->inside_quest].status) - { - if (quest[p_ptr->inside_quest].type != QUEST_TYPE_RANDOM) - { - init_flags = INIT_ASSIGN; - process_dungeon_file("q_info.txt", 0, 0, 0, 0); - } - quest[p_ptr->inside_quest].status = QUEST_STATUS_TAKEN; - } - - /* Leaving a quest */ - if (!p_ptr->inside_quest) - { - current_floor_ptr->dun_level = 0; - } - p_ptr->leaving = TRUE; - - p_ptr->oldpx = 0; - p_ptr->oldpy = 0; - - take_turn(p_ptr, 100); - - /* End the command */ - return; - } - - if (!current_floor_ptr->dun_level) - { - go_up = TRUE; - } - else - { - go_up = confirm_leave_level(FALSE); - } - - /* Cancel the command */ - if (!go_up) return; - - take_turn(p_ptr, 100); - - if (autosave_l) do_cmd_save_game(TRUE); - - /* For a random quest */ - if (p_ptr->inside_quest && - quest[p_ptr->inside_quest].type == QUEST_TYPE_RANDOM) - { - leave_quest_check(); - - p_ptr->inside_quest = 0; - } - - /* For a fixed quest */ - if (p_ptr->inside_quest && - quest[p_ptr->inside_quest].type != QUEST_TYPE_RANDOM) - { - leave_quest_check(); - - p_ptr->inside_quest = g_ptr->special; - current_floor_ptr->dun_level = 0; - up_num = 0; - } - - /* For normal dungeon and random quest */ - else - { - /* New depth */ - if (have_flag(f_ptr->flags, FF_SHAFT)) - { - /* Create a way back */ - prepare_change_floor_mode(CFM_SAVE_FLOORS | CFM_UP | CFM_SHAFT); - - up_num = 2; - } - else - { - /* Create a way back */ - prepare_change_floor_mode(CFM_SAVE_FLOORS | CFM_UP); - - up_num = 1; - } - - /* Get out from current dungeon */ - if (current_floor_ptr->dun_level - up_num < d_info[p_ptr->dungeon_idx].mindepth) - up_num = current_floor_ptr->dun_level; - } - if (record_stair) do_cmd_write_nikki(NIKKI_STAIR, 0-up_num, _("階段を上った", "climbed up the stairs to")); - - /* Success */ - if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) - msg_print(_("なんだこの階段は!", "What's this STAIRWAY!")); - else if (up_num == current_floor_ptr->dun_level) - msg_print(_("地上に戻った。", "You go back to the surface.")); - else - msg_print(_("階段を上って新たなる迷宮へと足を踏み入れた。", "You enter a maze of up staircases.")); - p_ptr->leaving = TRUE; -} - - -/*! - * @brief 階段を使って階層を降りる処理 / Go down one level - * @return なし - */ -void do_cmd_go_down(void) -{ - /* Player grid */ - grid_type *g_ptr = ¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x]; - feature_type *f_ptr = &f_info[g_ptr->feat]; - - bool fall_trap = FALSE; - int down_num = 0; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Verify stairs */ - if (!have_flag(f_ptr->flags, FF_MORE)) - { - msg_print(_("ここには下り階段が見当たらない。", "I see no down staircase here.")); - return; - } - - if (have_flag(f_ptr->flags, FF_TRAP)) fall_trap = TRUE; - - /* Quest entrance */ - if (have_flag(f_ptr->flags, FF_QUEST_ENTER)) - { - do_cmd_quest(); - } - - /* Quest down stairs */ - else if (have_flag(f_ptr->flags, FF_QUEST)) - { - /* Confirm Leaving */ - if(!confirm_leave_level(TRUE)) return; - - if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) - msg_print(_("なんだこの階段は!", "What's this STAIRWAY!")); - else - msg_print(_("下の階に降りた。", "You enter the down staircase.")); - - leave_quest_check(); - leave_tower_check(); - - p_ptr->inside_quest = g_ptr->special; - - /* Activate the quest */ - if (!quest[p_ptr->inside_quest].status) - { - if (quest[p_ptr->inside_quest].type != QUEST_TYPE_RANDOM) - { - init_flags = INIT_ASSIGN; - process_dungeon_file("q_info.txt", 0, 0, 0, 0); - } - quest[p_ptr->inside_quest].status = QUEST_STATUS_TAKEN; - } - - /* Leaving a quest */ - if (!p_ptr->inside_quest) - { - current_floor_ptr->dun_level = 0; - } - p_ptr->leaving = TRUE; - p_ptr->oldpx = 0; - p_ptr->oldpy = 0; - - take_turn(p_ptr, 100); - } - - else - { - DUNGEON_IDX target_dungeon = 0; - - if (!current_floor_ptr->dun_level) - { - target_dungeon = have_flag(f_ptr->flags, FF_ENTRANCE) ? g_ptr->special : DUNGEON_ANGBAND; - - if (ironman_downward && (target_dungeon != DUNGEON_ANGBAND)) - { - msg_print(_("ダンジョンの入口は塞がれている!", "The entrance of this dungeon is closed!")); - return; - } - if (!max_dlv[target_dungeon]) - { - msg_format(_("ここには%sの入り口(%d階相当)があります", "There is the entrance of %s (Danger level: %d)"), - d_name+d_info[target_dungeon].name, d_info[target_dungeon].mindepth); - if (!get_check(_("本当にこのダンジョンに入りますか?", "Do you really get in this dungeon? "))) return; - } - - /* Save old player position */ - p_ptr->oldpx = p_ptr->x; - p_ptr->oldpy = p_ptr->y; - p_ptr->dungeon_idx = target_dungeon; - - /* - * Clear all saved floors - * and create a first saved floor - */ - prepare_change_floor_mode(CFM_FIRST_FLOOR); - } - - take_turn(p_ptr, 100); - - if (autosave_l) do_cmd_save_game(TRUE); - - /* Go down */ - if (have_flag(f_ptr->flags, FF_SHAFT)) down_num += 2; - else down_num += 1; - - if (!current_floor_ptr->dun_level) - { - /* Enter the dungeon just now */ - p_ptr->enter_dungeon = TRUE; - down_num = d_info[p_ptr->dungeon_idx].mindepth; - } - - if (record_stair) - { - if (fall_trap) do_cmd_write_nikki(NIKKI_STAIR, down_num, _("落とし戸に落ちた", "fell through a trap door")); - else do_cmd_write_nikki(NIKKI_STAIR, down_num, _("階段を下りた", "climbed down the stairs to")); - } - - if (fall_trap) - { - msg_print(_("わざと落とし戸に落ちた。", "You deliberately jump through the trap door.")); - } - else - { - /* Success */ - if (target_dungeon) - { - msg_format(_("%sへ入った。", "You entered %s."), d_text + d_info[p_ptr->dungeon_idx].text); - } - else - { - if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) - msg_print(_("なんだこの階段は!", "What's this STAIRWAY!")); - else - msg_print(_("階段を下りて新たなる迷宮へと足を踏み入れた。", "You enter a maze of down staircases.")); - } - } - - p_ptr->leaving = TRUE; - - if (fall_trap) - { - prepare_change_floor_mode(CFM_SAVE_FLOORS | CFM_DOWN | CFM_RAND_PLACE | CFM_RAND_CONNECT); - } - else - { - if (have_flag(f_ptr->flags, FF_SHAFT)) - { - /* Create a way back */ - prepare_change_floor_mode(CFM_SAVE_FLOORS | CFM_DOWN | CFM_SHAFT); - } - else - { - /* Create a way back */ - prepare_change_floor_mode(CFM_SAVE_FLOORS | CFM_DOWN); - } - } - } -} - - -/*! - * @brief 探索コマンドのメインルーチン / Simple command to "search" for one current_world_ptr->game_turn - * @return なし - */ -void do_cmd_search(void) -{ - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - take_turn(p_ptr, 100); - - /* Search */ - search(); -} - - -/*! - * @brief 該当のマスに存在している箱のオブジェクトIDを返す。 - * @param y 走査対象にしたいマスのY座標 - * @param x 走査対象にしたいマスのX座標 - * @param trapped TRUEならばトラップが存在する箱のみ、FALSEならば空でない箱全てを対象にする - * @return 箱が存在する場合そのオブジェクトID、存在しない場合0を返す。 - */ -static OBJECT_IDX chest_check(POSITION y, POSITION x, bool trapped) -{ - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; - OBJECT_IDX this_o_idx, next_o_idx = 0; - - /* Scan all objects in the grid */ - for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) - { - object_type *o_ptr; - - o_ptr = ¤t_floor_ptr->o_list[this_o_idx]; - next_o_idx = o_ptr->next_o_idx; - - /* Skip unknown chests XXX XXX */ - /* if (!(o_ptr->marked & OM_FOUND)) continue; */ - - /* Check for non empty chest */ - if ((o_ptr->tval == TV_CHEST) && - (((!trapped) && (o_ptr->pval)) || /* non empty */ - ((trapped) && (o_ptr->pval > 0)))) /* trapped only */ - { - return (this_o_idx); - } - } - return (0); -} - -/*! - * @brief 箱を開けるコマンドのメインルーチン / - * Attempt to open the given chest at the given location - * @param y 箱の存在するマスのY座標 - * @param x 箱の存在するマスのX座標 - * @param o_idx 箱のオブジェクトID - * @return 箱が開かなかった場合TRUE / Returns TRUE if repeated commands may continue - * @details - * Assume there is no monster blocking the destination - */ -static bool do_cmd_open_chest(POSITION y, POSITION x, OBJECT_IDX o_idx) -{ - int i, j; - bool flag = TRUE; - bool more = FALSE; - object_type *o_ptr = ¤t_floor_ptr->o_list[o_idx]; - - take_turn(p_ptr, 100); - - /* Attempt to unlock it */ - if (o_ptr->pval > 0) - { - /* Assume locked, and thus not open */ - flag = FALSE; - - /* Get the "disarm" factor */ - i = p_ptr->skill_dis; - - /* Penalize some conditions */ - if (p_ptr->blind || no_lite()) i = i / 10; - if (p_ptr->confused || p_ptr->image) i = i / 10; - - /* Extract the difficulty */ - j = i - o_ptr->pval; - - /* Always have a small chance of success */ - if (j < 2) j = 2; - - /* Success -- May still have traps */ - if (randint0(100) < j) - { - msg_print(_("鍵をはずした。", "You have picked the lock.")); - gain_exp(1); - flag = TRUE; - } - - /* Failure -- Keep trying */ - else - { - /* We may continue repeating */ - more = TRUE; - if (flush_failure) flush(); - msg_print(_("鍵をはずせなかった。", "You failed to pick the lock.")); - - } - } - - /* Allowed to open */ - if (flag) - { - /* Apply chest traps, if any */ - chest_trap(y, x, o_idx); - - /* Let the Chest drop items */ - chest_death(FALSE, y, x, o_idx); - } - return (more); -} - -/*! - * @brief プレイヤーの周辺9マスに該当する地形がいくつあるかを返す / - * Attempt to open the given chest at the given location - * @param y 該当する地形の中から1つのY座標を返す参照ポインタ - * @param x 該当する地形の中から1つのX座標を返す参照ポインタ - * @param test 地形条件を判定するための関数ポインタ - * @param under TRUEならばプレイヤーの直下の座標も走査対象にする - * @return 該当する地形の数 - * @details Return the number of features around (or under) the character. - * Usually look for doors and floor traps. - */ -static int count_dt(POSITION *y, POSITION *x, bool (*test)(IDX feat), bool under) -{ - DIRECTION d; - int count; - POSITION xx, yy; - - /* Count how many matches */ - count = 0; - - /* Check around (and under) the character */ - for (d = 0; d < 9; d++) - { - grid_type *g_ptr; - FEAT_IDX feat; - - /* if not searching under player continue */ - if ((d == 8) && !under) continue; - - /* Extract adjacent (legal) location */ - yy = p_ptr->y + ddy_ddd[d]; - xx = p_ptr->x + ddx_ddd[d]; - - /* Get the current_floor_ptr->grid_array */ - g_ptr = ¤t_floor_ptr->grid_array[yy][xx]; - - /* Must have knowledge */ - if (!(g_ptr->info & (CAVE_MARK))) continue; - - /* Feature code (applying "mimic" field) */ - feat = get_feat_mimic(g_ptr); - - /* Not looking for this feature */ - if (!((*test)(feat))) continue; - - /* OK */ - ++count; - - /* Remember the location. Only useful if only one match */ - *y = yy; - *x = xx; - } - - /* All done */ - return count; -} - - -/*! - * @brief プレイヤーの周辺9マスに箱のあるマスがいくつあるかを返す / - * Return the number of chests around (or under) the character. - * @param y 該当するマスの中から1つのY座標を返す参照ポインタ - * @param x 該当するマスの中から1つのX座標を返す参照ポインタ - * @param trapped TRUEならばトラップの存在が判明している箱のみ対象にする - * @return 該当する地形の数 - * @details - * If requested, count only trapped chests. - */ -static int count_chests(POSITION *y, POSITION *x, bool trapped) -{ - DIRECTION d; - int count; - OBJECT_IDX o_idx; - object_type *o_ptr; - - /* Count how many matches */ - count = 0; - - /* Check around (and under) the character */ - for (d = 0; d < 9; d++) - { - /* Extract adjacent (legal) location */ - POSITION yy = p_ptr->y + ddy_ddd[d]; - POSITION xx = p_ptr->x + ddx_ddd[d]; - - /* No (visible) chest is there */ - if ((o_idx = chest_check(yy, xx, FALSE)) == 0) continue; - - /* Grab the object */ - o_ptr = ¤t_floor_ptr->o_list[o_idx]; - - /* Already open */ - if (o_ptr->pval == 0) continue; - - /* No (known) traps here */ - if (trapped && (!object_is_known(o_ptr) || - !chest_traps[o_ptr->pval])) continue; - - /* OK */ - ++count; - - /* Remember the location. Only useful if only one match */ - *y = yy; - *x = xx; - } - - /* All done */ - return count; -} - - - -/*! - * @brief 「開ける」動作コマンドのサブルーチン / - * Perform the basic "open" command on doors - * @param y 対象を行うマスのY座標 - * @param x 対象を行うマスのX座標 - * @return 実際に処理が行われた場合TRUEを返す。 - * @details - * Assume destination is a closed/locked/jammed door - * Assume there is no monster blocking the destination - * Returns TRUE if repeated commands may continue - */ -static bool do_cmd_open_aux(POSITION y, POSITION x) -{ - int i, j; - - /* Get requested grid */ - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; - feature_type *f_ptr = &f_info[g_ptr->feat]; - bool more = FALSE; - - take_turn(p_ptr, 100); - - /* Seeing true feature code (ignore mimic) */ - - /* Jammed door */ - if (!have_flag(f_ptr->flags, FF_OPEN)) - { - /* Stuck */ - msg_format(_("%sはがっちりと閉じられているようだ。", "The %s appears to be stuck."), f_name + f_info[get_feat_mimic(g_ptr)].name); - } - - /* Locked door */ - else if (f_ptr->power) - { - /* Disarm factor */ - i = p_ptr->skill_dis; - - /* Penalize some conditions */ - if (p_ptr->blind || no_lite()) i = i / 10; - if (p_ptr->confused || p_ptr->image) i = i / 10; - - /* Extract the lock power */ - j = f_ptr->power; - - /* Extract the difficulty */ - j = i - (j * 4); - - /* Always have a small chance of success */ - if (j < 2) j = 2; - - /* Success */ - if (randint0(100) < j) - { - msg_print(_("鍵をはずした。", "You have picked the lock.")); - - /* Open the door */ - cave_alter_feat(y, x, FF_OPEN); - - sound(SOUND_OPENDOOR); - - /* Experience */ - gain_exp(1); - } - - /* Failure */ - else - { - /* Failure */ - if (flush_failure) flush(); - - msg_print(_("鍵をはずせなかった。", "You failed to pick the lock.")); - - /* We may keep trying */ - more = TRUE; - } - } - - /* Closed door */ - else - { - /* Open the door */ - cave_alter_feat(y, x, FF_OPEN); - - sound(SOUND_OPENDOOR); - } - return (more); -} - -/*! - * @brief 「開ける」コマンドのメインルーチン / - * Open a closed/locked/jammed door or a closed/locked chest. - * @return なし - * @details - * Unlocking a locked door/chest is worth one experience point. - */ -void do_cmd_open(void) -{ - POSITION y, x; - DIRECTION dir; - OBJECT_IDX o_idx; - - bool more = FALSE; - - if (p_ptr->wild_mode) return; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Option: Pick a direction */ - if (easy_open) - { - int num_doors, num_chests; - - /* Count closed doors (locked or jammed) */ - num_doors = count_dt(&y, &x, is_closed_door, FALSE); - - /* Count chests (locked) */ - num_chests = count_chests(&y, &x, FALSE); - - /* See if only one target */ - if (num_doors || num_chests) - { - bool too_many = (num_doors && num_chests) || (num_doors > 1) || - (num_chests > 1); - if (!too_many) command_dir = coords_to_dir(y, x); - } - } - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir, TRUE)) - { - FEAT_IDX feat; - grid_type *g_ptr; - - /* Get requested location */ - y = p_ptr->y + ddy[dir]; - x = p_ptr->x + ddx[dir]; - - /* Get requested grid */ - g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - /* Feature code (applying "mimic" field) */ - feat = get_feat_mimic(g_ptr); - - /* Check for chest */ - o_idx = chest_check(y, x, FALSE); - - /* Nothing useful */ - if (!have_flag(f_info[feat].flags, FF_OPEN) && !o_idx) - { - msg_print(_("そこには開けるものが見当たらない。", "You see nothing there to open.")); - } - - /* Monster in the way */ - else if (g_ptr->m_idx && p_ptr->riding != g_ptr->m_idx) - { - take_turn(p_ptr, 100); - msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); - py_attack(y, x, 0); - } - - /* Handle chests */ - else if (o_idx) - { - /* Open the chest */ - more = do_cmd_open_chest(y, x, o_idx); - } - - /* Handle doors */ - else - { - /* Open the door */ - more = do_cmd_open_aux(y, x); - } - } - - /* Cancel repeat unless we may continue */ - if (!more) disturb(FALSE, FALSE); -} - - - -/*! - * @brief 「閉じる」動作コマンドのサブルーチン / - * Perform the basic "close" command - * @param y 対象を行うマスのY座標 - * @param x 対象を行うマスのX座標 - * @return 実際に処理が行われた場合TRUEを返す。 - * @details - * Assume destination is an open/broken door - * Assume there is no monster blocking the destination - * Returns TRUE if repeated commands may continue - */ -static bool do_cmd_close_aux(POSITION y, POSITION x) -{ - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; - FEAT_IDX old_feat = g_ptr->feat; - bool more = FALSE; - - take_turn(p_ptr, 100); - - /* Seeing true feature code (ignore mimic) */ - - /* Open door */ - if (have_flag(f_info[old_feat].flags, FF_CLOSE)) - { - s16b closed_feat = feat_state(old_feat, FF_CLOSE); - - /* Hack -- object in the way */ - if ((g_ptr->o_idx || (g_ptr->info & CAVE_OBJECT)) && - (closed_feat != old_feat) && !have_flag(f_info[closed_feat].flags, FF_DROP)) - { - msg_print(_("何かがつっかえて閉まらない。", "There seems stuck.")); - } - else - { - /* Close the door */ - cave_alter_feat(y, x, FF_CLOSE); - - /* Broken door */ - if (old_feat == g_ptr->feat) - { - msg_print(_("ドアは壊れてしまっている。", "The door appears to be broken.")); - } - else - { - sound(SOUND_SHUTDOOR); - } - } - } - return (more); -} - - -/*! - * @brief 「閉じる」コマンドのメインルーチン / - * Close an open door. - * @return なし - * @details - * Unlocking a locked door/chest is worth one experience point. - */ -void do_cmd_close(void) -{ - POSITION y, x; - DIRECTION dir; - - bool more = FALSE; - - if (p_ptr->wild_mode) return; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Option: Pick a direction */ - if (easy_open) - { - /* Count open doors */ - if (count_dt(&y, &x, is_open, FALSE) == 1) - { - command_dir = coords_to_dir(y, x); - } - } - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir, FALSE)) - { - grid_type *g_ptr; - FEAT_IDX feat; - - y = p_ptr->y + ddy[dir]; - x = p_ptr->x + ddx[dir]; - g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - /* Feature code (applying "mimic" field) */ - feat = get_feat_mimic(g_ptr); - - /* Require open/broken door */ - if (!have_flag(f_info[feat].flags, FF_CLOSE)) - { - msg_print(_("そこには閉じるものが見当たらない。", "You see nothing there to close.")); - } - - /* Monster in the way */ - else if (g_ptr->m_idx) - { - take_turn(p_ptr, 100); - - msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); - - /* Attack */ - py_attack(y, x, 0); - } - - /* Close the door */ - else - { - /* Close the door */ - more = do_cmd_close_aux(y, x); - } - } - - /* Cancel repeat unless we may continue */ - if (!more) disturb(FALSE, FALSE); -} - - -/*! - * @brief 「掘る」コマンドを該当のマスに行えるかの判定と結果メッセージの表示 / - * Determine if a given grid may be "tunneled" - * @param y 対象を行うマスのY座標 - * @param x 対象を行うマスのX座標 - * @return - */ -static bool do_cmd_tunnel_test(POSITION y, POSITION x) -{ - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - /* Must have knowledge */ - if (!(g_ptr->info & CAVE_MARK)) - { - msg_print(_("そこには何も見当たらない。", "You see nothing there.")); - - return (FALSE); - } - - /* Must be a wall/door/etc */ - if (!cave_have_flag_grid(g_ptr, FF_TUNNEL)) - { - msg_print(_("そこには掘るものが見当たらない。", "You see nothing there to tunnel.")); - - return (FALSE); - } - - return (TRUE); -} - - -/*! - * @brief 「掘る」動作コマンドのサブルーチン / - * Perform the basic "tunnel" command - * @param y 対象を行うマスのY座標 - * @param x 対象を行うマスのX座標 - * @return 実際に処理が行われた場合TRUEを返す。 - * @details - * Assumes that no monster is blocking the destination - * Do not use twall anymore - * Returns TRUE if repeated commands may continue - */ -static bool do_cmd_tunnel_aux(POSITION y, POSITION x) -{ - grid_type *g_ptr; - feature_type *f_ptr, *mimic_f_ptr; - int power; - concptr name; - bool more = FALSE; - - /* Verify legality */ - if (!do_cmd_tunnel_test(y, x)) return (FALSE); - - take_turn(p_ptr, 100); - - g_ptr = ¤t_floor_ptr->grid_array[y][x]; - f_ptr = &f_info[g_ptr->feat]; - power = f_ptr->power; - - /* Feature code (applying "mimic" field) */ - mimic_f_ptr = &f_info[get_feat_mimic(g_ptr)]; - - name = f_name + mimic_f_ptr->name; - - sound(SOUND_DIG); - - if (have_flag(f_ptr->flags, FF_PERMANENT)) - { - /* Titanium */ - if (have_flag(mimic_f_ptr->flags, FF_PERMANENT)) - { - msg_print(_("この岩は硬すぎて掘れないようだ。", "This seems to be permanent rock.")); - } - - /* Map border (mimiccing Permanent wall) */ - else - { - msg_print(_("そこは掘れない!", "You can't tunnel through that!")); - } - } - - /* Dig or tunnel */ - else if (have_flag(f_ptr->flags, FF_CAN_DIG)) - { - /* Dig */ - if (p_ptr->skill_dig > randint0(20 * power)) - { - msg_format(_("%sをくずした。", "You have removed the %s."), name); - - /* Remove the feature */ - cave_alter_feat(y, x, FF_TUNNEL); - p_ptr->update |= (PU_FLOW); - } - else - { - /* Message, keep digging */ - msg_format(_("%sをくずしている。", "You dig into the %s."), name); - - more = TRUE; - } - } - - else - { - bool tree = have_flag(mimic_f_ptr->flags, FF_TREE); - - /* Tunnel */ - if (p_ptr->skill_dig > power + randint0(40 * power)) - { - if (tree) msg_format(_("%sを切り払った。", "You have cleared away the %s."), name); - else - { - msg_print(_("穴を掘り終えた。", "You have finished the tunnel.")); - p_ptr->update |= (PU_FLOW); - } - - if (have_flag(f_ptr->flags, FF_GLASS)) sound(SOUND_GLASS); - - /* Remove the feature */ - cave_alter_feat(y, x, FF_TUNNEL); - - chg_virtue(V_DILIGENCE, 1); - chg_virtue(V_NATURE, -1); - } - - /* Keep trying */ - else - { - if (tree) - { - /* We may continue chopping */ - msg_format(_("%sを切っている。", "You chop away at the %s."), name); - /* Occasional Search XXX XXX */ - if (randint0(100) < 25) search(); - } - else - { - /* We may continue tunelling */ - msg_format(_("%sに穴を掘っている。", "You tunnel into the %s."), name); - } - - more = TRUE; - } - } - - if (is_hidden_door(g_ptr)) - { - /* Occasional Search XXX XXX */ - if (randint0(100) < 25) search(); - } - return more; -} - - -/*! - * @brief 「掘る」動作コマンドのメインルーチン / - * Tunnels through "walls" (including rubble and closed doors) - * @return なし - * @details - *
- * Note that you must tunnel in order to hit invisible monsters
- * in walls, though moving into walls still takes a current_world_ptr->game_turn anyway.
- *
- * Digging is very difficult without a "digger" weapon, but can be
- * accomplished by strong players using heavy weapons.
- * 
- */ -void do_cmd_tunnel(void) -{ - POSITION y, x; - DIRECTION dir; - grid_type *g_ptr; - FEAT_IDX feat; - - bool more = FALSE; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a direction to tunnel, or Abort */ - if (get_rep_dir(&dir,FALSE)) - { - /* Get location */ - y = p_ptr->y + ddy[dir]; - x = p_ptr->x + ddx[dir]; - - g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - /* Feature code (applying "mimic" field) */ - feat = get_feat_mimic(g_ptr); - - /* No tunnelling through doors */ - if (have_flag(f_info[feat].flags, FF_DOOR)) - { - msg_print(_("ドアは掘れない。", "You cannot tunnel through doors.")); - } - - /* No tunnelling through most features */ - else if (!have_flag(f_info[feat].flags, FF_TUNNEL)) - { - msg_print(_("そこは掘れない。", "You can't tunnel through that.")); - } - - /* A monster is in the way */ - else if (g_ptr->m_idx) - { - take_turn(p_ptr, 100); - - msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); - - /* Attack */ - py_attack(y, x, 0); - } - - /* Try digging */ - else - { - /* Tunnel through walls */ - more = do_cmd_tunnel_aux(y, x); - } - } - - /* Cancel repetition unless we can continue */ - if (!more) disturb(FALSE, FALSE); -} - -/*! - * @brief 移動処理による簡易な「開く」処理 / - * easy_open_door -- - * @return 開く処理が実際に試みられた場合TRUEを返す - * @details - *
- *	If there is a jammed/closed/locked door at the given location,
- *	then attempt to unlock/open it. Return TRUE if an attempt was
- *	made (successful or not), otherwise return FALSE.
- *
- *	The code here should be nearly identical to that in
- *	do_cmd_open_test() and do_cmd_open_aux().
- * 
- */ -bool easy_open_door(POSITION y, POSITION x) -{ - int i, j; - - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; - feature_type *f_ptr = &f_info[g_ptr->feat]; - - /* Must be a closed door */ - if (!is_closed_door(g_ptr->feat)) - { - return (FALSE); - } - - /* Jammed door */ - if (!have_flag(f_ptr->flags, FF_OPEN)) - { - /* Stuck */ - msg_format(_("%sはがっちりと閉じられているようだ。", "The %s appears to be stuck."), f_name + f_info[get_feat_mimic(g_ptr)].name); - - } - - /* Locked door */ - else if (f_ptr->power) - { - /* Disarm factor */ - i = p_ptr->skill_dis; - - /* Penalize some conditions */ - if (p_ptr->blind || no_lite()) i = i / 10; - if (p_ptr->confused || p_ptr->image) i = i / 10; - - /* Extract the lock power */ - j = f_ptr->power; - - /* Extract the difficulty */ - j = i - (j * 4); - - /* Always have a small chance of success */ - if (j < 2) j = 2; - - /* Success */ - if (randint0(100) < j) - { - msg_print(_("鍵をはずした。", "You have picked the lock.")); - - /* Open the door */ - cave_alter_feat(y, x, FF_OPEN); - - sound(SOUND_OPENDOOR); - - /* Experience */ - gain_exp(1); - } - - /* Failure */ - else - { - /* Failure */ - if (flush_failure) flush(); - - msg_print(_("鍵をはずせなかった。", "You failed to pick the lock.")); - - } - } - - /* Closed door */ - else - { - /* Open the door */ - cave_alter_feat(y, x, FF_OPEN); - - sound(SOUND_OPENDOOR); - } - return (TRUE); -} - -/*! - * @brief 箱のトラップを解除するコマンドのメインルーチン / - * Perform the basic "disarm" command - * @param y 解除を行うマスのY座標 - * @param x 解除を行うマスのX座標 - * @param o_idx 箱のオブジェクトID - * @return ターンを消費する処理が行われた場合TRUEを返す - * @details - *
- * Assume destination is a visible trap
- * Assume there is no monster blocking the destination
- * Returns TRUE if repeated commands may continue
- * 
- */ -static bool do_cmd_disarm_chest(POSITION y, POSITION x, OBJECT_IDX o_idx) -{ - int i, j; - bool more = FALSE; - object_type *o_ptr = ¤t_floor_ptr->o_list[o_idx]; - - take_turn(p_ptr, 100); - - /* Get the "disarm" factor */ - i = p_ptr->skill_dis; - - /* Penalize some conditions */ - if (p_ptr->blind || no_lite()) i = i / 10; - if (p_ptr->confused || p_ptr->image) i = i / 10; - - /* Extract the difficulty */ - j = i - o_ptr->pval; - - /* Always have a small chance of success */ - if (j < 2) j = 2; - - /* Must find the trap first. */ - if (!object_is_known(o_ptr)) - { - msg_print(_("トラップが見あたらない。", "I don't see any traps.")); - - } - - /* Already disarmed/unlocked */ - else if (o_ptr->pval <= 0) - { - msg_print(_("箱にはトラップが仕掛けられていない。", "The chest is not trapped.")); - } - - /* No traps to find. */ - else if (!chest_traps[o_ptr->pval]) - { - msg_print(_("箱にはトラップが仕掛けられていない。", "The chest is not trapped.")); - } - - /* Success (get a lot of experience) */ - else if (randint0(100) < j) - { - msg_print(_("箱に仕掛けられていたトラップを解除した。", "You have disarmed the chest.")); - gain_exp(o_ptr->pval); - o_ptr->pval = (0 - o_ptr->pval); - } - - /* Failure -- Keep trying */ - else if ((i > 5) && (randint1(i) > 5)) - { - /* We may keep trying */ - more = TRUE; - if (flush_failure) flush(); - msg_print(_("箱のトラップ解除に失敗した。", "You failed to disarm the chest.")); - } - - /* Failure -- Set off the trap */ - else - { - msg_print(_("トラップを作動させてしまった!", "You set off a trap!")); - sound(SOUND_FAIL); - chest_trap(y, x, o_idx); - } - return (more); -} - - -/*! - * @brief 箱のトラップを解除するコマンドのサブルーチン / - * Perform the basic "disarm" command - * @param y 解除を行うマスのY座標 - * @param x 解除を行うマスのX座標 - * @param dir プレイヤーからみた方向ID - * @return ターンを消費する処理が行われた場合TRUEを返す - * @details - *
- * Assume destination is a visible trap
- * Assume there is no monster blocking the destination
- * Returns TRUE if repeated commands may continue
- * 
- */ - -bool do_cmd_disarm_aux(POSITION y, POSITION x, DIRECTION dir) -{ - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - /* Get feature */ - feature_type *f_ptr = &f_info[g_ptr->feat]; - - /* Access trap name */ - concptr name = (f_name + f_ptr->name); - - /* Extract trap "power" */ - int power = f_ptr->power; - bool more = FALSE; - - /* Get the "disarm" factor */ - int i = p_ptr->skill_dis; - int j; - - take_turn(p_ptr, 100); - - /* Penalize some conditions */ - if (p_ptr->blind || no_lite()) i = i / 10; - if (p_ptr->confused || p_ptr->image) i = i / 10; - - /* Extract the difficulty */ - j = i - power; - - /* Always have a small chance of success */ - if (j < 2) j = 2; - - /* Success */ - if (randint0(100) < j) - { - msg_format(_("%sを解除した。", "You have disarmed the %s."), name); - - /* Reward */ - gain_exp(power); - - /* Remove the trap */ - cave_alter_feat(y, x, FF_DISARM); - - /* Move the player onto the trap */ - move_player(dir, easy_disarm, FALSE); - } - - /* Failure -- Keep trying */ - else if ((i > 5) && (randint1(i) > 5)) - { - /* Failure */ - if (flush_failure) flush(); - - msg_format(_("%sの解除に失敗した。", "You failed to disarm the %s."), name); - - /* We may keep trying */ - more = TRUE; - } - - /* Failure -- Set off the trap */ - else - { - msg_format(_("%sを作動させてしまった!", "You set off the %s!"), name); - /* Move the player onto the trap */ - move_player(dir, easy_disarm, FALSE); - } - return (more); -} - - -/*! - * @brief 箱、床のトラップ解除処理双方の統合メインルーチン / - * Disarms a trap, or chest - * @return なし - */ -void do_cmd_disarm(void) -{ - POSITION y, x; - DIRECTION dir; - OBJECT_IDX o_idx; - - bool more = FALSE; - - if (p_ptr->wild_mode) return; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Option: Pick a direction */ - if (easy_disarm) - { - int num_traps, num_chests; - - /* Count visible traps */ - num_traps = count_dt(&y, &x, is_trap, TRUE); - - /* Count chests (trapped) */ - num_chests = count_chests(&y, &x, TRUE); - - /* See if only one target */ - if (num_traps || num_chests) - { - bool too_many = (num_traps && num_chests) || (num_traps > 1) || (num_chests > 1); - if (!too_many) command_dir = coords_to_dir(y, x); - } - } - - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a direction (or abort) */ - if (get_rep_dir(&dir,TRUE)) - { - grid_type *g_ptr; - FEAT_IDX feat; - - y = p_ptr->y + ddy[dir]; - x = p_ptr->x + ddx[dir]; - g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - /* Feature code (applying "mimic" field) */ - feat = get_feat_mimic(g_ptr); - - /* Check for chests */ - o_idx = chest_check(y, x, TRUE); - - /* Disarm a trap */ - if (!is_trap(feat) && !o_idx) - { - msg_print(_("そこには解除するものが見当たらない。", "You see nothing there to disarm.")); - } - - /* Monster in the way */ - else if (g_ptr->m_idx && p_ptr->riding != g_ptr->m_idx) - { - msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); - - /* Attack */ - py_attack(y, x, 0); - } - - /* Disarm chest */ - else if (o_idx) - { - more = do_cmd_disarm_chest(y, x, o_idx); - } - - /* Disarm trap */ - else - { - more = do_cmd_disarm_aux(y, x, dir); - } - } - - /* Cancel repeat unless told not to */ - if (!more) disturb(FALSE, FALSE); -} - - -/*! - * @brief 「打ち破る」動作コマンドのサブルーチン / - * Perform the basic "bash" command - * @param y 対象を行うマスのY座標 - * @param x 対象を行うマスのX座標 - * @param dir プレイヤーから見たターゲットの方角ID - * @return 実際に処理が行われた場合TRUEを返す。 - * @details - *
- * Assume destination is a closed/locked/jammed door
- * Assume there is no monster blocking the destination
- * Returns TRUE if repeated commands may continue
- * 
- */ -static bool do_cmd_bash_aux(POSITION y, POSITION x, DIRECTION dir) -{ - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - /* Get feature */ - feature_type *f_ptr = &f_info[g_ptr->feat]; - - /* Hack -- Bash power based on strength */ - /* (Ranges from 3 to 20 to 100 to 200) */ - int bash = adj_str_blow[p_ptr->stat_ind[A_STR]]; - - /* Extract door power */ - int temp = f_ptr->power; - - bool more = FALSE; - - concptr name = f_name + f_info[get_feat_mimic(g_ptr)].name; - - take_turn(p_ptr, 100); - - msg_format(_("%sに体当たりをした!", "You smash into the %s!"), name); - - /* Compare bash power to door power */ - temp = (bash - (temp * 10)); - - if (p_ptr->pclass == CLASS_BERSERKER) temp *= 2; - - /* Hack -- always have a chance */ - if (temp < 1) temp = 1; - - /* Hack -- attempt to bash down the door */ - if (randint0(100) < temp) - { - msg_format(_("%sを壊した!", "The %s crashes open!"), name); - - sound(have_flag(f_ptr->flags, FF_GLASS) ? SOUND_GLASS : SOUND_OPENDOOR); - - /* Break down the door */ - if ((randint0(100) < 50) || (feat_state(g_ptr->feat, FF_OPEN) == g_ptr->feat) || have_flag(f_ptr->flags, FF_GLASS)) - { - cave_alter_feat(y, x, FF_BASH); - } - - /* Open the door */ - else - { - cave_alter_feat(y, x, FF_OPEN); - } - - /* Hack -- Fall through the door */ - move_player(dir, FALSE, FALSE); - } - - /* Saving throw against stun */ - else if (randint0(100) < adj_dex_safe[p_ptr->stat_ind[A_DEX]] + - p_ptr->lev) - { - msg_format(_("この%sは頑丈だ。", "The %s holds firm."), name); - - /* Allow repeated bashing */ - more = TRUE; - } - - /* High dexterity yields coolness */ - else - { - msg_print(_("体のバランスをくずしてしまった。", "You are off-balance.")); - - /* Hack -- Lose balance ala paralysis */ - (void)set_paralyzed(p_ptr->paralyzed + 2 + randint0(2)); - } - return (more); -} - - -/*! - * @brief 「打ち破る」動作コマンドのメインルーチン / - * Bash open a door, success based on character strength - * @return なし - * @details - *
- * For a closed door, pval is positive if locked; negative if stuck.
- *
- * For an open door, pval is positive for a broken door.
- *
- * A closed door can be opened - harder if locked. Any door might be
- * bashed open (and thereby broken). Bashing a door is (potentially)
- * faster! You move into the door way. To open a stuck door, it must
- * be bashed. A closed door can be jammed (see do_cmd_spike()).
- *
- * Creatures can also open or bash doors, see elsewhere.
- * 
- */ -void do_cmd_bash(void) -{ - int y, x, dir; - grid_type *g_ptr; - bool more = FALSE; - - if (p_ptr->wild_mode) return; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir,FALSE)) - { - FEAT_IDX feat; - - /* Bash location */ - y = p_ptr->y + ddy[dir]; - x = p_ptr->x + ddx[dir]; - - g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - /* Feature code (applying "mimic" field) */ - feat = get_feat_mimic(g_ptr); - - /* Nothing useful */ - if (!have_flag(f_info[feat].flags, FF_BASH)) - { - msg_print(_("そこには体当たりするものが見当たらない。", "You see nothing there to bash.")); - } - - /* Monster in the way */ - else if (g_ptr->m_idx) - { - take_turn(p_ptr, 100); - - msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); - - /* Attack */ - py_attack(y, x, 0); - } - - /* Bash a closed door */ - else - { - /* Bash the door */ - more = do_cmd_bash_aux(y, x, dir); - } - } - - /* Unless valid action taken, cancel bash */ - if (!more) disturb(FALSE, FALSE); -} - - -/*! - * @brief 特定のマスに影響を及ぼすための汎用的コマンド - * @return なし - * @details - *
- * Manipulate an adjacent grid in some way
- *
- * Attack monsters, tunnel through walls, disarm traps, open doors.
- *
- * Consider confusion 
- *
- * This command must always take a current_world_ptr->game_turn, to prevent free detection
- * of invisible monsters.
- * 
- */ -void do_cmd_alter(void) -{ - POSITION y, x; - DIRECTION dir; - grid_type *g_ptr; - bool more = FALSE; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a direction */ - if (get_rep_dir(&dir,TRUE)) - { - FEAT_IDX feat; - feature_type *f_ptr; - - y = p_ptr->y + ddy[dir]; - x = p_ptr->x + ddx[dir]; - - g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - /* Feature code (applying "mimic" field) */ - feat = get_feat_mimic(g_ptr); - f_ptr = &f_info[feat]; - - take_turn(p_ptr, 100); - - if (g_ptr->m_idx) - { - py_attack(y, x, 0); - } - - /* Locked doors */ - else if (have_flag(f_ptr->flags, FF_OPEN)) - { - more = do_cmd_open_aux(y, x); - } - - /* Bash jammed doors */ - else if (have_flag(f_ptr->flags, FF_BASH)) - { - more = do_cmd_bash_aux(y, x, dir); - } - - /* Tunnel through walls */ - else if (have_flag(f_ptr->flags, FF_TUNNEL)) - { - more = do_cmd_tunnel_aux(y, x); - } - - /* Close open doors */ - else if (have_flag(f_ptr->flags, FF_CLOSE)) - { - more = do_cmd_close_aux(y, x); - } - - /* Disarm traps */ - else if (have_flag(f_ptr->flags, FF_DISARM)) - { - more = do_cmd_disarm_aux(y, x, dir); - } - - else - { - msg_print(_("何もない空中を攻撃した。", "You attack the empty air.")); - } - } - - /* Cancel repetition unless we can continue */ - if (!more) disturb(FALSE, FALSE); -} - - - -/*! - * @brief 「くさびを打つ」ために必要なオブジェクトがあるかどうかの判定を返す / - * Find the index of some "spikes", if possible. - * @param ip くさびとして打てるオブジェクトのID - * @return オブジェクトがある場合TRUEを返す - * @details - *
- * Let user choose a pile of spikes, perhaps?
- * 
- */ -static bool get_spike(INVENTORY_IDX *ip) -{ - INVENTORY_IDX i; - - /* Check every item in the pack */ - for (i = 0; i < INVEN_PACK; i++) - { - object_type *o_ptr = &inventory[i]; - - /* Skip non-objects */ - if (!o_ptr->k_idx) continue; - - /* Check the "tval" code */ - if (o_ptr->tval == TV_SPIKE) - { - /* Save the spike index */ - (*ip) = i; - - /* Success */ - return (TRUE); - } - } - - return (FALSE); -} - - -/*! - * @brief 「くさびを打つ」動作コマンドのメインルーチン / - * Jam a closed door with a spike - * @return なし - * @details - *
- * This command may NOT be repeated
- * 
- */ -void do_cmd_spike(void) -{ - DIRECTION dir; - - if (p_ptr->wild_mode) return; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir, FALSE)) - { - POSITION y, x; - INVENTORY_IDX item; - grid_type *g_ptr; - FEAT_IDX feat; - - y = p_ptr->y + ddy[dir]; - x = p_ptr->x + ddx[dir]; - g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - /* Feature code (applying "mimic" field) */ - feat = get_feat_mimic(g_ptr); - - /* Require closed door */ - if (!have_flag(f_info[feat].flags, FF_SPIKE)) - { - msg_print(_("そこにはくさびを打てるものが見当たらない。", "You see nothing there to spike.")); - } - - /* Get a spike */ - else if (!get_spike(&item)) - { - msg_print(_("くさびを持っていない!", "You have no spikes!")); - } - - /* Is a monster in the way? */ - else if (g_ptr->m_idx) - { - take_turn(p_ptr, 100); - - msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!")); - - /* Attack */ - py_attack(y, x, 0); - } - - /* Go for it */ - else - { - take_turn(p_ptr, 100); - - /* Successful jamming */ - msg_format(_("%sにくさびを打ち込んだ。", "You jam the %s with a spike."), f_name + f_info[feat].name); - cave_alter_feat(y, x, FF_SPIKE); - - /* Use up, and describe, a single spike, from the bottom */ - inven_item_increase(item, -1); - inven_item_describe(item); - inven_item_optimize(item); - } - } -} - - - -/*! - * @brief 「歩く」動作コマンドのメインルーチン / - * Support code for the "Walk" and "Jump" commands - * @param pickup アイテムの自動拾いを行うならTRUE - * @return なし - */ -void do_cmd_walk(bool pickup) -{ - DIRECTION dir; - - bool more = FALSE; - - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir, FALSE)) - { - take_turn(p_ptr, 100); - - if ((dir != 5) && (p_ptr->special_defense & KATA_MUSOU)) - { - set_action(ACTION_NONE); - } - - /* Hack -- In small scale wilderness it takes MUCH more time to move */ - if (p_ptr->wild_mode) p_ptr->energy_use *= ((MAX_HGT + MAX_WID) / 2); - if (p_ptr->action == ACTION_HAYAGAKE) p_ptr->energy_use = p_ptr->energy_use * (45-(p_ptr->lev/2)) / 100; - - /* Actually move the character */ - move_player(dir, pickup, FALSE); - - /* Allow more walking */ - more = TRUE; - } - - /* Hack again -- Is there a special encounter ??? */ - if (p_ptr->wild_mode && !cave_have_flag_bold(p_ptr->y, p_ptr->x, FF_TOWN)) - { - int tmp = 120 + p_ptr->lev*10 - wilderness[p_ptr->y][p_ptr->x].level + 5; - if (tmp < 1) - tmp = 1; - if (((wilderness[p_ptr->y][p_ptr->x].level + 5) > (p_ptr->lev / 2)) && randint0(tmp) < (21-p_ptr->skill_stl)) - { - /* Inform the player of his horrible fate :=) */ - msg_print(_("襲撃だ!", "You are ambushed !")); - - /* Go into large wilderness view */ - p_ptr->oldpy = randint1(MAX_HGT-2); - p_ptr->oldpx = randint1(MAX_WID-2); - change_wild_mode(); - - /* Give first move to monsters */ - take_turn(p_ptr, 100); - - /* HACk -- set the encouter flag for the wilderness generation */ - generate_encounter = TRUE; - } - } - - /* Cancel repeat unless we may continue */ - if (!more) disturb(FALSE, FALSE); -} - - -/*! - * @brief 「走る」動作コマンドのメインルーチン / - * Start running. - * @return なし - */ -void do_cmd_run(void) -{ - DIRECTION dir; - if (cmd_limit_confused(p_ptr)) return; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir,FALSE)) - { - /* Hack -- Set the run counter */ - running = (command_arg ? command_arg : 1000); - - /* First step */ - run_step(dir); - } -} - - -/*! - * @brief 「留まる」動作コマンドのメインルーチン / - * Stay still. Search. Enter stores. - * Pick up treasure if "pickup" is true. - * @param pickup アイテムの自動拾いを行うならTRUE - * @return なし - */ -void do_cmd_stay(bool pickup) -{ - u32b mpe_mode = MPE_STAYING | MPE_ENERGY_USE; - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - take_turn(p_ptr, 100); - - if (pickup) mpe_mode |= MPE_DO_PICKUP; - (void)move_player_effect(p_ptr->y, p_ptr->x, mpe_mode); -} - - -/*! - * @brief 「休む」動作コマンドのメインルーチン / - * Resting allows a player to safely restore his hp -RAK- - * @return なし - */ -void do_cmd_rest(void) -{ - - set_action(ACTION_NONE); - - if ((p_ptr->pclass == CLASS_BARD) && (SINGING_SONG_EFFECT(p_ptr) || INTERUPTING_SONG_EFFECT(p_ptr))) - { - stop_singing(p_ptr); - } - - /* Hex */ - if (hex_spelling_any()) stop_hex_spell_all(); - - /* Prompt for time if needed */ - if (command_arg <= 0) - { - concptr p = _("休憩 (0-9999, '*' で HP/MP全快, '&' で必要なだけ): ", - "Rest (0-9999, '*' for HP/SP, '&' as needed): "); - - - char out_val[80]; - - /* Default */ - strcpy(out_val, "&"); - - /* Ask for duration */ - if (!get_string(p, out_val, 4)) return; - - /* Rest until done */ - if (out_val[0] == '&') - { - command_arg = COMMAND_ARG_REST_UNTIL_DONE; - } - - /* Rest a lot */ - else if (out_val[0] == '*') - { - command_arg = COMMAND_ARG_REST_FULL_HEALING; - } - - /* Rest some */ - else - { - command_arg = (COMMAND_ARG)atoi(out_val); - if (command_arg <= 0) return; - } - } - - if (command_arg > 9999) command_arg = 9999; - - if (p_ptr->special_defense & NINJA_S_STEALTH) set_superstealth(FALSE); - - /* Take a current_world_ptr->game_turn (?) */ - take_turn(p_ptr, 100); - - /* The sin of sloth */ - if (command_arg > 100) chg_virtue(V_DILIGENCE, -1); - - /* Why are you sleeping when there's no need? WAKE UP!*/ - if ((p_ptr->chp == p_ptr->mhp) && - (p_ptr->csp == p_ptr->msp) && - !p_ptr->blind && !p_ptr->confused && - !p_ptr->poisoned && !p_ptr->afraid && - !p_ptr->stun && !p_ptr->cut && - !p_ptr->slow && !p_ptr->paralyzed && - !p_ptr->image && !p_ptr->word_recall && - !p_ptr->alter_reality) - chg_virtue(V_DILIGENCE, -1); - - /* Save the rest code */ - p_ptr->resting = command_arg; - p_ptr->action = ACTION_REST; - p_ptr->update |= (PU_BONUS); - update_creature(p_ptr); - - p_ptr->redraw |= (PR_STATE); - update_output(); - - Term_fresh(); -} - - - -/*! - * @brief 射撃処理のメインルーチン - * @return なし - */ -void do_cmd_fire(SPELL_IDX snipe_type) -{ - OBJECT_IDX item; - object_type *j_ptr, *ammo_ptr; - concptr q, s; - - if(p_ptr->wild_mode) return; - - is_fired = FALSE; /* not fired yet */ - - /* Get the "bow" (if any) */ - j_ptr = &inventory[INVEN_BOW]; - - /* Require a launcher */ - if (!j_ptr->tval) - { - msg_print(_("射撃用の武器を持っていない。", "You have nothing to fire with.")); - flush(); - return; - } - - if (j_ptr->sval == SV_CRIMSON) - { - msg_print(_("この武器は発動して使うもののようだ。", "Do activate.")); - flush(); - return; - } - - if (j_ptr->sval == SV_HARP) - { - msg_print(_("この武器で射撃はできない。", "It's not for firing.")); - flush(); - return; - } - - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - /* Require proper missile */ - item_tester_tval = p_ptr->tval_ammo; - - q = _("どれを撃ちますか? ", "Fire which item? "); - s = _("発射されるアイテムがありません。", "You have nothing to fire."); - - - ammo_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR)); - if (!ammo_ptr) - { - flush(); - return; - } - - /* Fire the item */ - exe_fire(item, j_ptr, snipe_type); - - if (!is_fired || p_ptr->pclass != CLASS_SNIPER) return; - - /* Sniper actions after some shootings */ - if (snipe_type == SP_AWAY) - { - teleport_player(10 + (p_ptr->concent * 2), 0L); - } - if (snipe_type == SP_FINAL) - { - msg_print(_("射撃の反動が体を襲った。", "A reactionary of shooting attacked you. ")); - (void)set_slow(p_ptr->slow + randint0(7) + 7, FALSE); - (void)set_stun(p_ptr->stun + randint1(25)); - } -} - - -/*! - * @brief 投射処理メインルーチン / - * Throw an object from the pack or floor. - * @param mult 威力の倍率 - * @param boomerang ブーメラン処理ならばTRUE - * @param shuriken 忍者の手裏剣処理ならばTRUE - * @return ターンを消費した場合TRUEを返す - * @details - *
- * Note: "unseen" monsters are very hard to hit.
- *
- * Should throwing a weapon do full damage?  Should it allow the magic
- * to hit bonus of the weapon to have an effect?  Should it ever cause
- * the item to be destroyed?  Should it do any damage at all?
- * 
- */ -bool do_cmd_throw(int mult, bool boomerang, OBJECT_IDX shuriken) -{ - DIRECTION dir; - OBJECT_IDX item; - int i; - POSITION y, x, ty, tx, prev_y, prev_x; - POSITION ny[19], nx[19]; - int chance, tdam, tdis; - int mul, div, dd, ds; - int cur_dis, visible; - PERCENTAGE j; - - object_type forge; - object_type *q_ptr; - object_type *o_ptr; - - bool hit_body = FALSE; - bool hit_wall = FALSE; - bool equiped_item = FALSE; - bool return_when_thrown = FALSE; - - GAME_TEXT o_name[MAX_NLEN]; - - int msec = delay_factor * delay_factor * delay_factor; - - BIT_FLAGS flgs[TR_FLAG_SIZE]; - concptr q, s; - bool come_back = FALSE; - bool do_drop = TRUE; - - if (p_ptr->wild_mode) return FALSE; - - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - - if (shuriken >= 0) - { - item = shuriken; - o_ptr = &inventory[item]; - } - else if (boomerang) - { - if (has_melee_weapon(INVEN_RARM) && has_melee_weapon(INVEN_LARM)) - { - item_tester_hook = item_tester_hook_boomerang; - q = _("どの武器を投げますか? ", "Throw which item? "); - s = _("投げる武器がない。", "You have nothing to throw."); - o_ptr = choose_object(&item, q, s, (USE_EQUIP)); - if (!o_ptr) - { - flush(); - return FALSE; - } - } - else if (has_melee_weapon(INVEN_LARM)) - { - item = INVEN_LARM; - o_ptr = &inventory[item]; - } - else - { - item = INVEN_RARM; - o_ptr = &inventory[item]; - } - } - else - { - q = _("どのアイテムを投げますか? ", "Throw which item? "); - s = _("投げるアイテムがない。", "You have nothing to throw."); - o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EQUIP)); - if (!o_ptr) - { - flush(); - return FALSE; - } - } - - /* Item is cursed */ - if (object_is_cursed(o_ptr) && (item >= INVEN_RARM)) - { - msg_print(_("ふーむ、どうやら呪われているようだ。", "Hmmm, it seems to be cursed.")); - return FALSE; - } - - if (p_ptr->inside_arena && !boomerang) - { - if (o_ptr->tval != TV_SPIKE) - { - msg_print(_("アリーナではアイテムを使えない!", "You're in the arena now. This is hand-to-hand!")); - msg_print(NULL); - - return FALSE; - } - - } - q_ptr = &forge; - - /* Obtain a local object */ - object_copy(q_ptr, o_ptr); - - /* Extract the thrown object's flags. */ - object_flags(q_ptr, flgs); - torch_flags(q_ptr, flgs); - - /* Distribute the charges of rods/wands between the stacks */ - distribute_charges(o_ptr, q_ptr, 1); - - /* Single object */ - q_ptr->number = 1; - - object_desc(o_name, q_ptr, OD_OMIT_PREFIX); - - if (p_ptr->mighty_throw) mult += 3; - - /* Extract a "distance multiplier" */ - /* Changed for 'launcher' mutation */ - mul = 10 + 2 * (mult - 1); - - /* Enforce a minimum "weight" of one pound */ - div = ((q_ptr->weight > 10) ? q_ptr->weight : 10); - if ((have_flag(flgs, TR_THROW)) || boomerang) div /= 2; - - /* Hack -- Distance -- Reward strength, penalize weight */ - tdis = (adj_str_blow[p_ptr->stat_ind[A_STR]] + 20) * mul / div; - - /* Max distance of 10-18 */ - if (tdis > mul) tdis = mul; - - if (shuriken >= 0) - { - ty = randint0(101) - 50 + p_ptr->y; - tx = randint0(101) - 50 + p_ptr->x; - } - else - { - project_length = tdis + 1; - - /* Get a direction (or cancel) */ - if (!get_aim_dir(&dir)) return FALSE; - - /* Predict the "target" location */ - tx = p_ptr->x + 99 * ddx[dir]; - ty = p_ptr->y + 99 * ddy[dir]; - - /* Check for "target request" */ - if ((dir == 5) && target_okay()) - { - tx = target_col; - ty = target_row; - } - - project_length = 0; /* reset to default */ - } - - if ((q_ptr->name1 == ART_MJOLLNIR) || - (q_ptr->name1 == ART_AEGISFANG) || boomerang) - return_when_thrown = TRUE; - - /* Reduce and describe inventory */ - if (item >= 0) - { - inven_item_increase(item, -1); - if (!return_when_thrown) - inven_item_describe(item); - inven_item_optimize(item); - } - - /* Reduce and describe floor item */ - else - { - floor_item_increase(0 - item, -1); - floor_item_optimize(0 - item); - } - if (item >= INVEN_RARM) - { - equiped_item = TRUE; - p_ptr->redraw |= (PR_EQUIPPY); - } - - take_turn(p_ptr, 100); - - /* Rogue and Ninja gets bonus */ - if ((p_ptr->pclass == CLASS_ROGUE) || (p_ptr->pclass == CLASS_NINJA)) - p_ptr->energy_use -= p_ptr->lev; - - /* Start at the player */ - y = p_ptr->y; - x = p_ptr->x; - - handle_stuff(); - - if ((p_ptr->pclass == CLASS_NINJA) && ((q_ptr->tval == TV_SPIKE) || ((have_flag(flgs, TR_THROW)) && (q_ptr->tval == TV_SWORD)))) shuriken = TRUE; - else shuriken = FALSE; - - /* Chance of hitting */ - if (have_flag(flgs, TR_THROW)) chance = ((p_ptr->skill_tht) + - ((p_ptr->to_h_b + q_ptr->to_h) * BTH_PLUS_ADJ)); - else chance = (p_ptr->skill_tht + (p_ptr->to_h_b * BTH_PLUS_ADJ)); - - if (shuriken) chance *= 2; - - prev_y = y; - prev_x = x; - - /* Travel until stopped */ - for (cur_dis = 0; cur_dis <= tdis; ) - { - /* Hack -- Stop at the target */ - if ((y == ty) && (x == tx)) break; - - /* Calculate the new location (see "project()") */ - ny[cur_dis] = y; - nx[cur_dis] = x; - mmove2(&ny[cur_dis], &nx[cur_dis], p_ptr->y, p_ptr->x, ty, tx); - - /* Stopped by walls/doors */ - if (!cave_have_flag_bold(ny[cur_dis], nx[cur_dis], FF_PROJECT)) - { - hit_wall = TRUE; - if ((q_ptr->tval == TV_FIGURINE) || object_is_potion(q_ptr) || !current_floor_ptr->grid_array[ny[cur_dis]][nx[cur_dis]].m_idx) break; - } - - /* The player can see the (on screen) missile */ - if (panel_contains(ny[cur_dis], nx[cur_dis]) && player_can_see_bold(ny[cur_dis], nx[cur_dis])) - { - SYMBOL_CODE c = object_char(q_ptr); - TERM_COLOR a = object_attr(q_ptr); - - /* Draw, Hilite, Fresh, Pause, Erase */ - print_rel(c, a, ny[cur_dis], nx[cur_dis]); - move_cursor_relative(ny[cur_dis], nx[cur_dis]); - Term_fresh(); - Term_xtra(TERM_XTRA_DELAY, msec); - lite_spot(ny[cur_dis], nx[cur_dis]); - Term_fresh(); - } - - /* The player cannot see the missile */ - else - { - /* Pause anyway, for consistancy */ - Term_xtra(TERM_XTRA_DELAY, msec); - } - - prev_y = y; - prev_x = x; - - /* Save the new location */ - x = nx[cur_dis]; - y = ny[cur_dis]; - - /* Advance the distance */ - cur_dis++; - - /* Monster here, Try to hit it */ - if (current_floor_ptr->grid_array[y][x].m_idx) - { - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; - monster_type *m_ptr = ¤t_floor_ptr->m_list[g_ptr->m_idx]; - GAME_TEXT m_name[MAX_NLEN]; - monster_name(g_ptr->m_idx, m_name); - - /* Check the visibility */ - visible = m_ptr->ml; - - /* Note the collision */ - hit_body = TRUE; - - /* Did we hit it (penalize range) */ - if (test_hit_fire(chance - cur_dis, m_ptr, m_ptr->ml, o_name)) - { - bool fear = FALSE; - - /* Handle unseen monster */ - if (!visible) - { - /* Invisible monster */ - msg_format(_("%sが敵を捕捉した。", "The %s finds a mark."), o_name); - } - - /* Handle visible monster */ - else - { - msg_format(_("%sが%sに命中した。", "The %s hits %s."), o_name, m_name); - - if (m_ptr->ml) - { - if (!p_ptr->image) monster_race_track(m_ptr->ap_r_idx); - health_track(g_ptr->m_idx); - } - } - - /* Hack -- Base damage from thrown object */ - dd = q_ptr->dd; - ds = q_ptr->ds; - torch_dice(q_ptr, &dd, &ds); /* throwing a torch */ - tdam = damroll(dd, ds); - /* Apply special damage */ - tdam = tot_dam_aux(q_ptr, tdam, m_ptr, 0, TRUE); - tdam = critical_shot(q_ptr->weight, q_ptr->to_h, 0, tdam); - if (q_ptr->to_d > 0) - tdam += q_ptr->to_d; - else - tdam += -q_ptr->to_d; - - if (boomerang) - { - tdam *= (mult+p_ptr->num_blow[item - INVEN_RARM]); - tdam += p_ptr->to_d_m; - } - else if (have_flag(flgs, TR_THROW)) - { - tdam *= (3+mult); - tdam += p_ptr->to_d_m; - } - else - { - tdam *= mult; - } - if (shuriken) - { - tdam += ((p_ptr->lev+30)*(p_ptr->lev+30)-900)/55; - } - - /* No negative damage */ - if (tdam < 0) tdam = 0; - - /* Modify the damage */ - tdam = mon_damage_mod(m_ptr, tdam, FALSE); - - msg_format_wizard(CHEAT_MONSTER, _("%dのダメージを与えた。(残りHP %d/%d(%d))", "You do %d damage. (left HP %d/%d(%d))"), - tdam, m_ptr->hp - tdam, m_ptr->maxhp, m_ptr->max_maxhp); - - /* Hit the monster, check for death */ - if (mon_take_hit(g_ptr->m_idx, tdam, &fear, extract_note_dies(real_r_idx(m_ptr)))) - { - /* Dead monster */ - } - - /* No death */ - else - { - message_pain(g_ptr->m_idx, tdam); - - /* Anger the monster */ - if ((tdam > 0) && !object_is_potion(q_ptr)) - anger_monster(m_ptr); - - if (fear && m_ptr->ml) - { - sound(SOUND_FLEE); - msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), m_name); - } - } - } - - /* Stop looking */ - break; - } - } - - /* decrease toach's fuel */ - if (hit_body) torch_lost_fuel(q_ptr); - - /* Chance of breakage (during attacks) */ - j = (hit_body ? breakage_chance(q_ptr, 0) : 0); - - /* Figurines transform */ - if ((q_ptr->tval == TV_FIGURINE) && !(p_ptr->inside_arena)) - { - j = 100; - - if (!(summon_named_creature(0, y, x, q_ptr->pval, !(object_is_cursed(q_ptr)) ? PM_FORCE_PET : 0L))) - msg_print(_("人形は捻じ曲がり砕け散ってしまった!", "The Figurine writhes and then shatters.")); - else if (object_is_cursed(q_ptr)) - msg_print(_("これはあまり良くない気がする。", "You have a bad feeling about this.")); - - } - - /* Potions smash open */ - if (object_is_potion(q_ptr)) - { - if (hit_body || hit_wall || (randint1(100) < j)) - { - msg_format(_("%sは砕け散った!", "The %s shatters!"), o_name); - - if (potion_smash_effect(0, y, x, q_ptr->k_idx)) - { - monster_type *m_ptr = ¤t_floor_ptr->m_list[current_floor_ptr->grid_array[y][x].m_idx]; - if (current_floor_ptr->grid_array[y][x].m_idx && is_friendly(m_ptr) && !MON_INVULNER(m_ptr)) - { - GAME_TEXT m_name[MAX_NLEN]; - monster_desc(m_name, m_ptr, 0); - msg_format(_("%sは怒った!", "%^s gets angry!"), m_name); - set_hostile(¤t_floor_ptr->m_list[current_floor_ptr->grid_array[y][x].m_idx]); - } - } - do_drop = FALSE; - } - else - { - j = 0; - } - } - - if (return_when_thrown) - { - int back_chance = randint1(30)+20+((int)(adj_dex_th[p_ptr->stat_ind[A_DEX]]) - 128); - char o2_name[MAX_NLEN]; - bool super_boomerang = (((q_ptr->name1 == ART_MJOLLNIR) || (q_ptr->name1 == ART_AEGISFANG)) && boomerang); - - j = -1; - if (boomerang) back_chance += 4+randint1(5); - if (super_boomerang) back_chance += 100; - object_desc(o2_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - - if((back_chance > 30) && (!one_in_(100) || super_boomerang)) - { - for (i = cur_dis - 1; i > 0; i--) - { - if (panel_contains(ny[i], nx[i]) && player_can_see_bold(ny[i], nx[i])) - { - char c = object_char(q_ptr); - byte a = object_attr(q_ptr); - - /* Draw, Hilite, Fresh, Pause, Erase */ - print_rel(c, a, ny[i], nx[i]); - move_cursor_relative(ny[i], nx[i]); - Term_fresh(); - Term_xtra(TERM_XTRA_DELAY, msec); - lite_spot(ny[i], nx[i]); - Term_fresh(); - } - else - { - /* Pause anyway, for consistancy */ - Term_xtra(TERM_XTRA_DELAY, msec); - } - } - if((back_chance > 37) && !p_ptr->blind && (item >= 0)) - { - msg_format(_("%sが手元に返ってきた。", "%s comes back to you."), o2_name); - come_back = TRUE; - } - else - { - if (item >= 0) - { - msg_format(_("%sを受け損ねた!", "%s backs, but you can't catch!"), o2_name); - } - else - { - msg_format(_("%sが返ってきた。", "%s comes back."), o2_name); - } - y = p_ptr->y; - x = p_ptr->x; - } - } - else - { - msg_format(_("%sが返ってこなかった!", "%s doesn't back!"), o2_name); - } - } - - if (come_back) - { - if (item == INVEN_RARM || item == INVEN_LARM) - { - /* Access the wield slot */ - o_ptr = &inventory[item]; - - /* Wear the new stuff */ - object_copy(o_ptr, q_ptr); - - p_ptr->total_weight += q_ptr->weight; - - /* Increment the equip counter by hand */ - equip_cnt++; - - p_ptr->update |= (PU_BONUS | PU_TORCH | PU_MANA); - p_ptr->window |= (PW_EQUIP); - } - else - { - inven_carry(q_ptr); - } - do_drop = FALSE; - } - else if (equiped_item) - { - kamaenaoshi(item); - calc_android_exp(); - } - - if (do_drop) - { - if (cave_have_flag_bold(y, x, FF_PROJECT)) - { - (void)drop_near(q_ptr, j, y, x); - } - else - { - (void)drop_near(q_ptr, j, prev_y, prev_x); - } - } - - return TRUE; -} - -/*! - * @brief 自殺するコマンドのメインルーチン - * Hack -- commit suicide - * @return なし - * @details - */ -void do_cmd_suicide(void) -{ - int i; - - /* Flush input */ - flush(); - - /* Verify Retirement */ - if (p_ptr->total_winner) - { - /* Verify */ - if (!get_check_strict(_("引退しますか? ", "Do you want to retire? "), CHECK_NO_HISTORY)) return; - } - - /* Verify Suicide */ - else - { - /* Verify */ - if (!get_check(_("本当に自殺しますか?", "Do you really want to commit suicide? "))) return; - } - - - if (!p_ptr->noscore) - { - /* Special Verification for suicide */ - prt(_("確認のため '@' を押して下さい。", "Please verify SUICIDE by typing the '@' sign: "), 0, 0); - - flush(); - i = inkey(); - prt("", 0, 0); - if (i != '@') return; - - play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_GAMEOVER); - } - - /* Initialize "last message" buffer */ - if (p_ptr->last_message) string_free(p_ptr->last_message); - p_ptr->last_message = NULL; - - /* Hack -- Note *winning* message */ - if (p_ptr->total_winner && last_words) - { - char buf[1024] = ""; - play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_WINNER); - do - { - while (!get_string(_("*勝利*メッセージ: ", "*Winning* message: "), buf, sizeof buf)); - } while (!get_check_strict(_("よろしいですか?", "Are you sure? "), CHECK_NO_HISTORY)); - - if (buf[0]) - { - p_ptr->last_message = string_make(buf); - msg_print(p_ptr->last_message); - } - } - - /* Stop playing */ - p_ptr->playing = FALSE; - - /* Kill the player */ - p_ptr->is_dead = TRUE; - p_ptr->leaving = TRUE; - - if (!p_ptr->total_winner) - { - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("ダンジョンの探索に絶望して自殺した。", "give up all hope to commit suicide.")); - do_cmd_write_nikki(NIKKI_GAMESTART, 1, _("-------- ゲームオーバー --------", "-------- Game Over --------")); - do_cmd_write_nikki(NIKKI_BUNSHOU, 1, "\n\n\n\n"); - } - - /* Cause of death */ - (void)strcpy(p_ptr->died_from, _("途中終了", "Quitting")); -} diff --git a/src/cmd4.c b/src/cmd4.c deleted file mode 100644 index 64da996d8..000000000 --- a/src/cmd4.c +++ /dev/null @@ -1,8291 +0,0 @@ -/*! - * @file cmd4.c - * @brief プレイヤーのインターフェイスに関するコマンドの実装 / Interface commands - * @date 2014/01/02 - * @author - *
- * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
- * This software may be copied and distributed for educational, research,
- * and not for profit purposes provided that this copyright and statement
- * are included in all such copies.  Other copyrights may also apply.
- * 
- * @details - *
- * A set of functions to maintain automatic dumps of various kinds.
- * -Mogami-
- * remove_auto_dump(orig_file, mark)
- *     Remove the old automatic dump of type "mark".
- * auto_dump_printf(fmt, ...)
- *     Dump a formatted string using fprintf().
- * open_auto_dump(buf, mark)
- *     Open a file, remove old dump, and add new header.
- * close_auto_dump(void)
- *     Add a footer, and close the file.
- *    The dump commands of original Angband simply add new lines to
- * existing files; these files will become bigger and bigger unless
- * an user deletes some or all of these files by hand at some
- * point.
- *     These three functions automatically delete old dumped lines 
- * before adding new ones.  Since there are various kinds of automatic 
- * dumps in a single file, we add a header and a footer with a type 
- * name for every automatic dump, and kill old lines only when the 
- * lines have the correct type of header and footer.
- *     We need to be quite paranoid about correctness; the user might 
- * (mistakenly) edit the file by hand, and see all their work come
- * to nothing on the next auto dump otherwise.  The current code only 
- * detects changes by noting inconsistencies between the actual number 
- * of lines and the number written in the footer.  Note that this will 
- * not catch single-line edits.
- * 
- */ - -#include "angband.h" -#include "cmd-pet.h" -#include "world.h" -#include "player-status.h" -#include "sort.h" -#include "mutation.h" -#include "quest.h" -#include "store.h" -#include "artifact.h" -#include "avatar.h" -#include "object-hook.h" -#include "monster.h" -#include "monster-status.h" - - -/* - */ - -/* - * Mark strings for auto dump - */ -static char auto_dump_header[] = "# vvvvvvv== %s ==vvvvvvv"; -static char auto_dump_footer[] = "# ^^^^^^^== %s ==^^^^^^^"; - -/* - * Variables for auto dump - */ -static FILE *auto_dump_stream; -static concptr auto_dump_mark; -static int auto_dump_line_num; - - -/*! - * @brief prf出力内容を消去する / - * Remove old lines automatically generated before. - * @param orig_file 消去を行うファイル名 - */ -static void remove_auto_dump(concptr orig_file) -{ - FILE *tmp_fff, *orig_fff; - - char tmp_file[1024]; - char buf[1024]; - bool between_mark = FALSE; - bool changed = FALSE; - int line_num = 0; - long header_location = 0; - char header_mark_str[80]; - char footer_mark_str[80]; - size_t mark_len; - - /* Prepare a header/footer mark string */ - sprintf(header_mark_str, auto_dump_header, auto_dump_mark); - sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark); - - mark_len = strlen(footer_mark_str); - - /* Open an old dump file in read-only mode */ - orig_fff = my_fopen(orig_file, "r"); - - /* If original file does not exist, nothing to do */ - if (!orig_fff) return; - - /* Open a new (temporary) file */ - tmp_fff = my_fopen_temp(tmp_file, 1024); - - if (!tmp_fff) - { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file); - msg_print(NULL); - return; - } - - /* Loop for every line */ - while (TRUE) - { - /* Read a line */ - if (my_fgets(orig_fff, buf, sizeof(buf))) - { - /* Read error: Assume End of File */ - - /* - * Was looking for the footer, but not found. - * - * Since automatic dump might be edited by hand, - * it's dangerous to kill these lines. - * Seek back to the next line of the (pseudo) header, - * and read again. - */ - if (between_mark) - { - fseek(orig_fff, header_location, SEEK_SET); - between_mark = FALSE; - continue; - } - - /* Success -- End the loop */ - else - { - break; - } - } - - /* We are looking for the header mark of automatic dump */ - if (!between_mark) - { - /* Is this line a header? */ - if (!strcmp(buf, header_mark_str)) - { - /* Memorise seek point of this line */ - header_location = ftell(orig_fff); - - /* Initialize counter for number of lines */ - line_num = 0; - - /* Look for the footer from now */ - between_mark = TRUE; - - /* There are some changes */ - changed = TRUE; - } - - /* Not a header */ - else - { - /* Copy orginally lines */ - fprintf(tmp_fff, "%s\n", buf); - } - } - - /* We are looking for the footer mark of automatic dump */ - else - { - /* Is this line a footer? */ - if (!strncmp(buf, footer_mark_str, mark_len)) - { - int tmp; - - /* - * Compare the number of lines - * - * If there is an inconsistency between - * actual number of lines and the - * number here, the automatic dump - * might be edited by hand. So it's - * dangerous to kill these lines. - * Seek back to the next line of the - * (pseudo) header, and read again. - */ - if (!sscanf(buf + mark_len, " (%d)", &tmp) - || tmp != line_num) - { - fseek(orig_fff, header_location, SEEK_SET); - } - - /* Look for another header */ - between_mark = FALSE; - } - - /* Not a footer */ - else - { - /* Ignore old line, and count number of lines */ - line_num++; - } - } - } - - /* Close files */ - my_fclose(orig_fff); - my_fclose(tmp_fff); - - /* If there are some changes, overwrite the original file with new one */ - if (changed) - { - /* Copy contents of temporary file */ - - tmp_fff = my_fopen(tmp_file, "r"); - orig_fff = my_fopen(orig_file, "w"); - - while (!my_fgets(tmp_fff, buf, sizeof(buf))) - fprintf(orig_fff, "%s\n", buf); - - my_fclose(orig_fff); - my_fclose(tmp_fff); - } - - /* Kill the temporary file */ - fd_kill(tmp_file); - - return; -} - - -/*! - * @brief prfファイルのフォーマットに従った内容を出力する / - * Dump a formatted line, using "vstrnfmt()". - * @param fmt 出力内容 - */ -static void auto_dump_printf(concptr fmt, ...) -{ - concptr p; - va_list vp; - - char buf[1024]; - - /* Begin the Varargs Stuff */ - va_start(vp, fmt); - - /* Format the args, save the length */ - (void)vstrnfmt(buf, sizeof(buf), fmt, vp); - - /* End the Varargs Stuff */ - va_end(vp); - - /* Count number of lines */ - for (p = buf; *p; p++) - { - if (*p == '\n') auto_dump_line_num++; - } - - /* Dump it */ - fprintf(auto_dump_stream, "%s", buf); -} - - -/*! - * @brief prfファイルをファイルオープンする / - * Open file to append auto dump. - * @param buf ファイル名 - * @param mark 出力するヘッダマーク - * @return ファイルポインタを取得できたらTRUEを返す - */ -static bool open_auto_dump(concptr buf, concptr mark) -{ - - char header_mark_str[80]; - - /* Save the mark string */ - auto_dump_mark = mark; - - /* Prepare a header mark string */ - sprintf(header_mark_str, auto_dump_header, auto_dump_mark); - - /* Remove old macro dumps */ - remove_auto_dump(buf); - - /* Append to the file */ - auto_dump_stream = my_fopen(buf, "a"); - - /* Failure */ - if (!auto_dump_stream) { - msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf); - msg_print(NULL); - - /* Failed */ - return FALSE; - } - - /* Start dumping */ - fprintf(auto_dump_stream, "%s\n", header_mark_str); - - /* Initialize counter */ - auto_dump_line_num = 0; - - auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n", - "# *Warning!* The lines below are an automatic dump.\n")); - auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n", - "# Don't edit them; changes will be deleted and replaced automatically.\n")); - /* Success */ - return TRUE; -} - -/*! - * @brief prfファイルをファイルクローズする / - * Append foot part and close auto dump. - * @return なし - */ -static void close_auto_dump(void) -{ - char footer_mark_str[80]; - - /* Prepare a footer mark string */ - sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark); - - auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n", - "# *Warning!* The lines below are an automatic dump.\n")); - auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n", - "# Don't edit them; changes will be deleted and replaced automatically.\n")); - /* End of dump */ - fprintf(auto_dump_stream, "%s (%d)\n", footer_mark_str, auto_dump_line_num); - - /* Close */ - my_fclose(auto_dump_stream); - - return; -} - - -#ifndef JP - -/*! - * @brief Return suffix of ordinal number - * @param num number - * @return pointer of suffix string. - */ -concptr get_ordinal_number_suffix(int num) -{ - num = ABS(num) % 100; - switch (num % 10) - { - case 1: - return (num == 11) ? "th" : "st"; - case 2: - return (num == 12) ? "th" : "nd"; - case 3: - return (num == 13) ? "th" : "rd"; - default: - return "th"; - } -} -#endif - - -/*! - * @brief 日記にメッセージを追加する / - * Take note to the diary. - * @param type 日記内容のID - * @param num 日記内容のIDに応じた数値 - * @param note 日記内容のIDに応じた文字列参照ポインタ - * @return エラーID - */ -errr do_cmd_write_nikki(int type, int num, concptr note) -{ - int day, hour, min; - FILE *fff = NULL; - GAME_TEXT file_name[MAX_NLEN]; - char buf[1024]; - concptr note_level = ""; - bool do_level = TRUE; - char note_level_buf[40]; - QUEST_IDX q_idx; - - static bool disable_nikki = FALSE; - - extract_day_hour_min(&day, &hour, &min); - - if (disable_nikki) return(-1); - - if (type == NIKKI_FIX_QUEST_C || - type == NIKKI_FIX_QUEST_F || - type == NIKKI_RAND_QUEST_C || - type == NIKKI_RAND_QUEST_F || - type == NIKKI_TO_QUEST) - { - QUEST_IDX old_quest; - - old_quest = p_ptr->inside_quest; - p_ptr->inside_quest = (quest[num].type == QUEST_TYPE_RANDOM) ? 0 : num; - - /* Get the quest text */ - init_flags = INIT_NAME_ONLY; - - process_dungeon_file("q_info.txt", 0, 0, 0, 0); - - /* Reset the old quest number */ - p_ptr->inside_quest = old_quest; - } - - /* different filne name to avoid mixing */ - sprintf(file_name,_("playrecord-%s.txt", "playrec-%s.txt"),savefile_base); - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - fff = my_fopen(buf, "a"); - - /* Failure */ - if (!fff) - { - msg_format(_("%s を開くことができませんでした。プレイ記録を一時停止します。", "Failed to open %s. Play-Record is disabled temporally."), buf); - msg_format(NULL); - disable_nikki=TRUE; - return (-1); - } - - q_idx = quest_number(current_floor_ptr->dun_level); - - if (write_level) - { - if (p_ptr->inside_arena) - note_level = _("アリーナ:", "Arane:"); - else if (!current_floor_ptr->dun_level) - note_level = _("地上:", "Surface:"); - else if (q_idx && (is_fixed_quest_idx(q_idx) - && !((q_idx == QUEST_OBERON) || (q_idx == QUEST_SERPENT)))) - note_level = _("クエスト:", "Quest:"); - else - { -#ifdef JP - sprintf(note_level_buf, "%d階(%s):", (int)current_floor_ptr->dun_level, d_name+d_info[p_ptr->dungeon_idx].name); -#else - sprintf(note_level_buf, "%s L%d:", d_name+d_info[p_ptr->dungeon_idx].name, (int)current_floor_ptr->dun_level); -#endif - note_level = note_level_buf; - } - } - - switch(type) - { - case NIKKI_HIGAWARI: - { - if (day < MAX_DAYS) fprintf(fff, _("%d日目\n", "Day %d\n"), day); - else fputs(_("*****日目\n", "Day *****\n"), fff); - do_level = FALSE; - break; - } - case NIKKI_BUNSHOU: - { - if (num) - { - fprintf(fff, "%s\n",note); - do_level = FALSE; - } - else - fprintf(fff, " %2d:%02d %20s %s\n",hour, min, note_level, note); - break; - } - case NIKKI_ART: - { - fprintf(fff, _(" %2d:%02d %20s %sを発見した。\n", " %2d:%02d %20s discovered %s.\n"), hour, min, note_level, note); - break; - } - case NIKKI_ART_SCROLL: - { - fprintf(fff, _(" %2d:%02d %20s 巻物によって%sを生成した。\n", " %2d:%02d %20s created %s by scroll.\n"), hour, min, note_level, note); - break; - } - case NIKKI_UNIQUE: - { - fprintf(fff, _(" %2d:%02d %20s %sを倒した。\n", " %2d:%02d %20s defeated %s.\n"), hour, min, note_level, note); - break; - } - case NIKKI_FIX_QUEST_C: - { - if (quest[num].flags & QUEST_FLAG_SILENT) break; - fprintf(fff, _(" %2d:%02d %20s クエスト「%s」を達成した。\n", - " %2d:%02d %20s completed quest '%s'.\n"), hour, min, note_level, quest[num].name); - break; - } - case NIKKI_FIX_QUEST_F: - { - if (quest[num].flags & QUEST_FLAG_SILENT) break; - fprintf(fff, _(" %2d:%02d %20s クエスト「%s」から命からがら逃げ帰った。\n", - " %2d:%02d %20s run away from quest '%s'.\n"), hour, min, note_level, quest[num].name); - break; - } - case NIKKI_RAND_QUEST_C: - { - GAME_TEXT name[MAX_NLEN]; - strcpy(name, r_name+r_info[quest[num].r_idx].name); - fprintf(fff, _(" %2d:%02d %20s ランダムクエスト(%s)を達成した。\n", - " %2d:%02d %20s completed random quest '%s'\n"), hour, min, note_level, name); - break; - } - case NIKKI_RAND_QUEST_F: - { - GAME_TEXT name[MAX_NLEN]; - strcpy(name, r_name+r_info[quest[num].r_idx].name); - fprintf(fff, _(" %2d:%02d %20s ランダムクエスト(%s)から逃げ出した。\n", - " %2d:%02d %20s ran away from quest '%s'.\n"), hour, min, note_level, name); - break; - } - case NIKKI_MAXDEAPTH: - { - fprintf(fff, _(" %2d:%02d %20s %sの最深階%d階に到達した。\n", - " %2d:%02d %20s reached level %d of %s for the first time.\n"), hour, min, note_level, - _(d_name+d_info[p_ptr->dungeon_idx].name, num), - _(num, d_name+d_info[p_ptr->dungeon_idx].name)); - break; - } - case NIKKI_TRUMP: - { - fprintf(fff, _(" %2d:%02d %20s %s%sの最深階を%d階にセットした。\n", - " %2d:%02d %20s reset recall level of %s to %d %s.\n"), hour, min, note_level, note, - _(d_name + d_info[num].name, (int)max_dlv[num]), - _((int)max_dlv[num], d_name + d_info[num].name)); - break; - } - case NIKKI_STAIR: - { - concptr to; - if (q_idx && (is_fixed_quest_idx(q_idx) - && !((q_idx == QUEST_OBERON) || (q_idx == QUEST_SERPENT)))) - { - to = _("地上", "the surface"); - } - else - { - if (!(current_floor_ptr->dun_level+num)) to = _("地上", "the surface"); - else to = format(_("%d階", "level %d"), current_floor_ptr->dun_level+num); - } - fprintf(fff, _(" %2d:%02d %20s %sへ%s。\n", " %2d:%02d %20s %s %s.\n"), hour, min, note_level, _(to, note), _(note, to)); - break; - } - case NIKKI_RECALL: - { - if (!num) - fprintf(fff, _(" %2d:%02d %20s 帰還を使って%sの%d階へ下りた。\n", " %2d:%02d %20s recalled to dungeon level %d of %s.\n"), - hour, min, note_level, _(d_name+d_info[p_ptr->dungeon_idx].name, (int)max_dlv[p_ptr->dungeon_idx]), - _((int)max_dlv[p_ptr->dungeon_idx], d_name+d_info[p_ptr->dungeon_idx].name)); - else - fprintf(fff, _(" %2d:%02d %20s 帰還を使って地上へと戻った。\n", " %2d:%02d %20s recalled from dungeon to surface.\n"), hour, min, note_level); - break; - } - case NIKKI_TO_QUEST: - { - if (quest[num].flags & QUEST_FLAG_SILENT) break; - fprintf(fff, _(" %2d:%02d %20s クエスト「%s」へと突入した。\n", " %2d:%02d %20s entered the quest '%s'.\n"), - hour, min, note_level, quest[num].name); - break; - } - case NIKKI_TELE_LEV: - { - fprintf(fff, _(" %2d:%02d %20s レベル・テレポートで脱出した。\n", " %2d:%02d %20s Got out using teleport level.\n"), - hour, min, note_level); - break; - } - case NIKKI_BUY: - { - fprintf(fff, _(" %2d:%02d %20s %sを購入した。\n", " %2d:%02d %20s bought %s.\n"), hour, min, note_level, note); - break; - } - case NIKKI_SELL: - { - fprintf(fff, _(" %2d:%02d %20s %sを売却した。\n", " %2d:%02d %20s sold %s.\n"), hour, min, note_level, note); - break; - } - case NIKKI_ARENA: - { - if (num < 0) - { - int n = -num; - fprintf(fff, _(" %2d:%02d %20s 闘技場の%d%s回戦で、%sの前に敗れ去った。\n", " %2d:%02d %20s beaten by %s in the %d%s fight.\n"), - hour, min, note_level, _(n, note), _("", n), _(note, get_ordinal_number_suffix(n))); - break; - } - fprintf(fff, _(" %2d:%02d %20s 闘技場の%d%s回戦(%s)に勝利した。\n", " %2d:%02d %20s won the %d%s fight (%s).\n"), - hour, min, note_level, num, _("", get_ordinal_number_suffix(num)), note); - - if (num == MAX_ARENA_MONS) - { - fprintf(fff, _(" 闘技場のすべての敵に勝利し、チャンピオンとなった。\n", - " won all fight to become a Chanpion.\n")); - do_level = FALSE; - } - break; - } - case NIKKI_HANMEI: - { - fprintf(fff, _(" %2d:%02d %20s %sを識別した。\n", " %2d:%02d %20s identified %s.\n"), hour, min, note_level, note); - break; - } - case NIKKI_WIZ_TELE: - { - concptr to; - if (!current_floor_ptr->dun_level) - to = _("地上", "the surface"); - else - to = format(_("%d階(%s)", "level %d of %s"), current_floor_ptr->dun_level, d_name+d_info[p_ptr->dungeon_idx].name); - - fprintf(fff, _(" %2d:%02d %20s %sへとウィザード・テレポートで移動した。\n", - " %2d:%02d %20s wizard-teleport to %s.\n"), hour, min, note_level, to); - break; - } - case NIKKI_PAT_TELE: - { - concptr to; - if (!current_floor_ptr->dun_level) - to = _("地上", "the surface"); - else - to = format(_("%d階(%s)", "level %d of %s"), current_floor_ptr->dun_level, d_name+d_info[p_ptr->dungeon_idx].name); - - fprintf(fff, _(" %2d:%02d %20s %sへとパターンの力で移動した。\n", - " %2d:%02d %20s used Pattern to teleport to %s.\n"), hour, min, note_level, to); - break; - } - case NIKKI_LEVELUP: - { - fprintf(fff, _(" %2d:%02d %20s レベルが%dに上がった。\n", " %2d:%02d %20s reached player level %d.\n"), hour, min, note_level, num); - break; - } - case NIKKI_GAMESTART: - { - time_t ct = time((time_t*)0); - do_level = FALSE; - if (num) - { - fprintf(fff, "%s %s",note, ctime(&ct)); - } - else - fprintf(fff, " %2d:%02d %20s %s %s",hour, min, note_level, note, ctime(&ct)); - break; - } - case NIKKI_NAMED_PET: - { - fprintf(fff, " %2d:%02d %20s ", hour, min, note_level); - switch (num) - { - case RECORD_NAMED_PET_NAME: - fprintf(fff, _("%sを旅の友にすることに決めた。\n", "decided to travel together with %s.\n"), note); - break; - case RECORD_NAMED_PET_UNNAME: - fprintf(fff, _("%sの名前を消した。\n", "unnamed %s.\n"), note); - break; - case RECORD_NAMED_PET_DISMISS: - fprintf(fff, _("%sを解放した。\n", "dismissed %s.\n"), note); - break; - case RECORD_NAMED_PET_DEATH: - fprintf(fff, _("%sが死んでしまった。\n", "%s died.\n"), note); - break; - case RECORD_NAMED_PET_MOVED: - fprintf(fff, _("%sをおいて別のマップへ移動した。\n", "moved to another map leaving %s behind.\n"), note); - break; - case RECORD_NAMED_PET_LOST_SIGHT: - fprintf(fff, _("%sとはぐれてしまった。\n", "lost sight of %s.\n"), note); - break; - case RECORD_NAMED_PET_DESTROY: - fprintf(fff, _("%sが*破壊*によって消え去った。\n", "%s was made disappeared by *destruction*.\n"), note); - break; - case RECORD_NAMED_PET_EARTHQUAKE: - fprintf(fff, _("%sが岩石に押し潰された。\n", "%s was crushed by falling rocks.\n"), note); - break; - case RECORD_NAMED_PET_GENOCIDE: - fprintf(fff, _("%sが抹殺によって消え去った。\n", "%s was made disappeared by genocide.\n"), note); - break; - case RECORD_NAMED_PET_WIZ_ZAP: - fprintf(fff, _("%sがデバッグコマンドによって消え去った。\n", "%s was removed by debug command.\n"), note); - break; - case RECORD_NAMED_PET_TELE_LEVEL: - fprintf(fff, _("%sがテレポート・レベルによって消え去った。\n", "%s was made disappeared by teleport level.\n"), note); - break; - case RECORD_NAMED_PET_BLAST: - fprintf(fff, _("%sを爆破した。\n", "blasted %s.\n"), note); - break; - case RECORD_NAMED_PET_HEAL_LEPER: - fprintf(fff, _("%sの病気が治り旅から外れた。\n", "%s was healed and left.\n"), note); - break; - case RECORD_NAMED_PET_COMPACT: - fprintf(fff, _("%sがモンスター情報圧縮によって消え去った。\n", "%s was made disappeared by compacting monsters.\n"), note); - break; - case RECORD_NAMED_PET_LOSE_PARENT: - fprintf(fff, _("%sの召喚者が既にいないため消え去った。\n", "%s disappeared because there does not exist summoner.\n"), note); - break; - - - default: - fprintf(fff, "\n"); - break; - } - break; - } - - case NIKKI_WIZARD_LOG: - fprintf(fff, "%s\n", note); - break; - - default: - break; - } - - my_fclose(fff); - - if (do_level) write_level = FALSE; - - return (0); -} - - -#define MAX_SUBTITLE (sizeof(subtitle)/sizeof(subtitle[0])) - -/*! - * @brief 日記のタイトル表記と内容出力 / - * @return なし - * @details - * 日記のタイトルは本関数の subtitle ローカル変数で定義されている。 - */ -static void do_cmd_disp_nikki(void) -{ - char nikki_title[256]; - GAME_TEXT file_name[MAX_NLEN]; - char buf[1024]; - char tmp[80]; -#ifdef JP - /*! */ - static const char subtitle[][30] = {"最強の肉体を求めて", - "人生それははかない", - "明日に向かって", - "棚からぼたもち", - "あとの祭り", - "それはいい考えだ", - "何とでも言え", - "兎にも角にも", - "ウソだけど", - "もはやこれまで", - "なんでこうなるの", - "それは無理だ", - "倒すべき敵はゲ○ツ", - "ん~?聞こえんなぁ", - "オレの名を言ってみろ", - "頭が変になっちゃった", - "互換しません", - "せっかくだから", - "まだまだ甘いね", - "むごいむごすぎる", - "こんなもんじゃない", - "だめだこりゃ", - "次いってみよう", - "ちょっとだけよ", - "哀しき冒険者", - "野望の果て", - "無限地獄", - "神に喧嘩を売る者", - "未知の世界へ", - "最高の頭脳を求めて"}; -#else - static const char subtitle[][51] ={"Quest of The World's Toughest Body", - "Attack is the best form of defence.", - "Might is right.", - "An unexpected windfall", - "A drowning man will catch at a straw", - "Don't count your chickens before they are hatched.", - "It is no use crying over spilt milk.", - "Seeing is believing.", - "Strike the iron while it is hot.", - "I don't care what follows.", - "To dig a well to put out a house on fire.", - "Tomorrow is another day.", - "Easy come, easy go.", - "The more haste, the less speed.", - "Where there is life, there is hope.", - "There is no royal road to *WINNER*.", - "Danger past, God forgotten.", - "The best thing to do now is to run away.", - "Life is but an empty dream.", - "Dead men tell no tales.", - "A book that remains shut is but a block.", - "Misfortunes never come singly.", - "A little knowledge is a dangerous thing.", - "History repeats itself.", - "*WINNER* was not built in a day.", - "Ignorance is bliss.", - "To lose is to win?", - "No medicine can cure folly.", - "All good things come to an end.", - "M$ Empire strikes back.", - "To see is to believe", - "Time is money.", - "Quest of The World's Greatest Brain"}; -#endif - sprintf(file_name,_("playrecord-%s.txt", "playrec-%s.txt"),savefile_base); - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name); - - if (p_ptr->pclass == CLASS_WARRIOR || p_ptr->pclass == CLASS_MONK || p_ptr->pclass == CLASS_SAMURAI || p_ptr->pclass == CLASS_BERSERKER) - strcpy(tmp,subtitle[randint0(MAX_SUBTITLE-1)]); - else if (IS_WIZARD_CLASS()) - strcpy(tmp,subtitle[randint0(MAX_SUBTITLE-1)+1]); - else strcpy(tmp,subtitle[randint0(MAX_SUBTITLE-2)+1]); - -#ifdef JP - sprintf(nikki_title, "「%s%s%sの伝説 -%s-」", ap_ptr->title, ap_ptr->no ? "の" : "", p_ptr->name, tmp); -#else - sprintf(nikki_title, "Legend of %s %s '%s'", ap_ptr->title, p_ptr->name, tmp); -#endif - - /* Display the file contents */ - show_file(FALSE, buf, nikki_title, -1, 0); -} - -/*! - * @brief 日記に任意の内容を表記するコマンドのメインルーチン / - * @return なし - */ -static void do_cmd_bunshou(void) -{ - char tmp[80] = "\0"; - char bunshou[80] = "\0"; - - if (get_string(_("内容: ", "diary note: "), tmp, 79)) - { - strcpy(bunshou, tmp); - - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, bunshou); - } -} - -/*! - * @brief 最後に取得したアイテムの情報を日記に追加するメインルーチン / - * @return なし - */ -static void do_cmd_last_get(void) -{ - char buf[256]; - GAME_TURN turn_tmp; - - if (record_o_name[0] == '\0') return; - - sprintf(buf,_("%sの入手を記録します。", "Do you really want to record getting %s? "),record_o_name); - if (!get_check(buf)) return; - - turn_tmp = current_world_ptr->game_turn; - current_world_ptr->game_turn = record_turn; - sprintf(buf,_("%sを手に入れた。", "descover %s."), record_o_name); - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, buf); - current_world_ptr->game_turn = turn_tmp; -} - -/*! - * @brief ファイル中の全日記記録を消去する / - * @return なし - */ -static void do_cmd_erase_nikki(void) -{ - GAME_TEXT file_name[MAX_NLEN]; - char buf[256]; - FILE *fff = NULL; - - if (!get_check(_("本当に記録を消去しますか?", "Do you really want to delete all your record? "))) return; - sprintf(file_name,_("playrecord-%s.txt", "playrec-%s.txt"),savefile_base); - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name); - fd_kill(buf); - - fff = my_fopen(buf, "w"); - if(fff){ - my_fclose(fff); - msg_format(_("記録を消去しました。", "deleted record.")); - }else{ - msg_format(_("%s の消去に失敗しました。", "failed to delete %s."), buf); - } - msg_print(NULL); -} - -/*! - * @brief 日記コマンド - * @return なし - */ -void do_cmd_nikki(void) -{ - int i; - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - screen_save(); - - /* Interact until done */ - while (1) - { - Term_clear(); - - /* Ask for a choice */ - prt(_("[ 記録の設定 ]", "[ Play Record ]"), 2, 0); - - /* Give some choices */ - prt(_("(1) 記録を見る", "(1) Display your record"), 4, 5); - prt(_("(2) 文章を記録する", "(2) Add record"), 5, 5); - prt(_("(3) 直前に入手又は鑑定したものを記録する", "(3) Record item you last get/identify"), 6, 5); - prt(_("(4) 記録を消去する", "(4) Delete your record"), 7, 5); - - prt(_("(R) プレイ動画を記録する/中止する", "(R) Record playing movie / or stop it"), 9, 5); - - /* Prompt */ - prt(_("コマンド:", "Command: "), 18, 0); - - /* Prompt */ - i = inkey(); - - if (i == ESCAPE) break; - - switch (i) - { - case '1': - do_cmd_disp_nikki(); - break; - case '2': - do_cmd_bunshou(); - break; - case '3': - do_cmd_last_get(); - break; - case '4': - do_cmd_erase_nikki(); - break; - case 'r': case 'R': - screen_load(); - prepare_movie_hooks(); - return; - default: /* Unknown option */ - bell(); - } - - msg_erase(); - } - screen_load(); -} - -/*! - * @brief 画面を再描画するコマンドのメインルーチン - * Hack -- redraw the screen - * @return なし - * @details - *
- * This command performs various low level updates, clears all the "extra"
- * windows, does a total redraw of the main window, and requests all of the
- * interesting updates and redraws that I can think of.
- *
- * This command is also used to "instantiate" the results of the user
- * selecting various things, such as graphics mode, so it must call
- * the "TERM_XTRA_REACT" hook before redrawing the windows.
- * 
- */ -void do_cmd_redraw(void) -{ - int j; - term *old = Term; - - - /* Hack -- react to changes */ - Term_xtra(TERM_XTRA_REACT, 0); - - /* Combine and Reorder the pack (later) */ - p_ptr->update |= (PU_COMBINE | PU_REORDER); - p_ptr->update |= (PU_TORCH); - p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS); - p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE); - p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE); - p_ptr->update |= (PU_MONSTERS); - - p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY); - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER); - p_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_DUNGEON | PW_MONSTER | PW_OBJECT); - - update_playtime(); - - handle_stuff(); - - if (p_ptr->prace == RACE_ANDROID) calc_android_exp(); - - - /* Redraw every window */ - for (j = 0; j < 8; j++) - { - /* Dead window */ - if (!angband_term[j]) continue; - - /* Activate */ - Term_activate(angband_term[j]); - Term_redraw(); - Term_fresh(); - Term_activate(old); - } -} - - -/*! - * @brief 名前を変更するコマンドのメインルーチン - * Hack -- change name - * @return なし - */ -void do_cmd_change_name(void) -{ - char c; - - int mode = 0; - - char tmp[160]; - - screen_save(); - - /* Forever */ - while (1) - { - update_playtime(); - - /* Display the player */ - display_player(mode); - - if (mode == 4) - { - mode = 0; - display_player(mode); - } - - /* Prompt */ -#ifdef JP - Term_putstr(2, 23, -1, TERM_WHITE, - "['c'で名前変更, 'f'でファイルへ書出, 'h'でモード変更, ESCで終了]"); -#else - Term_putstr(2, 23, -1, TERM_WHITE, - "['c' to change name, 'f' to file, 'h' to change mode, or ESC]"); -#endif - - - /* Query */ - c = inkey(); - - /* Exit */ - if (c == ESCAPE) break; - - /* Change name */ - if (c == 'c') - { - get_name(); - - /* Process the player name */ - process_player_name(FALSE); - } - - /* File dump */ - else if (c == 'f') - { - sprintf(tmp, "%s.txt", player_base); - if (get_string(_("ファイル名: ", "File name: "), tmp, 80)) - { - if (tmp[0] && (tmp[0] != ' ')) - { - file_character(tmp); - } - } - } - - /* Toggle mode */ - else if (c == 'h') - { - mode++; - } - else - { - bell(); - } - - msg_erase(); - } - screen_load(); - p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY); - - handle_stuff(); -} - - -/*! - * @brief 最近表示されたメッセージを再表示するコマンドのメインルーチン - * Recall the most recent message - * @return なし - */ -void do_cmd_message_one(void) -{ - /* Recall one message */ - prt(format("> %s", message_str(0)), 0, 0); -} - - -/*! - * @brief メッセージのログを表示するコマンドのメインルーチン - * Recall the most recent message - * @return なし - * @details - *
- * Show previous messages to the user	-BEN-
- *
- * The screen format uses line 0 and 23 for headers and prompts,
- * skips line 1 and 22, and uses line 2 thru 21 for old messages.
- *
- * This command shows you which commands you are viewing, and allows
- * you to "search" for strings in the recall.
- *
- * Note that messages may be longer than 80 characters, but they are
- * displayed using "infinite" length, with a special sub-command to
- * "slide" the virtual display to the left or right.
- *
- * Attempt to only hilite the matching portions of the string.
- * 
- */ -void do_cmd_messages(int num_now) -{ - int i, n; - - char shower_str[81]; - char finder_str[81]; - char back_str[81]; - concptr shower = NULL; - int wid, hgt; - int num_lines; - - Term_get_size(&wid, &hgt); - - /* Number of message lines in a screen */ - num_lines = hgt - 4; - - /* Wipe finder */ - strcpy(finder_str, ""); - - /* Wipe shower */ - strcpy(shower_str, ""); - - /* Total messages */ - n = message_num(); - - /* Start on first message */ - i = 0; - screen_save(); - Term_clear(); - - /* Process requests until done */ - while (1) - { - int j; - int skey; - - /* Dump up to 20 lines of messages */ - for (j = 0; (j < num_lines) && (i + j < n); j++) - { - concptr msg = message_str(i+j); - - /* Dump the messages, bottom to top */ - c_prt((i + j < num_now ? TERM_WHITE : TERM_SLATE), msg, num_lines + 1 - j, 0); - - /* Hilite "shower" */ - if (shower && shower[0]) - { - concptr str = msg; - - /* Display matches */ - while ((str = my_strstr(str, shower)) != NULL) - { - int len = strlen(shower); - - /* Display the match */ - Term_putstr(str-msg, num_lines + 1 - j, len, TERM_YELLOW, shower); - - /* Advance */ - str += len; - } - } - } - - /* Erase remaining lines */ - for (; j < num_lines; j++) - { - Term_erase(0, num_lines + 1 - j, 255); - } - - /* Display header */ - /* translation */ - prt(format(_("以前のメッセージ %d-%d 全部で(%d)", "Message Recall (%d-%d of %d)"), - i, i + j - 1, n), 0, 0); - - /* Display prompt (not very informative) */ - prt(_("[ 'p' で更に古いもの, 'n' で更に新しいもの, '/' で検索, ESC で中断 ]", - "[Press 'p' for older, 'n' for newer, ..., or ESCAPE]"), hgt - 1, 0); - - skey = inkey_special(TRUE); - - /* Exit on Escape */ - if (skey == ESCAPE) break; - - /* Hack -- Save the old index */ - j = i; - - switch (skey) - { - /* Hack -- handle show */ - case '=': - /* Prompt */ - prt(_("強調: ", "Show: "), hgt - 1, 0); - - /* Get a "shower" string, or continue */ - strcpy(back_str, shower_str); - if (askfor(shower_str, 80)) - { - /* Show it */ - shower = shower_str[0] ? shower_str : NULL; - } - else strcpy(shower_str, back_str); - - continue; - - /* Hack -- handle find */ - case '/': - case KTRL('s'): - { - int z; - - /* Prompt */ - prt(_("検索: ", "Find: "), hgt - 1, 0); - - /* Get a "finder" string, or continue */ - strcpy(back_str, finder_str); - if (!askfor(finder_str, 80)) - { - strcpy(finder_str, back_str); - continue; - } - else if (!finder_str[0]) - { - shower = NULL; /* Stop showing */ - continue; - } - - /* Show it */ - shower = finder_str; - - /* Scan messages */ - for (z = i + 1; z < n; z++) - { - concptr msg = message_str(z); - - /* Search for it */ - if (my_strstr(msg, finder_str)) - { - /* New location */ - i = z; - - break; - } - } - } - break; - - /* Recall 1 older message */ - case SKEY_TOP: - /* Go to the oldest line */ - i = n - num_lines; - break; - - /* Recall 1 newer message */ - case SKEY_BOTTOM: - /* Go to the newest line */ - i = 0; - break; - - /* Recall 1 older message */ - case '8': - case SKEY_UP: - case '\n': - case '\r': - /* Go older if legal */ - i = MIN(i + 1, n - num_lines); - break; - - /* Recall 10 older messages */ - case '+': - /* Go older if legal */ - i = MIN(i + 10, n - num_lines); - break; - - /* Recall 20 older messages */ - case 'p': - case KTRL('P'): - case ' ': - case SKEY_PGUP: - /* Go older if legal */ - i = MIN(i + num_lines, n - num_lines); - break; - - /* Recall 20 newer messages */ - case 'n': - case KTRL('N'): - case SKEY_PGDOWN: - /* Go newer (if able) */ - i = MAX(0, i - num_lines); - break; - - /* Recall 10 newer messages */ - case '-': - /* Go newer (if able) */ - i = MAX(0, i - 10); - break; - - /* Recall 1 newer messages */ - case '2': - case SKEY_DOWN: - /* Go newer (if able) */ - i = MAX(0, i - 1); - break; - } - - /* Hack -- Error of some kind */ - if (i == j) bell(); - } - screen_load(); -} - - -/*! - * @brief チートオプションを変更するコマンドのメインルーチン - * Interact with some options for cheating - * @param info 表示メッセージ - * @return なし - */ -static void do_cmd_options_cheat(concptr info) -{ - char ch; - int i, k = 0, n = CHEAT_MAX; - char buf[80]; - Term_clear(); - - /* Interact with the player */ - while (TRUE) - { - DIRECTION dir; - - /* Prompt */ - sprintf(buf, _("%s ( リターンで次へ, y/n でセット, ESC で決定 )", "%s (RET to advance, y/n to set, ESC to accept) "), info); - - prt(buf, 0, 0); - -#ifdef JP - /* 詐欺オプションをうっかりいじってしまう人がいるようなので注意 */ - prt(" << 注意 >>", 11, 0); - prt(" 詐欺オプションを一度でも設定すると、スコア記録が残らなくなります!", 12, 0); - prt(" 後に解除してもダメですので、勝利者を目指す方はここのオプションはい", 13, 0); - prt(" じらないようにして下さい。", 14, 0); -#endif - /* Display the options */ - for (i = 0; i < n; i++) - { - byte a = TERM_WHITE; - - /* Color current option */ - if (i == k) a = TERM_L_BLUE; - - /* Display the option text */ - sprintf(buf, "%-48s: %s (%s)", - cheat_info[i].o_desc, - (*cheat_info[i].o_var ? _("はい ", "yes") : _("いいえ", "no ")), - cheat_info[i].o_text); - c_prt(a, buf, i + 2, 0); - } - - /* Hilite current option */ - move_cursor(k + 2, 50); - - /* Get a key */ - ch = inkey(); - - /* - * HACK - Try to translate the key into a direction - * to allow using the roguelike keys for navigation. - */ - dir = get_keymap_dir(ch); - if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) - ch = I2D(dir); - - /* Analyze */ - switch (ch) - { - case ESCAPE: - { - return; - } - - case '-': - case '8': - { - k = (n + k - 1) % n; - break; - } - - case ' ': - case '\n': - case '\r': - case '2': - { - k = (k + 1) % n; - break; - } - - case 'y': - case 'Y': - case '6': - { - if(!p_ptr->noscore) - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, - _("詐欺オプションをONにして、スコアを残せなくなった。", "give up sending score to use cheating options.")); - p_ptr->noscore |= (cheat_info[k].o_set * 256 + cheat_info[k].o_bit); - (*cheat_info[k].o_var) = TRUE; - k = (k + 1) % n; - break; - } - - case 'n': - case 'N': - case '4': - { - (*cheat_info[k].o_var) = FALSE; - k = (k + 1) % n; - break; - } - - case '?': - { - strnfmt(buf, sizeof(buf), _("joption.txt#%s", "option.txt#%s"), cheat_info[k].o_text); - /* Peruse the help file */ - (void)show_file(TRUE, buf, NULL, 0, 0); - - Term_clear(); - break; - } - - default: - { - bell(); - break; - } - } - } -} - - -/*! - * @brief セーブ頻度ターンの次の値を返す - * @param current 現在のセーブ頻度ターン値 - * @return 次のセーブ頻度ターン値 - */ -static s16b toggle_frequency(s16b current) -{ - switch (current) - { - case 0: return 50; - case 50: return 100; - case 100: return 250; - case 250: return 500; - case 500: return 1000; - case 1000: return 2500; - case 2500: return 5000; - case 5000: return 10000; - case 10000: return 25000; - default: return 0; - } -} - - -/*! - * @brief 自動セーブオプションを変更するコマンドのメインルーチン - * @param info 表示メッセージ - * @return なし - */ -static void do_cmd_options_autosave(concptr info) -{ - char ch; - int i, k = 0, n = 2; - char buf[80]; - - Term_clear(); - - /* Interact with the player */ - while (TRUE) - { - /* Prompt */ - sprintf(buf, _("%s ( リターンで次へ, y/n でセット, F で頻度を入力, ESC で決定 ) ", - "%s (RET to advance, y/n to set, 'F' for frequency, ESC to accept) "), info); - - prt(buf, 0, 0); - - /* Display the options */ - for (i = 0; i < n; i++) - { - byte a = TERM_WHITE; - - /* Color current option */ - if (i == k) a = TERM_L_BLUE; - - /* Display the option text */ - sprintf(buf, "%-48s: %s (%s)", - autosave_info[i].o_desc, - (*autosave_info[i].o_var ? _("はい ", "yes") : _("いいえ", "no ")), - autosave_info[i].o_text); - c_prt(a, buf, i + 2, 0); - } - prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"), autosave_freq), 5, 0); - - /* Hilite current option */ - move_cursor(k + 2, 50); - - /* Get a key */ - ch = inkey(); - - /* Analyze */ - switch (ch) - { - case ESCAPE: - { - return; - } - - case '-': - case '8': - { - k = (n + k - 1) % n; - break; - } - - case ' ': - case '\n': - case '\r': - case '2': - { - k = (k + 1) % n; - break; - } - - case 'y': - case 'Y': - case '6': - { - - (*autosave_info[k].o_var) = TRUE; - k = (k + 1) % n; - break; - } - - case 'n': - case 'N': - case '4': - { - (*autosave_info[k].o_var) = FALSE; - k = (k + 1) % n; - break; - } - - case 'f': - case 'F': - { - autosave_freq = toggle_frequency(autosave_freq); - prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"), autosave_freq), 5, 0); - break; - } - - case '?': - { - (void)show_file(TRUE, _("joption.txt#Autosave", "option.txt#Autosave"), NULL, 0, 0); - Term_clear(); - break; - } - - default: - { - bell(); - break; - } - } - } -} - - -/*! - * @brief 標準オプションを変更するコマンドのサブルーチン / - * Interact with some options - * @param page オプションページ番号 - * @param info 表示メッセージ - * @return なし - */ -void do_cmd_options_aux(int page, concptr info) -{ - char ch; - int i, k = 0, n = 0, l; - int opt[24]; - char buf[80]; - bool browse_only = (page == OPT_PAGE_BIRTH) && character_generated && - (!p_ptr->wizard || !allow_debug_opts); - - - /* Lookup the options */ - for (i = 0; i < 24; i++) opt[i] = 0; - - /* Scan the options */ - for (i = 0; option_info[i].o_desc; i++) - { - /* Notice options on this "page" */ - if (option_info[i].o_page == page) opt[n++] = i; - } - Term_clear(); - - /* Interact with the player */ - while (TRUE) - { - DIRECTION dir; - - /* Prompt */ - sprintf(buf, _("%s (リターン:次, %sESC:終了, ?:ヘルプ) ", "%s (RET:next, %s, ?:help) "), - info, browse_only ? _("", "ESC:exit") : _("y/n:変更, ", "y/n:change, ESC:accept")); - prt(buf, 0, 0); - - /* HACK -- description for easy-auto-destroy options */ - if (page == OPT_PAGE_AUTODESTROY) - c_prt(TERM_YELLOW, _("以下のオプションは、簡易自動破壊を使用するときのみ有効", - "Following options will protect items from easy auto-destroyer."), 6, _(6, 3)); - - /* Display the options */ - for (i = 0; i < n; i++) - { - byte a = TERM_WHITE; - - /* Color current option */ - if (i == k) a = TERM_L_BLUE; - - /* Display the option text */ - sprintf(buf, "%-48s: %s (%.19s)", - option_info[opt[i]].o_desc, - (*option_info[opt[i]].o_var ? _("はい ", "yes") : _("いいえ", "no ")), - option_info[opt[i]].o_text); - if ((page == OPT_PAGE_AUTODESTROY) && i > 2) c_prt(a, buf, i + 5, 0); - else c_prt(a, buf, i + 2, 0); - } - - if ((page == OPT_PAGE_AUTODESTROY) && (k > 2)) l = 3; - else l = 0; - - /* Hilite current option */ - move_cursor(k + 2 + l, 50); - - /* Get a key */ - ch = inkey(); - - /* - * HACK - Try to translate the key into a direction - * to allow using the roguelike keys for navigation. - */ - dir = get_keymap_dir(ch); - if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) - ch = I2D(dir); - - /* Analyze */ - switch (ch) - { - case ESCAPE: - { - return; - } - - case '-': - case '8': - { - k = (n + k - 1) % n; - break; - } - - case ' ': - case '\n': - case '\r': - case '2': - { - k = (k + 1) % n; - break; - } - - case 'y': - case 'Y': - case '6': - { - if (browse_only) break; - (*option_info[opt[k]].o_var) = TRUE; - k = (k + 1) % n; - break; - } - - case 'n': - case 'N': - case '4': - { - if (browse_only) break; - (*option_info[opt[k]].o_var) = FALSE; - k = (k + 1) % n; - break; - } - - case 't': - case 'T': - { - if (!browse_only) (*option_info[opt[k]].o_var) = !(*option_info[opt[k]].o_var); - break; - } - - case '?': - { - strnfmt(buf, sizeof(buf), _("joption.txt#%s", "option.txt#%s"), option_info[opt[k]].o_text); - /* Peruse the help file */ - (void)show_file(TRUE, buf, NULL, 0, 0); - - Term_clear(); - break; - } - - default: - { - bell(); - break; - } - } - } -} - - -/*! - * @brief ウィンドウオプションを変更するコマンドのメインルーチン / - * Modify the "window" options - * @return なし - */ -static void do_cmd_options_win(void) -{ - int i, j, d; - TERM_LEN y = 0; - TERM_LEN x = 0; - char ch; - bool go = TRUE; - u32b old_flag[8]; - - - /* Memorize old flags */ - for (j = 0; j < 8; j++) - { - /* Acquire current flags */ - old_flag[j] = window_flag[j]; - } - - Term_clear(); - - /* Interact */ - while (go) - { - /* Prompt */ - prt(_("ウィンドウ・フラグ (<方向>で移動, tでチェンジ, y/n でセット, ESC)", "Window Flags (, t, y, n, ESC) "), 0, 0); - - /* Display the windows */ - for (j = 0; j < 8; j++) - { - byte a = TERM_WHITE; - - concptr s = angband_term_name[j]; - - /* Use color */ - if (j == x) a = TERM_L_BLUE; - - /* Window name, staggered, centered */ - Term_putstr(35 + j * 5 - strlen(s) / 2, 2 + j % 2, -1, a, s); - } - - /* Display the options */ - for (i = 0; i < 16; i++) - { - byte a = TERM_WHITE; - - concptr str = window_flag_desc[i]; - - /* Use color */ - if (i == y) a = TERM_L_BLUE; - - /* Unused option */ - if (!str) str = _("(未使用)", "(Unused option)"); - - /* Flag name */ - Term_putstr(0, i + 5, -1, a, str); - - /* Display the windows */ - for (j = 0; j < 8; j++) - { - char c = '.'; - a = TERM_WHITE; - - /* Use color */ - if ((i == y) && (j == x)) a = TERM_L_BLUE; - - /* Active flag */ - if (window_flag[j] & (1L << i)) c = 'X'; - - /* Flag value */ - Term_putch(35 + j * 5, i + 5, a, c); - } - } - - /* Place Cursor */ - Term_gotoxy(35 + x * 5, y + 5); - - /* Get key */ - ch = inkey(); - - /* Analyze */ - switch (ch) - { - case ESCAPE: - { - go = FALSE; - break; - } - - case 'T': - case 't': - { - /* Clear windows */ - for (j = 0; j < 8; j++) - { - window_flag[j] &= ~(1L << y); - } - - /* Clear flags */ - for (i = 0; i < 16; i++) - { - window_flag[x] &= ~(1L << i); - } - - /* Fall through */ - } - - case 'y': - case 'Y': - { - /* Ignore screen */ - if (x == 0) break; - - /* Set flag */ - window_flag[x] |= (1L << y); - break; - } - - case 'n': - case 'N': - { - /* Clear flag */ - window_flag[x] &= ~(1L << y); - break; - } - - case '?': - { - (void)show_file(TRUE, _("joption.txt#Window", "option.txt#Window"), NULL, 0, 0); - - Term_clear(); - break; - } - - default: - { - d = get_keymap_dir(ch); - - x = (x + ddx[d] + 8) % 8; - y = (y + ddy[d] + 16) % 16; - - if (!d) bell(); - } - } - } - - /* Notice changes */ - for (j = 0; j < 8; j++) - { - term *old = Term; - - /* Dead window */ - if (!angband_term[j]) continue; - - /* Ignore non-changes */ - if (window_flag[j] == old_flag[j]) continue; - - /* Activate */ - Term_activate(angband_term[j]); - Term_clear(); - Term_fresh(); - Term_activate(old); - } -} - - - -#define OPT_NUM 15 - -static struct opts -{ - char key; - concptr name; - int row; -} -option_fields[OPT_NUM] = -{ -#ifdef JP - { '1', " キー入力 オプション", 3 }, - { '2', " マップ画面 オプション", 4 }, - { '3', " テキスト表示 オプション", 5 }, - { '4', " ゲームプレイ オプション", 6 }, - { '5', " 行動中止関係 オプション", 7 }, - { '6', " 簡易自動破壊 オプション", 8 }, - { 'r', " プレイ記録 オプション", 9 }, - - { 'p', "自動拾いエディタ", 11 }, - { 'd', " 基本ウェイト量 ", 12 }, - { 'h', "低ヒットポイント", 13 }, - { 'm', " 低魔力色閾値 ", 14 }, - { 'a', " 自動セーブ オプション", 15 }, - { 'w', "ウインドウフラグ", 16 }, - - { 'b', " 初期 オプション (参照のみ)", 18 }, - { 'c', " 詐欺 オプション", 19 }, -#else - { '1', "Input Options", 3 }, - { '2', "Map Screen Options", 4 }, - { '3', "Text Display Options", 5 }, - { '4', "Game-Play Options", 6 }, - { '5', "Disturbance Options", 7 }, - { '6', "Easy Auto-Destroyer Options", 8 }, - { 'r', "Play record Options", 9 }, - - { 'p', "Auto-picker/destroyer editor", 11 }, - { 'd', "Base Delay Factor", 12 }, - { 'h', "Hitpoint Warning", 13 }, - { 'm', "Mana Color Threshold", 14 }, - { 'a', "Autosave Options", 15 }, - { 'w', "Window Flags", 16 }, - - { 'b', "Birth Options (Browse Only)", 18 }, - { 'c', "Cheat Options", 19 }, -#endif -}; - - -/*! - * @brief 標準オプションを変更するコマンドのメインルーチン / - * Set or unset various options. - * @return なし - * @details - *
- * The user must use the "Ctrl-R" command to "adapt" to changes
- * in any options which control "visual" aspects of the game.
- * 
- */ -void do_cmd_options(void) -{ - char k; - int d, skey; - TERM_LEN i, y = 0; - screen_save(); - - /* Interact */ - while (1) - { - int n = OPT_NUM; - - /* Does not list cheat option when cheat option is off */ - if (!p_ptr->noscore && !allow_debug_opts) n--; - Term_clear(); - - /* Why are we here */ - prt(_("[ オプションの設定 ]", "TinyAngband options"), 1, 0); - - while(1) - { - /* Give some choices */ - for (i = 0; i < n; i++) - { - byte a = TERM_WHITE; - if (i == y) a = TERM_L_BLUE; - Term_putstr(5, option_fields[i].row, -1, a, - format("(%c) %s", toupper(option_fields[i].key), option_fields[i].name)); - } - - prt(_("<方向>で移動, Enterで決定, ESCでキャンセル, ?でヘルプ: ", "Move to , Select to Enter, Cancel to ESC, ? to help: "), 21, 0); - - /* Get command */ - skey = inkey_special(TRUE); - if (!(skey & SKEY_MASK)) k = (char)skey; - else k = 0; - - /* Exit */ - if (k == ESCAPE) break; - - if (my_strchr("\n\r ", k)) - { - k = option_fields[y].key; - break; - } - - for (i = 0; i < n; i++) - { - if (tolower(k) == option_fields[i].key) break; - } - - /* Command is found */ - if (i < n) break; - - /* Hack -- browse help */ - if (k == '?') break; - - /* Move cursor */ - d = 0; - if (skey == SKEY_UP) d = 8; - if (skey == SKEY_DOWN) d = 2; - y = (y + ddy[d] + n) % n; - if (!d) bell(); - } - - /* Exit */ - if (k == ESCAPE) break; - - /* Analyze */ - switch (k) - { - case '1': - { - /* Process the general options */ - do_cmd_options_aux(OPT_PAGE_INPUT, _("キー入力オプション", "Input Options")); - break; - } - - case '2': - { - /* Process the general options */ - do_cmd_options_aux(OPT_PAGE_MAPSCREEN, _("マップ画面オプション", "Map Screen Options")); - break; - } - - case '3': - { - /* Spawn */ - do_cmd_options_aux(OPT_PAGE_TEXT, _("テキスト表示オプション", "Text Display Options")); - break; - } - - case '4': - { - /* Spawn */ - do_cmd_options_aux(OPT_PAGE_GAMEPLAY, _("ゲームプレイ・オプション", "Game-Play Options")); - break; - } - - case '5': - { - /* Spawn */ - do_cmd_options_aux(OPT_PAGE_DISTURBANCE, _("行動中止関係のオプション", "Disturbance Options")); - break; - } - - case '6': - { - /* Spawn */ - do_cmd_options_aux(OPT_PAGE_AUTODESTROY, _("簡易自動破壊オプション", "Easy Auto-Destroyer Options")); - break; - } - - /* Play-record Options */ - case 'R': - case 'r': - { - /* Spawn */ - do_cmd_options_aux(OPT_PAGE_PLAYRECORD, _("プレイ記録オプション", "Play-record Options")); - break; - } - - /* Birth Options */ - case 'B': - case 'b': - { - /* Spawn */ - do_cmd_options_aux(OPT_PAGE_BIRTH, (!p_ptr->wizard || !allow_debug_opts) ? - _("初期オプション(参照のみ)", "Birth Options(browse only)") : - _("初期オプション((*)はスコアに影響)", "Birth Options((*)s effect score)")); - break; - } - - /* Cheating Options */ - case 'C': - { - if (!p_ptr->noscore && !allow_debug_opts) - { - /* Cheat options are not permitted */ - bell(); - break; - } - - /* Spawn */ - do_cmd_options_cheat(_("詐欺師は決して勝利できない!", "Cheaters never win")); - break; - } - - case 'a': - case 'A': - { - do_cmd_options_autosave(_("自動セーブ", "Autosave")); - break; - } - - /* Window flags */ - case 'W': - case 'w': - { - /* Spawn */ - do_cmd_options_win(); - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | - PW_PLAYER | PW_MESSAGE | PW_OVERHEAD | - PW_MONSTER | PW_OBJECT | PW_SNAPSHOT | - PW_BORG_1 | PW_BORG_2 | PW_DUNGEON | - PW_MONSTER_LIST); - break; - } - - /* Auto-picker/destroyer editor */ - case 'P': - case 'p': - { - do_cmd_edit_autopick(); - break; - } - - /* Hack -- Delay Speed */ - case 'D': - case 'd': - { - /* Prompt */ - clear_from(18); - prt(_("コマンド: 基本ウェイト量", "Command: Base Delay Factor"), 19, 0); - - /* Get a new value */ - while (1) - { - int msec = delay_factor * delay_factor * delay_factor; - prt(format(_("現在のウェイト: %d (%dミリ秒)", "Current base delay factor: %d (%d msec)"), delay_factor, msec), 22, 0); - prt(_("ウェイト (0-9) ESCで決定: ", "Delay Factor (0-9 or ESC to accept): "), 20, 0); - k = inkey(); - if (k == ESCAPE) break; - else if (k == '?') - { - (void)show_file(TRUE, _("joption.txt#BaseDelay", "option.txt#BaseDelay"), NULL, 0, 0); - Term_clear(); - } - else if (isdigit(k)) delay_factor = D2I(k); - else bell(); - } - - break; - } - - /* Hack -- hitpoint warning factor */ - case 'H': - case 'h': - { - /* Prompt */ - clear_from(18); - prt(_("コマンド: 低ヒットポイント警告", "Command: Hitpoint Warning"), 19, 0); - - /* Get a new value */ - while (1) - { - prt(format(_("現在の低ヒットポイント警告: %d0%%", "Current hitpoint warning: %d0%%"), hitpoint_warn), 22, 0); - prt(_("低ヒットポイント警告 (0-9) ESCで決定: ", "Hitpoint Warning (0-9 or ESC to accept): "), 20, 0); - k = inkey(); - if (k == ESCAPE) break; - else if (k == '?') - { - (void)show_file(TRUE, _("joption.txt#Hitpoint", "option.txt#Hitpoint"), NULL, 0, 0); - Term_clear(); - } - else if (isdigit(k)) hitpoint_warn = D2I(k); - else bell(); - } - - break; - } - - /* Hack -- mana color factor */ - case 'M': - case 'm': - { - /* Prompt */ - clear_from(18); - prt(_("コマンド: 低魔力色閾値", "Command: Mana Color Threshold"), 19, 0); - - /* Get a new value */ - while (1) - { - prt(format(_("現在の低魔力色閾値: %d0%%", "Current mana color threshold: %d0%%"), mana_warn), 22, 0); - prt(_("低魔力閾値 (0-9) ESCで決定: ", "Mana color Threshold (0-9 or ESC to accept): "), 20, 0); - k = inkey(); - if (k == ESCAPE) break; - else if (k == '?') - { - (void)show_file(TRUE, _("joption.txt#Manapoint", "option.txt#Manapoint"), NULL, 0, 0); - Term_clear(); - } - else if (isdigit(k)) mana_warn = D2I(k); - else bell(); - } - - break; - } - - case '?': - (void)show_file(TRUE, _("joption.txt", "option.txt"), NULL, 0, 0); - Term_clear(); - break; - - /* Unknown option */ - default: - { - bell(); - break; - } - } - - msg_erase(); - } - - screen_load(); - - /* Hack - Redraw equippy chars */ - p_ptr->redraw |= (PR_EQUIPPY); -} - - - -/*! - * @brief prefファイルを選択して処理する / - * Ask for a "user pref line" and process it - * @return なし - * @details - * Allow absolute file names? - */ -void do_cmd_pref(void) -{ - char buf[80]; - - /* Default */ - strcpy(buf, ""); - - /* Ask for a "user pref command" */ - if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return; - - /* Process that pref command */ - (void)process_pref_file_command(buf); -} - -/*! - * @brief 自動拾い設定ファイルをロードするコマンドのメインルーチン / - * @return なし - */ -void do_cmd_reload_autopick(void) -{ - if (!get_check(_("自動拾い設定ファイルをロードしますか? ", "Reload auto-pick preference file? "))) return; - /* Load the file with messages */ - autopick_load_pref(TRUE); -} - -#ifdef ALLOW_MACROS - -/*! - * @brief マクロ情報をprefファイルに保存する / - * @param fname ファイル名 - * @return なし - */ -static errr macro_dump(concptr fname) -{ - static concptr mark = "Macro Dump"; - - int i; - - char buf[1024]; - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Append to the file */ - if (!open_auto_dump(buf, mark)) return (-1); - - /* Start dumping */ - auto_dump_printf(_("\n# 自動マクロセーブ\n\n", "\n# Automatic macro dump\n\n")); - - /* Dump them */ - for (i = 0; i < macro__num; i++) - { - /* Extract the action */ - ascii_to_text(buf, macro__act[i]); - - /* Dump the macro */ - auto_dump_printf("A:%s\n", buf); - - /* Extract the action */ - ascii_to_text(buf, macro__pat[i]); - - /* Dump normal macros */ - auto_dump_printf("P:%s\n", buf); - - /* End the macro */ - auto_dump_printf("\n"); - } - - /* Close */ - close_auto_dump(); - - /* Success */ - return (0); -} - - -/*! - * @brief マクロのトリガーキーを取得する / - * Hack -- ask for a "trigger" (see below) - * @param buf キー表記を保管するバッファ - * @return なし - * @details - *
- * Note the complex use of the "inkey()" function from "util.c".
- *
- * Note that both "flush()" calls are extremely important.
- * 
- */ -static void do_cmd_macro_aux(char *buf) -{ - char i; - int n = 0; - char tmp[1024]; - - flush(); - - /* Do not process macros */ - inkey_base = TRUE; - - /* First key */ - i = inkey(); - - /* Read the pattern */ - while (i) - { - /* Save the key */ - buf[n++] = i; - - /* Do not process macros */ - inkey_base = TRUE; - - /* Do not wait for keys */ - inkey_scan = TRUE; - - /* Attempt to read a key */ - i = inkey(); - } - - /* Terminate */ - buf[n] = '\0'; - - flush(); - - /* Convert the trigger */ - ascii_to_text(tmp, buf); - - /* Hack -- display the trigger */ - Term_addstr(-1, TERM_WHITE, tmp); -} - -#endif - -/*! - * @brief マクロのキー表記からアスキーコードを得てターミナルに表示する / - * Hack -- ask for a keymap "trigger" (see below) - * @param buf キー表記を取得するバッファ - * @return なし - * @details - *
- * Note that both "flush()" calls are extremely important.  This may
- * no longer be true, since "util.c" is much simpler now.  
- * 
- */ -static void do_cmd_macro_aux_keymap(char *buf) -{ - char tmp[1024]; - - flush(); - - /* Get a key */ - buf[0] = inkey(); - buf[1] = '\0'; - - /* Convert to ascii */ - ascii_to_text(tmp, buf); - - /* Hack -- display the trigger */ - Term_addstr(-1, TERM_WHITE, tmp); - - flush(); -} - - -/*! - * @brief キーマップをprefファイルにダンプする / - * Hack -- append all keymaps to the given file - * @param fname ファイルネーム - * @return エラーコード - * @details - */ -static errr keymap_dump(concptr fname) -{ - static concptr mark = "Keymap Dump"; - int i; - - char key[1024]; - char buf[1024]; - - BIT_FLAGS mode; - - /* Roguelike */ - if (rogue_like_commands) - { - mode = KEYMAP_MODE_ROGUE; - } - - /* Original */ - else - { - mode = KEYMAP_MODE_ORIG; - } - - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Append to the file */ - if (!open_auto_dump(buf, mark)) return -1; - - /* Start dumping */ - auto_dump_printf(_("\n# 自動キー配置セーブ\n\n", "\n# Automatic keymap dump\n\n")); - - /* Dump them */ - for (i = 0; i < 256; i++) - { - concptr act; - - /* Loop up the keymap */ - act = keymap_act[mode][i]; - - /* Skip empty keymaps */ - if (!act) continue; - - /* Encode the key */ - buf[0] = (char)i; - buf[1] = '\0'; - ascii_to_text(key, buf); - - /* Encode the action */ - ascii_to_text(buf, act); - - /* Dump the macro */ - auto_dump_printf("A:%s\n", buf); - auto_dump_printf("C:%d:%s\n", mode, key); - } - - /* Close */ - close_auto_dump(); - - /* Success */ - return (0); -} - - -/*! - * @brief マクロを設定するコマンドのメインルーチン / - * Interact with "macros" - * @return なし - * @details - *
- * Note that the macro "action" must be defined before the trigger.
- *
- * Could use some helpful instructions on this page.  
- * 
- */ -void do_cmd_macros(void) -{ - int i; - - char tmp[1024]; - - char buf[1024]; - - BIT_FLAGS mode; - - - /* Roguelike */ - if (rogue_like_commands) - { - mode = KEYMAP_MODE_ROGUE; - } - - /* Original */ - else - { - mode = KEYMAP_MODE_ORIG; - } - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - screen_save(); - - - /* Process requests until done */ - while (1) - { - Term_clear(); - prt(_("[ マクロの設定 ]", "Interact with Macros"), 2, 0); - - /* Describe that action */ - prt(_("マクロ行動が(もしあれば)下に表示されます:", "Current action (if any) shown below:"), 20, 0); - - /* Analyze the current action */ - ascii_to_text(buf, macro__buf); - - /* Display the current action */ - prt(buf, 22, 0); - - - /* Selections */ - prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5); -#ifdef ALLOW_MACROS - prt(_("(2) ファイルにマクロを追加", "(2) Append macros to a file"), 5, 5); - prt(_("(3) マクロの確認", "(3) Query a macro"), 6, 5); - prt(_("(4) マクロの作成", "(4) Create a macro"), 7, 5); - prt(_("(5) マクロの削除", "(5) Remove a macro"), 8, 5); - prt(_("(6) ファイルにキー配置を追加", "(6) Append keymaps to a file"), 9, 5); - prt(_("(7) キー配置の確認", "(7) Query a keymap"), 10, 5); - prt(_("(8) キー配置の作成", "(8) Create a keymap"), 11, 5); - prt(_("(9) キー配置の削除", "(9) Remove a keymap"), 12, 5); - prt(_("(0) マクロ行動の入力", "(0) Enter a new action"), 13, 5); -#endif /* ALLOW_MACROS */ - - /* Prompt */ - prt(_("コマンド: ", "Command: "), 16, 0); - - i = inkey(); - - /* Leave */ - if (i == ESCAPE) break; - - /* Load a 'macro' file */ - else if (i == '1') - { - errr err; - - /* Prompt */ - prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 16, 0); - - /* Prompt */ - prt(_("ファイル: ", "File: "), 18, 0); - - /* Default filename */ - sprintf(tmp, "%s.prf", player_base); - - /* Ask for a file */ - if (!askfor(tmp, 80)) continue; - - /* Process the given filename */ - err = process_pref_file(tmp); - if (-2 == err) - { - msg_format(_("標準の設定ファイル'%s'を読み込みました。", "Loaded default '%s'."), tmp); - } - else if (err) - { - /* Prompt */ - msg_format(_("'%s'の読み込みに失敗しました!", "Failed to load '%s'!"), tmp); - } - else - { - msg_format(_("'%s'を読み込みました。", "Loaded '%s'."), tmp); - } - } - -#ifdef ALLOW_MACROS - - /* Save macros */ - else if (i == '2') - { - /* Prompt */ - prt(_("コマンド: マクロをファイルに追加する", "Command: Append macros to a file"), 16, 0); - - /* Prompt */ - prt(_("ファイル: ", "File: "), 18, 0); - - /* Default filename */ - sprintf(tmp, "%s.prf", player_base); - - /* Ask for a file */ - if (!askfor(tmp, 80)) continue; - - /* Dump the macros */ - (void)macro_dump(tmp); - - /* Prompt */ - msg_print(_("マクロを追加しました。", "Appended macros.")); - } - - /* Query a macro */ - else if (i == '3') - { - int k; - - /* Prompt */ - prt(_("コマンド: マクロの確認", "Command: Query a macro"), 16, 0); - - - /* Prompt */ - prt(_("トリガーキー: ", "Trigger: "), 18, 0); - - /* Get a macro trigger */ - do_cmd_macro_aux(buf); - - /* Acquire action */ - k = macro_find_exact(buf); - - /* Nothing found */ - if (k < 0) - { - /* Prompt */ - msg_print(_("そのキーにはマクロは定義されていません。", "Found no macro.")); - } - - /* Found one */ - else - { - /* Obtain the action */ - strcpy(macro__buf, macro__act[k]); - - /* Analyze the current action */ - ascii_to_text(buf, macro__buf); - - /* Display the current action */ - prt(buf, 22, 0); - - /* Prompt */ - msg_print(_("マクロを確認しました。", "Found a macro.")); - } - } - - /* Create a macro */ - else if (i == '4') - { - /* Prompt */ - prt(_("コマンド: マクロの作成", "Command: Create a macro"), 16, 0); - - /* Prompt */ - prt(_("トリガーキー: ", "Trigger: "), 18, 0); - - /* Get a macro trigger */ - do_cmd_macro_aux(buf); - - /* Clear */ - clear_from(20); - - /* Help message */ - c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。", - "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0); - - /* Prompt */ - prt(_("マクロ行動: ", "Action: "), 20, 0); - - /* Convert to text */ - ascii_to_text(tmp, macro__buf); - - /* Get an encoded action */ - if (askfor(tmp, 80)) - { - /* Convert to ascii */ - text_to_ascii(macro__buf, tmp); - - /* Link the macro */ - macro_add(buf, macro__buf); - - /* Prompt */ - msg_print(_("マクロを追加しました。", "Added a macro.")); - } - } - - /* Remove a macro */ - else if (i == '5') - { - /* Prompt */ - prt(_("コマンド: マクロの削除", "Command: Remove a macro"), 16, 0); - - /* Prompt */ - prt(_("トリガーキー: ", "Trigger: "), 18, 0); - - /* Get a macro trigger */ - do_cmd_macro_aux(buf); - - /* Link the macro */ - macro_add(buf, buf); - - /* Prompt */ - msg_print(_("マクロを削除しました。", "Removed a macro.")); - } - - /* Save keymaps */ - else if (i == '6') - { - /* Prompt */ - prt(_("コマンド: キー配置をファイルに追加する", "Command: Append keymaps to a file"), 16, 0); - - /* Prompt */ - prt(_("ファイル: ", "File: "), 18, 0); - - /* Default filename */ - sprintf(tmp, "%s.prf", player_base); - - /* Ask for a file */ - if (!askfor(tmp, 80)) continue; - - /* Dump the macros */ - (void)keymap_dump(tmp); - - /* Prompt */ - msg_print(_("キー配置を追加しました。", "Appended keymaps.")); - } - - /* Query a keymap */ - else if (i == '7') - { - concptr act; - - /* Prompt */ - prt(_("コマンド: キー配置の確認", "Command: Query a keymap"), 16, 0); - - /* Prompt */ - prt(_("押すキー: ", "Keypress: "), 18, 0); - - /* Get a keymap trigger */ - do_cmd_macro_aux_keymap(buf); - - /* Look up the keymap */ - act = keymap_act[mode][(byte)(buf[0])]; - - /* Nothing found */ - if (!act) - { - /* Prompt */ - msg_print(_("キー配置は定義されていません。", "Found no keymap.")); - } - - /* Found one */ - else - { - /* Obtain the action */ - strcpy(macro__buf, act); - - /* Analyze the current action */ - ascii_to_text(buf, macro__buf); - - /* Display the current action */ - prt(buf, 22, 0); - - /* Prompt */ - msg_print(_("キー配置を確認しました。", "Found a keymap.")); - } - } - - /* Create a keymap */ - else if (i == '8') - { - /* Prompt */ - prt(_("コマンド: キー配置の作成", "Command: Create a keymap"), 16, 0); - - /* Prompt */ - prt(_("押すキー: ", "Keypress: "), 18, 0); - - /* Get a keymap trigger */ - do_cmd_macro_aux_keymap(buf); - - /* Clear */ - clear_from(20); - - /* Help message */ - c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。", - "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0); - - /* Prompt */ - prt(_("行動: ", "Action: "), 20, 0); - - /* Convert to text */ - ascii_to_text(tmp, macro__buf); - - /* Get an encoded action */ - if (askfor(tmp, 80)) - { - /* Convert to ascii */ - text_to_ascii(macro__buf, tmp); - - /* Free old keymap */ - string_free(keymap_act[mode][(byte)(buf[0])]); - - /* Make new keymap */ - keymap_act[mode][(byte)(buf[0])] = string_make(macro__buf); - - /* Prompt */ - msg_print(_("キー配置を追加しました。", "Added a keymap.")); - } - } - - /* Remove a keymap */ - else if (i == '9') - { - /* Prompt */ - prt(_("コマンド: キー配置の削除", "Command: Remove a keymap"), 16, 0); - - /* Prompt */ - prt(_("押すキー: ", "Keypress: "), 18, 0); - - /* Get a keymap trigger */ - do_cmd_macro_aux_keymap(buf); - - /* Free old keymap */ - string_free(keymap_act[mode][(byte)(buf[0])]); - - /* Make new keymap */ - keymap_act[mode][(byte)(buf[0])] = NULL; - - /* Prompt */ - msg_print(_("キー配置を削除しました。", "Removed a keymap.")); - } - - /* Enter a new action */ - else if (i == '0') - { - /* Prompt */ - prt(_("コマンド: マクロ行動の入力", "Command: Enter a new action"), 16, 0); - - /* Clear */ - clear_from(20); - - /* Help message */ - c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。", - "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0); - - /* Prompt */ - prt(_("マクロ行動: ", "Action: "), 20, 0); - - /* Hack -- limit the value */ - tmp[80] = '\0'; - - /* Get an encoded action */ - if (!askfor(buf, 80)) continue; - - /* Extract an action */ - text_to_ascii(macro__buf, buf); - } - -#endif /* ALLOW_MACROS */ - - else - { - bell(); - } - - msg_erase(); - } - screen_load(); -} - -/*! - * @brief キャラクタ色の明暗表現 - */ -static concptr lighting_level_str[F_LIT_MAX] = -{ -#ifdef JP - "標準色", - "明色", - "暗色", -#else - "standard", - "brightly lit", - "darkened", -#endif -}; - - -/*! - * @brief キャラクタのビジュアルIDを変更する際の対象指定関数 - * @param i 指定対象となるキャラクタコード - * @param num 指定されたビジュアルIDを返す参照ポインタ - * @param max ビジュアルIDの最大数 - * @return 指定が実際に行われた場合TRUE、キャンセルされた場合FALSE - */ -static bool cmd_visuals_aux(int i, IDX *num, IDX max) -{ - if (iscntrl(i)) - { - char str[10] = ""; - IDX tmp; - - sprintf(str, "%d", *num); - - if (!get_string(format("Input new number(0-%d): ", max-1), str, 4)) - return FALSE; - - tmp = (IDX)strtol(str, NULL, 0); - if (tmp >= 0 && tmp < max) - *num = tmp; - } - else if (isupper(i)) - *num = (*num + max - 1) % max; - else - *num = (*num + 1) % max; - - return TRUE; -} - -/*! - * @brief キャラクタの変更メニュー表示 - * @param choice_msg 選択メッセージ - * @return なし - */ -static void print_visuals_menu(concptr choice_msg) -{ - prt(_("[ 画面表示の設定 ]", "Interact with Visuals"), 1, 0); - - /* Give some choices */ - prt(_("(0) ユーザー設定ファイルのロード", "(0) Load a user pref file"), 3, 5); - -#ifdef ALLOW_VISUALS - prt(_("(1) モンスターの 色/文字 をファイルに書き出す", "(1) Dump monster attr/chars"), 4, 5); - prt(_("(2) アイテムの 色/文字 をファイルに書き出す", "(2) Dump object attr/chars"), 5, 5); - prt(_("(3) 地形の 色/文字 をファイルに書き出す", "(3) Dump feature attr/chars"), 6, 5); - prt(_("(4) モンスターの 色/文字 を変更する (数値操作)", "(4) Change monster attr/chars (numeric operation)"), 7, 5); - prt(_("(5) アイテムの 色/文字 を変更する (数値操作)", "(5) Change object attr/chars (numeric operation)"), 8, 5); - prt(_("(6) 地形の 色/文字 を変更する (数値操作)", "(6) Change feature attr/chars (numeric operation)"), 9, 5); - prt(_("(7) モンスターの 色/文字 を変更する (シンボルエディタ)", "(7) Change monster attr/chars (visual mode)"), 10, 5); - prt(_("(8) アイテムの 色/文字 を変更する (シンボルエディタ)", "(8) Change object attr/chars (visual mode)"), 11, 5); - prt(_("(9) 地形の 色/文字 を変更する (シンボルエディタ)", "(9) Change feature attr/chars (visual mode)"), 12, 5); -#endif /* ALLOW_VISUALS */ - - prt(_("(R) 画面表示方法の初期化", "(R) Reset visuals"), 13, 5); - - /* Prompt */ - prt(format("コマンド: %s", choice_msg ? choice_msg : _("", "")), 15, 0); -} - -static void do_cmd_knowledge_monsters(bool *need_redraw, bool visual_only, IDX direct_r_idx); -static void do_cmd_knowledge_objects(bool *need_redraw, bool visual_only, IDX direct_k_idx); -static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level); - -/* - * Interact with "visuals" - */ -void do_cmd_visuals(void) -{ - int i; - char tmp[160]; - char buf[1024]; - bool need_redraw = FALSE; - concptr empty_symbol = "<< ? >>"; - - if (use_bigtile) empty_symbol = "<< ?? >>"; - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - screen_save(); - - /* Interact until done */ - while (1) - { - Term_clear(); - - /* Ask for a choice */ - print_visuals_menu(NULL); - - /* Prompt */ - i = inkey(); - - if (i == ESCAPE) break; - - switch (i) - { - /* Load a 'pref' file */ - case '0': - /* Prompt */ - prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 15, 0); - - /* Prompt */ - prt(_("ファイル: ", "File: "), 17, 0); - - /* Default filename */ - sprintf(tmp, "%s.prf", player_base); - - /* Query */ - if (!askfor(tmp, 70)) continue; - - /* Process the given filename */ - (void)process_pref_file(tmp); - - need_redraw = TRUE; - break; - -#ifdef ALLOW_VISUALS - - /* Dump monster attr/chars */ - case '1': - { - static concptr mark = "Monster attr/chars"; - - /* Prompt */ - prt(_("コマンド: モンスターの[色/文字]をファイルに書き出します", "Command: Dump monster attr/chars"), 15, 0); - - /* Prompt */ - prt(_("ファイル: ", "File: "), 17, 0); - - /* Default filename */ - sprintf(tmp, "%s.prf", player_base); - - /* Get a filename */ - if (!askfor(tmp, 70)) continue; - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp); - - /* Append to the file */ - if (!open_auto_dump(buf, mark)) continue; - - /* Start dumping */ - auto_dump_printf(_("\n# モンスターの[色/文字]の設定\n\n", "\n# Monster attr/char definitions\n\n")); - - /* Dump monsters */ - for (i = 0; i < max_r_idx; i++) - { - monster_race *r_ptr = &r_info[i]; - - /* Skip non-entries */ - if (!r_ptr->name) continue; - - /* Dump a comment */ - auto_dump_printf("# %s\n", (r_name + r_ptr->name)); - - /* Dump the monster attr/char info */ - auto_dump_printf("R:%d:0x%02X/0x%02X\n\n", i, - (byte)(r_ptr->x_attr), (byte)(r_ptr->x_char)); - } - - /* Close */ - close_auto_dump(); - - msg_print(_("モンスターの[色/文字]をファイルに書き出しました。", "Dumped monster attr/chars.")); - - break; - } - - /* Dump object attr/chars */ - case '2': - { - static concptr mark = "Object attr/chars"; - KIND_OBJECT_IDX k_idx; - - /* Prompt */ - prt(_("コマンド: アイテムの[色/文字]をファイルに書き出します", "Command: Dump object attr/chars"), 15, 0); - - /* Prompt */ - prt(_("ファイル: ", "File: "), 17, 0); - - /* Default filename */ - sprintf(tmp, "%s.prf", player_base); - - /* Get a filename */ - if (!askfor(tmp, 70)) continue; - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp); - - /* Append to the file */ - if (!open_auto_dump(buf, mark)) continue; - - /* Start dumping */ - auto_dump_printf(_("\n# アイテムの[色/文字]の設定\n\n", "\n# Object attr/char definitions\n\n")); - - /* Dump objects */ - for (k_idx = 0; k_idx < max_k_idx; k_idx++) - { - GAME_TEXT o_name[MAX_NLEN]; - object_kind *k_ptr = &k_info[k_idx]; - - /* Skip non-entries */ - if (!k_ptr->name) continue; - - if (!k_ptr->flavor) - { - /* Tidy name */ - strip_name(o_name, k_idx); - } - else - { - object_type forge; - - /* Prepare dummy object */ - object_prep(&forge, k_idx); - - /* Get un-shuffled flavor name */ - object_desc(o_name, &forge, OD_FORCE_FLAVOR); - } - - /* Dump a comment */ - auto_dump_printf("# %s\n", o_name); - - /* Dump the object attr/char info */ - auto_dump_printf("K:%d:0x%02X/0x%02X\n\n", (int)k_idx, - (byte)(k_ptr->x_attr), (byte)(k_ptr->x_char)); - } - - /* Close */ - close_auto_dump(); - - msg_print(_("アイテムの[色/文字]をファイルに書き出しました。", "Dumped object attr/chars.")); - - break; - } - - /* Dump feature attr/chars */ - case '3': - { - static concptr mark = "Feature attr/chars"; - - /* Prompt */ - prt(_("コマンド: 地形の[色/文字]をファイルに書き出します", "Command: Dump feature attr/chars"), 15, 0); - - /* Prompt */ - prt(_("ファイル: ", "File: "), 17, 0); - - /* Default filename */ - sprintf(tmp, "%s.prf", player_base); - - /* Get a filename */ - if (!askfor(tmp, 70)) continue; - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp); - - /* Append to the file */ - if (!open_auto_dump(buf, mark)) continue; - - /* Start dumping */ - auto_dump_printf(_("\n# 地形の[色/文字]の設定\n\n", "\n# Feature attr/char definitions\n\n")); - - /* Dump features */ - for (i = 0; i < max_f_idx; i++) - { - feature_type *f_ptr = &f_info[i]; - - /* Skip non-entries */ - if (!f_ptr->name) continue; - - /* Skip mimiccing features */ - if (f_ptr->mimic != i) continue; - - /* Dump a comment */ - auto_dump_printf("# %s\n", (f_name + f_ptr->name)); - - /* Dump the feature attr/char info */ - auto_dump_printf("F:%d:0x%02X/0x%02X:0x%02X/0x%02X:0x%02X/0x%02X\n\n", i, - (byte)(f_ptr->x_attr[F_LIT_STANDARD]), (byte)(f_ptr->x_char[F_LIT_STANDARD]), - (byte)(f_ptr->x_attr[F_LIT_LITE]), (byte)(f_ptr->x_char[F_LIT_LITE]), - (byte)(f_ptr->x_attr[F_LIT_DARK]), (byte)(f_ptr->x_char[F_LIT_DARK])); - } - - /* Close */ - close_auto_dump(); - - msg_print(_("地形の[色/文字]をファイルに書き出しました。", "Dumped feature attr/chars.")); - - break; - } - - /* Modify monster attr/chars (numeric operation) */ - case '4': - { - static concptr choice_msg = _("モンスターの[色/文字]を変更します", "Change monster attr/chars"); - static MONRACE_IDX r = 0; - - prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0); - - /* Hack -- query until done */ - while (1) - { - monster_race *r_ptr = &r_info[r]; - int c; - IDX t; - - TERM_COLOR da = r_ptr->d_attr; - byte dc = r_ptr->d_char; - TERM_COLOR ca = r_ptr->x_attr; - byte cc = r_ptr->x_char; - - /* Label the object */ - Term_putstr(5, 17, -1, TERM_WHITE, - format(_("モンスター = %d, 名前 = %-40.40s", "Monster = %d, Name = %-40.40s"), r, (r_name + r_ptr->name))); - - /* Label the Default values */ - Term_putstr(10, 19, -1, TERM_WHITE, - format(_("初期値 色 / 文字 = %3u / %3u", "Default attr/char = %3u / %3u"), da, dc)); - - Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol); - Term_queue_bigchar(43, 19, da, dc, 0, 0); - - /* Label the Current values */ - Term_putstr(10, 20, -1, TERM_WHITE, - format(_("現在値 色 / 文字 = %3u / %3u", "Current attr/char = %3u / %3u"), ca, cc)); - - Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol); - Term_queue_bigchar(43, 20, ca, cc, 0, 0); - - /* Prompt */ - Term_putstr(0, 22, -1, TERM_WHITE, - _("コマンド (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ")); - - i = inkey(); - - /* All done */ - if (i == ESCAPE) break; - - if (iscntrl(i)) c = 'a' + i - KTRL('A'); - else if (isupper(i)) c = 'a' + i - 'A'; - else c = i; - - switch (c) - { - case 'n': - { - IDX prev_r = r; - do - { - if (!cmd_visuals_aux(i, &r, max_r_idx)) - { - r = prev_r; - break; - } - } - while (!r_info[r].name); - } - break; - case 'a': - t = (int)r_ptr->x_attr; - (void)cmd_visuals_aux(i, &t, 256); - r_ptr->x_attr = (byte)t; - need_redraw = TRUE; - break; - case 'c': - t = (int)r_ptr->x_char; - (void)cmd_visuals_aux(i, &t, 256); - r_ptr->x_char = (byte)t; - need_redraw = TRUE; - break; - case 'v': - do_cmd_knowledge_monsters(&need_redraw, TRUE, r); - Term_clear(); - print_visuals_menu(choice_msg); - break; - } - } - - break; - } - - /* Modify object attr/chars (numeric operation) */ - case '5': - { - static concptr choice_msg = _("アイテムの[色/文字]を変更します", "Change object attr/chars"); - static IDX k = 0; - prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0); - - /* Hack -- query until done */ - while (1) - { - object_kind *k_ptr = &k_info[k]; - int c; - IDX t; - - TERM_COLOR da = k_ptr->d_attr; - SYMBOL_CODE dc = k_ptr->d_char; - TERM_COLOR ca = k_ptr->x_attr; - SYMBOL_CODE cc = k_ptr->x_char; - - /* Label the object */ - Term_putstr(5, 17, -1, TERM_WHITE, - format(_("アイテム = %d, 名前 = %-40.40s", "Object = %d, Name = %-40.40s"), - k, k_name + (!k_ptr->flavor ? k_ptr->name : k_ptr->flavor_name))); - - /* Label the Default values */ - Term_putstr(10, 19, -1, TERM_WHITE, - format(_("初期値 色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc)); - - Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol); - Term_queue_bigchar(43, 19, da, dc, 0, 0); - - /* Label the Current values */ - Term_putstr(10, 20, -1, TERM_WHITE, - format(_("現在値 色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc)); - - Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol); - Term_queue_bigchar(43, 20, ca, cc, 0, 0); - - /* Prompt */ - Term_putstr(0, 22, -1, TERM_WHITE, - _("コマンド (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ")); - - i = inkey(); - - /* All done */ - if (i == ESCAPE) break; - - if (iscntrl(i)) c = 'a' + i - KTRL('A'); - else if (isupper(i)) c = 'a' + i - 'A'; - else c = i; - - switch (c) - { - case 'n': - { - IDX prev_k = k; - do - { - if (!cmd_visuals_aux(i, &k, max_k_idx)) - { - k = prev_k; - break; - } - } - while (!k_info[k].name); - } - break; - case 'a': - t = (int)k_ptr->x_attr; - (void)cmd_visuals_aux(i, &t, 256); - k_ptr->x_attr = (byte)t; - need_redraw = TRUE; - break; - case 'c': - t = (int)k_ptr->x_char; - (void)cmd_visuals_aux(i, &t, 256); - k_ptr->x_char = (byte)t; - need_redraw = TRUE; - break; - case 'v': - do_cmd_knowledge_objects(&need_redraw, TRUE, k); - Term_clear(); - print_visuals_menu(choice_msg); - break; - } - } - - break; - } - - /* Modify feature attr/chars (numeric operation) */ - case '6': - { - static concptr choice_msg = _("地形の[色/文字]を変更します", "Change feature attr/chars"); - static IDX f = 0; - static IDX lighting_level = F_LIT_STANDARD; - prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0); - - /* Hack -- query until done */ - while (1) - { - feature_type *f_ptr = &f_info[f]; - int c; - IDX t; - - TERM_COLOR da = f_ptr->d_attr[lighting_level]; - byte dc = f_ptr->d_char[lighting_level]; - TERM_COLOR ca = f_ptr->x_attr[lighting_level]; - byte cc = f_ptr->x_char[lighting_level]; - - /* Label the object */ - prt("", 17, 5); - Term_putstr(5, 17, -1, TERM_WHITE, - format(_("地形 = %d, 名前 = %s, 明度 = %s", "Terrain = %d, Name = %s, Lighting = %s"), - f, (f_name + f_ptr->name), lighting_level_str[lighting_level])); - - /* Label the Default values */ - Term_putstr(10, 19, -1, TERM_WHITE, - format(_("初期値 色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc)); - - Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol); - Term_queue_bigchar(43, 19, da, dc, 0, 0); - - /* Label the Current values */ -#ifdef JP - Term_putstr(10, 20, -1, TERM_WHITE, - format("現在値 色 / 文字 = %3d / %3d", ca, cc)); -#else - Term_putstr(10, 20, -1, TERM_WHITE, - format("Current attr/char = %3d / %3d", ca, cc)); -#endif - - Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol); - Term_queue_bigchar(43, 20, ca, cc, 0, 0); - - /* Prompt */ -#ifdef JP - Term_putstr(0, 22, -1, TERM_WHITE, - "コマンド (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): "); -#else - Term_putstr(0, 22, -1, TERM_WHITE, - "Command (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): "); -#endif - - i = inkey(); - - /* All done */ - if (i == ESCAPE) break; - - if (iscntrl(i)) c = 'a' + i - KTRL('A'); - else if (isupper(i)) c = 'a' + i - 'A'; - else c = i; - - switch (c) - { - case 'n': - { - IDX prev_f = f; - do - { - if (!cmd_visuals_aux(i, &f, max_f_idx)) - { - f = prev_f; - break; - } - } - while (!f_info[f].name || (f_info[f].mimic != f)); - } - break; - case 'a': - t = (int)f_ptr->x_attr[lighting_level]; - (void)cmd_visuals_aux(i, &t, 256); - f_ptr->x_attr[lighting_level] = (byte)t; - need_redraw = TRUE; - break; - case 'c': - t = (int)f_ptr->x_char[lighting_level]; - (void)cmd_visuals_aux(i, &t, 256); - f_ptr->x_char[lighting_level] = (byte)t; - need_redraw = TRUE; - break; - case 'l': - (void)cmd_visuals_aux(i, &lighting_level, F_LIT_MAX); - break; - case 'd': - apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char); - need_redraw = TRUE; - break; - case 'v': - do_cmd_knowledge_features(&need_redraw, TRUE, f, &lighting_level); - Term_clear(); - print_visuals_menu(choice_msg); - break; - } - } - - break; - } - - /* Modify monster attr/chars (visual mode) */ - case '7': - do_cmd_knowledge_monsters(&need_redraw, TRUE, -1); - break; - - /* Modify object attr/chars (visual mode) */ - case '8': - do_cmd_knowledge_objects(&need_redraw, TRUE, -1); - break; - - /* Modify feature attr/chars (visual mode) */ - case '9': - { - IDX lighting_level = F_LIT_STANDARD; - do_cmd_knowledge_features(&need_redraw, TRUE, -1, &lighting_level); - break; - } - -#endif /* ALLOW_VISUALS */ - - /* Reset visuals */ - case 'R': - case 'r': - /* Reset */ - reset_visuals(); - - msg_print(_("画面上の[色/文字]を初期値にリセットしました。", "Visual attr/char tables reset.")); - need_redraw = TRUE; - break; - - /* Unknown option */ - default: - bell(); - break; - } - - msg_erase(); - } - screen_load(); - - if (need_redraw) do_cmd_redraw(); -} - - -/* - * Interact with "colors" - */ -void do_cmd_colors(void) -{ - int i; - - char tmp[160]; - - char buf[1024]; - - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - screen_save(); - - - /* Interact until done */ - while (1) - { - Term_clear(); - - /* Ask for a choice */ - prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0); - - /* Give some choices */ - prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5); - -#ifdef ALLOW_COLORS - prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5); - prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5); -#endif - - /* Prompt */ - prt(_("コマンド: ", "Command: "), 8, 0); - /* Prompt */ - i = inkey(); - - if (i == ESCAPE) break; - - /* Load a 'pref' file */ - if (i == '1') - { - /* Prompt */ - prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0); - - /* Prompt */ - prt(_("ファイル: ", "File: "), 10, 0); - - /* Default file */ - sprintf(tmp, "%s.prf", player_base); - - /* Query */ - if (!askfor(tmp, 70)) continue; - - /* Process the given filename */ - (void)process_pref_file(tmp); - - /* Mega-Hack -- react to changes */ - Term_xtra(TERM_XTRA_REACT, 0); - - /* Mega-Hack -- redraw */ - Term_redraw(); - } - -#ifdef ALLOW_COLORS - - /* Dump colors */ - else if (i == '2') - { - static concptr mark = "Colors"; - - /* Prompt */ - prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0); - - /* Prompt */ - prt(_("ファイル: ", "File: "), 10, 0); - - /* Default filename */ - sprintf(tmp, "%s.prf", player_base); - - /* Get a filename */ - if (!askfor(tmp, 70)) continue; - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp); - - /* Append to the file */ - if (!open_auto_dump(buf, mark)) continue; - - /* Start dumping */ - auto_dump_printf(_("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n")); - - /* Dump colors */ - for (i = 0; i < 256; i++) - { - int kv = angband_color_table[i][0]; - int rv = angband_color_table[i][1]; - int gv = angband_color_table[i][2]; - int bv = angband_color_table[i][3]; - - concptr name = _("未知", "unknown"); - - /* Skip non-entries */ - if (!kv && !rv && !gv && !bv) continue; - - /* Extract the color name */ - if (i < 16) name = color_names[i]; - - /* Dump a comment */ - auto_dump_printf(_("# カラー '%s'\n", "# Color '%s'\n"), name); - - /* Dump the monster attr/char info */ - auto_dump_printf("V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n", - i, kv, rv, gv, bv); - } - - /* Close */ - close_auto_dump(); - - msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions.")); - } - - /* Edit colors */ - else if (i == '3') - { - static byte a = 0; - - /* Prompt */ - prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0); - - /* Hack -- query until done */ - while (1) - { - concptr name; - byte j; - - /* Clear */ - clear_from(10); - - /* Exhibit the normal colors */ - for (j = 0; j < 16; j++) - { - /* Exhibit this color */ - Term_putstr(j*4, 20, -1, a, "###"); - - /* Exhibit all colors */ - Term_putstr(j*4, 22, -1, j, format("%3d", j)); - } - - /* Describe the color */ - name = ((a < 16) ? color_names[a] : _("未定義", "undefined")); - - /* Describe the color */ - Term_putstr(5, 10, -1, TERM_WHITE, - format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name)); - - /* Label the Current values */ - Term_putstr(5, 12, -1, TERM_WHITE, - format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x", - angband_color_table[a][0], - angband_color_table[a][1], - angband_color_table[a][2], - angband_color_table[a][3])); - - /* Prompt */ - Term_putstr(0, 14, -1, TERM_WHITE, - _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): ")); - - i = inkey(); - - /* All done */ - if (i == ESCAPE) break; - - /* Analyze */ - if (i == 'n') a = (byte)(a + 1); - if (i == 'N') a = (byte)(a - 1); - if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1); - if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1); - if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1); - if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1); - if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1); - if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1); - if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1); - if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1); - - /* Hack -- react to changes */ - Term_xtra(TERM_XTRA_REACT, 0); - - /* Hack -- redraw */ - Term_redraw(); - } - } - -#endif - - /* Unknown option */ - else - { - bell(); - } - - msg_erase(); - } - - screen_load(); -} - - -/* - * Note something in the message recall - */ -void do_cmd_note(void) -{ - char buf[80]; - - /* Default */ - strcpy(buf, ""); - - /* Input */ - if (!get_string(_("メモ: ", "Note: "), buf, 60)) return; - - /* Ignore empty notes */ - if (!buf[0] || (buf[0] == ' ')) return; - - /* Add the note to the message recall */ - msg_format(_("メモ: %s", "Note: %s"), buf); -} - - -/* - * Mention the current version - */ -void do_cmd_version(void) -{ -#if FAKE_VER_EXTRA > 0 - msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."), - FAKE_VER_MAJOR-10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA); -#else - msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."), - FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH); -#endif -} - - - -/* - * Array of feeling strings - */ -static concptr do_cmd_feeling_text[11] = -{ - _("この階の雰囲気を感じとれなかった...", "Looks like any other level."), - _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."), - _("恐ろしい死の幻が目に浮かび、気絶しそうになった!", "You nearly faint as horrible visions of death fill your mind!"), - _("この階はとても危険なようだ。", "This level looks very dangerous."), - _("とても悪い予感がする...", "You have a very bad feeling..."), - _("悪い予感がする...", "You have a bad feeling..."), - _("何か緊張する。", "You feel nervous."), - _("少し不運な気がする...", "You feel your luck is turning..."), - _("この場所は好きになれない。", "You don't like the look of this place."), - _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."), - _("なんて退屈なところだ...", "What a boring place...") -}; - -static concptr do_cmd_feeling_text_combat[11] = -{ - _("この階の雰囲気を感じとれなかった...", "Looks like any other level."), - _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."), - _("今夜もまた、誰かが命を落とす...", "You nearly faint as horrible visions of death fill your mind!"), - _("この階はとても危険なようだ。", "This level looks very dangerous."), - _("とても悪い予感がする...", "You have a very bad feeling..."), - _("悪い予感がする...", "You have a bad feeling..."), - _("何か緊張する。", "You feel nervous."), - _("少し不運な気がする...", "You feel your luck is turning..."), - _("この場所は好きになれない。", "You don't like the look of this place."), - _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."), - _("なんて退屈なところだ...", "What a boring place...") -}; - -static concptr do_cmd_feeling_text_lucky[11] = -{ - _("この階の雰囲気を感じとれなかった...", "Looks like any other level."), - _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."), - _("この階はこの上なく素晴らしい感じがする。", "You have a superb feeling about this level."), - _("素晴らしい感じがする...", "You have an excellent feeling..."), - _("とても良い感じがする...", "You have a very good feeling..."), - _("良い感じがする...", "You have a good feeling..."), - _("ちょっと幸運な感じがする...", "You feel strangely lucky..."), - _("多少は運が向いてきたか...", "You feel your luck is turning..."), - _("見た感じ悪くはない...", "You like the look of this place..."), - _("全然駄目ということはないが...", "This level can't be all bad..."), - _("なんて退屈なところだ...", "What a boring place...") -}; - - -/* - * Note that "feeling" is set to zero unless some time has passed. - * Note that this is done when the level is GENERATED, not entered. - */ -void do_cmd_feeling(void) -{ - if (p_ptr->wild_mode) return; - - /* No useful feeling in quests */ - if (p_ptr->inside_quest && !random_quest_number(current_floor_ptr->dun_level)) - { - msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level.")); - return; - } - - /* No useful feeling in town */ - else if (p_ptr->town_num && !current_floor_ptr->dun_level) - { - if (!strcmp(town_info[p_ptr->town_num].name, _("荒野", "wilderness"))) - { - msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness.")); - return; - } - else - { - msg_print(_("典型的な町のようだ。", "Looks like a typical town.")); - return; - } - } - - /* No useful feeling in the wilderness */ - else if (!current_floor_ptr->dun_level) - { - msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness.")); - return; - } - - /* Display the feeling */ - if (p_ptr->muta3 & MUT3_GOOD_LUCK) - msg_print(do_cmd_feeling_text_lucky[p_ptr->feeling]); - else if (p_ptr->pseikaku == SEIKAKU_COMBAT || - inventory[INVEN_BOW].name1 == ART_CRIMSON) - msg_print(do_cmd_feeling_text_combat[p_ptr->feeling]); - else - msg_print(do_cmd_feeling_text[p_ptr->feeling]); -} - - - -/* - * Description of each monster group. - */ -static concptr monster_group_text[] = -{ -#ifdef JP - "ユニーク", /* "Uniques" */ - "乗馬可能なモンスター", /* "Riding" */ - "賞金首", /* "Wanted */ - "アンバーの王族", /* "Ambertite" */ - "アリ", - "コウモリ", - "ムカデ", - "ドラゴン", - "目玉", - "ネコ", - "ゴーレム", - "標準人間型生物", - "ベトベト", - "ゼリー", - "コボルド", - "水棲生物", - "モルド", - "ナーガ", - "オーク", - "人間", - "四足獣", - "ネズミ", - "スケルトン", - "デーモン", - "ボルテックス", - "イモムシ/大群", - /* "unused", */ - "イーク", - "ゾンビ/ミイラ", - "天使", - "鳥", - "犬", - /* "古代ドラゴン/ワイアーム", */ - "エレメンタル", - "トンボ", - "ゴースト", - "雑種", - "昆虫", - "ヘビ", - "キラー・ビートル", - "リッチ", - "多首の爬虫類", - "謎の生物", - "オーガ", - "巨大人間型生物", - "クイルスルグ", - "爬虫類/両生類", - "蜘蛛/サソリ/ダニ", - "トロル", - /* "上級デーモン", */ - "バンパイア", - "ワイト/レイス/等", - "ゾーン/ザレン/等", - "イエティ", - "ハウンド", - "ミミック", - "壁/植物/気体", - "おばけキノコ", - "球体", - "プレイヤー", -#else - "Uniques", - "Ridable monsters", - "Wanted monsters", - "Ambertite", - "Ant", - "Bat", - "Centipede", - "Dragon", - "Floating Eye", - "Feline", - "Golem", - "Hobbit/Elf/Dwarf", - "Icky Thing", - "Jelly", - "Kobold", - "Aquatic monster", - "Mold", - "Naga", - "Orc", - "Person/Human", - "Quadruped", - "Rodent", - "Skeleton", - "Demon", - "Vortex", - "Worm/Worm-Mass", - /* "unused", */ - "Yeek", - "Zombie/Mummy", - "Angel", - "Bird", - "Canine", - /* "Ancient Dragon/Wyrm", */ - "Elemental", - "Dragon Fly", - "Ghost", - "Hybrid", - "Insect", - "Snake", - "Killer Beetle", - "Lich", - "Multi-Headed Reptile", - "Mystery Living", - "Ogre", - "Giant Humanoid", - "Quylthulg", - "Reptile/Amphibian", - "Spider/Scorpion/Tick", - "Troll", - /* "Major Demon", */ - "Vampire", - "Wight/Wraith/etc", - "Xorn/Xaren/etc", - "Yeti", - "Zephyr Hound", - "Mimic", - "Wall/Plant/Gas", - "Mushroom patch", - "Ball", - "Player", -#endif - NULL -}; - - -/* - * Symbols of monsters in each group. Note the "Uniques" group - * is handled differently. - */ -static concptr monster_group_char[] = -{ - (char *) -1L, - (char *) -2L, - (char *) -3L, - (char *) -4L, - "a", - "b", - "c", - "dD", - "e", - "f", - "g", - "h", - "i", - "j", - "k", - "l", - "m", - "n", - "o", - "pt", - "q", - "r", - "s", - "uU", - "v", - "w", - /* "x", */ - "y", - "z", - "A", - "B", - "C", - /* "D", */ - "E", - "F", - "G", - "H", - "I", - "J", - "K", - "L", - "M", - "N", - "O", - "P", - "Q", - "R", - "S", - "T", - /* "U", */ - "V", - "W", - "X", - "Y", - "Z", - "!$&()+./=>?[\\]`{|~", - "#%", - ",", - "*", - "@", - NULL -}; - - -/* - * Build a list of monster indexes in the given group. Return the number - * of monsters in the group. - * - * mode & 0x01 : check for non-empty group - * mode & 0x02 : visual operation only - */ -static IDX collect_monsters(IDX grp_cur, IDX mon_idx[], BIT_FLAGS8 mode) -{ - IDX i; - IDX mon_cnt = 0; - int dummy_why; - - /* Get a list of x_char in this group */ - concptr group_char = monster_group_char[grp_cur]; - - /* XXX Hack -- Check if this is the "Uniques" group */ - bool grp_unique = (monster_group_char[grp_cur] == (char *) -1L); - - /* XXX Hack -- Check if this is the "Riding" group */ - bool grp_riding = (monster_group_char[grp_cur] == (char *) -2L); - - /* XXX Hack -- Check if this is the "Wanted" group */ - bool grp_wanted = (monster_group_char[grp_cur] == (char *) -3L); - - /* XXX Hack -- Check if this is the "Amberite" group */ - bool grp_amberite = (monster_group_char[grp_cur] == (char *) -4L); - - - /* Check every race */ - for (i = 0; i < max_r_idx; i++) - { - /* Access the race */ - monster_race *r_ptr = &r_info[i]; - - /* Skip empty race */ - if (!r_ptr->name) continue ; - - /* Require known monsters */ - if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights) continue; - - if (grp_unique) - { - if (!(r_ptr->flags1 & RF1_UNIQUE)) continue; - } - - else if (grp_riding) - { - if (!(r_ptr->flags7 & RF7_RIDING)) continue; - } - - else if (grp_wanted) - { - bool wanted = FALSE; - int j; - for (j = 0; j < MAX_KUBI; j++) - { - if (current_world_ptr->bounty_r_idx[j] == i || current_world_ptr->bounty_r_idx[j] - 10000 == i || - (p_ptr->today_mon && p_ptr->today_mon == i)) - { - wanted = TRUE; - break; - } - } - if (!wanted) continue; - } - - else if (grp_amberite) - { - if (!(r_ptr->flags3 & RF3_AMBERITE)) continue; - } - - else - { - /* Check for race in the group */ - if (!my_strchr(group_char, r_ptr->d_char)) continue; - } - - /* Add the race */ - mon_idx[mon_cnt++] = i; - - /* XXX Hack -- Just checking for non-empty group */ - if (mode & 0x01) break; - } - - /* Terminate the list */ - mon_idx[mon_cnt] = -1; - - ang_sort(mon_idx, &dummy_why, mon_cnt, ang_sort_comp_monster_level, ang_sort_swap_hook); - - /* Return the number of races */ - return mon_cnt; -} - - -/* - * Description of each monster group. - */ -static concptr object_group_text[] = -{ -#ifdef JP - "キノコ", /* "Mushrooms" */ - "薬", /* "Potions" */ - "油つぼ", /* "Flasks" */ - "巻物", /* "Scrolls" */ - "指輪", /* "Rings" */ - "アミュレット", /* "Amulets" */ - "笛", /* "Whistle" */ - "光源", /* "Lanterns" */ - "魔法棒", /* "Wands" */ - "杖", /* "Staffs" */ - "ロッド", /* "Rods" */ - "カード", /* "Cards" */ - "キャプチャー・ボール", - "羊皮紙", - "くさび", - "箱", - "人形", - "像", - "ゴミ", - "空のビン", - "骨", - "死体", - "刀剣類", /* "Swords" */ - "鈍器", /* "Blunt Weapons" */ - "長柄武器", /* "Polearms" */ - "採掘道具", /* "Diggers" */ - "飛び道具", /* "Bows" */ - "弾", - "矢", - "ボルト", - "軽装鎧", /* "Soft Armor" */ - "重装鎧", /* "Hard Armor" */ - "ドラゴン鎧", /* "Dragon Armor" */ - "盾", /* "Shields" */ - "クローク", /* "Cloaks" */ - "籠手", /* "Gloves" */ - "ヘルメット", /* "Helms" */ - "冠", /* "Crowns" */ - "ブーツ", /* "Boots" */ - "魔法書", - "財宝", - "何か", -#else - "Mushrooms", - "Potions", - "Flasks", - "Scrolls", - "Rings", - "Amulets", - "Whistle", - "Lanterns", - "Wands", - "Staves", - "Rods", - "Cards", - "Capture Balls", - "Parchments", - "Spikes", - "Boxs", - "Figurines", - "Statues", - "Junks", - "Bottles", - "Skeletons", - "Corpses", - "Swords", - "Blunt Weapons", - "Polearms", - "Diggers", - "Bows", - "Shots", - "Arrows", - "Bolts", - "Soft Armor", - "Hard Armor", - "Dragon Armor", - "Shields", - "Cloaks", - "Gloves", - "Helms", - "Crowns", - "Boots", - "Spellbooks", - "Treasure", - "Something", -#endif - NULL -}; - - -/* - * TVALs of items in each group - */ -static byte object_group_tval[] = -{ - TV_FOOD, - TV_POTION, - TV_FLASK, - TV_SCROLL, - TV_RING, - TV_AMULET, - TV_WHISTLE, - TV_LITE, - TV_WAND, - TV_STAFF, - TV_ROD, - TV_CARD, - TV_CAPTURE, - TV_PARCHMENT, - TV_SPIKE, - TV_CHEST, - TV_FIGURINE, - TV_STATUE, - TV_JUNK, - TV_BOTTLE, - TV_SKELETON, - TV_CORPSE, - TV_SWORD, - TV_HAFTED, - TV_POLEARM, - TV_DIGGING, - TV_BOW, - TV_SHOT, - TV_ARROW, - TV_BOLT, - TV_SOFT_ARMOR, - TV_HARD_ARMOR, - TV_DRAG_ARMOR, - TV_SHIELD, - TV_CLOAK, - TV_GLOVES, - TV_HELM, - TV_CROWN, - TV_BOOTS, - TV_LIFE_BOOK, /* Hack -- all spellbooks */ - TV_GOLD, - 0, - 0, -}; - - -/* - * Build a list of object indexes in the given group. Return the number - * of objects in the group. - * - * mode & 0x01 : check for non-empty group - * mode & 0x02 : visual operation only - */ -static KIND_OBJECT_IDX collect_objects(int grp_cur, KIND_OBJECT_IDX object_idx[], BIT_FLAGS8 mode) -{ - KIND_OBJECT_IDX i, object_cnt = 0; - int j, k; - - /* Get a list of x_char in this group */ - byte group_tval = object_group_tval[grp_cur]; - - /* Check every object */ - for (i = 0; i < max_k_idx; i++) - { - /* Access the object */ - object_kind *k_ptr = &k_info[i]; - - /* Skip empty objects */ - if (!k_ptr->name) continue; - - if (mode & 0x02) - { - /* Any objects will be displayed */ - } - else - { - if (!p_ptr->wizard) - { - /* Skip non-flavoured objects */ - if (!k_ptr->flavor) continue; - - /* Require objects ever seen */ - if (!k_ptr->aware) continue; - } - - /* Skip items with no distribution (special artifacts) */ - for (j = 0, k = 0; j < 4; j++) k += k_ptr->chance[j]; - if (!k) continue; - } - - /* Check for objects in the group */ - if (TV_LIFE_BOOK == group_tval) - { - /* Hack -- All spell books */ - if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK) - { - /* Add the object */ - object_idx[object_cnt++] = i; - } - else continue; - } - else if (k_ptr->tval == group_tval) - { - /* Add the object */ - object_idx[object_cnt++] = i; - } - else continue; - - /* XXX Hack -- Just checking for non-empty group */ - if (mode & 0x01) break; - } - - /* Terminate the list */ - object_idx[object_cnt] = -1; - - /* Return the number of objects */ - return object_cnt; -} - - -/* - * Description of each feature group. - */ -static concptr feature_group_text[] = -{ - "terrains", - NULL -}; - - -/* - * Build a list of feature indexes in the given group. Return the number - * of features in the group. - * - * mode & 0x01 : check for non-empty group - */ -static FEAT_IDX collect_features(int grp_cur, FEAT_IDX *feat_idx, BIT_FLAGS8 mode) -{ - FEAT_IDX i; - FEAT_IDX feat_cnt = 0; - - /* Unused; There is a single group. */ - (void)grp_cur; - - /* Check every feature */ - for (i = 0; i < max_f_idx; i++) - { - feature_type *f_ptr = &f_info[i]; - - /* Skip empty index */ - if (!f_ptr->name) continue; - - /* Skip mimiccing features */ - if (f_ptr->mimic != i) continue; - - /* Add the index */ - feat_idx[feat_cnt++] = i; - - /* XXX Hack -- Just checking for non-empty group */ - if (mode & 0x01) break; - } - - /* Terminate the list */ - feat_idx[feat_cnt] = -1; - - /* Return the number of races */ - return feat_cnt; -} - - -#if 0 -/* - * Build a list of monster indexes in the given group. Return the number - * of monsters in the group. - */ -static int collect_artifacts(int grp_cur, int object_idx[]) -{ - int i, object_cnt = 0; - - /* Get a list of x_char in this group */ - byte group_tval = object_group_tval[grp_cur]; - - /* Check every object */ - for (i = 0; i < max_a_idx; i++) - { - /* Access the artifact */ - artifact_type *a_ptr = &a_info[i]; - - /* Skip empty artifacts */ - if (!a_ptr->name) continue; - - /* Skip "uncreated" artifacts */ - if (!a_ptr->cur_num) continue; - - /* Check for race in the group */ - if (a_ptr->tval == group_tval) - { - /* Add the race */ - object_idx[object_cnt++] = i; - } - } - - /* Terminate the list */ - object_idx[object_cnt] = 0; - - /* Return the number of races */ - return object_cnt; -} -#endif /* 0 */ - - -/* - * Encode the screen colors - */ -static char hack[17] = "dwsorgbuDWvyRGBU"; - - -/* - * Hack -- load a screen dump from a file - */ -void do_cmd_load_screen(void) -{ - int i; - TERM_LEN y, x; - TERM_COLOR a = 0; - SYMBOL_CODE c = ' '; - bool okay = TRUE; - FILE *fff; - char buf[1024]; - TERM_LEN wid, hgt; - - Term_get_size(&wid, &hgt); - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt"); - - /* Append to the file */ - fff = my_fopen(buf, "r"); - - if (!fff) { - msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf); - msg_print(NULL); - return; - } - - screen_save(); - Term_clear(); - - /* Load the screen */ - for (y = 0; okay; y++) - { - /* Get a line of data including control code */ - if (!fgets(buf, 1024, fff)) okay = FALSE; - - /* Get the blank line */ - if (buf[0] == '\n' || buf[0] == '\0') break; - - /* Ignore too large screen image */ - if (y >= hgt) continue; - - /* Show each row */ - for (x = 0; x < wid - 1; x++) - { - /* End of line */ - if (buf[x] == '\n' || buf[x] == '\0') break; - - /* Put the attr/char */ - Term_draw(x, y, TERM_WHITE, buf[x]); - } - } - - /* Dump the screen */ - for (y = 0; okay; y++) - { - /* Get a line of data including control code */ - if (!fgets(buf, 1024, fff)) okay = FALSE; - - /* Get the blank line */ - if (buf[0] == '\n' || buf[0] == '\0') break; - - /* Ignore too large screen image */ - if (y >= hgt) continue; - - /* Dump each row */ - for (x = 0; x < wid - 1; x++) - { - /* End of line */ - if (buf[x] == '\n' || buf[x] == '\0') break; - - /* Get the attr/char */ - (void)(Term_what(x, y, &a, &c)); - - /* Look up the attr */ - for (i = 0; i < 16; i++) - { - /* Use attr matches */ - if (hack[i] == buf[x]) a = (byte_hack)i; - } - - /* Put the attr/char */ - Term_draw(x, y, a, c); - } - } - my_fclose(fff); - - prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0); - - flush(); - inkey(); - - screen_load(); -} - - - - -concptr inven_res_label = _(" 酸電火冷毒光闇破轟獄因沌劣 盲怖乱痺透命感消復浮", - " AcElFiCoPoLiDkShSoNtNxCaDi BlFeCfFaSeHlEpSdRgLv"); - - -#define IM_FLAG_STR _("*", "* ") -#define HAS_FLAG_STR _("+", "+ ") -#define NO_FLAG_STR _("・", ". ") - -#define print_im_or_res_flag(IM, RES) \ -{ \ - fputs(have_flag(flgs, (IM)) ? IM_FLAG_STR : \ - (have_flag(flgs, (RES)) ? HAS_FLAG_STR : NO_FLAG_STR), fff); \ -} - -#define print_flag(TR) \ -{ \ - fputs(have_flag(flgs, (TR)) ? HAS_FLAG_STR : NO_FLAG_STR, fff); \ -} - - -/* XTRA HACK RESLIST */ -static void do_cmd_knowledge_inven_aux(FILE *fff, object_type *o_ptr, int *j, OBJECT_TYPE_VALUE tval, char *where) -{ - GAME_TEXT o_name[MAX_NLEN]; - BIT_FLAGS flgs[TR_FLAG_SIZE]; - - if (!o_ptr->k_idx) return; - if (o_ptr->tval != tval) return; - - /* Identified items only */ - if (!object_is_known(o_ptr)) return; - - /* - * HACK:Ring of Lordly protection and Dragon equipment - * have random resistances. - */ - if ((object_is_wearable(o_ptr) && object_is_ego(o_ptr)) - || ((tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_RESISTANCE)) - || ((tval == TV_RING) && (o_ptr->sval == SV_RING_LORDLY)) - || ((tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD)) - || ((tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM)) - || ((tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES)) - || ((tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE)) - || object_is_artifact(o_ptr)) - { - int i = 0; - object_desc(o_name, o_ptr, OD_NAME_ONLY); - - while (o_name[i] && (i < 26)) - { -#ifdef JP - if (iskanji(o_name[i])) i++; -#endif - i++; - } - - if (i < 28) - { - while (i < 28) - { - o_name[i] = ' '; i++; - } - } - o_name[i] = '\0'; - - fprintf(fff, "%s %s", where, o_name); - - if (!(o_ptr->ident & (IDENT_MENTAL))) - { - fputs(_("-------不明--------------- -------不明---------\n", - "-------unknown------------ -------unknown------\n"), fff); - } - else - { - object_flags_known(o_ptr, flgs); - - print_im_or_res_flag(TR_IM_ACID, TR_RES_ACID); - print_im_or_res_flag(TR_IM_ELEC, TR_RES_ELEC); - print_im_or_res_flag(TR_IM_FIRE, TR_RES_FIRE); - print_im_or_res_flag(TR_IM_COLD, TR_RES_COLD); - print_flag(TR_RES_POIS); - print_flag(TR_RES_LITE); - print_flag(TR_RES_DARK); - print_flag(TR_RES_SHARDS); - print_flag(TR_RES_SOUND); - print_flag(TR_RES_NETHER); - print_flag(TR_RES_NEXUS); - print_flag(TR_RES_CHAOS); - print_flag(TR_RES_DISEN); - - fputs(" ", fff); - - print_flag(TR_RES_BLIND); - print_flag(TR_RES_FEAR); - print_flag(TR_RES_CONF); - print_flag(TR_FREE_ACT); - print_flag(TR_SEE_INVIS); - print_flag(TR_HOLD_EXP); - print_flag(TR_TELEPATHY); - print_flag(TR_SLOW_DIGEST); - print_flag(TR_REGEN); - print_flag(TR_LEVITATION); - - fputc('\n', fff); - } - (*j)++; - if (*j == 9) - { - *j = 0; - fprintf(fff, "%s\n", inven_res_label); - } - } -} - -/* - * Display *ID* ed weapons/armors's resistances - */ -static void do_cmd_knowledge_inven(void) -{ - FILE *fff; - GAME_TEXT file_name[1024]; - store_type *st_ptr; - OBJECT_TYPE_VALUE tval; - int i = 0; - int j = 0; - - char where[32]; - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - if (!fff) - { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - fprintf(fff, "%s\n", inven_res_label); - - for (tval = TV_WEARABLE_BEGIN; tval <= TV_WEARABLE_END; tval++) - { - if (j != 0) - { - for (; j < 9; j++) fputc('\n', fff); - j = 0; - fprintf(fff, "%s\n", inven_res_label); - } - strcpy(where, _("装", "E ")); - for (i = INVEN_RARM; i < INVEN_TOTAL; i++) - { - do_cmd_knowledge_inven_aux(fff, &inventory[i], &j, tval, where); - } - strcpy(where, _("持", "I ")); - for (i = 0; i < INVEN_PACK; i++) - { - do_cmd_knowledge_inven_aux(fff, &inventory[i], &j, tval, where); - } - - st_ptr = &town_info[1].store[STORE_HOME]; - strcpy(where, _("家", "H ")); - for (i = 0; i < st_ptr->stock_num; i++) - { - do_cmd_knowledge_inven_aux(fff, &st_ptr->stock[i], &j, tval, where); - } - } - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("*鑑定*済み武器/防具の耐性リスト", "Resistances of *identified* equipment"), 0, 0); - fd_kill(file_name); -} - - -void do_cmd_save_screen_html_aux(char *filename, int message) -{ - TERM_LEN y, x; - int i; - - TERM_COLOR a = 0, old_a = 0; - char c = ' '; - - FILE *fff, *tmpfff; - char buf[2048]; - - int yomikomu = 0; - concptr tags[4] = { - "HEADER_START:", - "HEADER_END:", - "FOOTER_START:", - "FOOTER_END:", - }; - - concptr html_head[] = { - "\n\n", - "
",
-		0,
-	};
-	concptr html_foot[] = {
-		"
\n", - "\n\n", - 0, - }; - - TERM_LEN wid, hgt; - - Term_get_size(&wid, &hgt); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Append to the file */ - fff = my_fopen(filename, "w"); - - if (!fff) { - if (message) { - msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename); - msg_print(NULL); - } - - return; - } - if (message) screen_save(); - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf"); - tmpfff = my_fopen(buf, "r"); - if (!tmpfff) { - for (i = 0; html_head[i]; i++) - fputs(html_head[i], fff); - } - else { - yomikomu = 0; - while (!my_fgets(tmpfff, buf, sizeof(buf))) { - if (!yomikomu) { - if (strncmp(buf, tags[0], strlen(tags[0])) == 0) - yomikomu = 1; - } - else { - if (strncmp(buf, tags[1], strlen(tags[1])) == 0) - break; - fprintf(fff, "%s\n", buf); - } - } - } - - /* Dump the screen */ - for (y = 0; y < hgt; y++) - { - /* Start the row */ - if (y != 0) - fprintf(fff, "\n"); - - /* Dump each row */ - for (x = 0; x < wid - 1; x++) - { - int rv, gv, bv; - concptr cc = NULL; - /* Get the attr/char */ - (void)(Term_what(x, y, &a, &c)); - - switch (c) - { - case '&': cc = "&"; break; - case '<': cc = "<"; break; - case '>': cc = ">"; break; -#ifdef WINDOWS - case 0x1f: c = '.'; break; - case 0x7f: c = (a == 0x09) ? '%' : '#'; break; -#endif - } - - a = a & 0x0F; - if ((y == 0 && x == 0) || a != old_a) { - rv = angband_color_table[a][1]; - gv = angband_color_table[a][2]; - bv = angband_color_table[a][3]; - fprintf(fff, "%s", - ((y == 0 && x == 0) ? "" : ""), rv, gv, bv); - old_a = a; - } - if (cc) - fprintf(fff, "%s", cc); - else - fprintf(fff, "%c", c); - } - } - fprintf(fff, ""); - - if (!tmpfff) { - for (i = 0; html_foot[i]; i++) - fputs(html_foot[i], fff); - } - else { - rewind(tmpfff); - yomikomu = 0; - while (!my_fgets(tmpfff, buf, sizeof(buf))) { - if (!yomikomu) { - if (strncmp(buf, tags[2], strlen(tags[2])) == 0) - yomikomu = 1; - } - else { - if (strncmp(buf, tags[3], strlen(tags[3])) == 0) - break; - fprintf(fff, "%s\n", buf); - } - } - my_fclose(tmpfff); - } - - /* Skip a line */ - fprintf(fff, "\n"); - my_fclose(fff); - - if (message) { - msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved.")); - msg_print(NULL); - } - if (message) - screen_load(); -} - -/* - * Hack -- save a screen dump to a file - */ -static void do_cmd_save_screen_html(void) -{ - char buf[1024], tmp[256] = "screen.html"; - - if (!get_string(_("ファイル名: ", "File name: "), tmp, 80)) - return; - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp); - - msg_print(NULL); - - do_cmd_save_screen_html_aux(buf, 1); -} - - -/* - * Redefinable "save_screen" action - */ -void (*screendump_aux)(void) = NULL; - - -/* - * Hack -- save a screen dump to a file - */ -void do_cmd_save_screen(void) -{ - bool old_use_graphics = use_graphics; - bool html_dump = FALSE; - - int wid, hgt; - - prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0); - while(TRUE) - { - char c = inkey(); - if (c == 'Y' || c == 'y') - break; - else if (c == 'H' || c == 'h') - { - html_dump = TRUE; - break; - } - else - { - prt("", 0, 0); - return; - } - } - - Term_get_size(&wid, &hgt); - - if (old_use_graphics) - { - use_graphics = FALSE; - reset_visuals(); - p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY); - handle_stuff(); - } - - if (html_dump) - { - do_cmd_save_screen_html(); - do_cmd_redraw(); - } - - /* Do we use a special screendump function ? */ - else if (screendump_aux) - { - /* Dump the screen to a graphics file */ - (*screendump_aux)(); - } - else /* Dump the screen as text */ - { - TERM_LEN y, x; - TERM_COLOR a = 0; - SYMBOL_CODE c = ' '; - FILE *fff; - char buf[1024]; - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt"); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Append to the file */ - fff = my_fopen(buf, "w"); - - if (!fff) - { - msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf); - msg_print(NULL); - return; - } - - screen_save(); - - - /* Dump the screen */ - for (y = 0; y < hgt; y++) - { - /* Dump each row */ - for (x = 0; x < wid - 1; x++) - { - /* Get the attr/char */ - (void)(Term_what(x, y, &a, &c)); - - /* Dump it */ - buf[x] = c; - } - - /* Terminate */ - buf[x] = '\0'; - - /* End the row */ - fprintf(fff, "%s\n", buf); - } - - /* Skip a line */ - fprintf(fff, "\n"); - - - /* Dump the screen */ - for (y = 0; y < hgt; y++) - { - /* Dump each row */ - for (x = 0; x < wid - 1; x++) - { - /* Get the attr/char */ - (void)(Term_what(x, y, &a, &c)); - - /* Dump it */ - buf[x] = hack[a&0x0F]; - } - - /* Terminate */ - buf[x] = '\0'; - - /* End the row */ - fprintf(fff, "%s\n", buf); - } - - /* Skip a line */ - fprintf(fff, "\n"); - my_fclose(fff); - - msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved.")); - msg_print(NULL); - screen_load(); - } - - if (old_use_graphics) - { - use_graphics = TRUE; - reset_visuals(); - p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY); - handle_stuff(); - } -} - -/* - * Check the status of "artifacts" - */ -static void do_cmd_knowledge_artifacts(void) -{ - ARTIFACT_IDX i; - ARTIFACT_IDX k; - POSITION x, y; - int n = 0; - ARTIFACT_IDX z; - u16b why = 3; - ARTIFACT_IDX *who; - FILE *fff; - GAME_TEXT file_name[1024]; - GAME_TEXT base_name[MAX_NLEN]; - - bool *okay; - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - - if (!fff) { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - /* Allocate the "who" array */ - C_MAKE(who, max_a_idx, ARTIFACT_IDX); - - /* Allocate the "okay" array */ - C_MAKE(okay, max_a_idx, bool); - - /* Scan the artifacts */ - for (k = 0; k < max_a_idx; k++) - { - artifact_type *a_ptr = &a_info[k]; - - /* Default */ - okay[k] = FALSE; - - /* Skip "empty" artifacts */ - if (!a_ptr->name) continue; - - /* Skip "uncreated" artifacts */ - if (!a_ptr->cur_num) continue; - - /* Assume okay */ - okay[k] = TRUE; - } - - /* Check the dungeon */ - for (y = 0; y < current_floor_ptr->height; y++) - { - for (x = 0; x < current_floor_ptr->width; x++) - { - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; - - OBJECT_IDX this_o_idx, next_o_idx = 0; - - /* Scan all objects in the grid */ - for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) - { - object_type *o_ptr; - o_ptr = ¤t_floor_ptr->o_list[this_o_idx]; - next_o_idx = o_ptr->next_o_idx; - - /* Ignore non-artifacts */ - if (!object_is_fixed_artifact(o_ptr)) continue; - - /* Ignore known items */ - if (object_is_known(o_ptr)) continue; - - /* Note the artifact */ - okay[o_ptr->name1] = FALSE; - } - } - } - - /* Check the inventory and equipment */ - for (i = 0; i < INVEN_TOTAL; i++) - { - object_type *o_ptr = &inventory[i]; - - /* Ignore non-objects */ - if (!o_ptr->k_idx) continue; - - /* Ignore non-artifacts */ - if (!object_is_fixed_artifact(o_ptr)) continue; - - /* Ignore known items */ - if (object_is_known(o_ptr)) continue; - - /* Note the artifact */ - okay[o_ptr->name1] = FALSE; - } - - for (k = 0; k < max_a_idx; k++) - { - if (okay[k]) who[n++] = k; - } - - ang_sort(who, &why, n, ang_sort_art_comp, ang_sort_art_swap); - - /* Scan the artifacts */ - for (k = 0; k < n; k++) - { - artifact_type *a_ptr = &a_info[who[k]]; - strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact")); - - /* Obtain the base object type */ - z = lookup_kind(a_ptr->tval, a_ptr->sval); - - /* Real object */ - if (z) - { - object_type forge; - object_type *q_ptr; - q_ptr = &forge; - - /* Create fake object */ - object_prep(q_ptr, z); - - /* Make it an artifact */ - q_ptr->name1 = (byte)who[k]; - - /* Display as if known */ - q_ptr->ident |= IDENT_STORE; - - /* Describe the artifact */ - object_desc(base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - } - - /* Hack -- Build the artifact name */ - fprintf(fff, _(" %s\n", " The %s\n"), base_name); - } - - /* Free the "who" array */ - C_KILL(who, max_a_idx, ARTIFACT_IDX); - - /* Free the "okay" array */ - C_KILL(okay, max_a_idx, bool); - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0); - fd_kill(file_name); -} - - -/* - * Display known uniques - * With "XTRA HACK UNIQHIST" (Originally from XAngband) - */ -static void do_cmd_knowledge_uniques(void) -{ - IDX i; - int k, n = 0; - u16b why = 2; - IDX *who; - - FILE *fff; - - GAME_TEXT file_name[1024]; - - int n_alive[10]; - int n_alive_surface = 0; - int n_alive_over100 = 0; - int n_alive_total = 0; - int max_lev = -1; - - for (i = 0; i < 10; i++) n_alive[i] = 0; - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - - if (!fff) - { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - /* Allocate the "who" array */ - C_MAKE(who, max_r_idx, MONRACE_IDX); - - /* Scan the monsters */ - for (i = 1; i < max_r_idx; i++) - { - monster_race *r_ptr = &r_info[i]; - int lev; - - if (!r_ptr->name) continue; - - /* Require unique monsters */ - if (!(r_ptr->flags1 & RF1_UNIQUE)) continue; - - /* Only display "known" uniques */ - if (!cheat_know && !r_ptr->r_sights) continue; - - /* Only print rarity <= 100 uniques */ - if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue; - - /* Only "alive" uniques */ - if (r_ptr->max_num == 0) continue; - - if (r_ptr->level) - { - lev = (r_ptr->level - 1) / 10; - if (lev < 10) - { - n_alive[lev]++; - if (max_lev < lev) max_lev = lev; - } - else n_alive_over100++; - } - else n_alive_surface++; - - /* Collect "appropriate" monsters */ - who[n++] = i; - } - - /* Sort the array by dungeon depth of monsters */ - ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook); - - if (n_alive_surface) - { - fprintf(fff, _(" 地上 生存: %3d体\n", " Surface alive: %3d\n"), n_alive_surface); - n_alive_total += n_alive_surface; - } - for (i = 0; i <= max_lev; i++) - { - fprintf(fff, _("%3d-%3d階 生存: %3d体\n", "Level %3d-%3d alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]); - n_alive_total += n_alive[i]; - } - if (n_alive_over100) - { - fprintf(fff, _("101- 階 生存: %3d体\n", "Level 101- alive: %3d\n"), n_alive_over100); - n_alive_total += n_alive_over100; - } - - if (n_alive_total) - { - fputs(_("--------- -----------\n", "------------- ----------\n"), fff); - fprintf(fff, _(" 合計 生存: %3d体\n\n", " Total alive: %3d\n\n"), n_alive_total); - } - else - { - fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff); - } - - /* Scan the monster races */ - for (k = 0; k < n; k++) - { - monster_race *r_ptr = &r_info[who[k]]; - - fprintf(fff, _(" %s (レベル%d)\n", " %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level); - } - - /* Free the "who" array */ - C_KILL(who, max_r_idx, s16b); - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0); - fd_kill(file_name); -} - - -/* - * Display weapon-exp - */ -static void do_cmd_knowledge_weapon_exp(void) -{ - int i, num; - SUB_EXP weapon_exp; - KIND_OBJECT_IDX j; - - FILE *fff; - - GAME_TEXT file_name[1024]; - char tmp[30]; - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - if (!fff) { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - for (i = 0; i < 5; i++) - { - for (num = 0; num < 64; num++) - { - for (j = 0; j < max_k_idx; j++) - { - object_kind *k_ptr = &k_info[j]; - - if ((k_ptr->tval == TV_SWORD - i) && (k_ptr->sval == num)) - { - if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue; - - weapon_exp = p_ptr->weapon_exp[4 - i][num]; - strip_name(tmp, j); - fprintf(fff, "%-25s ", tmp); - if (weapon_exp >= s_info[p_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!"); - else fprintf(fff, " "); - fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]); - if (cheat_xtra) fprintf(fff, " %d", weapon_exp); - fprintf(fff, "\n"); - break; - } - } - } - } - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0); - fd_kill(file_name); -} - - -/*! - * @brief 魔法の経験値を表示するコマンドのメインルーチン - * Display spell-exp - * @return なし - */ -static void do_cmd_knowledge_spell_exp(void) -{ - SPELL_IDX i = 0; - SUB_EXP spell_exp; - int exp_level; - - FILE *fff; - const magic_type *s_ptr; - - GAME_TEXT file_name[1024]; - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - if (!fff) { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - if (p_ptr->realm1 != REALM_NONE) - { - fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[p_ptr->realm1]); - for (i = 0; i < 32; i++) - { - if (!is_magic(p_ptr->realm1)) - { - s_ptr = &technic_info[p_ptr->realm1 - MIN_TECHNIC][i]; - } - else - { - s_ptr = &mp_ptr->info[p_ptr->realm1 - 1][i]; - } - if (s_ptr->slevel >= 99) continue; - spell_exp = p_ptr->spell_exp[i]; - exp_level = spell_exp_level(spell_exp); - fprintf(fff, "%-25s ", do_spell(p_ptr->realm1, i, SPELL_NAME)); - if (p_ptr->realm1 == REALM_HISSATSU) - fprintf(fff, "[--]"); - else - { - if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!"); - else fprintf(fff, " "); - fprintf(fff, "%s", exp_level_str[exp_level]); - } - if (cheat_xtra) fprintf(fff, " %d", spell_exp); - fprintf(fff, "\n"); - } - } - - if (p_ptr->realm2 != REALM_NONE) - { - fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[p_ptr->realm2]); - for (i = 0; i < 32; i++) - { - if (!is_magic(p_ptr->realm1)) - { - s_ptr = &technic_info[p_ptr->realm2 - MIN_TECHNIC][i]; - } - else - { - s_ptr = &mp_ptr->info[p_ptr->realm2 - 1][i]; - } - if (s_ptr->slevel >= 99) continue; - - spell_exp = p_ptr->spell_exp[i + 32]; - exp_level = spell_exp_level(spell_exp); - fprintf(fff, "%-25s ", do_spell(p_ptr->realm2, i, SPELL_NAME)); - if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!"); - else fprintf(fff, " "); - fprintf(fff, "%s", exp_level_str[exp_level]); - if (cheat_xtra) fprintf(fff, " %d", spell_exp); - fprintf(fff, "\n"); - } - } - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0); - fd_kill(file_name); -} - - -/*! - * @brief スキル情報を表示するコマンドのメインルーチン / - * Display skill-exp - * @return なし - */ -static void do_cmd_knowledge_skill_exp(void) -{ - int i = 0, skill_exp; - - FILE *fff; - - char file_name[1024]; - char skill_name[GINOU_TEMPMAX][20] = - { - _("マーシャルアーツ", "Martial Arts "), - _("二刀流 ", "Dual Wielding "), - _("乗馬 ", "Riding "), - _("盾 ", "Shield ") - }; - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - if (!fff) { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - for (i = 0; i < GINOU_TEMPMAX; i++) - { - skill_exp = p_ptr->skill_exp[i]; - fprintf(fff, "%-20s ", skill_name[i]); - if (skill_exp >= s_info[p_ptr->pclass].s_max[i]) fprintf(fff, "!"); - else fprintf(fff, " "); - fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]); - if (cheat_xtra) fprintf(fff, " %d", skill_exp); - fprintf(fff, "\n"); - } - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0); - fd_kill(file_name); -} - - -/*! - * @brief 英単語、句、説を複数形を変換する / Pluralize a monster name - * @param Name 変換したい文字列の参照ポインタ - * @return なし - */ -void plural_aux(char *Name) -{ - int NameLen = strlen(Name); - - if (my_strstr(Name, "Disembodied hand")) - { - strcpy(Name, "Disembodied hands that strangled people"); - } - else if (my_strstr(Name, "Colour out of space")) - { - strcpy(Name, "Colours out of space"); - } - else if (my_strstr(Name, "stairway to hell")) - { - strcpy(Name, "stairways to hell"); - } - else if (my_strstr(Name, "Dweller on the threshold")) - { - strcpy(Name, "Dwellers on the threshold"); - } - else if (my_strstr(Name, " of ")) - { - concptr aider = my_strstr(Name, " of "); - char dummy[80]; - int i = 0; - concptr ctr = Name; - - while (ctr < aider) - { - dummy[i] = *ctr; - ctr++; i++; - } - - if (dummy[i-1] == 's') - { - strcpy(&(dummy[i]), "es"); - i++; - } - else - { - strcpy(&(dummy[i]), "s"); - } - - strcpy(&(dummy[i+1]), aider); - strcpy(Name, dummy); - } - else if (my_strstr(Name, "coins")) - { - char dummy[80]; - strcpy(dummy, "piles of "); - strcat(dummy, Name); - strcpy(Name, dummy); - return; - } - else if (my_strstr(Name, "Manes")) - { - return; - } - else if (streq(&(Name[NameLen - 2]), "ey")) - { - strcpy(&(Name[NameLen - 2]), "eys"); - } - else if (Name[NameLen - 1] == 'y') - { - strcpy(&(Name[NameLen - 1]), "ies"); - } - else if (streq(&(Name[NameLen - 4]), "ouse")) - { - strcpy(&(Name[NameLen - 4]), "ice"); - } - else if (streq(&(Name[NameLen - 2]), "us")) - { - strcpy(&(Name[NameLen - 2]), "i"); - } - else if (streq(&(Name[NameLen - 6]), "kelman")) - { - strcpy(&(Name[NameLen - 6]), "kelmen"); - } - else if (streq(&(Name[NameLen - 8]), "wordsman")) - { - strcpy(&(Name[NameLen - 8]), "wordsmen"); - } - else if (streq(&(Name[NameLen - 7]), "oodsman")) - { - strcpy(&(Name[NameLen - 7]), "oodsmen"); - } - else if (streq(&(Name[NameLen - 7]), "eastman")) - { - strcpy(&(Name[NameLen - 7]), "eastmen"); - } - else if (streq(&(Name[NameLen - 8]), "izardman")) - { - strcpy(&(Name[NameLen - 8]), "izardmen"); - } - else if (streq(&(Name[NameLen - 5]), "geist")) - { - strcpy(&(Name[NameLen - 5]), "geister"); - } - else if (streq(&(Name[NameLen - 2]), "ex")) - { - strcpy(&(Name[NameLen - 2]), "ices"); - } - else if (streq(&(Name[NameLen - 2]), "lf")) - { - strcpy(&(Name[NameLen - 2]), "lves"); - } - else if (suffix(Name, "ch") || - suffix(Name, "sh") || - suffix(Name, "nx") || - suffix(Name, "s") || - suffix(Name, "o")) - { - strcpy(&(Name[NameLen]), "es"); - } - else - { - strcpy(&(Name[NameLen]), "s"); - } -} - -/*! - * @brief 現在のペットを表示するコマンドのメインルーチン / - * Display current pets - * @return なし - */ -static void do_cmd_knowledge_pets(void) -{ - int i; - FILE *fff; - monster_type *m_ptr; - GAME_TEXT pet_name[MAX_NLEN]; - int t_friends = 0; - int show_upkeep = 0; - GAME_TEXT file_name[1024]; - - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - if (!fff) { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - /* Process the monsters (backwards) */ - for (i = m_max - 1; i >= 1; i--) - { - /* Access the monster */ - m_ptr = ¤t_floor_ptr->m_list[i]; - - /* Ignore "dead" monsters */ - if (!monster_is_valid(m_ptr)) continue; - - /* Calculate "upkeep" for pets */ - if (is_pet(m_ptr)) - { - t_friends++; - monster_desc(pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE); - fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00)); - } - } - - show_upkeep = calculate_upkeep(); - - fprintf(fff, "----------------------------------------------\n"); -#ifdef JP - fprintf(fff, " 合計: %d 体のペット\n", t_friends); -#else - fprintf(fff, " Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s")); -#endif - fprintf(fff, _(" 維持コスト: %d%% MP\n", " Upkeep: %d%% mana.\n"), show_upkeep); - - - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0); - fd_kill(file_name); -} - - -/*! - * @brief 現在のペットを表示するコマンドのメインルーチン / - * Total kill count - * @return なし - * @note the player ghosts are ignored. - */ -static void do_cmd_knowledge_kill_count(void) -{ - MONRACE_IDX i; - int k, n = 0; - u16b why = 2; - MONRACE_IDX *who; - FILE *fff; - GAME_TEXT file_name[1024]; - - s32b Total = 0; - - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - - if (!fff) { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - /* Allocate the "who" array */ - C_MAKE(who, max_r_idx, MONRACE_IDX); - - { - /* Monsters slain */ - int kk; - - for (kk = 1; kk < max_r_idx; kk++) - { - monster_race *r_ptr = &r_info[kk]; - - if (r_ptr->flags1 & (RF1_UNIQUE)) - { - bool dead = (r_ptr->max_num == 0); - - if (dead) - { - Total++; - } - } - else - { - MONSTER_NUMBER This = r_ptr->r_pkills; - - if (This > 0) - { - Total += This; - } - } - } - - if (Total < 1) - fprintf(fff,_("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n")); - else -#ifdef JP - fprintf(fff,"あなたは%ld体の敵を倒している。\n\n", (long int)Total); -#else - fprintf(fff,"You have defeated %ld %s.\n\n", (long int)Total, (Total == 1) ? "enemy" : "enemies"); -#endif - } - - Total = 0; - - /* Scan the monsters */ - for (i = 1; i < max_r_idx; i++) - { - monster_race *r_ptr = &r_info[i]; - - /* Use that monster */ - if (r_ptr->name) who[n++] = i; - } - - /* Sort the array by dungeon depth of monsters */ - ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook); - - /* Scan the monster races */ - for (k = 0; k < n; k++) - { - monster_race *r_ptr = &r_info[who[k]]; - - if (r_ptr->flags1 & (RF1_UNIQUE)) - { - bool dead = (r_ptr->max_num == 0); - - if (dead) - { - fprintf(fff, " %s\n", (r_name + r_ptr->name)); - Total++; - } - } - else - { - MONSTER_NUMBER This = r_ptr->r_pkills; - - if (This > 0) - { -#ifdef JP - /* p,tは人と数える by ita */ - if (my_strchr("pt", r_ptr->d_char)) - fprintf(fff, " %3d 人の %s\n", (int)This, r_name + r_ptr->name); - else - fprintf(fff, " %3d 体の %s\n", (int)This, r_name + r_ptr->name); -#else - if (This < 2) - { - if (my_strstr(r_name + r_ptr->name, "coins")) - { - fprintf(fff, " 1 pile of %s\n", (r_name + r_ptr->name)); - } - else - { - fprintf(fff, " 1 %s\n", (r_name + r_ptr->name)); - } - } - else - { - char ToPlural[80]; - strcpy(ToPlural, (r_name + r_ptr->name)); - plural_aux(ToPlural); - fprintf(fff, " %d %s\n", This, ToPlural); - } -#endif - - - Total += This; - } - } - } - - fprintf(fff,"----------------------------------------------\n"); -#ifdef JP - fprintf(fff," 合計: %lu 体を倒した。\n", (unsigned long int)Total); -#else - fprintf(fff," Total: %lu creature%s killed.\n", (unsigned long int)Total, (Total == 1 ? "" : "s")); -#endif - - - /* Free the "who" array */ - C_KILL(who, max_r_idx, s16b); - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0); - fd_kill(file_name); -} - - -/*! - * @brief モンスター情報リスト中のグループを表示する / - * Display the object groups. - * @param col 開始行 - * @param row 開始列 - * @param wid 表示文字数幅 - * @param per_page リストの表示行 - * @param grp_idx グループのID配列 - * @param group_text グループ名の文字列配列 - * @param grp_cur 現在の選択ID - * @param grp_top 現在の選択リスト最上部ID - * @return なし - */ -static void display_group_list(int col, int row, int wid, int per_page, IDX grp_idx[], concptr group_text[], int grp_cur, int grp_top) -{ - int i; - - /* Display lines until done */ - for (i = 0; i < per_page && (grp_idx[i] >= 0); i++) - { - /* Get the group index */ - int grp = grp_idx[grp_top + i]; - - /* Choose a color */ - TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE; - - /* Erase the entire line */ - Term_erase(col, row + i, wid); - - /* Display the group label */ - c_put_str(attr, group_text[grp], row + i, col); - } -} - - -/* - * Move the cursor in a browser window - */ -static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt, - IDX *list_cur, int list_cnt) -{ - int d; - int col = *column; - IDX grp = *grp_cur; - IDX list = *list_cur; - - /* Extract direction */ - if (ch == ' ') - { - /* Hack -- scroll up full screen */ - d = 3; - } - else if (ch == '-') - { - /* Hack -- scroll down full screen */ - d = 9; - } - else - { - d = get_keymap_dir(ch); - } - - if (!d) return; - - /* Diagonals - hack */ - if ((ddx[d] > 0) && ddy[d]) - { - int browser_rows; - int wid, hgt; - - Term_get_size(&wid, &hgt); - - browser_rows = hgt - 8; - - /* Browse group list */ - if (!col) - { - int old_grp = grp; - - /* Move up or down */ - grp += ddy[d] * (browser_rows - 1); - - /* Verify */ - if (grp >= grp_cnt) grp = grp_cnt - 1; - if (grp < 0) grp = 0; - if (grp != old_grp) list = 0; - } - - /* Browse sub-list list */ - else - { - /* Move up or down */ - list += ddy[d] * browser_rows; - - /* Verify */ - if (list >= list_cnt) list = list_cnt - 1; - if (list < 0) list = 0; - } - - (*grp_cur) = grp; - (*list_cur) = list; - - return; - } - - if (ddx[d]) - { - col += ddx[d]; - if (col < 0) col = 0; - if (col > 1) col = 1; - - (*column) = col; - - return; - } - - /* Browse group list */ - if (!col) - { - int old_grp = grp; - - /* Move up or down */ - grp += (IDX)ddy[d]; - - /* Verify */ - if (grp >= grp_cnt) grp = grp_cnt - 1; - if (grp < 0) grp = 0; - if (grp != old_grp) list = 0; - } - - /* Browse sub-list list */ - else - { - /* Move up or down */ - list += (IDX)ddy[d]; - - /* Verify */ - if (list >= list_cnt) list = list_cnt - 1; - if (list < 0) list = 0; - } - - (*grp_cur) = grp; - (*list_cur) = list; -} - - -/* - * Display visuals. - */ -static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left) -{ - int i, j; - - /* Clear the display lines */ - for (i = 0; i < height; i++) - { - Term_erase(col, row + i, width); - } - - /* Bigtile mode uses double width */ - if (use_bigtile) width /= 2; - - /* Display lines until done */ - for (i = 0; i < height; i++) - { - /* Display columns until done */ - for (j = 0; j < width; j++) - { - TERM_COLOR a, ia; - SYMBOL_CODE c, ic; - TERM_LEN x = col + j; - TERM_LEN y = row + i; - - /* Bigtile mode uses double width */ - if (use_bigtile) x += j; - - ia = attr_top + i; - ic = char_left + j; - - /* Ignore illegal characters */ - if (ia > 0x7f || ic > 0xff || ic < ' ' || - (!use_graphics && ic > 0x7f)) - continue; - - a = ia; - c = ic; - - /* Force correct code for both ASCII character and tile */ - if (c & 0x80) a |= 0x80; - - /* Display symbol */ - Term_queue_bigchar(x, y, a, c, 0, 0); - } - } -} - - -/* - * Place the cursor at the collect position for visual mode - */ -static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left) -{ - int i = (a & 0x7f) - attr_top; - int j = c - char_left; - - TERM_LEN x = col + j; - TERM_LEN y = row + i; - - /* Bigtile mode uses double width */ - if (use_bigtile) x += j; - - /* Place the cursor */ - Term_gotoxy(x, y); -} - - -/* - * Clipboard variables for copy&paste in visual mode - */ -static TERM_COLOR attr_idx = 0; -static SYMBOL_CODE char_idx = 0; - -/* Hack -- for feature lighting */ -static TERM_COLOR attr_idx_feat[F_LIT_MAX]; -static SYMBOL_CODE char_idx_feat[F_LIT_MAX]; - -/* - * Do visual mode command -- Change symbols - */ -static bool visual_mode_command(char ch, bool *visual_list_ptr, - int height, int width, - TERM_COLOR *attr_top_ptr, byte *char_left_ptr, - TERM_COLOR *cur_attr_ptr, SYMBOL_CODE *cur_char_ptr, bool *need_redraw) -{ - static TERM_COLOR attr_old = 0; - static SYMBOL_CODE char_old = 0; - - switch (ch) - { - case ESCAPE: - if (*visual_list_ptr) - { - /* Cancel change */ - *cur_attr_ptr = attr_old; - *cur_char_ptr = char_old; - *visual_list_ptr = FALSE; - - return TRUE; - } - break; - - case '\n': - case '\r': - if (*visual_list_ptr) - { - /* Accept change */ - *visual_list_ptr = FALSE; - *need_redraw = TRUE; - - return TRUE; - } - break; - - case 'V': - case 'v': - if (!*visual_list_ptr) - { - *visual_list_ptr = TRUE; - - *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5); - *char_left_ptr = MAX(0, *cur_char_ptr - 10); - - attr_old = *cur_attr_ptr; - char_old = *cur_char_ptr; - - return TRUE; - } - break; - - case 'C': - case 'c': - { - int i; - - /* Set the visual */ - attr_idx = *cur_attr_ptr; - char_idx = *cur_char_ptr; - - /* Hack -- for feature lighting */ - for (i = 0; i < F_LIT_MAX; i++) - { - attr_idx_feat[i] = 0; - char_idx_feat[i] = 0; - } - } - return TRUE; - - case 'P': - case 'p': - if (attr_idx || (!(char_idx & 0x80) && char_idx)) /* Allow TERM_DARK text */ - { - /* Set the char */ - *cur_attr_ptr = attr_idx; - *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5); - if (!*visual_list_ptr) *need_redraw = TRUE; - } - - if (char_idx) - { - /* Set the char */ - *cur_char_ptr = char_idx; - *char_left_ptr = MAX(0, *cur_char_ptr - 10); - if (!*visual_list_ptr) *need_redraw = TRUE; - } - - return TRUE; - - default: - if (*visual_list_ptr) - { - int eff_width; - int d = get_keymap_dir(ch); - TERM_COLOR a = (*cur_attr_ptr & 0x7f); - SYMBOL_CODE c = *cur_char_ptr; - - if (use_bigtile) eff_width = width / 2; - else eff_width = width; - - /* Restrict direction */ - if ((a == 0) && (ddy[d] < 0)) d = 0; - if ((c == 0) && (ddx[d] < 0)) d = 0; - if ((a == 0x7f) && (ddy[d] > 0)) d = 0; - if ((c == 0xff) && (ddx[d] > 0)) d = 0; - - a += (TERM_COLOR)ddy[d]; - c += (SYMBOL_CODE)ddx[d]; - - /* Force correct code for both ASCII character and tile */ - if (c & 0x80) a |= 0x80; - - /* Set the visual */ - *cur_attr_ptr = a; - *cur_char_ptr = c; - - - /* Move the frame */ - if ((ddx[d] < 0) && *char_left_ptr > MAX(0, (int)c - 10)) (*char_left_ptr)--; - if ((ddx[d] > 0) && *char_left_ptr + eff_width < MIN(0xff, (int)c + 10)) (*char_left_ptr)++; - if ((ddy[d] < 0) && *attr_top_ptr > MAX(0, (int)(a & 0x7f) - 4)) (*attr_top_ptr)--; - if ((ddy[d] > 0) && *attr_top_ptr + height < MIN(0x7f, (a & 0x7f) + 4)) (*attr_top_ptr)++; - return TRUE; - } - break; - } - - /* Visual mode command is not used */ - return FALSE; -} - - -/* - * Display the monsters in a group. - */ -static void display_monster_list(int col, int row, int per_page, s16b mon_idx[], - int mon_cur, int mon_top, bool visual_only) -{ - int i; - - /* Display lines until done */ - for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++) - { - TERM_COLOR attr; - - /* Get the race index */ - MONRACE_IDX r_idx = mon_idx[mon_top + i] ; - - /* Access the race */ - monster_race *r_ptr = &r_info[r_idx]; - - /* Choose a color */ - attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE); - - /* Display the name */ - c_prt(attr, (r_name + r_ptr->name), row + i, col); - - /* Hack -- visual_list mode */ - if (per_page == 1) - { - c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (p_ptr->wizard || visual_only) ? 56 : 61); - } - if (p_ptr->wizard || visual_only) - { - c_prt(attr, format("%d", r_idx), row + i, 62); - } - - /* Erase chars before overwritten by the race letter */ - Term_erase(69, row + i, 255); - - /* Display symbol */ - Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0); - - if (!visual_only) - { - /* Display kills */ - if (!(r_ptr->flags1 & RF1_UNIQUE)) - put_str(format("%5d", r_ptr->r_pkills), row + i, 73); - else - c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE), - (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74); - } - } - - /* Clear remaining lines */ - for (; i < per_page; i++) - { - Term_erase(col, row + i, 255); - } -} - - -/* - * Display known monsters. - */ -static void do_cmd_knowledge_monsters(bool *need_redraw, bool visual_only, IDX direct_r_idx) -{ - IDX i; - int len, max; - IDX grp_cur, grp_top, old_grp_cur; - IDX mon_cur, mon_top; - IDX grp_cnt, grp_idx[100]; - IDX mon_cnt; - IDX *mon_idx; - - int column = 0; - bool flag; - bool redraw; - - bool visual_list = FALSE; - TERM_COLOR attr_top = 0; - byte char_left = 0; - - int browser_rows; - TERM_LEN wid, hgt; - - BIT_FLAGS8 mode; - - Term_get_size(&wid, &hgt); - - browser_rows = hgt - 8; - - /* Allocate the "mon_idx" array */ - C_MAKE(mon_idx, max_r_idx, MONRACE_IDX); - - max = 0; - grp_cnt = 0; - - if (direct_r_idx < 0) - { - mode = visual_only ? 0x03 : 0x01; - - /* Check every group */ - for (i = 0; monster_group_text[i] != NULL; i++) - { - /* Measure the label */ - len = strlen(monster_group_text[i]); - - /* Save the maximum length */ - if (len > max) max = len; - - /* See if any monsters are known */ - if ((monster_group_char[i] == ((char *) -1L)) || collect_monsters(i, mon_idx, mode)) - { - /* Build a list of groups with known monsters */ - grp_idx[grp_cnt++] = i; - } - } - - mon_cnt = 0; - } - else - { - mon_idx[0] = direct_r_idx; - mon_cnt = 1; - - /* Terminate the list */ - mon_idx[1] = -1; - - (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3), - &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw); - } - - /* Terminate the list */ - grp_idx[grp_cnt] = -1; - - old_grp_cur = -1; - grp_cur = grp_top = 0; - mon_cur = mon_top = 0; - - flag = FALSE; - redraw = TRUE; - - mode = visual_only ? 0x02 : 0x00; - - while (!flag) - { - char ch; - monster_race *r_ptr; - - if (redraw) - { - clear_from(0); - prt(format(_("%s - モンスター", "%s - monsters"), !visual_only ? _("知識", "Knowledge") : _("表示", "Visuals")), 2, 0); - if (direct_r_idx < 0) prt(_("グループ", "Group"), 4, 0); - prt(_("名前", "Name"), 4, max + 3); - if (p_ptr->wizard || visual_only) prt("Idx", 4, 62); - prt(_("文字", "Sym"), 4, 67); - if (!visual_only) prt(_("殺害数", "Kills"), 4, 72); - - for (i = 0; i < 78; i++) - { - Term_putch(i, 5, TERM_WHITE, '='); - } - - if (direct_r_idx < 0) - { - for (i = 0; i < browser_rows; i++) - { - Term_putch(max + 1, 6 + i, TERM_WHITE, '|'); - } - } - - redraw = FALSE; - } - - if (direct_r_idx < 0) - { - /* Scroll group list */ - if (grp_cur < grp_top) grp_top = grp_cur; - if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1; - - /* Display a list of monster groups */ - display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top); - - if (old_grp_cur != grp_cur) - { - old_grp_cur = grp_cur; - - /* Get a list of monsters in the current group */ - mon_cnt = collect_monsters(grp_idx[grp_cur], mon_idx, mode); - } - - /* Scroll monster list */ - while (mon_cur < mon_top) - mon_top = MAX(0, mon_top - browser_rows/2); - while (mon_cur >= mon_top + browser_rows) - mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows/2); - } - - if (!visual_list) - { - /* Display a list of monsters in the current group */ - display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only); - } - else - { - mon_top = mon_cur; - - /* Display a monster name */ - display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only); - - /* Display visual list below first monster */ - display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left); - } - - /* Prompt */ - prt(format(_("<方向>%s%s%s, ESC", "%s%s%s, ESC"), - (!visual_list && !visual_only) ? _(", 'r'で思い出を見る", ", 'r' to recall") : "", - visual_list ? _(", ENTERで決定", ", ENTER to accept") : _(", 'v'でシンボル変更", ", 'v' for visuals"), - (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")), - hgt - 1, 0); - - /* Get the current monster */ - r_ptr = &r_info[mon_idx[mon_cur]]; - - if (!visual_only) - { - /* Mega Hack -- track this monster race */ - if (mon_cnt) monster_race_track(mon_idx[mon_cur]); - handle_stuff(); - } - - if (visual_list) - { - place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left); - } - else if (!column) - { - Term_gotoxy(0, 6 + (grp_cur - grp_top)); - } - else - { - Term_gotoxy(max + 3, 6 + (mon_cur - mon_top)); - } - - ch = inkey(); - - /* Do visual mode command if needed */ - if (visual_mode_command(ch, &visual_list, browser_rows-1, wid - (max + 3), &attr_top, &char_left, &r_ptr->x_attr, &r_ptr->x_char, need_redraw)) - { - if (direct_r_idx >= 0) - { - switch (ch) - { - case '\n': - case '\r': - case ESCAPE: - flag = TRUE; - break; - } - } - continue; - } - - switch (ch) - { - case ESCAPE: - { - flag = TRUE; - break; - } - - case 'R': - case 'r': - { - /* Recall on screen */ - if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0)) - { - screen_roff(mon_idx[mon_cur], 0); - - (void)inkey(); - - redraw = TRUE; - } - break; - } - - default: - { - /* Move the cursor */ - browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt); - - break; - } - } - } - - /* Free the "mon_idx" array */ - C_KILL(mon_idx, max_r_idx, MONRACE_IDX); -} - - -/* - * Display the objects in a group. - */ -static void display_object_list(int col, int row, int per_page, IDX object_idx[], - int object_cur, int object_top, bool visual_only) -{ - int i; - - /* Display lines until done */ - for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++) - { - GAME_TEXT o_name[MAX_NLEN]; - TERM_COLOR a; - SYMBOL_CODE c; - object_kind *flavor_k_ptr; - - /* Get the object index */ - KIND_OBJECT_IDX k_idx = object_idx[object_top + i]; - - /* Access the object */ - object_kind *k_ptr = &k_info[k_idx]; - - /* Choose a color */ - TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE); - byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE); - - - if (!visual_only && k_ptr->flavor) - { - /* Appearance of this object is shuffled */ - flavor_k_ptr = &k_info[k_ptr->flavor]; - } - else - { - /* Appearance of this object is very normal */ - flavor_k_ptr = k_ptr; - } - - - - attr = ((i + object_top == object_cur) ? cursor : attr); - - if (!k_ptr->flavor || (!visual_only && k_ptr->aware)) - { - /* Tidy name */ - strip_name(o_name, k_idx); - } - else - { - /* Flavor name */ - strcpy(o_name, k_name + flavor_k_ptr->flavor_name); - } - - /* Display the name */ - c_prt(attr, o_name, row + i, col); - - /* Hack -- visual_list mode */ - if (per_page == 1) - { - c_prt(attr, format("%02x/%02x", flavor_k_ptr->x_attr, flavor_k_ptr->x_char), row + i, (p_ptr->wizard || visual_only) ? 64 : 68); - } - if (p_ptr->wizard || visual_only) - { - c_prt(attr, format("%d", k_idx), row + i, 70); - } - - a = flavor_k_ptr->x_attr; - c = flavor_k_ptr->x_char; - - /* Display symbol */ - Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0); - } - - /* Clear remaining lines */ - for (; i < per_page; i++) - { - Term_erase(col, row + i, 255); - } -} - -/* - * Describe fake object - */ -static void desc_obj_fake(KIND_OBJECT_IDX k_idx) -{ - object_type *o_ptr; - object_type object_type_body; - o_ptr = &object_type_body; - object_wipe(o_ptr); - - /* Create the artifact */ - object_prep(o_ptr, k_idx); - - /* It's fully know */ - o_ptr->ident |= IDENT_KNOWN; - - /* Track the object */ - /* object_actual_track(o_ptr); */ - - /* Hack - mark as fake */ - /* term_obj_real = FALSE; */ - handle_stuff(); - - if (!screen_object(o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL)) - { - msg_print(_("特に変わったところはないようだ。", "You see nothing special.")); - msg_print(NULL); - } -} - - - -/* - * Display known objects - */ -static void do_cmd_knowledge_objects(bool *need_redraw, bool visual_only, IDX direct_k_idx) -{ - IDX i; - int len, max; - IDX grp_cur, grp_top, old_grp_cur; - IDX object_old, object_cur, object_top; - int grp_cnt; - IDX grp_idx[100]; - int object_cnt; - OBJECT_IDX *object_idx; - - int column = 0; - bool flag; - bool redraw; - - bool visual_list = FALSE; - TERM_COLOR attr_top = 0; - byte char_left = 0; - - int browser_rows; - TERM_LEN wid, hgt; - - byte mode; - - Term_get_size(&wid, &hgt); - - browser_rows = hgt - 8; - - /* Allocate the "object_idx" array */ - C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX); - - max = 0; - grp_cnt = 0; - - if (direct_k_idx < 0) - { - mode = visual_only ? 0x03 : 0x01; - - /* Check every group */ - for (i = 0; object_group_text[i] != NULL; i++) - { - /* Measure the label */ - len = strlen(object_group_text[i]); - - /* Save the maximum length */ - if (len > max) max = len; - - /* See if any monsters are known */ - if (collect_objects(i, object_idx, mode)) - { - /* Build a list of groups with known monsters */ - grp_idx[grp_cnt++] = i; - } - } - - object_old = -1; - object_cnt = 0; - } - else - { - object_kind *k_ptr = &k_info[direct_k_idx]; - object_kind *flavor_k_ptr; - - if (!visual_only && k_ptr->flavor) - { - /* Appearance of this object is shuffled */ - flavor_k_ptr = &k_info[k_ptr->flavor]; - } - else - { - /* Appearance of this object is very normal */ - flavor_k_ptr = k_ptr; - } - - object_idx[0] = direct_k_idx; - object_old = direct_k_idx; - object_cnt = 1; - - /* Terminate the list */ - object_idx[1] = -1; - - (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3), - &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw); - } - - /* Terminate the list */ - grp_idx[grp_cnt] = -1; - - old_grp_cur = -1; - grp_cur = grp_top = 0; - object_cur = object_top = 0; - - flag = FALSE; - redraw = TRUE; - - mode = visual_only ? 0x02 : 0x00; - - while (!flag) - { - char ch; - object_kind *k_ptr, *flavor_k_ptr; - - if (redraw) - { - clear_from(0); - -#ifdef JP - prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0); - if (direct_k_idx < 0) prt("グループ", 4, 0); - prt("名前", 4, max + 3); - if (p_ptr->wizard || visual_only) prt("Idx", 4, 70); - prt("文字", 4, 74); -#else - prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0); - if (direct_k_idx < 0) prt("Group", 4, 0); - prt("Name", 4, max + 3); - if (p_ptr->wizard || visual_only) prt("Idx", 4, 70); - prt("Sym", 4, 75); -#endif - - for (i = 0; i < 78; i++) - { - Term_putch(i, 5, TERM_WHITE, '='); - } - - if (direct_k_idx < 0) - { - for (i = 0; i < browser_rows; i++) - { - Term_putch(max + 1, 6 + i, TERM_WHITE, '|'); - } - } - - redraw = FALSE; - } - - if (direct_k_idx < 0) - { - /* Scroll group list */ - if (grp_cur < grp_top) grp_top = grp_cur; - if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1; - - /* Display a list of object groups */ - display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top); - - if (old_grp_cur != grp_cur) - { - old_grp_cur = grp_cur; - - /* Get a list of objects in the current group */ - object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode); - } - - /* Scroll object list */ - while (object_cur < object_top) - object_top = MAX(0, object_top - browser_rows/2); - while (object_cur >= object_top + browser_rows) - object_top = MIN(object_cnt - browser_rows, object_top + browser_rows/2); - } - - if (!visual_list) - { - /* Display a list of objects in the current group */ - display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only); - } - else - { - object_top = object_cur; - - /* Display a list of objects in the current group */ - display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only); - - /* Display visual list below first object */ - display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left); - } - - /* Get the current object */ - k_ptr = &k_info[object_idx[object_cur]]; - - if (!visual_only && k_ptr->flavor) - { - /* Appearance of this object is shuffled */ - flavor_k_ptr = &k_info[k_ptr->flavor]; - } - else - { - /* Appearance of this object is very normal */ - flavor_k_ptr = k_ptr; - } - - /* Prompt */ -#ifdef JP - prt(format("<方向>%s%s%s, ESC", - (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "", - visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更", - (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"), - hgt - 1, 0); -#else - prt(format("%s%s%s, ESC", - (!visual_list && !visual_only) ? ", 'r' to recall" : "", - visual_list ? ", ENTER to accept" : ", 'v' for visuals", - (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"), - hgt - 1, 0); -#endif - - if (!visual_only) - { - /* Mega Hack -- track this object */ - if (object_cnt) object_kind_track(object_idx[object_cur]); - - /* The "current" object changed */ - if (object_old != object_idx[object_cur]) - { - handle_stuff(); - - /* Remember the "current" object */ - object_old = object_idx[object_cur]; - } - } - - if (visual_list) - { - place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left); - } - else if (!column) - { - Term_gotoxy(0, 6 + (grp_cur - grp_top)); - } - else - { - Term_gotoxy(max + 3, 6 + (object_cur - object_top)); - } - - ch = inkey(); - - /* Do visual mode command if needed */ - if (visual_mode_command(ch, &visual_list, browser_rows-1, wid - (max + 3), &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw)) - { - if (direct_k_idx >= 0) - { - switch (ch) - { - case '\n': - case '\r': - case ESCAPE: - flag = TRUE; - break; - } - } - continue; - } - - switch (ch) - { - case ESCAPE: - { - flag = TRUE; - break; - } - - case 'R': - case 'r': - { - /* Recall on screen */ - if (!visual_list && !visual_only && (grp_cnt > 0)) - { - desc_obj_fake(object_idx[object_cur]); - redraw = TRUE; - } - break; - } - - default: - { - /* Move the cursor */ - browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt); - break; - } - } - } - - /* Free the "object_idx" array */ - C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX); -} - - -/* - * Display the features in a group. - */ -static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx, - FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level) -{ - int lit_col[F_LIT_MAX], i, j; - int f_idx_col = use_bigtile ? 62 : 64; - - /* Correct columns 1 and 4 */ - lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71; - for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++) - lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0); - - /* Display lines until done */ - for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++) - { - TERM_COLOR attr; - FEAT_IDX f_idx = feat_idx[feat_top + i]; - feature_type *f_ptr = &f_info[f_idx]; - int row_i = row + i; - - /* Choose a color */ - attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE); - - /* Display the name */ - c_prt(attr, f_name + f_ptr->name, row_i, col); - - /* Hack -- visual_list mode */ - if (per_page == 1) - { - /* Display lighting level */ - c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name)); - - c_prt(attr, format("%02x/%02x", f_ptr->x_attr[lighting_level], f_ptr->x_char[lighting_level]), row_i, f_idx_col - ((p_ptr->wizard || visual_only) ? 6 : 2)); - } - if (p_ptr->wizard || visual_only) - { - c_prt(attr, format("%d", f_idx), row_i, f_idx_col); - } - - /* Display symbol */ - Term_queue_bigchar(lit_col[F_LIT_STANDARD], row_i, f_ptr->x_attr[F_LIT_STANDARD], f_ptr->x_char[F_LIT_STANDARD], 0, 0); - - Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '('); - for (j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++) - { - Term_putch(lit_col[j], row_i, TERM_SLATE, '/'); - } - Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')'); - - /* Mega-hack -- Use non-standard colour */ - for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++) - { - Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0); - } - } - - /* Clear remaining lines */ - for (; i < per_page; i++) - { - Term_erase(col, row + i, 255); - } -} - - -/* - * Interact with feature visuals. - */ -static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level) -{ - FEAT_IDX i; - int len, max; - FEAT_IDX grp_cur, grp_top, old_grp_cur; - FEAT_IDX feat_cur, feat_top; - int grp_cnt; - FEAT_IDX grp_idx[100]; - int feat_cnt; - FEAT_IDX *feat_idx; - - TERM_LEN column = 0; - bool flag; - bool redraw; - - bool visual_list = FALSE; - TERM_COLOR attr_top = 0; - byte char_left = 0; - - TERM_LEN browser_rows; - TERM_LEN wid, hgt; - - TERM_COLOR attr_old[F_LIT_MAX]; - SYMBOL_CODE char_old[F_LIT_MAX]; - TERM_COLOR *cur_attr_ptr; - SYMBOL_CODE *cur_char_ptr; - - (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR); - (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE); - - Term_get_size(&wid, &hgt); - - browser_rows = hgt - 8; - - /* Allocate the "feat_idx" array */ - C_MAKE(feat_idx, max_f_idx, FEAT_IDX); - - max = 0; - grp_cnt = 0; - - if (direct_f_idx < 0) - { - /* Check every group */ - for (i = 0; feature_group_text[i] != NULL; i++) - { - /* Measure the label */ - len = strlen(feature_group_text[i]); - - /* Save the maximum length */ - if (len > max) max = len; - - /* See if any features are known */ - if (collect_features(i, feat_idx, 0x01)) - { - /* Build a list of groups with known features */ - grp_idx[grp_cnt++] = i; - } - } - - feat_cnt = 0; - } - else - { - feature_type *f_ptr = &f_info[direct_f_idx]; - - feat_idx[0] = direct_f_idx; - feat_cnt = 1; - - /* Terminate the list */ - feat_idx[1] = -1; - - (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3), - &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw); - - for (i = 0; i < F_LIT_MAX; i++) - { - attr_old[i] = f_ptr->x_attr[i]; - char_old[i] = f_ptr->x_char[i]; - } - } - - /* Terminate the list */ - grp_idx[grp_cnt] = -1; - - old_grp_cur = -1; - grp_cur = grp_top = 0; - feat_cur = feat_top = 0; - - flag = FALSE; - redraw = TRUE; - - while (!flag) - { - char ch; - feature_type *f_ptr; - - if (redraw) - { - clear_from(0); - - prt(_("表示 - 地形", "Visuals - features"), 2, 0); - if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0); - prt(_("名前", "Name"), 4, max + 3); - if (use_bigtile) - { - if (p_ptr->wizard || visual_only) prt("Idx", 4, 62); - prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66); - } - else - { - if (p_ptr->wizard || visual_only) prt("Idx", 4, 64); - prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68); - } - - for (i = 0; i < 78; i++) - { - Term_putch(i, 5, TERM_WHITE, '='); - } - - if (direct_f_idx < 0) - { - for (i = 0; i < browser_rows; i++) - { - Term_putch(max + 1, 6 + i, TERM_WHITE, '|'); - } - } - - redraw = FALSE; - } - - if (direct_f_idx < 0) - { - /* Scroll group list */ - if (grp_cur < grp_top) grp_top = grp_cur; - if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1; - - /* Display a list of feature groups */ - display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top); - - if (old_grp_cur != grp_cur) - { - old_grp_cur = grp_cur; - - /* Get a list of features in the current group */ - feat_cnt = collect_features(grp_idx[grp_cur], feat_idx, 0x00); - } - - /* Scroll feature list */ - while (feat_cur < feat_top) - feat_top = MAX(0, feat_top - browser_rows/2); - while (feat_cur >= feat_top + browser_rows) - feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows/2); - } - - if (!visual_list) - { - /* Display a list of features in the current group */ - display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD); - } - else - { - feat_top = feat_cur; - - /* Display a list of features in the current group */ - display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level); - - /* Display visual list below first object */ - display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left); - } - - /* Prompt */ - prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "%s, 'd' for default lighting%s, ESC"), - visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"), - (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")), - hgt - 1, 0); - - /* Get the current feature */ - f_ptr = &f_info[feat_idx[feat_cur]]; - cur_attr_ptr = &f_ptr->x_attr[*lighting_level]; - cur_char_ptr = &f_ptr->x_char[*lighting_level]; - - if (visual_list) - { - place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left); - } - else if (!column) - { - Term_gotoxy(0, 6 + (grp_cur - grp_top)); - } - else - { - Term_gotoxy(max + 3, 6 + (feat_cur - feat_top)); - } - - ch = inkey(); - - if (visual_list && ((ch == 'A') || (ch == 'a'))) - { - int prev_lighting_level = *lighting_level; - - if (ch == 'A') - { - if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1; - else (*lighting_level)--; - } - else - { - if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0; - else (*lighting_level)++; - } - - if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level]) - attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5); - - if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level]) - char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10); - - continue; - } - - else if ((ch == 'D') || (ch == 'd')) - { - TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level]; - byte prev_x_char = f_ptr->x_char[*lighting_level]; - - apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char); - - if (visual_list) - { - if (prev_x_attr != f_ptr->x_attr[*lighting_level]) - attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5); - - if (prev_x_char != f_ptr->x_char[*lighting_level]) - char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10); - } - else *need_redraw = TRUE; - - continue; - } - - /* Do visual mode command if needed */ - else if (visual_mode_command(ch, &visual_list, browser_rows-1, wid - (max + 3), &attr_top, &char_left, cur_attr_ptr, cur_char_ptr, need_redraw)) - { - switch (ch) - { - /* Restore previous visual settings */ - case ESCAPE: - for (i = 0; i < F_LIT_MAX; i++) - { - f_ptr->x_attr[i] = attr_old[i]; - f_ptr->x_char[i] = char_old[i]; - } - - /* Fall through */ - - case '\n': - case '\r': - if (direct_f_idx >= 0) flag = TRUE; - else *lighting_level = F_LIT_STANDARD; - break; - - /* Preserve current visual settings */ - case 'V': - case 'v': - for (i = 0; i < F_LIT_MAX; i++) - { - attr_old[i] = f_ptr->x_attr[i]; - char_old[i] = f_ptr->x_char[i]; - } - *lighting_level = F_LIT_STANDARD; - break; - - case 'C': - case 'c': - if (!visual_list) - { - for (i = 0; i < F_LIT_MAX; i++) - { - attr_idx_feat[i] = f_ptr->x_attr[i]; - char_idx_feat[i] = f_ptr->x_char[i]; - } - } - break; - - case 'P': - case 'p': - if (!visual_list) - { - /* Allow TERM_DARK text */ - for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++) - { - if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i]; - if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i]; - } - } - break; - } - continue; - } - - switch (ch) - { - case ESCAPE: - { - flag = TRUE; - break; - } - - default: - { - /* Move the cursor */ - browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt); - break; - } - } - } - - /* Free the "feat_idx" array */ - C_KILL(feat_idx, max_f_idx, FEAT_IDX); -} - - -/* - * List wanted monsters - */ -static void do_cmd_knowledge_kubi(void) -{ - int i; - FILE *fff; - - GAME_TEXT file_name[1024]; - - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - if (!fff) { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - if (fff) - { - bool listed = FALSE; - - fprintf(fff, _("今日のターゲット : %s\n", "Today target : %s\n"), - (p_ptr->today_mon ? r_name + r_info[p_ptr->today_mon].name : _("不明", "unknown"))); - fprintf(fff, "\n"); - fprintf(fff, _("賞金首リスト\n", "List of wanted monsters\n")); - fprintf(fff, "----------------------------------------------\n"); - - for (i = 0; i < MAX_KUBI; i++) - { - if (current_world_ptr->bounty_r_idx[i] <= 10000) - { - fprintf(fff,"%s\n", r_name + r_info[current_world_ptr->bounty_r_idx[i]].name); - - listed = TRUE; - } - } - - if (!listed) - { - fprintf(fff,"\n%s\n", _("賞金首はもう残っていません。", "There is no more wanted monster.")); - } - } - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0); - fd_kill(file_name); -} - -/* - * List virtues & status - */ -static void do_cmd_knowledge_virtues(void) -{ - FILE *fff; - GAME_TEXT file_name[1024]; - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - if (!fff) { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - if (fff) - { - fprintf(fff, _("現在の属性 : %s\n\n", "Your alighnment : %s\n\n"), your_alignment()); - dump_virtues(fff); - } - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("八つの徳", "Virtues"), 0, 0); - fd_kill(file_name); -} - -/* - * Dungeon - */ -static void do_cmd_knowledge_dungeon(void) -{ - FILE *fff; - - GAME_TEXT file_name[1024]; - int i; - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - if (!fff) { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - if (fff) - { - for (i = 1; i < max_d_idx; i++) - { - bool seiha = FALSE; - - if (!d_info[i].maxdepth) continue; - if (!max_dlv[i]) continue; - if (d_info[i].final_guardian) - { - if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE; - } - else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE; - - fprintf(fff, _("%c%-12s : %3d 階\n", "%c%-16s : level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]); - } - } - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0); - fd_kill(file_name); -} - -/* -* List virtues & status -* -*/ -static void do_cmd_knowledge_stat(void) -{ - FILE *fff; - - GAME_TEXT file_name[1024]; - int percent, v_nr; - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - if (!fff) { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - if (fff) - { - percent = (int)(((long)p_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) / - (2 * p_ptr->hitdie + - ((PY_MAX_LEVEL - 1+3) * (p_ptr->hitdie + 1)))); - - if (p_ptr->knowledge & KNOW_HPRATE) - fprintf(fff, _("現在の体力ランク : %d/100\n\n", "Your current Life Rating is %d/100.\n\n"), percent); - else fprintf(fff, _("現在の体力ランク : ???\n\n", "Your current Life Rating is ???.\n\n")); - - fprintf(fff, _("能力の最大値\n\n", "Limits of maximum stats\n\n")); - for (v_nr = 0; v_nr < A_MAX; v_nr++) - { - if ((p_ptr->knowledge & KNOW_STAT) || p_ptr->stat_max[v_nr] == p_ptr->stat_max_max[v_nr]) fprintf(fff, "%s 18/%d\n", stat_names[v_nr], p_ptr->stat_max_max[v_nr]-18); - else fprintf(fff, "%s ???\n", stat_names[v_nr]); - } - } - - dump_yourself(fff); - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0); - fd_kill(file_name); -} - - -/* - * Print all active quests - */ -static void do_cmd_knowledge_quests_current(FILE *fff) -{ - char tmp_str[120]; - char rand_tmp_str[120] = "\0"; - GAME_TEXT name[MAX_NLEN]; - monster_race *r_ptr; - QUEST_IDX i; - int rand_level = 100; - int total = 0; - - fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n")); - - for (i = 1; i < max_q_idx; i++) - { - if ((quest[i].status == QUEST_STATUS_TAKEN) || - ((quest[i].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[i].type == QUEST_TYPE_TOWER)) || - (quest[i].status == QUEST_STATUS_COMPLETED)) - { - /* Set the quest number temporary */ - QUEST_IDX old_quest = p_ptr->inside_quest; - int j; - - /* Clear the text */ - for (j = 0; j < 10; j++) quest_text[j][0] = '\0'; - quest_text_line = 0; - - p_ptr->inside_quest = i; - - /* Get the quest text */ - init_flags = INIT_SHOW_TEXT; - - process_dungeon_file("q_info.txt", 0, 0, 0, 0); - - /* Reset the old quest number */ - p_ptr->inside_quest = old_quest; - - /* No info from "silent" quests */ - if (quest[i].flags & QUEST_FLAG_SILENT) continue; - - total++; - - if (quest[i].type != QUEST_TYPE_RANDOM) - { - char note[80] = "\0"; - - if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED) - { - switch (quest[i].type) - { - case QUEST_TYPE_KILL_LEVEL: - case QUEST_TYPE_KILL_ANY_LEVEL: - r_ptr = &r_info[quest[i].r_idx]; - strcpy(name, r_name + r_ptr->name); - if (quest[i].max_num > 1) - { -#ifdef JP - sprintf(note," - %d 体の%sを倒す。(あと %d 体)", - (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num)); -#else - plural_aux(name); - sprintf(note," - kill %d %s, have killed %d.", - (int)quest[i].max_num, name, (int)quest[i].cur_num); -#endif - } - else - sprintf(note,_(" - %sを倒す。", " - kill %s."),name); - break; - - case QUEST_TYPE_FIND_ARTIFACT: - if (quest[i].k_idx) - { - artifact_type *a_ptr = &a_info[quest[i].k_idx]; - object_type forge; - object_type *q_ptr = &forge; - KIND_OBJECT_IDX k_idx = lookup_kind(a_ptr->tval, a_ptr->sval); - object_prep(q_ptr, k_idx); - q_ptr->name1 = quest[i].k_idx; - q_ptr->ident = IDENT_STORE; - object_desc(name, q_ptr, OD_NAME_ONLY); - } - sprintf(note,_("\n - %sを見つけ出す。", "\n - Find out %s."), name); - break; - case QUEST_TYPE_FIND_EXIT: - sprintf(note,_(" - 出口に到達する。", " - Reach to Exit.")); - break; - - case QUEST_TYPE_KILL_NUMBER: -#ifdef JP - sprintf(note," - %d 体のモンスターを倒す。(あと %d 体)", - (int)quest[i].max_num, (int)(quest[i].max_num - quest[i].cur_num)); -#else - sprintf(note," - Kill %d monsters, have killed %d.", - (int)quest[i].max_num, (int)quest[i].cur_num); -#endif - break; - - case QUEST_TYPE_KILL_ALL: - case QUEST_TYPE_TOWER: - sprintf(note,_(" - 全てのモンスターを倒す。", " - Kill all monsters.")); - break; - } - } - - /* Print the quest info */ - sprintf(tmp_str, _(" %s (危険度:%d階相当)%s\n", " %s (Danger level: %d)%s\n"), - quest[i].name, (int)quest[i].level, note); - - fputs(tmp_str, fff); - - if (quest[i].status == QUEST_STATUS_COMPLETED) - { - sprintf(tmp_str, _(" クエスト達成 - まだ報酬を受けとってない。\n", " Quest Completed - Unrewarded\n")); - fputs(tmp_str, fff); - } - else - { - j = 0; - - while (quest_text[j][0] && j < 10) - { - fprintf(fff, " %s\n", quest_text[j]); - j++; - } - } - } - else if (quest[i].level < rand_level) /* QUEST_TYPE_RANDOM */ - { - /* New random */ - rand_level = quest[i].level; - - if (max_dlv[DUNGEON_ANGBAND] >= rand_level) - { - /* Print the quest info */ - r_ptr = &r_info[quest[i].r_idx]; - strcpy(name, r_name + r_ptr->name); - - if (quest[i].max_num > 1) - { -#ifdef JP - sprintf(rand_tmp_str," %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n", - quest[i].name, (int)quest[i].level, - (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num)); -#else - plural_aux(name); - - sprintf(rand_tmp_str," %s (Dungeon level: %d)\n Kill %d %s, have killed %d.\n", - quest[i].name, (int)quest[i].level, - (int)quest[i].max_num, name, (int)quest[i].cur_num); -#endif - } - else - { - sprintf(rand_tmp_str,_(" %s (%d 階) - %sを倒す。\n", " %s (Dungeon level: %d)\n Kill %s.\n"), - quest[i].name, (int)quest[i].level, name); - } - } - } - } - } - - /* Print the current random quest */ - if (rand_tmp_str[0]) fputs(rand_tmp_str, fff); - - if (!total) fprintf(fff, _(" なし\n", " Nothing.\n")); -} - - -static bool do_cmd_knowledge_quests_aux(FILE *fff, IDX q_idx) -{ - char tmp_str[120]; - char playtime_str[16]; - quest_type* const q_ptr = &quest[q_idx]; - - if (is_fixed_quest_idx(q_idx)) - { - /* Set the quest number temporary */ - IDX old_quest = p_ptr->inside_quest; - - p_ptr->inside_quest = q_idx; - - /* Get the quest */ - init_flags = INIT_NAME_ONLY; - - process_dungeon_file("q_info.txt", 0, 0, 0, 0); - - /* Reset the old quest number */ - p_ptr->inside_quest = old_quest; - - /* No info from "silent" quests */ - if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE; - } - - strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d", - q_ptr->comptime/(60*60), (q_ptr->comptime/60)%60, q_ptr->comptime%60); - - if (!is_fixed_quest_idx(q_idx) && q_ptr->r_idx) - { - /* Print the quest info */ - if (q_ptr->complev == 0) - { - sprintf(tmp_str, - _(" %-35s (%3d階) - 不戦勝 - %s\n", - " %-35s (Dungeon level: %3d) - Unearned - %s\n") , - r_name+r_info[q_ptr->r_idx].name, - (int)q_ptr->level, playtime_str); - } - else - { - sprintf(tmp_str, - _(" %-35s (%3d階) - レベル%2d - %s\n", - " %-35s (Dungeon level: %3d) - level %2d - %s\n") , - r_name+r_info[q_ptr->r_idx].name, - (int)q_ptr->level, - q_ptr->complev, - playtime_str); - } - } - else - { - /* Print the quest info */ - sprintf(tmp_str, - _(" %-35s (危険度:%3d階相当) - レベル%2d - %s\n", - " %-35s (Danger level: %3d) - level %2d - %s\n") , - q_ptr->name, (int)q_ptr->level, q_ptr->complev, playtime_str); - } - - fputs(tmp_str, fff); - - return TRUE; -} - -/* - * Print all finished quests - */ -void do_cmd_knowledge_quests_completed(FILE *fff, QUEST_IDX quest_num[]) -{ - QUEST_IDX i; - QUEST_IDX total = 0; - - fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n")); - for (i = 1; i < max_q_idx; i++) - { - QUEST_IDX q_idx = quest_num[i]; - quest_type* const q_ptr = &quest[q_idx]; - - if (q_ptr->status == QUEST_STATUS_FINISHED && do_cmd_knowledge_quests_aux(fff, q_idx)) - { - ++total; - } - } - if (!total) fprintf(fff, _(" なし\n", " Nothing.\n")); -} - - -/* - * Print all failed quests - */ -void do_cmd_knowledge_quests_failed(FILE *fff, QUEST_IDX quest_num[]) -{ - QUEST_IDX i; - QUEST_IDX total = 0; - - fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n")); - for (i = 1; i < max_q_idx; i++) - { - QUEST_IDX q_idx = quest_num[i]; - quest_type* const q_ptr = &quest[q_idx]; - - if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) && - do_cmd_knowledge_quests_aux(fff, q_idx)) - { - ++total; - } - } - if (!total) fprintf(fff, _(" なし\n", " Nothing.\n")); -} - - -/* - * Print all random quests - */ -static void do_cmd_knowledge_quests_wiz_random(FILE *fff) -{ - GAME_TEXT tmp_str[120]; - QUEST_IDX i; - QUEST_IDX total = 0; - - fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n")); - for (i = 1; i < max_q_idx; i++) - { - /* No info from "silent" quests */ - if (quest[i].flags & QUEST_FLAG_SILENT) continue; - - if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN)) - { - total++; - - /* Print the quest info */ - sprintf(tmp_str, _(" %s (%d階, %s)\n", " %s (%d, %s)\n"), - quest[i].name, (int)quest[i].level, r_name+r_info[quest[i].r_idx].name); - fputs(tmp_str, fff); - } - } - if (!total) fprintf(fff, _(" なし\n", " Nothing.\n")); -} - -/* - * Print quest status of all active quests - */ -static void do_cmd_knowledge_quests(void) -{ - FILE *fff; - GAME_TEXT file_name[1024]; - IDX *quest_num; - int dummy; - IDX i; - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - if (!fff) - { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - /* Allocate Memory */ - C_MAKE(quest_num, max_q_idx, QUEST_IDX); - - /* Sort by compete level */ - for (i = 1; i < max_q_idx; i++) quest_num[i] = i; - ang_sort(quest_num, &dummy, max_q_idx, ang_sort_comp_quest_num, ang_sort_swap_quest_num); - - /* Dump Quest Information */ - do_cmd_knowledge_quests_current(fff); - fputc('\n', fff); - do_cmd_knowledge_quests_completed(fff, quest_num); - fputc('\n', fff); - do_cmd_knowledge_quests_failed(fff, quest_num); - if (p_ptr->wizard) - { - fputc('\n', fff); - do_cmd_knowledge_quests_wiz_random(fff); - } - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0); - fd_kill(file_name); - - /* Free Memory */ - C_KILL(quest_num, max_q_idx, QUEST_IDX); -} - - -/* - * List my home - */ -static void do_cmd_knowledge_home(void) -{ - FILE *fff; - - int i; - GAME_TEXT file_name[1024]; - store_type *st_ptr; - GAME_TEXT o_name[MAX_NLEN]; - concptr paren = ")"; - - process_dungeon_file("w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x); - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - if (!fff) { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - if (fff) - { - /* Print all homes in the different towns */ - st_ptr = &town_info[1].store[STORE_HOME]; - - /* Home -- if anything there */ - if (st_ptr->stock_num) - { -#ifdef JP - TERM_LEN x = 1; -#endif - /* Header with name of the town */ - fprintf(fff, _(" [ 我が家のアイテム ]\n", " [Home Inventory]\n")); - - /* Dump all available items */ - for (i = 0; i < st_ptr->stock_num; i++) - { -#ifdef JP - if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++); - object_desc(o_name, &st_ptr->stock[i], 0); - if (strlen(o_name) <= 80-3) - { - fprintf(fff, "%c%s %s\n", I2A(i%12), paren, o_name); - } - else - { - int n; - char *t; - for (n = 0, t = o_name; n < 80-3; n++, t++) - if(iskanji(*t)) {t++; n++;} - if (n == 81-3) n = 79-3; /* 最後が漢字半分 */ - - fprintf(fff, "%c%s %.*s\n", I2A(i%12), paren, n, o_name); - fprintf(fff, " %.77s\n", o_name+n); - } -#else - object_desc(o_name, &st_ptr->stock[i], 0); - fprintf(fff, "%c%s %s\n", I2A(i%12), paren, o_name); -#endif - - } - - /* Add an empty line */ - fprintf(fff, "\n\n"); - } - } - my_fclose(fff); - - /* Display the file contents */ - show_file(TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0); - fd_kill(file_name); -} - - -/* - * Check the status of "autopick" - */ -static void do_cmd_knowledge_autopick(void) -{ - int k; - FILE *fff; - GAME_TEXT file_name[1024]; - - /* Open a new file */ - fff = my_fopen_temp(file_name, 1024); - - if (!fff) - { - msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name); - msg_print(NULL); - return; - } - - if (!max_autopick) - { - fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer.")); - } - else - { - fprintf(fff, _(" 自動拾い/破壊には現在 %d行登録されています。\n\n", - " There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick); - } - - for (k = 0; k < max_autopick; k++) - { - concptr tmp; - byte act = autopick_list[k].action; - if (act & DONT_AUTOPICK) - { - tmp = _("放置", "Leave"); - } - else if (act & DO_AUTODESTROY) - { - tmp = _("破壊", "Destroy"); - } - else if (act & DO_AUTOPICK) - { - tmp = _("拾う", "Pickup"); - } - else - { - tmp = _("確認", "Query"); - } - - if (act & DO_DISPLAY) - fprintf(fff, "%11s", format("[%s]", tmp)); - else - fprintf(fff, "%11s", format("(%s)", tmp)); - - tmp = autopick_line_from_entry(&autopick_list[k]); - fprintf(fff, " %s", tmp); - string_free(tmp); - fprintf(fff, "\n"); - } - my_fclose(fff); - /* Display the file contents */ - show_file(TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0); - fd_kill(file_name); -} - - -/* - * Interact with "knowledge" - */ -void do_cmd_knowledge(void) -{ - int i, p = 0; - bool need_redraw = FALSE; - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - screen_save(); - - /* Interact until done */ - while (1) - { - Term_clear(); - - /* Ask for a choice */ - prt(format(_("%d/2 ページ", "page %d/2"), (p+1)), 2, 65); - prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0); - - /* Give some choices */ -#ifdef JP - if (p == 0) - { - prt("(1) 既知の伝説のアイテム の一覧", 6, 5); - prt("(2) 既知のアイテム の一覧", 7, 5); - prt("(3) 既知の生きているユニーク・モンスター の一覧", 8, 5); - prt("(4) 既知のモンスター の一覧", 9, 5); - prt("(5) 倒した敵の数 の一覧", 10, 5); - if (!vanilla_town) prt("(6) 賞金首 の一覧", 11, 5); - prt("(7) 現在のペット の一覧", 12, 5); - prt("(8) 我が家のアイテム の一覧", 13, 5); - prt("(9) *鑑定*済み装備の耐性 の一覧", 14, 5); - prt("(0) 地形の表示文字/タイル の一覧", 15, 5); - } - else - { - prt("(a) 自分に関する情報 の一覧", 6, 5); - prt("(b) 突然変異 の一覧", 7, 5); - prt("(c) 武器の経験値 の一覧", 8, 5); - prt("(d) 魔法の経験値 の一覧", 9, 5); - prt("(e) 技能の経験値 の一覧", 10, 5); - prt("(f) プレイヤーの徳 の一覧", 11, 5); - prt("(g) 入ったダンジョン の一覧", 12, 5); - prt("(h) 実行中のクエスト の一覧", 13, 5); - prt("(i) 現在の自動拾い/破壊設定 の一覧", 14, 5); - } -#else - if (p == 0) - { - prt("(1) Display known artifacts", 6, 5); - prt("(2) Display known objects", 7, 5); - prt("(3) Display remaining uniques", 8, 5); - prt("(4) Display known monster", 9, 5); - prt("(5) Display kill count", 10, 5); - if (!vanilla_town) prt("(6) Display wanted monsters", 11, 5); - prt("(7) Display current pets", 12, 5); - prt("(8) Display home inventory", 13, 5); - prt("(9) Display *identified* equip.", 14, 5); - prt("(0) Display terrain symbols.", 15, 5); - } - else - { - prt("(a) Display about yourself", 6, 5); - prt("(b) Display mutations", 7, 5); - prt("(c) Display weapon proficiency", 8, 5); - prt("(d) Display spell proficiency", 9, 5); - prt("(e) Display misc. proficiency", 10, 5); - prt("(f) Display virtues", 11, 5); - prt("(g) Display dungeons", 12, 5); - prt("(h) Display current quests", 13, 5); - prt("(i) Display auto pick/destroy", 14, 5); - } -#endif - /* Prompt */ - prt(_("-続く-", "-more-"), 17, 8); - prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1); - prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30); - /*prt("-) 前ページ", 21, 60);*/ - prt(_("コマンド:", "Command: "), 20, 0); - i = inkey(); - - if (i == ESCAPE) break; - switch (i) - { - case ' ': /* Page change */ - case '-': - p = 1 - p; - break; - case '1': /* Artifacts */ - do_cmd_knowledge_artifacts(); - break; - case '2': /* Objects */ - do_cmd_knowledge_objects(&need_redraw, FALSE, -1); - break; - case '3': /* Uniques */ - do_cmd_knowledge_uniques(); - break; - case '4': /* Monsters */ - do_cmd_knowledge_monsters(&need_redraw, FALSE, -1); - break; - case '5': /* Kill count */ - do_cmd_knowledge_kill_count(); - break; - case '6': /* wanted */ - if (!vanilla_town) do_cmd_knowledge_kubi(); - break; - case '7': /* Pets */ - do_cmd_knowledge_pets(); - break; - case '8': /* Home */ - do_cmd_knowledge_home(); - break; - case '9': /* Resist list */ - do_cmd_knowledge_inven(); - break; - case '0': /* Feature list */ - { - IDX lighting_level = F_LIT_STANDARD; - do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level); - } - break; - /* Next page */ - case 'a': /* Max stat */ - do_cmd_knowledge_stat(); - break; - case 'b': /* Mutations */ - do_cmd_knowledge_mutations(); - break; - case 'c': /* weapon-exp */ - do_cmd_knowledge_weapon_exp(); - break; - case 'd': /* spell-exp */ - do_cmd_knowledge_spell_exp(); - break; - case 'e': /* skill-exp */ - do_cmd_knowledge_skill_exp(); - break; - case 'f': /* Virtues */ - do_cmd_knowledge_virtues(); - break; - case 'g': /* Dungeon */ - do_cmd_knowledge_dungeon(); - break; - case 'h': /* Quests */ - do_cmd_knowledge_quests(); - break; - case 'i': /* Autopick */ - do_cmd_knowledge_autopick(); - break; - default: /* Unknown option */ - bell(); - } - - msg_erase(); - } - screen_load(); - - if (need_redraw) do_cmd_redraw(); -} - - -/* - * Check on the status of an active quest - */ -void do_cmd_checkquest(void) -{ - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - screen_save(); - - /* Quest info */ - do_cmd_knowledge_quests(); - screen_load(); -} - - -/* - * Display the time and date - */ -void do_cmd_time(void) -{ - int day, hour, min, full, start, end, num; - char desc[1024]; - - char buf[1024]; - char day_buf[10]; - - FILE *fff; - - extract_day_hour_min(&day, &hour, &min); - - full = hour * 100 + min; - - start = 9999; - end = -9999; - - num = 0; - - strcpy(desc, _("変な時刻だ。", "It is a strange time.")); - - if (day < MAX_DAYS) sprintf(day_buf, "%d", day); - else strcpy(day_buf, "*****"); - - msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."), - day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM"); - - /* Find the path */ - if (!randint0(10) || p_ptr->image) - { - path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt")); - } - else - { - path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt")); - } - - /* Open this file */ - fff = my_fopen(buf, "rt"); - - if (!fff) return; - - /* Find this time */ - while (!my_fgets(fff, buf, sizeof(buf))) - { - /* Ignore comments */ - if (!buf[0] || (buf[0] == '#')) continue; - - /* Ignore invalid lines */ - if (buf[1] != ':') continue; - - /* Process 'Start' */ - if (buf[0] == 'S') - { - /* Extract the starting time */ - start = atoi(buf + 2); - - /* Assume valid for an hour */ - end = start + 59; - - /* Next... */ - continue; - } - - /* Process 'End' */ - if (buf[0] == 'E') - { - /* Extract the ending time */ - end = atoi(buf + 2); - - /* Next... */ - continue; - } - - /* Ignore incorrect range */ - if ((start > full) || (full > end)) continue; - - /* Process 'Description' */ - if (buf[0] == 'D') - { - num++; - - /* Apply the randomizer */ - if (!randint0(num)) strcpy(desc, buf + 2); - - /* Next... */ - continue; - } - } - - msg_print(desc); - my_fclose(fff); -} diff --git a/src/combat/attack-accuracy.c b/src/combat/attack-accuracy.c new file mode 100644 index 000000000..684d10153 --- /dev/null +++ b/src/combat/attack-accuracy.c @@ -0,0 +1,157 @@ +#include "combat/attack-accuracy.h" +#include "inventory/inventory-slot-types.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags-resistance.h" +#include "player/attack-defense-types.h" +#include "player/player-status-flags.h" +#include "specific-object/death-scythe.h" +#include "sv-definition/sv-weapon-types.h" +#include "view/display-messages.h" + +/*! + * @brief プレイヤーからモンスターへの打撃命中判定 / + * Determine if the player "hits" a monster (normal combat). + * @param chance 基本命中値 + * @param ac モンスターのAC + * @param visible 目標を視界に捕らえているならばTRUEを指定 + * @return 命中と判定された場合TRUEを返す + * @note Always miss 5%, always hit 5%, otherwise random. + */ +bool test_hit_norm(player_type *attacker_ptr, HIT_RELIABILITY chance, ARMOUR_CLASS ac, bool visible) +{ + if (!visible) + chance = (chance + 1) / 2; + return hit_chance(attacker_ptr, chance, ac) >= randint1(100); +} + +/*! + * @brief モンスターへの命中率の計算 + * @param player_ptr プレーヤーへの参照ポインタ + * @param to_h 命中値 + * @param ac 敵AC + * @return 命中確率 + */ +PERCENTAGE hit_chance(player_type *attacker_ptr, HIT_RELIABILITY reli, ARMOUR_CLASS ac) +{ + PERCENTAGE chance = 5, chance_left = 90; + if (reli <= 0) + return 5; + if (attacker_ptr->pseikaku == PERSONALITY_LAZY) + chance_left = (chance_left * 19 + 9) / 20; + chance += (100 - ((ac * 75) / reli)) * chance_left / 100; + if (chance < 5) + chance = 5; + return chance; +} + +/*! + * @brief モンスター打撃の命中を判定する / + * Determine if a monster attack against the player succeeds. + * @param power 打撃属性毎の基本命中値 + * @param level モンスターのレベル + * @param stun モンスターの朦朧値 + * @return TRUEならば命中判定 + * @details + * Always miss 5% of the time, Always hit 5% of the time. + * Otherwise, match monster power against player armor. + */ +int check_hit_from_monster_to_player(player_type *target_ptr, int power, DEPTH level, int stun) +{ + int k = randint0(100); + if (stun && one_in_(2)) + return FALSE; + if (k < 10) + return (k < 5); + int i = (power + (level * 3)); + + int ac = target_ptr->ac + target_ptr->to_a; + if (target_ptr->special_attack & ATTACK_SUIKEN) + ac += (target_ptr->lev * 2); + + if ((i > 0) && (randint1(i) > ((ac * 3) / 4))) + return TRUE; + return FALSE; +} + +/*! + * @brief モンスターから敵モンスターへの命中判定 + * @param power 打撃属性による基本命中値 + * @param level 攻撃側モンスターのレベル + * @param ac 目標モンスターのAC + * @param stun 攻撃側モンスターが朦朧状態ならTRUEを返す + * @return 命中ならばTRUEを返す + */ +int check_hit_from_monster_to_monster(int power, DEPTH level, ARMOUR_CLASS ac, int stun) +{ + int k = randint0(100); + if (stun && one_in_(2)) + return FALSE; + if (k < 10) + return (k < 5); + int i = (power + (level * 3)); + + if ((i > 0) && (randint1(i) > ((ac * 3) / 4))) + return TRUE; + return FALSE; +} + +/*! + * @brief 攻撃が当たるかどうかを判定する + * @param attacker_ptr プレーヤーへの参照ポインタ + * @param pa_ptr 直接攻撃構造体への参照ポインタ + * @param chance 基本命中値 + * @return なし + */ +static bool decide_attack_hit(player_type *attacker_ptr, player_attack_type *pa_ptr, int chance) +{ + bool success_hit = FALSE; + object_type *o_ptr = &attacker_ptr->inventory_list[INVEN_RARM + pa_ptr->hand]; + monster_race *r_ptr = &r_info[pa_ptr->m_ptr->r_idx]; + if (((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_POISON_NEEDLE)) || (pa_ptr->mode == HISSATSU_KYUSHO)) { + int n = 1; + + if (have_right_hand_weapon(attacker_ptr) && have_left_hand_weapon(attacker_ptr)) + n *= 2; + + if (pa_ptr->mode == HISSATSU_3DAN) + n *= 2; + + success_hit = one_in_(n); + } else if ((attacker_ptr->pclass == CLASS_NINJA) && ((pa_ptr->backstab || pa_ptr->surprise_attack) && !(r_ptr->flagsr & RFR_RES_ALL))) + success_hit = TRUE; + else + success_hit = test_hit_norm(attacker_ptr, chance, r_ptr->ac, pa_ptr->m_ptr->ml); + + if ((pa_ptr->mode == HISSATSU_MAJIN) && one_in_(2)) + success_hit = FALSE; + + return success_hit; +} + +/*! + * @brief 直接攻撃の命中を処理するメインルーチン + * @param attacker_ptr プレーヤーへの参照ポインタ + * @param pa_ptr 直接攻撃構造体への参照ポインタ + * @param chance 基本命中値 + * @return 当たればTRUE、外れればFALSE + */ +bool process_attack_hit(player_type *attacker_ptr, player_attack_type *pa_ptr, int chance) +{ + object_type *o_ptr = &attacker_ptr->inventory_list[INVEN_RARM + pa_ptr->hand]; + if (decide_attack_hit(attacker_ptr, pa_ptr, chance)) + return TRUE; + + pa_ptr->backstab = FALSE; /* Clumsy! */ + pa_ptr->surprise_attack = FALSE; /* Clumsy! */ + + if ((o_ptr->tval == TV_POLEARM) && (o_ptr->sval == SV_DEATH_SCYTHE) && one_in_(3)) { + process_death_scythe_reflection(attacker_ptr, pa_ptr); + } else { + sound(SOUND_MISS); + msg_format(_("ミス! %sにかわされた。", "You miss %s."), pa_ptr->m_name); + } + + return FALSE; +} diff --git a/src/combat/attack-accuracy.h b/src/combat/attack-accuracy.h new file mode 100644 index 000000000..cefc96d43 --- /dev/null +++ b/src/combat/attack-accuracy.h @@ -0,0 +1,10 @@ +#pragma once + +#include "system/angband.h" +#include "player-attack/player-attack-util.h" + +bool test_hit_norm(player_type *attacker_ptr, HIT_RELIABILITY chance, ARMOUR_CLASS ac, bool visible); +PERCENTAGE hit_chance(player_type *attacker_ptr, HIT_RELIABILITY chance, ARMOUR_CLASS ac); +int check_hit_from_monster_to_player(player_type *target_ptr, int power, DEPTH level, int stun); +int check_hit_from_monster_to_monster(int power, DEPTH level, ARMOUR_CLASS ac, int stun); +bool process_attack_hit(player_type *attacker_ptr, player_attack_type *pa_ptr, int chance); diff --git a/src/combat/attack-criticality.c b/src/combat/attack-criticality.c new file mode 100644 index 000000000..f794d2fd7 --- /dev/null +++ b/src/combat/attack-criticality.c @@ -0,0 +1,168 @@ +#include "combat/combat-options-type.h" +#include "combat/attack-criticality.h" +#include "inventory/inventory-slot-types.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags7.h" +#include "sv-definition/sv-weapon-types.h" +#include "view/display-messages.h" + +/*! +* @brief プレイヤーからモンスターへの打撃クリティカル判定 / +* Critical hits (by player) Factor in weapon weight, total plusses, player melee bonus +* @param weight 矢弾の重量 +* @param plus 武器の命中修正 +* @param dam 現在算出中のダメージ値 +* @param meichuu 打撃の基本命中力 +* @param mode オプションフラグ +* @return クリティカル修正が入ったダメージ値 +*/ +HIT_POINT critical_norm(player_type *attacker_ptr, WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, combat_options mode) +{ + /* Extract "blow" power */ + int i = (weight + (meichuu * 3 + plus * 5) + attacker_ptr->skill_thn); + + /* Chance */ + bool is_special_option = randint1((attacker_ptr->pclass == CLASS_NINJA) ? 4444 : 5000) <= i; + is_special_option |= mode == HISSATSU_MAJIN; + is_special_option |= mode == HISSATSU_3DAN; + if (!is_special_option) + return dam; + + int k = weight + randint1(650); + if ((mode == HISSATSU_MAJIN) || (mode == HISSATSU_3DAN)) + k += randint1(650); + + if (k < 400) { + msg_print(_("手ごたえがあった!", "It was a good hit!")); + + dam = 2 * dam + 5; + return dam; + } + + if (k < 700) { + msg_print(_("かなりの手ごたえがあった!", "It was a great hit!")); + dam = 2 * dam + 10; + return dam; + } + + if (k < 900) { + msg_print(_("会心の一撃だ!", "It was a superb hit!")); + dam = 3 * dam + 15; + return dam; + } + + if (k < 1300) { + msg_print(_("最高の会心の一撃だ!", "It was a *GREAT* hit!")); + dam = 3 * dam + 20; + return dam; + } + + msg_print(_("比類なき最高の会心の一撃だ!", "It was a *SUPERB* hit!")); + dam = ((7 * dam) / 2) + 25; + return dam; +} + +/*! + * @brief モンスター打撃のクリティカルランクを返す / + * Critical blow. All hits that do 95% of total possible damage, + * @param dice モンスター打撃のダイス数 + * @param sides モンスター打撃の最大ダイス目 + * @param dam プレイヤーに与えたダメージ + * @details + * and which also do at least 20 damage, or, sometimes, N damage. + * This is used only to determine "cuts" and "stuns". + */ +int calc_monster_critical(DICE_NUMBER dice, DICE_SID sides, HIT_POINT dam) +{ + int total = dice * sides; + if (dam < total * 19 / 20) + return 0; + + if ((dam < 20) && (randint0(100) >= dam)) + return 0; + + int max = 0; + if ((dam >= total) && (dam >= 40)) + max++; + + if (dam >= 20) + while (randint0(100) < 2) + max++; + + if (dam > 45) + return (6 + max); + + if (dam > 33) + return (5 + max); + + if (dam > 25) + return (4 + max); + + if (dam > 18) + return (3 + max); + + if (dam > 11) + return (2 + max); + + return (1 + max); +} + +/*! + * @brief 忍者ヒットで急所を突く + * @param attacker_ptr プレーヤーへの参照ポインタ + * @param pa_ptr 直接攻撃構造体への参照ポインタ + * @return なし + */ +static void ninja_critical(player_type *attacker_ptr, player_attack_type *pa_ptr) +{ + monster_race *r_ptr = &r_info[pa_ptr->m_ptr->r_idx]; + int maxhp = maxroll(r_ptr->hdice, r_ptr->hside); + if (one_in_(pa_ptr->backstab ? 13 : (pa_ptr->stab_fleeing || pa_ptr->surprise_attack) ? 15 : 27)) { + pa_ptr->attack_damage *= 5; + pa_ptr->drain_result *= 2; + msg_format(_("刃が%sに深々と突き刺さった!", "You critically injured %s!"), pa_ptr->m_name); + return; + } + + bool is_critical = ((pa_ptr->m_ptr->hp < maxhp / 2) && one_in_((attacker_ptr->num_blow[0] + attacker_ptr->num_blow[1] + 1) * 10)) + || ((one_in_(666) || ((pa_ptr->backstab || pa_ptr->surprise_attack) && one_in_(11))) && ((r_ptr->flags1 & RF1_UNIQUE) == 0) + && ((r_ptr->flags7 & RF7_UNIQUE2) == 0)); + if (!is_critical) + return; + + if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_UNIQUE2) || (pa_ptr->m_ptr->hp >= maxhp / 2)) { + pa_ptr->attack_damage = MAX(pa_ptr->attack_damage * 5, pa_ptr->m_ptr->hp / 2); + pa_ptr->drain_result *= 2; + msg_format(_("%sに致命傷を負わせた!", "You fatally injured %s!"), pa_ptr->m_name); + } else { + pa_ptr->attack_damage = pa_ptr->m_ptr->hp + 1; + msg_format(_("刃が%sの急所を貫いた!", "You hit %s on a fatal spot!"), pa_ptr->m_name); + } +} + +/*! + * @brief 急所を突く + * @param attacker_ptr プレーヤーへの参照ポインタ + * @param pa_ptr 直接攻撃構造体への参照ポインタ + * @return なし + */ +void critical_attack(player_type *attacker_ptr, player_attack_type *pa_ptr) +{ + object_type *o_ptr = &attacker_ptr->inventory_list[INVEN_RARM + pa_ptr->hand]; + monster_race *r_ptr = &r_info[pa_ptr->m_ptr->r_idx]; + if (((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_POISON_NEEDLE)) || (pa_ptr->mode == HISSATSU_KYUSHO)) { + if ((randint1(randint1(r_ptr->level / 7) + 5) == 1) && !(r_ptr->flags1 & RF1_UNIQUE) && !(r_ptr->flags7 & RF7_UNIQUE2)) { + pa_ptr->attack_damage = pa_ptr->m_ptr->hp + 1; + msg_format(_("%sの急所を突き刺した!", "You hit %s on a fatal spot!"), pa_ptr->m_name); + } else + pa_ptr->attack_damage = 1; + + return; + } + + bool is_ninja_hit = (attacker_ptr->pclass == CLASS_NINJA) && has_melee_weapon(attacker_ptr, INVEN_RARM + pa_ptr->hand) + && !attacker_ptr->icky_wield[pa_ptr->hand] && ((attacker_ptr->cur_lite <= 0) || one_in_(7)); + if (is_ninja_hit) + ninja_critical(attacker_ptr, pa_ptr); +} diff --git a/src/combat/attack-criticality.h b/src/combat/attack-criticality.h new file mode 100644 index 000000000..04558ddda --- /dev/null +++ b/src/combat/attack-criticality.h @@ -0,0 +1,8 @@ +#pragma once + +#include "system/angband.h" +#include "player-attack/player-attack-util.h" + +HIT_POINT critical_norm(player_type *attacker_ptr, WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, combat_options mode); +int calc_monster_critical(DICE_NUMBER dice, DICE_SID sides, HIT_POINT dam); +void critical_attack(player_type *attacker_ptr, player_attack_type *pa_ptr); diff --git a/src/combat/attack-power-table.c b/src/combat/attack-power-table.c new file mode 100644 index 000000000..06642f570 --- /dev/null +++ b/src/combat/attack-power-table.c @@ -0,0 +1,215 @@ +#include "combat/attack-power-table.h" + +/*! + * @brief 修行僧のターンダメージ算出テーブル + */ +const int monk_ave_damage[PY_MAX_LEVEL + 1][3] = { + { 0, 0, 0 }, + { 249, 249, 249 }, + { 324, 324, 324 }, + { 382, 438, 382 }, + { 382, 439, 382 }, + { 390, 446, 390 }, + { 394, 473, 394 }, + { 425, 528, 425 }, + { 430, 535, 430 }, + { 505, 560, 435 }, + { 517, 575, 444 }, + { 566, 655, 474 }, + { 585, 713, 486 }, + { 653, 843, 527 }, + { 678, 890, 544 }, + { 703, 973, 558 }, + { 765, 1096, 596 }, + { 914, 1146, 614 }, + { 943, 1240, 629 }, + { 971, 1276, 643 }, + { 1018, 1350, 667 }, + { 1063, 1464, 688 }, + { 1099, 1515, 705 }, + { 1128, 1559, 721 }, + { 1153, 1640, 735 }, + { 1336, 1720, 757 }, + { 1387, 1789, 778 }, + { 1430, 1893, 794 }, + { 1610, 2199, 863 }, + { 1666, 2280, 885 }, + { 1713, 2401, 908 }, + { 1755, 2465, 925 }, + { 1909, 2730, 984 }, + { 2156, 2891, 1009 }, + { 2218, 2970, 1031 }, + { 2319, 3107, 1063 }, + { 2404, 3290, 1098 }, + { 2477, 3389, 1125 }, + { 2544, 3483, 1150 }, + { 2771, 3899, 1228 }, + { 2844, 3982, 1259 }, + { 3129, 4064, 1287 }, + { 3200, 4190, 1313 }, + { 3554, 4674, 1432 }, + { 3614, 4738, 1463 }, + { 3679, 4853, 1485 }, + { 3741, 4905, 1512 }, + { 3785, 4943, 1538 }, + { 4141, 5532, 1652 }, + { 4442, 5581, 1679 }, + { 4486, 5636, 1702 }, +}; + +/*! + * 腕力による攻撃回数算定値テーブル + * Stat Table (STR) -- help index into the "blow" table + */ +const byte adj_str_blow[MAX_ADJ_STR] = { + 3 /* 3 */, + 4 /* 4 */, + 5 /* 5 */, + 6 /* 6 */, + 7 /* 7 */, + 8 /* 8 */, + 9 /* 9 */, + 10 /* 10 */, + 11 /* 11 */, + 12 /* 12 */, + 13 /* 13 */, + 14 /* 14 */, + 15 /* 15 */, + 16 /* 16 */, + 17 /* 17 */, + 20 /* 18/00-18/09 */, + 30 /* 18/10-18/19 */, + 40 /* 18/20-18/29 */, + 50 /* 18/30-18/39 */, + 60 /* 18/40-18/49 */, + 70 /* 18/50-18/59 */, + 80 /* 18/60-18/69 */, + 90 /* 18/70-18/79 */, + 100 /* 18/80-18/89 */, + 110 /* 18/90-18/99 */, + 120 /* 18/100-18/109 */, + 130 /* 18/110-18/119 */, + 140 /* 18/120-18/129 */, + 150 /* 18/130-18/139 */, + 160 /* 18/140-18/149 */, + 170 /* 18/150-18/159 */, + 180 /* 18/160-18/169 */, + 190 /* 18/170-18/179 */, + 200 /* 18/180-18/189 */, + 210 /* 18/190-18/199 */, + 220 /* 18/200-18/209 */, + 230 /* 18/210-18/219 */, + 240 /* 18/220+ */ +}; + +/*! + * 器用さによる攻撃回数インデックステーブル + * Stat Table (DEX) -- index into the "blow" table + */ +const byte adj_dex_blow[MAX_ADJ_DEX] = { + 0 /* 3 */, + 0 /* 4 */, + 0 /* 5 */, + 0 /* 6 */, + 0 /* 7 */, + 0 /* 8 */, + 0 /* 9 */, + 1 /* 10 */, + 1 /* 11 */, + 1 /* 12 */, + 1 /* 13 */, + 1 /* 14 */, + 2 /* 15 */, + 2 /* 16 */, + 2 /* 17 */, + 2 /* 18/00-18/09 */, + 3 /* 18/10-18/19 */, + 3 /* 18/20-18/29 */, + 3 /* 18/30-18/39 */, + 4 /* 18/40-18/49 */, + 4 /* 18/50-18/59 */, + 5 /* 18/60-18/69 */, + 5 /* 18/70-18/79 */, + 6 /* 18/80-18/89 */, + 6 /* 18/90-18/99 */, + 7 /* 18/100-18/109 */, + 7 /* 18/110-18/119 */, + 8 /* 18/120-18/129 */, + 8 /* 18/130-18/139 */, + 9 /* 18/140-18/149 */, + 9 /* 18/150-18/159 */, + 10 /* 18/160-18/169 */, + 10 /* 18/170-18/179 */, + 11 /* 18/180-18/189 */, + 11 /* 18/190-18/199 */, + 12 /* 18/200-18/209 */, + 12 /* 18/210-18/219 */, + 13 /* 18/220+ */ +}; + +/*! + * @brief + * 腕力、器用さに応じた攻撃回数テーブル / + * This table is used to help calculate the number of blows the player can + * make in a single round of attacks (one player turn) with a normal weapon. + * @details + *
+ * This number ranges from a single blow/round for weak players to up to six
+ * blows/round for powerful warriors.
+ *
+ * Note that certain artifacts and ego-items give "bonus" blows/round.
+ *
+ * First, from the player class, we extract some values:
+ *
+ * Warrior       num = 6; mul = 5; div = MAX(70, weapon_weight);
+ * Berserker     num = 6; mul = 7; div = MAX(70, weapon_weight);
+ * Mage          num = 3; mul = 2; div = MAX(100, weapon_weight);
+ * Priest        num = 5; mul = 3; div = MAX(100, weapon_weight);
+ * Mindcrafter   num = 5; mul = 3; div = MAX(100, weapon_weight);
+ * Rogue         num = 5; mul = 3; div = MAX(40, weapon_weight);
+ * Ranger        num = 5; mul = 4; div = MAX(70, weapon_weight);
+ * Paladin       num = 5; mul = 4; div = MAX(70, weapon_weight);
+ * Weaponsmith   num = 5; mul = 5; div = MAX(150, weapon_weight);
+ * Warrior-Mage  num = 5; mul = 3; div = MAX(70, weapon_weight);
+ * Chaos Warrior num = 5; mul = 4; div = MAX(70, weapon_weight);
+ * Monk          num = 5; mul = 3; div = MAX(60, weapon_weight);
+ * Tourist       num = 4; mul = 3; div = MAX(100, weapon_weight);
+ * Imitator      num = 5; mul = 4; div = MAX(70, weapon_weight);
+ * Beastmaster   num = 5; mul = 3; div = MAX(70, weapon_weight);
+ * Cavalry(Ride) num = 5; mul = 4; div = MAX(70, weapon_weight);
+ * Cavalry(Walk) num = 5; mul = 3; div = MAX(100, weapon_weight);
+ * Sorcerer      num = 1; mul = 1; div = MAX(1, weapon_weight);
+ * Archer        num = 4; mul = 2; div = MAX(70, weapon_weight);
+ * Magic eater   num = 4; mul = 2; div = MAX(70, weapon_weight);
+ * ForceTrainer  num = 4; mul = 2; div = MAX(60, weapon_weight);
+ * Mirror Master num = 3; mul = 3; div = MAX(100, weapon_weight);
+ * Ninja         num = 4; mul = 1; div = MAX(20, weapon_weight);
+ *
+ * To get "P", we look up the relevant "adj_str_blow[]" (see above),
+ * multiply it by "mul", and then divide it by "div".
+ * Increase P by 1 if you wield a weapon two-handed.
+ * Decrease P by 1 if you are a Ninja.
+ *
+ * To get "D", we look up the relevant "adj_dex_blow[]" (see above),
+ *
+ * The player gets "blows_table[P][D]" blows/round, as shown below,
+ * up to a maximum of "num" blows/round, plus any "bonus" blows/round.
+ * 
+ */ +const byte blows_table[12][12] = { + /* P/D */ + /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11+ */ + /* 3 10 15 /10 /40 /60 /80 /100 /120 /140 /160 /180 */ + /* 0 */ { 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4 }, + /* 1 */ { 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4 }, + /* 2 */ { 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5 }, + /* 3 */ { 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5 }, + /* 4 */ { 1, 1, 2, 3, 3, 4, 4, 5, 5, 5, 5, 5 }, + /* 5 */ { 1, 1, 2, 3, 4, 4, 4, 5, 5, 5, 5, 6 }, + /* 6 */ { 1, 1, 2, 3, 4, 4, 4, 5, 5, 5, 5, 6 }, + /* 7 */ { 1, 2, 2, 3, 4, 4, 4, 5, 5, 5, 5, 6 }, + /* 8 */ { 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6 }, + /* 9 */ { 1, 2, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6 }, + /* 10*/ { 2, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6 }, + /*11+*/ { 2, 2, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6 }, +}; diff --git a/src/combat/attack-power-table.h b/src/combat/attack-power-table.h new file mode 100644 index 000000000..864e98fc9 --- /dev/null +++ b/src/combat/attack-power-table.h @@ -0,0 +1,11 @@ +#pragma once + +#include "system/angband.h" + +#define MAX_ADJ_STR 38 +#define MAX_ADJ_DEX 39 + +extern const int monk_ave_damage[PY_MAX_LEVEL + 1][3]; +extern const byte adj_str_blow[MAX_ADJ_STR]; +extern const byte adj_dex_blow[MAX_ADJ_DEX]; +extern const byte blows_table[12][12]; diff --git a/src/combat/aura-counterattack.c b/src/combat/aura-counterattack.c new file mode 100644 index 000000000..64416e19d --- /dev/null +++ b/src/combat/aura-counterattack.c @@ -0,0 +1,221 @@ +/*! + * @brief モンスターから直接攻撃を受けた時に、プレーヤーのオーラダメージで反撃する処理 + * @date 2020/05/31 + * @author Hourier + */ + +#include "combat/aura-counterattack.h" +#include "effect/effect-characteristics.h" +#include "effect/effect-processor.h" +#include "grid/grid.h" +#include "inventory/inventory-slot-types.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags-resistance.h" +#include "monster-race/race-flags3.h" +#include "monster/monster-info.h" +#include "monster/monster-status.h" +#include "object-hook/hook-armor.h" +#include "object-hook/hook-checker.h" +#include "realm/realm-hex-numbers.h" +#include "spell-kind/spells-teleport.h" +#include "spell-realm/spells-hex.h" +#include "spell/spell-types.h" +#include "system/floor-type-definition.h" +#include "system/object-type-definition.h" +#include "view/display-messages.h" + +static void aura_fire_by_monster_attack(player_type *target_ptr, monap_type *monap_ptr) +{ + if (!target_ptr->sh_fire || !monap_ptr->alive || target_ptr->is_dead) + return; + + monster_race *r_ptr = &r_info[monap_ptr->m_ptr->r_idx]; + if ((r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK) != 0) { + if (is_original_ap_and_seen(target_ptr, monap_ptr->m_ptr)) + r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK); + + return; + } + + HIT_POINT dam = damroll(2, 6); + dam = mon_damage_mod(target_ptr, monap_ptr->m_ptr, dam, FALSE); + msg_format(_("%^sは突然熱くなった!", "%^s is suddenly very hot!"), monap_ptr->m_name); + if (mon_take_hit(target_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, _("は灰の山になった。", " turns into a pile of ash."))) { + monap_ptr->blinked = FALSE; + monap_ptr->alive = FALSE; + } +} + +static void aura_elec_by_monster_attack(player_type *target_ptr, monap_type *monap_ptr) +{ + if (!target_ptr->sh_elec || !monap_ptr->alive || target_ptr->is_dead) + return; + + monster_race *r_ptr = &r_info[monap_ptr->m_ptr->r_idx]; + if ((r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK) != 0) { + if (is_original_ap_and_seen(target_ptr, monap_ptr->m_ptr)) + r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK); + + return; + } + + HIT_POINT dam = damroll(2, 6); + dam = mon_damage_mod(target_ptr, monap_ptr->m_ptr, dam, FALSE); + msg_format(_("%^sは電撃をくらった!", "%^s gets zapped!"), monap_ptr->m_name); + if (mon_take_hit(target_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, _("は燃え殻の山になった。", " turns into a pile of cinders."))) { + monap_ptr->blinked = FALSE; + monap_ptr->alive = FALSE; + } +} + +static void aura_cold_by_monster_attack(player_type *target_ptr, monap_type *monap_ptr) +{ + if (!target_ptr->sh_cold || !monap_ptr->alive || target_ptr->is_dead) + return; + + monster_race *r_ptr = &r_info[monap_ptr->m_ptr->r_idx]; + if ((r_ptr->flagsr & RFR_EFF_IM_COLD_MASK) != 0) { + if (is_original_ap_and_seen(target_ptr, monap_ptr->m_ptr)) + r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_COLD_MASK); + + return; + } + + HIT_POINT dam = damroll(2, 6); + dam = mon_damage_mod(target_ptr, monap_ptr->m_ptr, dam, FALSE); + msg_format(_("%^sは冷気をくらった!", "%^s is very cold!"), monap_ptr->m_name); + if (mon_take_hit(target_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, _("は凍りついた。", " was frozen."))) { + monap_ptr->blinked = FALSE; + monap_ptr->alive = FALSE; + } +} + +static void aura_shards_by_monster_attack(player_type *target_ptr, monap_type *monap_ptr) +{ + if (!target_ptr->dustrobe || !monap_ptr->alive || target_ptr->is_dead) + return; + + monster_race *r_ptr = &r_info[monap_ptr->m_ptr->r_idx]; + if ((r_ptr->flagsr & RFR_EFF_RES_SHAR_MASK) != 0) { + if (is_original_ap_and_seen(target_ptr, monap_ptr->m_ptr)) + r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_RES_SHAR_MASK); + } else { + HIT_POINT dam = damroll(2, 6); + dam = mon_damage_mod(target_ptr, monap_ptr->m_ptr, dam, FALSE); + msg_format(_("%^sは鏡の破片をくらった!", "%^s gets sliced!"), monap_ptr->m_name); + if (mon_take_hit(target_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, _("はズタズタになった。", " is torn to pieces."))) { + monap_ptr->blinked = FALSE; + monap_ptr->alive = FALSE; + } + } + + if (is_mirror_grid(&target_ptr->current_floor_ptr->grid_array[target_ptr->y][target_ptr->x])) + teleport_player(target_ptr, 10, TELEPORT_SPONTANEOUS); +} + +static void aura_holy_by_monster_attack(player_type *target_ptr, monap_type *monap_ptr) +{ + if (!target_ptr->tim_sh_holy || !monap_ptr->alive || target_ptr->is_dead) + return; + + monster_race *r_ptr = &r_info[monap_ptr->m_ptr->r_idx]; + if ((r_ptr->flags3 & RF3_EVIL) == 0) + return; + + if ((r_ptr->flagsr & RFR_RES_ALL) != 0) { + if (is_original_ap_and_seen(target_ptr, monap_ptr->m_ptr)) + r_ptr->r_flagsr |= RFR_RES_ALL; + + return; + } + + HIT_POINT dam = damroll(2, 6); + dam = mon_damage_mod(target_ptr, monap_ptr->m_ptr, dam, FALSE); + msg_format(_("%^sは聖なるオーラで傷ついた!", "%^s is injured by holy power!"), monap_ptr->m_name); + if (mon_take_hit(target_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, _("は倒れた。", " is destroyed."))) { + monap_ptr->blinked = FALSE; + monap_ptr->alive = FALSE; + } + + if (is_original_ap_and_seen(target_ptr, monap_ptr->m_ptr)) + r_ptr->r_flags3 |= RF3_EVIL; +} + +static void aura_force_by_monster_attack(player_type *target_ptr, monap_type *monap_ptr) +{ + if (!target_ptr->tim_sh_touki || !monap_ptr->alive || target_ptr->is_dead) + return; + + monster_race *r_ptr = &r_info[monap_ptr->m_ptr->r_idx]; + if ((r_ptr->flagsr & RFR_RES_ALL) != 0) { + if (is_original_ap_and_seen(target_ptr, monap_ptr->m_ptr)) + r_ptr->r_flagsr |= RFR_RES_ALL; + + return; + } + + HIT_POINT dam = damroll(2, 6); + dam = mon_damage_mod(target_ptr, monap_ptr->m_ptr, dam, FALSE); + msg_format(_("%^sが鋭い闘気のオーラで傷ついた!", "%^s is injured by the Force"), monap_ptr->m_name); + if (mon_take_hit(target_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, _("は倒れた。", " is destroyed."))) { + monap_ptr->blinked = FALSE; + monap_ptr->alive = FALSE; + } +} + +static void aura_shadow_by_monster_attack(player_type *target_ptr, monap_type *monap_ptr) +{ + if (!hex_spelling(target_ptr, HEX_SHADOW_CLOAK) || !monap_ptr->alive || target_ptr->is_dead) + return; + + HIT_POINT dam = 1; + object_type *o_armed_ptr = &target_ptr->inventory_list[INVEN_RARM]; + monster_race *r_ptr = &r_info[monap_ptr->m_ptr->r_idx]; + if (((r_ptr->flagsr & RFR_RES_ALL) != 0) || ((r_ptr->flagsr & RFR_RES_DARK) != 0)) { + if (is_original_ap_and_seen(target_ptr, monap_ptr->m_ptr)) + r_ptr->r_flagsr |= (RFR_RES_ALL | RFR_RES_DARK); + + return; + } + + if (o_armed_ptr->k_idx) { + int basedam = ((o_armed_ptr->dd + target_ptr->to_dd[0]) * (o_armed_ptr->ds + target_ptr->to_ds[0] + 1)); + dam = basedam / 2 + o_armed_ptr->to_d + target_ptr->to_d[0]; + } + + o_armed_ptr = &target_ptr->inventory_list[INVEN_BODY]; + if ((o_armed_ptr->k_idx) && object_is_cursed(o_armed_ptr)) + dam *= 2; + + dam = mon_damage_mod(target_ptr, monap_ptr->m_ptr, dam, FALSE); + msg_format(_("影のオーラが%^sに反撃した!", "Enveloping shadows attack %^s."), monap_ptr->m_name); + if (mon_take_hit(target_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, _("は倒れた。", " is destroyed."))) { + monap_ptr->blinked = FALSE; + monap_ptr->alive = FALSE; + return; + } + + BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL; + EFFECT_ID typ[4][2] = { { INVEN_HEAD, GF_OLD_CONF }, { INVEN_LARM, GF_OLD_SLEEP }, { INVEN_HANDS, GF_TURN_ALL }, { INVEN_FEET, GF_OLD_SLOW } }; + + /* Some cursed armours gives an extra effect */ + for (int j = 0; j < 4; j++) { + o_armed_ptr = &target_ptr->inventory_list[typ[j][0]]; + if ((o_armed_ptr->k_idx) && object_is_cursed(o_armed_ptr) && object_is_armour(target_ptr, o_armed_ptr)) + project(target_ptr, 0, 0, monap_ptr->m_ptr->fy, monap_ptr->m_ptr->fx, (target_ptr->lev * 2), typ[j][1], flg, -1); + } +} + +void process_aura_counterattack(player_type *target_ptr, monap_type *monap_ptr) +{ + if (!monap_ptr->touched) + return; + + aura_fire_by_monster_attack(target_ptr, monap_ptr); + aura_elec_by_monster_attack(target_ptr, monap_ptr); + aura_cold_by_monster_attack(target_ptr, monap_ptr); + aura_shards_by_monster_attack(target_ptr, monap_ptr); + aura_holy_by_monster_attack(target_ptr, monap_ptr); + aura_force_by_monster_attack(target_ptr, monap_ptr); + aura_shadow_by_monster_attack(target_ptr, monap_ptr); +} diff --git a/src/combat/aura-counterattack.h b/src/combat/aura-counterattack.h new file mode 100644 index 000000000..e3a20f74b --- /dev/null +++ b/src/combat/aura-counterattack.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" +#include "monster-attack/monster-attack-util.h" + +void process_aura_counterattack(player_type *target_ptr, monap_type *monap_ptr); diff --git a/src/combat/combat-options-type.h b/src/combat/combat-options-type.h new file mode 100644 index 000000000..a50e9e317 --- /dev/null +++ b/src/combat/combat-options-type.h @@ -0,0 +1,36 @@ +#pragma once + +typedef enum combat_options { + HISSATSU_NONE = 0, + HISSATSU_2 = 1, + HISSATSU_3WAY = 2, + HISSATSU_SUTEMI = 3, + HISSATSU_FIRE = 4, + HISSATSU_COLD = 5, + HISSATSU_POISON = 6, + HISSATSU_ELEC = 7, + HISSATSU_NYUSIN = 8, + HISSATSU_FUKI = 9, + HISSATSU_MAJIN = 10, + HISSATSU_BOOMER = 11, + HISSATSU_DRAIN = 12, + HISSATSU_SEKIRYUKA = 13, + HISSATSU_OTAKEBI = 14, + HISSATSU_SHOUGE = 15, + HISSATSU_CONF = 16, + HISSATSU_ISSEN = 17, + HISSATSU_KYUSHO = 18, + HISSATSU_KONSIN = 19, + HISSATSU_HYAKU = 20, + HISSATSU_MINEUCHI = 21, + HISSATSU_MEKIKI = 22, + HISSATSU_ZANMA = 23, + HISSATSU_UNDEAD = 24, + HISSATSU_HAGAN = 25, + HISSATSU_QUAKE = 26, + HISSATSU_COUNTER = 27, + HISSATSU_HARAI = 28, + HISSATSU_3DAN = 29, + HISSATSU_100NIN = 30, + HISSATSU_IAI = 100, +} combat_options; diff --git a/src/combat/hallucination-attacks-table.c b/src/combat/hallucination-attacks-table.c new file mode 100644 index 000000000..bb77df4e2 --- /dev/null +++ b/src/combat/hallucination-attacks-table.c @@ -0,0 +1,134 @@ +#include "combat/hallucination-attacks-table.h" + +/*! + * @brief 幻覚時の打撃記述テーブル / Weird melee attack types when hallucinating + */ +#ifdef JP +const concptr silly_attacks[MAX_SILLY_ATTACK] = { + "に小便をかけられた。", + "があなたの回りを3回回ってワンと言った。", + "にしばきまわされた。", + "に靴をなめさせられた。", + "にハナクソを飛ばされた。", + "にジャン拳で攻撃された。", + "があなたの頬を札束でしばいた。", + "があなたの前でポージングをした。", + "にアカンベーされた。", + "に「神の国」発言の撤回を求められた。", + "にメッ○ールを飲まされた。", + "につっこみを入れられた。", + "はあなたと踊った。", + "に顔にらく書きをされた。", + "に借金の返済をせまられた。", + "にスカートをめくられた。", + "はあなたの手相を占った。", + "から役満を上がられた。", + "から愛の告白をされた。", + "はあなたを時給500円で雇った。", + "はあなたの100の秘密について熱く語った。", + "がニャーと鳴いた。", + "はあなたに気をつけた。", + "はあなたをポリゴン化させた。", + "に少しかじられた。", + "はアルテマの呪文を唱えた!", + "はあなたのスパイクをブロックした。", + "はスライド移動した。", + "は昇龍拳コマンドの入力に失敗した。", + "は拡散波動砲を発射した。", + "はデスラー戦法をしかけた。", + "にライダーキックで攻撃された。", + "に二週間以内でビデオを人に見せないと死ぬ呪いをかけられた。", + "はパルプンテを唱えた。", + "はスーパーウルトラギャラクティカマグナムを放った。", + "にしゃがみ小キックでハメられた。", + "にジェットストリームアタックをかけられた。", + "はあなたに卍固めをかけて「1、2、3、ダーッ!」と叫んだ。", + "は「いくじなし!ばかばかばか!」といって駆け出した。", + "が「ごらん、ルーベンスの絵だよ」と言って静かに目を閉じた。", + "は言った。「馬鹿馬鹿蛮怒、絶賛公開中!」", +}; + +/*! + * @brief 幻覚時の打撃記述テーブル(フォーマットつき) / Weird melee attack types when hallucinating (%s for strfmt()) + */ +const concptr silly_attacks2[MAX_SILLY_ATTACK] = { + "%sに小便をかけた。", + "%sの回りを3回回ってワンと言った。", + "%sをしばきまわした。", + "%sに靴をなめさせた。", + "%sにハナクソを飛ばした。", + "%sをジャン拳で攻撃した。", + "%sの頬を札束でしばいた。", + "%sの前でポージングをした。", + "%sにアカンベーした。", + "%sに「神の国」発言の撤回を求めた。", + "%sにメッ○ールを飲ませた。", + "%sにつっこみを入れた。", + "%sと踊った。", + "%sの顔にらく書きをした。", + "%sに借金の返済をせまった。", + "%sのスカートをめくった。", + "%sの手相を占った。", + "%sから役満を上がった。", + "%sに愛の告白をした。", + "%sを時給500円で雇った。", + "%sの100の秘密について熱く語った。", + "ニャーと鳴いた。", + "%sに気をつけた。", + "%sをポリゴン化させた。", + "%sを少しかじった。", + "アルテマの呪文を唱えた!", + "%sのスパイクをブロックした。", + "スライド移動した。", + "昇龍拳コマンドの入力に失敗した。", + "%sに拡散波動砲を発射した。", + "%sにデスラー戦法をしかけた。", + "%sをライダーキックで攻撃した。", + "%sに二週間以内でビデオを人に見せないと死ぬ呪いをかけた。", + "パルプンテを唱えた。", + "%sにスーパーウルトラギャラクティカマグナムを放った。", + "%sをしゃがみ小キックでハメた。", + "%sにジェットストリームアタックをかけた。", + "%sに卍固めをかけて「1、2、3、ダーッ!」と叫んだ。", + "「いくじなし!ばかばかばか!」といって駆け出した。", + "「ごらん、ルーベンスの絵だよ」と言って静かに目を閉じた。", + "言った。「馬鹿馬鹿蛮怒、絶賛公開中!」", +}; +#else +const concptr silly_attacks[MAX_SILLY_ATTACK] = { + "smothers", + "hugs", + "humiliates", + "whips", + "kisses", + + "disgusts", + "pees all over", + "passes the gas on", + "makes obscene gestures at", + "licks", + + "stomps on", + "swallows", + "drools on", + "misses", + "shrinks", + + "emasculates", + "evaporates", + "solidifies", + "digitizes", + "insta-kills", + + "massacres", + "slaughters", + "drugs", + "psychoanalyzes", + "deconstructs", + + "falsifies", + "disbelieves", + "molests", + "pusupusu", +}; +#endif diff --git a/src/combat/hallucination-attacks-table.h b/src/combat/hallucination-attacks-table.h new file mode 100644 index 000000000..622181df7 --- /dev/null +++ b/src/combat/hallucination-attacks-table.h @@ -0,0 +1,11 @@ +#pragma once + +#include "system/angband.h" + +// 幻覚時のジョークメッセージ最大数 / Hallucination stuff. +#define MAX_SILLY_ATTACK _(41, 29) + +extern const concptr silly_attacks[MAX_SILLY_ATTACK]; +#ifdef JP +extern const concptr silly_attacks2[MAX_SILLY_ATTACK]; +#endif diff --git a/src/combat/martial-arts-table.c b/src/combat/martial-arts-table.c new file mode 100644 index 000000000..e487081d9 --- /dev/null +++ b/src/combat/martial-arts-table.c @@ -0,0 +1,23 @@ +#include "combat/martial-arts-table.h" +/*! + * @brief マーシャルアーツ打撃テーブル + */ +const martial_arts ma_blows[MAX_MA] = { + { _("%sを殴った。", "You punch %s."), 1, 0, 1, _(5, 4), 0 }, + { _("%sを蹴った。", "You kick %s."), 2, 0, 1, _(7, 6), 0 }, + { _("%sに正拳突きをくらわした。", "You strike %s."), 3, 0, 1, _(9, 7), 0 }, + { _("%sに膝蹴りをくらわした。", "You hit %s with your knee."), 5, 5, 2, _(4, 3), MA_KNEE }, + { _("%sに肘打ちをくらわした。", "You hit %s with your elbow."), 7, 5, 1, _(12, 8), 0 }, + { _("%sに体当りした。", "You butt %s."), 9, 10, 2, _(6, 5), 0 }, + { _("%sを蹴った。", "You kick %s."), 11, 10, 3, _(6, 4), MA_SLOW }, + { _("%sにアッパーをくらわした。", "You uppercut %s."), 13, 12, _(5, 4), _(5, 4), 6 }, + { _("%sに二段蹴りをくらわした。", "You double-kick %s."), 16, 15, 5, _(6, 4), 8 }, + { _("%sに猫爪撃をくらわした。", "You hit %s with a Cat's Claw."), 20, 20, 5, _(8, 5), 0 }, + { _("%sに跳空脚をくらわした。", "You hit %s with a jump kick."), _(24, 25), 25, _(6, 5), _(8, 6), 10 }, + { _("%sに鷲爪襲をくらわした。", "You hit %s with an Eagle's Claw."), _(28, 29), 25, _(7, 6), _(9, 6), 0 }, + { _("%sに回し蹴りをくらわした。", "You hit %s with a circle kick."), _(32, 33), 30, _(8, 6), _(10, 8), 10 }, + { _("%sに鉄拳撃をくらわした。", "You hit %s with an Iron Fist."), _(35, 37), 35, 8, _(11, 8), 10 }, + { _("%sに飛空脚をくらわした。", "You hit %s with a flying kick."), _(39, 41), 35, 8, _(12, 10), 12 }, + { _("%sに昇龍拳をくらわした。", "You hit %s with a Dragon Fist."), _(43, 45), 35, _(9, 10), _(12, 10), 16 }, + { _("%sに石破天驚拳をくらわした。", "You hit %s with a Crushing Blow."), 48, _(40, 35), 10, _(13, 12), 18 }, +}; diff --git a/src/combat/martial-arts-table.h b/src/combat/martial-arts-table.h new file mode 100644 index 000000000..793546b45 --- /dev/null +++ b/src/combat/martial-arts-table.h @@ -0,0 +1,19 @@ +#pragma once + +#include "system/angband.h" + +#define MAX_MA 17 /*!< 修行僧マーシャルアーツの技数 / Monk martial arts... */ +#define MA_KNEE 1 /*!< 金的効果ID */ +#define MA_SLOW 2 /*!< 膝蹴り効果ID */ + +/* For Monk martial arts */ +typedef struct martial_arts { + concptr desc; /* A verbose attack description */ + PLAYER_LEVEL min_level; /* Minimum level to use */ + int chance; /* Chance of 'success' */ + int dd; /* Damage dice */ + int ds; /* Damage sides */ + int effect; /* Special effects */ +} martial_arts; + +extern const martial_arts ma_blows[MAX_MA]; diff --git a/src/combat/shoot.c b/src/combat/shoot.c new file mode 100644 index 000000000..f24eca6b2 --- /dev/null +++ b/src/combat/shoot.c @@ -0,0 +1,1186 @@ +#include "combat/shoot.h" +#include "art-definition/art-bow-types.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/stuff-handler.h" +#include "effect/effect-characteristics.h" +#include "effect/effect-processor.h" +#include "effect/spells-effect-util.h" +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "floor/cave.h" +#include "floor/floor-object.h" +#include "game-option/cheat-types.h" +#include "game-option/special-options.h" +#include "grid/feature-flag-types.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "inventory/inventory-object.h" +#include "inventory/inventory-slot-types.h" +#include "io/cursor.h" +#include "io/screen-util.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "mind/mind-sniper.h" +#include "mind/snipe-types.h" +#include "monster-floor/monster-death.h" +#include "monster-floor/monster-move.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags-resistance.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags2.h" +#include "monster-race/race-flags3.h" +#include "monster-race/race-flags7.h" +#include "monster-race/race-indice-types.h" +#include "monster/monster-describer.h" +#include "monster/monster-info.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "monster/monster-update.h" +#include "object-enchant/tr-types.h" +#include "object-hook/hook-enchant.h" +#include "object/object-broken.h" +#include "object/object-flags.h" +#include "object/object-generator.h" +#include "object/object-info.h" +#include "object/object-kind.h" +#include "object/object-mark-types.h" +#include "player-info/avatar.h" +#include "player/player-class.h" +#include "player/player-personalities-types.h" +#include "player/player-skill.h" +#include "player/player-status.h" +#include "player/player-status-table.h" +#include "spell/spell-types.h" +#include "sv-definition/sv-bow-types.h" +#include "system/artifact-type-definition.h" +#include "system/floor-type-definition.h" +#include "target/projection-path-calculator.h" +#include "target/target-checker.h" +#include "target/target-getter.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" +#include "wizard/wizard-messages.h" +#include "world/world-object.h" + +/*! + * @brief 矢弾を射撃した際のスレイ倍率をかけた結果を返す / + * Determines the odds of an object breaking when thrown at a monster + * @param o_ptr 矢弾のオブジェクト構造体参照ポインタ + * @param tdam 計算途中のダメージ量 + * @param m_ptr 目標モンスターの構造体参照ポインタ + * @return スレイ倍率をかけたダメージ量 + */ +static MULTIPLY calc_shot_damage_with_slay(player_type *sniper_ptr, object_type *o_ptr, HIT_POINT tdam, monster_type *m_ptr, SPELL_IDX snipe_type) +{ + MULTIPLY mult = 10; + + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + + BIT_FLAGS flgs[TR_FLAG_SIZE]; + object_flags(sniper_ptr, o_ptr, flgs); + + /* Some "weapons" and "ammo" do extra damage */ + switch (o_ptr->tval) { + case TV_SHOT: + case TV_ARROW: + case TV_BOLT: { + if ((have_flag(flgs, TR_SLAY_ANIMAL)) && (r_ptr->flags3 & RF3_ANIMAL)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_ANIMAL; + } + if (mult < 17) + mult = 17; + } + + if ((have_flag(flgs, TR_KILL_ANIMAL)) && (r_ptr->flags3 & RF3_ANIMAL)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_ANIMAL; + } + if (mult < 27) + mult = 27; + } + + if ((have_flag(flgs, TR_SLAY_EVIL)) && (r_ptr->flags3 & RF3_EVIL)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_EVIL; + } + if (mult < 15) + mult = 15; + } + + if ((have_flag(flgs, TR_KILL_EVIL)) && (r_ptr->flags3 & RF3_EVIL)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_EVIL; + } + if (mult < 25) + mult = 25; + } + + if ((have_flag(flgs, TR_SLAY_HUMAN)) && (r_ptr->flags2 & RF2_HUMAN)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags2 |= RF2_HUMAN; + } + if (mult < 17) + mult = 17; + } + + if ((have_flag(flgs, TR_KILL_HUMAN)) && (r_ptr->flags2 & RF2_HUMAN)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags2 |= RF2_HUMAN; + } + if (mult < 27) + mult = 27; + } + + if ((have_flag(flgs, TR_SLAY_UNDEAD)) && (r_ptr->flags3 & RF3_UNDEAD)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_UNDEAD; + } + if (mult < 20) + mult = 20; + } + + if ((have_flag(flgs, TR_KILL_UNDEAD)) && (r_ptr->flags3 & RF3_UNDEAD)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_UNDEAD; + } + if (mult < 30) + mult = 30; + } + + if ((have_flag(flgs, TR_SLAY_DEMON)) && (r_ptr->flags3 & RF3_DEMON)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_DEMON; + } + if (mult < 20) + mult = 20; + } + + if ((have_flag(flgs, TR_KILL_DEMON)) && (r_ptr->flags3 & RF3_DEMON)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_DEMON; + } + if (mult < 30) + mult = 30; + } + + if ((have_flag(flgs, TR_SLAY_ORC)) && (r_ptr->flags3 & RF3_ORC)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_ORC; + } + if (mult < 20) + mult = 20; + } + + if ((have_flag(flgs, TR_KILL_ORC)) && (r_ptr->flags3 & RF3_ORC)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_ORC; + } + if (mult < 30) + mult = 30; + } + + if ((have_flag(flgs, TR_SLAY_TROLL)) && (r_ptr->flags3 & RF3_TROLL)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_TROLL; + } + + if (mult < 20) + mult = 20; + } + + if ((have_flag(flgs, TR_KILL_TROLL)) && (r_ptr->flags3 & RF3_TROLL)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_TROLL; + } + if (mult < 30) + mult = 30; + } + + if ((have_flag(flgs, TR_SLAY_GIANT)) && (r_ptr->flags3 & RF3_GIANT)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_GIANT; + } + if (mult < 20) + mult = 20; + } + + if ((have_flag(flgs, TR_KILL_GIANT)) && (r_ptr->flags3 & RF3_GIANT)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_GIANT; + } + if (mult < 30) + mult = 30; + } + + if ((have_flag(flgs, TR_SLAY_DRAGON)) && (r_ptr->flags3 & RF3_DRAGON)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_DRAGON; + } + if (mult < 20) + mult = 20; + } + + if ((have_flag(flgs, TR_KILL_DRAGON)) && (r_ptr->flags3 & RF3_DRAGON)) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_DRAGON; + } + if (mult < 30) + mult = 30; + if ((o_ptr->name1 == ART_BARD_ARROW) && (m_ptr->r_idx == MON_SMAUG) && (sniper_ptr->inventory_list[INVEN_BOW].name1 == ART_BARD)) + mult *= 5; + } + + if (have_flag(flgs, TR_BRAND_ACID)) { + /* Notice immunity */ + if (r_ptr->flagsr & RFR_EFF_IM_ACID_MASK) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_ACID_MASK); + } + } else { + if (mult < 17) + mult = 17; + } + } + + if (have_flag(flgs, TR_BRAND_ELEC)) { + /* Notice immunity */ + if (r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK); + } + } else { + if (mult < 17) + mult = 17; + } + } + + if (have_flag(flgs, TR_BRAND_FIRE)) { + /* Notice immunity */ + if (r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK); + } + } + /* Otherwise, take the damage */ + else { + if (r_ptr->flags3 & RF3_HURT_FIRE) { + if (mult < 25) + mult = 25; + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_HURT_FIRE; + } + } else if (mult < 17) + mult = 17; + } + } + + if (have_flag(flgs, TR_BRAND_COLD)) { + /* Notice immunity */ + if (r_ptr->flagsr & RFR_EFF_IM_COLD_MASK) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_COLD_MASK); + } + } + /* Otherwise, take the damage */ + else { + if (r_ptr->flags3 & RF3_HURT_COLD) { + if (mult < 25) + mult = 25; + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flags3 |= RF3_HURT_COLD; + } + } else if (mult < 17) + mult = 17; + } + } + + if (have_flag(flgs, TR_BRAND_POIS)) { + /* Notice immunity */ + if (r_ptr->flagsr & RFR_EFF_IM_POIS_MASK) { + if (is_original_ap_and_seen(sniper_ptr, m_ptr)) { + r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_POIS_MASK); + } + } + /* Otherwise, take the damage */ + else { + if (mult < 17) + mult = 17; + } + } + + if ((have_flag(flgs, TR_FORCE_WEAPON)) && (sniper_ptr->csp > (sniper_ptr->msp / 30))) { + sniper_ptr->csp -= (1 + (sniper_ptr->msp / 30)); + sniper_ptr->redraw |= (PR_MANA); + mult = mult * 5 / 2; + } + break; + } + } + + /* Sniper */ + if (snipe_type) + mult = calc_snipe_damage_with_slay(sniper_ptr, mult, m_ptr, snipe_type); + + /* Return the total damage */ + return (tdam * mult / 10); +} + +/*! + * @brief 射撃処理実行 / + * Fire an object from the pack or floor. + * @param item 射撃するオブジェクトの所持ID + * @param j_ptr 射撃武器のオブジェクト参照ポインタ + * @return なし + * @details + *
+ * You may only fire items that "match" your missile launcher.
+ * You must use slings + pebbles/shots, bows + arrows, xbows + bolts.
+ * See "calc_bonuses()" for more calculations and such.
+ * Note that "firing" a missile is MUCH better than "throwing" it.
+ * Note: "unseen" monsters are very hard to hit.
+ * Objects are more likely to break if they "attempt" to hit a monster.
+ * Rangers (with Bows) and Anyone (with "Extra Shots") get extra shots.
+ * The "extra shot" code works by decreasing the amount of energy
+ * required to make each shot, spreading the shots out over time.
+ * Note that when firing missiles, the launcher multiplier is applied
+ * after all the bonuses are added in, making multipliers very useful.
+ * Note that Bows of "Extra Might" get extra range and an extra bonus
+ * for the damage multiplier.
+ * Note that Bows of "Extra Shots" give an extra shot.
+ * 
+ */ +void exe_fire(player_type *shooter_ptr, INVENTORY_IDX item, object_type *j_ptr, SPELL_IDX snipe_type) +{ + DIRECTION dir; + int i; + POSITION y, x, ny, nx, ty, tx, prev_y, prev_x; + int tdam_base, tdis, thits, tmul; + int bonus, chance; + int cur_dis, visible; + PERCENTAGE j; + + object_type forge; + object_type *q_ptr; + + object_type *o_ptr; + + bool hit_body = FALSE; + + GAME_TEXT o_name[MAX_NLEN]; + + u16b path_g[512]; /* For calcuration of path length */ + + int msec = delay_factor * delay_factor * delay_factor; + + /* STICK TO */ + bool stick_to = FALSE; + + /* Access the item (if in the pack) */ + if (item >= 0) { + o_ptr = &shooter_ptr->inventory_list[item]; + } else { + o_ptr = &shooter_ptr->current_floor_ptr->o_list[0 - item]; + } + + /* Sniper - Cannot shot a single arrow twice */ + if ((snipe_type == SP_DOUBLE) && (o_ptr->number < 2)) + snipe_type = SP_NONE; + + describe_flavor(shooter_ptr, o_name, o_ptr, OD_OMIT_PREFIX); + + /* Use the proper number of shots */ + thits = shooter_ptr->num_fire; + + /* Use a base distance */ + tdis = 10; + + /* Base damage from thrown object plus launcher bonus */ + tdam_base = damroll(o_ptr->dd, o_ptr->ds) + o_ptr->to_d + j_ptr->to_d; + + /* Actually "fire" the object */ + bonus = (shooter_ptr->to_h_b + o_ptr->to_h + j_ptr->to_h); + if ((j_ptr->sval == SV_LIGHT_XBOW) || (j_ptr->sval == SV_HEAVY_XBOW)) + chance = (shooter_ptr->skill_thb + (shooter_ptr->weapon_exp[0][j_ptr->sval] / 400 + bonus) * BTH_PLUS_ADJ); + else + chance = (shooter_ptr->skill_thb + ((shooter_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + bonus) * BTH_PLUS_ADJ); + + shooter_ptr->energy_use = bow_energy(j_ptr->sval); + tmul = bow_tmul(j_ptr->sval); + + /* Get extra "power" from "extra might" */ + if (shooter_ptr->xtra_might) + tmul++; + + tmul = tmul * (100 + (int)(adj_str_td[shooter_ptr->stat_ind[A_STR]]) - 128); + + /* Boost the damage */ + tdam_base *= tmul; + tdam_base /= 100; + + /* Base range */ + tdis = 13 + tmul / 80; + if ((j_ptr->sval == SV_LIGHT_XBOW) || (j_ptr->sval == SV_HEAVY_XBOW)) { + if (shooter_ptr->concent) + tdis -= (5 - (shooter_ptr->concent + 1) / 2); + else + tdis -= 5; + } + + project_length = tdis + 1; + + /* Get a direction (or cancel) */ + if (!get_aim_dir(shooter_ptr, &dir)) { + free_turn(shooter_ptr); + + if (snipe_type == SP_AWAY) + snipe_type = SP_NONE; + + /* need not to reset project_length (already did)*/ + + return; + } + + /* Predict the "target" location */ + tx = shooter_ptr->x + 99 * ddx[dir]; + ty = shooter_ptr->y + 99 * ddy[dir]; + + /* Check for "target request" */ + if ((dir == 5) && target_okay(shooter_ptr)) { + tx = target_col; + ty = target_row; + } + + /* Get projection path length */ + tdis = projection_path(shooter_ptr, path_g, project_length, shooter_ptr->y, shooter_ptr->x, ty, tx, PROJECT_PATH | PROJECT_THRU) - 1; + + project_length = 0; /* reset to default */ + + /* Don't shoot at my feet */ + if (tx == shooter_ptr->x && ty == shooter_ptr->y) { + free_turn(shooter_ptr); + + /* project_length is already reset to 0 */ + + return; + } + + /* Take a (partial) turn */ + shooter_ptr->energy_use = (shooter_ptr->energy_use / thits); + shooter_ptr->is_fired = TRUE; + + /* Sniper - Difficult to shot twice at 1 turn */ + if (snipe_type == SP_DOUBLE) + shooter_ptr->concent = (shooter_ptr->concent + 1) / 2; + + /* Sniper - Repeat shooting when double shots */ + for (i = 0; i < ((snipe_type == SP_DOUBLE) ? 2 : 1); i++) { + + /* Start at the player */ + y = shooter_ptr->y; + x = shooter_ptr->x; + q_ptr = &forge; + object_copy(q_ptr, o_ptr); + + /* Single object */ + q_ptr->number = 1; + + vary_item(shooter_ptr, item, -1); + + sound(SOUND_SHOOT); + handle_stuff(shooter_ptr); + + prev_y = y; + prev_x = x; + + /* The shot does not hit yet */ + hit_body = FALSE; + + /* Travel until stopped */ + for (cur_dis = 0; cur_dis <= tdis;) { + grid_type *g_ptr; + + /* Hack -- Stop at the target */ + if ((y == ty) && (x == tx)) + break; + + /* Calculate the new location (see "project()") */ + ny = y; + nx = x; + mmove2(&ny, &nx, shooter_ptr->y, shooter_ptr->x, ty, tx); + + /* Shatter Arrow */ + if (snipe_type == SP_KILL_WALL) { + g_ptr = &shooter_ptr->current_floor_ptr->grid_array[ny][nx]; + + if (cave_have_flag_grid(g_ptr, FF_HURT_ROCK) && !g_ptr->m_idx) { + if (g_ptr->info & (CAVE_MARK)) + msg_print(_("岩が砕け散った。", "Wall rocks were shattered.")); + /* Forget the wall */ + g_ptr->info &= ~(CAVE_MARK); + shooter_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE); + + /* Destroy the wall */ + cave_alter_feat(shooter_ptr, ny, nx, FF_HURT_ROCK); + + hit_body = TRUE; + break; + } + } + + /* Stopped by walls/doors */ + if (!cave_have_flag_bold(shooter_ptr->current_floor_ptr, ny, nx, FF_PROJECT) && !shooter_ptr->current_floor_ptr->grid_array[ny][nx].m_idx) + break; + + /* Advance the distance */ + cur_dis++; + + /* Sniper */ + if (snipe_type == SP_LITE) { + shooter_ptr->current_floor_ptr->grid_array[ny][nx].info |= (CAVE_GLOW); + note_spot(shooter_ptr, ny, nx); + lite_spot(shooter_ptr, ny, nx); + } + + /* The player can see the (on screen) missile */ + if (panel_contains(ny, nx) && player_can_see_bold(shooter_ptr, ny, nx)) { + SYMBOL_CODE c = object_char(q_ptr); + byte a = object_attr(q_ptr); + + /* Draw, Hilite, Fresh, Pause, Erase */ + print_rel(shooter_ptr, c, a, ny, nx); + move_cursor_relative(ny, nx); + term_fresh(); + term_xtra(TERM_XTRA_DELAY, msec); + lite_spot(shooter_ptr, ny, nx); + term_fresh(); + } + + /* The player cannot see the missile */ + else { + /* Pause anyway, for consistancy */ + term_xtra(TERM_XTRA_DELAY, msec); + } + + /* Sniper */ + if (snipe_type == SP_KILL_TRAP) { + project(shooter_ptr, 0, 0, ny, nx, 0, GF_KILL_TRAP, (PROJECT_JUMP | PROJECT_HIDE | PROJECT_GRID | PROJECT_ITEM), -1); + } + + /* Sniper */ + if (snipe_type == SP_EVILNESS) { + shooter_ptr->current_floor_ptr->grid_array[ny][nx].info &= ~(CAVE_GLOW | CAVE_MARK); + note_spot(shooter_ptr, ny, nx); + lite_spot(shooter_ptr, ny, nx); + } + + prev_y = y; + prev_x = x; + + /* Save the new location */ + x = nx; + y = ny; + + /* Monster here, Try to hit it */ + if (shooter_ptr->current_floor_ptr->grid_array[y][x].m_idx) { + grid_type *c_mon_ptr = &shooter_ptr->current_floor_ptr->grid_array[y][x]; + + monster_type *m_ptr = &shooter_ptr->current_floor_ptr->m_list[c_mon_ptr->m_idx]; + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + + /* Check the visibility */ + visible = m_ptr->ml; + + /* Note the collision */ + hit_body = TRUE; + + if (monster_csleep_remaining(m_ptr)) { + if (!(r_ptr->flags3 & RF3_EVIL) || one_in_(5)) + chg_virtue(shooter_ptr, V_COMPASSION, -1); + if (!(r_ptr->flags3 & RF3_EVIL) || one_in_(5)) + chg_virtue(shooter_ptr, V_HONOUR, -1); + } + + if ((r_ptr->level + 10) > shooter_ptr->lev) { + int now_exp = shooter_ptr->weapon_exp[0][j_ptr->sval]; + if (now_exp < s_info[shooter_ptr->pclass].w_max[0][j_ptr->sval]) { + SUB_EXP amount = 0; + if (now_exp < WEAPON_EXP_BEGINNER) + amount = 80; + else if (now_exp < WEAPON_EXP_SKILLED) + amount = 25; + else if ((now_exp < WEAPON_EXP_EXPERT) && (shooter_ptr->lev > 19)) + amount = 10; + else if (shooter_ptr->lev > 34) + amount = 2; + shooter_ptr->weapon_exp[0][j_ptr->sval] += amount; + shooter_ptr->update |= (PU_BONUS); + } + } + + if (shooter_ptr->riding) { + if ((shooter_ptr->skill_exp[GINOU_RIDING] < s_info[shooter_ptr->pclass].s_max[GINOU_RIDING]) + && ((shooter_ptr->skill_exp[GINOU_RIDING] - (RIDING_EXP_BEGINNER * 2)) / 200 + < r_info[shooter_ptr->current_floor_ptr->m_list[shooter_ptr->riding].r_idx].level) + && one_in_(2)) { + shooter_ptr->skill_exp[GINOU_RIDING] += 1; + shooter_ptr->update |= (PU_BONUS); + } + } + + /* Did we hit it (penalize range) */ + if (test_hit_fire(shooter_ptr, chance - cur_dis, m_ptr, m_ptr->ml, o_name)) { + bool fear = FALSE; + int tdam = tdam_base; + + /* Get extra damage from concentration */ + if (shooter_ptr->concent) + tdam = boost_concentration_damage(shooter_ptr, tdam); + + /* Handle unseen monster */ + if (!visible) { + /* Invisible monster */ + msg_format(_("%sが敵を捕捉した。", "The %s finds a mark."), o_name); + } + + /* Handle visible monster */ + else { + GAME_TEXT m_name[MAX_NLEN]; + + /* Get "the monster" or "it" */ + monster_desc(shooter_ptr, m_name, m_ptr, 0); + + msg_format(_("%sが%sに命中した。", "The %s hits %s."), o_name, m_name); + + if (m_ptr->ml) { + if (!shooter_ptr->image) + monster_race_track(shooter_ptr, m_ptr->ap_r_idx); + health_track(shooter_ptr, c_mon_ptr->m_idx); + } + } + + if (snipe_type == SP_NEEDLE) { + if ((randint1(randint1(r_ptr->level / (3 + shooter_ptr->concent)) + (8 - shooter_ptr->concent)) == 1) && !(r_ptr->flags1 & RF1_UNIQUE) + && !(r_ptr->flags7 & RF7_UNIQUE2)) { + GAME_TEXT m_name[MAX_NLEN]; + + /* Get "the monster" or "it" */ + monster_desc(shooter_ptr, m_name, m_ptr, 0); + + tdam = m_ptr->hp + 1; + msg_format(_("%sの急所に突き刺さった!", "Your shot hit a fatal spot of %s!"), m_name); + } else + tdam = 1; + } else { + /* Apply special damage */ + tdam = calc_shot_damage_with_slay(shooter_ptr, q_ptr, tdam, m_ptr, snipe_type); + tdam = critical_shot(shooter_ptr, q_ptr->weight, q_ptr->to_h, j_ptr->to_h, tdam); + + /* No negative damage */ + if (tdam < 0) + tdam = 0; + + /* Modify the damage */ + tdam = mon_damage_mod(shooter_ptr, m_ptr, tdam, FALSE); + } + + msg_format_wizard(shooter_ptr, CHEAT_MONSTER, _("%dのダメージを与えた。(残りHP %d/%d(%d))", "You do %d damage. (left HP %d/%d(%d))"), tdam, + m_ptr->hp - tdam, m_ptr->maxhp, m_ptr->max_maxhp); + + /* Sniper */ + if (snipe_type == SP_EXPLODE) { + u16b flg = (PROJECT_STOP | PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID); + + sound(SOUND_EXPLODE); /* No explode sound - use breath fire instead */ + project(shooter_ptr, 0, ((shooter_ptr->concent + 1) / 2 + 1), ny, nx, tdam, GF_MISSILE, flg, -1); + break; + } + + /* Sniper */ + if (snipe_type == SP_HOLYNESS) { + shooter_ptr->current_floor_ptr->grid_array[ny][nx].info |= (CAVE_GLOW); + note_spot(shooter_ptr, ny, nx); + lite_spot(shooter_ptr, ny, nx); + } + + /* Hit the monster, check for death */ + if (mon_take_hit(shooter_ptr, c_mon_ptr->m_idx, tdam, &fear, extract_note_dies(real_r_idx(m_ptr)))) { + /* Dead monster */ + } + + /* No death */ + else { + /* STICK TO */ + if (object_is_fixed_artifact(q_ptr) && (shooter_ptr->pclass != CLASS_SNIPER || shooter_ptr->concent == 0)) { + GAME_TEXT m_name[MAX_NLEN]; + + monster_desc(shooter_ptr, m_name, m_ptr, 0); + + stick_to = TRUE; + msg_format(_("%sは%sに突き刺さった!", "%^s is stuck in %s!"), o_name, m_name); + } + + message_pain(shooter_ptr, c_mon_ptr->m_idx, tdam); + + /* Anger the monster */ + if (tdam > 0) + anger_monster(shooter_ptr, m_ptr); + + if (fear && m_ptr->ml) { + GAME_TEXT m_name[MAX_NLEN]; + sound(SOUND_FLEE); + monster_desc(shooter_ptr, m_name, m_ptr, 0); + msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), m_name); + } + + set_target(m_ptr, shooter_ptr->y, shooter_ptr->x); + + /* Sniper */ + if (snipe_type == SP_RUSH) { + int n = randint1(5) + 3; + MONSTER_IDX m_idx = c_mon_ptr->m_idx; + + for (; cur_dis <= tdis;) { + POSITION ox = nx; + POSITION oy = ny; + + if (!n) + break; + + /* Calculate the new location (see "project()") */ + mmove2(&ny, &nx, shooter_ptr->y, shooter_ptr->x, ty, tx); + + /* Stopped by wilderness boundary */ + if (!in_bounds2(shooter_ptr->current_floor_ptr, ny, nx)) + break; + + /* Stopped by walls/doors */ + if (!player_can_enter(shooter_ptr, shooter_ptr->current_floor_ptr->grid_array[ny][nx].feat, 0)) + break; + + /* Stopped by monsters */ + if (!is_cave_empty_bold(shooter_ptr, ny, nx)) + break; + + shooter_ptr->current_floor_ptr->grid_array[ny][nx].m_idx = m_idx; + shooter_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = 0; + + m_ptr->fx = nx; + m_ptr->fy = ny; + + update_monster(shooter_ptr, c_mon_ptr->m_idx, TRUE); + + lite_spot(shooter_ptr, ny, nx); + lite_spot(shooter_ptr, oy, ox); + + term_fresh(); + term_xtra(TERM_XTRA_DELAY, msec); + + x = nx; + y = ny; + cur_dis++; + n--; + } + } + } + } + + /* Sniper */ + if (snipe_type == SP_PIERCE) { + if (shooter_ptr->concent < 1) + break; + shooter_ptr->concent--; + continue; + } + + /* Stop looking */ + break; + } + } + + /* Chance of breakage (during attacks) */ + j = (hit_body ? breakage_chance(shooter_ptr, q_ptr, shooter_ptr->pclass == CLASS_ARCHER, snipe_type) : 0); + + if (stick_to) { + MONSTER_IDX m_idx = shooter_ptr->current_floor_ptr->grid_array[y][x].m_idx; + monster_type *m_ptr = &shooter_ptr->current_floor_ptr->m_list[m_idx]; + OBJECT_IDX o_idx = o_pop(shooter_ptr->current_floor_ptr); + + if (!o_idx) { + msg_format(_("%sはどこかへ行った。", "The %s went somewhere."), o_name); + if (object_is_fixed_artifact(q_ptr)) { + a_info[j_ptr->name1].cur_num = 0; + } + return; + } + + o_ptr = &shooter_ptr->current_floor_ptr->o_list[o_idx]; + object_copy(o_ptr, q_ptr); + + /* Forget mark */ + o_ptr->marked &= OM_TOUCHED; + + /* Forget location */ + o_ptr->iy = o_ptr->ix = 0; + + /* Memorize monster */ + o_ptr->held_m_idx = m_idx; + + /* Build a stack */ + o_ptr->next_o_idx = m_ptr->hold_o_idx; + + /* Carry object */ + m_ptr->hold_o_idx = o_idx; + } else if (cave_have_flag_bold(shooter_ptr->current_floor_ptr, y, x, FF_PROJECT)) { + /* Drop (or break) near that location */ + (void)drop_near(shooter_ptr, q_ptr, j, y, x); + } else { + /* Drop (or break) near that location */ + (void)drop_near(shooter_ptr, q_ptr, j, prev_y, prev_x); + } + + /* Sniper - Repeat shooting when double shots */ + } + + /* Sniper - Loose his/her concentration after any shot */ + if (shooter_ptr->concent) + reset_concentration(shooter_ptr, FALSE); +} + +/*! + * @brief プレイヤーからモンスターへの射撃命中判定 / + * Determine if the player "hits" a monster (normal combat). + * @param chance 基本命中値 + * @param m_ptr モンスターの構造体参照ポインタ + * @param vis 目標を視界に捕らえているならばTRUEを指定 + * @param o_name メッセージ表示時のモンスター名 + * @return 命中と判定された場合TRUEを返す + * @note Always miss 5%, always hit 5%, otherwise random. + */ +bool test_hit_fire(player_type *shooter_ptr, int chance, monster_type *m_ptr, int vis, char *o_name) +{ + int k; + ARMOUR_CLASS ac; + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + + /* Percentile dice */ + k = randint1(100); + + /* Snipers with high-concentration reduce instant miss percentage.*/ + k += shooter_ptr->concent; + + /* Hack -- Instant miss or hit */ + if (k <= 5) + return FALSE; + if (k > 95) + return TRUE; + + if (shooter_ptr->pseikaku == PERSONALITY_LAZY) + if (one_in_(20)) + return FALSE; + + /* Never hit */ + if (chance <= 0) + return FALSE; + + ac = r_ptr->ac; + if (shooter_ptr->concent) { + ac *= (8 - shooter_ptr->concent); + ac /= 8; + } + + if (m_ptr->r_idx == MON_GOEMON && !monster_csleep_remaining(m_ptr)) + ac *= 3; + + /* Invisible monsters are harder to hit */ + if (!vis) + chance = (chance + 1) / 2; + + /* Power competes against armor */ + if (randint0(chance) < (ac * 3 / 4)) { + if (m_ptr->r_idx == MON_GOEMON && !monster_csleep_remaining(m_ptr)) { + GAME_TEXT m_name[MAX_NLEN]; + monster_desc(shooter_ptr, m_name, m_ptr, 0); + msg_format(_("%sは%sを斬り捨てた!", "%s cuts down %s!"), m_name, o_name); + } + return FALSE; + } + + /* Assume hit */ + return TRUE; +} + +/*! + * @brief プレイヤーからモンスターへの射撃クリティカル判定 / + * Critical hits (from objects thrown by player) Factor in item weight, total plusses, and player level. + * @param weight 矢弾の重量 + * @param plus_ammo 矢弾の命中修正 + * @param plus_bow 弓の命中修正 + * @param dam 現在算出中のダメージ値 + * @return クリティカル修正が入ったダメージ値 + */ +HIT_POINT critical_shot(player_type *shooter_ptr, WEIGHT weight, int plus_ammo, int plus_bow, HIT_POINT dam) +{ + int i, k; + object_type *j_ptr = &shooter_ptr->inventory_list[INVEN_BOW]; + + /* Extract "shot" power */ + i = shooter_ptr->to_h_b + plus_ammo; + + if (shooter_ptr->tval_ammo == TV_BOLT) + i = (shooter_ptr->skill_thb + (shooter_ptr->weapon_exp[0][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ); + else + i = (shooter_ptr->skill_thb + ((shooter_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + i) * BTH_PLUS_ADJ); + + /* Snipers can shot more critically with crossbows */ + if (shooter_ptr->concent) + i += ((i * shooter_ptr->concent) / 5); + if ((shooter_ptr->pclass == CLASS_SNIPER) && (shooter_ptr->tval_ammo == TV_BOLT)) + i *= 2; + + /* Good bow makes more critical */ + i += plus_bow * 8 * (shooter_ptr->concent ? shooter_ptr->concent + 5 : 5); + + /* Critical hit */ + if (randint1(10000) <= i) { + k = weight * randint1(500); + + if (k < 900) { + msg_print(_("手ごたえがあった!", "It was a good hit!")); + dam += (dam / 2); + } else if (k < 1350) { + msg_print(_("かなりの手ごたえがあった!", "It was a great hit!")); + dam *= 2; + } else { + msg_print(_("会心の一撃だ!", "It was a superb hit!")); + dam *= 3; + } + } + + return (dam); +} + +/*! + * @brief 射撃武器の攻撃に必要な基本消費エネルギーを返す/Return bow energy + * @param sval 射撃武器のアイテム副分類ID + * @return 消費する基本エネルギー + */ +ENERGY bow_energy(OBJECT_SUBTYPE_VALUE sval) +{ + ENERGY energy = 10000; + + /* Analyze the launcher */ + switch (sval) { + /* Sling and ammo */ + case SV_SLING: { + energy = 8000; + break; + } + + /* Short Bow and Arrow */ + case SV_SHORT_BOW: { + energy = 10000; + break; + } + + /* Long Bow and Arrow */ + case SV_LONG_BOW: { + energy = 10000; + break; + } + + /* Bow of irresponsiblity and Arrow */ + case SV_NAMAKE_BOW: { + energy = 7777; + break; + } + + /* Light Crossbow and Bolt */ + case SV_LIGHT_XBOW: { + energy = 12000; + break; + } + + /* Heavy Crossbow and Bolt */ + case SV_HEAVY_XBOW: { + energy = 13333; + break; + } + } + + return (energy); +} + +/* + * Return bow tmul + */ +int bow_tmul(OBJECT_SUBTYPE_VALUE sval) +{ + int tmul = 0; + + /* Analyze the launcher */ + switch (sval) { + /* Sling and ammo */ + case SV_SLING: { + tmul = 2; + break; + } + + /* Short Bow and Arrow */ + case SV_SHORT_BOW: { + tmul = 2; + break; + } + + /* Long Bow and Arrow */ + case SV_LONG_BOW: { + tmul = 3; + break; + } + + /* Bow of irresponsiblity and Arrow */ + case SV_NAMAKE_BOW: { + tmul = 3; + break; + } + + /* Light Crossbow and Bolt */ + case SV_LIGHT_XBOW: { + tmul = 3; + break; + } + + /* Heavy Crossbow and Bolt */ + case SV_HEAVY_XBOW: { + tmul = 4; + break; + } + } + + return (tmul); +} + +/*! + * @brief 射撃時クリティカルによるダメージ期待値修正計算(スナイパーの集中処理と武器経験値) / critical happens at i / 10000 + * @param shooter_ptr 射撃を行うクリーチャー参照ポインタ + * @param plus_ammo 矢弾のダメージ修正 + * @param plus_bow 弓のダメージ修正 + * @return ダメージ期待値 + * @note 基本ダメージ量と重量はこの部位では計算に加わらない。 + */ +HIT_POINT calc_crit_ratio_shot(player_type *shooter_ptr, HIT_POINT plus_ammo, HIT_POINT plus_bow) +{ + HIT_POINT i; + object_type *j_ptr = &shooter_ptr->inventory_list[INVEN_BOW]; + + /* Extract "shot" power */ + i = shooter_ptr->to_h_b + plus_ammo; + + if (shooter_ptr->tval_ammo == TV_BOLT) + i = (shooter_ptr->skill_thb + (shooter_ptr->weapon_exp[0][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ); + else + i = (shooter_ptr->skill_thb + ((shooter_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + i) * BTH_PLUS_ADJ); + + /* Snipers can shot more critically with crossbows */ + if (shooter_ptr->concent) + i += ((i * shooter_ptr->concent) / 5); + if ((shooter_ptr->pclass == CLASS_SNIPER) && (shooter_ptr->tval_ammo == TV_BOLT)) + i *= 2; + + /* Good bow makes more critical */ + i += plus_bow * 8 * (shooter_ptr->concent ? shooter_ptr->concent + 5 : 5); + + if (i < 0) + i = 0; + + return i; +} + +/*! + * @brief 射撃時クリティカルによるダメージ期待値修正計算(重量依存部分) / critical happens at i / 10000 + * @param weight 武器の重量 + * @param plus_ammo 矢弾のダメージ修正 + * @param plus_bow 弓のダメージ修正 + * @param dam 基本ダメージ量 + * @return ダメージ期待値 + */ +HIT_POINT calc_expect_crit_shot(player_type *shooter_ptr, WEIGHT weight, int plus_ammo, int plus_bow, HIT_POINT dam) +{ + u32b num; + int i, k, crit; + i = calc_crit_ratio_shot(shooter_ptr, plus_ammo, plus_bow); + + k = 0; + num = 0; + + crit = MIN(500, 900 / weight); + num += dam * 3 / 2 * crit; + k = crit; + + crit = MIN(500, 1350 / weight); + crit -= k; + num += dam * 2 * crit; + k += crit; + + if (k < 500) { + crit = 500 - k; + num += dam * 3 * crit; + } + + num /= 500; + + num *= i; + num += (10000 - i) * dam; + num /= 10000; + + return num; +} + +/*! + * @brief 攻撃時クリティカルによるダメージ期待値修正計算(重量と毒針処理) / critical happens at i / 10000 + * @param shooter_ptr プレーヤーへの参照ポインタ + * @param weight 武器の重量 + * @param plus 武器のダメージ修正 + * @param dam 基本ダメージ + * @param meichuu 命中値 + * @param dokubari 毒針処理か否か + * @return ダメージ期待値 + */ +HIT_POINT calc_expect_crit(player_type *shooter_ptr, WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, bool dokubari) +{ + u32b k, num; + if (dokubari) + return dam; + + int i = (weight + (meichuu * 3 + plus * 5) + shooter_ptr->skill_thn); + if (i < 0) + i = 0; + + k = weight; + num = 0; + + if (k < 400) + num += (2 * dam + 5) * (400 - k); + if (k < 700) + num += (2 * dam + 10) * (MIN(700, k + 650) - MAX(400, k)); + if (k > (700 - 650) && k < 900) + num += (3 * dam + 15) * (MIN(900, k + 650) - MAX(700, k)); + if (k > (900 - 650) && k < 1300) + num += (3 * dam + 20) * (MIN(1300, k + 650) - MAX(900, k)); + if (k > (1300 - 650)) + num += (7 * dam / 2 + 25) * MIN(650, k - (1300 - 650)); + + num /= 650; + if (shooter_ptr->pclass == CLASS_NINJA) { + num *= i; + num += (4444 - i) * dam; + num /= 4444; + } else { + num *= i; + num += (5000 - i) * dam; + num /= 5000; + } + + return num; +} diff --git a/src/combat/shoot.h b/src/combat/shoot.h new file mode 100644 index 000000000..b0d4c9e81 --- /dev/null +++ b/src/combat/shoot.h @@ -0,0 +1,13 @@ +#pragma once + +#include "system/angband.h" +#include "system/monster-type-definition.h" + +bool test_hit_fire(player_type *shooter_ptr, int chance, monster_type *m_ptr, int vis, char* o_name); +HIT_POINT critical_shot(player_type *shooter_ptr, WEIGHT weight, int plus_ammo, int plus_bow, HIT_POINT dam); +ENERGY bow_energy(OBJECT_SUBTYPE_VALUE sval); +int bow_tmul(OBJECT_SUBTYPE_VALUE sval); +HIT_POINT calc_crit_ratio_shot(player_type *shooter_ptr, HIT_POINT plus_ammo, HIT_POINT plus_bow); +HIT_POINT calc_expect_crit_shot(player_type *shooter_ptr, WEIGHT weight, int plus_ammo, int plus_bow, HIT_POINT dam); +HIT_POINT calc_expect_crit(player_type *shooter_ptr, WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, bool dokubari); +void exe_fire(player_type *shooter_ptr, INVENTORY_IDX item, object_type *j_ptr, SPELL_IDX snipe_type); diff --git a/src/combat/slaying.c b/src/combat/slaying.c new file mode 100644 index 000000000..58d196ed0 --- /dev/null +++ b/src/combat/slaying.c @@ -0,0 +1,202 @@ +#include "combat/slaying.h" +#include "art-definition/art-sword-types.h" +#include "core/player-redraw-types.h" +#include "mind/mind-samurai.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags-resistance.h" +#include "monster-race/race-flags2.h" +#include "monster-race/race-flags3.h" +#include "monster-race/race-indice-types.h" +#include "monster/monster-info.h" +#include "object-enchant/tr-types.h" +#include "object/object-flags.h" +#include "player/attack-defense-types.h" +#include "realm/realm-hex-numbers.h" +#include "specific-object/torch.h" +#include "spell-realm/spells-hex.h" +#include "util/bit-flags-calculator.h" + +/*! + * @brief プレイヤー攻撃の種族スレイング倍率計算 + * @param player_ptr プレーヤーへの参照ポインタ + * @param mult 算出前の基本倍率(/10倍) + * @param flgs スレイフラグ配列 + * @param m_ptr 目標モンスターの構造体参照ポインタ + * @return スレイング加味後の倍率(/10倍) + */ +MULTIPLY mult_slaying(player_type *player_ptr, MULTIPLY mult, const BIT_FLAGS *flgs, monster_type *m_ptr) +{ + static const struct slay_table_t { + int slay_flag; + BIT_FLAGS affect_race_flag; + MULTIPLY slay_mult; + size_t flag_offset; + size_t r_flag_offset; + } slay_table[] = { +#define OFFSET(X) offsetof(monster_race, X) + { TR_SLAY_ANIMAL, RF3_ANIMAL, 25, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_KILL_ANIMAL, RF3_ANIMAL, 40, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_SLAY_EVIL, RF3_EVIL, 20, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_KILL_EVIL, RF3_EVIL, 35, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_SLAY_GOOD, RF3_GOOD, 20, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_KILL_GOOD, RF3_GOOD, 35, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_SLAY_HUMAN, RF2_HUMAN, 25, OFFSET(flags2), OFFSET(r_flags2) }, + { TR_KILL_HUMAN, RF2_HUMAN, 40, OFFSET(flags2), OFFSET(r_flags2) }, + { TR_SLAY_UNDEAD, RF3_UNDEAD, 30, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_KILL_UNDEAD, RF3_UNDEAD, 50, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_SLAY_DEMON, RF3_DEMON, 30, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_KILL_DEMON, RF3_DEMON, 50, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_SLAY_ORC, RF3_ORC, 30, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_KILL_ORC, RF3_ORC, 50, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_SLAY_TROLL, RF3_TROLL, 30, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_KILL_TROLL, RF3_TROLL, 50, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_SLAY_GIANT, RF3_GIANT, 30, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_KILL_GIANT, RF3_GIANT, 50, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_SLAY_DRAGON, RF3_DRAGON, 30, OFFSET(flags3), OFFSET(r_flags3) }, + { TR_KILL_DRAGON, RF3_DRAGON, 50, OFFSET(flags3), OFFSET(r_flags3) }, +#undef OFFSET + }; + + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + for (size_t i = 0; i < sizeof(slay_table) / sizeof(slay_table[0]); ++i) { + const struct slay_table_t *p = &slay_table[i]; + + if (!have_flag(flgs, p->slay_flag) || !(atoffset(BIT_FLAGS, r_ptr, p->flag_offset) & p->affect_race_flag)) + continue; + + if (is_original_ap_and_seen(player_ptr, m_ptr)) { + atoffset(BIT_FLAGS, r_ptr, p->r_flag_offset) |= p->affect_race_flag; + } + + mult = MAX(mult, p->slay_mult); + } + + return mult; +} + +/*! + * @brief プレイヤー攻撃の属性スレイング倍率計算 + * @param player_ptr プレーヤーへの参照ポインタ + * @param mult 算出前の基本倍率(/10倍) + * @param flgs スレイフラグ配列 + * @param m_ptr 目標モンスターの構造体参照ポインタ + * @return スレイング加味後の倍率(/10倍) + */ +MULTIPLY mult_brand(player_type *player_ptr, MULTIPLY mult, const BIT_FLAGS *flgs, monster_type *m_ptr) +{ + static const struct brand_table_t { + int brand_flag; + BIT_FLAGS resist_mask; + BIT_FLAGS hurt_flag; + } brand_table[] = { + { TR_BRAND_ACID, RFR_EFF_IM_ACID_MASK, 0U }, + { TR_BRAND_ELEC, RFR_EFF_IM_ELEC_MASK, 0U }, + { TR_BRAND_FIRE, RFR_EFF_IM_FIRE_MASK, RF3_HURT_FIRE }, + { TR_BRAND_COLD, RFR_EFF_IM_COLD_MASK, RF3_HURT_COLD }, + { TR_BRAND_POIS, RFR_EFF_IM_POIS_MASK, 0U }, + }; + + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + for (size_t i = 0; i < sizeof(brand_table) / sizeof(brand_table[0]); ++i) { + const struct brand_table_t *p = &brand_table[i]; + + if (!have_flag(flgs, p->brand_flag)) + continue; + + /* Notice immunity */ + if (r_ptr->flagsr & p->resist_mask) { + if (is_original_ap_and_seen(player_ptr, m_ptr)) { + r_ptr->r_flagsr |= (r_ptr->flagsr & p->resist_mask); + } + + continue; + } + + /* Otherwise, take the damage */ + if (r_ptr->flags3 & p->hurt_flag) { + if (is_original_ap_and_seen(player_ptr, m_ptr)) { + r_ptr->r_flags3 |= p->hurt_flag; + } + + mult = MAX(mult, 50); + continue; + } + + mult = MAX(mult, 25); + } + + return mult; +} + +/*! + * @brief ダメージにスレイ要素を加える総合処理ルーチン / + * Extract the "total damage" from a given object hitting a given monster. + * @param o_ptr 使用武器オブジェクトの構造体参照ポインタ + * @param tdam 現在算出途中のダメージ値 + * @param m_ptr 目標モンスターの構造体参照ポインタ + * @param mode 剣術のID + * @param thrown 投擲処理ならばTRUEを指定する + * @return 総合的なスレイを加味したダメージ値 + * @note + * Note that "flasks of oil" do NOT do fire damage, although they\n + * certainly could be made to do so. XXX XXX\n + *\n + * Note that most brands and slays are x3, except Slay Animal (x2),\n + * Slay Evil (x2), and Kill dragon (x5).\n + */ +HIT_POINT calc_attack_damage_with_slay(player_type *attacker_ptr, object_type *o_ptr, HIT_POINT tdam, monster_type *m_ptr, combat_options mode, bool thrown) +{ + BIT_FLAGS flgs[TR_FLAG_SIZE]; + object_flags(attacker_ptr, o_ptr, flgs); + torch_flags(o_ptr, flgs); /* torches has secret flags */ + + if (!thrown) { + if (attacker_ptr->special_attack & (ATTACK_ACID)) + add_flag(flgs, TR_BRAND_ACID); + if (attacker_ptr->special_attack & (ATTACK_COLD)) + add_flag(flgs, TR_BRAND_COLD); + if (attacker_ptr->special_attack & (ATTACK_ELEC)) + add_flag(flgs, TR_BRAND_ELEC); + if (attacker_ptr->special_attack & (ATTACK_FIRE)) + add_flag(flgs, TR_BRAND_FIRE); + if (attacker_ptr->special_attack & (ATTACK_POIS)) + add_flag(flgs, TR_BRAND_POIS); + } + + if (hex_spelling(attacker_ptr, HEX_RUNESWORD)) + add_flag(flgs, TR_SLAY_GOOD); + + MULTIPLY mult = 10; + switch (o_ptr->tval) { + case TV_SHOT: + case TV_ARROW: + case TV_BOLT: + case TV_HAFTED: + case TV_POLEARM: + case TV_SWORD: + case TV_DIGGING: + case TV_LITE: { + mult = mult_slaying(attacker_ptr, mult, flgs, m_ptr); + + mult = mult_brand(attacker_ptr, mult, flgs, m_ptr); + + if (attacker_ptr->pclass == CLASS_SAMURAI) { + mult = mult_hissatsu(attacker_ptr, mult, flgs, m_ptr, mode); + } + + if ((attacker_ptr->pclass != CLASS_SAMURAI) && (have_flag(flgs, TR_FORCE_WEAPON)) && (attacker_ptr->csp > (o_ptr->dd * o_ptr->ds / 5))) { + attacker_ptr->csp -= (1 + (o_ptr->dd * o_ptr->ds / 5)); + attacker_ptr->redraw |= (PR_MANA); + mult = mult * 3 / 2 + 20; + } + + if ((o_ptr->name1 == ART_NOTHUNG) && (m_ptr->r_idx == MON_FAFNER)) + mult = 150; + break; + } + } + + if (mult > 150) + mult = 150; + return (tdam * mult / 10); +} diff --git a/src/combat/slaying.h b/src/combat/slaying.h new file mode 100644 index 000000000..e0f81991f --- /dev/null +++ b/src/combat/slaying.h @@ -0,0 +1,10 @@ +#pragma once + +#include "system/angband.h" +#include "combat/combat-options-type.h" +#include "system/object-type-definition.h" +#include "system/monster-type-definition.h" + +MULTIPLY mult_slaying(player_type *player_ptr, MULTIPLY mult, const BIT_FLAGS *flgs, monster_type *m_ptr); +MULTIPLY mult_brand(player_type *player_ptr, MULTIPLY mult, const BIT_FLAGS *flgs, monster_type *m_ptr); +HIT_POINT calc_attack_damage_with_slay(player_type *attacker_ptr, object_type *o_ptr, HIT_POINT tdam, monster_type *m_ptr, combat_options mode, bool thrown); diff --git a/src/core/asking-player.c b/src/core/asking-player.c new file mode 100644 index 000000000..4d285ca92 --- /dev/null +++ b/src/core/asking-player.c @@ -0,0 +1,410 @@ +#include "core/asking-player.h" +#include "cmd-io/macro-util.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "game-option/input-options.h" +#include "io/command-repeater.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-requester.h" // todo 相互依存している、後で何とかする. +#include "main/sound-of-music.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/int-char-converter.h" +#include "util/string-processor.h" +#include "view/display-messages.h" + +/* + * Get some string input at the cursor location. + * Assume the buffer is initialized to a default string. + * + * The default buffer is in Overwrite mode and displayed in yellow at + * first. Normal chars clear the yellow text and append the char in + * white text. + * + * LEFT (^B) and RIGHT (^F) movement keys move the cursor position. + * If the text is still displayed in yellow (Overwite mode), it will + * turns into white (Insert mode) when cursor moves. + * + * DELETE (^D) deletes a char at the cursor position. + * BACKSPACE (^H) deletes a char at the left of cursor position. + * ESCAPE clears the buffer and the window and returns FALSE. + * RETURN accepts the current buffer contents and returns TRUE. + */ +bool askfor_aux(char *buf, int len, bool numpad_cursor) +{ + /* + * Text color + * TERM_YELLOW : Overwrite mode + * TERM_WHITE : Insert mode + */ + byte color = TERM_YELLOW; + + int y, x; + term_locate(&x, &y); + if (len < 1) + len = 1; + if ((x < 0) || (x >= 80)) + x = 0; + if (x + len > 80) + len = 80 - x; + + buf[len] = '\0'; + + int pos = 0; + while (TRUE) { + term_erase(x, y, len); + term_putstr(x, y, -1, color, buf); + + term_gotoxy(x + pos, y); + int skey = inkey_special(numpad_cursor); + + switch (skey) { + case SKEY_LEFT: + case KTRL('b'): { + int i = 0; + color = TERM_WHITE; + + if (0 == pos) + break; + while (TRUE) { + int next_pos = i + 1; +#ifdef JP + if (iskanji(buf[i])) + next_pos++; +#endif + if (next_pos >= pos) + break; + + i = next_pos; + } + + pos = i; + break; + } + + case SKEY_RIGHT: + case KTRL('f'): + color = TERM_WHITE; + if ('\0' == buf[pos]) + break; + +#ifdef JP + if (iskanji(buf[pos])) + pos += 2; + else + pos++; +#else + pos++; +#endif + break; + + case ESCAPE: + buf[0] = '\0'; + return FALSE; + + case '\n': + case '\r': + return TRUE; + + case '\010': { + int i = 0; + color = TERM_WHITE; + if (0 == pos) + break; + while (TRUE) { + int next_pos = i + 1; +#ifdef JP + if (iskanji(buf[i])) + next_pos++; +#endif + if (next_pos >= pos) + break; + + i = next_pos; + } + + pos = i; + } + /* Fall through */ + + case 0x7F: + case KTRL('d'): { + color = TERM_WHITE; + if ('\0' == buf[pos]) + break; + int src = pos + 1; +#ifdef JP + if (iskanji(buf[pos])) + src++; +#endif + + int dst = pos; + while ('\0' != (buf[dst++] = buf[src++])) + ; + break; + } + + default: { + char tmp[100]; + if (skey & SKEY_MASK) + break; + char c = (char)skey; + + if (color == TERM_YELLOW) { + buf[0] = '\0'; + color = TERM_WHITE; + } + + strcpy(tmp, buf + pos); +#ifdef JP + if (iskanji(c)) { + inkey_base = TRUE; + char next = inkey(); + if (pos + 1 < len) { + buf[pos++] = c; + buf[pos++] = next; + } else { + bell(); + } + } else +#endif + { +#ifdef JP + if (pos < len && (isprint(c) || iskana(c))) +#else + if (pos < len && isprint(c)) +#endif + { + buf[pos++] = c; + } else { + bell(); + } + } + + buf[pos] = '\0'; + angband_strcat(buf, tmp, len + 1); + + break; + } + } + } +} + +/* + * Get some string input at the cursor location. + * + * Allow to use numpad keys as cursor keys. + */ +bool askfor(char *buf, int len) { return askfor_aux(buf, len, TRUE); } + +/* + * Get a string from the user + * + * The "prompt" should take the form "Prompt: " + * + * Note that the initial contents of the string is used as + * the default response, so be sure to "clear" it if needed. + * + * We clear the input, and return FALSE, on "ESCAPE". + */ +bool get_string(concptr prompt, char *buf, int len) +{ + bool res; + msg_print(NULL); + prt(prompt, 0, 0); + res = askfor(buf, len); + prt("", 0, 0); + return (res); +} + +/* + * Verify something with the user + * + * The "prompt" should take the form "Query? " + * + * Note that "[y/n]" is appended to the prompt. + */ +bool get_check(concptr prompt) { return get_check_strict(p_ptr, prompt, 0); } + +/* + * Verify something with the user strictly + * + * mode & CHECK_OKAY_CANCEL : force user to answer 'O'kay or 'C'ancel + * mode & CHECK_NO_ESCAPE : don't allow ESCAPE key + * mode & CHECK_NO_HISTORY : no message_add + * mode & CHECK_DEFAULT_Y : accept any key as y, except n and Esc. + */ +bool get_check_strict(player_type *player_ptr, concptr prompt, BIT_FLAGS mode) +{ + char buf[80]; + if (auto_more) { + player_ptr->window |= PW_MESSAGE; + handle_stuff(player_ptr); + num_more = 0; + } + + msg_print(NULL); + if (!rogue_like_commands) + mode &= ~CHECK_OKAY_CANCEL; + + if (mode & CHECK_OKAY_CANCEL) { + angband_strcpy(buf, prompt, sizeof(buf) - 15); + strcat(buf, "[(O)k/(C)ancel]"); + } else if (mode & CHECK_DEFAULT_Y) { + angband_strcpy(buf, prompt, sizeof(buf) - 5); + strcat(buf, "[Y/n]"); + } else { + angband_strcpy(buf, prompt, sizeof(buf) - 5); + strcat(buf, "[y/n]"); + } + + prt(buf, 0, 0); + if (!(mode & CHECK_NO_HISTORY) && player_ptr->playing) { + message_add(buf); + player_ptr->window |= (PW_MESSAGE); + handle_stuff(player_ptr); + } + + bool flag = FALSE; + while (TRUE) { + int i = inkey(); + + if (!(mode & CHECK_NO_ESCAPE)) { + if (i == ESCAPE) { + flag = FALSE; + break; + } + } + + if (mode & CHECK_OKAY_CANCEL) { + if (i == 'o' || i == 'O') { + flag = TRUE; + break; + } else if (i == 'c' || i == 'C') { + flag = FALSE; + break; + } + } else { + if (i == 'y' || i == 'Y') { + flag = TRUE; + break; + } else if (i == 'n' || i == 'N') { + flag = FALSE; + break; + } + } + + if (mode & CHECK_DEFAULT_Y) { + flag = TRUE; + break; + } + + bell(); + } + + prt("", 0, 0); + return flag; +} + +/* + * Prompts for a keypress + * + * The "prompt" should take the form "Command: " + * + * Returns TRUE unless the character is "Escape" + */ +bool get_com(concptr prompt, char *command, bool z_escape) +{ + msg_print(NULL); + prt(prompt, 0, 0); + if (get_com_no_macros) + *command = (char)inkey_special(FALSE); + else + *command = inkey(); + + prt("", 0, 0); + if (*command == ESCAPE) + return FALSE; + if (z_escape && ((*command == 'z') || (*command == 'Z'))) + return FALSE; + + return TRUE; +} + +/* + * Request a "quantity" from the user + * + * Hack -- allow "command_arg" to specify a quantity + */ +QUANTITY get_quantity(concptr prompt, QUANTITY max) +{ + bool res; + char tmp[80]; + char buf[80]; + + QUANTITY amt; + if (command_arg) { + amt = command_arg; + command_arg = 0; + if (amt > max) + amt = max; + + return (amt); + } + + COMMAND_CODE code; + bool result = repeat_pull(&code); + amt = (QUANTITY)code; + if ((max != 1) && result) { + if (amt > max) + amt = max; + if (amt < 0) + amt = 0; + + return (amt); + } + + if (!prompt) { + sprintf(tmp, _("いくつですか (1-%d): ", "Quantity (1-%d): "), max); + prompt = tmp; + } + + msg_print(NULL); + prt(prompt, 0, 0); + amt = 1; + sprintf(buf, "%d", amt); + + /* + * Ask for a quantity + * Don't allow to use numpad as cursor key. + */ + res = askfor_aux(buf, 6, FALSE); + + prt("", 0, 0); + if (!res) + return 0; + + amt = (COMMAND_CODE)atoi(buf); + if (isalpha(buf[0])) + amt = max; + if (amt > max) + amt = max; + if (amt < 0) + amt = 0; + if (amt) + repeat_push((COMMAND_CODE)amt); + + return (amt); +} + +/* + * Pause for user response + */ +void pause_line(int row) +{ + prt("", row, 0); + put_str(_("[ 何かキーを押して下さい ]", "[Press any key to continue]"), row, _(26, 23)); + + (void)inkey(); + prt("", row, 0); +} diff --git a/src/core/asking-player.h b/src/core/asking-player.h new file mode 100644 index 000000000..535522d54 --- /dev/null +++ b/src/core/asking-player.h @@ -0,0 +1,20 @@ +#pragma once + +#include "system/angband.h" + +/* + * Bit flags for control of get_check_strict() + */ +#define CHECK_OKAY_CANCEL 0x01 +#define CHECK_NO_ESCAPE 0x02 +#define CHECK_NO_HISTORY 0x04 +#define CHECK_DEFAULT_Y 0x08 + +bool askfor_aux(char *buf, int len, bool numpad_cursor); +bool askfor(char *buf, int len); +bool get_string(concptr prompt, char *buf, int len); +bool get_check(concptr prompt); +bool get_check_strict(player_type *player_ptr, concptr prompt, BIT_FLAGS mode); +bool get_com(concptr prompt, char *command, bool z_escape); +QUANTITY get_quantity(concptr prompt, QUANTITY max); +void pause_line(int row); diff --git a/src/core/disturbance.c b/src/core/disturbance.c new file mode 100644 index 000000000..3bc25db9d --- /dev/null +++ b/src/core/disturbance.c @@ -0,0 +1,48 @@ +#include "core/disturbance.h" +#include "action/travel-execution.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "game-option/disturbance-options.h" +#include "game-option/map-screen-options.h" +#include "io/input-key-requester.h" +#include "player/attack-defense-types.h" +#include "status/action-setter.h" +#include "target/target-checker.h" +#include "term/screen-processor.h" + +/* + * Something has happened to disturb the player. + * The first arg indicates a major disturbance, which affects search. + * The second arg is currently unused, but could induce output flush. + * All disturbance cancels repeated commands, resting, and running. + */ +void disturb(player_type *creature_ptr, bool stop_search, bool stop_travel) +{ + if (command_rep) { + command_rep = 0; + creature_ptr->redraw |= PR_STATE; + } + + if ((creature_ptr->action == ACTION_REST) || (creature_ptr->action == ACTION_FISH) || (stop_search && (creature_ptr->action == ACTION_SEARCH))) + set_action(creature_ptr, ACTION_NONE); + + if (creature_ptr->running) { + creature_ptr->running = 0; + if (center_player && !center_running) + verify_panel(creature_ptr); + + creature_ptr->update |= PU_TORCH; + creature_ptr->update |= PU_FLOW; + } + + if (stop_travel) { + travel.run = 0; + if (center_player && !center_running) + verify_panel(creature_ptr); + + creature_ptr->update |= PU_TORCH; + } + + if (flush_disturb) + flush(); +} diff --git a/src/core/disturbance.h b/src/core/disturbance.h new file mode 100644 index 000000000..2a8b66cec --- /dev/null +++ b/src/core/disturbance.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void disturb(player_type *creature_ptr, bool stop_search, bool flush_output); diff --git a/src/core/game-closer.c b/src/core/game-closer.c new file mode 100644 index 000000000..91b2b1c5c --- /dev/null +++ b/src/core/game-closer.c @@ -0,0 +1,109 @@ +#include "core/game-closer.h" +#include "cmd-io/cmd-save.h" +#include "core/asking-player.h" +#include "core/scores.h" +#include "core/stuff-handler.h" +#include "game-option/cheat-options.h" +#include "io/input-key-acceptor.h" +#include "io/signal-handlers.h" +#include "io/uid-checker.h" +#include "main/music-definitions-table.h" +#include "main/sound-of-music.h" +#include "player/process-death.h" +#include "save/save.h" +#include "term/screen-processor.h" +#include "util/angband-files.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" +#include "view/display-player.h" +#include "world/world.h" + +static void clear_floor(player_type *player_ptr) +{ + (void)fd_close(highscore_fd); + highscore_fd = -1; + clear_saved_floor_files(player_ptr); + signals_handle_tstp(); +} + +static void send_world_score_on_closing(player_type *player_ptr, bool do_send) +{ + if (send_world_score(player_ptr, do_send, update_playtime, display_player)) + return; + + if (!get_check_strict( + player_ptr, _("後でスコアを登録するために待機しますか?", "Stand by for later score registration? "), (CHECK_NO_ESCAPE | CHECK_NO_HISTORY))) + return; + + player_ptr->wait_report_score = TRUE; + player_ptr->is_dead = FALSE; + if (!save_player(player_ptr)) + msg_print(_("セーブ失敗!", "death save failed!")); +} + +static bool check_death(player_type *player_ptr) +{ + if (player_ptr->is_dead) + return TRUE; + + do_cmd_save_game(player_ptr, FALSE); + prt(_("リターンキーか ESC キーを押して下さい。", "Press Return (or Escape)."), 0, 40); + play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_EXIT); + if (inkey() != ESCAPE) + predict_score(player_ptr); + + clear_floor(player_ptr); + return FALSE; +} + +/*! + * @brief ゲーム終了処理 / + * Close up the current game (player may or may not be dead) + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + * @details + *
+ * This function is called only from "main.c" and "signals.c".
+ * 
+ */ +void close_game(player_type *player_ptr) +{ + bool do_send = TRUE; + handle_stuff(player_ptr); + msg_print(NULL); + flush(); + signals_ignore_tstp(); + + current_world_ptr->character_icky = TRUE; + char buf[1024]; + path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); + safe_setuid_grab(player_ptr); + highscore_fd = fd_open(buf, O_RDWR); + safe_setuid_drop(); + + if (!check_death(player_ptr)) + return; + + if (current_world_ptr->total_winner) + kingly(player_ptr); + + if (!cheat_save || get_check(_("死んだデータをセーブしますか? ", "Save death? "))) { + if (!save_player(player_ptr)) + msg_print(_("セーブ失敗!", "death save failed!")); + } else + do_send = FALSE; + + print_tomb(player_ptr); + flush(); + show_death_info(player_ptr, update_playtime, display_player); + term_clear(); + if (check_score(player_ptr)) { + send_world_score_on_closing(player_ptr, do_send); + if (!player_ptr->wait_report_score) + (void)top_twenty(player_ptr); + } else if (highscore_fd >= 0) { + display_scores_aux(0, 10, -1, NULL); + } + + clear_floor(player_ptr); +} diff --git a/src/core/game-closer.h b/src/core/game-closer.h new file mode 100644 index 000000000..010e2df7b --- /dev/null +++ b/src/core/game-closer.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void close_game(player_type* player_ptr); diff --git a/src/core/game-play.c b/src/core/game-play.c new file mode 100644 index 000000000..a2f93d9de --- /dev/null +++ b/src/core/game-play.c @@ -0,0 +1,391 @@ +/*! + * @brief ゲームプレイのメインルーチン + * @date 2020/05/10 + * @author Hourier + * @details + * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + * 2013 Deskull rearranged comment for Doxygen. + */ + +#include "core/game-play.h" +#include "autopick/autopick-pref-processor.h" +#include "birth/character-builder.h" +#include "birth/inventory-initializer.h" +#include "cmd-io/cmd-gameoption.h" +#include "core/asking-player.h" +#include "core/game-closer.h" +#include "core/output-updater.h" +#include "core/player-processor.h" +#include "core/player-update-types.h" +#include "core/scores.h" +#include "core/speed-table.h" +#include "core/status-reseter.h" +#include "core/stuff-handler.h" +#include "core/visuals-reseter.h" +#include "core/window-redrawer.h" +#include "dungeon/dungeon-processor.h" +#include "flavor/object-flavor.h" +#include "floor/cave.h" +#include "floor/floor-changer.h" +#include "floor/floor-events.h" +#include "floor/floor-leaver.h" +#include "floor/floor-mode-changer.h" +#include "floor/floor-util.h" +#include "floor/wild.h" +#include "game-option/cheat-options.h" +#include "game-option/input-options.h" +#include "game-option/play-record-options.h" +#include "game-option/runtime-arguments.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "info-reader/fixed-map-parser.h" +#include "io/chuukei.h" +#include "io/inet.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-processor.h" +#include "io/read-pref-file.h" +#include "io/screen-util.h" +#include "io/signal-handlers.h" +#include "io/write-diary.h" +#include "load/load.h" +#include "main/sound-of-music.h" +#include "market/arena-info-table.h" +#include "market/bounty.h" +#include "monster-floor/monster-generator.h" +#include "monster-floor/monster-remover.h" +#include "monster-floor/monster-lite.h" +#include "monster-floor/place-monster-types.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-indice-types.h" +#include "monster/monster-util.h" +#include "player/player-class.h" +#include "player/player-personalities-types.h" +#include "player/player-race-types.h" +#include "player/player-skill.h" +#include "player/process-name.h" +#include "racial/racial-android.h" +#include "realm/realm-names-table.h" +#include "save/save.h" +#include "spell/spells-status.h" +#include "spell/technic-info-table.h" +#include "store/home.h" +#include "store/store-util.h" +#include "store/store.h" +#include "sv-definition/sv-weapon-types.h" +#include "system/angband-version.h" +#include "system/floor-type-definition.h" +#include "system/system-variables.h" +#include "target/target-checker.h" +#include "term/gameterm.h" +#include "term/screen-processor.h" +#include "util/angband-files.h" +#include "view/display-messages.h" +#include "view/display-player.h" +#include "window/main-window-util.h" +#include "world/world.h" + +/*! + * @brief 1ゲームプレイの主要ルーチン / Actually play a game + * @return なし + * @note + * If the "new_game" parameter is true, then, after loading the + * savefile, we will commit suicide, if necessary, to allow the + * player to start a new game. + */ +void play_game(player_type *player_ptr, bool new_game) +{ + bool load_game = TRUE; + bool init_random_seed = FALSE; + +#ifdef CHUUKEI + if (chuukei_client) { + reset_visuals(player_ptr, process_autopick_file_command); + browse_chuukei(); + return; + } + + else if (chuukei_server) { + prepare_chuukei_hooks(); + } +#endif + + if (browsing_movie) { + reset_visuals(player_ptr, process_autopick_file_command); + browse_movie(); + return; + } + + player_ptr->hack_mutation = FALSE; + current_world_ptr->character_icky = TRUE; + term_activate(angband_term[0]); + angband_term[0]->resize_hook = resize_map; + for (MONSTER_IDX i = 1; i < 8; i++) { + if (angband_term[i]) { + angband_term[i]->resize_hook = redraw_window; + } + } + + (void)term_set_cursor(0); + if (!load_savedata(player_ptr)) { + quit(_("セーブファイルが壊れています", "broken savefile")); + } + + extract_option_vars(); + if (player_ptr->wait_report_score) { + char buf[1024]; + bool success; + + if (!get_check_strict(player_ptr, _("待機していたスコア登録を今行ないますか?", "Do you register score now? "), CHECK_NO_HISTORY)) + quit(0); + + player_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS); + update_creature(player_ptr); + player_ptr->is_dead = TRUE; + current_world_ptr->start_time = (u32b)time(NULL); + signals_ignore_tstp(); + current_world_ptr->character_icky = TRUE; + path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); + highscore_fd = fd_open(buf, O_RDWR); + + /* 町名消失バグ対策(#38205)のためここで世界マップ情報を読み出す */ + parse_fixed_map(player_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x); + success = send_world_score(player_ptr, TRUE, update_playtime, display_player); + + if (!success && !get_check_strict(player_ptr, _("スコア登録を諦めますか?", "Do you give up score registration? "), CHECK_NO_HISTORY)) { + prt(_("引き続き待機します。", "standing by for future registration..."), 0, 0); + (void)inkey(); + } else { + player_ptr->wait_report_score = FALSE; + top_twenty(player_ptr); + if (!save_player(player_ptr)) + msg_print(_("セーブ失敗!", "death save failed!")); + } + + (void)fd_close(highscore_fd); + highscore_fd = -1; + signals_handle_tstp(); + + quit(0); + } + + current_world_ptr->creating_savefile = new_game; + + if (!current_world_ptr->character_loaded) { + new_game = TRUE; + current_world_ptr->character_dungeon = FALSE; + init_random_seed = TRUE; + init_saved_floors(player_ptr, FALSE); + } else if (new_game) { + init_saved_floors(player_ptr, TRUE); + } + + if (!new_game) { + process_player_name(player_ptr, FALSE); + } + + if (init_random_seed) { + Rand_state_init(); + } + + floor_type *floor_ptr = player_ptr->current_floor_ptr; + if (new_game) { + current_world_ptr->character_dungeon = FALSE; + + floor_ptr->dun_level = 0; + floor_ptr->inside_quest = 0; + floor_ptr->inside_arena = FALSE; + player_ptr->phase_out = FALSE; + write_level = TRUE; + + current_world_ptr->seed_flavor = randint0(0x10000000); + current_world_ptr->seed_town = randint0(0x10000000); + + player_birth(player_ptr, process_autopick_file_command); + counts_write(player_ptr, 2, 0); + player_ptr->count = 0; + load = FALSE; + determine_bounty_uniques(player_ptr); + determine_daily_bounty(player_ptr, FALSE); + wipe_o_list(floor_ptr); + } else { + write_level = FALSE; + exe_write_diary( + player_ptr, DIARY_GAMESTART, 1, _(" ----ゲーム再開----", " --- Restarted Game ---")); + + /* + * todo もう2.2.Xなので互換性は打ち切ってもいいのでは? + * 1.0.9 以前はセーブ前に player_ptr->riding = -1 としていたので、再設定が必要だった。 + * もう不要だが、以前のセーブファイルとの互換のために残しておく。 + */ + if (player_ptr->riding == -1) { + player_ptr->riding = 0; + for (MONSTER_IDX i = floor_ptr->m_max; i > 0; i--) { + if (player_bold(player_ptr, floor_ptr->m_list[i].fy, floor_ptr->m_list[i].fx)) { + player_ptr->riding = i; + break; + } + } + } + } + + current_world_ptr->creating_savefile = FALSE; + + player_ptr->teleport_town = FALSE; + player_ptr->sutemi = FALSE; + current_world_ptr->timewalk_m_idx = 0; + player_ptr->now_damaged = FALSE; + now_message = 0; + current_world_ptr->start_time = time(NULL) - 1; + record_o_name[0] = '\0'; + + panel_row_min = floor_ptr->height; + panel_col_min = floor_ptr->width; + if (player_ptr->pseikaku == PERSONALITY_SEXY) + s_info[player_ptr->pclass].w_max[TV_HAFTED - TV_WEAPON_BEGIN][SV_WHIP] = WEAPON_EXP_MASTER; + + set_floor_and_wall(player_ptr->dungeon_idx); + flavor_init(); + prt(_("お待ち下さい...", "Please wait..."), 0, 0); + term_fresh(); + + if (arg_wizard) { + if (enter_wizard_mode(player_ptr)) { + current_world_ptr->wizard = TRUE; + + if (player_ptr->is_dead || !player_ptr->y || !player_ptr->x) { + init_saved_floors(player_ptr, TRUE); + floor_ptr->inside_quest = 0; + player_ptr->y = player_ptr->x = 10; + } + } else if (player_ptr->is_dead) { + quit("Already dead."); + } + } + + if (!floor_ptr->dun_level && !floor_ptr->inside_quest) { + parse_fixed_map(player_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x); + init_flags = INIT_ONLY_BUILDINGS; + parse_fixed_map(player_ptr, "t_info.txt", 0, 0, MAX_HGT, MAX_WID); + select_floor_music(player_ptr); + } + + if (!current_world_ptr->character_dungeon) { + change_floor(player_ptr); + } else { + if (player_ptr->panic_save) { + if (!player_ptr->y || !player_ptr->x) { + msg_print(_("プレイヤーの位置がおかしい。フロアを再生成します。", "What a strange player location, regenerate the dungeon floor.")); + change_floor(player_ptr); + } + + if (!player_ptr->y || !player_ptr->x) + player_ptr->y = player_ptr->x = 10; + + player_ptr->panic_save = 0; + } + } + + current_world_ptr->character_generated = TRUE; + current_world_ptr->character_icky = FALSE; + + if (new_game) { + char buf[80]; + sprintf(buf, _("%sに降り立った。", "arrived in %s."), map_name(player_ptr)); + exe_write_diary(player_ptr, DIARY_DESCRIPTION, 0, buf); + } + + player_ptr->playing = TRUE; + reset_visuals(player_ptr, process_autopick_file_command); + load_all_pref_files(player_ptr); + if (new_game) { + player_outfit(player_ptr); + } + + term_xtra(TERM_XTRA_REACT, 0); + + player_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER); + player_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_DUNGEON | PW_MONSTER | PW_OBJECT); + handle_stuff(player_ptr); + + if (arg_force_original) + rogue_like_commands = FALSE; + if (arg_force_roguelike) + rogue_like_commands = TRUE; + + if (player_ptr->chp < 0) + player_ptr->is_dead = TRUE; + + if (player_ptr->prace == RACE_ANDROID) + calc_android_exp(player_ptr); + + if (new_game && ((player_ptr->pclass == CLASS_CAVALRY) || (player_ptr->pclass == CLASS_BEASTMASTER))) { + monster_type *m_ptr; + MONRACE_IDX pet_r_idx = ((player_ptr->pclass == CLASS_CAVALRY) ? MON_HORSE : MON_YASE_HORSE); + monster_race *r_ptr = &r_info[pet_r_idx]; + place_monster_aux(player_ptr, 0, player_ptr->y, player_ptr->x - 1, pet_r_idx, (PM_FORCE_PET | PM_NO_KAGE)); + m_ptr = &floor_ptr->m_list[hack_m_idx_ii]; + m_ptr->mspeed = r_ptr->speed; + m_ptr->maxhp = r_ptr->hdice * (r_ptr->hside + 1) / 2; + m_ptr->max_maxhp = m_ptr->maxhp; + m_ptr->hp = r_ptr->hdice * (r_ptr->hside + 1) / 2; + m_ptr->dealt_damage = 0; + m_ptr->energy_need = ENERGY_NEED() + ENERGY_NEED(); + } + + (void)combine_and_reorder_home(player_ptr, STORE_HOME); + (void)combine_and_reorder_home(player_ptr, STORE_MUSEUM); + select_floor_music(player_ptr); + + while (TRUE) { + process_dungeon(player_ptr, load_game); + current_world_ptr->character_xtra = TRUE; + handle_stuff(player_ptr); + + current_world_ptr->character_xtra = FALSE; + target_who = 0; + health_track(player_ptr, 0); + forget_lite(floor_ptr); + forget_view(floor_ptr); + clear_mon_lite(floor_ptr); + if (!player_ptr->playing && !player_ptr->is_dead) + break; + + wipe_o_list(floor_ptr); + if (!player_ptr->is_dead) + wipe_monsters_list(player_ptr); + + msg_print(NULL); + load_game = FALSE; + if (player_ptr->playing && player_ptr->is_dead) { + if (floor_ptr->inside_arena) { + floor_ptr->inside_arena = FALSE; + if (player_ptr->arena_number > MAX_ARENA_MONS) + player_ptr->arena_number++; + else + player_ptr->arena_number = -1 - player_ptr->arena_number; + player_ptr->is_dead = FALSE; + player_ptr->chp = 0; + player_ptr->chp_frac = 0; + player_ptr->exit_bldg = TRUE; + reset_tim_flags(player_ptr); + prepare_change_floor_mode(player_ptr, CFM_SAVE_FLOORS | CFM_RAND_CONNECT); + leave_floor(player_ptr); + } else { + if ((current_world_ptr->wizard || cheat_live) && !get_check(_("死にますか? ", "Die? "))) { + cheat_death(player_ptr); + } + } + } + + if (player_ptr->is_dead) + break; + + change_floor(player_ptr); + } + + close_game(player_ptr); + quit(NULL); +} diff --git a/src/core/game-play.h b/src/core/game-play.h new file mode 100644 index 000000000..672a1dae1 --- /dev/null +++ b/src/core/game-play.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void play_game(player_type* player_ptr, bool new_game); diff --git a/src/core/hp-mp-processor.c b/src/core/hp-mp-processor.c new file mode 100644 index 000000000..039346c5c --- /dev/null +++ b/src/core/hp-mp-processor.c @@ -0,0 +1,447 @@ +#include "core/hp-mp-processor.h" +#include "cmd-action/cmd-pet.h" +#include "core/hp-mp-regenerator.h" +#include "core/player-redraw-types.h" +#include "core/window-redrawer.h" +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "floor/pattern-walk.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "inventory/inventory-slot-types.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags2.h" +#include "monster-race/race-flags3.h" +#include "object-enchant/object-ego.h" +#include "object-enchant/trc-types.h" +#include "player/attack-defense-types.h" +#include "player-info/avatar.h" +#include "player/player-damage.h" +#include "player/player-race-types.h" +#include "player/player-race.h" +#include "player/special-defense-types.h" +#include "status/bad-status-setter.h" +#include "status/element-resistance.h" +#include "system/floor-type-definition.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" +#include "world/world.h" + +/*! + * @brief 10ゲームターンが進行するごとにプレイヤーのHPとMPの増減処理を行う。 + * / Handle timed damage and regeneration every 10 game turns + * @return なし + */ +void process_player_hp_mp(player_type *creature_ptr) +{ + feature_type *f_ptr = &f_info[creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].feat]; + bool cave_no_regen = FALSE; + int upkeep_factor = 0; + int regen_amount = PY_REGEN_NORMAL; + if (creature_ptr->poisoned && !is_invuln(creature_ptr)) { + take_hit(creature_ptr, DAMAGE_NOESCAPE, 1, _("毒", "poison"), -1); + } + + if (creature_ptr->cut && !is_invuln(creature_ptr)) { + HIT_POINT dam; + if (creature_ptr->cut > 1000) { + dam = 200; + } else if (creature_ptr->cut > 200) { + dam = 80; + } else if (creature_ptr->cut > 100) { + dam = 32; + } else if (creature_ptr->cut > 50) { + dam = 16; + } else if (creature_ptr->cut > 25) { + dam = 7; + } else if (creature_ptr->cut > 10) { + dam = 3; + } else { + dam = 1; + } + + take_hit(creature_ptr, DAMAGE_NOESCAPE, dam, _("致命傷", "a fatal wound"), -1); + } + + if (is_specific_player_race(creature_ptr, RACE_VAMPIRE) || (creature_ptr->mimic_form == MIMIC_VAMPIRE)) { + if (!creature_ptr->current_floor_ptr->dun_level && !creature_ptr->resist_lite && !is_invuln(creature_ptr) && is_daytime()) { + if ((creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW) { + msg_print(_("日光があなたのアンデッドの肉体を焼き焦がした!", "The sun's rays scorch your undead flesh!")); + take_hit(creature_ptr, DAMAGE_NOESCAPE, 1, _("日光", "sunlight"), -1); + cave_no_regen = TRUE; + } + } + + if (creature_ptr->inventory_list[INVEN_LITE].tval && (creature_ptr->inventory_list[INVEN_LITE].name2 != EGO_LITE_DARKNESS) + && !creature_ptr->resist_lite) { + object_type *o_ptr = &creature_ptr->inventory_list[INVEN_LITE]; + GAME_TEXT o_name[MAX_NLEN]; + char ouch[MAX_NLEN + 40]; + describe_flavor(creature_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); + msg_format(_("%sがあなたのアンデッドの肉体を焼き焦がした!", "The %s scorches your undead flesh!"), o_name); + + cave_no_regen = TRUE; + describe_flavor(creature_ptr, o_name, o_ptr, OD_NAME_ONLY); + sprintf(ouch, _("%sを装備したダメージ", "wielding %s"), o_name); + + if (!is_invuln(creature_ptr)) + take_hit(creature_ptr, DAMAGE_NOESCAPE, 1, ouch, -1); + } + } + + if (have_flag(f_ptr->flags, FF_LAVA) && !is_invuln(creature_ptr) && !creature_ptr->immune_fire) { + int damage = 0; + + if (have_flag(f_ptr->flags, FF_DEEP)) { + damage = 6000 + randint0(4000); + } else if (!creature_ptr->levitation) { + damage = 3000 + randint0(2000); + } + + if (damage) { + if (is_specific_player_race(creature_ptr, RACE_ENT)) + damage += damage / 3; + if (creature_ptr->resist_fire) + damage = damage / 3; + if (is_oppose_fire(creature_ptr)) + damage = damage / 3; + if (creature_ptr->levitation) + damage = damage / 5; + + damage = damage / 100 + (randint0(100) < (damage % 100)); + + if (creature_ptr->levitation) { + msg_print(_("熱で火傷した!", "The heat burns you!")); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, + format(_("%sの上に浮遊したダメージ", "flying over %s"), + f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name), + -1); + } else { + concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name; + msg_format(_("%sで火傷した!", "The %s burns you!"), name); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1); + } + + cave_no_regen = TRUE; + } + } + + if (have_flag(f_ptr->flags, FF_COLD_PUDDLE) && !is_invuln(creature_ptr) && !creature_ptr->immune_cold) { + int damage = 0; + + if (have_flag(f_ptr->flags, FF_DEEP)) { + damage = 6000 + randint0(4000); + } else if (!creature_ptr->levitation) { + damage = 3000 + randint0(2000); + } + + if (damage) { + if (creature_ptr->resist_cold) + damage = damage / 3; + if (is_oppose_cold(creature_ptr)) + damage = damage / 3; + if (creature_ptr->levitation) + damage = damage / 5; + + damage = damage / 100 + (randint0(100) < (damage % 100)); + + if (creature_ptr->levitation) { + msg_print(_("冷気に覆われた!", "The cold engulfs you!")); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, + format(_("%sの上に浮遊したダメージ", "flying over %s"), + f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name), + -1); + } else { + concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name; + msg_format(_("%sに凍えた!", "The %s frostbites you!"), name); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1); + } + + cave_no_regen = TRUE; + } + } + + if (have_flag(f_ptr->flags, FF_ELEC_PUDDLE) && !is_invuln(creature_ptr) && !creature_ptr->immune_elec) { + int damage = 0; + + if (have_flag(f_ptr->flags, FF_DEEP)) { + damage = 6000 + randint0(4000); + } else if (!creature_ptr->levitation) { + damage = 3000 + randint0(2000); + } + + if (damage) { + if (creature_ptr->resist_elec) + damage = damage / 3; + if (is_oppose_elec(creature_ptr)) + damage = damage / 3; + if (creature_ptr->levitation) + damage = damage / 5; + + damage = damage / 100 + (randint0(100) < (damage % 100)); + + if (creature_ptr->levitation) { + msg_print(_("電撃を受けた!", "The electricity shocks you!")); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, + format(_("%sの上に浮遊したダメージ", "flying over %s"), + f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name), + -1); + } else { + concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name; + msg_format(_("%sに感電した!", "The %s shocks you!"), name); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1); + } + + cave_no_regen = TRUE; + } + } + + if (have_flag(f_ptr->flags, FF_ACID_PUDDLE) && !is_invuln(creature_ptr) && !creature_ptr->immune_acid) { + int damage = 0; + + if (have_flag(f_ptr->flags, FF_DEEP)) { + damage = 6000 + randint0(4000); + } else if (!creature_ptr->levitation) { + damage = 3000 + randint0(2000); + } + + if (damage) { + if (creature_ptr->resist_acid) + damage = damage / 3; + if (is_oppose_acid(creature_ptr)) + damage = damage / 3; + if (creature_ptr->levitation) + damage = damage / 5; + + damage = damage / 100 + (randint0(100) < (damage % 100)); + + if (creature_ptr->levitation) { + msg_print(_("酸が飛び散った!", "The acid melts you!")); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, + format(_("%sの上に浮遊したダメージ", "flying over %s"), + f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name), + -1); + } else { + concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name; + msg_format(_("%sに溶かされた!", "The %s melts you!"), name); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1); + } + + cave_no_regen = TRUE; + } + } + + if (have_flag(f_ptr->flags, FF_POISON_PUDDLE) && !is_invuln(creature_ptr)) { + int damage = 0; + + if (have_flag(f_ptr->flags, FF_DEEP)) { + damage = 6000 + randint0(4000); + } else if (!creature_ptr->levitation) { + damage = 3000 + randint0(2000); + } + + if (damage) { + if (creature_ptr->resist_pois) + damage = damage / 3; + if (is_oppose_pois(creature_ptr)) + damage = damage / 3; + if (creature_ptr->levitation) + damage = damage / 5; + + damage = damage / 100 + (randint0(100) < (damage % 100)); + + if (creature_ptr->levitation) { + msg_print(_("毒気を吸い込んだ!", "The gas poisons you!")); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, + format(_("%sの上に浮遊したダメージ", "flying over %s"), + f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name), + -1); + if (creature_ptr->resist_pois) + (void)set_poisoned(creature_ptr, creature_ptr->poisoned + 1); + } else { + concptr name = f_name + f_info[get_feat_mimic(&creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x])].name; + msg_format(_("%sに毒された!", "The %s poisons you!"), name); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, name, -1); + if (creature_ptr->resist_pois) + (void)set_poisoned(creature_ptr, creature_ptr->poisoned + 3); + } + + cave_no_regen = TRUE; + } + } + + if (have_flag(f_ptr->flags, FF_WATER) && have_flag(f_ptr->flags, FF_DEEP) && !creature_ptr->levitation && !creature_ptr->can_swim + && !creature_ptr->resist_water) { + if (creature_ptr->total_weight > weight_limit(creature_ptr)) { + msg_print(_("溺れている!", "You are drowning!")); + take_hit(creature_ptr, DAMAGE_NOESCAPE, randint1(creature_ptr->lev), _("溺れ", "drowning"), -1); + cave_no_regen = TRUE; + } + } + + if (creature_ptr->riding) { + HIT_POINT damage; + if ((r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].flags2 & RF2_AURA_FIRE) && !creature_ptr->immune_fire) { + damage = r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].level / 2; + if (is_specific_player_race(creature_ptr, RACE_ENT)) + damage += damage / 3; + if (creature_ptr->resist_fire) + damage = damage / 3; + if (is_oppose_fire(creature_ptr)) + damage = damage / 3; + msg_print(_("熱い!", "It's hot!")); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, _("炎のオーラ", "Fire aura"), -1); + } + if ((r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].flags2 & RF2_AURA_ELEC) && !creature_ptr->immune_elec) { + damage = r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].level / 2; + if (is_specific_player_race(creature_ptr, RACE_ANDROID)) + damage += damage / 3; + if (creature_ptr->resist_elec) + damage = damage / 3; + if (is_oppose_elec(creature_ptr)) + damage = damage / 3; + msg_print(_("痛い!", "It hurts!")); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, _("電気のオーラ", "Elec aura"), -1); + } + if ((r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].flags3 & RF3_AURA_COLD) && !creature_ptr->immune_cold) { + damage = r_info[creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].r_idx].level / 2; + if (creature_ptr->resist_cold) + damage = damage / 3; + if (is_oppose_cold(creature_ptr)) + damage = damage / 3; + msg_print(_("冷たい!", "It's cold!")); + take_hit(creature_ptr, DAMAGE_NOESCAPE, damage, _("冷気のオーラ", "Cold aura"), -1); + } + } + + /* Spectres -- take damage when moving through walls */ + /* + * Added: ANYBODY takes damage if inside through walls + * without wraith form -- NOTE: Spectres will never be + * reduced below 0 hp by being inside a stone wall; others + * WILL BE! + */ + if (!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) { + if (!is_invuln(creature_ptr) && !creature_ptr->wraith_form && !creature_ptr->tim_pass_wall + && ((creature_ptr->chp > (creature_ptr->lev / 5)) || !creature_ptr->pass_wall)) { + concptr dam_desc; + cave_no_regen = TRUE; + + if (creature_ptr->pass_wall) { + msg_print(_("体の分子が分解した気がする!", "Your molecules feel disrupted!")); + dam_desc = _("密度", "density"); + } else { + msg_print(_("崩れた岩に押し潰された!", "You are being crushed!")); + dam_desc = _("硬い岩", "solid rock"); + } + + take_hit(creature_ptr, DAMAGE_NOESCAPE, 1 + (creature_ptr->lev / 5), dam_desc, -1); + } + } + + if (creature_ptr->food < PY_FOOD_WEAK) { + if (creature_ptr->food < PY_FOOD_STARVE) { + regen_amount = 0; + } else if (creature_ptr->food < PY_FOOD_FAINT) { + regen_amount = PY_REGEN_FAINT; + } else { + regen_amount = PY_REGEN_WEAK; + } + } + + if (pattern_effect(creature_ptr)) { + cave_no_regen = TRUE; + } else { + if (creature_ptr->regenerate) { + regen_amount = regen_amount * 2; + } + if (creature_ptr->special_defense & (KAMAE_MASK | KATA_MASK)) { + regen_amount /= 2; + } + if (creature_ptr->cursed & TRC_SLOW_REGEN) { + regen_amount /= 5; + } + } + + if ((creature_ptr->action == ACTION_SEARCH) || (creature_ptr->action == ACTION_REST)) { + regen_amount = regen_amount * 2; + } + + upkeep_factor = calculate_upkeep(creature_ptr); + if ((creature_ptr->action == ACTION_LEARN) || (creature_ptr->action == ACTION_HAYAGAKE) || (creature_ptr->special_defense & KATA_KOUKIJIN)) { + upkeep_factor += 100; + } + + regenmana(creature_ptr, upkeep_factor, regen_amount); + if (creature_ptr->pclass == CLASS_MAGIC_EATER) { + regenmagic(creature_ptr, regen_amount); + } + + if ((creature_ptr->csp == 0) && (creature_ptr->csp_frac == 0)) { + while (upkeep_factor > 100) { + msg_print(_("こんなに多くのペットを制御できない!", "Too many pets to control at once!")); + msg_print(NULL); + do_cmd_pet_dismiss(creature_ptr); + + upkeep_factor = calculate_upkeep(creature_ptr); + + msg_format(_("維持MPは %d%%", "Upkeep: %d%% mana."), upkeep_factor); + msg_print(NULL); + } + } + + if (creature_ptr->poisoned) + regen_amount = 0; + if (creature_ptr->cut) + regen_amount = 0; + if (cave_no_regen) + regen_amount = 0; + + regen_amount = (regen_amount * creature_ptr->mutant_regenerate_mod) / 100; + if ((creature_ptr->chp < creature_ptr->mhp) && !cave_no_regen) { + regenhp(creature_ptr, regen_amount); + } +} + +/* + * Increase players hit points, notice effects + */ +bool hp_player(player_type *creature_ptr, int num) +{ + int vir; + vir = virtue_number(creature_ptr, V_VITALITY); + + if (num <= 0) + return FALSE; + + if (vir) { + num = num * (creature_ptr->virtues[vir - 1] + 1250) / 1250; + } + + if (creature_ptr->chp < creature_ptr->mhp) { + if ((num > 0) && (creature_ptr->chp < (creature_ptr->mhp / 3))) + chg_virtue(creature_ptr, V_TEMPERANCE, 1); + + creature_ptr->chp += num; + if (creature_ptr->chp >= creature_ptr->mhp) { + creature_ptr->chp = creature_ptr->mhp; + creature_ptr->chp_frac = 0; + } + + creature_ptr->redraw |= (PR_HP); + creature_ptr->window |= (PW_PLAYER); + if (num < 5) { + msg_print(_("少し気分が良くなった。", "You feel a little better.")); + } else if (num < 15) { + msg_print(_("気分が良くなった。", "You feel better.")); + } else if (num < 35) { + msg_print(_("とても気分が良くなった。", "You feel much better.")); + } else { + msg_print(_("ひじょうに気分が良くなった。", "You feel very good.")); + } + + return TRUE; + } + + return FALSE; +} diff --git a/src/core/hp-mp-processor.h b/src/core/hp-mp-processor.h new file mode 100644 index 000000000..9efd21447 --- /dev/null +++ b/src/core/hp-mp-processor.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" + +void process_player_hp_mp(player_type* creature_ptr); +bool hp_player(player_type *creature_ptr, int num); diff --git a/src/core/hp-mp-regenerator.c b/src/core/hp-mp-regenerator.c new file mode 100644 index 000000000..0d29c8b9e --- /dev/null +++ b/src/core/hp-mp-regenerator.c @@ -0,0 +1,236 @@ +#include "core/hp-mp-regenerator.h" +#include "cmd-item/cmd-magiceat.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" +#include "inventory/inventory-slot-types.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags2.h" +#include "monster/monster-status.h" +#include "player/attack-defense-types.h" +#include "player/special-defense-types.h" +#include "player/player-status-table.h" +#include "system/floor-type-definition.h" +#include "system/object-type-definition.h" + +/*!<広域マップ移動時の自然回復処理カウンタ(広域マップ1マス毎に20回処理を基本とする)*/ +int wild_regen = 20; + +/*! + * @brief プレイヤーのHP自然回復処理 / Regenerate hit points -RAK- + * @param percent 回復比率 + * @return なし + */ +void regenhp(player_type *creature_ptr, int percent) +{ + if (creature_ptr->special_defense & KATA_KOUKIJIN) + return; + if (creature_ptr->action == ACTION_HAYAGAKE) + return; + + HIT_POINT old_chp = creature_ptr->chp; + + /* + * Extract the new hitpoints + * + * 'percent' is the Regen factor in unit (1/2^16) + */ + HIT_POINT new_chp = 0; + u32b new_chp_frac = (creature_ptr->mhp * percent + PY_REGEN_HPBASE); + s64b_LSHIFT(new_chp, new_chp_frac, 16); + s64b_add(&(creature_ptr->chp), &(creature_ptr->chp_frac), new_chp, new_chp_frac); + if (0 < s64b_cmp(creature_ptr->chp, creature_ptr->chp_frac, creature_ptr->mhp, 0)) { + creature_ptr->chp = creature_ptr->mhp; + creature_ptr->chp_frac = 0; + } + + if (old_chp != creature_ptr->chp) { + creature_ptr->redraw |= (PR_HP); + creature_ptr->window |= (PW_PLAYER); + wild_regen = 20; + } +} + +/*! + * @brief プレイヤーのMP自然回復処理(regen_magic()のサブセット) / Regenerate mana points + * @param upkeep_factor ペット維持によるMPコスト量 + * @param regen_amount 回復量 + * @return なし + */ +void regenmana(player_type *creature_ptr, MANA_POINT upkeep_factor, MANA_POINT regen_amount) +{ + MANA_POINT old_csp = creature_ptr->csp; + s32b regen_rate = regen_amount * 100 - upkeep_factor * PY_REGEN_NORMAL; + + /* + * Excess mana will decay 32 times faster than normal + * regeneration rate. + */ + if (creature_ptr->csp > creature_ptr->msp) { + s32b decay = 0; + u32b decay_frac = (creature_ptr->msp * 32 * PY_REGEN_NORMAL + PY_REGEN_MNBASE); + s64b_LSHIFT(decay, decay_frac, 16); + s64b_sub(&(creature_ptr->csp), &(creature_ptr->csp_frac), decay, decay_frac); + if (creature_ptr->csp < creature_ptr->msp) { + creature_ptr->csp = creature_ptr->msp; + creature_ptr->csp_frac = 0; + } + } + + /* Regenerating mana (unless the player has excess mana) */ + else if (regen_rate > 0) { + MANA_POINT new_mana = 0; + u32b new_mana_frac = (creature_ptr->msp * regen_rate / 100 + PY_REGEN_MNBASE); + s64b_LSHIFT(new_mana, new_mana_frac, 16); + s64b_add(&(creature_ptr->csp), &(creature_ptr->csp_frac), new_mana, new_mana_frac); + if (creature_ptr->csp >= creature_ptr->msp) { + creature_ptr->csp = creature_ptr->msp; + creature_ptr->csp_frac = 0; + } + } + + /* Reduce mana (even when the player has excess mana) */ + if (regen_rate < 0) { + s32b reduce_mana = 0; + u32b reduce_mana_frac = (creature_ptr->msp * (-1) * regen_rate / 100 + PY_REGEN_MNBASE); + s64b_LSHIFT(reduce_mana, reduce_mana_frac, 16); + s64b_sub(&(creature_ptr->csp), &(creature_ptr->csp_frac), reduce_mana, reduce_mana_frac); + if (creature_ptr->csp < 0) { + creature_ptr->csp = 0; + creature_ptr->csp_frac = 0; + } + } + + if (old_csp != creature_ptr->csp) { + creature_ptr->redraw |= (PR_MANA); + creature_ptr->window |= (PW_PLAYER); + creature_ptr->window |= (PW_SPELL); + wild_regen = 20; + } +} + +/*! + * @brief プレイヤーのMP自然回復処理 / Regenerate magic regen_amount: PY_REGEN_NORMAL * 2 (if resting) * 2 (if having regenarate) + * @param regen_amount 回復量 + * @return なし + */ +void regenmagic(player_type *creature_ptr, int regen_amount) +{ + MANA_POINT new_mana; + int dev = 30; + int mult = (dev + adj_mag_mana[creature_ptr->stat_ind[A_INT]]); /* x1 to x2 speed bonus for recharging */ + + for (int i = 0; i < EATER_EXT * 2; i++) { + if (!creature_ptr->magic_num2[i]) + continue; + if (creature_ptr->magic_num1[i] == ((long)creature_ptr->magic_num2[i] << 16)) + continue; + + /* Increase remaining charge number like float value */ + new_mana = (regen_amount * mult * ((long)creature_ptr->magic_num2[i] + 13)) / (dev * 8); + creature_ptr->magic_num1[i] += new_mana; + + /* Check maximum charge */ + if (creature_ptr->magic_num1[i] > (creature_ptr->magic_num2[i] << 16)) { + creature_ptr->magic_num1[i] = ((long)creature_ptr->magic_num2[i] << 16); + } + + wild_regen = 20; + } + + for (int i = EATER_EXT * 2; i < EATER_EXT * 3; i++) { + if (!creature_ptr->magic_num1[i]) + continue; + if (!creature_ptr->magic_num2[i]) + continue; + + /* Decrease remaining period for charging */ + new_mana = (regen_amount * mult * ((long)creature_ptr->magic_num2[i] + 10) * EATER_ROD_CHARGE) / (dev * 16 * PY_REGEN_NORMAL); + creature_ptr->magic_num1[i] -= new_mana; + + /* Check minimum remaining period for charging */ + if (creature_ptr->magic_num1[i] < 0) + creature_ptr->magic_num1[i] = 0; + wild_regen = 20; + } +} + +/*! + * @brief 100ゲームターン毎のモンスターのHP自然回復処理 / Regenerate the monsters (once per 100 game turns) + * @param player_ptr プレーヤーへの参照ポインタ + * @return なし + * @note Should probably be done during monster turns. + */ +void regenerate_monsters(player_type *player_ptr) +{ + for (int i = 1; i < player_ptr->current_floor_ptr->m_max; i++) { + monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[i]; + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + + if (!monster_is_valid(m_ptr)) + continue; + + if (m_ptr->hp < m_ptr->maxhp) { + int frac = m_ptr->maxhp / 100; + if (!frac) + if (one_in_(2)) + frac = 1; + + if (r_ptr->flags2 & RF2_REGENERATE) + frac *= 2; + + m_ptr->hp += frac; + if (m_ptr->hp > m_ptr->maxhp) + m_ptr->hp = m_ptr->maxhp; + + if (player_ptr->health_who == i) + player_ptr->redraw |= (PR_HEALTH); + if (player_ptr->riding == i) + player_ptr->redraw |= (PR_UHEALTH); + } + } +} + +/*! + * @brief 30ゲームターン毎のボール中モンスターのHP自然回復処理 / Regenerate the captured monsters (once per 30 game turns) + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + * @note Should probably be done during monster turns. + */ +void regenerate_captured_monsters(player_type *creature_ptr) +{ + bool heal = FALSE; + for (int i = 0; i < INVEN_TOTAL; i++) { + monster_race *r_ptr; + object_type *o_ptr = &creature_ptr->inventory_list[i]; + if (!o_ptr->k_idx) + continue; + if (o_ptr->tval != TV_CAPTURE) + continue; + if (!o_ptr->pval) + continue; + + heal = TRUE; + r_ptr = &r_info[o_ptr->pval]; + if (o_ptr->xtra4 < o_ptr->xtra5) { + int frac = o_ptr->xtra5 / 100; + if (!frac) + if (one_in_(2)) + frac = 1; + + if (r_ptr->flags2 & RF2_REGENERATE) + frac *= 2; + + o_ptr->xtra4 += (XTRA16)frac; + if (o_ptr->xtra4 > o_ptr->xtra5) + o_ptr->xtra4 = o_ptr->xtra5; + } + } + + if (heal) { + creature_ptr->update |= (PU_COMBINE); + creature_ptr->window |= (PW_INVEN); + creature_ptr->window |= (PW_EQUIP); + wild_regen = 20; + } +} diff --git a/src/core/hp-mp-regenerator.h b/src/core/hp-mp-regenerator.h new file mode 100644 index 000000000..b9fb03aaa --- /dev/null +++ b/src/core/hp-mp-regenerator.h @@ -0,0 +1,11 @@ +#pragma once + +#include "system/angband.h" + +extern int wild_regen; + +void regenhp(player_type* creature_ptr, int percent); +void regenmana(player_type* creature_ptr, MANA_POINT upkeep_factor, MANA_POINT regen_amount); +void regenmagic(player_type* creature_ptr, int regen_amount); +void regenerate_monsters(player_type* player_ptr); +void regenerate_captured_monsters(player_type* creature_ptr); diff --git a/src/core/magic-effects-timeout-reducer.c b/src/core/magic-effects-timeout-reducer.c new file mode 100644 index 000000000..79a5a6401 --- /dev/null +++ b/src/core/magic-effects-timeout-reducer.c @@ -0,0 +1,224 @@ +#include "core/magic-effects-timeout-reducer.h" +#include "game-option/birth-options.h" +#include "mind/mind-force-trainer.h" +#include "mind/mind-magic-resistance.h" +#include "mind/mind-mirror-master.h" +#include "racial/racial-kutar.h" +#include "player/player-status-table.h" +#include "spell-realm/spells-craft.h" +#include "spell-realm/spells-crusade.h" +#include "spell-realm/spells-demon.h" +#include "spell-realm/spells-song.h" +#include "status/bad-status-setter.h" +#include "status/body-improvement.h" +#include "status/buff-setter.h" +#include "status/element-resistance.h" +#include "status/shape-changer.h" +#include "status/sight-setter.h" +#include "status/temporary-resistance.h" + +/*! + * @brief 10ゲームターンが進行するごとに魔法効果の残りターンを減らしていく処理 + * / Handle timeout every 10 game turns + * @return なし + */ +void reduce_magic_effects_timeout(player_type *creature_ptr) +{ + const int dec_count = (easy_band ? 2 : 1); + if (creature_ptr->tim_mimic) { + (void)set_mimic(creature_ptr, creature_ptr->tim_mimic - 1, creature_ptr->mimic_form, TRUE); + } + + if (creature_ptr->image) { + (void)set_image(creature_ptr, creature_ptr->image - dec_count); + } + + if (creature_ptr->blind) { + (void)set_blind(creature_ptr, creature_ptr->blind - dec_count); + } + + if (creature_ptr->tim_invis) { + (void)set_tim_invis(creature_ptr, creature_ptr->tim_invis - 1, TRUE); + } + + if (creature_ptr->suppress_multi_reward) { + creature_ptr->suppress_multi_reward = FALSE; + } + + if (creature_ptr->tim_esp) { + (void)set_tim_esp(creature_ptr, creature_ptr->tim_esp - 1, TRUE); + } + + if (creature_ptr->ele_attack) { + creature_ptr->ele_attack--; + if (!creature_ptr->ele_attack) + set_ele_attack(creature_ptr, 0, 0); + } + + if (creature_ptr->ele_immune) { + creature_ptr->ele_immune--; + if (!creature_ptr->ele_immune) + set_ele_immune(creature_ptr, 0, 0); + } + + if (creature_ptr->tim_infra) { + (void)set_tim_infra(creature_ptr, creature_ptr->tim_infra - 1, TRUE); + } + + if (creature_ptr->tim_stealth) { + (void)set_tim_stealth(creature_ptr, creature_ptr->tim_stealth - 1, TRUE); + } + + if (creature_ptr->tim_levitation) { + (void)set_tim_levitation(creature_ptr, creature_ptr->tim_levitation - 1, TRUE); + } + + if (creature_ptr->tim_sh_touki) { + (void)set_tim_sh_force(creature_ptr, creature_ptr->tim_sh_touki - 1, TRUE); + } + + if (creature_ptr->tim_sh_fire) { + (void)set_tim_sh_fire(creature_ptr, creature_ptr->tim_sh_fire - 1, TRUE); + } + + if (creature_ptr->tim_sh_holy) { + (void)set_tim_sh_holy(creature_ptr, creature_ptr->tim_sh_holy - 1, TRUE); + } + + if (creature_ptr->tim_eyeeye) { + (void)set_tim_eyeeye(creature_ptr, creature_ptr->tim_eyeeye - 1, TRUE); + } + + if (creature_ptr->resist_magic) { + (void)set_resist_magic(creature_ptr, creature_ptr->resist_magic - 1, TRUE); + } + + if (creature_ptr->tim_regen) { + (void)set_tim_regen(creature_ptr, creature_ptr->tim_regen - 1, TRUE); + } + + if (creature_ptr->tim_res_nether) { + (void)set_tim_res_nether(creature_ptr, creature_ptr->tim_res_nether - 1, TRUE); + } + + if (creature_ptr->tim_res_time) { + (void)set_tim_res_time(creature_ptr, creature_ptr->tim_res_time - 1, TRUE); + } + + if (creature_ptr->tim_reflect) { + (void)set_tim_reflect(creature_ptr, creature_ptr->tim_reflect - 1, TRUE); + } + + if (creature_ptr->multishadow) { + (void)set_multishadow(creature_ptr, creature_ptr->multishadow - 1, TRUE); + } + + if (creature_ptr->dustrobe) { + (void)set_dustrobe(creature_ptr, creature_ptr->dustrobe - 1, TRUE); + } + + if (creature_ptr->tim_pass_wall) { + (void)set_pass_wall(creature_ptr, creature_ptr->tim_pass_wall - 1, TRUE); + } + + if (creature_ptr->paralyzed) { + (void)set_paralyzed(creature_ptr, creature_ptr->paralyzed - dec_count); + } + + if (creature_ptr->confused) { + (void)set_confused(creature_ptr, creature_ptr->confused - dec_count); + } + + if (creature_ptr->afraid) { + (void)set_afraid(creature_ptr, creature_ptr->afraid - dec_count); + } + + if (creature_ptr->fast) { + (void)set_fast(creature_ptr, creature_ptr->fast - 1, TRUE); + } + + if (creature_ptr->slow) { + (void)set_slow(creature_ptr, creature_ptr->slow - dec_count, TRUE); + } + + if (creature_ptr->protevil) { + (void)set_protevil(creature_ptr, creature_ptr->protevil - 1, TRUE); + } + + if (creature_ptr->invuln) { + (void)set_invuln(creature_ptr, creature_ptr->invuln - 1, TRUE); + } + + if (creature_ptr->wraith_form) { + (void)set_wraith_form(creature_ptr, creature_ptr->wraith_form - 1, TRUE); + } + + if (creature_ptr->hero) { + (void)set_hero(creature_ptr, creature_ptr->hero - 1, TRUE); + } + + if (creature_ptr->shero) { + (void)set_shero(creature_ptr, creature_ptr->shero - 1, TRUE); + } + + if (creature_ptr->blessed) { + (void)set_blessed(creature_ptr, creature_ptr->blessed - 1, TRUE); + } + + if (creature_ptr->shield) { + (void)set_shield(creature_ptr, creature_ptr->shield - 1, TRUE); + } + + if (creature_ptr->tsubureru) { + (void)set_leveling(creature_ptr, creature_ptr->tsubureru - 1, TRUE); + } + + if (creature_ptr->magicdef) { + (void)set_magicdef(creature_ptr, creature_ptr->magicdef - 1, TRUE); + } + + if (creature_ptr->tsuyoshi) { + (void)set_tsuyoshi(creature_ptr, creature_ptr->tsuyoshi - 1, TRUE); + } + + if (creature_ptr->oppose_acid) { + (void)set_oppose_acid(creature_ptr, creature_ptr->oppose_acid - 1, TRUE); + } + + if (creature_ptr->oppose_elec) { + (void)set_oppose_elec(creature_ptr, creature_ptr->oppose_elec - 1, TRUE); + } + + if (creature_ptr->oppose_fire) { + (void)set_oppose_fire(creature_ptr, creature_ptr->oppose_fire - 1, TRUE); + } + + if (creature_ptr->oppose_cold) { + (void)set_oppose_cold(creature_ptr, creature_ptr->oppose_cold - 1, TRUE); + } + + if (creature_ptr->oppose_pois) { + (void)set_oppose_pois(creature_ptr, creature_ptr->oppose_pois - 1, TRUE); + } + + if (creature_ptr->ult_res) { + (void)set_ultimate_res(creature_ptr, creature_ptr->ult_res - 1, TRUE); + } + + if (creature_ptr->poisoned) { + int adjust = adj_con_fix[creature_ptr->stat_ind[A_CON]] + 1; + (void)set_poisoned(creature_ptr, creature_ptr->poisoned - adjust); + } + + if (creature_ptr->stun) { + int adjust = adj_con_fix[creature_ptr->stat_ind[A_CON]] + 1; + (void)set_stun(creature_ptr, creature_ptr->stun - adjust); + } + + if (creature_ptr->cut) { + int adjust = adj_con_fix[creature_ptr->stat_ind[A_CON]] + 1; + if (creature_ptr->cut > 1000) + adjust = 0; + (void)set_cut(creature_ptr, creature_ptr->cut - adjust); + } +} diff --git a/src/core/magic-effects-timeout-reducer.h b/src/core/magic-effects-timeout-reducer.h new file mode 100644 index 000000000..7fdfd38ba --- /dev/null +++ b/src/core/magic-effects-timeout-reducer.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void reduce_magic_effects_timeout(player_type* creature_ptr); diff --git a/src/core/object-compressor.c b/src/core/object-compressor.c new file mode 100644 index 000000000..3362f6cb6 --- /dev/null +++ b/src/core/object-compressor.c @@ -0,0 +1,130 @@ +#include "core/object-compressor.h" +#include "core/player-redraw-types.h" +#include "core/window-redrawer.h" +#include "floor/floor-object.h" +#include "grid/grid.h" +#include "object-hook/hook-checker.h" +#include "object-hook/hook-enchant.h" +#include "object/object-generator.h" +#include "object/object-kind.h" +#include "system/floor-type-definition.h" +#include "system/monster-type-definition.h" +#include "system/object-type-definition.h" +#include "view/display-messages.h" + +/*! + * @brief ƒOƒ[ƒoƒ‹ƒIƒuƒWƒFƒNƒg”z—ñ‚ɑ΂µŽw’è”͈͂̃IƒuƒWƒFƒNƒg‚𐮗‚µ‚ÄID‚ÌŽá‚¢‡‚ÉŠñ‚¹‚é / + * Move an object from index i1 to index i2 in the object list + * @param i1 ®—‚µ‚½‚¢”z—ñ‚ÌŽn“_ + * @param i2 ®—‚µ‚½‚¢”z—ñ‚̏I“_ + * @return ‚È‚µ + */ +static void compact_objects_aux(floor_type *floor_ptr, OBJECT_IDX i1, OBJECT_IDX i2) +{ + if (i1 == i2) + return; + + object_type *o_ptr; + for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++) { + o_ptr = &floor_ptr->o_list[i]; + if (!o_ptr->k_idx) + continue; + + if (o_ptr->next_o_idx == i1) + o_ptr->next_o_idx = i2; + } + + o_ptr = &floor_ptr->o_list[i1]; + + if (object_is_held_monster(o_ptr)) { + monster_type *m_ptr; + m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx]; + if (m_ptr->hold_o_idx == i1) + m_ptr->hold_o_idx = i2; + } else { + POSITION y = o_ptr->iy; + POSITION x = o_ptr->ix; + grid_type *g_ptr; + g_ptr = &floor_ptr->grid_array[y][x]; + if (g_ptr->o_idx == i1) + g_ptr->o_idx = i2; + } + + floor_ptr->o_list[i2] = floor_ptr->o_list[i1]; + object_wipe(o_ptr); +} + +/*! + * @brief ƒOƒ[ƒoƒ‹ƒIƒuƒWƒFƒNƒg”z—ñ‚©‚ç—Dæ“x‚Ì’á‚¢‚à‚Ì‚ðíœ‚µAƒf[ƒ^‚ðˆ³k‚·‚éB / + * Compact and Reorder the object list. + * @param player_ptr ƒvƒŒ[ƒ„[‚Ö‚ÌŽQÆƒ|ƒCƒ“ƒ^ + * @param size Å’á‚Å‚àŒ¸‚炵‚½‚¢ƒIƒuƒWƒFƒNƒg”‚̐…€ + * @return ‚È‚µ + * @details + * iŠëŒ¯‚È‚Ì‚ÅŽg—p‚É‚Í’ˆÓ‚·‚邱‚Ɓj + * This function can be very dangerous, use with caution!\n + *\n + * When actually "compacting" objects, we base the saving throw on a\n + * combination of object level, distance from player, and current\n + * "desperation".\n + *\n + * After "compacting" (if needed), we "reorder" the objects into a more\n + * compact order, and we reset the allocation info, and the "live" array.\n + */ +void compact_objects(player_type *player_ptr, int size) +{ + object_type *o_ptr; + if (size) { + msg_print(_("ƒAƒCƒeƒ€î•ñ‚ðˆ³k‚µ‚Ä‚¢‚Ü‚·...", "Compacting objects...")); + player_ptr->redraw |= PR_MAP; + player_ptr->window |= PW_OVERHEAD | PW_DUNGEON; + } + + floor_type *floor_ptr = player_ptr->current_floor_ptr; + for (int num = 0, cnt = 1; num < size; cnt++) { + int cur_lev = 5 * cnt; + int cur_dis = 5 * (20 - cnt); + for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++) { + o_ptr = &floor_ptr->o_list[i]; + + if (!object_is_valid(o_ptr) || (k_info[o_ptr->k_idx].level > cur_lev)) + continue; + + POSITION y, x; + if (object_is_held_monster(o_ptr)) { + monster_type *m_ptr; + m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx]; + y = m_ptr->fy; + x = m_ptr->fx; + + if (randint0(100) < 90) + continue; + } else { + y = o_ptr->iy; + x = o_ptr->ix; + } + + if ((cur_dis > 0) && (distance(player_ptr->y, player_ptr->x, y, x) < cur_dis)) + continue; + + int chance = 90; + if ((object_is_fixed_artifact(o_ptr) || o_ptr->art_name) && (cnt < 1000)) + chance = 100; + + if (randint0(100) < chance) + continue; + + delete_object_idx(player_ptr, i); + num++; + } + } + + for (OBJECT_IDX i = floor_ptr->o_max - 1; i >= 1; i--) { + o_ptr = &floor_ptr->o_list[i]; + if (o_ptr->k_idx) + continue; + + compact_objects_aux(floor_ptr, floor_ptr->o_max - 1, i); + floor_ptr->o_max--; + } +} diff --git a/src/core/object-compressor.h b/src/core/object-compressor.h new file mode 100644 index 000000000..e897063d8 --- /dev/null +++ b/src/core/object-compressor.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void compact_objects(player_type *owner_ptr, int size); diff --git a/src/core/output-updater.c b/src/core/output-updater.c new file mode 100644 index 000000000..363c7c02d --- /dev/null +++ b/src/core/output-updater.c @@ -0,0 +1,16 @@ +/*! + * @brief メインウィンドウの再描画を行う + * @date 2020/05/09 + * @author Hourier + */ + +#include "core/output-updater.h" +#include "core/window-redrawer.h" + +void update_output(player_type* player_ptr) +{ + if (player_ptr->redraw) + redraw_stuff(player_ptr); + if (player_ptr->window) + window_stuff(player_ptr); +} diff --git a/src/core/output-updater.h b/src/core/output-updater.h new file mode 100644 index 000000000..925630bf5 --- /dev/null +++ b/src/core/output-updater.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void update_output(player_type* player_ptr); diff --git a/src/core/player-processor.c b/src/core/player-processor.c new file mode 100644 index 000000000..49926700e --- /dev/null +++ b/src/core/player-processor.c @@ -0,0 +1,414 @@ +#include "core/player-processor.h" +#include "action/run-execution.h" +#include "action/travel-execution.h" +#include "core/disturbance.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/special-internal-keys.h" +#include "core/speed-table.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "floor/floor-save-util.h" +#include "floor/floor-util.h" +#include "floor/wild.h" +#include "game-option/disturbance-options.h" +#include "game-option/map-screen-options.h" +#include "grid/grid.h" +#include "inventory/pack-overflow.h" +#include "io/cursor.h" +#include "io/input-key-acceptor.h" +#include "io/input-key-processor.h" +#include "io/input-key-requester.h" +#include "mind/mind-force-trainer.h" +#include "mind/mind-sniper.h" +#include "monster-floor/monster-generator.h" +#include "monster-floor/place-monster-types.h" +#include "monster-race/monster-race-hook.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster/monster-describer.h" +#include "monster/monster-flag-types.h" +#include "monster/monster-list.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "monster/monster-update.h" +#include "monster/monster-util.h" +#include "mutation/mutation-investor-remover.h" +#include "player/attack-defense-types.h" +#include "player/player-skill.h" +#include "player/special-defense-types.h" +#include "spell-kind/spells-random.h" +#include "spell-realm/spells-hex.h" +#include "spell-realm/spells-song.h" +#include "status/action-setter.h" +#include "system/floor-type-definition.h" +#include "term/screen-processor.h" +#include "view/display-messages.h" +#include "world/world-turn-processor.h" + +bool load = TRUE; +bool can_save = FALSE; + +static void process_fishing(player_type *creature_ptr) +{ + term_xtra(TERM_XTRA_DELAY, 10); + if (one_in_(1000)) { + MONRACE_IDX r_idx; + bool success = FALSE; + get_mon_num_prep(creature_ptr, monster_is_fishing_target, NULL); + r_idx = get_mon_num(creature_ptr, + creature_ptr->current_floor_ptr->dun_level ? creature_ptr->current_floor_ptr->dun_level + : wilderness[creature_ptr->wilderness_y][creature_ptr->wilderness_x].level, + 0); + msg_print(NULL); + if (r_idx && one_in_(2)) { + POSITION y, x; + y = creature_ptr->y + ddy[creature_ptr->fishing_dir]; + x = creature_ptr->x + ddx[creature_ptr->fishing_dir]; + if (place_monster_aux(creature_ptr, 0, y, x, r_idx, PM_NO_KAGE)) { + GAME_TEXT m_name[MAX_NLEN]; + monster_desc(creature_ptr, m_name, &creature_ptr->current_floor_ptr->m_list[creature_ptr->current_floor_ptr->grid_array[y][x].m_idx], 0); + msg_format(_("%sが釣れた!", "You have a good catch!"), m_name); + success = TRUE; + } + } + + if (!success) { + msg_print(_("餌だけ食われてしまった!くっそ~!", "Damn! The fish stole your bait!")); + } + + disturb(creature_ptr, FALSE, TRUE); + } +} + +/*! + * @brief プレイヤーの行動処理 / Process the player + * @return なし + * @note + * Notice the annoying code to handle "pack overflow", which\n + * must come first just in case somebody manages to corrupt\n + * the savefiles by clever use of menu commands or something.\n + */ +void process_player(player_type *creature_ptr) +{ + if (creature_ptr->hack_mutation) { + msg_print(_("何か変わった気がする!", "You feel different!")); + (void)gain_mutation(creature_ptr, 0); + creature_ptr->hack_mutation = FALSE; + } + + if (creature_ptr->invoking_midnight_curse) { + int count = 0; + activate_ty_curse(creature_ptr, FALSE, &count); + creature_ptr->invoking_midnight_curse = FALSE; + } + + if (creature_ptr->phase_out) { + for (MONSTER_IDX m_idx = 1; m_idx < creature_ptr->current_floor_ptr->m_max; m_idx++) { + monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx]; + if (!monster_is_valid(m_ptr)) + continue; + + m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW); + update_monster(creature_ptr, m_idx, FALSE); + } + + print_time(creature_ptr); + } else if (!(load && creature_ptr->energy_need <= 0)) { + creature_ptr->energy_need -= SPEED_TO_ENERGY(creature_ptr->pspeed); + } + + if (creature_ptr->energy_need > 0) + return; + if (!command_rep) + print_time(creature_ptr); + + if (creature_ptr->resting < 0) { + if (creature_ptr->resting == COMMAND_ARG_REST_FULL_HEALING) { + if ((creature_ptr->chp == creature_ptr->mhp) && (creature_ptr->csp >= creature_ptr->msp)) { + set_action(creature_ptr, ACTION_NONE); + } + } else if (creature_ptr->resting == COMMAND_ARG_REST_UNTIL_DONE) { + if ((creature_ptr->chp == creature_ptr->mhp) && (creature_ptr->csp >= creature_ptr->msp) && !creature_ptr->blind && !creature_ptr->confused + && !creature_ptr->poisoned && !creature_ptr->afraid && !creature_ptr->stun && !creature_ptr->cut && !creature_ptr->slow + && !creature_ptr->paralyzed && !creature_ptr->image && !creature_ptr->word_recall && !creature_ptr->alter_reality) { + set_action(creature_ptr, ACTION_NONE); + } + } + } + + if (creature_ptr->action == ACTION_FISH) + process_fishing(creature_ptr); + + if (check_abort) { + if (creature_ptr->running || travel.run || command_rep || (creature_ptr->action == ACTION_REST) || (creature_ptr->action == ACTION_FISH)) { + inkey_scan = TRUE; + if (inkey()) { + flush(); + disturb(creature_ptr, FALSE, TRUE); + msg_print(_("中断しました。", "Canceled.")); + } + } + } + + if (creature_ptr->riding && !creature_ptr->confused && !creature_ptr->blind) { + monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[creature_ptr->riding]; + monster_race *r_ptr = &r_info[m_ptr->r_idx]; + if (monster_csleep_remaining(m_ptr)) { + GAME_TEXT m_name[MAX_NLEN]; + (void)set_monster_csleep(creature_ptr, creature_ptr->riding, 0); + monster_desc(creature_ptr, m_name, m_ptr, 0); + msg_format(_("%^sを起こした。", "You have woken %s up."), m_name); + } + + if (monster_stunned_remaining(m_ptr)) { + if (set_monster_stunned(creature_ptr, creature_ptr->riding, + (randint0(r_ptr->level) < creature_ptr->skill_exp[GINOU_RIDING]) ? 0 : (monster_stunned_remaining(m_ptr) - 1))) { + GAME_TEXT m_name[MAX_NLEN]; + monster_desc(creature_ptr, m_name, m_ptr, 0); + msg_format(_("%^sを朦朧状態から立ち直らせた。", "%^s is no longer stunned."), m_name); + } + } + + if (monster_confused_remaining(m_ptr)) { + if (set_monster_confused(creature_ptr, creature_ptr->riding, + (randint0(r_ptr->level) < creature_ptr->skill_exp[GINOU_RIDING]) ? 0 : (monster_confused_remaining(m_ptr) - 1))) { + GAME_TEXT m_name[MAX_NLEN]; + monster_desc(creature_ptr, m_name, m_ptr, 0); + msg_format(_("%^sを混乱状態から立ち直らせた。", "%^s is no longer confused."), m_name); + } + } + + if (monster_fear_remaining(m_ptr)) { + if (set_monster_monfear(creature_ptr, creature_ptr->riding, + (randint0(r_ptr->level) < creature_ptr->skill_exp[GINOU_RIDING]) ? 0 : (monster_fear_remaining(m_ptr) - 1))) { + GAME_TEXT m_name[MAX_NLEN]; + monster_desc(creature_ptr, m_name, m_ptr, 0); + msg_format(_("%^sを恐怖から立ち直らせた。", "%^s is no longer afraid."), m_name); + } + } + + handle_stuff(creature_ptr); + } + + load = FALSE; + if (creature_ptr->lightspeed) + set_lightspeed(creature_ptr, creature_ptr->lightspeed - 1, TRUE); + + if ((creature_ptr->pclass == CLASS_FORCETRAINER) && get_current_ki(creature_ptr)) { + if (get_current_ki(creature_ptr) < 40) + set_current_ki(creature_ptr, TRUE, 0); + else + set_current_ki(creature_ptr, FALSE, -40); + creature_ptr->update |= (PU_BONUS); + } + + if (creature_ptr->action == ACTION_LEARN) { + s32b cost = 0L; + u32b cost_frac = (creature_ptr->msp + 30L) * 256L; + s64b_LSHIFT(cost, cost_frac, 16); + if (s64b_cmp(creature_ptr->csp, creature_ptr->csp_frac, cost, cost_frac) < 0) { + creature_ptr->csp = 0; + creature_ptr->csp_frac = 0; + set_action(creature_ptr, ACTION_NONE); + } else { + s64b_sub(&(creature_ptr->csp), &(creature_ptr->csp_frac), cost, cost_frac); + } + + creature_ptr->redraw |= PR_MANA; + } + + if (creature_ptr->special_defense & KATA_MASK) { + if (creature_ptr->special_defense & KATA_MUSOU) { + if (creature_ptr->csp < 3) { + set_action(creature_ptr, ACTION_NONE); + } else { + creature_ptr->csp -= 2; + creature_ptr->redraw |= (PR_MANA); + } + } + } + + /*** Handle actual user input ***/ + while (creature_ptr->energy_need <= 0) { + creature_ptr->window |= PW_PLAYER; + creature_ptr->sutemi = FALSE; + creature_ptr->counter = FALSE; + creature_ptr->now_damaged = FALSE; + + handle_stuff(creature_ptr); + move_cursor_relative(creature_ptr->y, creature_ptr->x); + if (fresh_before) + term_fresh(); + + pack_overflow(creature_ptr); + if (!command_new) + command_see = FALSE; + + free_turn(creature_ptr); + if (creature_ptr->phase_out) { + move_cursor_relative(creature_ptr->y, creature_ptr->x); + command_cmd = SPECIAL_KEY_BUILDING; + process_command(creature_ptr); + } else if (creature_ptr->paralyzed || (creature_ptr->stun >= 100)) { + take_turn(creature_ptr, 100); + } else if (creature_ptr->action == ACTION_REST) { + if (creature_ptr->resting > 0) { + creature_ptr->resting--; + if (!creature_ptr->resting) + set_action(creature_ptr, ACTION_NONE); + creature_ptr->redraw |= (PR_STATE); + } + + take_turn(creature_ptr, 100); + } else if (creature_ptr->action == ACTION_FISH) { + take_turn(creature_ptr, 100); + } else if (creature_ptr->running) { + run_step(creature_ptr, 0); + } else if (travel.run) { + travel_step(creature_ptr); + } else if (command_rep) { + command_rep--; + creature_ptr->redraw |= (PR_STATE); + handle_stuff(creature_ptr); + msg_flag = FALSE; + prt("", 0, 0); + process_command(creature_ptr); + } else { + move_cursor_relative(creature_ptr->y, creature_ptr->x); + can_save = TRUE; + request_command(creature_ptr, FALSE); + can_save = FALSE; + process_command(creature_ptr); + } + + pack_overflow(creature_ptr); + if (creature_ptr->energy_use) { + if (creature_ptr->timewalk || creature_ptr->energy_use > 400) { + creature_ptr->energy_need += creature_ptr->energy_use * TURNS_PER_TICK / 10; + } else { + creature_ptr->energy_need += (s16b)((s32b)creature_ptr->energy_use * ENERGY_NEED() / 100L); + } + + if (creature_ptr->image) + creature_ptr->redraw |= (PR_MAP); + + for (MONSTER_IDX m_idx = 1; m_idx < creature_ptr->current_floor_ptr->m_max; m_idx++) { + monster_type *m_ptr; + monster_race *r_ptr; + m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx]; + if (!monster_is_valid(m_ptr)) + continue; + if (!m_ptr->ml) + continue; + + r_ptr = &r_info[m_ptr->ap_r_idx]; + if (!(r_ptr->flags1 & (RF1_ATTR_MULTI | RF1_SHAPECHANGER))) + continue; + + lite_spot(creature_ptr, m_ptr->fy, m_ptr->fx); + } + + if (repair_monsters) { + repair_monsters = FALSE; + for (MONSTER_IDX m_idx = 1; m_idx < creature_ptr->current_floor_ptr->m_max; m_idx++) { + monster_type *m_ptr; + m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx]; + if (!monster_is_valid(m_ptr)) + continue; + + if (m_ptr->mflag & MFLAG_NICE) { + m_ptr->mflag &= ~(MFLAG_NICE); + } + + if (m_ptr->mflag2 & MFLAG2_MARK) { + if (m_ptr->mflag2 & MFLAG2_SHOW) { + m_ptr->mflag2 &= ~(MFLAG2_SHOW); + repair_monsters = TRUE; + } else { + m_ptr->mflag2 &= ~(MFLAG2_MARK); + m_ptr->ml = FALSE; + update_monster(creature_ptr, m_idx, FALSE); + if (creature_ptr->health_who == m_idx) + creature_ptr->redraw |= (PR_HEALTH); + if (creature_ptr->riding == m_idx) + creature_ptr->redraw |= (PR_UHEALTH); + + lite_spot(creature_ptr, m_ptr->fy, m_ptr->fx); + } + } + } + } + + if (creature_ptr->pclass == CLASS_IMITATOR) { + if (creature_ptr->mane_num > (creature_ptr->lev > 44 ? 3 : creature_ptr->lev > 29 ? 2 : 1)) { + creature_ptr->mane_num--; + for (int j = 0; j < creature_ptr->mane_num; j++) { + creature_ptr->mane_spell[j] = creature_ptr->mane_spell[j + 1]; + creature_ptr->mane_dam[j] = creature_ptr->mane_dam[j + 1]; + } + } + + creature_ptr->new_mane = FALSE; + creature_ptr->redraw |= (PR_IMITATION); + } + + if (creature_ptr->action == ACTION_LEARN) { + creature_ptr->new_mane = FALSE; + creature_ptr->redraw |= (PR_STATE); + } + + if (creature_ptr->timewalk && (creature_ptr->energy_need > -1000)) { + + creature_ptr->redraw |= (PR_MAP); + creature_ptr->update |= (PU_MONSTERS); + creature_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); + + msg_print(_("「時は動きだす…」", "You feel time flowing around you once more.")); + msg_print(NULL); + creature_ptr->timewalk = FALSE; + creature_ptr->energy_need = ENERGY_NEED(); + + handle_stuff(creature_ptr); + } + } + + if (!creature_ptr->playing || creature_ptr->is_dead) { + creature_ptr->timewalk = FALSE; + break; + } + + if (creature_ptr->energy_use && creature_ptr->reset_concent) + reset_concentration(creature_ptr, TRUE); + + if (creature_ptr->leaving) + break; + } + + update_smell(creature_ptr->current_floor_ptr, creature_ptr); +} + +/*! + * @brief プレイヤーの行動エネルギーが充填される(=プレイヤーのターンが回る)毎に行われる処理 / process the effects per 100 energy at player speed. + * @return なし + */ +void process_upkeep_with_speed(player_type *creature_ptr) +{ + if (!load && creature_ptr->enchant_energy_need > 0 && !creature_ptr->leaving) { + creature_ptr->enchant_energy_need -= SPEED_TO_ENERGY(creature_ptr->pspeed); + } + + if (creature_ptr->enchant_energy_need > 0) + return; + + while (creature_ptr->enchant_energy_need <= 0) { + if (!load) + check_music(creature_ptr); + if (!load) + check_hex(creature_ptr); + if (!load) + revenge_spell(creature_ptr); + + creature_ptr->enchant_energy_need += ENERGY_NEED(); + } +} diff --git a/src/core/player-processor.h b/src/core/player-processor.h new file mode 100644 index 000000000..89a141db8 --- /dev/null +++ b/src/core/player-processor.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" + +extern bool load; /*!<ロード処理中の分岐フラグ*/ +extern bool can_save; + +void process_player(player_type *creature_ptr); +void process_upkeep_with_speed(player_type *creature_ptr); diff --git a/src/core/player-redraw-types.h b/src/core/player-redraw-types.h new file mode 100644 index 000000000..6e8cba0ad --- /dev/null +++ b/src/core/player-redraw-types.h @@ -0,0 +1,32 @@ +#pragma once + +typedef enum player_redraw_type { + PR_MISC = 0x00000001L, /*!< 再描画フラグ: 種族と職業 / Display Race/Class */ + PR_TITLE = 0x00000002L, /*!< 再描画フラグ: 称号 / Display Title */ + PR_LEV = 0x00000004L, /*!< 再描画フラグ: レベル / Display Level */ + PR_EXP = 0x00000008L, /*!< 再描画フラグ: 経験値 / Display Experience */ + PR_STATS = 0x00000010L, /*!< 再描画フラグ: ステータス / Display Stats */ + PR_ARMOR = 0x00000020L, /*!< 再描画フラグ: AC / Display Armor */ + PR_HP = 0x00000040L, /*!< 再描画フラグ: HP / Display Hitpoints */ + PR_MANA = 0x00000080L, /*!< 再描画フラグ: MP / Display Mana */ + PR_GOLD = 0x00000100L, /*!< 再描画フラグ: 所持金 / Display Gold */ + PR_DEPTH = 0x00000200L, /*!< 再描画フラグ: ダンジョンの階 / Display Depth */ + PR_EQUIPPY = 0x00000400L, /*!< 再描画フラグ: 装備シンボル / Display equippy chars */ + PR_HEALTH = 0x00000800L, /*!< 再描画フラグ: モンスターのステータス / Display Health Bar */ + PR_CUT = 0x00001000L, /*!< 再描画フラグ: 負傷度 / Display Extra (Cut) */ + PR_STUN = 0x00002000L, /*!< 再描画フラグ: 朦朧度 / Display Extra (Stun) */ + PR_HUNGER = 0x00004000L, /*!< 再描画フラグ: 空腹度 / Display Extra (Hunger) */ + PR_STATUS = 0x00008000L, /*!< 再描画フラグ: プレイヤーの付与状態 / Display Status Bar */ + PR_XXX0 = 0x00010000L, /*!< (unused) */ + PR_UHEALTH = 0x00020000L, /*!< 再描画フラグ: ペットのステータス / Display Uma Health Bar */ + PR_XXX1 = 0x00040000L, /*!< (unused) */ + PR_XXX2 = 0x00080000L, /*!< (unused) */ + PR_STATE = 0x00100000L, /*!< 再描画フラグ: プレイヤーの行動状態 / Display Extra (State) */ + PR_SPEED = 0x00200000L, /*!< 再描画フラグ: 加速 / Display Extra (Speed) */ + PR_STUDY = 0x00400000L, /*!< 再描画フラグ: 学習 / Display Extra (Study) */ + PR_IMITATION = 0x00800000L, /*!< 再描画フラグ: ものまね / Display Extra (Imitation) */ + PR_EXTRA = 0x01000000L, /*!< 再描画フラグ: 拡張ステータス全体 / Display Extra Info */ + PR_BASIC = 0x02000000L, /*!< 再描画フラグ: 基本ステータス全体 / Display Basic Info */ + PR_MAP = 0x04000000L, /*!< 再描画フラグ: ゲームマップ / Display Map */ + PR_WIPE = 0x08000000L, /*!< 再描画フラグ: 画面消去 / Hack -- Total Redraw */ +} player_redraw_type; diff --git a/src/core/player-update-types.h b/src/core/player-update-types.h new file mode 100644 index 000000000..18568f0bc --- /dev/null +++ b/src/core/player-update-types.h @@ -0,0 +1,21 @@ +#pragma once + +typedef enum player_update_type { + PU_BONUS = 0x00000001L, /*!< ステータス更新フラグ: 能力値修正 / Calculate bonuses */ + PU_TORCH = 0x00000002L, /*!< ステータス更新フラグ: 光源半径 / Calculate torch radius */ + PU_HP = 0x00000010L, /*!< ステータス更新フラグ: HP / Calculate chp and mhp */ + PU_MANA = 0x00000020L, /*!< ステータス更新フラグ: MP / Calculate csp and msp */ + PU_SPELLS = 0x00000040L, /*!< ステータス更新フラグ: 魔法学習数 / Calculate spells */ + PU_COMBINE = 0x00000100L, /*!< アイテム処理フラグ: アイテムの結合を要する / Combine the pack */ + PU_REORDER = 0x00000200L, /*!< アイテム処理フラグ: アイテムの並び替えを要する / Reorder the pack */ + PU_AUTODESTROY = 0x00000400L, /*!< アイテム処理フラグ: アイテムの自動破壊を要する / Auto-destroy marked item */ + PU_UN_VIEW = 0x00010000L, /*!< ステータス更新フラグ: 地形の視界外化 / Forget view */ + PU_UN_LITE = 0x00020000L, /*!< ステータス更新フラグ: 明暗範囲の視界外化 / Forget lite */ + PU_VIEW = 0x00100000L, /*!< ステータス更新フラグ: 視界 / Update view */ + PU_LITE = 0x00200000L, /*!< ステータス更新フラグ: 明暗範囲 / Update lite */ + PU_MON_LITE = 0x00400000L, /*!< ステータス更新フラグ: モンスターの光源範囲 / Monster illumination */ + PU_DELAY_VIS = 0x00800000L, /*!< ステータス更新フラグ: 視界の追加更新 / Mega-Hack -- Delayed visual update */ + PU_MONSTERS = 0x01000000L, /*!< ステータス更新フラグ: モンスターのステータス / Update monsters */ + PU_DISTANCE = 0x02000000L, /*!< ステータス更新フラグ: プレイヤーとモンスターの距離 / Update distances */ + PU_FLOW = 0x10000000L, /*!< ステータス更新フラグ: プレイヤーから各マスへの到達距離 / Update flow */ +} player_update_type; diff --git a/src/core/scores.c b/src/core/scores.c new file mode 100644 index 000000000..7d3fce842 --- /dev/null +++ b/src/core/scores.c @@ -0,0 +1,946 @@ +/*! + * @file scores.c + * @brief ハイスコア処理 / Highscores handling + * @date 2014/07/14 + * @author + * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke + * This software may be copied and distributed for educational, research, + * and not for profit purposes provided that this copyright and statement + * are included in all such copies. Other copyrights may also apply. + * 2014 Deskull rearranged comment for Doxygen. + */ + +#include "core/scores.h" +#include "cmd-io/cmd-dump.h" +#include "core/asking-player.h" +#include "core/turn-compensator.h" +#include "dungeon/dungeon.h" +#include "game-option/birth-options.h" +#include "game-option/game-play-options.h" +#include "io/input-key-acceptor.h" +#include "io/report.h" +#include "io/signal-handlers.h" +#include "io/uid-checker.h" +#include "io/write-diary.h" +#include "player/player-class.h" +#include "player/player-personality.h" +#include "player/player-sex.h" +#include "player/player-status.h" +#include "player/race-info-table.h" +#include "system/angband-version.h" +#include "system/floor-type-definition.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/angband-files.h" +#include "util/int-char-converter.h" +#include "util/string-processor.h" +#include "view/display-messages.h" +#include "world/world.h" +#ifdef JP +#include "locale/japanese.h" +#endif + + /* + * The "highscore" file descriptor, if available. + */ +int highscore_fd = -1; + +/*! + * @brief i番目のスコア情報にバッファ位置をシークする / Seek score 'i' in the highscore file + * @param i スコア情報ID + * @return 問題がなければ0を返す + */ +static int highscore_seek(int i) +{ + /* Seek for the requested record */ + return (fd_seek(highscore_fd, (huge)(i) * sizeof(high_score))); +} + + +/*! + * @brief 所定ポインタからスコア情報を読み取る / Read one score from the highscore file + * @param score スコア情報参照ポインタ + * @return エラーコード + */ +static errr highscore_read(high_score *score) +{ + /* Read the record, note failure */ + return (fd_read(highscore_fd, (char*)(score), sizeof(high_score))); +} + + +/*! + * @brief 所定ポインタへスコア情報を書き込む / Write one score to the highscore file + * @param score スコア情報参照ポインタ + * @return エラーコード(問題がなければ0を返す) + */ +static int highscore_write(high_score *score) +{ + /* Write the record, note failure */ + return (fd_write(highscore_fd, (char*)(score), sizeof(high_score))); +} + + +/*! + * @brief スコア情報を全て得るまで繰り返し取得する / Just determine where a new score *would* be placed + * @param score スコア情報参照ポインタ + * @return 正常ならば(MAX_HISCORES - 1)、問題があれば-1を返す + */ +static int highscore_where(high_score *score) +{ + /* Paranoia -- it may not have opened */ + if (highscore_fd < 0) return -1; + + /* Go to the start of the highscore file */ + if (highscore_seek(0)) return -1; + + /* Read until we get to a higher score */ + high_score the_score; + int my_score = atoi(score->pts); + for (int i = 0; i < MAX_HISCORES; i++) + { + int old_score; + if (highscore_read(&the_score)) return (i); + old_score = atoi(the_score.pts); + if (my_score > old_score) return (i); + } + + /* The "last" entry is always usable */ + return MAX_HISCORES - 1; +} + + +/*! + * @brief スコア情報をバッファの末尾に追加する / Actually place an entry into the high score file + * @param score スコア情報参照ポインタ + * @return 正常ならば書き込んだスロット位置、問題があれば-1を返す / Return the location (0 is best) or -1 on "failure" + */ +static int highscore_add(high_score *score) +{ + /* Paranoia -- it may not have opened */ + if (highscore_fd < 0) return -1; + + /* Determine where the score should go */ + int slot = highscore_where(score); + + /* Hack -- Not on the list */ + if (slot < 0) return -1; + + /* Hack -- prepare to dump the new score */ + high_score the_score = (*score); + + /* Slide all the scores down one */ + bool done = FALSE; + high_score tmpscore; + for (int i = slot; !done && (i < MAX_HISCORES); i++) + { + /* Read the old guy, note errors */ + if (highscore_seek(i)) return -1; + if (highscore_read(&tmpscore)) done = TRUE; + + /* Back up and dump the score we were holding */ + if (highscore_seek(i)) return -1; + if (highscore_write(&the_score)) return -1; + + /* Hack -- Save the old score, for the next pass */ + the_score = tmpscore; + } + + /* Return location used */ + return slot; +} + + +/*! + * @brief 指定された順位範囲でスコアを並べて表示する / Display the scores in a given range. + * @param from 順位先頭 + * @param to 順位末尾 + * @param note 黄色表示でハイライトする順位 + * @param score スコア配列参照ポインタ + * @return なし + * @details + *
+ * Assumes the high score list is already open.
+ * Only five entries per line, too much info.
+ *
+ * Mega-Hack -- allow "fake" entry at the given position.
+ * 
+ */ +void display_scores_aux(int from, int to, int note, high_score *score) +{ + int i, j, k, n, place; + TERM_COLOR attr; + + high_score the_score; + + GAME_TEXT out_val[256]; + GAME_TEXT tmp_val[160]; + + TERM_LEN wid, hgt, per_screen; + + term_get_size(&wid, &hgt); + per_screen = (hgt - 4) / 4; + + /* Paranoia -- it may not have opened */ + if (highscore_fd < 0) return; + + + /* Assume we will show the first 10 */ + if (from < 0) from = 0; + if (to < 0) to = 10; + if (to > MAX_HISCORES) to = MAX_HISCORES; + + + /* Seek to the beginning */ + if (highscore_seek(0)) return; + + /* Hack -- Count the high scores */ + for (i = 0; i < MAX_HISCORES; i++) + { + if (highscore_read(&the_score)) break; + } + + /* Hack -- allow "fake" entry to be last */ + if ((note == i) && score) i++; + + /* Forget about the last entries */ + if (i > to) i = to; + + + /* Show per_screen per page, until "done" */ + for (k = from, place = k+1; k < i; k += per_screen) + { + term_clear(); + + /* Title */ + put_str(_(" 馬鹿馬鹿蛮怒: 勇者の殿堂", " Bakabakaband Hall of Fame"), 0, 0); + + /* Indicate non-top scores */ + if (k > 0) + { + sprintf(tmp_val, _("( %d 位以下 )", "(from position %d)"), k + 1); + put_str(tmp_val, 0, 40); + } + + /* Dump per_screen entries */ + for (j = k, n = 0; j < i && n < per_screen; place++, j++, n++) + { + int pr, pc, pa, clev, mlev, cdun, mdun; + + concptr user, gold, when, aged; + + + /* Hack -- indicate death in yellow */ + attr = (j == note) ? TERM_YELLOW : TERM_WHITE; + + + /* Mega-Hack -- insert a "fake" record */ + if ((note == j) && score) + { + the_score = (*score); + attr = TERM_L_GREEN; + score = NULL; + note = -1; + j--; + } + + /* Read a normal record */ + else + { + /* Read the proper record */ + if (highscore_seek(j)) break; + if (highscore_read(&the_score)) break; + } + + /* Extract the race/class */ + pr = atoi(the_score.p_r); + pc = atoi(the_score.p_c); + pa = atoi(the_score.p_a); + + /* Extract the level info */ + clev = atoi(the_score.cur_lev); + mlev = atoi(the_score.max_lev); + cdun = atoi(the_score.cur_dun); + mdun = atoi(the_score.max_dun); + + /* Hack -- extract the gold and such */ + for (user = the_score.uid; iswspace(*user); user++) /* loop */; + for (when = the_score.day; iswspace(*when); when++) /* loop */; + for (gold = the_score.gold; iswspace(*gold); gold++) /* loop */; + for (aged = the_score.turns; iswspace(*aged); aged++) /* loop */; + + /* Clean up standard encoded form of "when" */ + if ((*when == '@') && strlen(when) == 9) + { + sprintf(tmp_val, "%.4s-%.2s-%.2s", + when + 1, when + 5, when + 7); + when = tmp_val; + } + + /* Dump some info */ +#ifdef JP +/*sprintf(out_val, "%3d.%9s %s%s%sという名の%sの%s (レベル %d)", */ + sprintf(out_val, "%3d.%9s %s%s%s - %s%s (レベル %d)", + place, the_score.pts, + personality_info[pa].title, (personality_info[pa].no ? "の" : ""), + the_score.who, + race_info[pr].title, class_info[pc].title, + clev); + +#else + sprintf(out_val, "%3d.%9s %s %s the %s %s, Level %d", + place, the_score.pts, + personality_info[pa].title, + the_score.who, race_info[pr].title, class_info[pc].title, + clev); +#endif + + + /* Append a "maximum level" */ + if (mlev > clev) strcat(out_val, format(_(" (最高%d)", " (Max %d)"), mlev)); + + /* Dump the first line */ + c_put_str(attr, out_val, n*4 + 2, 0); + + /* Another line of info */ +#ifdef JP + if (mdun != 0) + sprintf(out_val, " 最高%3d階", mdun); + else + sprintf(out_val, " "); + + + /* 死亡原因をオリジナルより細かく表示 */ + if (streq(the_score.how, "yet")) + { + sprintf(out_val+13, " まだ生きている (%d%s)", + cdun, "階"); + } + else + if (streq(the_score.how, "ripe")) + { + sprintf(out_val+13, " 勝利の後に引退 (%d%s)", + cdun, "階"); + } + else if (streq(the_score.how, "Seppuku")) + { + sprintf(out_val+13, " 勝利の後に切腹 (%d%s)", + cdun, "階"); + } + else + { + codeconv(the_score.how); + + /* Some people die outside of the dungeon */ + if (!cdun) + sprintf(out_val+13, " 地上で%sに殺された", the_score.how); + else + sprintf(out_val+13, " %d階で%sに殺された", + cdun, the_score.how); + } + +#else + /* Some people die outside of the dungeon */ + if (!cdun) + sprintf(out_val, + " Killed by %s on the surface", + the_score.how); + else + sprintf(out_val, + " Killed by %s on %s %d", + the_score.how, "Dungeon Level", cdun); + + /* Append a "maximum level" */ + if (mdun > cdun) strcat(out_val, format(" (Max %d)", mdun)); +#endif + + /* Dump the info */ + c_put_str(attr, out_val, n*4 + 3, 0); + + /* And still another line of info */ +#ifdef JP + { + char buf[11]; + + /* 日付を 19yy/mm/dd の形式に変更する */ + if (strlen(when) == 8 && when[2] == '/' && when[5] == '/') { + sprintf(buf, "%d%s/%.5s", 19 + (when[6] < '8'), when + 6, when); + when = buf; + } + sprintf(out_val, + " (ユーザー:%s, 日付:%s, 所持金:%s, ターン:%s)", + user, when, gold, aged); + } + +#else + sprintf(out_val, + " (User %s, Date %s, Gold %s, Turn %s).", + user, when, gold, aged); +#endif + + c_put_str(attr, out_val, n*4 + 4, 0); + } + + + /* Wait for response */ + prt(_("[ ESCで中断, その他のキーで続けます ]", "[Press ESC to quit, any other key to continue.]"), hgt - 1, _(21, 17)); + + j = inkey(); + prt("", hgt - 1, 0); + + /* Hack -- notice Escape */ + if (j == ESCAPE) break; + } +} + + +/*! + * @brief スコア表示処理メインルーチン / Hack -- Display the scores in a given range and quit. + * @param from 順位先頭 + * @param to 順位末尾 + * @return なし + * @details + *
+ * This function is only called from "main.c" when the user asks
+ * to see the "high scores".
+ * 
+ */ +void display_scores(int from, int to) +{ + char buf[1024]; + path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); + + /* Open the binary high score file, for reading */ + highscore_fd = fd_open(buf, O_RDONLY); + + /* Paranoia -- No score file */ + if (highscore_fd < 0) quit(_("スコア・ファイルが使用できません。", "Score file unavailable.")); + term_clear(); + + /* Display the scores */ + display_scores_aux(from, to, -1, NULL); + + /* Shut the high score file */ + (void)fd_close(highscore_fd); + + /* Forget the high score fd */ + highscore_fd = -1; + + /* Quit */ + quit(NULL); +} + + +/*! + * todo プリプロが邪魔していて最初のif文を削除すると到達不能コードが発生する + * @brief スコアサーバへの転送処理 + * @param current_player_ptr プレーヤーへの参照ポインタ + * @param do_send 実際に転送ア処置を行うか否か + * @return 転送が成功したらTRUEを返す + */ +bool send_world_score(player_type *current_player_ptr, bool do_send, void(*update_playtime)(void), display_player_pf display_player) +{ +#ifdef WORLD_SCORE + if (send_score && do_send) + { + if (easy_band) + { + msg_print(_("初心者モードではワールドスコアに登録できません。", + "Since you are in the Easy Mode, you cannot send score to world score server.")); + return TRUE; + } + + bool is_registration = get_check_strict(current_player_ptr, + _("スコアをスコア・サーバに登録しますか? ", "Do you send score to the world score server? "), (CHECK_NO_ESCAPE | CHECK_NO_HISTORY)); + if (!is_registration) return FALSE; + + errr err; + prt("", 0, 0); + prt(_("送信中..", "Sending..."), 0, 0); + term_fresh(); + screen_save(); + err = report_score(current_player_ptr, update_playtime, display_player); + screen_load(); + if (err) return FALSE; + + prt(_("完了。何かキーを押してください。", "Completed. Hit any key."), 0, 0); + (void)inkey(); + } +#endif + return TRUE; +} + + +/*! + * @brief スコアの過去二十位内ランキングを表示する + * Enters a players name on a hi-score table, if "legal", and in any + * case, displays some relevant portion of the high score list. + * @param current_player_ptr スコアに適用するための現在プレイヤークリーチャー参照ポインタ + * @return エラーコード + * @details + * Assumes "signals_ignore_tstp()" has been called. + */ +errr top_twenty(player_type *current_player_ptr) +{ + high_score the_score; + (void)WIPE(&the_score, high_score); + + /* Save the version */ + sprintf(the_score.what, "%u.%u.%u", + FAKE_VER_MAJOR, FAKE_VER_MINOR, FAKE_VER_PATCH); + + /* Calculate and save the points */ + sprintf(the_score.pts, "%9ld", (long)calc_score(current_player_ptr)); + the_score.pts[9] = '\0'; + + /* Save the current gold */ + sprintf(the_score.gold, "%9lu", (long)current_player_ptr->au); + the_score.gold[9] = '\0'; + + /* Save the current turn */ + sprintf(the_score.turns, "%9lu", (long)turn_real(current_player_ptr, current_world_ptr->game_turn)); + the_score.turns[9] = '\0'; + + time_t ct = time((time_t*)0); + + /* Save the date in standard encoded form (9 chars) */ + strftime(the_score.day, 10, "@%Y%m%d", localtime(&ct)); + + /* Save the player name (15 chars) */ + sprintf(the_score.who, "%-.15s", current_player_ptr->name); + + /* Save the player info */ + sprintf(the_score.uid, "%7u", current_player_ptr->player_uid); + sprintf(the_score.sex, "%c", (current_player_ptr->psex ? 'm' : 'f')); + sprintf(the_score.p_r, "%2d", MIN(current_player_ptr->prace, MAX_RACES)); + sprintf(the_score.p_c, "%2d", MIN(current_player_ptr->pclass, MAX_CLASS)); + sprintf(the_score.p_a, "%2d", MIN(current_player_ptr->pseikaku, MAX_PERSONALITIES)); + + /* Save the level and such */ + sprintf(the_score.cur_lev, "%3d", MIN((u16b)current_player_ptr->lev, 999)); + sprintf(the_score.cur_dun, "%3d", (int)current_player_ptr->current_floor_ptr->dun_level); + sprintf(the_score.max_lev, "%3d", MIN((u16b)current_player_ptr->max_plv, 999)); + sprintf(the_score.max_dun, "%3d", (int)max_dlv[current_player_ptr->dungeon_idx]); + + /* Save the cause of death (31 chars) */ + if (strlen(current_player_ptr->died_from) >= sizeof(the_score.how)) + { +#ifdef JP + angband_strcpy(the_score.how, current_player_ptr->died_from, sizeof(the_score.how) - 2); + strcat(the_score.how, "…"); +#else + angband_strcpy(the_score.how, current_player_ptr->died_from, sizeof(the_score.how) - 3); + strcat(the_score.how, "..."); +#endif + } + else + { + strcpy(the_score.how, current_player_ptr->died_from); + } + + /* Grab permissions */ + safe_setuid_grab(current_player_ptr); + + /* Lock (for writing) the highscore file, or fail */ + errr err = fd_lock(highscore_fd, F_WRLCK); + + /* Drop permissions */ + safe_setuid_drop(); + + if (err) return 1; + + /* Add a new entry to the score list, see where it went */ + int j = highscore_add(&the_score); + + /* Grab permissions */ + safe_setuid_grab(current_player_ptr); + + /* Unlock the highscore file, or fail */ + err = fd_lock(highscore_fd, F_UNLCK); + + /* Drop permissions */ + safe_setuid_drop(); + + if (err) return 1; + + /* Hack -- Display the top fifteen scores */ + if (j < 10) + { + display_scores_aux(0, 15, j, NULL); + return 0; + } + + /* Display the scores surrounding the player */ + display_scores_aux(0, 5, j, NULL); + display_scores_aux(j - 2, j + 7, j, NULL); + return 0; +} + + +/*! + * @brief プレイヤーの現在のスコアをランキングに挟む / + * Predict the players location, and display it. + * @return エラーコード + */ +errr predict_score(player_type *current_player_ptr) +{ + high_score the_score; + + /* No score file */ + if (highscore_fd < 0) + { + msg_print(_("スコア・ファイルが使用できません。", "Score file unavailable.")); + msg_print(NULL); + return 0; + } + + /* Save the version */ + sprintf(the_score.what, "%u.%u.%u", + FAKE_VER_MAJOR, FAKE_VER_MINOR, FAKE_VER_PATCH); + + /* Calculate and save the points */ + sprintf(the_score.pts, "%9ld", (long)calc_score(current_player_ptr)); + + /* Save the current gold */ + sprintf(the_score.gold, "%9lu", (long)current_player_ptr->au); + + /* Save the current turn */ + sprintf(the_score.turns, "%9lu", (long)turn_real(current_player_ptr, current_world_ptr->game_turn)); + + /* Hack -- no time needed */ + strcpy(the_score.day, _("今日", "TODAY")); + + /* Save the player name (15 chars) */ + sprintf(the_score.who, "%-.15s", current_player_ptr->name); + + /* Save the player info */ + sprintf(the_score.uid, "%7u", current_player_ptr->player_uid); + sprintf(the_score.sex, "%c", (current_player_ptr->psex ? 'm' : 'f')); + sprintf(the_score.p_r, "%2d", MIN(current_player_ptr->prace, MAX_RACES)); + sprintf(the_score.p_c, "%2d", MIN(current_player_ptr->pclass, MAX_CLASS)); + sprintf(the_score.p_a, "%2d", MIN(current_player_ptr->pseikaku, MAX_PERSONALITIES)); + + /* Save the level and such */ + sprintf(the_score.cur_lev, "%3d", MIN((u16b)current_player_ptr->lev, 999)); + sprintf(the_score.cur_dun, "%3d", (int)current_player_ptr->current_floor_ptr->dun_level); + sprintf(the_score.max_lev, "%3d", MIN((u16b)current_player_ptr->max_plv, 999)); + sprintf(the_score.max_dun, "%3d", (int)max_dlv[current_player_ptr->dungeon_idx]); + + /* Hack -- no cause of death */ + /* まだ死んでいないときの識別文字 */ + strcpy(the_score.how, _("yet", "nobody (yet!)")); + + /* See where the entry would be placed */ + int j = highscore_where(&the_score); + + /* Hack -- Display the top fifteen scores */ + if (j < 10) + { + display_scores_aux(0, 15, j, &the_score); + return 0; + } + + display_scores_aux(0, 5, -1, NULL); + display_scores_aux(j - 2, j + 7, j, &the_score); + return 0; +} + + +/*! + * @brief スコアランキングの簡易表示 / + * show_highclass - selectively list highscores based on class -KMW- + * @return なし + */ +void show_highclass(player_type *current_player_ptr) +{ + screen_save(); + char buf[1024], out_val[256]; + path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); + + highscore_fd = fd_open(buf, O_RDONLY); + + if (highscore_fd < 0) + { + msg_print(_("スコア・ファイルが使用できません。", "Score file unavailable.")); + msg_print(NULL); + return; + } + + if (highscore_seek(0)) return; + + high_score the_score; + for (int i = 0; i < MAX_HISCORES; i++) + if (highscore_read(&the_score)) break; + + int m = 0; + int j = 0; + PLAYER_LEVEL clev = 0; + int pr; + while ((m < 9) && (j < MAX_HISCORES)) + { + if (highscore_seek(j)) break; + if (highscore_read(&the_score)) break; + pr = atoi(the_score.p_r); + clev = (PLAYER_LEVEL)atoi(the_score.cur_lev); + +#ifdef JP + sprintf(out_val, " %3d) %sの%s (レベル %2d)", + (m + 1), race_info[pr].title,the_score.who, clev); +#else + sprintf(out_val, "%3d) %s the %s (Level %2d)", + (m + 1), the_score.who, race_info[pr].title, clev); +#endif + + prt(out_val, (m + 7), 0); + m++; + j++; + } + +#ifdef JP + sprintf(out_val, "あなた) %sの%s (レベル %2d)", + race_info[current_player_ptr->prace].title,current_player_ptr->name, current_player_ptr->lev); +#else + sprintf(out_val, "You) %s the %s (Level %2d)", + current_player_ptr->name, race_info[current_player_ptr->prace].title, current_player_ptr->lev); +#endif + + prt(out_val, (m + 8), 0); + + (void)fd_close(highscore_fd); + highscore_fd = -1; + prt(_("何かキーを押すとゲームに戻ります", "Hit any key to continue"),0,0); + + (void)inkey(); + + for (j = 5; j < 18; j++) prt("", j, 0); + screen_load(); +} + + +/*! + * @brief スコアランキングの簡易表示(種族毎)サブルーチン / + * Race Legends -KMW- + * @param race_num 種族ID + * @return なし + */ +void race_score(player_type *current_player_ptr, int race_num) +{ + register int i = 0, j, m = 0; + int pr, clev, lastlev; + high_score the_score; + char buf[1024], out_val[256], tmp_str[80]; + + lastlev = 0; + + /* rr9: TODO - pluralize the race */ + sprintf(tmp_str,_("最高の%s", "The Greatest of all the %s"), race_info[race_num].title); + + prt(tmp_str, 5, 15); + path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); + + highscore_fd = fd_open(buf, O_RDONLY); + + if (highscore_fd < 0) + { + msg_print(_("スコア・ファイルが使用できません。", "Score file unavailable.")); + msg_print(NULL); + return; + } + + if (highscore_seek(0)) return; + + for (i = 0; i < MAX_HISCORES; i++) + { + if (highscore_read(&the_score)) break; + } + + m = 0; + j = 0; + + while ((m < 10) || (j < MAX_HISCORES)) + { + if (highscore_seek(j)) break; + if (highscore_read(&the_score)) break; + pr = atoi(the_score.p_r); + clev = atoi(the_score.cur_lev); + + if (pr == race_num) + { +#ifdef JP + sprintf(out_val, " %3d) %sの%s (レベル %2d)", + (m + 1), race_info[pr].title, + the_score.who,clev); +#else + sprintf(out_val, "%3d) %s the %s (Level %3d)", + (m + 1), the_score.who, + race_info[pr].title, clev); +#endif + + prt(out_val, (m + 7), 0); + m++; + lastlev = clev; + } + j++; + } + + /* add player if qualified */ + if ((current_player_ptr->prace == race_num) && (current_player_ptr->lev >= lastlev)) + { +#ifdef JP + sprintf(out_val, "あなた) %sの%s (レベル %2d)", + race_info[current_player_ptr->prace].title,current_player_ptr->name, current_player_ptr->lev); +#else + sprintf(out_val, "You) %s the %s (Level %3d)", + current_player_ptr->name, race_info[current_player_ptr->prace].title, current_player_ptr->lev); +#endif + + prt(out_val, (m + 8), 0); + } + + (void)fd_close(highscore_fd); + highscore_fd = -1; +} + + +/*! + * @brief スコアランキングの簡易表示(種族毎)メインルーチン / + * Race Legends -KMW- + * @return なし + */ +void race_legends(player_type *current_player_ptr) +{ + for (int i = 0; i < MAX_RACES; i++) + { + race_score(current_player_ptr, i); + msg_print(_("何かキーを押すとゲームに戻ります", "Hit any key to continue")); + msg_print(NULL); + for (int j = 5; j < 19; j++) + prt("", j, 0); + } +} + + +/*! + * @brief 勝利者用の引退演出処理 / + * Change the player into a King! -RAK- + * @return なし + */ +void kingly(player_type *winner_ptr) +{ + TERM_LEN wid, hgt; + TERM_LEN cx, cy; + bool seppuku = streq(winner_ptr->died_from, "Seppuku"); + + /* Hack -- retire in town */ + winner_ptr->current_floor_ptr->dun_level = 0; + + /* Fake death */ + if (!seppuku) + /* 引退したときの識別文字 */ + (void)strcpy(winner_ptr->died_from, _("ripe", "Ripe Old Age")); + + /* Restore the experience */ + winner_ptr->exp = winner_ptr->max_exp; + + /* Restore the level */ + winner_ptr->lev = winner_ptr->max_plv; + + term_get_size(&wid, &hgt); + cy = hgt / 2; + cx = wid / 2; + + /* Hack -- Instant Gold */ + winner_ptr->au += 10000000L; + term_clear(); + + /* Display a crown */ + put_str("#", cy - 11, cx - 1); + put_str("#####", cy - 10, cx - 3); + put_str("#", cy - 9, cx - 1); + put_str(",,, $$$ ,,,", cy - 8, cx - 7); + put_str(",,=$ \"$$$$$\" $=,,", cy - 7, cx - 11); + put_str(",$$ $$$ $$,", cy - 6, cx - 13); + put_str("*> <*> <*", cy - 5, cx - 13); + put_str("$$ $$$ $$", cy - 4, cx - 13); + put_str("\"$$ $$$ $$\"", cy - 3, cx - 13); + put_str("\"$$ $$$ $$\"", cy - 2, cx - 12); + put_str("*#########*#########*", cy - 1, cx - 11); + put_str("*#########*#########*", cy, cx - 11); + + /* Display a message */ +#ifdef JP + put_str("Veni, Vidi, Vici!", cy + 3, cx - 9); + put_str("来た、見た、勝った!", cy + 4, cx - 10); + put_str(format("偉大なる%s万歳!", sp_ptr->winner), cy + 5, cx - 11); +#else + put_str("Veni, Vidi, Vici!", cy + 3, cx - 9); + put_str("I came, I saw, I conquered!", cy + 4, cx - 14); + put_str(format("All Hail the Mighty %s!", sp_ptr->winner), cy + 5, cx - 13); +#endif + + /* If player did Seppuku, that is already written in playrecord */ + if (!seppuku) + { + exe_write_diary(winner_ptr, DIARY_DESCRIPTION, 0, _("ダンジョンの探索から引退した。", "retired exploring dungeons.")); + exe_write_diary(winner_ptr, DIARY_GAMESTART, 1, _("-------- ゲームオーバー --------", "-------- Game Over --------")); + exe_write_diary(winner_ptr, DIARY_DESCRIPTION, 1, "\n\n\n\n"); + } + + /* Flush input */ + flush(); + + /* Wait for response */ + pause_line(hgt - 1); +} + + +/*! + * @brief スコアファイル出力 + * Display some character info + * @return なし + */ +bool check_score(player_type *current_player_ptr) +{ + term_clear(); + + /* No score file */ + if (highscore_fd < 0) + { + msg_print(_("スコア・ファイルが使用できません。", "Score file unavailable.")); + msg_print(NULL); + return FALSE; + } + + /* Wizard-mode pre-empts scoring */ + if (current_world_ptr->noscore & 0x000F) + { + msg_print(_("ウィザード・モードではスコアが記録されません。", "Score not registered for wizards.")); + msg_print(NULL); + return FALSE; + } + + /* Cheaters are not scored */ + if (current_world_ptr->noscore & 0xFF00) + { + msg_print(_("詐欺をやった人はスコアが記録されません。", "Score not registered for cheaters.")); + msg_print(NULL); + return FALSE; + } + + /* Interupted */ + if (!current_world_ptr->total_winner && streq(current_player_ptr->died_from, _("強制終了", "Interrupting"))) + { + msg_print(_("強制終了のためスコアが記録されません。", "Score not registered due to interruption.")); + msg_print(NULL); + return FALSE; + } + + /* Quitter */ + if (!current_world_ptr->total_winner && streq(current_player_ptr->died_from, _("途中終了", "Quitting"))) + { + msg_print(_("途中終了のためスコアが記録されません。", "Score not registered due to quitting.")); + msg_print(NULL); + return FALSE; + } + return TRUE; +} diff --git a/src/core/scores.h b/src/core/scores.h new file mode 100644 index 000000000..b4bb5394a --- /dev/null +++ b/src/core/scores.h @@ -0,0 +1,51 @@ +#pragma once + +#include "io/files-util.h" +#include "system/angband.h" + +/* + * Semi-Portable High Score List Entry (128 bytes) -- BEN + * + * All fields listed below are null terminated ascii strings. + * + * In addition, the "number" fields are right justified, and + * space padded, to the full available length (minus the "null"). + * + * Note that "string comparisons" are thus valid on "pts". + */ +typedef struct high_score +{ + GAME_TEXT what[8]; /* Version info (string) */ + GAME_TEXT pts[10]; /* Total Score (number) */ + GAME_TEXT gold[10]; /* Total Gold (number) */ + GAME_TEXT turns[10]; /* Turns Taken (number) */ + GAME_TEXT day[10]; /* Time stamp (string) */ + GAME_TEXT who[16]; /* Player Name (string) */ + GAME_TEXT uid[8]; /* Player UID (number) */ + GAME_TEXT sex[2]; /* Player Sex (string) */ + GAME_TEXT p_r[3]; /* Player Race (number) */ + GAME_TEXT p_c[3]; /* Player Class (number) */ + GAME_TEXT p_a[3]; /* Player Seikaku (number) */ + + GAME_TEXT cur_lev[4]; /* Current Player Level (number) */ + GAME_TEXT cur_dun[4]; /* Current Dungeon Level (number) */ + GAME_TEXT max_lev[4]; /* Max Player Level (number) */ + GAME_TEXT max_dun[4]; /* Max Dungeon Level (number) */ + + GAME_TEXT how[40]; /* Method of death (string) */ +} high_score; + +#define MAX_HISCORES 999 /*!< スコア情報保存の最大数 / Maximum number of high scores in the high score file */ + +extern int highscore_fd; + +void display_scores_aux(int from, int to, int note, high_score *score); +void display_scores(int from, int to); +void kingly(player_type *winner_ptr); +bool send_world_score(player_type *current_player_ptr, bool do_send, void(*update_playtime)(void), display_player_pf display_player); +errr top_twenty(player_type *current_player_ptr); +errr predict_score(player_type *current_player_ptr); +void race_legends(player_type *current_player_ptr); +void race_score(player_type *current_player_ptr, int race_num); +void show_highclass(player_type *current_player_ptr); +bool check_score(player_type *current_player_ptr); diff --git a/src/core/show-file.c b/src/core/show-file.c new file mode 100644 index 000000000..a27562684 --- /dev/null +++ b/src/core/show-file.c @@ -0,0 +1,524 @@ +#include "core/show-file.h" +#include "core/asking-player.h" +#include "io/files-util.h" +#include "io/input-key-acceptor.h" +#include "main/sound-of-music.h" +#include "system/angband-version.h" +#include "term/gameterm.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "util/angband-files.h" +#include "util/int-char-converter.h" +#include "util/string-processor.h" +#include "view/display-messages.h" + +/*! + * todo 表示とそれ以外を分割する + * @brief ファイル内容の一行をコンソールに出力する + * Display single line of on-line help file + * @param str 出力する文字列 + * @param cy コンソールの行 + * @param shower 確認中 + * @return なし + * @details + *
+ * You can insert some special color tag to change text color.
+ * Such as...
+ * WHITETEXT [[[[y|SOME TEXT WHICH IS DISPLAYED IN YELLOW| WHITETEXT
+ * A colored segment is between "[[[[y|" and the last "|".
+ * You can use any single character in place of the "|".
+ * 
+ */ +static void show_file_aux_line(concptr str, int cy, concptr shower) +{ + char lcstr[1024]; + if (shower) + { + strcpy(lcstr, str); + str_tolower(lcstr); + } + + int cx = 0; + term_gotoxy(cx, cy); + + static const char tag_str[] = "[[[["; + byte color = TERM_WHITE; + char in_tag = '\0'; + for (int i = 0; str[i];) + { + int len = strlen(&str[i]); + int showercol = len + 1; + int bracketcol = len + 1; + int endcol = len; + concptr ptr; + if (shower) + { + ptr = angband_strstr(&lcstr[i], shower); + if (ptr) showercol = ptr - &lcstr[i]; + } + + ptr = in_tag ? angband_strchr(&str[i], in_tag) : angband_strstr(&str[i], tag_str); + if (ptr) bracketcol = ptr - &str[i]; + if (bracketcol < endcol) endcol = bracketcol; + if (showercol < endcol) endcol = showercol; + + term_addstr(endcol, color, &str[i]); + cx += endcol; + i += endcol; + + if (shower && endcol == showercol) + { + int showerlen = strlen(shower); + term_addstr(showerlen, TERM_YELLOW, &str[i]); + cx += showerlen; + i += showerlen; + continue; + } + + if (endcol != bracketcol) continue; + + if (in_tag) + { + i++; + in_tag = '\0'; + color = TERM_WHITE; + continue; + } + + i += sizeof(tag_str) - 1; + color = color_char_to_attr(str[i]); + if (color == 255 || str[i + 1] == '\0') + { + color = TERM_WHITE; + term_addstr(-1, TERM_WHITE, tag_str); + cx += sizeof(tag_str) - 1; + continue; + } + + i++; + in_tag = str[i]; + i++; + } + + term_erase(cx, cy, 255); +} + + +/*! + * todo 表示とそれ以外を分割する + * @brief ファイル内容をコンソールに出力する + * Recursive file perusal. + * @param creature_ptr プレーヤーへの参照ポインタ + * @param show_version TRUEならばコンソール上にゲームのバージョンを表示する + * @param name ファイル名の文字列 + * @param what 内容キャプションの文字列 + * @param line 表示の現在行 + * @param mode オプション + * @return なし + * @details + *
+ * Process various special text in the input file, including
+ * the "menu" structures used by the "help file" system.
+ * Return FALSE on 'q' to exit from a deep, otherwise TRUE.
+ * 
+ */ +bool show_file(player_type *creature_ptr, bool show_version, concptr name, concptr what, int line, BIT_FLAGS mode) +{ + int wid, hgt; + term_get_size(&wid, &hgt); + + char finder_str[81]; + strcpy(finder_str, ""); + + char shower_str[81]; + strcpy(shower_str, ""); + + char caption[128]; + strcpy(caption, ""); + + char hook[68][32]; + for (int i = 0; i < 68; i++) + { + hook[i][0] = '\0'; + } + + char filename[1024]; + strcpy(filename, name); + int n = strlen(filename); + + concptr tag = NULL; + for (int i = 0; i < n; i++) + { + if (filename[i] == '#') + { + filename[i] = '\0'; + tag = filename + i + 1; + break; + } + } + + name = filename; + FILE *fff = NULL; + char path[1024]; + if (what) + { + strcpy(caption, what); + strcpy(path, name); + fff = angband_fopen(path, "r"); + } + + if (!fff) + { + sprintf(caption, _("ヘルプ・ファイル'%s'", "Help file '%s'"), name); + path_build(path, sizeof(path), ANGBAND_DIR_HELP, name); + fff = angband_fopen(path, "r"); + } + + if (!fff) + { + sprintf(caption, _("スポイラー・ファイル'%s'", "Info file '%s'"), name); + path_build(path, sizeof(path), ANGBAND_DIR_INFO, name); + fff = angband_fopen(path, "r"); + } + + if (!fff) + { + path_build(path, sizeof(path), ANGBAND_DIR, name); + + for (int i = 0; path[i]; i++) + if ('\\' == path[i]) + path[i] = PATH_SEP[0]; + + sprintf(caption, _("スポイラー・ファイル'%s'", "Info file '%s'"), name); + fff = angband_fopen(path, "r"); + } + + if (!fff) + { + msg_format(_("'%s'をオープンできません。", "Cannot open '%s'."), name); + msg_print(NULL); + + return TRUE; + } + + int skey; + int next = 0; + int size = 0; + int back = 0; + bool menu = FALSE; + char buf[1024]; + bool reverse = (line < 0); + while (TRUE) + { + char *str = buf; + if (angband_fgets(fff, buf, sizeof(buf))) break; + if (!prefix(str, "***** ")) + { + next++; + continue; + } + + if ((str[6] == '[') && isalpha(str[7])) + { + int k = str[7] - 'A'; + menu = TRUE; + if ((str[8] == ']') && (str[9] == ' ')) + { + strncpy(hook[k], str + 10, 31); + hook[k][31] = '\0'; + } + + continue; + } + + if (str[6] != '<') continue; + + size_t len = strlen(str); + if (str[len - 1] == '>') + { + str[len - 1] = '\0'; + if (tag && streq(str + 7, tag)) line = next; + } + } + + size = next; + int rows = hgt - 4; + if (line == -1) + line = ((size - 1) / rows)*rows; + + term_clear(); + + concptr find = NULL; + while (TRUE) + { + if (line >= size - rows) + line = size - rows; + if (line < 0) line = 0; + + if (next > line) + { + angband_fclose(fff); + fff = angband_fopen(path, "r"); + if (!fff) return FALSE; + + next = 0; + } + + while (next < line) + { + if (angband_fgets(fff, buf, sizeof(buf))) break; + if (prefix(buf, "***** ")) continue; + next++; + } + + int row_count = 0; + concptr shower = NULL; + for (int i = 0; i < rows; i++) + { + concptr str = buf; + if (!i) line = next; + if (angband_fgets(fff, buf, sizeof(buf))) break; + if (prefix(buf, "***** ")) continue; + next++; + if (find && !i) + { + char lc_buf[1024]; + strcpy(lc_buf, str); + str_tolower(lc_buf); + if (!angband_strstr(lc_buf, find)) continue; + } + + find = NULL; + show_file_aux_line(str, i + 2, shower); + row_count++; + } + + while (row_count < rows) + { + term_erase(0, row_count + 2, 255); + row_count++; + } + + if (find) + { + bell(); + line = back; + find = NULL; + continue; + } + + if (show_version) + { + prt(format(_("[馬鹿馬鹿蛮怒 %d.%d.%d, %s, %d/%d]", "[Bakabakaband %d.%d.%d, %s, Line %d/%d]"), + FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, + caption, line, size), 0, 0); + } + else + { + prt(format(_("[%s, %d/%d]", "[%s, Line %d/%d]"), + caption, line, size), 0, 0); + } + + if (size <= rows) + { + prt(_("[キー:(?)ヘルプ (ESC)終了]", "[Press ESC to exit.]"), hgt - 1, 0); + } + else + { +#ifdef JP + if (reverse) + prt("[キー:(RET/スペース)↑ (-)↓ (?)ヘルプ (ESC)終了]", hgt - 1, 0); + else + prt("[キー:(RET/スペース)↓ (-)↑ (?)ヘルプ (ESC)終了]", hgt - 1, 0); +#else + prt("[Press Return, Space, -, =, /, |, or ESC to exit.]", hgt - 1, 0); +#endif + } + + skey = inkey_special(TRUE); + switch (skey) + { + case '?': + if (strcmp(name, _("jhelpinfo.txt", "helpinfo.txt")) != 0) + show_file(creature_ptr, TRUE, _("jhelpinfo.txt", "helpinfo.txt"), NULL, 0, mode); + break; + case '=': + prt(_("強調: ", "Show: "), hgt - 1, 0); + + char back_str[81]; + strcpy(back_str, shower_str); + if (askfor(shower_str, 80)) + { + if (shower_str[0]) + { + str_tolower(shower_str); + shower = shower_str; + } + else shower = NULL; + } + else strcpy(shower_str, back_str); + break; + + case '/': + case KTRL('s'): + prt(_("検索: ", "Find: "), hgt - 1, 0); + strcpy(back_str, finder_str); + if (askfor(finder_str, 80)) + { + if (finder_str[0]) + { + find = finder_str; + back = line; + line = line + 1; + str_tolower(finder_str); + shower = finder_str; + } + else shower = NULL; + } + else strcpy(finder_str, back_str); + break; + + case '#': + { + char tmp[81]; + prt(_("行: ", "Goto Line: "), hgt - 1, 0); + strcpy(tmp, "0"); + + if (askfor(tmp, 80)) line = atoi(tmp); + break; + } + + case SKEY_TOP: + line = 0; + break; + + case SKEY_BOTTOM: + line = ((size - 1) / rows) * rows; + break; + + case '%': + { + char tmp[81]; + prt(_("ファイル・ネーム: ", "Goto File: "), hgt - 1, 0); + strcpy(tmp, _("jhelp.hlp", "help.hlp")); + + if (askfor(tmp, 80)) + { + if (!show_file(creature_ptr, TRUE, tmp, NULL, 0, mode)) skey = 'q'; + } + + break; + } + + case '-': + line = line + (reverse ? rows : -rows); + if (line < 0) line = 0; + break; + + case SKEY_PGUP: + line = line - rows; + if (line < 0) line = 0; + break; + + case '\n': + case '\r': + line = line + (reverse ? -1 : 1); + if (line < 0) line = 0; + break; + + case '8': + case SKEY_UP: + line--; + if (line < 0) line = 0; + break; + + case '2': + case SKEY_DOWN: + line++; + break; + + case ' ': + line = line + (reverse ? -rows : rows); + if (line < 0) line = 0; + break; + + case SKEY_PGDOWN: + line = line + rows; + break; + } + + if (menu) + { + int key = -1; + if (!(skey & SKEY_MASK) && isalpha(skey)) + key = skey - 'A'; + + if ((key > -1) && hook[key][0]) + { + /* Recurse on that file */ + if (!show_file(creature_ptr, TRUE, hook[key], NULL, 0, mode)) + skey = 'q'; + } + } + + if (skey == '|') + { + FILE *ffp; + char buff[1024]; + char xtmp[82]; + + strcpy(xtmp, ""); + + if (!get_string(_("ファイル名: ", "File name: "), xtmp, 80)) continue; + angband_fclose(fff); + path_build(buff, sizeof(buff), ANGBAND_DIR_USER, xtmp); + + /* Hack -- Re-Open the file */ + fff = angband_fopen(path, "r"); + + ffp = angband_fopen(buff, "w"); + + if (!(fff && ffp)) + { + msg_print(_("ファイルを開けません。", "Failed to open file.")); + skey = ESCAPE; + break; + } + + sprintf(xtmp, "%s: %s", creature_ptr->name, what ? what : caption); + angband_fputs(ffp, xtmp, 80); + angband_fputs(ffp, "\n", 80); + + while (!angband_fgets(fff, buff, sizeof(buff))) + angband_fputs(ffp, buff, 80); + angband_fclose(fff); + angband_fclose(ffp); + fff = angband_fopen(path, "r"); + } + + if ((skey == ESCAPE) || (skey == '<')) break; + + if (skey == KTRL('q')) skey = 'q'; + + if (skey == 'q') break; + } + + angband_fclose(fff); + return (skey != 'q'); +} + +/* + * Convert string to lower case + */ +void str_tolower(char *str) +{ + for (; *str; str++) { +#ifdef JP + if (iskanji(*str)) { + str++; + continue; + } +#endif + *str = (char)tolower(*str); + } +} diff --git a/src/core/show-file.h b/src/core/show-file.h new file mode 100644 index 000000000..74b25cbca --- /dev/null +++ b/src/core/show-file.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" + +bool show_file(player_type *player_ptr, bool show_version, concptr name, concptr what, int line, BIT_FLAGS mode); +void str_tolower(char *str); diff --git a/src/core/special-internal-keys.h b/src/core/special-internal-keys.h new file mode 100644 index 000000000..f95335d67 --- /dev/null +++ b/src/core/special-internal-keys.h @@ -0,0 +1,9 @@ +#pragma once + +/* + * Special internal key + */ +#define SPECIAL_KEY_QUEST 255 +#define SPECIAL_KEY_BUILDING 254 +#define SPECIAL_KEY_STORE 253 +#define SPECIAL_KEY_QUIT 252 diff --git a/src/core/speed-table.c b/src/core/speed-table.c new file mode 100644 index 000000000..5aa1ca0f8 --- /dev/null +++ b/src/core/speed-table.c @@ -0,0 +1,51 @@ +#include "core/speed-table.h" + +/*! + * @brief 加速値による実質速度修正倍率テーブル / + * This table allows quick conversion from "speed" to "energy" + * @date 2019/05/10 + * @author deskull + * @details + * The basic function WAS ((S>=110) ? (S-110) : (100 / (120-S))) + * Note that table access is *much* quicker than computation. + * + * Note that the table has been changed at high speeds. From + * "Slow (-40)" to "Fast (+30)" is pretty much unchanged, but + * at speeds above "Fast (+30)", one approaches an asymptotic + * effective limit of 50 energy per turn. This means that it + * is relatively easy to reach "Fast (+30)" and get about 40 + * energy per turn, but then speed becomes very "expensive", + * and you must get all the way to "Fast (+50)" to reach the + * point of getting 45 energy per turn. After that point, + * furthur increases in speed are more or less pointless, + * except to balance out heavy inventory. + * + * Note that currently the fastest monster is "Fast (+30)". + * + * It should be possible to lower the energy threshhold from + * 100 units to 50 units, though this may interact badly with + * the (compiled out) small random energy boost code. It may + * also tend to cause more "clumping" at high speeds. + */ +const byte extract_energy[NUM_SPEED] = { + /* Slow */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* Slow */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* Slow */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* Slow */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* Slow */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* Slow */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* S-50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* S-40 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + /* S-30 */ 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, + /* S-20 */ 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, + /* S-10 */ 5, 5, 5, 5, 6, 6, 7, 7, 8, 9, + /* Norm */ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + /* F+10 */ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + /* F+20 */ 30, 31, 32, 33, 34, 35, 36, 36, 37, 37, + /* F+30 */ 38, 38, 39, 39, 40, 40, 40, 41, 41, 41, + /* F+40 */ 42, 42, 42, 43, 43, 43, 44, 44, 44, 44, + /* F+50 */ 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, + /* F+60 */ 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, + /* F+70 */ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + /* Fast */ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, +}; diff --git a/src/core/speed-table.h b/src/core/speed-table.h new file mode 100644 index 000000000..0f6a1cea6 --- /dev/null +++ b/src/core/speed-table.h @@ -0,0 +1,13 @@ +#pragma once + +#include "system/angband.h" + +#define NUM_SPEED 200 + +/*! @brief 消費する行動エネルギー値を正規乱数で返す(中央100/分散25) / Random energy */ +#define ENERGY_NEED() (randnor(100, 25)) + +/*! @brief 加速値に応じた基本行動エネルギー消費量を返す / Extract energy from speed (Assumes that SPEED is unsigned) */ +#define SPEED_TO_ENERGY(SPEED) (((SPEED) > 199) ? 49 : extract_energy[(SPEED)]) + +extern const byte extract_energy[NUM_SPEED]; diff --git a/src/core/status-reseter.c b/src/core/status-reseter.c new file mode 100644 index 000000000..a86162730 --- /dev/null +++ b/src/core/status-reseter.c @@ -0,0 +1,93 @@ +#include "core/status-reseter.h" +#include "core/speed-table.h" +#include "monster/monster-status-setter.h" +#include "player/attack-defense-types.h" +#include "player/player-race.h" + +/*! + * @brief プレイヤーの全ての時限効果をリセットする。 / reset timed flags + * @return なし + */ +void reset_tim_flags(player_type *creature_ptr) +{ + creature_ptr->fast = 0; /* Timed -- Fast */ + creature_ptr->lightspeed = 0; + creature_ptr->slow = 0; /* Timed -- Slow */ + creature_ptr->blind = 0; /* Timed -- Blindness */ + creature_ptr->paralyzed = 0; /* Timed -- Paralysis */ + creature_ptr->confused = 0; /* Timed -- Confusion */ + creature_ptr->afraid = 0; /* Timed -- Fear */ + creature_ptr->image = 0; /* Timed -- Hallucination */ + creature_ptr->poisoned = 0; /* Timed -- Poisoned */ + creature_ptr->cut = 0; /* Timed -- Cut */ + creature_ptr->stun = 0; /* Timed -- Stun */ + + creature_ptr->protevil = 0; /* Timed -- Protection */ + creature_ptr->invuln = 0; /* Timed -- Invulnerable */ + creature_ptr->ult_res = 0; + creature_ptr->hero = 0; /* Timed -- Heroism */ + creature_ptr->shero = 0; /* Timed -- Super Heroism */ + creature_ptr->shield = 0; /* Timed -- Shield Spell */ + creature_ptr->blessed = 0; /* Timed -- Blessed */ + creature_ptr->tim_invis = 0; /* Timed -- Invisibility */ + creature_ptr->tim_infra = 0; /* Timed -- Infra Vision */ + creature_ptr->tim_regen = 0; /* Timed -- Regeneration */ + creature_ptr->tim_stealth = 0; /* Timed -- Stealth */ + creature_ptr->tim_esp = 0; + creature_ptr->wraith_form = 0; /* Timed -- Wraith Form */ + creature_ptr->tim_levitation = 0; + creature_ptr->tim_sh_touki = 0; + creature_ptr->tim_sh_fire = 0; + creature_ptr->tim_sh_holy = 0; + creature_ptr->tim_eyeeye = 0; + creature_ptr->magicdef = 0; + creature_ptr->resist_magic = 0; + creature_ptr->tsuyoshi = 0; + creature_ptr->tim_pass_wall = 0; + creature_ptr->tim_res_nether = 0; + creature_ptr->tim_res_time = 0; + creature_ptr->tim_mimic = 0; + creature_ptr->mimic_form = 0; + creature_ptr->tim_reflect = 0; + creature_ptr->multishadow = 0; + creature_ptr->dustrobe = 0; + creature_ptr->action = ACTION_NONE; + + creature_ptr->oppose_acid = 0; /* Timed -- oppose acid */ + creature_ptr->oppose_elec = 0; /* Timed -- oppose lightning */ + creature_ptr->oppose_fire = 0; /* Timed -- oppose heat */ + creature_ptr->oppose_cold = 0; /* Timed -- oppose cold */ + creature_ptr->oppose_pois = 0; /* Timed -- oppose poison */ + + creature_ptr->word_recall = 0; + creature_ptr->alter_reality = 0; + creature_ptr->sutemi = FALSE; + creature_ptr->counter = FALSE; + creature_ptr->ele_attack = 0; + creature_ptr->ele_immune = 0; + creature_ptr->special_attack = 0L; + creature_ptr->special_defense = 0L; + + while (creature_ptr->energy_need < 0) + creature_ptr->energy_need += ENERGY_NEED(); + + creature_ptr->timewalk = FALSE; + + if (is_specific_player_race(creature_ptr, RACE_BALROG) && (creature_ptr->lev > 44)) + creature_ptr->oppose_fire = 1; + if ((creature_ptr->pclass == CLASS_NINJA) && (creature_ptr->lev > 44)) + creature_ptr->oppose_pois = 1; + if (creature_ptr->pclass == CLASS_BERSERKER) + creature_ptr->shero = 1; + + if (creature_ptr->riding) { + (void)set_monster_fast(creature_ptr, creature_ptr->riding, 0); + (void)set_monster_slow(creature_ptr, creature_ptr->riding, 0); + (void)set_monster_invulner(creature_ptr, creature_ptr->riding, 0, FALSE); + } + + if (creature_ptr->pclass == CLASS_BARD) { + SINGING_SONG_EFFECT(creature_ptr) = 0; + SINGING_SONG_ID(creature_ptr) = 0; + } +} diff --git a/src/core/status-reseter.h b/src/core/status-reseter.h new file mode 100644 index 000000000..fcaf6b593 --- /dev/null +++ b/src/core/status-reseter.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void reset_tim_flags(player_type *creature_ptr); diff --git a/src/core/stuff-handler.c b/src/core/stuff-handler.c new file mode 100644 index 000000000..50105d554 --- /dev/null +++ b/src/core/stuff-handler.c @@ -0,0 +1,71 @@ +#include "core/stuff-handler.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" + +/*! + * @brief 全更新処理をチェックして処理していく + * Handle "player_ptr->update" and "player_ptr->redraw" and "player_ptr->window" + * @return なし + */ +void handle_stuff(player_type* player_ptr) +{ + if (player_ptr->update) + update_creature(player_ptr); + if (player_ptr->redraw) + redraw_stuff(player_ptr); + if (player_ptr->window) + window_stuff(player_ptr); +} + +/* + * Track the given monster race + */ +void monster_race_track(player_type *player_ptr, MONRACE_IDX r_idx) +{ + player_ptr->monster_race_idx = r_idx; + player_ptr->window |= (PW_MONSTER); +} + +/* + * Track the given object kind + */ +void object_kind_track(player_type *player_ptr, KIND_OBJECT_IDX k_idx) +{ + player_ptr->object_kind_idx = k_idx; + player_ptr->window |= (PW_OBJECT); +} + +/* + * Track a new monster + * @param player_ptr プレーヤーへの参照ポインタ + * @param m_idx トラッキング対象のモンスターID。0の時キャンセル + * @param なし + */ +void health_track(player_type *player_ptr, MONSTER_IDX m_idx) +{ + if (m_idx && m_idx == player_ptr->riding) + return; + + player_ptr->health_who = m_idx; + player_ptr->redraw |= (PR_HEALTH); +} + +bool update_player(player_type *caster_ptr) +{ + caster_ptr->update |= PU_COMBINE | PU_REORDER; + caster_ptr->window |= PW_INVEN; + return TRUE; +} + +bool redraw_player(player_type *caster_ptr) +{ + if (caster_ptr->csp > caster_ptr->msp) { + caster_ptr->csp = caster_ptr->msp; + } + + caster_ptr->redraw |= PR_MANA; + caster_ptr->update |= PU_COMBINE | PU_REORDER; + caster_ptr->window |= PW_INVEN; + return TRUE; +} diff --git a/src/core/stuff-handler.h b/src/core/stuff-handler.h new file mode 100644 index 000000000..054dfd286 --- /dev/null +++ b/src/core/stuff-handler.h @@ -0,0 +1,11 @@ +#pragma once + +#include "system/angband.h" + +void handle_stuff(player_type* player_ptr); +void monster_race_track(player_type *player_ptr, MONRACE_IDX r_idx); +void object_kind_track(player_type *player_ptr, KIND_OBJECT_IDX k_idx); +void health_track(player_type *player_ptr, MONSTER_IDX m_idx); + +bool update_player(player_type *caster_ptr); +bool redraw_player(player_type *caster_ptr); diff --git a/src/core/turn-compensator.c b/src/core/turn-compensator.c new file mode 100644 index 000000000..b73abb588 --- /dev/null +++ b/src/core/turn-compensator.c @@ -0,0 +1,78 @@ +#include "core/turn-compensator.h" +#include "floor/floor-town.h" +#include "player/player-race-types.h" +#include "store/store-owners.h" +#include "store/store-util.h" +#include "store/store.h" +#include "system/floor-type-definition.h" +#include "world/world.h" + +/*! + * @brief ゲームターンからの実時間換算を行うための補正をかける + * @param hoge ゲームターン + * @details アンデッド種族は18:00からゲームを開始するので、この修正を予め行う。 + * @return 修正をかけた後のゲームターン + */ +s32b turn_real(player_type *player_ptr, s32b hoge) +{ + switch (player_ptr->start_race) { + case RACE_VAMPIRE: + case RACE_SKELETON: + case RACE_ZOMBIE: + case RACE_SPECTRE: + return hoge - (TURNS_PER_TICK * TOWN_DAWN * 3 / 4); + default: + return hoge; + } +} + +/*! + * @brief ターンのオーバーフローに対する対処 + * @param player_ptr プレーヤーへの参照ポインタ + * @details ターン及びターンを記録する変数をターンの限界の1日前まで巻き戻す. + * @return 修正をかけた後のゲームターン + */ +void prevent_turn_overflow(player_type *player_ptr) +{ + if (current_world_ptr->game_turn < current_world_ptr->game_turn_limit) + return; + + int rollback_days = 1 + (current_world_ptr->game_turn - current_world_ptr->game_turn_limit) / (TURNS_PER_TICK * TOWN_DAWN); + s32b rollback_turns = TURNS_PER_TICK * TOWN_DAWN * rollback_days; + + if (current_world_ptr->game_turn > rollback_turns) + current_world_ptr->game_turn -= rollback_turns; + else + current_world_ptr->game_turn = 1; + floor_type *floor_ptr = player_ptr->current_floor_ptr; + if (floor_ptr->generated_turn > rollback_turns) + floor_ptr->generated_turn -= rollback_turns; + else + floor_ptr->generated_turn = 1; + if (current_world_ptr->arena_start_turn > rollback_turns) + current_world_ptr->arena_start_turn -= rollback_turns; + else + current_world_ptr->arena_start_turn = 1; + if (player_ptr->feeling_turn > rollback_turns) + player_ptr->feeling_turn -= rollback_turns; + else + player_ptr->feeling_turn = 1; + + for (int i = 1; i < max_towns; i++) { + for (int j = 0; j < MAX_STORES; j++) { + store_type *store_ptr = &town_info[i].store[j]; + + if (store_ptr->last_visit > -10L * TURNS_PER_TICK * STORE_TICKS) { + store_ptr->last_visit -= rollback_turns; + if (store_ptr->last_visit < -10L * TURNS_PER_TICK * STORE_TICKS) + store_ptr->last_visit = -10L * TURNS_PER_TICK * STORE_TICKS; + } + + if (store_ptr->store_open) { + store_ptr->store_open -= rollback_turns; + if (store_ptr->store_open < 1) + store_ptr->store_open = 1; + } + } + } +} diff --git a/src/core/turn-compensator.h b/src/core/turn-compensator.h new file mode 100644 index 000000000..98aea4433 --- /dev/null +++ b/src/core/turn-compensator.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" + +s32b turn_real(player_type* player_ptr, s32b hoge); +void prevent_turn_overflow(player_type* player_ptr); diff --git a/src/core/visuals-reseter.c b/src/core/visuals-reseter.c new file mode 100644 index 000000000..2dd98cbca --- /dev/null +++ b/src/core/visuals-reseter.c @@ -0,0 +1,42 @@ +#include "core/visuals-reseter.h" +#include "game-option/special-options.h" +#include "grid/feature.h" +#include "io/read-pref-file.h" +#include "monster-race/monster-race.h" +#include "object/object-kind.h" + +/*! + * @brief オブジェクト、地形の表示シンボルなど初期化する / Reset the "visual" lists + * @param owner_ptr プレーヤーへの参照ポインタ + * @param process_autopick_file_command 自動拾いファイル読み込みへの関数ポインタ + * @return なし + */ +void reset_visuals(player_type *owner_ptr, void (*process_autopick_file_command)(char *)) +{ + for (int i = 0; i < max_f_idx; i++) { + feature_type *f_ptr = &f_info[i]; + for (int j = 0; j < F_LIT_MAX; j++) { + f_ptr->x_attr[j] = f_ptr->d_attr[j]; + f_ptr->x_char[j] = f_ptr->d_char[j]; + } + } + + for (int i = 0; i < max_k_idx; i++) { + object_kind *k_ptr = &k_info[i]; + k_ptr->x_attr = k_ptr->d_attr; + k_ptr->x_char = k_ptr->d_char; + } + + for (int i = 0; i < max_r_idx; i++) { + monster_race *r_ptr = &r_info[i]; + r_ptr->x_attr = r_ptr->d_attr; + r_ptr->x_char = r_ptr->d_char; + } + + char *pref_file = use_graphics ? "graf.prf" : "font.prf"; + char *base_name = use_graphics ? "graf-%s.prf" : "font-%s.prf"; + char buf[1024]; + process_pref_file(owner_ptr, pref_file, process_autopick_file_command); + sprintf(buf, base_name, owner_ptr->base_name); + process_pref_file(owner_ptr, buf, process_autopick_file_command); +} diff --git a/src/core/visuals-reseter.h b/src/core/visuals-reseter.h new file mode 100644 index 000000000..41253e1b5 --- /dev/null +++ b/src/core/visuals-reseter.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void reset_visuals(player_type *owner_ptr, void (*process_autopick_file_command)(char *)); diff --git a/src/core/window-redrawer.c b/src/core/window-redrawer.c new file mode 100644 index 000000000..135bd71d2 --- /dev/null +++ b/src/core/window-redrawer.c @@ -0,0 +1,292 @@ +/*! + * @brief ウィンドウの再描画処理 + * @date 2020/06/27 + * @author Hourier + */ +#include "core/window-redrawer.h" +#include "core/player-redraw-types.h" +#include "core/stuff-handler.h" +#include "floor/floor-util.h" +#include "game-option/option-flags.h" +#include "player/player-race.h" +#include "term/gameterm.h" +#include "term/screen-processor.h" +#include "term/term-color-types.h" +#include "view/display-messages.h" +#include "view/display-player.h" +#include "window/display-sub-windows.h" +#include "window/display-sub-window-spells.h" +#include "window/main-window-left-frame.h" +#include "window/main-window-row-column.h" +#include "window/main-window-stat-poster.h" +#include "window/main-window-util.h" +#include "world/world-turn-processor.h" +#include "world/world.h" + +/*! + * todo ここにplayer_type を追加するとz-termに影響が行くので保留 + * @brief コンソールを再描画する / + * Redraw a term when it is resized + * @return なし + */ +void redraw_window(void) +{ + if (!current_world_ptr->character_dungeon) + return; + + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER); + p_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_DUNGEON | PW_MONSTER | PW_OBJECT); + + handle_stuff(p_ptr); + term_redraw(); +} + +/*! + * @brief 現在のマップ名を描画する / Print dungeon + * @param creature_ptr プレーヤーへの参照ポインタ + * @return なし + */ +static void print_dungeon(player_type *creature_ptr) +{ + c_put_str(TERM_WHITE, " ", ROW_DUNGEON, COL_DUNGEON); + concptr dungeon_name = map_name(creature_ptr); + TERM_LEN col = COL_DUNGEON + 6 - strlen(dungeon_name) / 2; + if (col < 0) + col = 0; + + c_put_str(TERM_L_UMBER, format("%s", dungeon_name), ROW_DUNGEON, col); +} + +/*! + * @brief redraw のフラグに応じた更新をまとめて行う / Handle "redraw" + * @return なし + * @details 更新処理の対象はゲーム中の全描画処理 + */ +void redraw_stuff(player_type *creature_ptr) +{ + if (!creature_ptr->redraw) + return; + + if (!current_world_ptr->character_generated) + return; + + if (current_world_ptr->character_icky) + return; + + if (creature_ptr->redraw & (PR_WIPE)) { + creature_ptr->redraw &= ~(PR_WIPE); + msg_print(NULL); + term_clear(); + } + + if (creature_ptr->redraw & (PR_MAP)) { + creature_ptr->redraw &= ~(PR_MAP); + print_map(creature_ptr); + } + + if (creature_ptr->redraw & (PR_BASIC)) { + creature_ptr->redraw &= ~(PR_BASIC); + creature_ptr->redraw &= ~(PR_MISC | PR_TITLE | PR_STATS); + creature_ptr->redraw &= ~(PR_LEV | PR_EXP | PR_GOLD); + creature_ptr->redraw &= ~(PR_ARMOR | PR_HP | PR_MANA); + creature_ptr->redraw &= ~(PR_DEPTH | PR_HEALTH | PR_UHEALTH); + print_frame_basic(creature_ptr); + print_time(creature_ptr); + print_dungeon(creature_ptr); + } + + if (creature_ptr->redraw & (PR_EQUIPPY)) { + creature_ptr->redraw &= ~(PR_EQUIPPY); + display_player_equippy(creature_ptr, ROW_EQUIPPY, COL_EQUIPPY, 0); + } + + if (creature_ptr->redraw & (PR_MISC)) { + creature_ptr->redraw &= ~(PR_MISC); + print_field(rp_ptr->title, ROW_RACE, COL_RACE); + } + + if (creature_ptr->redraw & (PR_TITLE)) { + creature_ptr->redraw &= ~(PR_TITLE); + print_title(creature_ptr); + } + + if (creature_ptr->redraw & (PR_LEV)) { + creature_ptr->redraw &= ~(PR_LEV); + print_level(creature_ptr); + } + + if (creature_ptr->redraw & (PR_EXP)) { + creature_ptr->redraw &= ~(PR_EXP); + print_exp(creature_ptr); + } + + if (creature_ptr->redraw & (PR_STATS)) { + creature_ptr->redraw &= ~(PR_STATS); + print_stat(creature_ptr, A_STR); + print_stat(creature_ptr, A_INT); + print_stat(creature_ptr, A_WIS); + print_stat(creature_ptr, A_DEX); + print_stat(creature_ptr, A_CON); + print_stat(creature_ptr, A_CHR); + } + + if (creature_ptr->redraw & (PR_STATUS)) { + creature_ptr->redraw &= ~(PR_STATUS); + print_status(creature_ptr); + } + + if (creature_ptr->redraw & (PR_ARMOR)) { + creature_ptr->redraw &= ~(PR_ARMOR); + print_ac(creature_ptr); + } + + if (creature_ptr->redraw & (PR_HP)) { + creature_ptr->redraw &= ~(PR_HP); + print_hp(creature_ptr); + } + + if (creature_ptr->redraw & (PR_MANA)) { + creature_ptr->redraw &= ~(PR_MANA); + print_sp(creature_ptr); + } + + if (creature_ptr->redraw & (PR_GOLD)) { + creature_ptr->redraw &= ~(PR_GOLD); + print_gold(creature_ptr); + } + + if (creature_ptr->redraw & (PR_DEPTH)) { + creature_ptr->redraw &= ~(PR_DEPTH); + print_depth(creature_ptr); + } + + if (creature_ptr->redraw & (PR_HEALTH)) { + creature_ptr->redraw &= ~(PR_HEALTH); + health_redraw(creature_ptr, FALSE); + } + + if (creature_ptr->redraw & (PR_UHEALTH)) { + creature_ptr->redraw &= ~(PR_UHEALTH); + health_redraw(creature_ptr, TRUE); + } + + if (creature_ptr->redraw & (PR_EXTRA)) { + creature_ptr->redraw &= ~(PR_EXTRA); + creature_ptr->redraw &= ~(PR_CUT | PR_STUN); + creature_ptr->redraw &= ~(PR_HUNGER); + creature_ptr->redraw &= ~(PR_STATE | PR_SPEED | PR_STUDY | PR_IMITATION | PR_STATUS); + print_frame_extra(creature_ptr); + } + + if (creature_ptr->redraw & (PR_CUT)) { + creature_ptr->redraw &= ~(PR_CUT); + print_cut(creature_ptr); + } + + if (creature_ptr->redraw & (PR_STUN)) { + creature_ptr->redraw &= ~(PR_STUN); + print_stun(creature_ptr); + } + + if (creature_ptr->redraw & (PR_HUNGER)) { + creature_ptr->redraw &= ~(PR_HUNGER); + print_hunger(creature_ptr); + } + + if (creature_ptr->redraw & (PR_STATE)) { + creature_ptr->redraw &= ~(PR_STATE); + print_state(creature_ptr); + } + + if (creature_ptr->redraw & (PR_SPEED)) { + creature_ptr->redraw &= ~(PR_SPEED); + print_speed(creature_ptr); + } + + if (creature_ptr->pclass == CLASS_IMITATOR) { + if (creature_ptr->redraw & (PR_IMITATION)) { + creature_ptr->redraw &= ~(PR_IMITATION); + print_imitation(creature_ptr); + } + + return; + } + + if (creature_ptr->redraw & (PR_STUDY)) { + creature_ptr->redraw &= ~(PR_STUDY); + print_study(creature_ptr); + } +} + +/*! + * @brief player_ptr->window のフラグに応じた更新をまとめて行う / Handle "player_ptr->window" + * @param player_ptr プレーヤーへの参照ポインタ + * @return なし + * @details 更新処理の対象はサブウィンドウ全般 + */ +void window_stuff(player_type *player_ptr) +{ + if (!player_ptr->window) + return; + + BIT_FLAGS mask = 0L; + for (int j = 0; j < 8; j++) { + if (angband_term[j]) + mask |= window_flag[j]; + } + + player_ptr->window &= mask; + + if (!player_ptr->window) + return; + + if (player_ptr->window & (PW_INVEN)) { + player_ptr->window &= ~(PW_INVEN); + fix_inventory(player_ptr, 0); // TODO:2.2.2 まともなtval参照手段を確保 + } + + if (player_ptr->window & (PW_EQUIP)) { + player_ptr->window &= ~(PW_EQUIP); + fix_equip(player_ptr, 0); // TODO:2.2.2 まともなtval参照手段を確保 + } + + if (player_ptr->window & (PW_SPELL)) { + player_ptr->window &= ~(PW_SPELL); + fix_spell(player_ptr); + } + + if (player_ptr->window & (PW_PLAYER)) { + player_ptr->window &= ~(PW_PLAYER); + fix_player(player_ptr); + } + + if (player_ptr->window & (PW_MONSTER_LIST)) { + player_ptr->window &= ~(PW_MONSTER_LIST); + fix_monster_list(player_ptr); + } + + if (player_ptr->window & (PW_MESSAGE)) { + player_ptr->window &= ~(PW_MESSAGE); + fix_message(); + } + + if (player_ptr->window & (PW_OVERHEAD)) { + player_ptr->window &= ~(PW_OVERHEAD); + fix_overhead(player_ptr); + } + + if (player_ptr->window & (PW_DUNGEON)) { + player_ptr->window &= ~(PW_DUNGEON); + fix_dungeon(player_ptr); + } + + if (player_ptr->window & (PW_MONSTER)) { + player_ptr->window &= ~(PW_MONSTER); + fix_monster(player_ptr); + } + + if (player_ptr->window & (PW_OBJECT)) { + player_ptr->window &= ~(PW_OBJECT); + fix_object(player_ptr); + } +} diff --git a/src/core/window-redrawer.h b/src/core/window-redrawer.h new file mode 100644 index 000000000..444425100 --- /dev/null +++ b/src/core/window-redrawer.h @@ -0,0 +1,21 @@ +#pragma once + +#include "system/angband.h" + +typedef enum window_redraw_type { + PW_INVEN = 0x00000001L, /*!<サブウィンドウ描画フラグ: 所持品-装備品 / Display inven/equip */ + PW_EQUIP = 0x00000002L, /*!<サブウィンドウ描画フラグ: 装備品-所持品 / Display equip/inven */ + PW_SPELL = 0x00000004L, /*!<サブウィンドウ描画フラグ: 魔法一覧 / Display spell list */ + PW_PLAYER = 0x00000008L, /*!<サブウィンドウ描画フラグ: プレイヤーのステータス / Display character */ + PW_MONSTER_LIST = 0x00000010L, /*!<サブウィンドウ描画フラグ: 視界内モンスターの一覧 / Display monster list */ + PW_MESSAGE = 0x00000040L, /*!<サブウィンドウ描画フラグ: メッセージログ / Display messages */ + PW_OVERHEAD = 0x00000080L, /*!<サブウィンドウ描画フラグ: 周辺の光景 / Display overhead view */ + PW_MONSTER = 0x00000100L, /*!<サブウィンドウ描画フラグ: モンスターの思い出 / Display monster recall */ + PW_OBJECT = 0x00000200L, /*!<サブウィンドウ描画フラグ: アイテムの知識 / Display object recall */ + PW_DUNGEON = 0x00000400L, /*!<サブウィンドウ描画フラグ: ダンジョンの地形 / Display dungeon view */ + PW_SNAPSHOT = 0x00000800L, /*!<サブウィンドウ描画フラグ: 記念写真 / Display snap-shot */ +} window_redraw_type; + +void redraw_window(void); +void window_stuff(player_type *player_ptr); +void redraw_stuff(player_type *creature_ptr); diff --git a/src/defines.h b/src/defines.h deleted file mode 100644 index 5e5781be6..000000000 --- a/src/defines.h +++ /dev/null @@ -1,4564 +0,0 @@ -/*! - * @file defines.h - * @brief 主要なマクロ定義ヘッダ / Purpose: global constants and macro definitions - * @date 2014/01/02 - * @author - * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n - *\n - * This software may be copied and distributed for educational, research,\n - * and not for profit purposes provided that this copyright and statement\n - * are included in all such copies. Other copyrights may also apply.\n - * @details - * Do not edit this file unless you know *exactly* what you are doing.\n - *\n - * Some of the values in this file were chosen to preserve game balance,\n - * while others are hard-coded based on the format of old save-files, the\n - * definition of arrays in various places, mathematical properties, fast\n - * computation, storage limits, or the format of external text files.\n - *\n - * Changing some of these values will induce crashes or memory errors or\n - * savefile mis-reads. Most of the comments in this file are meant as\n - * reminders, not complete descriptions, and even a complete knowledge\n - * of the source may not be sufficient to fully understand the effects\n - * of changing certain definitions.\n - *\n - * Lastly, note that the code does not always use the symbolic constants\n - * below, and sometimes uses various hard-coded values that may not even\n - * be defined in this file, but which may be related to definitions here.\n - * This is of course bad programming practice, but nobody is perfect...\n - *\n - * For example, there are MANY things that depend on the screen being\n - * 80x24, with the top line used for messages, the bottom line being\n - * used for status, and exactly 22 lines used to show the dungeon.\n - * Just because your screen can hold 46 lines does not mean that the\n - * game will work if you try to use 44 lines to show the dungeon.\n - *\n - * You have been warned.\n - */ - -#define VERSION_NAME "Hengband" /*!< バリアント名称 / Name of the version/variant */ - -/*! - * @brief ゲームのバージョン番号定義 / "Program Version Number" of the game - * @details - * 本FAKE_VERSIONそのものは未使用である。Zangと整合性を合わせるための疑似的処理のためFAKE_VER_MAJORは実値-10が該当のバージョン番号となる。 - *
- * FAKE_VER_MAJOR=1,2 were reserved for ZAngband version 1.x.x/2.x.x .
- * Program Version of Hengband version is
- *   "(FAKE_VER_MAJOR-10).(FAKE_VER_MINOR).(FAKE_VER_PATCH)".
- * 
- */ -#define FAKE_VERSION 0 - -#define FAKE_VER_MAJOR 12 /*!< ゲームのバージョン番号定義(メジャー番号 + 10) */ -#define FAKE_VER_MINOR 2 /*!< ゲームのバージョン番号定義(マイナー番号) */ -#define FAKE_VER_PATCH 1 /*!< ゲームのバージョン番号定義(パッチ番号) */ -#define FAKE_VER_EXTRA 7 /*!< ゲームのバージョン番号定義(エクストラ番号) */ - - - /*! - * @brief バージョンが開発版が安定版かを返す - */ -#define IS_STABLE_VERSION (FAKE_VER_MINOR % 2 == 0 && FAKE_VER_EXTRA == 0) - -/*! - * @brief セーブファイル上のバージョン定義(メジャー番号) / "Savefile Version Number" for Hengband 1.1.1 and later - * @details - * 当面FAKE_VER_*を参照しておく。 - *
- * First three digits may be same as the Program Version.  But not
- * always same.  It means that newer version may preserves lower
- * compatibility with the older version.
- * For example, newer Hengband 1.4.4 creates savefiles marked with
- * Savefile Version 1.4.0.0 .  It means that Hengband 1.4.0 can load a
- * savefile of Hengband 1.4.4 (lower compatibility!).
- * Upper compatibility is always guaranteed.
- * 
- */ -#define H_VER_MAJOR (FAKE_VER_MAJOR-10) /*!< セーブファイル上のバージョン定義(メジャー番号) */ -#define H_VER_MINOR FAKE_VER_MINOR /*!< セーブファイル上のバージョン定義(マイナー番号) */ -#define H_VER_PATCH FAKE_VER_PATCH /*!< セーブファイル上のバージョン定義(パッチ番号) */ -#define H_VER_EXTRA FAKE_VER_EXTRA /*!< セーブファイル上のバージョン定義(エクストラ番号) */ - -#define ANGBAND_2_8_1 /*!< Angband 2.8.1以降から有効な処理分岐を定義 */ -#define ZANGBAND /*!< Zangband 以降から有効な処理分岐を定義 */ - -/*! - * @brief generate.cで用いられる基本的なブロック数単位(垂直方向) - * Number of grids in each block (vertically) Probably hard-coded to 11, see "generate.c" - */ -#define BLOCK_HGT 11 - -/*! - * @brief generate.cで用いられる基本的なブロック数単位(水平方向) - * Number of grids in each block (horizontally) Probably hard-coded to 11, see "generate.c" - */ -#define BLOCK_WID 11 - -/*! - * @brief 表示上の基本的なパネル単位(垂直方向、BLOCK_HGTの倍数で設定すること) - * Number of grids in each panel (vertically) Must be a multiple of BLOCK_HGT - */ -#define PANEL_HGT 11 - -/*! - * @brief 表示上の基本的なパネル単位(水平方向、BLOCK_WIDの倍数で設定すること) - * Number of grids in each panel (horizontally) Must be a multiple of BLOCK_WID - */ -#define PANEL_WID 33 - -/*! - * @brief 表示上の基本的なブロック単位(垂直方向、PANEL_HGTの倍数で設定すること) - * Number of grids used to display the dungeon (vertically). Must be a multiple of 11, probably hard-coded to 22. - */ -#define SCREEN_HGT 22 - -/*! - * @brief 表示上の基本的なブロック単位(水平方向、PANEL_WIDの倍数で設定すること) - * Number of grids used to display the dungeon (horizontally). Must be a multiple of 33, probably hard-coded to 66. - */ -#define SCREEN_WID 66 - -/*! - * @brief 表示上のダンジョンの最大垂直サイズ(SCREEN_HGTの3倍が望ましい) - * Maximum dungeon height in grids, must be a multiple of SCREEN_HGT, probably hard-coded to SCREEN_HGT * 3. - */ -#define MAX_HGT 66 - -/*! - * @brief 表示上のダンジョンの最大水平サイズ(SCREEN_WIDの3倍が望ましい) - * Maximum dungeon width in grids, must be a multiple of SCREEN_WID, probably hard-coded to SCREEN_WID * 3. - */ -#define MAX_WID 198 - -/* - * Arena constants - */ -#define MAX_ARENA_MONS 41 /*grid_array.c") - * @details Note that the "lite radius" will NEVER exceed 14, and we would - * never require more than 581 entries in the array for circular "lite". - */ -#define LITE_MAX 600 - -/*! - * @brief モンスター用光源処理配列サイズ / Maximum size of the "mon_lite" array (see "current_floor_ptr->grid_array.c") - * @details Note that the "view radius" will NEVER exceed 20, monster illumination - * flags are dependent on CAVE_VIEW, and even if the "view" was octagonal, - * we would never require more than 1520 entries in the array. - */ -#define MON_LITE_MAX 1536 - -/*! - * @brief 視界処理配列サイズ / Maximum size of the "view" array (see "current_floor_ptr->grid_array.c") - * @details Note that the "view radius" will NEVER exceed 20, and even if the "view" - * was octagonal, we would never require more than 1520 entries in the array. - */ -#define VIEW_MAX 1536 - -/*! - * @brief 視界及び光源の過渡処理配列サイズ / Maximum size of the "temp" array (see "current_floor_ptr->grid_array.c") - * @details We must be as large as "VIEW_MAX" and "LITE_MAX" for proper functioning - * of "update_view()" and "update_lite()". We must also be as large as the - * largest illuminatable room, but no room is larger than 800 grids. We - * must also be large enough to allow "good enough" use as a circular queue, - * to calculate monster flow, but note that the flow code is "paranoid". - */ -#define TEMP_MAX 2298 - -/*! - * @brief 再描画処理用配列サイズ / Maximum size of the "redraw" array (see "current_floor_ptr->grid_array.c") - * @details We must be large for proper functioning of delayed redrawing. - * We must also be as large as two times of the largest view area. - * Note that maximum view grids are 1149 entries. - */ -#define REDRAW_MAX 2298 - -#define KEYMAP_MODE_ORIG 0 /*!< オリジナルキー配置 / Mode for original keyset commands */ -#define KEYMAP_MODE_ROGUE 1 /*!< ローグライクキー配置 / Mode for roguelike keyset commands */ -#define KEYMAP_MODES 2 /*!< キー配置の数 / Number of keymap modes */ - - - - - -/*! - * @brief マクロ登録の最大数 / Maximum number of macros (see "io.c") - * @note Default: assume at most 256 macros are used - */ -#define MACRO_MAX 256 - -/*! - * @brief 銘情報の最大数 / Maximum number of "quarks" (see "io.c") - * @note - * Default: assume at most 512 different inscriptions are used
- * Was 512... 256 quarks added for random artifacts
- */ -#define QUARK_MAX 768 - -/* - * OPTION: Maximum number of messages to remember (see "io.c") - * Default: assume maximal memorization of 2048 total messages - */ -#define MESSAGE_MAX 81920 - -/* - * OPTION: Maximum space for the message text buffer (see "io.c") - * Default: assume that each of the 2048 messages is repeated an - * average of three times, and has an average length of 48 - */ -#define MESSAGE_BUF 655360 - - -/* - * Maximum value storable in a "byte" (hard-coded) - */ -#define MAX_UCHAR 255 - -/* - * Maximum value storable in a "s16b" (hard-coded) - */ -#define MAX_SHORT 32767 - -/* - * Maximum length of object's name - */ -#define MAX_NLEN 160 - -/* - * Special internal key - */ -#define SPECIAL_KEY_QUEST 255 -#define SPECIAL_KEY_BUILDING 254 -#define SPECIAL_KEY_STORE 253 -#define SPECIAL_KEY_QUIT 252 - -/*! @brief 消費する行動エネルギー値を正規乱数で返す(中央100/分散25) / Random energy */ -#define ENERGY_NEED() (randnor(100, 25)) - -/*! @brief 加速値に応じた基本行動エネルギー消費量を返す / Extract energy from speed (Assumes that SPEED is unsigned) */ -#define SPEED_TO_ENERGY(SPEED) (((SPEED) > 199) ? 49 : extract_energy[(SPEED)]) - - -/* - * Misc constants - */ -#define TOWN_DAWN 10000 /*!< 1日分のターン / Number of ticks from dawn to dawn XXX */ -#define TURNS_PER_TICK 10L /*!< 時間経過処理を行うターン数の刻み / Number of energy-gain-turns per ticks */ -#define INN_DUNGEON_TURN_ADJ 10 /*!< 宿屋で時間をつぶした場合に増えるcurrent_world_ptr->dungeon_turnの倍率 */ -#define MAX_DAYS 20000 /*!< 内部処理中で保持される最大日数 / Maximum days */ -#define BREAK_GLYPH 550 /*!< 守りのルーンの強靭度 / Rune of protection resistance */ -#define BREAK_MINOR_GLYPH 299 /*!< 爆発のルーンの発動しやすさ / For explosive runes */ -#define BTH_PLUS_ADJ 3 /*!< 武器経験値及びプレイヤーの打撃/射撃能力に応じた修正値倍率 / Adjust BTH per plus-to-hit */ -#define MON_MULT_ADJ 8 /*!< モンスターの増殖しにくさの基本倍率 / High value slows multiplication */ -#define MON_SUMMON_ADJ 2 /*!< 現在未使用 Adjust level of summoned creatures */ -#define MON_DRAIN_LIFE 2 /*!< モンスターの打撃によるプレイヤーの経験値吸収基本倍率(%) / Percent of player exp drained per hit */ -#define USE_DEVICE 3 /*!< 魔道具の最低失敗基準値 x> Harder devices x< Easier devices */ - -/*** Pet constants ***/ - - -/* - * ペットに関するコマンド群 / Pet Commands - */ -#define PET_DISMISS 1 /*!< ペットに関するコマンド: ペットを離す */ -#define PET_TARGET 2 /*!< ペットに関するコマンド: ペットのターゲットを指定 */ -#define PET_STAY_CLOSE 3 /*!< ペットに関するコマンド: 近くにいろ */ -#define PET_FOLLOW_ME 4 /*!< ペットに関するコマンド: ついて来い */ -#define PET_SEEK_AND_DESTROY 5 /*!< ペットに関するコマンド: 敵を見つけて倒せ */ -#define PET_ALLOW_SPACE 6 /*!< ペットに関するコマンド: 少し離れていろ */ -#define PET_STAY_AWAY 7 /*!< ペットに関するコマンド: 離れていろ */ -#define PET_OPEN_DOORS 8 /*!< ペットに関するコマンド: ドア解放の許可 */ -#define PET_TAKE_ITEMS 9 /*!< ペットに関するコマンド: アイテム取得の許可 */ -#define PET_TELEPORT 10 /*!< ペットに関するコマンド: テレポートの許可 */ -#define PET_ATTACK_SPELL 11 /*!< ペットに関するコマンド: 攻撃魔法の許可 */ -#define PET_SUMMON_SPELL 12 /*!< ペットに関するコマンド: 召喚魔法の許可 */ -#define PET_BALL_SPELL 13 /*!< ペットに関するコマンド: プレイヤーを魔法に巻き込む許可 */ -#define PET_RIDING 14 /*!< ペットに関するコマンド: ペットに乗る */ -#define PET_NAME 15 /*!< ペットに関するコマンド: ペットに名前をつける */ -#define PET_RYOUTE 16 /*!< ペットに関するコマンド: 騎乗中に両手で武器を使うかどうか */ - -/* - * Follow distances - */ -#define PET_CLOSE_DIST 1 /*!<ペットの行動範囲…近くにいろ */ -#define PET_FOLLOW_DIST 6 /*!<ペットの行動範囲…ついて来い */ -#define PET_SEEK_DIST 10 /*!<ペットの行動範囲…特になし? */ -#define PET_DESTROY_DIST 255 /*!<ペットの行動範囲…敵を見つけて倒せ */ -#define PET_SPACE_DIST (-10) /*!<ペットの行動範囲…少し離れていろ */ -#define PET_AWAY_DIST (-25) /*!<ペットの行動範囲…離れていろ */ - -#define PF_OPEN_DOORS 0x0001 /*!< ペットの行動許可…ドアを開けてよい */ -#define PF_PICKUP_ITEMS 0x0002 /*!< ペットの行動許可…アイテムを拾ってよい */ -#define PF_TELEPORT 0x0004 /*!< ペットの行動許可…テレポート魔法を使ってよい */ -#define PF_ATTACK_SPELL 0x0008 /*!< ペットの行動許可…攻撃魔法を使ってよい */ -#define PF_SUMMON_SPELL 0x0010 /*!< ペットの行動許可…召喚魔法を使ってよい */ -#define PF_BALL_SPELL 0x0020 /*!< ペットの行動許可…ボール魔法でプレイヤーを巻き込んでよい */ -#define PF_RYOUTE 0x0040 /*!< プレイヤーの騎乗フラグ…武器を片手で持つ */ - - -#define CAN_TWO_HANDS_WIELDING() (!p_ptr->riding || (p_ptr->pet_extra_flags & PF_RYOUTE)) - - -/* - * Player constants - */ -#define PY_MAX_EXP 99999999L /*!< プレイヤー経験値の最大値 / Maximum exp */ -#define PY_MAX_GOLD 999999999L /*!< プレイヤー所持金の最大値 / Maximum gold */ -#define PY_MAX_LEVEL 50 /*!< プレイヤーレベルの最大値 / Maximum level */ - -/* - * Player "food" crucial values - */ -#define PY_FOOD_MAX 15000 /*!< 食べ過ぎ~満腹の閾値 / Food value (Bloated) */ -#define PY_FOOD_FULL 10000 /*!< 満腹~平常の閾値 / Food value (Normal) */ -#define PY_FOOD_ALERT 2000 /*!< 平常~空腹の閾値 / Food value (Hungry) */ -#define PY_FOOD_WEAK 1000 /*!< 空腹~衰弱の閾値 / Food value (Weak) */ -#define PY_FOOD_FAINT 500 /*!< 衰弱~衰弱(赤表示/麻痺)の閾値 / Food value (Fainting) */ -#define PY_FOOD_STARVE 100 /*!< è¡°å¼±(赤表示/麻痺)~飢餓ダメージの閾値 / Food value (Starving) */ - -/* - * Player regeneration constants - */ -#define PY_REGEN_NORMAL 197 /* Regen factor*2^16 when full */ -#define PY_REGEN_WEAK 98 /* Regen factor*2^16 when weak */ -#define PY_REGEN_FAINT 33 /* Regen factor*2^16 when fainting */ -#define PY_REGEN_HPBASE 1442 /* Min amount hp regen*2^16 */ -#define PY_REGEN_MNBASE 524 /* Min amount mana regen*2^16 */ - -/* - * 職業ごとの選択可能な魔法領域現在の所 bitrh.cとtables.cでのみ使用。 - * Possible realms that can be chosen currently used only by birth.c and tables.c - */ -#define CH_NONE 0x00 -#define CH_LIFE 0x01 -#define CH_SORCERY 0x02 -#define CH_NATURE 0x04 -#define CH_CHAOS 0x08 -#define CH_DEATH 0x10 -#define CH_TRUMP 0x20 -#define CH_ARCANE 0x40 -#define CH_ENCHANT 0x80 -#define CH_DAEMON 0x100 -#define CH_CRUSADE 0x200 - -#define CH_MUSIC 0x08000 /* This is 16th bit */ -#define CH_HISSATSU 0x10000 -#define CH_HEX 0x20000 - - -/* - * Magic realms - */ -#define REALM_NONE 0 -#define REALM_LIFE 1 -#define REALM_SORCERY 2 -#define REALM_NATURE 3 -#define REALM_CHAOS 4 -#define REALM_DEATH 5 -#define REALM_TRUMP 6 -#define REALM_ARCANE 7 -#define REALM_CRAFT 8 -#define REALM_DAEMON 9 -#define REALM_CRUSADE 10 -#define MAX_MAGIC 10 -#define MIN_TECHNIC 16 -#define REALM_MUSIC 16 -#define REALM_HISSATSU 17 -#define REALM_HEX 18 -#define MAX_REALM 18 - -#define VALID_REALM (MAX_REALM + MAX_MAGIC - MIN_TECHNIC + 1) -#define NUM_TECHNIC (MAX_REALM - MIN_TECHNIC + 1) - -#define is_magic(A) ((((A) > REALM_NONE) && ((A) < MAX_MAGIC + 1)) ? TRUE : FALSE) -#define tval2realm(A) ((A) - TV_LIFE_BOOK + 1) -#define technic2magic(A) (is_magic(A) ? (A) : (A) - MIN_TECHNIC + 1 + MAX_MAGIC) -#define is_good_realm(REALM) ((REALM) == REALM_LIFE || (REALM) == REALM_CRUSADE) - -/* - * Magic-books for the realms - */ -#define REALM1_BOOK (p_ptr->realm1 + TV_LIFE_BOOK - 1) -#define REALM2_BOOK (p_ptr->realm2 + TV_LIFE_BOOK - 1) - - -/* - * Mode constant for do_spell() - */ -#define SPELL_NAME 0 -#define SPELL_DESC 1 -#define SPELL_INFO 2 -#define SPELL_CAST 3 -#define SPELL_FAIL 4 -#define SPELL_STOP 5 -#define SPELL_CONT 6 - - -/* - * Maximum number of "normal" pack slots, and the index of the "overflow" - * slot, which can hold an item, but only temporarily, since it causes the - * pack to "overflow", dropping the "last" item onto the ground. Since this - * value is used as an actual slot, it must be less than "INVEN_RARM" (below). - * Note that "INVEN_PACK" is probably hard-coded by its use in savefiles, and - * by the fact that the screen can only show 23 items plus a one-line prompt. - */ -#define INVEN_PACK 23 /*!< アイテムスロット…所持品(0~) */ - -/* - * Indexes used for various "equipment" slots (hard-coded by savefiles, etc). - */ -#define INVEN_RARM 24 /*!< アイテムスロット…右手 */ -#define INVEN_LARM 25 /*!< アイテムスロット…左手 */ -#define INVEN_BOW 26 /*!< アイテムスロット…射撃 */ -#define INVEN_RIGHT 27 /*!< アイテムスロット…右手指 */ -#define INVEN_LEFT 28 /*!< アイテムスロット…左手指 */ -#define INVEN_NECK 29 /*!< アイテムスロット…首 */ -#define INVEN_LITE 30 /*!< アイテムスロット…光源 */ -#define INVEN_BODY 31 /*!< アイテムスロット…体 */ -#define INVEN_OUTER 32 /*!< アイテムスロット…体の上 */ -#define INVEN_HEAD 33 /*!< アイテムスロット…頭部 */ -#define INVEN_HANDS 34 /*!< アイテムスロット…腕部 */ -#define INVEN_FEET 35 /*!< アイテムスロット…脚部 */ - -/* - * used for get_random_ego() - */ -#define INVEN_AMMO 23 - -/* - * Total number of inventory slots (hard-coded). - */ -#define INVEN_TOTAL 36 - -/* - * Fake inventory slot for selecting force (hard-coded). - */ -#define INVEN_FORCE 1111 - - -/* - * Indexes of the various "stats" (hard-coded by savefiles, etc). - */ -#define A_STR 0 -#define A_INT 1 -#define A_WIS 2 -#define A_DEX 3 -#define A_CON 4 -#define A_CHR 5 -#define A_MAX 6 - -/* - * Player sex constants (hard-coded by save-files, arrays, etc) - */ -#define SEX_FEMALE 0 -#define SEX_MALE 1 - - -/* - * Player race constants (hard-coded by save-files, arrays, etc) - */ -#define RACE_HUMAN 0 -#define RACE_HALF_ELF 1 -#define RACE_ELF 2 -#define RACE_HOBBIT 3 -#define RACE_GNOME 4 -#define RACE_DWARF 5 -#define RACE_HALF_ORC 6 -#define RACE_HALF_TROLL 7 -#define RACE_AMBERITE 8 -#define RACE_HIGH_ELF 9 -#define RACE_BARBARIAN 10 -#define RACE_HALF_OGRE 11 -#define RACE_HALF_GIANT 12 -#define RACE_HALF_TITAN 13 -#define RACE_CYCLOPS 14 -#define RACE_YEEK 15 -#define RACE_KLACKON 16 -#define RACE_KOBOLD 17 -#define RACE_NIBELUNG 18 -#define RACE_DARK_ELF 19 -#define RACE_DRACONIAN 20 -#define RACE_MIND_FLAYER 21 -#define RACE_IMP 22 -#define RACE_GOLEM 23 -#define RACE_SKELETON 24 -#define RACE_ZOMBIE 25 -#define RACE_VAMPIRE 26 -#define RACE_SPECTRE 27 -#define RACE_SPRITE 28 -#define RACE_BEASTMAN 29 -#define RACE_ENT 30 -#define RACE_ANGEL 31 -#define RACE_DEMON 32 -#define RACE_DUNADAN 33 -#define RACE_S_FAIRY 34 -#define RACE_KUTAR 35 -#define RACE_ANDROID 36 -#define RACE_MERFOLK 37 - -/* - * Maximum number of player "race" types (see "table.c", etc) - */ -#define MAX_RACES 38 - - -/* - * Player class constants (hard-coded by save-files, arrays, etc) - */ -#define CLASS_WARRIOR 0 -#define CLASS_MAGE 1 -#define CLASS_PRIEST 2 -#define CLASS_ROGUE 3 -#define CLASS_RANGER 4 -#define CLASS_PALADIN 5 -#define CLASS_WARRIOR_MAGE 6 -#define CLASS_CHAOS_WARRIOR 7 -#define CLASS_MONK 8 -#define CLASS_MINDCRAFTER 9 -#define CLASS_HIGH_MAGE 10 -#define CLASS_TOURIST 11 -#define CLASS_IMITATOR 12 -#define CLASS_BEASTMASTER 13 -#define CLASS_SORCERER 14 -#define CLASS_ARCHER 15 -#define CLASS_MAGIC_EATER 16 -#define CLASS_BARD 17 -#define CLASS_RED_MAGE 18 -#define CLASS_SAMURAI 19 -#define CLASS_FORCETRAINER 20 -#define CLASS_BLUE_MAGE 21 -#define CLASS_CAVALRY 22 -#define CLASS_BERSERKER 23 -#define CLASS_SMITH 24 -#define CLASS_MIRROR_MASTER 25 -#define CLASS_NINJA 26 -#define CLASS_SNIPER 27 - -#define SEIKAKU_FUTUU 0 -#define SEIKAKU_CHIKARA 1 -#define SEIKAKU_KIREMONO 2 -#define SEIKAKU_SHIAWASE 3 -#define SEIKAKU_SUBASI 4 -#define SEIKAKU_INOCHI 5 -#define SEIKAKU_COMBAT 6 -#define SEIKAKU_NAMAKE 7 -#define SEIKAKU_SEXY 8 -#define SEIKAKU_LUCKY 9 -#define SEIKAKU_GAMAN 10 -#define SEIKAKU_MUNCHKIN 11 -#define SEIKAKU_CHARGEMAN 12 - -/*** Screen Locations ***/ - -#define VER_INFO_ROW 3 //!< タイトル表記(行) - - -#define ROW_MAP 0 -#define COL_MAP 12 - -/* - * Number of feats we change to (Excluding default). Used in f_info.txt. - */ -#define MAX_FEAT_STATES 8 - - -/* - * Wilderness terrains - */ -#define TERRAIN_EDGE 0 /* Edge of the World */ -#define TERRAIN_TOWN 1 /* Town */ -#define TERRAIN_DEEP_WATER 2 /* Deep water */ -#define TERRAIN_SHALLOW_WATER 3 /* Shallow water */ -#define TERRAIN_SWAMP 4 /* Swamp */ -#define TERRAIN_DIRT 5 /* Dirt */ -#define TERRAIN_GRASS 6 /* Grass */ -#define TERRAIN_TREES 7 /* Trees */ -#define TERRAIN_DESERT 8 /* Desert */ -#define TERRAIN_SHALLOW_LAVA 9 /* Shallow lava */ -#define TERRAIN_DEEP_LAVA 10 /* Deep lava */ -#define TERRAIN_MOUNTAIN 11 /* Mountain */ - -#define MAX_WILDERNESS 12 /* Maximum wilderness index */ - - -/* - * Feature flags - should be used instead of feature indexes unless generating. - * Originally from UnAngband, and modified into TR-like style in Hengband - */ - -#define FF_LOS 0 /*!< 視界が通る地形である */ -#define FF_PROJECT 1 /*!< 飛び道具が通過できる地形である */ -#define FF_MOVE 2 /*!< 移動可能な地形である */ -#define FF_PLACE 3 /*!< モンスター配置をしても良い地形である(cave_empty_bold/cave_empty_gridで利用) */ -#define FF_DROP 4 /*!< アイテムを落としてよい地形である */ -#define FF_SECRET 5 /*!< 隠し扉やトラップが潜んでいる地形である */ -#define FF_NOTICE 6 /*!< 何か興味を引くものがある地形である(シフトキー+方向で走行中の時に止まる基準) */ -#define FF_REMEMBER 7 /*!< 常に記憶対象となる地形である(記憶喪失時に忘れたりしなくなる) */ -#define FF_OPEN 8 /*!< 開けるコマンドの対象となる地形である */ -#define FF_CLOSE 9 /*!< 閉じるコマンドの対象となる地形である */ -#define FF_BASH 10 /*!< 体当たりコマンドの対象となる地形である */ -#define FF_SPIKE 11 /*!< くさびを打つコマンドの対象となる地形である */ -#define FF_DISARM 12 /*!< 解除コマンドの対象となる地形である */ -#define FF_STORE 13 /*!< 店舗の入口となる地形である */ -#define FF_TUNNEL 14 /*!< 魔王変化などで掘り進められる地形である */ -#define FF_MAY_HAVE_GOLD 15 /*!< 何か財宝を隠した可能性のある地形である?(f_infoに使用している地形なし) */ -#define FF_HAS_GOLD 16 /*!< 財宝を含んだ地形である */ -#define FF_HAS_ITEM 17 /*!< アイテムを含んだ地形である */ -#define FF_DOOR 18 /*!< ドアのある地形である */ -#define FF_TRAP 19 /*!< トラップのある地形である */ -#define FF_STAIRS 20 /*!< 階段のある地形である */ -#define FF_GLYPH 21 /*!< 守りのルーンが張られた地形である */ -#define FF_LESS 22 /*!< 階上に通じる地形である */ -#define FF_MORE 23 /*!< 階下に通じる地形である */ -#define FF_AVOID_RUN 24 /*!< 自動移動機能時に障害として迂回すべき地形である */ -#define FF_FLOOR 25 /*!< 床のある地形である */ -#define FF_WALL 26 /*!< 壁のある地形である */ -#define FF_PERMANENT 27 /*!< 絶対に破壊できない永久地形である */ -/* #define FF_XXX00 28 未定義 */ -/* #define FF_XXX01 29 未定義 */ -/* #define FF_XXX02 30 未定義 */ -#define FF_HIT_TRAP 31 /*!< トラップのある地形である(TRAPと常に重複している?) */ -/* #define FF_BRIDGE 32 未使用 */ -/* #define FF_RIVER 33 未使用 */ -/* #define FF_LAKE 34 未使用 */ -/* #define FF_BRIDGED 35 未使用 */ -/* #define FF_COVERED 36 未使用 */ -#define FF_GLOW 37 /*!< 常に光っている地形である */ -#define FF_ENSECRET 38 /*!< 不明(f_info.txt上で利用している地形がない) */ -#define FF_WATER 39 /*!< 水のある地形である */ -#define FF_LAVA 40 /*!< 溶岩のある地形である */ -#define FF_SHALLOW 41 /*!< 浅い地形である */ -#define FF_DEEP 42 /*!< 深い地形である */ -#define FF_POISON_PUDDLE 43 /*!< 毒溜まりがある */ -#define FF_HURT_ROCK 44 /*!< 岩石溶解の対象となる地形である */ -/* #define FF_HURT_FIRE 45 */ /*!< 未使用 */ -/* #define FF_HURT_COLD 46 */ /*!< 未使用 */ -/* #define FF_HURT_ACID 47 */ /*!< 未使用 */ -#define FF_COLD_PUDDLE 48 /*!< 冷気溜まりがある */ -#define FF_ACID_PUDDLE 49 /*!< 酸溜まりがある */ -/* #define FF_OIL 50 */ /*!< 未使用 */ -#define FF_ELEC_PUDDLE 51 /*!< 接地部が帯電している */ -/* #define FF_CAN_CLIMB 52 */ /*!< 未使用 */ -#define FF_CAN_FLY 53 /*!< 飛行可能な地形である */ -#define FF_CAN_SWIM 54 /*!< 泳ぐことが可能な地形である */ -#define FF_CAN_PASS 55 /*!< 通過可能な地形である */ -/* #define FF_CAN_OOZE 56 */ /*!< 未使用 */ -#define FF_CAN_DIG 57 /*!< 掘削コマンドの対象となる地形である */ -/* #define FF_HIDE_ITEM 58 未使用 */ -/* #define FF_HIDE_SNEAK 59 未使用 */ -/* #define FF_HIDE_SWIM 60 未使用 */ -/* #define FF_HIDE_DIG 61 未使用 */ -/* #define FF_KILL_HUGE 62 未使用 */ -/* #define FF_KILL_MOVE 63 未使用 */ -/* #define FF_PICK_TRAP 64 未使用 */ -/* #define FF_PICK_DOOR 65 未使用 */ -/* #define FF_ALLOC 66 未使用 */ -/* #define FF_CHEST 67 未使用 */ -/* #define FF_DROP_1D2 68 未使用 */ -/* #define FF_DROP_2D2 69 未使用 */ -/* #define FF_DROP_GOOD 70 未使用 */ -/* #define FF_DROP_GREAT 71 未使用 */ -/* #define FF_HURT_POIS 72 未使用 */ -/* #define FF_HURT_ELEC 73 未使用 */ -/* #define FF_HURT_WATER 74 未使用 */ -/* #define FF_HURT_BWATER 75 未使用 */ -/* #define FF_USE_FEAT 76 未使用 */ -/* #define FF_GET_FEAT 77 未使用 */ -/* #define FF_GROUND 78 未使用 */ -/* #define FF_OUTSIDE 79 未使用 */ -/* #define FF_EASY_HIDE 80 未使用 */ -/* #define FF_EASY_CLIMB 81 未使用 */ -/* #define FF_MUST_CLIMB 82 未使用 */ -#define FF_TREE 83 /*!< 木の生えた地形である */ -/* #define FF_NEED_TREE 84 未使用 */ -/* #define FF_BLOOD 85 未使用 */ -/* #define FF_DUST 86 未使用 */ -/* #define FF_SLIME 87 未使用 */ -#define FF_PLANT 88 /*!< 植物の生えた地形である */ -/* #define FF_XXX2 89 未定義 */ -/* #define FF_INSTANT 90 未使用 */ -/* #define FF_EXPLODE 91 未使用 */ -/* #define FF_TIMED 92 未使用 */ -/* #define FF_ERUPT 93 未使用 */ -/* #define FF_STRIKE 94 未使用 */ -/* #define FF_SPREAD 95 未使用 */ -#define FF_SPECIAL 96 /*!< クエストやダンジョンに関わる特別な地形である */ -#define FF_HURT_DISI 97 /*!< 分解属性の対象となる地形である */ -#define FF_QUEST_ENTER 98 /*!< クエストの入り口である */ -#define FF_QUEST_EXIT 99 /*!< クエストの出口である */ -#define FF_QUEST 100 /*!< クエストに関する地形である */ -#define FF_SHAFT 101 /*!< 坑道である。(2階層移動する階段である) */ -#define FF_MOUNTAIN 102 /*!< ダンジョンの山地形である */ -#define FF_BLDG 103 /*!< 施設の入り口である */ -#define FF_MINOR_GLYPH 104 /*!< 爆発のルーンのある地形である */ -#define FF_PATTERN 105 /*!< パターンのある地形である */ -#define FF_TOWN 106 /*!< 広域マップ用の街がある地形である */ -#define FF_ENTRANCE 107 /*!< 広域マップ用のダンジョンがある地形である */ -#define FF_MIRROR 108 /*!< 鏡使いの鏡が張られた地形である */ -#define FF_UNPERM 109 /*!< 破壊不能な地形である(K:フラグ向け?) */ -#define FF_TELEPORTABLE 110 /*!< テレポート先の対象となる地形である */ -#define FF_CONVERT 111 /*!< 地形生成処理中の疑似フラグ */ -#define FF_GLASS 112 /*!< ガラス製の地形である */ - - -#define FF_FLAG_MAX 113 -#define FF_FLAG_SIZE (1 + ((FF_FLAG_MAX - 1) / 32)) - -/* Which features are dynamic */ -#define have_dynamic_flags(ARRAY) \ - (!!((ARRAY)[(FF_INSTANT / 32)] & \ - ((1UL << (FF_INSTANT % 32)) | \ - (1UL << (FF_EXPLODE % 32)) | \ - (1UL << (FF_TIMED % 32)) | \ - (1UL << (FF_ERUPT % 32)) | \ - (1UL << (FF_STRIKE % 32)) | \ - (1UL << (FF_SPREAD % 32))))) - - -/* - * Feature action flags - */ -#define FAF_DESTROY 0x01 -#define FAF_NO_DROP 0x02 -#define FAF_CRASH_GLASS 0x04 - - -/* - * Bit flags for teleportation - */ -#define TELEPORT_NONMAGICAL 0x00000001 -#define TELEPORT_PASSIVE 0x00000002 -#define TELEPORT_DEC_VALOUR 0x00000004 - - -/* Types of doors */ -#define DOOR_DEFAULT -1 -#define DOOR_DOOR 0 -#define DOOR_GLASS_DOOR 1 -#define DOOR_CURTAIN 2 - -#define MAX_DOOR_TYPES 3 - -#define feat_locked_door_random(DOOR_TYPE) \ - (feat_door[(DOOR_TYPE)].num_locked ? \ - feat_door[(DOOR_TYPE)].locked[randint0(feat_door[(DOOR_TYPE)].num_locked)] : feat_none) - -#define feat_jammed_door_random(DOOR_TYPE) \ - (feat_door[(DOOR_TYPE)].num_jammed ? \ - feat_door[(DOOR_TYPE)].jammed[randint0(feat_door[(DOOR_TYPE)].num_jammed)] : feat_none) - - - - -/* Types of pattern tiles */ -#define NOT_PATTERN_TILE -1 -#define PATTERN_TILE_START 0 -#define PATTERN_TILE_1 1 -#define PATTERN_TILE_2 2 -#define PATTERN_TILE_3 3 -#define PATTERN_TILE_4 4 -#define PATTERN_TILE_END 5 -#define PATTERN_TILE_OLD 6 -#define PATTERN_TILE_TELEPORT 7 -#define PATTERN_TILE_WRECKED 8 - - -/* Types of conversions */ -#define CONVERT_TYPE_FLOOR 0 -#define CONVERT_TYPE_WALL 1 -#define CONVERT_TYPE_INNER 2 -#define CONVERT_TYPE_OUTER 3 -#define CONVERT_TYPE_SOLID 4 -#define CONVERT_TYPE_STREAM1 5 -#define CONVERT_TYPE_STREAM2 6 - - -/* - * Bit flags for the *_can_enter() and monster_can_cross_terrain() - */ -#define CEM_RIDING 0x0001 -#define CEM_P_CAN_ENTER_PATTERN 0x0002 - - -/* Lighting levels of features' attr and char */ - -#define F_LIT_STANDARD 0 /* Standard */ -#define F_LIT_LITE 1 /* Brightly lit */ -#define F_LIT_DARK 2 /* Darkened */ - -#define F_LIT_NS_BEGIN 1 /* Nonstandard */ -#define F_LIT_MAX 3 - - - -/*** Ego-Item indexes (see "lib/edit/e_info.txt") ***/ - - -/* Nothing */ -/* xxx */ -/* xxx */ -/* xxx */ - -/* Body Armor */ -#define EGO_A_MORGUL 4 -#define EGO_A_DEMON 5 -#define EGO_DRUID 6 -#define EGO_OLOG 7 -#define EGO_RESISTANCE 8 -#define EGO_ELVENKIND 9 -#define EGO_DWARVEN 10 -#define EGO_PERMANENCE 11 -#define EGO_YOIYAMI 12 -#define EGO_URUKISH 13 -/* xxx */ -/* xxx */ - -/* Shields */ -#define EGO_ENDURE_ACID 16 -#define EGO_ENDURE_ELEC 17 -#define EGO_ENDURE_FIRE 18 -#define EGO_ENDURE_COLD 19 -#define EGO_ENDURANCE 20 -#define EGO_REFLECTION 21 -#define EGO_NIGHT_DAY 22 -#define EGO_S_PROTECTION 238 -#define EGO_S_DWARVEN 239 - -/* Crowns and Helms */ -#define EGO_DARK 23 -#define EGO_BRILLIANCE 24 -#define EGO_H_PROTECTION 25 -#define EGO_H_DEMON 26 -#define EGO_MAGI 27 -#define EGO_MIGHT 28 -#define EGO_LORDLINESS 29 -#define EGO_SEEING 30 -#define EGO_INFRAVISION 31 -#define EGO_LITE 32 -#define EGO_TELEPATHY 33 -#define EGO_REGENERATION 34 -#define EGO_TELEPORTATION 35 -#define EGO_FOOL 36 -#define EGO_BASILISK 37 -#define EGO_ANCIENT_CURSE 38 -#define EGO_SICKLINESS 39 - -/* Cloaks */ -#define EGO_PROTECTION 40 -#define EGO_STEALTH 41 -#define EGO_AMAN 42 -#define EGO_AURA_FIRE 43 -#define EGO_ENVELOPING 44 -#define EGO_VULNERABILITY 45 -#define EGO_IRRITATION 46 -#define EGO_AURA_ELEC 47 -#define EGO_AURA_COLD 128 -#define EGO_BAT 129 -#define EGO_NAZGUL 240 - -/* Gloves */ -#define EGO_FREE_ACTION 48 -#define EGO_SLAYING 49 -#define EGO_AGILITY 50 -#define EGO_POWER 51 -#define EGO_2WEAPON 52 -#define EGO_MAGIC_MASTERY 53 -#define EGO_WEAKNESS 54 -#define EGO_CLUMSINESS 55 - -/* Boots */ -#define EGO_SLOW_DESCENT 56 -#define EGO_QUIET 57 -#define EGO_MOTION 58 -#define EGO_SPEED 59 -#define EGO_JUMP 60 -#define EGO_NOISE 61 -#define EGO_SLOWNESS 62 -#define EGO_ANNOYANCE 63 - -/* Weapons */ -#define EGO_HA 64 -#define EGO_DF 65 -#define EGO_BLESS_BLADE 66 -/* xxx */ -#define EGO_WEST 68 -#define EGO_ATTACKS 69 -#define EGO_SLAYING_WEAPON 70 -#define EGO_FORCE_WEAPON 71 -#define EGO_BRAND_ACID 72 -#define EGO_BRAND_ELEC 73 -#define EGO_BRAND_FIRE 74 -#define EGO_BRAND_COLD 75 -#define EGO_BRAND_POIS 76 -#define EGO_CHAOTIC 77 -#define EGO_SHARPNESS 78 -#define EGO_EARTHQUAKES 79 -#define EGO_XXX_1 80 -#define EGO_XXX_2 81 -#define EGO_XXX_3 82 -#define EGO_XXX_4 83 -#define EGO_XXX_5 84 -#define EGO_XXX_6 85 -#define EGO_XXX_7 86 -#define EGO_WEIRD 87 -#define EGO_KILL_ANIMAL 88 -#define EGO_KILL_EVIL 89 -#define EGO_KILL_UNDEAD 90 -#define EGO_KILL_DEMON 91 -#define EGO_KILL_ORC 92 -#define EGO_KILL_TROLL 93 -#define EGO_KILL_GIANT 94 -#define EGO_KILL_DRAGON 95 -#define EGO_VAMPIRIC 96 -#define EGO_PRISM 97 -#define EGO_TRUMP 98 -#define EGO_PATTERN 99 -#define EGO_DIGGING 100 -#define EGO_DEMON 101 -#define EGO_MORGUL 102 -#define EGO_KILL_HUMAN 103 - -/* Bows */ -#define EGO_ACCURACY 104 -#define EGO_VELOCITY 105 -/* xxx */ -/* xxx */ -#define EGO_EXTRA_MIGHT 108 -#define EGO_EXTRA_SHOTS 109 -/* xxx */ -/* xxx */ - -/* Ammo */ -#define EGO_HURT_ANIMAL 112 -#define EGO_HURT_EVIL 113 -/* xxx */ -/* xxx */ -/* xxx */ -/* xxx */ -/* xxx */ -#define EGO_HURT_DRAGON 119 -#define EGO_SLAYING_BOLT 120 -#define EGO_LIGHTNING_BOLT 121 -#define EGO_FLAME 122 -#define EGO_FROST 123 -#define EGO_WOUNDING 124 -#define EGO_BACKBITING 125 -#define EGO_SHATTERED 126 -#define EGO_BLASTED 127 - -#define EGO_LITE_SHINE 140 -#define EGO_LITE_ILLUMINATION 141 -#define EGO_LITE_AURA_FIRE 142 -#define EGO_LITE_INFRA 143 -#define EGO_LITE_LONG 144 -#define EGO_LITE_DARKNESS 145 -#define EGO_LITE_EYE 146 - -#define EGO_RING_HERO 150 -#define EGO_RING_SLAY 151 -#define EGO_RING_SUPER_AC 152 -#define EGO_RING_MAGIC_MIS 153 -#define EGO_RING_FIRE_BOLT 154 -#define EGO_RING_COLD_BOLT 155 -#define EGO_RING_ELEC_BOLT 156 -#define EGO_RING_ACID_BOLT 157 -#define EGO_RING_MANA_BOLT 158 -#define EGO_RING_FIRE_BALL 159 -#define EGO_RING_COLD_BALL 160 -#define EGO_RING_ELEC_BALL 161 -#define EGO_RING_ACID_BALL 162 -#define EGO_RING_MANA_BALL 163 -#define EGO_RING_DRAGON_F 164 -#define EGO_RING_DRAGON_C 165 -#define EGO_RING_D_SPEED 166 -#define EGO_RING_BERSERKER 167 -#define EGO_RING_HUNTER 168 -#define EGO_RING_THROW 169 -#define EGO_RING_REGEN 170 -#define EGO_RING_LITE 171 -#define EGO_RING_M_DETECT 172 -#define EGO_RING_STEALTH 173 -#define EGO_RING_TELE_AWAY 174 -#define EGO_RING_TO_H 175 -#define EGO_RING_TO_D 176 -#define EGO_RING_RES_LITE 177 -#define EGO_RING_RES_DARK 178 -#define EGO_RING_WIZARD 179 -#define EGO_RING_TRUE 180 -#define EGO_RING_DRAIN_EXP 181 -#define EGO_RING_NO_MELEE 182 -#define EGO_RING_AGGRAVATE 183 -#define EGO_RING_TY_CURSE 184 -#define EGO_RING_RES_TIME 185 -#define EGO_RING_TELEPORT 186 -#define EGO_RING_ALBINO 187 - -#define EGO_AMU_SLOW_D 210 -#define EGO_AMU_INFRA 211 -#define EGO_AMU_SEE_INVIS 212 -#define EGO_AMU_HOLD_EXP 213 -#define EGO_AMU_DRAIN_EXP 214 -#define EGO_AMU_FOOL 215 -#define EGO_AMU_AGGRAVATE 216 -#define EGO_AMU_TY_CURSE 217 -#define EGO_AMU_AC 218 -#define EGO_AMU_IDENT 219 -#define EGO_AMU_CHARM 220 -#define EGO_AMU_STEALTH 221 -#define EGO_AMU_JUMP 222 -#define EGO_AMU_TELEPORT 223 -#define EGO_AMU_D_DOOR 224 -#define EGO_AMU_DEFENDER 225 -#define EGO_AMU_RES_FIRE 226 -#define EGO_AMU_RES_FIRE_ 227 -#define EGO_AMU_RES_COLD 228 -#define EGO_AMU_RES_COLD_ 229 -#define EGO_AMU_RES_ELEC 230 -#define EGO_AMU_RES_ELEC_ 231 -#define EGO_AMU_RES_ACID 232 -#define EGO_AMU_RES_ACID_ 233 -#define EGO_AMU_LEVITATION 234 -#define EGO_AMU_GREAT 235 -#define EGO_AMU_DETECTION 236 -#define EGO_AMU_NAIVETY 237 -// MAX 240 - - -/*** Object "tval" and "sval" codes ***/ - - -/* - * The values for the "tval" field of various objects. - * - * This value is the primary means by which items are sorted in the - * player inventory, followed by "sval" and "cost". - * - * Note that a "BOW" with tval = 19 and sval S = 10*N+P takes a missile - * weapon with tval = 16+N, and does (xP) damage when so combined. This - * fact is not actually used in the source, but it kind of interesting. - * - * Note that as of 2.7.8, the "item flags" apply to all items, though - * only armor and weapons and a few other items use any of these flags. - */ - -#define TV_SKELETON 1 /* Skeletons ('s'), not specified */ -#define TV_BOTTLE 2 /* Empty bottles ('!') */ -#define TV_JUNK 3 /* Sticks, Pottery, etc ('~') */ -#define TV_WHISTLE 4 /* Whistle ('~') */ -#define TV_SPIKE 5 /* Spikes ('~') */ -#define TV_CHEST 7 /* Chests ('&') */ -#define TV_FIGURINE 8 /* Magical figurines */ -#define TV_STATUE 9 /* Statue, what a silly object... */ -#define TV_CORPSE 10 /* Corpses and Skeletons, specific */ -#define TV_CAPTURE 11 /* Monster ball */ -#define TV_NO_AMMO 15 /* Ammo for crimson */ -#define TV_SHOT 16 /* Ammo for slings */ -#define TV_ARROW 17 /* Ammo for bows */ -#define TV_BOLT 18 /* Ammo for x-bows */ -#define TV_BOW 19 /* Slings/Bows/Xbows */ -#define TV_DIGGING 20 /* Shovels/Picks */ -#define TV_HAFTED 21 /* Priest Weapons */ -#define TV_POLEARM 22 /* Axes and Pikes */ -#define TV_SWORD 23 /* Edged Weapons */ -#define TV_BOOTS 30 /* Boots */ -#define TV_GLOVES 31 /* Gloves */ -#define TV_HELM 32 /* Helms */ -#define TV_CROWN 33 /* Crowns */ -#define TV_SHIELD 34 /* Shields */ -#define TV_CLOAK 35 /* Cloaks */ -#define TV_SOFT_ARMOR 36 /* Soft Armor */ -#define TV_HARD_ARMOR 37 /* Hard Armor */ -#define TV_DRAG_ARMOR 38 /* Dragon Scale Mail */ -#define TV_LITE 39 /* Lites (including Specials) */ -#define TV_AMULET 40 /* Amulets (including Specials) */ -#define TV_RING 45 /* Rings (including Specials) */ -#define TV_CARD 50 -#define TV_STAFF 55 -#define TV_WAND 65 -#define TV_ROD 66 -#define TV_PARCHMENT 69 -#define TV_SCROLL 70 -#define TV_POTION 75 -#define TV_FLASK 77 -#define TV_FOOD 80 -#define TV_LIFE_BOOK 90 -#define TV_SORCERY_BOOK 91 -#define TV_NATURE_BOOK 92 -#define TV_CHAOS_BOOK 93 -#define TV_DEATH_BOOK 94 -#define TV_TRUMP_BOOK 95 -#define TV_ARCANE_BOOK 96 -#define TV_CRAFT_BOOK 97 -#define TV_DAEMON_BOOK 98 -#define TV_CRUSADE_BOOK 99 -#define TV_MUSIC_BOOK 105 -#define TV_HISSATSU_BOOK 106 -#define TV_HEX_BOOK 107 -#define TV_GOLD 127 /* Gold can only be picked up by players */ - -#define TV_EQUIP_BEGIN TV_SHOT -#define TV_EQUIP_END TV_CARD -#define TV_MISSILE_BEGIN TV_SHOT -#define TV_MISSILE_END TV_BOLT -#define TV_WEARABLE_BEGIN TV_BOW -#define TV_WEARABLE_END TV_CARD -#define TV_WEAPON_BEGIN TV_BOW -#define TV_WEAPON_END TV_SWORD -#define TV_ARMOR_BEGIN TV_BOOTS -#define TV_ARMOR_END TV_DRAG_ARMOR - -/* Any subvalue */ -#define SV_ANY 255 - -/* The "sval" codes for TV_FIGURINE */ -#define SV_FIGURINE_NORMAL 0 - -#define SV_CAPTURE_NONE 0 - -/* The "sval" codes for TV_STATUE */ -#define SV_WOODEN_STATUE 0 -#define SV_CLAY_STATUE 1 -#define SV_STONE_STATUE 2 -#define SV_IRON_STATUE 3 -#define SV_COPPER_STATUE 4 -#define SV_SILVER_STATUE 5 -#define SV_GOLDEN_STATUE 6 -#define SV_IVORY_STATUE 7 -#define SV_MITHRIL_STATUE 8 -#define SV_ORNATE_STATUE 9 -#define SV_PHOTO 50 - -/* The "sval" codes for TV_CORPSE */ -#define SV_SKELETON 0 -#define SV_CORPSE 1 - -/* The "sval" codes for TV_SHOT/TV_ARROW/TV_BOLT */ -#define SV_AMMO_LIGHT 0 /* pebbles */ -#define SV_AMMO_NORMAL 1 /* shots, arrows, bolts */ -#define SV_AMMO_HEAVY 2 /* seeker arrows and bolts, mithril shots */ - -/* The "sval" codes for TV_BOW (note information in "sval") */ -#define SV_SLING 2 /* (x2) */ -#define SV_SHORT_BOW 12 /* (x2) */ -#define SV_LONG_BOW 13 /* (x3) */ -#define SV_LIGHT_XBOW 23 /* (x3) */ -#define SV_HEAVY_XBOW 24 /* (x4) */ -#define SV_CRIMSON 50 /* (x0) */ -#define SV_HARP 51 /* (x0) */ -#define SV_NAMAKE_BOW 63 /* (x3) */ - -/* The "sval" codes for TV_DIGGING */ -#define SV_SHOVEL 1 -#define SV_GNOMISH_SHOVEL 2 -#define SV_DWARVEN_SHOVEL 3 -#define SV_PICK 4 -#define SV_ORCISH_PICK 5 -#define SV_DWARVEN_PICK 6 -#define SV_MATTOCK 7 - -/* The "sval" values for TV_HAFTED */ -#define SV_CLUB 1 /* 1d4 */ -#define SV_WHIP 2 /* 1d6 */ -#define SV_QUARTERSTAFF 3 /* 1d9 */ -#define SV_NUNCHAKU 4 /* 2d3 */ -#define SV_MACE 5 /* 2d4 */ -#define SV_BALL_AND_CHAIN 6 /* 2d4 */ -#define SV_JO_STAFF 7 /* 1d7 */ -#define SV_WAR_HAMMER 8 /* 3d3 */ -#define SV_THREE_PIECE_ROD 11 /* 3d3 */ -#define SV_MORNING_STAR 12 /* 2d6 */ -#define SV_FLAIL 13 /* 2d6 */ -#define SV_BO_STAFF 14 /* 1d11 */ -#define SV_LEAD_FILLED_MACE 15 /* 3d4 */ -#define SV_TETSUBO 16 /* 2d7 */ -#define SV_TWO_HANDED_FLAIL 18 /* 3d6 */ -#define SV_GREAT_HAMMER 19 /* 4d6 */ -#define SV_MACE_OF_DISRUPTION 20 /* 5d8 */ -#define SV_WIZSTAFF 21 /* 1d2 */ -#define SV_GROND 50 /* 3d9 */ -#define SV_NAMAKE_HAMMER 63 /* 1d77 */ - -/* The "sval" values for TV_POLEARM */ -#define SV_HATCHET 1 /* 1d5 */ -#define SV_SPEAR 2 /* 1d6 */ -#define SV_SICKLE 3 /* 2d3 */ -#define SV_AWL_PIKE 4 /* 1d8 */ -#define SV_TRIDENT 5 /* 1d9 */ -#define SV_FAUCHARD 6 /* 1d10 */ -#define SV_BROAD_SPEAR 7 /* 1d9 */ -#define SV_PIKE 8 /* 2d5 */ -#define SV_NAGINATA 9 /* 2d6 */ -#define SV_BEAKED_AXE 10 /* 2d6 */ -#define SV_BROAD_AXE 11 /* 2d6 */ -#define SV_LUCERNE_HAMMER 12 /* 2d5 */ -#define SV_GLAIVE 13 /* 2d6 */ -#define SV_LAJATANG 14 /* 2d7 */ -#define SV_HALBERD 15 /* 3d4 */ -#define SV_GUISARME 16 /* 2d5 */ -#define SV_SCYTHE 17 /* 5d3 */ -#define SV_LANCE 20 /* 2d8 */ -#define SV_BATTLE_AXE 22 /* 2d8 */ -#define SV_GREAT_AXE 25 /* 4d4 */ -#define SV_TRIFURCATE_SPEAR 26 /* 2d9 */ -#define SV_LOCHABER_AXE 28 /* 3d8 */ -#define SV_HEAVY_LANCE 29 /* 4d8 */ -#define SV_SCYTHE_OF_SLICING 30 /* 8d4 */ -#define SV_TSURIZAO 40 /* 1d1 */ -#define SV_DEATH_SCYTHE 50 /* 10d10 */ - -/* The "sval" codes for TV_SWORD */ -#define SV_BROKEN_DAGGER 1 /* 1d1 */ -#define SV_BROKEN_SWORD 2 /* 1d2 */ -#define SV_DAGGER 4 /* 1d4 */ -#define SV_MAIN_GAUCHE 5 /* 1d5 */ -#define SV_TANTO 6 /* 1d5 */ -#define SV_RAPIER 7 /* 1d6 */ -#define SV_SMALL_SWORD 8 /* 1d6 */ -#define SV_BASILLARD 9 /* 1d8 */ -#define SV_SHORT_SWORD 10 /* 1d7 */ -#define SV_SABRE 11 /* 1d7 */ -#define SV_CUTLASS 12 /* 1d7 */ -#define SV_WAKIZASHI 13 /* 2d4 */ -#define SV_KHOPESH 14 /* 2d4 */ -#define SV_TULWAR 15 /* 2d4 */ -#define SV_BROAD_SWORD 16 /* 2d5 */ -#define SV_LONG_SWORD 17 /* 2d5 */ -#define SV_SCIMITAR 18 /* 2d5 */ -#define SV_NINJATO 19 /* 1d9 */ -#define SV_KATANA 20 /* 3d4 */ -#define SV_BASTARD_SWORD 21 /* 3d4 */ -#define SV_GREAT_SCIMITAR 22 /* 4d5 */ -#define SV_CLAYMORE 23 /* 2d8 */ -#define SV_ESPADON 24 /* 2d9 */ -#define SV_TWO_HANDED_SWORD 25 /* 3d6 */ -#define SV_FLAMBERGE 26 /* 3d7 */ -#define SV_NO_DACHI 27 /* 5d4 */ -#define SV_EXECUTIONERS_SWORD 28 /* 4d5 */ -#define SV_ZWEIHANDER 29 /* 4d6 */ -#define SV_BLADE_OF_CHAOS 30 /* 6d5 */ -#define SV_DIAMOND_EDGE 31 /* 7d5 */ -#define SV_DOKUBARI 32 /* 1d1 */ -#define SV_HAYABUSA 33 /* 1d6 */ - -/* The "sval" codes for TV_SHIELD */ -#define SV_SMALL_LEATHER_SHIELD 2 -#define SV_SMALL_METAL_SHIELD 3 -#define SV_LARGE_LEATHER_SHIELD 4 -#define SV_LARGE_METAL_SHIELD 5 -#define SV_DRAGON_SHIELD 6 -#define SV_KNIGHT_SHIELD 7 -#define SV_MIRROR_SHIELD 10 -#define SV_YATA_MIRROR 50 - -/* The "sval" codes for TV_HELM */ -#define SV_HARD_LEATHER_CAP 2 -#define SV_METAL_CAP 3 -#define SV_JINGASA 4 /* 4 */ -#define SV_IRON_HELM 5 -#define SV_STEEL_HELM 6 -#define SV_DRAGON_HELM 7 -#define SV_KABUTO 8 /* 7 */ - -/* The "sval" codes for TV_CROWN */ -#define SV_IRON_CROWN 10 -#define SV_GOLDEN_CROWN 11 -#define SV_JEWELED_CROWN 12 -#define SV_CHAOS 50 - -/* The "sval" codes for TV_BOOTS */ -#define SV_PAIR_OF_SOFT_LEATHER_BOOTS 2 -#define SV_PAIR_OF_HARD_LEATHER_BOOTS 3 -#define SV_PAIR_OF_DRAGON_GREAVE 4 -#define SV_PAIR_OF_METAL_SHOD_BOOTS 6 - -/* The "sval" codes for TV_CLOAK */ -#define SV_CLOAK 1 -#define SV_ELVEN_CLOAK 2 -#define SV_FUR_CLOAK 3 -#define SV_ETHEREAL_CLOAK 5 -#define SV_SHADOW_CLOAK 6 - -/* The "sval" codes for TV_GLOVES */ -#define SV_SET_OF_LEATHER_GLOVES 1 -#define SV_SET_OF_GAUNTLETS 2 -#define SV_SET_OF_DRAGON_GLOVES 3 -#define SV_SET_OF_CESTI 5 - -/* The "sval" codes for TV_SOFT_ARMOR */ -#define SV_T_SHIRT 0 -#define SV_FILTHY_RAG 1 -#define SV_ROBE 2 -#define SV_PAPER_ARMOR 3 /* 4 */ -#define SV_SOFT_LEATHER_ARMOR 4 -#define SV_SOFT_STUDDED_LEATHER 5 -#define SV_HARD_LEATHER_ARMOR 6 -#define SV_HARD_STUDDED_LEATHER 7 -#define SV_RHINO_HIDE_ARMOR 8 -#define SV_CORD_ARMOR 9 /* 6 */ -#define SV_PADDED_ARMOR 10 /* 4 */ -#define SV_LEATHER_SCALE_MAIL 11 -#define SV_LEATHER_JACK 12 -#define SV_KUROSHOUZOKU 13 -#define SV_STONE_AND_HIDE_ARMOR 15 /* 15 */ -#define SV_ABUNAI_MIZUGI 50 -#define SV_YOIYAMI_ROBE 60 -#define SV_NAMAKE_ARMOR 63 - -/* The "sval" codes for TV_HARD_ARMOR */ -#define SV_RUSTY_CHAIN_MAIL 1 /* 14- */ -#define SV_RING_MAIL 2 /* 12 */ -#define SV_METAL_SCALE_MAIL 3 /* 13 */ -#define SV_CHAIN_MAIL 4 /* 14 */ -#define SV_DOUBLE_RING_MAIL 5 /* 15 */ -#define SV_AUGMENTED_CHAIN_MAIL 6 /* 16 */ -#define SV_DOUBLE_CHAIN_MAIL 7 /* 16 */ -#define SV_BAR_CHAIN_MAIL 8 /* 18 */ -#define SV_METAL_BRIGANDINE_ARMOUR 9 /* 19 */ -#define SV_SPLINT_MAIL 10 /* 19 */ -#define SV_DO_MARU 11 /* 20 */ -#define SV_PARTIAL_PLATE_ARMOUR 12 /* 22 */ -#define SV_METAL_LAMELLAR_ARMOUR 13 /* 23 */ -#define SV_HARAMAKIDO 14 /* 17 */ -#define SV_FULL_PLATE_ARMOUR 15 /* 25 */ -#define SV_O_YOROI 16 /* 24 */ -#define SV_RIBBED_PLATE_ARMOUR 18 /* 28 */ -#define SV_MITHRIL_CHAIN_MAIL 20 /* 28+ */ -#define SV_MITHRIL_PLATE_MAIL 25 /* 35+ */ -#define SV_ADAMANTITE_PLATE_MAIL 30 /* 40+ */ - -/* The "sval" codes for TV_DRAG_ARMOR */ -#define SV_DRAGON_BLACK 1 -#define SV_DRAGON_BLUE 2 -#define SV_DRAGON_WHITE 3 -#define SV_DRAGON_RED 4 -#define SV_DRAGON_GREEN 5 -#define SV_DRAGON_MULTIHUED 6 -#define SV_DRAGON_SHINING 10 -#define SV_DRAGON_LAW 12 -#define SV_DRAGON_BRONZE 14 -#define SV_DRAGON_GOLD 16 -#define SV_DRAGON_CHAOS 18 -#define SV_DRAGON_BALANCE 20 -#define SV_DRAGON_POWER 30 - -/* The sval codes for TV_LITE */ -#define SV_LITE_TORCH 0 -#define SV_LITE_LANTERN 1 -#define SV_LITE_FEANOR 2 -#define SV_LITE_EDISON 3 -#define SV_LITE_GALADRIEL 4 -#define SV_LITE_ELENDIL 5 -#define SV_LITE_JUDGE 6 -#define SV_LITE_LORE 7 -#define SV_LITE_PALANTIR 8 -#define SV_LITE_FLY_STONE 9 - -/* The "sval" codes for TV_AMULET */ -#define SV_AMULET_DOOM 0 -#define SV_AMULET_TELEPORT 1 -#define SV_AMULET_ADORNMENT 2 -#define SV_AMULET_SLOW_DIGEST 3 -#define SV_AMULET_RESIST_ACID 4 -#define SV_AMULET_SEARCHING 5 -#define SV_AMULET_BRILLIANCE 6 -#define SV_AMULET_CHARISMA 7 -#define SV_AMULET_THE_MAGI 8 -#define SV_AMULET_REFLECTION 9 -#define SV_AMULET_CARLAMMAS 10 -#define SV_AMULET_INGWE 11 -#define SV_AMULET_DWARVES 12 -#define SV_AMULET_NO_MAGIC 13 -#define SV_AMULET_NO_TELE 14 -#define SV_AMULET_RESISTANCE 15 -#define SV_AMULET_TELEPATHY 16 -#define SV_AMULET_FARAMIR 17 -#define SV_AMULET_BOROMIR 18 -#define SV_AMULET_MAGATAMA 19 -#define SV_AMULET_INROU 20 -#define SV_AMULET_INTELLIGENCE 21 -#define SV_AMULET_WISDOM 22 -#define SV_AMULET_MAGIC_MASTERY 23 -#define SV_AMULET_NIGHT 24 - -/* The sval codes for TV_RING */ -#define SV_RING_WOE 0 -#define SV_RING_AGGRAVATION 1 -#define SV_RING_WEAKNESS 2 -#define SV_RING_STUPIDITY 3 -#define SV_RING_TELEPORTATION 4 -#define SV_RING_SLOW_DIGESTION 6 -#define SV_RING_LEVITATION_FALL 7 -#define SV_RING_RESIST_FIRE 8 -#define SV_RING_RESIST_COLD 9 -#define SV_RING_SUSTAIN_STR 10 -#define SV_RING_SUSTAIN_INT 11 -#define SV_RING_SUSTAIN_WIS 12 -#define SV_RING_SUSTAIN_CON 13 -#define SV_RING_SUSTAIN_DEX 14 -#define SV_RING_SUSTAIN_CHR 15 -#define SV_RING_PROTECTION 16 -#define SV_RING_ACID 17 -#define SV_RING_FLAMES 18 -#define SV_RING_ICE 19 -#define SV_RING_RESIST_POIS 20 -#define SV_RING_FREE_ACTION 21 -#define SV_RING_SEE_INVIS 22 -#define SV_RING_SEARCHING 23 -#define SV_RING_STR 24 -#define SV_RING_ELEC 25 -#define SV_RING_DEX 26 -#define SV_RING_CON 27 -#define SV_RING_ACCURACY 28 -#define SV_RING_DAMAGE 29 -#define SV_RING_SLAYING 30 -#define SV_RING_SPEED 31 -#define SV_RING_FRAKIR 32 -#define SV_RING_TULKAS 33 -#define SV_RING_NARYA 34 -#define SV_RING_NENYA 35 -#define SV_RING_VILYA 36 -#define SV_RING_POWER 37 -#define SV_RING_RES_FEAR 38 -#define SV_RING_RES_LD 39 -#define SV_RING_RES_NETHER 40 -#define SV_RING_RES_NEXUS 41 -#define SV_RING_RES_SOUND 42 -#define SV_RING_RES_CONFUSION 43 -#define SV_RING_RES_SHARDS 44 -#define SV_RING_RES_DISENCHANT 45 -#define SV_RING_RES_CHAOS 46 -#define SV_RING_RES_BLINDNESS 47 -#define SV_RING_LORDLY 48 -#define SV_RING_ATTACKS 49 -#define SV_RING_AHO 50 -#define SV_RING_SHOTS 51 -#define SV_RING_SUSTAIN 52 -#define SV_RING_DEC_MANA 53 -#define SV_RING_WARNING 54 -#define SV_RING_MUSCLE 55 - -#define SV_EXPRESS_CARD 0 - -/* The "sval" codes for TV_STAFF */ -#define SV_STAFF_DARKNESS 0 -#define SV_STAFF_SLOWNESS 1 -#define SV_STAFF_HASTE_MONSTERS 2 -#define SV_STAFF_SUMMONING 3 -#define SV_STAFF_TELEPORTATION 4 -#define SV_STAFF_IDENTIFY 5 -#define SV_STAFF_REMOVE_CURSE 6 -#define SV_STAFF_STARLITE 7 -#define SV_STAFF_LITE 8 -#define SV_STAFF_MAPPING 9 -#define SV_STAFF_DETECT_GOLD 10 -#define SV_STAFF_DETECT_ITEM 11 -#define SV_STAFF_DETECT_TRAP 12 -#define SV_STAFF_DETECT_DOOR 13 -#define SV_STAFF_DETECT_INVIS 14 -#define SV_STAFF_DETECT_EVIL 15 -#define SV_STAFF_CURE_LIGHT 16 -#define SV_STAFF_CURING 17 -#define SV_STAFF_HEALING 18 -#define SV_STAFF_THE_MAGI 19 -#define SV_STAFF_SLEEP_MONSTERS 20 -#define SV_STAFF_SLOW_MONSTERS 21 -#define SV_STAFF_SPEED 22 -#define SV_STAFF_PROBING 23 -#define SV_STAFF_DISPEL_EVIL 24 -#define SV_STAFF_POWER 25 -#define SV_STAFF_HOLINESS 26 -#define SV_STAFF_GENOCIDE 27 -#define SV_STAFF_EARTHQUAKES 28 -#define SV_STAFF_DESTRUCTION 29 -#define SV_STAFF_ANIMATE_DEAD 30 -#define SV_STAFF_MSTORM 31 -#define SV_STAFF_NOTHING 32 - - -/* The "sval" codes for TV_WAND */ -#define SV_WAND_HEAL_MONSTER 0 -#define SV_WAND_HASTE_MONSTER 1 -#define SV_WAND_CLONE_MONSTER 2 -#define SV_WAND_TELEPORT_AWAY 3 -#define SV_WAND_DISARMING 4 -#define SV_WAND_TRAP_DOOR_DEST 5 -#define SV_WAND_STONE_TO_MUD 6 -#define SV_WAND_LITE 7 -#define SV_WAND_SLEEP_MONSTER 8 -#define SV_WAND_SLOW_MONSTER 9 -#define SV_WAND_CONFUSE_MONSTER 10 -#define SV_WAND_FEAR_MONSTER 11 -#define SV_WAND_HYPODYNAMIA 12 -#define SV_WAND_POLYMORPH 13 -#define SV_WAND_STINKING_CLOUD 14 -#define SV_WAND_MAGIC_MISSILE 15 -#define SV_WAND_ACID_BOLT 16 -#define SV_WAND_CHARM_MONSTER 17 -#define SV_WAND_FIRE_BOLT 18 -#define SV_WAND_COLD_BOLT 19 -#define SV_WAND_ACID_BALL 20 -#define SV_WAND_ELEC_BALL 21 -#define SV_WAND_FIRE_BALL 22 -#define SV_WAND_COLD_BALL 23 -#define SV_WAND_WONDER 24 -#define SV_WAND_DISINTEGRATE 25 -#define SV_WAND_DRAGON_FIRE 26 -#define SV_WAND_DRAGON_COLD 27 -#define SV_WAND_DRAGON_BREATH 28 -#define SV_WAND_ROCKETS 29 -#define SV_WAND_STRIKING 30 -#define SV_WAND_GENOCIDE 31 - -/* The "sval" codes for TV_ROD */ -#define SV_ROD_DETECT_TRAP 0 -#define SV_ROD_DETECT_DOOR 1 -#define SV_ROD_IDENTIFY 2 -#define SV_ROD_RECALL 3 -#define SV_ROD_ILLUMINATION 4 -#define SV_ROD_MAPPING 5 -#define SV_ROD_DETECTION 6 -#define SV_ROD_PROBING 7 -#define SV_ROD_CURING 8 -#define SV_ROD_HEALING 9 -#define SV_ROD_RESTORATION 10 -#define SV_ROD_SPEED 11 -#define SV_ROD_PESTICIDE 12 -#define SV_ROD_TELEPORT_AWAY 13 -#define SV_ROD_DISARMING 14 -#define SV_ROD_LITE 15 -#define SV_ROD_SLEEP_MONSTER 16 -#define SV_ROD_SLOW_MONSTER 17 -#define SV_ROD_HYPODYNAMIA 18 -#define SV_ROD_POLYMORPH 19 -#define SV_ROD_ACID_BOLT 20 -#define SV_ROD_ELEC_BOLT 21 -#define SV_ROD_FIRE_BOLT 22 -#define SV_ROD_COLD_BOLT 23 -#define SV_ROD_ACID_BALL 24 -#define SV_ROD_ELEC_BALL 25 -#define SV_ROD_FIRE_BALL 26 -#define SV_ROD_COLD_BALL 27 -#define SV_ROD_HAVOC 28 -#define SV_ROD_STONE_TO_MUD 29 -#define SV_ROD_AGGRAVATE 30 - - -/* The "sval" codes for TV_SCROLL */ - -#define SV_SCROLL_DARKNESS 0 -#define SV_SCROLL_AGGRAVATE_MONSTER 1 -#define SV_SCROLL_CURSE_ARMOR 2 -#define SV_SCROLL_CURSE_WEAPON 3 -#define SV_SCROLL_SUMMON_MONSTER 4 -#define SV_SCROLL_SUMMON_UNDEAD 5 -#define SV_SCROLL_SUMMON_PET 6 -#define SV_SCROLL_TRAP_CREATION 7 -#define SV_SCROLL_PHASE_DOOR 8 -#define SV_SCROLL_TELEPORT 9 -#define SV_SCROLL_TELEPORT_LEVEL 10 -#define SV_SCROLL_WORD_OF_RECALL 11 -#define SV_SCROLL_IDENTIFY 12 -#define SV_SCROLL_STAR_IDENTIFY 13 -#define SV_SCROLL_REMOVE_CURSE 14 -#define SV_SCROLL_STAR_REMOVE_CURSE 15 -#define SV_SCROLL_ENCHANT_ARMOR 16 -#define SV_SCROLL_ENCHANT_WEAPON_TO_HIT 17 -#define SV_SCROLL_ENCHANT_WEAPON_TO_DAM 18 -/* xxx enchant missile? */ -#define SV_SCROLL_STAR_ENCHANT_ARMOR 20 -#define SV_SCROLL_STAR_ENCHANT_WEAPON 21 -#define SV_SCROLL_RECHARGING 22 -#define SV_SCROLL_MUNDANITY 23 -#define SV_SCROLL_LIGHT 24 -#define SV_SCROLL_MAPPING 25 -#define SV_SCROLL_DETECT_GOLD 26 -#define SV_SCROLL_DETECT_ITEM 27 -#define SV_SCROLL_DETECT_TRAP 28 -#define SV_SCROLL_DETECT_DOOR 29 -#define SV_SCROLL_DETECT_INVIS 30 -/* xxx (detect evil?) */ -#define SV_SCROLL_SATISFY_HUNGER 32 -#define SV_SCROLL_BLESSING 33 -#define SV_SCROLL_HOLY_CHANT 34 -#define SV_SCROLL_HOLY_PRAYER 35 -#define SV_SCROLL_MONSTER_CONFUSION 36 -#define SV_SCROLL_PROTECTION_FROM_EVIL 37 -#define SV_SCROLL_RUNE_OF_PROTECTION 38 -#define SV_SCROLL_TRAP_DOOR_DESTRUCTION 39 -/* xxx */ -#define SV_SCROLL_STAR_DESTRUCTION 41 -#define SV_SCROLL_DISPEL_UNDEAD 42 -#define SV_SCROLL_SPELL 43 -#define SV_SCROLL_GENOCIDE 44 -#define SV_SCROLL_MASS_GENOCIDE 45 -#define SV_SCROLL_ACQUIREMENT 46 -#define SV_SCROLL_STAR_ACQUIREMENT 47 -#define SV_SCROLL_FIRE 48 -#define SV_SCROLL_ICE 49 -#define SV_SCROLL_CHAOS 50 -#define SV_SCROLL_RUMOR 51 -#define SV_SCROLL_ARTIFACT 52 -#define SV_SCROLL_RESET_RECALL 53 -#define SV_SCROLL_SUMMON_KIN 54 -#define SV_SCROLL_AMUSEMENT 55 -#define SV_SCROLL_STAR_AMUSEMENT 56 - -/* The "sval" codes for TV_POTION */ -#define SV_POTION_WATER 0 -#define SV_POTION_APPLE_JUICE 1 -#define SV_POTION_SLIME_MOLD 2 -/* xxx (fixed color) */ -#define SV_POTION_SLOWNESS 4 -#define SV_POTION_SALT_WATER 5 -#define SV_POTION_POISON 6 -#define SV_POTION_BLINDNESS 7 -/* xxx */ -#define SV_POTION_BOOZE 9 -/* xxx */ -#define SV_POTION_SLEEP 11 -/* xxx */ -#define SV_POTION_LOSE_MEMORIES 13 -/* xxx */ -#define SV_POTION_RUINATION 15 -#define SV_POTION_DEC_STR 16 -#define SV_POTION_DEC_INT 17 -#define SV_POTION_DEC_WIS 18 -#define SV_POTION_DEC_DEX 19 -#define SV_POTION_DEC_CON 20 -#define SV_POTION_DEC_CHR 21 -#define SV_POTION_DETONATIONS 22 -#define SV_POTION_DEATH 23 -#define SV_POTION_INFRAVISION 24 -#define SV_POTION_DETECT_INVIS 25 -#define SV_POTION_SLOW_POISON 26 -#define SV_POTION_CURE_POISON 27 -#define SV_POTION_BOLDNESS 28 -#define SV_POTION_SPEED 29 -#define SV_POTION_RESIST_HEAT 30 -#define SV_POTION_RESIST_COLD 31 -#define SV_POTION_HEROISM 32 -#define SV_POTION_BESERK_STRENGTH 33 -#define SV_POTION_CURE_LIGHT 34 -#define SV_POTION_CURE_SERIOUS 35 -#define SV_POTION_CURE_CRITICAL 36 -#define SV_POTION_HEALING 37 -#define SV_POTION_STAR_HEALING 38 -#define SV_POTION_LIFE 39 -#define SV_POTION_RESTORE_MANA 40 -#define SV_POTION_RESTORE_EXP 41 -#define SV_POTION_RES_STR 42 -#define SV_POTION_RES_INT 43 -#define SV_POTION_RES_WIS 44 -#define SV_POTION_RES_DEX 45 -#define SV_POTION_RES_CON 46 -#define SV_POTION_RES_CHR 47 -#define SV_POTION_INC_STR 48 -#define SV_POTION_INC_INT 49 -#define SV_POTION_INC_WIS 50 -#define SV_POTION_INC_DEX 51 -#define SV_POTION_INC_CON 52 -#define SV_POTION_INC_CHR 53 -/* xxx */ -#define SV_POTION_AUGMENTATION 55 -#define SV_POTION_ENLIGHTENMENT 56 -#define SV_POTION_STAR_ENLIGHTENMENT 57 -#define SV_POTION_SELF_KNOWLEDGE 58 -#define SV_POTION_EXPERIENCE 59 -#define SV_POTION_RESISTANCE 60 -#define SV_POTION_CURING 61 -#define SV_POTION_INVULNERABILITY 62 -#define SV_POTION_NEW_LIFE 63 -#define SV_POTION_NEO_TSUYOSHI 64 -#define SV_POTION_TSUYOSHI 65 -#define SV_POTION_POLYMORPH 66 - -/* The "sval" codes for TV_FLASK */ -#define SV_FLASK_OIL 0 - -/* The "sval" codes for TV_FOOD */ -#define SV_FOOD_POISON 0 -#define SV_FOOD_BLINDNESS 1 -#define SV_FOOD_PARANOIA 2 -#define SV_FOOD_CONFUSION 3 -#define SV_FOOD_HALLUCINATION 4 -#define SV_FOOD_PARALYSIS 5 -#define SV_FOOD_WEAKNESS 6 -#define SV_FOOD_SICKNESS 7 -#define SV_FOOD_STUPIDITY 8 -#define SV_FOOD_NAIVETY 9 -#define SV_FOOD_UNHEALTH 10 -#define SV_FOOD_DISEASE 11 -#define SV_FOOD_CURE_POISON 12 -#define SV_FOOD_CURE_BLINDNESS 13 -#define SV_FOOD_CURE_PARANOIA 14 -#define SV_FOOD_CURE_CONFUSION 15 -#define SV_FOOD_CURE_SERIOUS 16 -#define SV_FOOD_RESTORE_STR 17 -#define SV_FOOD_RESTORE_CON 18 -#define SV_FOOD_RESTORING 19 -/* many missing mushrooms */ -#define SV_FOOD_BISCUIT 32 -#define SV_FOOD_JERKY 33 -#define SV_FOOD_RATION 35 -#define SV_FOOD_SLIME_MOLD 36 -#define SV_FOOD_WAYBREAD 37 -#define SV_FOOD_PINT_OF_ALE 38 -#define SV_FOOD_PINT_OF_WINE 39 - - -#define SV_ROD_MIN_DIRECTION 12 /*!< この値以降の小項目IDを持ったロッドは使用時にターゲットを要求する / Special "sval" limit -- first "aimed" rod */ - -#define SV_CHEST_MIN_LARGE 4 /*!< この値以降の小項目IDを持った箱は大型の箱としてドロップ数を増やす / Special "sval" limit -- first "large" chest */ -#define SV_CHEST_KANDUME 50 /*!< 箱アイテムの小項目ID: おもちゃのカンヅメ */ - -/* - * Special "sval" limit -- first "good" magic/prayer book - */ -#define SV_BOOK_MIN_GOOD 2 - - -#define OBJ_GOLD_LIST 480 /* First "gold" entry */ -#define MAX_GOLD 18 /* Number of "gold" entries */ - - -/*** General flag values ***/ - - -/* - * 特殊なマス状態フラグ / Special grid flags - */ -#define CAVE_MARK 0x0001 /*!< 現在プレイヤーの記憶に収まっている / memorized feature */ -#define CAVE_GLOW 0x0002 /*!< マス自体が光源を持っている / self-illuminating */ -#define CAVE_ICKY 0x0004 /*!< 生成されたVaultの一部である / part of a vault */ -#define CAVE_ROOM 0x0008 /*!< 生成された部屋の一部である / part of a room */ -#define CAVE_LITE 0x0010 /*!< 現在光に照らされている / lite flag */ -#define CAVE_VIEW 0x0020 /*!< 現在プレイヤーの視界に収まっている / view flag */ -#define CAVE_TEMP 0x0040 /*!< 光源に関する処理のアルゴリズム用記録フラグ / temp flag */ -#define CAVE_XTRA 0x0080 /*!< 視界に関する処理のアルゴリズム用記録フラグ(update_view()等参照) / misc flag */ -#define CAVE_MNLT 0x0100 /*!< モンスターの光源によって照らされている / Illuminated by monster */ -#define CAVE_MNDK 0x8000 /*!< モンスターの暗源によって暗闇になっている / Darken by monster */ - -/* Used only while current_floor_ptr->grid_array generation */ -#define CAVE_FLOOR 0x0200 /*!< フロア属性のあるマス */ -#define CAVE_EXTRA 0x0400 -#define CAVE_INNER 0x0800 -#define CAVE_OUTER 0x1000 -#define CAVE_SOLID 0x2000 -#define CAVE_VAULT 0x4000 -#define CAVE_MASK (CAVE_FLOOR | CAVE_EXTRA | CAVE_INNER | CAVE_OUTER | CAVE_SOLID | CAVE_VAULT) - -/* Used only after current_floor_ptr->grid_array generation */ -#define CAVE_KNOWN 0x0200 /* Directly viewed or map detected flag */ -#define CAVE_NOTE 0x0400 /* Flag for delayed visual update (needs note_spot()) */ -#define CAVE_REDRAW 0x0800 /* Flag for delayed visual update (needs lite_spot()) */ -#define CAVE_OBJECT 0x1000 /* Mirror, glyph, etc. */ -#define CAVE_UNSAFE 0x2000 /* Might have trap */ -#define CAVE_IN_DETECT 0x4000 /* trap detected area (inner circle only) */ - - -/* - * Special caster ID for project() - */ -#define PROJECT_WHO_UNCTRL_POWER -1 /*!< 魔法効果の自然発生要因: 名状し難い力の解放 */ -#define PROJECT_WHO_GLASS_SHARDS -2 /*!< 魔法効果の自然発生要因: 破壊されたガラス地形の破片 */ - - -/* - * Bit flags for the "enchant()" function - */ -#define ENCH_TOHIT 0x01 /*!< 装備強化処理: 命中強化 / Enchant to hit */ -#define ENCH_TODAM 0x02 /*!< 装備強化処理: ダメージ強化 / Enchant to damage */ -#define ENCH_TOAC 0x04 /*!< 装備強化処理: AC強化 / Enchant to AC */ -#define ENCH_FORCE 0x08 /*!< 装備強化処理: 無条件に成功させる / Force enchantment */ - -/* - * target_set用関数の利用用途フラグ / Bit flags for the "target_set" function - */ -#define TARGET_KILL 0x01 /*!< モンスターへの狙いをつける(視界内モンスターのみクエリ対象) / Target monsters */ -#define TARGET_LOOK 0x02 /*!< "L"ookコマンド向けの既存情報確認向け(全ての有為な情報をクエリ対象) / Describe grid fully */ -#define TARGET_XTRA 0x04 /*!< 現在未使用 / Currently unused flag */ -#define TARGET_GRID 0x08 /*!< 全てのマス対象にする(現在未使用) / Select from all grids */ - - -/* - * Bit flags for control of get_check_strict() - */ -#define CHECK_OKAY_CANCEL 0x01 -#define CHECK_NO_ESCAPE 0x02 -#define CHECK_NO_HISTORY 0x04 -#define CHECK_DEFAULT_Y 0x08 - - - - -/* - * get_item()関数でアイテムの選択を行うフラグ / Bit flags for the "get_item" function - */ -#define USE_EQUIP 0x01 /*!< アイテム表示/選択範囲: 装備品からの選択を許可する / Allow equip items */ -#define USE_INVEN 0x02 /*!< アイテム表示/選択範囲: 所持品からの選択を許可する / Allow inven items */ -#define USE_FLOOR 0x04 /*!< アイテム表示/選択範囲: 床下のアイテムからの選択を許可する / Allow floor items */ -#define USE_FORCE 0x08 /*!< 特殊: wキーで錬気術への切り替えを許可する */ -#define IGNORE_BOTHHAND_SLOT 0x10 /*!< アイテム表示/選択範囲: 両手持ちスロットを選択に含めない */ -#define USE_FULL 0x20 /*!< アイテム表示/選択範囲: 空欄まですべて表示する*/ - - - - -/* - * p_ptr->updateに充てるプレイヤーステータス更新処理要求 / Bit flags for the "p_ptr->update" variable - */ - - -/* - * Bit flags for the "p_ptr->redraw" variable - */ -#define PR_MISC 0x00000001L /*!< 再描画フラグ: 種族と職業 / Display Race/Class */ -#define PR_TITLE 0x00000002L /*!< 再描画フラグ: 称号 / Display Title */ -#define PR_LEV 0x00000004L /*!< 再描画フラグ: レベル / Display Level */ -#define PR_EXP 0x00000008L /*!< 再描画フラグ: 経験値 / Display Experience */ -#define PR_STATS 0x00000010L /*!< 再描画フラグ: ステータス / Display Stats */ -#define PR_ARMOR 0x00000020L /*!< 再描画フラグ: AC / Display Armor */ -#define PR_HP 0x00000040L /*!< 再描画フラグ: HP / Display Hitpoints */ -#define PR_MANA 0x00000080L /*!< 再描画フラグ: MP / Display Mana */ -#define PR_GOLD 0x00000100L /*!< 再描画フラグ: 所持金 / Display Gold */ -#define PR_DEPTH 0x00000200L /*!< 再描画フラグ: ダンジョンの階 / Display Depth */ -#define PR_EQUIPPY 0x00000400L /*!< 再描画フラグ: 装備シンボル / Display equippy chars */ -#define PR_HEALTH 0x00000800L /*!< 再描画フラグ: モンスターのステータス / Display Health Bar */ -#define PR_CUT 0x00001000L /*!< 再描画フラグ: 負傷度 / Display Extra (Cut) */ -#define PR_STUN 0x00002000L /*!< 再描画フラグ: 朦朧度 / Display Extra (Stun) */ -#define PR_HUNGER 0x00004000L /*!< 再描画フラグ: 空腹度 / Display Extra (Hunger) */ -#define PR_STATUS 0x00008000L /*!< 再描画フラグ: プレイヤーの付与状態 / Display Status Bar */ -#define PR_XXX0 0x00010000L /*!< (unused) */ -#define PR_UHEALTH 0x00020000L /*!< 再描画フラグ: ペットのステータス / Display Uma Health Bar */ -#define PR_XXX1 0x00040000L /*!< (unused) */ -#define PR_XXX2 0x00080000L /*!< (unused) */ -#define PR_STATE 0x00100000L /*!< 再描画フラグ: プレイヤーの行動状態 / Display Extra (State) */ -#define PR_SPEED 0x00200000L /*!< 再描画フラグ: 加速 / Display Extra (Speed) */ -#define PR_STUDY 0x00400000L /*!< 再描画フラグ: 学習 / Display Extra (Study) */ -#define PR_IMITATION 0x00800000L /*!< 再描画フラグ: ものまね / Display Extra (Imitation) */ -#define PR_EXTRA 0x01000000L /*!< 再描画フラグ: 拡張ステータス全体 / Display Extra Info */ -#define PR_BASIC 0x02000000L /*!< 再描画フラグ: 基本ステータス全体 / Display Basic Info */ -#define PR_MAP 0x04000000L /*!< 再描画フラグ: ゲームマップ / Display Map */ -#define PR_WIPE 0x08000000L /*!< 再描画フラグ: 画面消去 / Hack -- Total Redraw */ -/* xxx */ -/* xxx */ -/* xxx */ -/* xxx */ - -/* - * Bit flags for the "p_ptr->window" variable (etc) - */ -#define PW_INVEN 0x00000001L /*!<サブウィンドウ描画フラグ: 所持品-装備品 / Display inven/equip */ -#define PW_EQUIP 0x00000002L /*!<サブウィンドウ描画フラグ: 装備品-所持品 / Display equip/inven */ -#define PW_SPELL 0x00000004L /*!<サブウィンドウ描画フラグ: 魔法一覧 / Display spell list */ -#define PW_PLAYER 0x00000008L /*!<サブウィンドウ描画フラグ: プレイヤーのステータス / Display character */ -#define PW_MONSTER_LIST 0x00000010L /*!<サブウィンドウ描画フラグ: 視界内モンスターの一覧 / Display monster list */ -/* xxx */ -/* xxx */ -#define PW_MESSAGE 0x00000040L /*!<サブウィンドウ描画フラグ: メッセージログ / Display messages */ -#define PW_OVERHEAD 0x00000080L /*!<サブウィンドウ描画フラグ: 周辺の光景 / Display overhead view */ -#define PW_MONSTER 0x00000100L /*!<サブウィンドウ描画フラグ: モンスターの思い出 / Display monster recall */ -#define PW_OBJECT 0x00000200L /*!<サブウィンドウ描画フラグ: アイテムの知識 / Display object recall */ -#define PW_DUNGEON 0x00000400L /*!<サブウィンドウ描画フラグ: ダンジョンの地形 / Display dungeon view */ -#define PW_SNAPSHOT 0x00000800L /*!<サブウィンドウ描画フラグ: 記念写真 / Display snap-shot */ -/* xxx */ -/* xxx */ -#define PW_BORG_1 0x00004000L /*!<サブウィンドウ描画フラグ: ボーグメッセージ / Display borg messages */ -#define PW_BORG_2 0x00008000L /*!<サブウィンドウ描画フラグ: ボーグステータス / Display borg status */ - - -/* - * Bit flags for object_desc() - */ -#define OD_NAME_ONLY 0x00000001 /* Omit values, pval, inscription */ -#define OD_NAME_AND_ENCHANT 0x00000002 /* Omit pval, inscription */ -#define OD_OMIT_INSCRIPTION 0x00000004 /* Omit inscription */ -#define OD_OMIT_PREFIX 0x00000008 /* Omit numeric prefix */ -#define OD_NO_PLURAL 0x00000010 /* Don't use plural */ -#define OD_STORE 0x00000020 /* Assume to be aware and known */ -#define OD_NO_FLAVOR 0x00000040 /* Allow to hidden flavor */ -#define OD_FORCE_FLAVOR 0x00000080 /* Get un-shuffled flavor name */ - - -/* - * p_ptr->special_attackによるプレイヤーの攻撃状態の定義 / Bit flags for the "p_ptr->special_attack" variable. -LM- - * - * Note: The elemental and poison attacks should be managed using the - * function "set_ele_attack", in spell2.c. This provides for timeouts and - * prevents the player from getting more than one at a time. - */ -#define ATTACK_CONFUSE 0x00000001 /*!< プレイヤーのステータス:混乱打撃 */ -#define ATTACK_XXX1 0x00000002 /*!< プレイヤーのステータス:未使用1 */ -#define ATTACK_XXX2 0x00000004 /*!< プレイヤーのステータス:未使用2 */ -#define ATTACK_XXX3 0x00000008 /*!< プレイヤーのステータス:未使用3 */ -#define ATTACK_ACID 0x00000010 /*!< プレイヤーのステータス:魔法剣/溶解 */ -#define ATTACK_ELEC 0x00000020 /*!< プレイヤーのステータス:魔法剣/電撃 */ -#define ATTACK_FIRE 0x00000040 /*!< プレイヤーのステータス:魔法剣/火炎 */ -#define ATTACK_COLD 0x00000080 /*!< プレイヤーのステータス:魔法剣/冷凍 */ -#define ATTACK_POIS 0x00000100 /*!< プレイヤーのステータス:魔法剣/毒殺 */ -#define ATTACK_HOLY 0x00000200 /*!< プレイヤーのステータス:対邪?(未使用) */ -#define ATTACK_SUIKEN 0x00000400 /*!< プレイヤーのステータス:酔拳 */ - -/* - * p_ptr->special_defenseによるプレイヤーの防御状態の定義 / Bit flags for the "p_ptr->special_defense" variable. -LM- - */ -#define DEFENSE_ACID 0x00000001 /*!< プレイヤーのステータス:酸免疫 */ -#define DEFENSE_ELEC 0x00000002 /*!< プレイヤーのステータス:電撃免疫 */ -#define DEFENSE_FIRE 0x00000004 /*!< プレイヤーのステータス:火炎免疫 */ -#define DEFENSE_COLD 0x00000008 /*!< プレイヤーのステータス:冷気免疫 */ -#define DEFENSE_POIS 0x00000010 /*!< プレイヤーのステータス:毒免疫 */ -#define KAMAE_GENBU 0x00000020 /*!< プレイヤーのステータス:玄武の構え */ -#define KAMAE_BYAKKO 0x00000040 /*!< プレイヤーのステータス:白虎の構え */ -#define KAMAE_SEIRYU 0x00000080 /*!< プレイヤーのステータス:青竜の構え */ -#define KAMAE_SUZAKU 0x00000100 /*!< プレイヤーのステータス:朱雀の構え */ -#define KATA_IAI 0x00000200 /*!< プレイヤーのステータス:居合 */ -#define KATA_FUUJIN 0x00000400 /*!< プレイヤーのステータス:風塵 */ -#define KATA_KOUKIJIN 0x00000800 /*!< プレイヤーのステータス:降鬼陣 */ -#define KATA_MUSOU 0x00001000 /*!< プレイヤーのステータス:無想 */ -#define NINJA_KAWARIMI 0x00002000 /*!< プレイヤーのステータス:変わり身 */ -#define NINJA_S_STEALTH 0x00004000 /*!< プレイヤーのステータス:超隠密 */ - -#define MAX_KAMAE 4 /*!< 修行僧の構え最大数 */ -#define KAMAE_MASK (KAMAE_GENBU | KAMAE_BYAKKO | KAMAE_SEIRYU | KAMAE_SUZAKU) /*!< 修行僧の構えビット配列 */ - -#define MAX_KATA 4 /*!< 修行僧の型最大数 */ -#define KATA_MASK (KATA_IAI | KATA_FUUJIN | KATA_KOUKIJIN | KATA_MUSOU) /*!< 修行僧の型ビット配列 */ - - -#define ACTION_NONE 0 /*!< 持続行動: なし */ -#define ACTION_SEARCH 1 /*!< 持続行動: 探索 */ -#define ACTION_REST 2 /*!< 持続行動: 休憩 */ -#define ACTION_LEARN 3 /*!< 持続行動: 青魔法ラーニング */ -#define ACTION_FISH 4 /*!< 持続行動: 釣り */ -#define ACTION_KAMAE 5 /*!< 持続行動: 修行僧の構え */ -#define ACTION_KATA 6 /*!< 持続行動: 剣術家の型 */ -#define ACTION_SING 7 /*!< 持続行動: 歌 */ -#define ACTION_HAYAGAKE 8 /*!< 持続行動: 早駆け */ -#define ACTION_SPELL 9 /*!< 持続行動: 呪術 */ - - -/* Empty hand status */ -#define EMPTY_HAND_NONE 0x0000 /* Both hands are used */ -#define EMPTY_HAND_LARM 0x0001 /* Left hand is empty */ -#define EMPTY_HAND_RARM 0x0002 /* Right hand is empty */ - -/*** General index values ***/ - - -/* - * summon_specificで取り扱われる、召喚の種別定義 / Legal restrictions for "summon_specific()" - */ -#define SUMMON_ANT 11 /*!< 召喚タイプ: アリ */ -#define SUMMON_SPIDER 12 /*!< 召喚タイプ: 蜘蛛 */ -#define SUMMON_HOUND 13 /*!< 召喚タイプ: ハウンド */ -#define SUMMON_HYDRA 14 /*!< 召喚タイプ: ヒドラ */ -#define SUMMON_ANGEL 15 /*!< 召喚タイプ: 天使 */ -#define SUMMON_DEMON 16 /*!< 召喚タイプ: 悪魔 */ -#define SUMMON_UNDEAD 17 /*!< 召喚タイプ: アンデッド */ -#define SUMMON_DRAGON 18 /*!< 召喚タイプ: ドラゴン */ -#define SUMMON_HI_UNDEAD 21 /*!< 召喚タイプ: 強力なアンデッド */ -#define SUMMON_HI_DRAGON 22 /*!< 召喚タイプ: 古代ドラゴン */ -#define SUMMON_HI_DEMON 23 /*!< 召喚タイプ: 上級デーモン */ -#define SUMMON_AMBERITES 31 /*!< 召喚タイプ: アンバーの王族 */ -#define SUMMON_UNIQUE 32 /*!< 召喚タイプ: ユニーク */ -#define SUMMON_MOLD 33 /*!< 召喚タイプ: カビ */ -#define SUMMON_BAT 34 /*!< 召喚タイプ: コウモリ */ -#define SUMMON_QUYLTHULG 35 /*!< 召喚タイプ: クイルスルグ */ -#define SUMMON_XXX1 36 /*!< 召喚タイプ: 未使用 */ -#define SUMMON_COIN_MIMIC 37 /*!< 召喚タイプ: クリーピング・コイン */ -#define SUMMON_MIMIC 38 /*!< 召喚タイプ: ミミック */ -#define SUMMON_CYBER 39 /*!< 召喚タイプ: サイバーデーモン */ -#define SUMMON_KIN 40 /*!< 召喚タイプ: 召喚者の同族 */ -#define SUMMON_DAWN 41 /*!< 召喚タイプ: 暁の戦士 */ -#define SUMMON_ANIMAL 42 /*!< 召喚タイプ: 自然界の動物 */ -#define SUMMON_ANIMAL_RANGER 43 /*!< 召喚タイプ: レンジャー向け自然界の動物 */ -/*#define SUMMON_HI_UNDEAD_NO_UNIQUES 44*/ -/*#define SUMMON_HI_DRAGON_NO_UNIQUES 45*/ -/*#define SUMMON_NO_UNIQUES 46*/ -#define SUMMON_PHANTOM 47 /*!< 召喚タイプ: ゴースト */ -/*#define SUMMON_ELEMENTAL_NO_UNIQUES 48*/ -#define SUMMON_BLUE_HORROR 49 /*!< 召喚タイプ: ブルー・ホラー */ -#define SUMMON_LIVING 50 /*!< 召喚タイプ: 生命のあるモンスター */ -#define SUMMON_HI_DRAGON_LIVING 51 /*!< 召喚タイプ: 生命のある古代ドラゴン */ -#define SUMMON_GOLEM 52 /*!< 召喚タイプ: ゴーレム */ -#define SUMMON_ELEMENTAL 53 /*!< 召喚タイプ: エレメンタル */ -#define SUMMON_VORTEX 54 /*!< 召喚タイプ: ボルテックス */ -#define SUMMON_HYBRID 55 /*!< 召喚タイプ: 混合生物 */ -#define SUMMON_BIRD 56 /*!< 召喚タイプ: é³¥ */ -/*#define SUMMON_AQUATIC_NO_UNIQUES 57*/ -#define SUMMON_KAMIKAZE 58 /*!< 召喚タイプ: 自爆モンスター */ -#define SUMMON_KAMIKAZE_LIVING 59 /*!< 召喚タイプ: 生命のある自爆モンスター */ -#define SUMMON_MANES 60 /*!< 召喚タイプ: 古代の死霊 */ -#define SUMMON_LOUSE 61 /*!< 召喚タイプ: シラミ */ -#define SUMMON_GUARDIANS 62 /*!< 召喚タイプ: ダンジョンの主 */ -#define SUMMON_KNIGHTS 63 /*!< 召喚タイプ: 聖戦用騎士系モンスター */ -#define SUMMON_EAGLES 64 /*!< 召喚タイプ: 鷲系モンスター */ -#define SUMMON_PIRANHAS 65 /*!< 召喚タイプ: ピラニア・トラップ用 */ -#define SUMMON_ARMAGE_GOOD 66 /*!< 召喚タイプ: ハルマゲドン・トラップ用天使陣営 */ -#define SUMMON_ARMAGE_EVIL 67 /*!< 召喚タイプ: ハルマゲドン・トラップ用悪魔陣営 */ - - -/* - * Spell types used by project(), and related functions. - */ -#define GF_ELEC 1 /*!< 魔法効果: 電撃*/ -#define GF_POIS 2 /*!< 魔法効果: 毒*/ -#define GF_ACID 3 /*!< 魔法効果: 酸*/ -#define GF_COLD 4 /*!< 魔法効果: 冷気*/ -#define GF_FIRE 5 /*!< 魔法効果: 火炎*/ -#define GF_PSY_SPEAR 9 /*!< 魔法効果: 光の剣*/ -#define GF_MISSILE 10 /*!< 魔法効果: 弱魔力*/ -#define GF_ARROW 11 /*!< 魔法効果: 射撃*/ -#define GF_PLASMA 12 /*!< 魔法効果: プラズマ*/ -/* Replaced with GF_HOLY_FIRE and GF_HELL_FIRE */ -/* #define GF_HOLY_ORB 13 */ -#define GF_WATER 14 /*!< 魔法効果: 水流*/ -#define GF_LITE 15 /*!< 魔法効果: 閃光*/ -#define GF_DARK 16 /*!< 魔法効果: 暗黒*/ -#define GF_LITE_WEAK 17 /*!< 魔法効果: 弱光*/ -#define GF_DARK_WEAK 18 /*!< 魔法効果: 弱暗*/ -#define GF_SHARDS 20 /*!< 魔法効果: 破片*/ -#define GF_SOUND 21 /*!< 魔法効果: 轟音*/ -#define GF_CONFUSION 22 /*!< 魔法効果: æ··ä¹±*/ -#define GF_FORCE 23 /*!< 魔法効果: フォース*/ -#define GF_INERTIAL 24 /*!< 魔法効果: 遅鈍*/ -#define GF_MANA 26 /*!< 魔法効果: 純粋魔力*/ -#define GF_METEOR 27 /*!< 魔法効果: 隕石*/ -#define GF_ICE 28 /*!< 魔法効果: 極寒*/ -#define GF_CHAOS 30 /*!< 魔法効果: カオス*/ -#define GF_NETHER 31 /*!< 魔法効果: 地獄*/ -#define GF_DISENCHANT 32 /*!< 魔法効果: 劣化*/ -#define GF_NEXUS 33 /*!< 魔法効果: 因果混乱*/ -#define GF_TIME 34 /*!< 魔法効果: 時間逆転*/ -#define GF_GRAVITY 35 /*!< 魔法効果: 重力*/ -#define GF_KILL_WALL 40 /*!< 魔法効果: 岩石溶解*/ -#define GF_KILL_DOOR 41 /*!< 魔法効果: ドア破壊*/ -#define GF_KILL_TRAP 42 /*!< 魔法効果: トラップ破壊*/ -#define GF_MAKE_WALL 45 /*!< 魔法効果: 壁生成*/ -#define GF_MAKE_DOOR 46 /*!< 魔法効果: ドア生成*/ -#define GF_MAKE_TRAP 47 /*!< 魔法効果: トラップ生成*/ -#define GF_MAKE_TREE 48 /*!< 魔法効果: 森林生成*/ -#define GF_OLD_CLONE 51 /*!< 魔法効果: クローン・モンスター*/ -#define GF_OLD_POLY 52 /*!< 魔法効果: チェンジ・モンスター*/ -#define GF_OLD_HEAL 53 /*!< 魔法効果: 回復モンスター*/ -#define GF_OLD_SPEED 54 /*!< 魔法効果: スピード・モンスター*/ -#define GF_OLD_SLOW 55 /*!< 魔法効果: スロウ・モンスター*/ -#define GF_OLD_CONF 56 /*!< 魔法効果: パニック・モンスター*/ -#define GF_OLD_SLEEP 57 /*!< 魔法効果: スリープ・モンスター*/ -#define GF_HYPODYNAMIA 58 /*!< 魔法効果: è¡°å¼±*/ -#define GF_AWAY_UNDEAD 61 /*!< 魔法効果: アンデッド・アウェイ*/ -#define GF_AWAY_EVIL 62 /*!< 魔法効果: 邪悪飛ばし*/ -#define GF_AWAY_ALL 63 /*!< 魔法効果: テレポート・アウェイ*/ -#define GF_TURN_UNDEAD 64 /*!< 魔法効果: アンデッド恐慌*/ -#define GF_TURN_EVIL 65 /*!< 魔法効果: 邪悪恐慌*/ -#define GF_TURN_ALL 66 /*!< 魔法効果: モンスター恐慌*/ -#define GF_DISP_UNDEAD 67 /*!< 魔法効果: アンデッド退散*/ -#define GF_DISP_EVIL 68 /*!< 魔法効果: 邪悪退散*/ -#define GF_DISP_ALL 69 /*!< 魔法効果: モンスター退散*/ -/* New types for Zangband begin here... */ -#define GF_DISP_DEMON 70 /*!< 魔法効果: 悪魔退散*/ -#define GF_DISP_LIVING 71 /*!< 魔法効果: 生命退散*/ -#define GF_ROCKET 72 /*!< 魔法効果: ロケット*/ -#define GF_NUKE 73 /*!< 魔法効果: 放射性廃棄物*/ -#define GF_MAKE_GLYPH 74 /*!< 魔法効果: 守りのルーン生成*/ -#define GF_STASIS 75 /*!< 魔法効果: モンスター拘束*/ -#define GF_STONE_WALL 76 /*!< 魔法効果: 壁生成*/ -#define GF_DEATH_RAY 77 /*!< 魔法効果: 死の光線*/ -#define GF_STUN 78 /*!< 魔法効果: 朦朧*/ -#define GF_HOLY_FIRE 79 /*!< 魔法効果: 聖光*/ -#define GF_HELL_FIRE 80 /*!< 魔法効果: 地獄の劫火*/ -#define GF_DISINTEGRATE 81 /*!< 魔法効果: 分解*/ -#define GF_CHARM 82 /*!< 魔法効果: モンスター魅了*/ -#define GF_CONTROL_UNDEAD 83 /*!< 魔法効果: アンデッド支配*/ -#define GF_CONTROL_ANIMAL 84 /*!< 魔法効果: 動物支配*/ -#define GF_PSI 85 /*!< 魔法効果: サイキック攻撃*/ -#define GF_PSI_DRAIN 86 /*!< 魔法効果: 精神吸収*/ -#define GF_TELEKINESIS 87 /*!< 魔法効果: テレキシネス*/ -#define GF_JAM_DOOR 88 /*!< 魔法効果: 施錠*/ -#define GF_DOMINATION 89 /*!< 魔法効果: 精神支配*/ -#define GF_DISP_GOOD 90 /*!< 魔法効果: 善良退散*/ -#define GF_DRAIN_MANA 91 /*!< 魔法効果: 魔力吸収*/ -#define GF_MIND_BLAST 92 /*!< 魔法効果: 精神攻撃*/ -#define GF_BRAIN_SMASH 93 /*!< 魔法効果: 脳攻撃*/ -#define GF_CAUSE_1 94 /*!< 魔法効果: 軽傷の呪い*/ -#define GF_CAUSE_2 95 /*!< 魔法効果: 重傷の呪い*/ -#define GF_CAUSE_3 96 /*!< 魔法効果: 致命傷の呪い*/ -#define GF_CAUSE_4 97 /*!< 魔法効果: 秘孔を突く*/ -#define GF_HAND_DOOM 98 /*!< 魔法効果: 破滅の手*/ -#define GF_CAPTURE 99 /*!< 魔法効果: 捕縛*/ -#define GF_ANIM_DEAD 100 /*!< 魔法効果: 死者復活*/ -#define GF_CHARM_LIVING 101 /*!< 魔法効果: 生命魅了*/ -#define GF_IDENTIFY 102 /*!< 魔法効果: 鑑定*/ -#define GF_ATTACK 103 /*!< 魔法効果: 白兵*/ -#define GF_ENGETSU 104 /*!< 魔法効果: 円月*/ -#define GF_GENOCIDE 105 /*!< 魔法効果: 抹殺*/ -#define GF_PHOTO 106 /*!< 魔法効果: 撮影*/ -#define GF_CONTROL_DEMON 107 /*!< 魔法効果: 悪魔支配*/ -#define GF_LAVA_FLOW 108 /*!< 魔法効果: 溶岩噴出*/ -#define GF_BLOOD_CURSE 109 /*!< 魔法効果: 血の呪い*/ -#define GF_SEEKER 110 /*!< 魔法効果: シーカーレイ*/ -#define GF_SUPER_RAY 111 /*!< 魔法効果: スーパーレイ*/ -#define GF_STAR_HEAL 112 /*!< 魔法効果: 星の癒し*/ -#define GF_WATER_FLOW 113 /*!< 魔法効果: 流水*/ -#define GF_CRUSADE 114 /*!< 魔法効果: 聖戦*/ -#define GF_STASIS_EVIL 115 /*!< 魔法効果: 邪悪拘束*/ -#define GF_WOUNDS 116 /*!< 魔法効果: 創傷*/ - -#define MAX_GF 117 - -/* - * Some things which induce learning - */ -#define DRS_ACID 1 -#define DRS_ELEC 2 -#define DRS_FIRE 3 -#define DRS_COLD 4 -#define DRS_POIS 5 -#define DRS_NETH 6 -#define DRS_LITE 7 -#define DRS_DARK 8 -#define DRS_FEAR 9 -#define DRS_CONF 10 -#define DRS_CHAOS 11 -#define DRS_DISEN 12 -#define DRS_BLIND 13 -#define DRS_NEXUS 14 -#define DRS_SOUND 15 -#define DRS_SHARD 16 -#define DRS_FREE 30 -#define DRS_MANA 31 -#define DRS_REFLECT 32 - - - -#define DAMAGE_FORCE 1 -#define DAMAGE_GENO 2 -#define DAMAGE_LOSELIFE 3 -#define DAMAGE_ATTACK 4 -#define DAMAGE_NOESCAPE 5 -#define DAMAGE_USELIFE 6 - - -/* - * アイテムの簡易鑑定定義 / Game generated inscription indices. These are stored in the object, - * and are used to index the string array from tables.c. - */ -#define FEEL_NONE 0 /*!< 簡易鑑定: 未鑑定 */ -#define FEEL_BROKEN 1 /*!< 簡易鑑定: 壊れている */ -#define FEEL_TERRIBLE 2 /*!< 簡易鑑定: 恐ろしい */ -#define FEEL_WORTHLESS 3 /*!< 簡易鑑定: 無価値 */ -#define FEEL_CURSED 4 /*!< 簡易鑑定: 呪われている */ -#define FEEL_UNCURSED 5 /*!< 簡易鑑定: 呪われていない */ -#define FEEL_AVERAGE 6 /*!< 簡易鑑定: 並 */ -#define FEEL_GOOD 7 /*!< 簡易鑑定: 上質 */ -#define FEEL_EXCELLENT 8 /*!< 簡易鑑定: 高級 */ -#define FEEL_SPECIAL 9 /*!< 簡易鑑定: 特別 */ - -#define FEEL_MAX 9 /*!< 簡易鑑定の種別数 */ - -/* - * 変愚ver1.5.0以前に使われていたアイテムの追加特性フラグ / Hack -- special "xtra" object powers - */ -#define EGO_XTRA_SUSTAIN 1 /*!< 旧版アイテムフラグ(非推奨): 追加維持能力 / Sustain one stat */ -#define EGO_XTRA_POWER 2 /*!< 旧版アイテムフラグ(非推奨): 追加上級耐性 / High resist */ -#define EGO_XTRA_ABILITY 3 /*!< 旧版アイテムフラグ(非推奨): 追加能力 / Special ability */ - - -/*** Object flag values ***/ - - -/*! - * 箱のトラップ定義 Chest trap flags (see "tables.c") - */ -#define CHEST_LOSE_STR 0x0001 /*!< 箱のトラップ: STR減少の毒針 */ -#define CHEST_LOSE_CON 0x0002 /*!< 箱のトラップ: CON減少の毒針 */ -#define CHEST_POISON 0x0004 /*!< 箱のトラップ: 毒針 */ -#define CHEST_PARALYZE 0x0008 /*!< 箱のトラップ: 麻痺ガス */ -#define CHEST_EXPLODE 0x0010 /*!< 箱のトラップ: 爆発 */ -#define CHEST_SUMMON 0x0020 /*!< 箱のトラップ: 召喚のルーン(モンスター) */ -#define CHEST_SCATTER 0x0040 /*!< 箱のトラップ: アイテム散乱 */ -#define CHEST_E_SUMMON 0x0080 /*!< 箱のトラップ: 召喚のルーン(エレメンタル) */ -#define CHEST_BIRD_STORM 0x0100 /*!< 箱のトラップ: 召喚のルーン(é³¥) */ -#define CHEST_H_SUMMON 0x0200 /*!< 箱のトラップ: 召喚のルーン(強敵) */ -#define CHEST_RUNES_OF_EVIL 0x0400 /*!< 箱のトラップ: 邪悪なルーン */ -#define CHEST_ALARM 0x0800 /*!< 箱のトラップ: 警報装置 */ - - -/* - * Special Object Flags - */ -#define IDENT_SENSE 0x01 /* Item has been "sensed" */ -#define IDENT_FIXED 0x02 /* Item has been "haggled" */ -#define IDENT_EMPTY 0x04 /* Item charges are known */ -#define IDENT_KNOWN 0x08 /* Item abilities are known */ -#define IDENT_STORE 0x10 /* Item is storebought !!!! */ -#define IDENT_MENTAL 0x20 /* Item information is known */ -#if 0 -#define IDENT_CURSED 0x40 /* Item is temporarily cursed */ -#endif -#define IDENT_BROKEN 0x80 /* Item is permanently worthless */ - - -/* - * How object is marked (flags in object_type.mark) - * OM_FOUND --- original boolean flag - * OM_NOMSG --- temporary flag to suppress messages which were - * already printed in autopick_pickup_items(). - */ -#define OM_FOUND 0x01 /*!< アイテムを一度でも視界に収めたことがあるか */ -#define OM_NOMSG 0x02 /* temporary flag to suppress messages */ -#define OM_NO_QUERY 0x04 /* Query for auto-pick was already answered as 'No' */ -#define OM_AUTODESTROY 0x08 /* Destroy later to avoid illegal inventry shift */ -#define OM_TOUCHED 0x10 /* Object was touched by player */ - - -/* - * Object flags - * - * Old variables for object flags such as flags1, flags2, and flags3 - * are obsolated. Now single array flgs[TR_FLAG_SIZE] contains all - * object flags. And each flag is refered by single index number - * instead of a bit mask. - * - * Therefore it's very easy to add a lot of new flags; no one need to - * worry about in which variable a new flag should be put, nor to - * modify a huge number of files all over the source directory at once - * to add new flag variables such as flags4, a_ability_flags1, etc... - * - * All management of flags is now treated using a set of macros - * instead of bit operations. - * Note: These macros are using division, modulo, and bit shift - * operations, and it seems that these operations are rather slower - * than original bit operation. But since index numbers are almost - * always given as constant, such slow operations are performed in the - * compile time. So there is no problem on the speed. - * - * Exceptions of new flag management is a set of flags to control - * object generation and the curse flags. These are not yet rewritten - * in new index form; maybe these have no merit of rewriting. - */ - -#define have_flag(ARRAY, INDEX) !!((ARRAY)[(INDEX)/32] & (1L << ((INDEX)%32))) -#define add_flag(ARRAY, INDEX) ((ARRAY)[(INDEX)/32] |= (1L << ((INDEX)%32))) -#define remove_flag(ARRAY, INDEX) ((ARRAY)[(INDEX)/32] &= ~(1L << ((INDEX)%32))) -#define is_pval_flag(INDEX) ((TR_STR <= (INDEX) && (INDEX) <= TR_MAGIC_MASTERY) || (TR_STEALTH <= (INDEX) && (INDEX) <= TR_BLOWS)) -#define have_pval_flags(ARRAY) !!((ARRAY)[0] & (0x00003f7f)) - - -#define TR_STR 0 /* STR += "pval" */ -#define TR_INT 1 /* INT += "pval" */ -#define TR_WIS 2 /* WIS += "pval" */ -#define TR_DEX 3 /* DEX += "pval" */ -#define TR_CON 4 /* CON += "pval" */ -#define TR_CHR 5 /* CHR += "pval" */ -#define TR_MAGIC_MASTERY 6 /* Later */ -#define TR_FORCE_WEAPON 7 /* Later */ -#define TR_STEALTH 8 /* Stealth += "pval" */ -#define TR_SEARCH 9 /* Search += "pval" */ -#define TR_INFRA 10 /* Infra += "pval" */ -#define TR_TUNNEL 11 /* Tunnel += "pval" */ -#define TR_SPEED 12 /* Speed += "pval" */ -#define TR_BLOWS 13 /* Blows += "pval" */ -#define TR_CHAOTIC 14 -#define TR_VAMPIRIC 15 -#define TR_SLAY_ANIMAL 16 -#define TR_SLAY_EVIL 17 -#define TR_SLAY_UNDEAD 18 -#define TR_SLAY_DEMON 19 -#define TR_SLAY_ORC 20 -#define TR_SLAY_TROLL 21 -#define TR_SLAY_GIANT 22 -#define TR_SLAY_DRAGON 23 -#define TR_KILL_DRAGON 24 /* Execute Dragon */ -#define TR_VORPAL 25 /* Later */ -#define TR_IMPACT 26 /* Cause Earthquakes */ -#define TR_BRAND_POIS 27 -#define TR_BRAND_ACID 28 -#define TR_BRAND_ELEC 29 -#define TR_BRAND_FIRE 30 -#define TR_BRAND_COLD 31 - -#define TR_SUST_STR 32 -#define TR_SUST_INT 33 -#define TR_SUST_WIS 34 -#define TR_SUST_DEX 35 -#define TR_SUST_CON 36 -#define TR_SUST_CHR 37 -#define TR_RIDING 38 -#define TR_EASY_SPELL 39 -#define TR_IM_ACID 40 -#define TR_IM_ELEC 41 -#define TR_IM_FIRE 42 -#define TR_IM_COLD 43 -#define TR_THROW 44 /* Later */ -#define TR_REFLECT 45 /* Reflect 'bolts' */ -#define TR_FREE_ACT 46 /* Free Action */ -#define TR_HOLD_EXP 47 /* Hold EXP */ -#define TR_RES_ACID 48 -#define TR_RES_ELEC 49 -#define TR_RES_FIRE 50 -#define TR_RES_COLD 51 -#define TR_RES_POIS 52 -#define TR_RES_FEAR 53 /* Added for Zangband */ -#define TR_RES_LITE 54 -#define TR_RES_DARK 55 -#define TR_RES_BLIND 56 -#define TR_RES_CONF 57 -#define TR_RES_SOUND 58 -#define TR_RES_SHARDS 59 -#define TR_RES_NETHER 60 -#define TR_RES_NEXUS 61 -#define TR_RES_CHAOS 62 -#define TR_RES_DISEN 63 - -#define TR_SH_FIRE 64 /* Immolation (Fire) */ -#define TR_SH_ELEC 65 /* Electric Sheath */ -#define TR_SLAY_HUMAN 66 /* Slay human */ -#define TR_SH_COLD 67 /* cold aura */ -#define TR_NO_TELE 68 /* Anti-teleportation */ -#define TR_NO_MAGIC 69 /* Anti-magic */ -#define TR_DEC_MANA 70 /* ??? */ -#define TR_TY_CURSE 71 /* The Ancient Curse */ -#define TR_WARNING 72 /* Warning */ -#define TR_HIDE_TYPE 73 /* Hide "pval" description */ -#define TR_SHOW_MODS 74 /* Always show Tohit/Todam */ -#define TR_SLAY_GOOD 75 -#define TR_LEVITATION 76 /* Feather Falling */ -#define TR_LITE_1 77 /* Light Radius 1*/ -#define TR_SEE_INVIS 78 /* See Invisible */ -#define TR_TELEPATHY 79 /* Telepathy */ -#define TR_SLOW_DIGEST 80 /* Item slows down digestion */ -#define TR_REGEN 81 /* Item induces regeneration */ -#define TR_XTRA_MIGHT 82 /* Bows get extra multiplier */ -#define TR_XTRA_SHOTS 83 /* Bows get extra shots */ -#define TR_IGNORE_ACID 84 /* Item ignores Acid Damage */ -#define TR_IGNORE_ELEC 85 /* Item ignores Elec Damage */ -#define TR_IGNORE_FIRE 86 /* Item ignores Fire Damage */ -#define TR_IGNORE_COLD 87 /* Item ignores Cold Damage */ -#define TR_ACTIVATE 88 /* Item can be activated */ -#define TR_DRAIN_EXP 89 /* Item drains Experience */ -#define TR_TELEPORT 90 /* Item teleports player */ -#define TR_AGGRAVATE 91 /* Item aggravates monsters */ -#define TR_BLESSED 92 /* Item is Blessed */ -#define TR_ES_ATTACK 93 /* Fake flag for Smith */ -#define TR_ES_AC 94 /* Fake flag for Smith */ -#define TR_KILL_GOOD 95 - -#define TR_KILL_ANIMAL 96 -#define TR_KILL_EVIL 97 -#define TR_KILL_UNDEAD 98 -#define TR_KILL_DEMON 99 -#define TR_KILL_ORC 100 -#define TR_KILL_TROLL 101 -#define TR_KILL_GIANT 102 -#define TR_KILL_HUMAN 103 -#define TR_ESP_ANIMAL 104 -#define TR_ESP_UNDEAD 105 -#define TR_ESP_DEMON 106 -#define TR_ESP_ORC 107 -#define TR_ESP_TROLL 108 -#define TR_ESP_GIANT 109 -#define TR_ESP_DRAGON 110 -#define TR_ESP_HUMAN 111 -#define TR_ESP_EVIL 112 -#define TR_ESP_GOOD 113 -#define TR_ESP_NONLIVING 114 -#define TR_ESP_UNIQUE 115 -#define TR_FULL_NAME 116 -#define TR_FIXED_FLAVOR 117 -#define TR_ADD_L_CURSE 118 -#define TR_ADD_H_CURSE 119 -#define TR_DRAIN_HP 120 -#define TR_DRAIN_MANA 121 -#define TR_LITE_2 122 -#define TR_LITE_3 123 -#define TR_LITE_M1 124 /* Permanent decrease Light Area (-1) */ -#define TR_LITE_M2 125 /* Permanent decrease Light Area (-1) */ -#define TR_LITE_M3 126 /* Permanent decrease Light Area (-1) */ -#define TR_LITE_FUEL 127 /* Lights need Fuels */ - -#define TR_CALL_ANIMAL 128 -#define TR_CALL_DEMON 129 -#define TR_CALL_DRAGON 130 -#define TR_CALL_UNDEAD 131 -#define TR_COWARDICE 132 -#define TR_LOW_MELEE 133 -#define TR_LOW_AC 134 -#define TR_LOW_MAGIC 135 -#define TR_FAST_DIGEST 136 -#define TR_SLOW_REGEN 137 - -#define TR_FLAG_MAX 138 -#define TR_FLAG_SIZE 5 - - -#define TRG_INSTA_ART 0x00000001L /* Item must be an artifact */ -#define TRG_QUESTITEM 0x00000002L /* quest level item -KMW- */ -#define TRG_XTRA_POWER 0x00000004L /* Extra power */ -#define TRG_ONE_SUSTAIN 0x00000008L /* One sustain */ -#define TRG_XTRA_RES_OR_POWER 0x00000010L /* Extra resistance or power */ -#define TRG_XTRA_H_RES 0x00000020L /* Extra high resistance */ -#define TRG_XTRA_E_RES 0x00000040L /* Extra element resistance */ -#define TRG_XTRA_L_RES 0x00000080L /* Extra lordly resistance */ -#define TRG_XTRA_D_RES 0x00000100L /* Extra dragon resistance */ -#define TRG_XTRA_RES 0x00000200L /* Extra resistance */ -#define TRG_CURSED 0x00000400L /* Item is Cursed */ -#define TRG_HEAVY_CURSE 0x00000800L /* Item is Heavily Cursed */ -#define TRG_PERMA_CURSE 0x00001000L /* Item is Perma Cursed */ -#define TRG_RANDOM_CURSE0 0x00002000L /* Item is Random Cursed */ -#define TRG_RANDOM_CURSE1 0x00004000L /* Item is Random Cursed */ -#define TRG_RANDOM_CURSE2 0x00008000L /* Item is Random Cursed */ -#define TRG_XTRA_DICE 0x00010000L /* Extra dice */ -#define TRG_POWERFUL 0x00020000L /* Item has good value even if Cursed */ - - -#define MAX_CURSE 18 - -#define TRC_CURSED 0x00000001L -#define TRC_HEAVY_CURSE 0x00000002L -#define TRC_PERMA_CURSE 0x00000004L -#define TRC_XXX1 0x00000008L -#define TRC_TY_CURSE 0x00000010L -#define TRC_AGGRAVATE 0x00000020L -#define TRC_DRAIN_EXP 0x00000040L -#define TRC_SLOW_REGEN 0x00000080L -#define TRC_ADD_L_CURSE 0x00000100L -#define TRC_ADD_H_CURSE 0x00000200L -#define TRC_CALL_ANIMAL 0x00000400L -#define TRC_CALL_DEMON 0x00000800L -#define TRC_CALL_DRAGON 0x00001000L -#define TRC_COWARDICE 0x00002000L -#define TRC_TELEPORT 0x00004000L -#define TRC_LOW_MELEE 0x00008000L -#define TRC_LOW_AC 0x00010000L -#define TRC_LOW_MAGIC 0x00020000L -#define TRC_FAST_DIGEST 0x00040000L -#define TRC_DRAIN_HP 0x00080000L -#define TRC_DRAIN_MANA 0x00100000L -#define TRC_CALL_UNDEAD 0x00200000L - -#define TRC_TELEPORT_SELF 0x00000001L -#define TRC_CHAINSWORD 0x00000002L - -#define TRC_SPECIAL_MASK \ - (TRC_TY_CURSE | TRC_AGGRAVATE) - -#define TRC_HEAVY_MASK \ - (TRC_TY_CURSE | TRC_AGGRAVATE | TRC_DRAIN_EXP | TRC_ADD_H_CURSE | \ - TRC_CALL_DEMON | TRC_CALL_DRAGON | TRC_CALL_UNDEAD | TRC_TELEPORT) - -#define TRC_P_FLAG_MASK \ - (TRC_TELEPORT_SELF | TRC_CHAINSWORD | \ - TRC_TY_CURSE | TRC_DRAIN_EXP | TRC_ADD_L_CURSE | TRC_ADD_H_CURSE | \ - TRC_CALL_ANIMAL | TRC_CALL_DEMON | TRC_CALL_DRAGON | TRC_COWARDICE | \ - TRC_TELEPORT | TRC_DRAIN_HP | TRC_DRAIN_MANA | TRC_CALL_UNDEAD) - - - -/* - * Bit flags for apply_magic() (etc) - */ -#define AM_NO_FIXED_ART 0x00000001 /* Don't allow roll for fixed artifacts */ -#define AM_GOOD 0x00000002 /* Generate good items */ -#define AM_GREAT 0x00000004 /* Generate great items */ -#define AM_SPECIAL 0x00000008 /* Generate artifacts (for debug mode only) */ -#define AM_CURSED 0x00000010 /* Generate cursed/worthless items */ - - -/*** Monster blow constants ***/ - - -/*! - * @note モンスターの打撃方法 / New monster blow methods - * 打撃の種別に応じて傷と朦朧が発生するかがコメントの通りに決まる - */ -#define RBM_HIT 1 /*!< モンスターの攻撃種別:殴る(傷/朦朧が半々) */ -#define RBM_TOUCH 2 /*!< モンスターの攻撃種別:触る */ -#define RBM_PUNCH 3 /*!< モンスターの攻撃種別:パンチする(朦朧) */ -#define RBM_KICK 4 /*!< モンスターの攻撃種別:蹴る(朦朧) */ -#define RBM_CLAW 5 /*!< モンスターの攻撃種別:ひっかく(傷) */ -#define RBM_BITE 6 /*!< モンスターの攻撃種別:噛む(傷) */ -#define RBM_STING 7 /*!< モンスターの攻撃種別:刺す */ -#define RBM_SLASH 8 /*!< モンスターの攻撃種別:斬る(傷) */ -#define RBM_BUTT 9 /*!< モンスターの攻撃種別:角で突く(朦朧) */ -#define RBM_CRUSH 10 /*!< モンスターの攻撃種別:体当たりする(朦朧) */ -#define RBM_ENGULF 11 /*!< モンスターの攻撃種別:飲み込む */ -#define RBM_CHARGE 12 /*!< モンスターの攻撃種別:請求書を寄越す */ -#define RBM_CRAWL 13 /*!< モンスターの攻撃種別:体の上を這い回る */ -#define RBM_DROOL 14 /*!< モンスターの攻撃種別:よだれをたらす */ -#define RBM_SPIT 15 /*!< モンスターの攻撃種別:つばを吐く */ -#define RBM_EXPLODE 16 /*!< モンスターの攻撃種別:爆発する */ -#define RBM_GAZE 17 /*!< モンスターの攻撃種別:にらむ */ -#define RBM_WAIL 18 /*!< モンスターの攻撃種別:泣き叫ぶ */ -#define RBM_SPORE 19 /*!< モンスターの攻撃種別:胞子を飛ばす */ -#define RBM_XXX4 20 /*!< モンスターの攻撃種別:未定義 */ -#define RBM_BEG 21 /*!< モンスターの攻撃種別:金をせがむ */ -#define RBM_INSULT 22 /*!< モンスターの攻撃種別:侮辱する */ -#define RBM_MOAN 23 /*!< モンスターの攻撃種別:うめく */ -#define RBM_SHOW 24 /*!< モンスターの攻撃種別:歌う */ -#define RBM_SHOOT 25 /*!< モンスターの攻撃種別:射撃(非打撃) */ - - -/*! - * @note モンスターの攻撃効果 / New monster blow effects - */ -#define RBE_HURT 1 /*!< モンスターの攻撃効果: 攻撃する*/ -#define RBE_POISON 2 /*!< モンスターの攻撃効果: 毒をくらわす*/ -#define RBE_UN_BONUS 3 /*!< モンスターの攻撃効果: 劣化させる*/ -#define RBE_UN_POWER 4 /*!< モンスターの攻撃効果: 充填魔力を吸収する*/ -#define RBE_EAT_GOLD 5 /*!< モンスターの攻撃効果: 金を盗む*/ -#define RBE_EAT_ITEM 6 /*!< モンスターの攻撃効果: アイテムを盗む*/ -#define RBE_EAT_FOOD 7 /*!< モンスターの攻撃効果: あなたの食糧を食べる*/ -#define RBE_EAT_LITE 8 /*!< モンスターの攻撃効果: 明かりを吸収する*/ -#define RBE_ACID 9 /*!< モンスターの攻撃効果: 酸を飛ばす*/ -#define RBE_ELEC 10 /*!< モンスターの攻撃効果: 感電させる*/ -#define RBE_FIRE 11 /*!< モンスターの攻撃効果: 燃やす*/ -#define RBE_COLD 12 /*!< モンスターの攻撃効果: 凍らせる*/ -#define RBE_BLIND 13 /*!< モンスターの攻撃効果: 盲目にする*/ -#define RBE_CONFUSE 14 /*!< モンスターの攻撃効果: 混乱させる*/ -#define RBE_TERRIFY 15 /*!< モンスターの攻撃効果: 恐怖させる*/ -#define RBE_PARALYZE 16 /*!< モンスターの攻撃効果: 麻痺させる*/ -#define RBE_LOSE_STR 17 /*!< モンスターの攻撃効果: 腕力を減少させる*/ -#define RBE_LOSE_INT 18 /*!< モンスターの攻撃効果: 知能を減少させる*/ -#define RBE_LOSE_WIS 19 /*!< モンスターの攻撃効果: 賢さを減少させる*/ -#define RBE_LOSE_DEX 20 /*!< モンスターの攻撃効果: 器用さを減少させる*/ -#define RBE_LOSE_CON 21 /*!< モンスターの攻撃効果: 耐久力を減少させる*/ -#define RBE_LOSE_CHR 22 /*!< モンスターの攻撃効果: 魅力を減少させる*/ -#define RBE_LOSE_ALL 23 /*!< モンスターの攻撃効果: 全ステータスを減少させる*/ -#define RBE_SHATTER 24 /*!< モンスターの攻撃効果: 粉砕する*/ -#define RBE_EXP_10 25 /*!< モンスターの攻撃効果: 経験値を減少(10d6+)させる*/ -#define RBE_EXP_20 26 /*!< モンスターの攻撃効果: 経験値を減少(20d6+)させる*/ -#define RBE_EXP_40 27 /*!< モンスターの攻撃効果: 経験値を減少(40d6+)させる*/ -#define RBE_EXP_80 28 /*!< モンスターの攻撃効果: 経験値を減少(80d6+)させる*/ -#define RBE_DISEASE 29 /*!< モンスターの攻撃効果: 病気にする*/ -#define RBE_TIME 30 /*!< モンスターの攻撃効果: 時間を逆戻りさせる*/ -#define RBE_DR_LIFE 31 /*!< モンスターの攻撃効果: 生命力を吸収する*/ -#define RBE_DR_MANA 32 /*!< モンスターの攻撃効果: 魔力を奪う*/ -#define RBE_SUPERHURT 33 /*!< モンスターの攻撃効果: 強力に攻撃する*/ -#define RBE_INERTIA 34 /*!< モンスターの攻撃効果: 減速させる*/ -#define RBE_STUN 35 /*!< モンスターの攻撃効果: 朦朧とさせる*/ - - -/*** Monster flag values (hard-coded) ***/ - - -/* - * New monster race bit flags - */ -#define RF1_UNIQUE 0x00000001 /*!< モンスター特性: ユニーク / Unique Monster */ -#define RF1_QUESTOR 0x00000002 /*!< モンスター特性: クエストモンスター / Quest Monster */ -#define RF1_MALE 0x00000004 /*!< モンスター特性: 男性 / Male gender */ -#define RF1_FEMALE 0x00000008 /*!< モンスター特性: 女性 / Female gender */ -#define RF1_CHAR_CLEAR 0x00000010 /*!< モンスター特性: シンボルが完全に透明 / Absorbs symbol */ -#define RF1_SHAPECHANGER 0x00000020 /*!< モンスター特性: シンボルアルファベットがランダムになる / TY: shapechanger */ -#define RF1_ATTR_CLEAR 0x00000040 /*!< モンスター特性: シンボルカラーが透明色になる(地形と同じ色になる) / Absorbs color */ -#define RF1_ATTR_MULTI 0x00000080 /*!< モンスター特性: シンボルカラーがランダムに変化する(基本7色) / Changes color */ -#define RF1_FORCE_DEPTH 0x00000100 /*!< モンスター特性: 指定階未満では生成されない / Start at "correct" depth */ -#define RF1_FORCE_MAXHP 0x00000200 /*!< モンスター特性: 通常生成時必ずHPがダイス最大値になる / Start with max hitpoints */ -#define RF1_FORCE_SLEEP 0x00000400 /*!< モンスター特性: 通常生成時必ず寝ている / Start out sleeping */ -#define RF1_FORCE_EXTRA 0x00000800 /*!< モンスター特性: (未使用) / Start out something */ -#define RF1_ATTR_SEMIRAND 0x00001000 /*!< モンスター特性: シンボルカラーがランダムに変化する(15色) / Color is determined semi-randomly */ -#define RF1_FRIENDS 0x00002000 /*!< モンスター特性: 同種の友軍を用意している / Arrive with some friends */ -#define RF1_ESCORT 0x00004000 /*!< モンスター特性: 護衛を用意している/ Arrive with an escort */ -#define RF1_ESCORTS 0x00008000 /*!< モンスター特性: さらに大量の護衛を用意している / Arrive with some escorts */ -#define RF1_NEVER_BLOW 0x00010000 /*!< モンスター特性: 打撃を一切行わない / Never make physical blow */ -#define RF1_NEVER_MOVE 0x00020000 /*!< モンスター特性: 移動を一切行わない / Never make physical move */ -#define RF1_RAND_25 0x00040000 /*!< モンスター特性: ランダムに移動する確率+25%/ Moves randomly (25%) */ -#define RF1_RAND_50 0x00080000 /*!< モンスター特性: ランダムに移動する確率+50%/ Moves randomly (50%) */ -#define RF1_ONLY_GOLD 0x00100000 /*!< モンスター特性: 財宝しか落とさない / Drop only gold */ -#define RF1_ONLY_ITEM 0x00200000 /*!< モンスター特性: アイテムしか落とさない / Drop only items */ -#define RF1_DROP_60 0x00400000 /*!< モンスター特性: 落とすアイテム数60%で+1/ Drop an item/gold (60%) */ -#define RF1_DROP_90 0x00800000 /*!< モンスター特性: 落とすアイテム数90%で+1 / Drop an item/gold (90%) */ -#define RF1_DROP_1D2 0x01000000 /*!< モンスター特性: 落とすアイテム数+1d2 / Drop 1d2 items/gold */ -#define RF1_DROP_2D2 0x02000000 /*!< モンスター特性: 落とすアイテム数+2d2 / Drop 2d2 items/gold */ -#define RF1_DROP_3D2 0x04000000 /*!< モンスター特性: 落とすアイテム数+3d2 / Drop 3d2 items/gold */ -#define RF1_DROP_4D2 0x08000000 /*!< モンスター特性: 落とすアイテム数+4d2 / Drop 4d2 items/gold */ -#define RF1_DROP_GOOD 0x10000000 /*!< モンスター特性: 必ず上質品をドロップする / Drop good items */ -#define RF1_DROP_GREAT 0x20000000 /*!< モンスター特性: 必ず高級品をドロップする / Drop great items */ -#define RF1_XXX2 0x40000000 /*!< モンスター特性: 未使用 / XXX */ -#define RF1_XXX3 0x80000000 /*!< モンスター特性: 未使用 / XXX */ - -/* - * New monster race bit flags - */ -#define RF2_STUPID 0x00000001 /*!< モンスター特性: 愚かな行動を取る / Monster is stupid */ -#define RF2_SMART 0x00000002 /*!< モンスター特性: 賢い行動を取る / Monster is smart */ -#define RF2_CAN_SPEAK 0x00000004 /*!< モンスター特性: 台詞をしゃべる / TY: can speak */ -#define RF2_REFLECTING 0x00000008 /*!< モンスター特性: 矢やボルト魔法を反射する / Reflects bolts */ -#define RF2_INVISIBLE 0x00000010 /*!< モンスター特性: 透明視力がないと見えない / Monster avoids vision */ -#define RF2_COLD_BLOOD 0x00000020 /*!< モンスター特性: 冷血動物である / Monster avoids infra */ -#define RF2_EMPTY_MIND 0x00000040 /*!< モンスター特性: 知性を持たない(テレパシー回避) / Monster avoids telepathy */ -#define RF2_WEIRD_MIND 0x00000080 /*!< モンスター特性: 異質な知性(テレパシーで感知づらい) / Monster avoids telepathy? */ -#define RF2_MULTIPLY 0x00000100 /*!< モンスター特性: 増殖する / Monster reproduces */ -#define RF2_REGENERATE 0x00000200 /*!< モンスター特性: 急激に回復する / Monster regenerates */ -#define RF2_CHAR_MULTI 0x00000400 /*!< モンスター特性: 未使用 / (Not implemented) */ -#define RF2_ATTR_ANY 0x00000800 /*!< モンスター特性: ATTR_MULTIの色数が増える / TY: Attr_any */ -#define RF2_POWERFUL 0x00001000 /*!< モンスター特性: 強力に魔法をあやつる / Monster has strong breath */ -#define RF2_ELDRITCH_HORROR 0x00002000 /*!< モンスター特性: 狂気を呼び起こす / Sanity-blasting horror */ -#define RF2_AURA_FIRE 0x00004000 /*!< モンスター特性: 火炎のオーラを持つ / Burns in melee */ -#define RF2_AURA_ELEC 0x00008000 /*!< モンスター特性: 電撃のオーラを持つ / Shocks in melee */ -#define RF2_OPEN_DOOR 0x00010000 /*!< モンスター特性: ドアを開けることができる / Monster can open doors */ -#define RF2_BASH_DOOR 0x00020000 /*!< モンスター特性: ドアを破壊することができる / Monster can bash doors */ -#define RF2_PASS_WALL 0x00040000 /*!< モンスター特性: 壁を抜けることができる / Monster can pass walls */ -#define RF2_KILL_WALL 0x00080000 /*!< モンスター特性: 壁を破壊して進む / Monster can destroy walls */ -#define RF2_MOVE_BODY 0x00100000 /*!< モンスター特性: 道中の弱いモンスターを押しのけることができる / Monster can move monsters */ -#define RF2_KILL_BODY 0x00200000 /*!< モンスター特性: 道中の弱いモンスターを殺して進む / Monster can kill monsters */ -#define RF2_TAKE_ITEM 0x00400000 /*!< モンスター特性: 道中のアイテムを拾う / Monster can pick up items */ -#define RF2_KILL_ITEM 0x00800000 /*!< モンスター特性: 道中のアイテムを破壊する / Monster can crush items */ -#define RF2_XXX1 0x01000000 /*!< モンスター特性: 未使用 / XXX */ -#define RF2_XXX2 0x02000000 /*!< モンスター特性: 未使用 / XXX */ -#define RF2_XXX3 0x04000000 /*!< モンスター特性: 未使用 / XXX */ -#define RF2_XXX4 0x08000000 /*!< モンスター特性: 未使用 / XXX */ -#define RF2_XXX5 0x10000000 /*!< モンスター特性: 未使用 / XXX */ -#define RF2_XXX6 0x20000000 /*!< モンスター特性: 未使用 / XXX */ -#define RF2_HUMAN 0x40000000 /*!< モンスター特性: 人間 / Human */ -#define RF2_QUANTUM 0x80000000 /*!< モンスター特性: 量子的な振る舞いをする / Monster has quantum behavior */ - -/* - * New monster race bit flags - */ -#define RF3_ORC 0x00000001 /*!< モンスター特性: オーク / Orc */ -#define RF3_TROLL 0x00000002 /*!< モンスター特性: トロル / Troll */ -#define RF3_GIANT 0x00000004 /*!< モンスター特性: 巨人 / Giant */ -#define RF3_DRAGON 0x00000008 /*!< モンスター特性: ドラゴン / Dragon */ -#define RF3_DEMON 0x00000010 /*!< モンスター特性: 悪魔 / Demon */ -#define RF3_UNDEAD 0x00000020 /*!< モンスター特性: アンデッド / Undead */ -#define RF3_EVIL 0x00000040 /*!< モンスター特性: 邪悪 / Evil */ -#define RF3_ANIMAL 0x00000080 /*!< モンスター特性: 動物 / Animal */ -#define RF3_AMBERITE 0x00000100 /*!< モンスター特性: アンバーの血族 / TY: Amberite */ -#define RF3_GOOD 0x00000200 /*!< モンスター特性: 善良 / Good */ -#define RF3_AURA_COLD 0x00000400 /*!< モンスター特性: 冷気オーラ / Freezes in melee */ -#define RF3_NONLIVING 0x00000800 /*!< モンスター特性: 無生物 / TY: Non-Living (?) */ -#define RF3_HURT_LITE 0x00001000 /*!< モンスター特性: 通常の光(GF_WEAK_LITE)でダメージを受ける / Hurt by lite */ -#define RF3_HURT_ROCK 0x00002000 /*!< モンスター特性: 岩石溶解(GF_KILL_WALL)でダメージを受ける / Hurt by rock remover */ -#define RF3_HURT_FIRE 0x00004000 /*!< モンスター特性: 火炎が弱点 / Hurt badly by fire */ -#define RF3_HURT_COLD 0x00008000 /*!< モンスター特性: 冷気が弱点 / Hurt badly by cold */ -#define RF3_ANGEL 0x00010000 /*!< モンスター特性: 天使 / ANGEL */ -#define RF3_XXX17 0x00020000 /*!< モンスター特性: 未使用 / XXX */ -#define RF3_XXX18 0x00040000 /*!< モンスター特性: 未使用 / XXX */ -#define RF3_XXX19 0x00080000 /*!< モンスター特性: 未使用 / XXX */ -#define RF3_XXX20 0x00100000 /*!< モンスター特性: 未使用 / XXX */ -#define RF3_XXX21 0x00200000 /*!< モンスター特性: 未使用 / XXX */ -#define RF3_XXX22 0x00400000 /*!< モンスター特性: 未使用 / XXX */ -#define RF3_XXX23 0x00800000 /*!< モンスター特性: 未使用 / XXX */ -#define RF3_XXX24 0x01000000 /*!< モンスター特性: 未使用 / XXX */ -#define RF3_XXX25 0x02000000 /*!< モンスター特性: 未使用 / XXX */ -#define RF3_XXX26 0x04000000 /*!< モンスター特性: 未使用 / XXX */ -#define RF3_XXX27 0x08000000 /*!< モンスター特性: 未使用 / XXX */ -#define RF3_NO_FEAR 0x10000000 /*!< モンスター特性: 恐怖しない / Cannot be scared */ -#define RF3_NO_STUN 0x20000000 /*!< モンスター特性: 朦朧としない / Cannot be stunned */ -#define RF3_NO_CONF 0x40000000 /*!< モンスター特性: 混乱しない / Cannot be confused and resist confusion */ -#define RF3_NO_SLEEP 0x80000000 /*!< モンスター特性: 眠らない / Cannot be slept */ - -/* - * New monster race bit flags - */ -#define RF4_SHRIEK 0x00000001 /*!< モンスター能力: 叫ぶ / Shriek for help */ -#define RF4_XXX1 0x00000002 /*!< モンスター能力: 未使用 / XXX */ -#define RF4_DISPEL 0x00000004 /*!< モンスター能力: 魔力消去 / Dispel magic */ -#define RF4_ROCKET 0x00000008 /*!< モンスター能力: ロケット / TY: Rocket */ -#define RF4_SHOOT 0x00000010 /*!< モンスター能力: 射撃/ Fire missiles */ -#define RF4_XXX2 0x00000020 /*!< モンスター能力: 未使用 / XXX */ -#define RF4_XXX3 0x00000040 /*!< モンスター能力: 未使用 / XXX */ -#define RF4_XXX4 0x00000080 /*!< モンスター能力: 未使用 / XXX */ -#define RF4_BR_ACID 0x00000100 /*!< モンスター能力: 酸のブレス / Breathe Acid */ -#define RF4_BR_ELEC 0x00000200 /*!< モンスター能力: 電撃のブレス / Breathe Elec */ -#define RF4_BR_FIRE 0x00000400 /*!< モンスター能力: 火炎のブレス / Breathe Fire */ -#define RF4_BR_COLD 0x00000800 /*!< モンスター能力: 冷気のブレス / Breathe Cold */ -#define RF4_BR_POIS 0x00001000 /*!< モンスター能力: 毒のブレス / Breathe Poison */ -#define RF4_BR_NETH 0x00002000 /*!< モンスター能力: 地獄のブレス / Breathe Nether */ -#define RF4_BR_LITE 0x00004000 /*!< モンスター能力: 閃光のブレス / Breathe Lite */ -#define RF4_BR_DARK 0x00008000 /*!< モンスター能力: 暗黒のブレス / Breathe Dark */ -#define RF4_BR_CONF 0x00010000 /*!< モンスター能力: 混乱のブレス / Breathe Confusion */ -#define RF4_BR_SOUN 0x00020000 /*!< モンスター能力: 轟音のブレス / Breathe Sound */ -#define RF4_BR_CHAO 0x00040000 /*!< モンスター能力: カオスのブレス / Breathe Chaos */ -#define RF4_BR_DISE 0x00080000 /*!< モンスター能力: 劣化のブレス / Breathe Disenchant */ -#define RF4_BR_NEXU 0x00100000 /*!< モンスター能力: 因果混乱のブレス / Breathe Nexus */ -#define RF4_BR_TIME 0x00200000 /*!< モンスター能力: 時間逆転のブレス / Breathe Time */ -#define RF4_BR_INER 0x00400000 /*!< モンスター能力: 遅鈍のブレス / Breathe Inertia */ -#define RF4_BR_GRAV 0x00800000 /*!< モンスター能力: 重力のブレス / Breathe Gravity */ -#define RF4_BR_SHAR 0x01000000 /*!< モンスター能力: 破片のブレス / Breathe Shards */ -#define RF4_BR_PLAS 0x02000000 /*!< モンスター能力: プラズマのブレス / Breathe Plasma */ -#define RF4_BR_WALL 0x04000000 /*!< モンスター能力: フォースのブレス / Breathe Force */ -#define RF4_BR_MANA 0x08000000 /*!< モンスター能力: 魔力のブレス / Breathe Mana */ -#define RF4_BA_NUKE 0x10000000 /*!< モンスター能力: 放射能球 / TY: Nuke Ball */ -#define RF4_BR_NUKE 0x20000000 /*!< モンスター能力: 放射性廃棄物のブレス / TY: Toxic Breath */ -#define RF4_BA_CHAO 0x40000000 /*!< モンスター能力: ログルス球 / TY: Logrus Ball */ -#define RF4_BR_DISI 0x80000000 /*!< モンスター能力: 分解のブレス / Breathe Disintegration */ - -/* - * New monster race bit flags - */ -#define RF5_BA_ACID 0x00000001 /*!< モンスター能力: アシッド・ボール / Acid Ball */ -#define RF5_BA_ELEC 0x00000002 /*!< モンスター能力: サンダー・ボール / Elec Ball */ -#define RF5_BA_FIRE 0x00000004 /*!< モンスター能力: ファイア・ボール / Fire Ball */ -#define RF5_BA_COLD 0x00000008 /*!< モンスター能力: アイス・ボール / Cold Ball */ -#define RF5_BA_POIS 0x00000010 /*!< モンスター能力: 悪臭雲 / Poison Ball */ -#define RF5_BA_NETH 0x00000020 /*!< モンスター能力: 地獄球 / Nether Ball */ -#define RF5_BA_WATE 0x00000040 /*!< モンスター能力: ウォーター・ボール / Water Ball */ -#define RF5_BA_MANA 0x00000080 /*!< モンスター能力: 魔力の嵐 / Mana Storm */ -#define RF5_BA_DARK 0x00000100 /*!< モンスター能力: 暗黒の嵐 / Darkness Storm */ -#define RF5_DRAIN_MANA 0x00000200 /*!< モンスター能力: 魔力吸収 / Drain Mana */ -#define RF5_MIND_BLAST 0x00000400 /*!< モンスター能力: 精神攻撃 / Blast Mind */ -#define RF5_BRAIN_SMASH 0x00000800 /*!< モンスター能力: 脳攻撃 / Smash Brain */ -#define RF5_CAUSE_1 0x00001000 /*!< モンスター能力: 軽傷の呪い / Cause Light Wound */ -#define RF5_CAUSE_2 0x00002000 /*!< モンスター能力: 重症の頃い / Cause Serious Wound */ -#define RF5_CAUSE_3 0x00004000 /*!< モンスター能力: 致命傷の呪い / Cause Critical Wound */ -#define RF5_CAUSE_4 0x00008000 /*!< モンスター能力: 秘孔を突く / Cause Mortal Wound */ -#define RF5_BO_ACID 0x00010000 /*!< モンスター能力: アシッド・ボルト / Acid Bolt */ -#define RF5_BO_ELEC 0x00020000 /*!< モンスター能力: サンダー・ボルト / Elec Bolt */ -#define RF5_BO_FIRE 0x00040000 /*!< モンスター能力: ファイア・ボルト / Fire Bolt */ -#define RF5_BO_COLD 0x00080000 /*!< モンスター能力: アイス・ボルト / Cold Bolt */ -#define RF5_BA_LITE 0x00100000 /*!< モンスター能力: スター・バースト / StarBurst */ -#define RF5_BO_NETH 0x00200000 /*!< モンスター能力: 地獄の矢 / Nether Bolt */ -#define RF5_BO_WATE 0x00400000 /*!< モンスター能力: ウォーター・ボルト / Water Bolt */ -#define RF5_BO_MANA 0x00800000 /*!< モンスター能力: 魔力の矢 / Mana Bolt */ -#define RF5_BO_PLAS 0x01000000 /*!< モンスター能力: プラズマ・ボルト / Plasma Bolt */ -#define RF5_BO_ICEE 0x02000000 /*!< モンスター能力: 極寒の矢 / Ice Bolt */ -#define RF5_MISSILE 0x04000000 /*!< モンスター能力: マジック・ミサイルt / Magic Missile */ -#define RF5_SCARE 0x08000000 /*!< モンスター能力: 恐慌 / Frighten Player */ -#define RF5_BLIND 0x10000000 /*!< モンスター能力: 盲目 / Blind Player */ -#define RF5_CONF 0x20000000 /*!< モンスター能力: æ··ä¹± / Confuse Player */ -#define RF5_SLOW 0x40000000 /*!< モンスター能力: 減速 / Slow Player */ -#define RF5_HOLD 0x80000000 /*!< モンスター能力: 麻痺 / Paralyze Player */ - -/* - * New monster race bit flags - */ -#define RF6_HASTE 0x00000001 /* Speed self */ -#define RF6_HAND_DOOM 0x00000002 /* Hand of Doom */ -#define RF6_HEAL 0x00000004 /* Heal self */ -#define RF6_INVULNER 0x00000008 /* INVULNERABILITY! */ -#define RF6_BLINK 0x00000010 /* Teleport Short */ -#define RF6_TPORT 0x00000020 /* Teleport Long */ -#define RF6_WORLD 0x00000040 /* world */ -#define RF6_SPECIAL 0x00000080 /* Special Attack */ -#define RF6_TELE_TO 0x00000100 /* Move player to monster */ -#define RF6_TELE_AWAY 0x00000200 /* Move player far away */ -#define RF6_TELE_LEVEL 0x00000400 /* Move player vertically */ -#define RF6_PSY_SPEAR 0x00000800 /* Psyco-spear */ -#define RF6_DARKNESS 0x00001000 /* Create Darkness */ -#define RF6_TRAPS 0x00002000 /* Create Traps */ -#define RF6_FORGET 0x00004000 /* Cause amnesia */ -#define RF6_RAISE_DEAD 0x00008000 /* Raise Dead */ -#define RF6_S_KIN 0x00010000 /* Summon "kin" */ -#define RF6_S_CYBER 0x00020000 /* Summon Cyberdemons! */ -#define RF6_S_MONSTER 0x00040000 /* Summon Monster */ -#define RF6_S_MONSTERS 0x00080000 /* Summon Monsters */ -#define RF6_S_ANT 0x00100000 /* Summon Ants */ -#define RF6_S_SPIDER 0x00200000 /* Summon Spiders */ -#define RF6_S_HOUND 0x00400000 /* Summon Hounds */ -#define RF6_S_HYDRA 0x00800000 /* Summon Hydras */ -#define RF6_S_ANGEL 0x01000000 /* Summon Angel */ -#define RF6_S_DEMON 0x02000000 /* Summon Demon */ -#define RF6_S_UNDEAD 0x04000000 /* Summon Undead */ -#define RF6_S_DRAGON 0x08000000 /* Summon Dragon */ -#define RF6_S_HI_UNDEAD 0x10000000 /* Summon Greater Undead */ -#define RF6_S_HI_DRAGON 0x20000000 /* Summon Ancient Dragon */ -#define RF6_S_AMBERITES 0x40000000 /* Summon Amberites */ -#define RF6_S_UNIQUE 0x80000000 /* Summon Unique Monster */ - -/* - * New monster race bit flags - */ -#define RF7_AQUATIC 0x00000001 /* Aquatic monster */ -#define RF7_CAN_SWIM 0x00000002 /* Monster can swim */ -#define RF7_CAN_FLY 0x00000004 /* Monster can fly */ -#define RF7_FRIENDLY 0x00000008 /* Monster is friendly */ -#define RF7_NAZGUL 0x00000010 /* Is a "Nazgul" unique */ -#define RF7_UNIQUE2 0x00000020 /* Fake unique */ -#define RF7_RIDING 0x00000040 /* Good for riding */ -#define RF7_KAGE 0x00000080 /* Is kage */ -#define RF7_HAS_LITE_1 0x00000100 /* Monster carries light */ -#define RF7_SELF_LITE_1 0x00000200 /* Monster lights itself */ -#define RF7_HAS_LITE_2 0x00000400 /* Monster carries light */ -#define RF7_SELF_LITE_2 0x00000800 /* Monster lights itself */ -#define RF7_GUARDIAN 0x00001000 /* Guardian of a dungeon */ -#define RF7_CHAMELEON 0x00002000 /* Chameleon can change */ -#define RF7_XXXX4XXX 0x00004000 /* Now Empty */ -#define RF7_TANUKI 0x00008000 /* Tanuki disguise */ -#define RF7_HAS_DARK_1 0x00010000 /* Monster carries darkness */ -#define RF7_SELF_DARK_1 0x00020000 /* Monster darkens itself */ -#define RF7_HAS_DARK_2 0x00040000 /* Monster carries darkness */ -#define RF7_SELF_DARK_2 0x00080000 /* Monster darkens itself */ - -/* - * Monster race flags - */ -#define RF8_WILD_ONLY 0x00000001 -#define RF8_WILD_TOWN 0x00000002 -#define RF8_XXX8X02 0x00000004 -#define RF8_WILD_SHORE 0x00000008 -#define RF8_WILD_OCEAN 0x00000010 -#define RF8_WILD_WASTE 0x00000020 -#define RF8_WILD_WOOD 0x00000040 -#define RF8_WILD_VOLCANO 0x00000080 -#define RF8_XXX8X08 0x00000100 -#define RF8_WILD_MOUNTAIN 0x00000200 -#define RF8_WILD_GRASS 0x00000400 -#define RF8_WILD_ALL 0x80000000 - -/* - * Monster drop info - */ -#define RF9_DROP_CORPSE 0x00000001 -#define RF9_DROP_SKELETON 0x00000002 -#define RF9_EAT_BLIND 0x00000004 -#define RF9_EAT_CONF 0x00000008 -#define RF9_EAT_MANA 0x00000010 -#define RF9_EAT_NEXUS 0x00000020 -#define RF9_EAT_SLEEP 0x00000040 -#define RF9_EAT_BERSERKER 0x00000080 -#define RF9_EAT_ACIDIC 0x00000100 -#define RF9_EAT_SPEED 0x00000200 -#define RF9_EAT_CURE 0x00000400 -#define RF9_EAT_FIRE_RES 0x00000800 -#define RF9_EAT_COLD_RES 0x00001000 -#define RF9_EAT_ACID_RES 0x00002000 -#define RF9_EAT_ELEC_RES 0x00004000 -#define RF9_EAT_POIS_RES 0x00008000 -#define RF9_EAT_INSANITY 0x00010000 -#define RF9_EAT_DRAIN_EXP 0x00020000 -#define RF9_EAT_POISONOUS 0x00040000 -#define RF9_EAT_GIVE_STR 0x00080000 -#define RF9_EAT_GIVE_INT 0x00100000 -#define RF9_EAT_GIVE_WIS 0x00200000 -#define RF9_EAT_GIVE_DEX 0x00400000 -#define RF9_EAT_GIVE_CON 0x00800000 -#define RF9_EAT_GIVE_CHR 0x01000000 -#define RF9_EAT_LOSE_STR 0x02000000 -#define RF9_EAT_LOSE_INT 0x04000000 -#define RF9_EAT_LOSE_WIS 0x08000000 -#define RF9_EAT_LOSE_DEX 0x10000000 -#define RF9_EAT_LOSE_CON 0x20000000 -#define RF9_EAT_LOSE_CHR 0x40000000 -#define RF9_EAT_DRAIN_MANA 0x80000000 - -/* - * Monster bit flags of racial resistances - * Note: Resist confusion was merged to RFR_NO_CONF - */ -#define RFR_IM_ACID 0x00000001 /* Immunity acid */ -#define RFR_IM_ELEC 0x00000002 /* Immunity elec */ -#define RFR_IM_FIRE 0x00000004 /* Immunity fire */ -#define RFR_IM_COLD 0x00000008 /* Immunity cold */ -#define RFR_IM_POIS 0x00000010 /* Immunity poison */ -#define RFR_RES_LITE 0x00000020 /* Resist lite */ -#define RFR_RES_DARK 0x00000040 /* Resist dark */ -#define RFR_RES_NETH 0x00000080 /* Resist nether */ -#define RFR_RES_WATE 0x00000100 /* Resist water */ -#define RFR_RES_PLAS 0x00000200 /* Resist plasma */ -#define RFR_RES_SHAR 0x00000400 /* Resist shards */ -#define RFR_RES_SOUN 0x00000800 /* Resist sound */ -#define RFR_RES_CHAO 0x00001000 /* Resist chaos */ -#define RFR_RES_NEXU 0x00002000 /* Resist nexus */ -#define RFR_RES_DISE 0x00004000 /* Resist disenchantment */ -#define RFR_RES_WALL 0x00008000 /* Resist force */ -#define RFR_RES_INER 0x00010000 /* Resist inertia */ -#define RFR_RES_TIME 0x00020000 /* Resist time */ -#define RFR_RES_GRAV 0x00040000 /* Resist gravity */ -#define RFR_RES_ALL 0x00080000 /* Resist all */ -#define RFR_RES_TELE 0x00100000 /* Resist teleportation */ -#define RFR_XXX21 0x00200000 -#define RFR_XXX22 0x00400000 -#define RFR_XXX23 0x00800000 -#define RFR_XXX24 0x01000000 -#define RFR_XXX25 0x02000000 -#define RFR_XXX26 0x04000000 -#define RFR_XXX27 0x08000000 -#define RFR_XXX28 0x10000000 -#define RFR_XXX29 0x20000000 -#define RFR_XXX30 0x40000000 -#define RFR_XXX31 0x80000000 - - - /* - * Hack -- "torch" masks - */ -#define RF7_LITE_MASK \ - (RF7_HAS_LITE_1 | RF7_SELF_LITE_1 | RF7_HAS_LITE_2 | RF7_SELF_LITE_2) - -#define RF7_DARK_MASK \ - (RF7_HAS_DARK_1 | RF7_SELF_DARK_1 | RF7_HAS_DARK_2 | RF7_SELF_DARK_2) - -#define RF7_HAS_LD_MASK \ - (RF7_HAS_LITE_1 | RF7_HAS_LITE_2 | RF7_HAS_DARK_1 | RF7_HAS_DARK_2) - -#define RF7_SELF_LD_MASK \ - (RF7_SELF_LITE_1 | RF7_SELF_LITE_2 | RF7_SELF_DARK_1 | RF7_SELF_DARK_2) - - /* - * Hack -- effective elemental and poison immunity mask - */ -#define RFR_EFF_IM_ACID_MASK (RFR_IM_ACID | RFR_RES_ALL) -#define RFR_EFF_IM_ELEC_MASK (RFR_IM_ELEC | RFR_RES_ALL) -#define RFR_EFF_IM_FIRE_MASK (RFR_IM_FIRE | RFR_RES_ALL) -#define RFR_EFF_IM_COLD_MASK (RFR_IM_COLD | RFR_RES_ALL) -#define RFR_EFF_IM_POIS_MASK (RFR_IM_POIS | RFR_RES_ALL) -#define RFR_EFF_RES_SHAR_MASK (RFR_RES_SHAR | RFR_RES_ALL) -#define RFR_EFF_RES_CHAO_MASK (RFR_RES_CHAO | RFR_RES_ALL) -#define RFR_EFF_RES_NEXU_MASK (RFR_RES_NEXU | RFR_RES_ALL) - - -#define MR1_SINKA 0x01 - - -#define is_friendly(A) \ - (bool)(((A)->smart & SM_FRIENDLY) ? TRUE : FALSE) - -#define is_friendly_idx(IDX) \ - (bool)((IDX) > 0 && is_friendly(¤t_floor_ptr->m_list[(IDX)])) - -#define is_pet(A) \ - (bool)(((A)->smart & SM_PET) ? TRUE : FALSE) - -#define is_hostile(A) \ - (bool)((is_friendly(A) || is_pet(A)) ? FALSE : TRUE) - -/* Hack -- Determine monster race appearance index is same as race index */ -#define is_original_ap(A) \ - (bool)(((A)->ap_r_idx == (A)->r_idx) ? TRUE : FALSE) - -#define is_original_ap_and_seen(A) \ - (bool)((A)->ml && !p_ptr->image && ((A)->ap_r_idx == (A)->r_idx)) - -/* - * Is the monster seen by the player? - */ -#define is_seen(A) \ - ((bool)((A)->ml && (!ignore_unview || p_ptr->inside_battle || \ - (player_can_see_bold((A)->fy, (A)->fx) && projectable(p_ptr->y, p_ptr->x, (A)->fy, (A)->fx))))) - - -/*** Option Definitions ***/ - - -#define OPT_PAGE_INPUT 1 -#define OPT_PAGE_MAPSCREEN 2 -#define OPT_PAGE_TEXT 3 -#define OPT_PAGE_GAMEPLAY 4 -#define OPT_PAGE_DISTURBANCE 5 -#define OPT_PAGE_BIRTH 6 -#define OPT_PAGE_AUTODESTROY 7 -#define OPT_PAGE_PLAYRECORD 10 - -#define OPT_PAGE_JAPANESE_ONLY 99 - - -/*** Macro Definitions ***/ - - -/* - * Hack -- The main "screen" - */ -#define term_screen (angband_term[0]) - - -/* - * Determine if a given inventory item is "aware" - */ -#define object_is_aware(T) \ - (k_info[(T)->k_idx].aware) - -/* - * Determine if a given inventory item is "tried" - */ -#define object_is_tried(T) \ - (k_info[(T)->k_idx].tried) - - -/* - * Determine if a given inventory item is "known" - * Test One -- Check for special "known" tag - * Test Two -- Check for "Easy Know" + "Aware" - */ -#define object_is_known(T) \ - (((T)->ident & (IDENT_KNOWN)) || \ - (k_info[(T)->k_idx].easy_know && k_info[(T)->k_idx].aware)) - - -/* - * Return the "attr" for a given item. - * Use "flavor" if available. - * Default to user definitions. - */ -#define object_attr(T) \ - ((k_info[(T)->k_idx].flavor) ? \ - (k_info[k_info[(T)->k_idx].flavor].x_attr) : \ - ((!(T)->k_idx || ((T)->tval != TV_CORPSE) || ((T)->sval != SV_CORPSE) || \ - (k_info[(T)->k_idx].x_attr != TERM_DARK)) ? \ - (k_info[(T)->k_idx].x_attr) : (r_info[(T)->pval].x_attr))) - -/* - * Return the "char" for a given item. - * Use "flavor" if available. - * Default to user definitions. - */ -#define object_char(T) \ - ((k_info[(T)->k_idx].flavor) ? \ - (k_info[k_info[(T)->k_idx].flavor].x_char) : \ - (k_info[(T)->k_idx].x_char)) - - -/* - * Artifacts use the "name1" field - */ -#define object_is_fixed_artifact(T) \ - ((T)->name1 ? TRUE : FALSE) - -/* - * Ego-Items use the "name2" field - */ -#define object_is_ego(T) \ - ((T)->name2 ? TRUE : FALSE) - - -/* - * Broken items. - */ -#define object_is_broken(T) \ - ((T)->ident & (IDENT_BROKEN)) - -/* - * Cursed items. - */ -#define object_is_cursed(T) \ - ((T)->curse_flags) - - -/* - * Convert an "attr"/"char" pair into a "pict" (P) - */ -#define PICT(A,C) \ - ((((u16b)(A)) << 8) | ((byte)(C))) - -/* - * Convert a "pict" (P) into an "attr" (A) - */ -#define PICT_A(P) \ - ((byte)((P) >> 8)) - -/* - * Convert a "pict" (P) into an "char" (C) - */ -#define PICT_C(P) \ - ((char)((byte)(P))) - - -/* - * Convert a "location" (Y,X) into a "grid" (G) - */ -#define GRID(Y,X) \ - (256 * (Y) + (X)) - -/* - * Convert a "grid" (G) into a "location" (Y) - */ -#define GRID_Y(G) \ - ((int)((G) / 256U)) - -/* - * Convert a "grid" (G) into a "location" (X) - */ -#define GRID_X(G) \ - ((int)((G) % 256U)) - - -/* - * Determines if a map location is fully inside the outer walls - */ -#define in_bounds(Y,X) \ - (((Y) > 0) && ((X) > 0) && ((Y) < current_floor_ptr->height-1) && ((X) < current_floor_ptr->width-1)) - -/* - * Determines if a map location is on or inside the outer walls - */ -#define in_bounds2(Y,X) \ - (((Y) >= 0) && ((X) >= 0) && ((Y) < current_floor_ptr->height) && ((X) < current_floor_ptr->width)) - -/* - * Determines if a map location is on or inside the outer walls - * (unsigned version) - */ -#define in_bounds2u(Y,X) \ - (((Y) < current_floor_ptr->height) && ((X) < current_floor_ptr->width)) - -/* - * Determines if a map location is currently "on screen" -RAK- - * Note that "panel_contains(Y,X)" always implies "in_bounds2(Y,X)". - */ -#define panel_contains(Y,X) \ - (((Y) >= panel_row_min) && ((Y) <= panel_row_max) && \ - ((X) >= panel_col_min) && ((X) <= panel_col_max)) - - -/* - * Determine if player is on this grid - */ -#define player_bold(Y,X) \ - (((Y) == p_ptr->y) && ((X) == p_ptr->x)) - - -/* - * Grid based version of "player_bold()" - */ -#define player_grid(C) \ - ((C) == ¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x]) - - -#define cave_have_flag_bold(Y,X,INDEX) \ - (have_flag(f_info[current_floor_ptr->grid_array[(Y)][(X)].feat].flags, (INDEX))) - - -#define cave_have_flag_grid(C,INDEX) \ - (have_flag(f_info[(C)->feat].flags, (INDEX))) - - -/* - * Determine if a "feature" supports "los" - */ -#define feat_supports_los(F) \ - (have_flag(f_info[(F)].flags, FF_LOS)) - - -/* - * Determine if a "legal" grid supports "los" - */ -#define cave_los_bold(Y,X) \ - (feat_supports_los(current_floor_ptr->grid_array[(Y)][(X)].feat)) - -#define cave_los_grid(C) \ - (feat_supports_los((C)->feat)) - - -/* - * Determine if a "legal" grid is a "clean" floor grid - * Determine if terrain-change spells are allowed in a grid. - * - * Line 1 -- forbid non-floors - * Line 2 -- forbid object terrains - * Line 3 -- forbid normal objects - */ -#define cave_clean_bold(Y,X) \ - (cave_have_flag_bold((Y), (X), FF_FLOOR) && \ - !(current_floor_ptr->grid_array[Y][X].info & CAVE_OBJECT) && \ - (current_floor_ptr->grid_array[Y][X].o_idx == 0)) - - -/* - * Determine if an object can be dropped on a "legal" grid - * - * Line 1 -- forbid non-drops - * Line 2 -- forbid object terrains - */ -#define cave_drop_bold(Y,X) \ - (cave_have_flag_bold((Y), (X), FF_DROP) && \ - !(current_floor_ptr->grid_array[Y][X].info & CAVE_OBJECT)) - - -/* - * Determine if a "legal" grid is an "empty" floor grid - * Determine if monsters are allowed to move into a grid - * - * Line 1 -- forbid non-placement grids - * Line 2 -- forbid normal monsters - * Line 3 -- forbid the player - */ -#define cave_empty_bold(Y,X) \ - (cave_have_flag_bold((Y), (X), FF_PLACE) && \ - !(current_floor_ptr->grid_array[Y][X].m_idx) && \ - !player_bold(Y,X)) - - -/* - * Determine if a "legal" grid is an "empty" floor grid - * Determine if monster generation is allowed in a grid - * - * Line 1 -- forbid non-empty grids - * Line 2 -- forbid trees while dungeon generation - */ -#define cave_empty_bold2(Y,X) \ - (cave_empty_bold(Y,X) && \ - (character_dungeon || !cave_have_flag_bold((Y), (X), FF_TREE))) - - -/* - * Determine if a "legal" grid is an "naked" floor grid - * - * Line 1 -- forbid non-clean gird - * Line 2 -- forbid monsters - * Line 3 -- forbid the player - */ -#define cave_naked_bold(Y,X) \ - (cave_clean_bold(Y,X) && \ - !(current_floor_ptr->grid_array[Y][X].m_idx) && \ - !player_bold(Y,X)) - - -/* - * Determine if a "legal" grid is "permanent" - * - * Line 1 -- permanent flag - */ -#define cave_perma_bold(Y,X) \ - (cave_have_flag_bold((Y), (X), FF_PERMANENT)) - - -/* - * Grid based version of "cave_empty_bold()" - */ -#define cave_empty_grid(C) \ - (cave_have_flag_grid((C), FF_PLACE) && \ - !((C)->m_idx) && \ - !player_grid(C)) - - -/* - * Grid based version of "cave_perma_bold()" - */ -#define cave_perma_grid(C) \ - (cave_have_flag_grid((C), FF_PERMANENT)) - - -#define pattern_tile(Y,X) \ - (cave_have_flag_bold((Y), (X), FF_PATTERN)) - -/* - * Does the grid stop disintegration? - */ -#define cave_stop_disintegration(Y,X) \ - (!cave_have_flag_bold((Y), (X), FF_PROJECT) && \ - (!cave_have_flag_bold((Y), (X), FF_HURT_DISI) || \ - cave_have_flag_bold((Y), (X), FF_PERMANENT))) - - -/* - * Determine if a "legal" grid is within "los" of the player - * - * Note the use of comparison to zero to force a "boolean" result - */ -#define player_has_los_grid(C) \ - (((C)->info & (CAVE_VIEW)) != 0) - -/* - * Determine if a "legal" grid is within "los" of the player - * - * Note the use of comparison to zero to force a "boolean" result - */ -#define player_has_los_bold(Y,X) \ - (((current_floor_ptr->grid_array[Y][X].info & (CAVE_VIEW)) != 0) || p_ptr->inside_battle) - - -/* - * Determine if a "feature" is "permanent wall" - */ -#define permanent_wall(F) \ - (have_flag((F)->flags, FF_WALL) && \ - have_flag((F)->flags, FF_PERMANENT)) - -/* - * Get feature mimic from f_info[] (applying "mimic" field) - */ -#define get_feat_mimic(C) \ - (f_info[(C)->mimic ? (C)->mimic : (C)->feat].mimic) - -/* - * Hack -- Prepare to use the "Secure" routines - */ -#if defined(SET_UID) && defined(SECURE) -extern int PlayerUID; -# define getuid() PlayerUID -# define geteuid() PlayerUID -#endif - - - -/*** Color constants ***/ - - -/* - * Angband "attributes" (with symbols, and base (R,G,B) codes) - * - * The "(R,G,B)" codes are given in "fourths" of the "maximal" value, - * and should "gamma corrected" on most (non-Macintosh) machines. - */ -#define TERM_DARK 0 /*!< 'd' - 黒 0,0,0 */ -#define TERM_WHITE 1 /*!< 'w' - 白 4,4,4 */ -#define TERM_SLATE 2 /*!< 's' - 灰 2,2,2 */ -#define TERM_ORANGE 3 /*!< 'o' - 橙 4,2,0 */ -#define TERM_RED 4 /*!< 'r' - 赤 3,0,0 */ -#define TERM_GREEN 5 /*!< 'g' - 緑 0,2,1 */ -#define TERM_BLUE 6 /*!< 'b' - 青 0,0,4 */ -#define TERM_UMBER 7 /*!< 'u' - 琥珀 2,1,0 */ -#define TERM_L_DARK 8 /*!< 'D' - 暗い灰 1,1,1 */ -#define TERM_L_WHITE 9 /*!< 'W' - 明るい灰 3,3,3 */ -#define TERM_VIOLET 10 /*!< 'v' - ç´« 4,0,4 */ -#define TERM_YELLOW 11 /*!< 'y' - 黄 4,4,0 */ -#define TERM_L_RED 12 /*!< 'R' - 明るい赤 4,0,0 */ -#define TERM_L_GREEN 13 /*!< 'G' - 明るい緑 0,4,0 */ -#define TERM_L_BLUE 14 /*!< 'B' - 明るい青 0,4,4 */ -#define TERM_L_UMBER 15 /*!< 'U' - 明るい琥珀 3,2,1 */ - - -/* - * Not using graphical tiles for this feature? - */ -#define is_ascii_graphics(A) (!((A) & 0x80)) - -/*** Music constants ***/ - -#define MUSIC_BASIC_DEFAULT 0 -#define MUSIC_BASIC_GAMEOVER 1 -#define MUSIC_BASIC_EXIT 2 -#define MUSIC_BASIC_TOWN 3 -#define MUSIC_BASIC_FIELD1 4 -#define MUSIC_BASIC_FIELD2 5 -#define MUSIC_BASIC_FIELD3 6 -#define MUSIC_BASIC_DUN_LOW 7 -#define MUSIC_BASIC_DUN_MED 8 -#define MUSIC_BASIC_DUN_HIGH 9 -#define MUSIC_BASIC_DUN_FEEL1 10 -#define MUSIC_BASIC_DUN_FEEL2 11 -#define MUSIC_BASIC_WINNER 12 -#define MUSIC_BASIC_BUILD 13 -#define MUSIC_BASIC_WILD 14 -#define MUSIC_BASIC_QUEST 15 -#define MUSIC_BASIC_ARENA 16 -#define MUSIC_BASIC_BATTLE 17 -#define MUSIC_BASIC_QUEST_CLEAR 18 -#define MUSIC_BASIC_FINAL_QUEST_CLEAR 19 -#define MUSIC_BASIC_AMBUSH 20 -#define MUSIC_BASIC_MAX 21 /*!< BGM定義の最大数 */ - -/*** Sound constants ***/ - -/* - * Mega-Hack -- some primitive sound support (see "main-win.c") - * - * Some "sound" constants for "Term_xtra(TERM_XTRA_SOUND, val)" - */ -#define SOUND_HIT 1 -#define SOUND_MISS 2 -#define SOUND_FLEE 3 -#define SOUND_DROP 4 -#define SOUND_KILL 5 -#define SOUND_LEVEL 6 -#define SOUND_DEATH 7 -#define SOUND_STUDY 8 -#define SOUND_TELEPORT 9 -#define SOUND_SHOOT 10 -#define SOUND_QUAFF 11 -#define SOUND_ZAP 12 -#define SOUND_WALK 13 -#define SOUND_TPOTHER 14 -#define SOUND_HITWALL 15 -#define SOUND_EAT 16 -#define SOUND_STORE1 17 -#define SOUND_STORE2 18 -#define SOUND_STORE3 19 -#define SOUND_STORE4 20 -#define SOUND_DIG 21 -#define SOUND_OPENDOOR 22 -#define SOUND_SHUTDOOR 23 -#define SOUND_TPLEVEL 24 -#define SOUND_SCROLL 25 -#define SOUND_BUY 26 -#define SOUND_SELL 27 -#define SOUND_WARN 28 -#define SOUND_ROCKET 29 /*!< Somebody's shooting rockets */ -#define SOUND_N_KILL 30 /*!< The player kills a non-living/undead monster */ -#define SOUND_U_KILL 31 /*!< The player kills a unique */ -#define SOUND_QUEST 32 /*!< The player has just completed a quest */ -#define SOUND_HEAL 33 /*!< The player was healed a little bit */ -#define SOUND_X_HEAL 34 /*!< The player was healed full health */ -#define SOUND_BITE 35 /*!< A monster bites you */ -#define SOUND_CLAW 36 /*!< A monster claws you */ -#define SOUND_M_SPELL 37 /*!< A monster casts a miscellaneous spell */ -#define SOUND_SUMMON 38 /*!< A monster casts a summoning spell */ -#define SOUND_BREATH 39 /*!< A monster breathes */ -#define SOUND_BALL 40 /*!< A monster casts a ball / bolt spell */ -#define SOUND_M_HEAL 41 /*!< A monster heals itself somehow */ -#define SOUND_ATK_SPELL 42 /*!< A monster casts a misc. offensive spell */ -#define SOUND_EVIL 43 /*!< Something nasty has just happened! */ -#define SOUND_TOUCH 44 /*!< A monster touches you */ -#define SOUND_STING 45 /*!< A monster stings you */ -#define SOUND_CRUSH 46 /*!< A monster crushes / envelopes you */ -#define SOUND_SLIME 47 /*!< A monster drools/spits/etc on you */ -#define SOUND_WAIL 48 /*!< A monster wails */ -#define SOUND_WINNER 49 /*!< Just won the game! */ -#define SOUND_FIRE 50 /*!< An item was burned */ -#define SOUND_ACID 51 /*!< An item was destroyed by acid */ -#define SOUND_ELEC 52 /*!< An item was destroyed by electricity */ -#define SOUND_COLD 53 /*!< An item was shattered */ -#define SOUND_ILLEGAL 54 /*!< Illegal command attempted */ -#define SOUND_FAIL 55 /*!< Fail to get a spell off / activate an item */ -#define SOUND_WAKEUP 56 /*!< A monster wakes up */ -#define SOUND_INVULN 57 /*!< Invulnerability! */ -#define SOUND_FALL 58 /*!< Falling through a trapdoor... */ -#define SOUND_PAIN 59 /*!< A monster is in pain! */ -#define SOUND_DESTITEM 60 /*!< An item was destroyed by misc. means */ -#define SOUND_MOAN 61 /*!< A monster makes a moan/beg/insult attack */ -#define SOUND_SHOW 62 /*!< A monster makes a "show" attack */ -#define SOUND_UNUSED 63 /*!< (no sound for gaze attacks) */ -#define SOUND_EXPLODE 64 /*!< Something (or somebody) explodes */ -#define SOUND_GLASS 65 /*!< A glass feature was crashed */ -#define SOUND_REFLECT 66 /*!< A bolt was reflected */ - -/* - * Mega-Hack -- maximum known sounds - */ -#define SOUND_MAX 67 /*!< 効果音定義の最大数 */ - -#define MAX_VIRTUE 18 /*!< 徳定義の最大数 */ - -#define V_COMPASSION 1 -#define V_HONOUR 2 -#define V_JUSTICE 3 -#define V_SACRIFICE 4 -#define V_KNOWLEDGE 5 -#define V_FAITH 6 -#define V_ENLIGHTEN 7 -#define V_ENCHANT 8 -#define V_CHANCE 9 -#define V_NATURE 10 -#define V_HARMONY 11 -#define V_VITALITY 12 -#define V_UNLIFE 13 -#define V_PATIENCE 14 -#define V_TEMPERANCE 15 -#define V_DILIGENCE 16 -#define V_VALOUR 17 -#define V_INDIVIDUALISM 18 - - -/*** Hack ***/ - - -/* - * Hack -- attempt to reduce various values - */ -#ifdef ANGBAND_LITE -# undef MACRO_MAX -# define MACRO_MAX 128 -# undef QUARK_MAX -# define QUARK_MAX 128 -# undef MESSAGE_MAX -# define MESSAGE_MAX 128 -# undef MESSAGE_BUF -# define MESSAGE_BUF 4096 -#endif - - -/* - * Buildings actions - */ -#define BACT_NOTHING 0 -#define BACT_RESEARCH_ITEM 1 -#define BACT_TOWN_HISTORY 2 -#define BACT_RACE_LEGENDS 3 -#define BACT_GREET_KING 4 -#define BACT_KING_LEGENDS 5 -#define BACT_QUEST 6 -#define BACT_XXX_UNUSED 7 -#define BACT_POSTER 8 -#define BACT_ARENA_RULES 9 -#define BACT_ARENA 10 -#define BACT_ARENA_LEGENDS 11 -#define BACT_IN_BETWEEN 12 -#define BACT_GAMBLE_RULES 13 -#define BACT_CRAPS 14 -#define BACT_SPIN_WHEEL 15 -#define BACT_DICE_SLOTS 16 -#define BACT_REST 17 -#define BACT_FOOD 18 -#define BACT_RUMORS 19 -#define BACT_RESEARCH_MONSTER 20 -#define BACT_COMPARE_WEAPONS 21 -#define BACT_LEGENDS 22 -#define BACT_ENCHANT_WEAPON 23 -#define BACT_ENCHANT_ARMOR 24 -#define BACT_RECHARGE 25 -#define BACT_IDENTS 26 -#define BACT_LEARN 27 -#define BACT_HEALING 28 -#define BACT_RESTORE 29 -#define BACT_ENCHANT_ARROWS 30 -#define BACT_ENCHANT_BOW 31 -#define BACT_GREET 32 -#define BACT_RECALL 33 -#define BACT_TELEPORT_LEVEL 34 -#define BACT_LOSE_MUTATION 35 -#define BACT_BATTLE 36 -#define BACT_TSUCHINOKO 37 -#define BACT_TARGET 38 -#define BACT_KUBI 39 -#define BACT_KANKIN 40 -#define BACT_HEIKOUKA 41 -#define BACT_TELE_TOWN 42 -#define BACT_POKER 43 -#define BACT_IDENT_ONE 44 -#define BACT_RECHARGE_ALL 45 -#define BACT_EVAL_AC 46 -#define BACT_BROKEN_WEAPON 47 -#define MAX_BACT 48 - -/* - * Quest status - */ -#define QUEST_STATUS_UNTAKEN 0 /*!< クエストステータス状態:未発生*/ -#define QUEST_STATUS_TAKEN 1 /*!< クエストステータス状態:発生中*/ -#define QUEST_STATUS_COMPLETED 2 /*!< クエストステータス状態:達成*/ -#define QUEST_STATUS_REWARDED 3 /*!< クエストステータス状態:報酬受け取り前*/ -#define QUEST_STATUS_FINISHED 4 /*!< クエストステータス状態:完了*/ -#define QUEST_STATUS_FAILED 5 /*!< クエストステータス状態:失敗*/ -#define QUEST_STATUS_FAILED_DONE 6 /*!< クエストステータス状態:失敗完了*/ -#define QUEST_STATUS_STAGE_COMPLETED 7 /*!< クエストステータス状態:ステージ毎達成*/ - -/* - * Quest type - */ -#define QUEST_TYPE_KILL_LEVEL 1 /*!< クエスト目的: 特定のユニークモンスターを倒す */ -#define QUEST_TYPE_KILL_ANY_LEVEL 2 /*!< クエスト目的: イベント受託時点でランダムで選ばれた特定のユニークモンスターを倒す */ -#define QUEST_TYPE_FIND_ARTIFACT 3 /*!< クエスト目的: 特定のアーティファクトを発見する */ -#define QUEST_TYPE_FIND_EXIT 4 /*!< クエスト目的: 脱出する */ -#define QUEST_TYPE_KILL_NUMBER 5 /*!< クエスト目的: モンスターを無差別に特定数倒す */ -#define QUEST_TYPE_KILL_ALL 6 /*!< クエスト目的: エリア中のすべてのモンスターを全て倒す */ -#define QUEST_TYPE_RANDOM 7 /*!< クエスト目的: ランダムクエストとして選ばれたユニーク1体を倒す */ -#define QUEST_TYPE_TOWER 8 /*!< クエスト目的: 複数のエリアの全てのモンスターを倒す */ - -/* - * Initialization flags - */ -#define INIT_NAME_ONLY 0x01 -#define INIT_SHOW_TEXT 0x02 -#define INIT_ASSIGN 0x04 -#define INIT_CREATE_DUNGEON 0x08 -#define INIT_ONLY_FEATURES 0x10 -#define INIT_ONLY_BUILDINGS 0x20 - -/* - * Quest flags - */ -#define QUEST_FLAG_SILENT 0x01 /*!< クエストフラグ: クエスト進行に関する情報表示を抑止する / no messages from completion */ -#define QUEST_FLAG_PRESET 0x02 /*!< クエストフラグ: クエストがダンジョン外で発生する / quest is outside the main dungeon */ -#define QUEST_FLAG_ONCE 0x04 /*!< クエストフラグ: クエストがフロアを出た時点で完了する / quest is marked finished after leaving */ -#define QUEST_FLAG_TOWER 0x08 /*!< クエストフラグ: クエスト:塔の形式で進行する / Tower quest is special */ - -/* - * Available graphic modes - */ -#define GRAPHICS_NONE 0 -#define GRAPHICS_ORIGINAL 1 -#define GRAPHICS_ADAM_BOLT 2 -#define GRAPHICS_HENGBAND 3 - -/* - * Modes for the random name generator - */ -#define NAME_DWARF 1 -#define NAME_ELF 2 -#define NAME_GNOME 3 -#define NAME_HOBBIT 4 -#define NAME_HUMAN 5 -#define NAME_ORC 6 - -#ifdef JP -#define JVERB_AND 1 -#define JVERB_TO 2 -#define JVERB_OR 3 -#endif - -/* - * Modes for the tokenizer - */ -#define TOKENIZE_CHECKQUOTE 0x01 /* Special handling of single quotes */ - -/* - * Parse errors - */ -#define PARSE_ERROR_GENERIC 1 -#define PARSE_ERROR_ABSOLETE_FILE 2 -#define PARSE_ERROR_MISSING_RECORD_HEADER 3 -#define PARSE_ERROR_NON_SEQUENTIAL_RECORDS 4 -#define PARSE_ERROR_INVALID_FLAG 5 -#define PARSE_ERROR_UNDEFINED_DIRECTIVE 6 -#define PARSE_ERROR_OUT_OF_MEMORY 7 -#define PARSE_ERROR_OUT_OF_BOUNDS 8 -#define PARSE_ERROR_TOO_FEW_ARGUMENTS 9 -#define PARSE_ERROR_UNDEFINED_TERRAIN_TAG 10 -#define PARSE_ERROR_MAX 11 - -#define GINOU_SUDE 0 -#define GINOU_NITOURYU 1 -#define GINOU_RIDING 2 -#define GINOU_SHIELD 3 -#define GINOU_TEMPMAX 4 -#define GINOU_MAX 10 - -/* Proficiency level */ -#define EXP_LEVEL_UNSKILLED 0 -#define EXP_LEVEL_BEGINNER 1 -#define EXP_LEVEL_SKILLED 2 -#define EXP_LEVEL_EXPERT 3 -#define EXP_LEVEL_MASTER 4 - -/* Proficiency of weapons and misc. skills (except riding) */ -#define WEAPON_EXP_UNSKILLED 0 -#define WEAPON_EXP_BEGINNER 4000 -#define WEAPON_EXP_SKILLED 6000 -#define WEAPON_EXP_EXPERT 7000 -#define WEAPON_EXP_MASTER 8000 - -/* Proficiency of riding */ -#define RIDING_EXP_UNSKILLED 0 -#define RIDING_EXP_BEGINNER 500 -#define RIDING_EXP_SKILLED 2000 -#define RIDING_EXP_EXPERT 5000 -#define RIDING_EXP_MASTER 8000 - -/* Proficiency of spells */ -#define SPELL_EXP_UNSKILLED 0 -#define SPELL_EXP_BEGINNER 900 -#define SPELL_EXP_SKILLED 1200 -#define SPELL_EXP_EXPERT 1400 -#define SPELL_EXP_MASTER 1600 - -#define NO_TOWN 6 -#define SECRET_TOWN 5 - -#define NIKKI_HIGAWARI 0 -#define NIKKI_BUNSHOU 1 -#define NIKKI_ART 2 -#define NIKKI_UNIQUE 3 -#define NIKKI_FIX_QUEST_C 4 -#define NIKKI_FIX_QUEST_F 5 -#define NIKKI_RAND_QUEST_C 6 -#define NIKKI_RAND_QUEST_F 7 -#define NIKKI_MAXDEAPTH 8 -#define NIKKI_TRUMP 9 -#define NIKKI_STAIR 10 -#define NIKKI_RECALL 11 -#define NIKKI_TO_QUEST 12 -#define NIKKI_TELE_LEV 13 -#define NIKKI_BUY 14 -#define NIKKI_SELL 15 -#define NIKKI_ARENA 16 -#define NIKKI_HANMEI 17 -#define NIKKI_LEVELUP 18 -#define NIKKI_GAMESTART 19 -#define NIKKI_WIZ_TELE 20 -#define NIKKI_NAMED_PET 21 -#define NIKKI_PAT_TELE 22 -#define NIKKI_ART_SCROLL 23 - -#define NIKKI_WIZARD_LOG 24 - - -#define RECORD_NAMED_PET_NAME 0 -#define RECORD_NAMED_PET_UNNAME 1 -#define RECORD_NAMED_PET_DISMISS 2 -#define RECORD_NAMED_PET_DEATH 3 -#define RECORD_NAMED_PET_MOVED 4 -#define RECORD_NAMED_PET_LOST_SIGHT 5 -#define RECORD_NAMED_PET_DESTROY 6 -#define RECORD_NAMED_PET_EARTHQUAKE 7 -#define RECORD_NAMED_PET_GENOCIDE 8 -#define RECORD_NAMED_PET_WIZ_ZAP 9 -#define RECORD_NAMED_PET_TELE_LEVEL 10 -#define RECORD_NAMED_PET_BLAST 11 -#define RECORD_NAMED_PET_HEAL_LEPER 12 -#define RECORD_NAMED_PET_COMPACT 13 -#define RECORD_NAMED_PET_LOSE_PARENT 14 - -#define MAX_MANE 16 -#define MAX_MONSPELLS 96 -#define MONSPELL_TYPE_BOLT 1 -#define MONSPELL_TYPE_BALL 2 -#define MONSPELL_TYPE_BREATH 3 -#define MONSPELL_TYPE_SUMMON 4 -#define MONSPELL_TYPE_OTHER 5 - -#define EATER_EXT 36 -#define EATER_CHARGE 0x10000L -#define EATER_ROD_CHARGE 0x10L - -#define MAX_KUBI 20 - -#define DETECT_RAD_DEFAULT 30 -#define DETECT_RAD_MAP 30 -#define DETECT_RAD_ALL 255 - -/* Monster Spells */ -#define MS_SHRIEK 0 -#define MS_XXX1 1 -#define MS_DISPEL 2 -#define MS_ROCKET 3 -#define MS_SHOOT 4 -#define MS_XXX2 5 -#define MS_XXX3 6 -#define MS_XXX4 7 -#define MS_BR_ACID 8 -#define MS_BR_ELEC 9 -#define MS_BR_FIRE 10 -#define MS_BR_COLD 11 -#define MS_BR_POIS 12 -#define MS_BR_NETHER 13 -#define MS_BR_LITE 14 -#define MS_BR_DARK 15 -#define MS_BR_CONF 16 -#define MS_BR_SOUND 17 -#define MS_BR_CHAOS 18 -#define MS_BR_DISEN 19 -#define MS_BR_NEXUS 20 -#define MS_BR_TIME 21 -#define MS_BR_INERTIA 22 -#define MS_BR_GRAVITY 23 -#define MS_BR_SHARDS 24 -#define MS_BR_PLASMA 25 -#define MS_BR_FORCE 26 -#define MS_BR_MANA 27 -#define MS_BALL_NUKE 28 -#define MS_BR_NUKE 29 -#define MS_BALL_CHAOS 30 -#define MS_BR_DISI 31 -#define MS_BALL_ACID 32 -#define MS_BALL_ELEC 33 -#define MS_BALL_FIRE 34 -#define MS_BALL_COLD 35 -#define MS_BALL_POIS 36 -#define MS_BALL_NETHER 37 -#define MS_BALL_WATER 38 -#define MS_BALL_MANA 39 -#define MS_BALL_DARK 40 -#define MS_DRAIN_MANA 41 -#define MS_MIND_BLAST 42 -#define MS_BRAIN_SMASH 43 -#define MS_CAUSE_1 44 -#define MS_CAUSE_2 45 -#define MS_CAUSE_3 46 -#define MS_CAUSE_4 47 -#define MS_BOLT_ACID 48 -#define MS_BOLT_ELEC 49 -#define MS_BOLT_FIRE 50 -#define MS_BOLT_COLD 51 -#define MS_STARBURST 52 -#define MS_BOLT_NETHER 53 -#define MS_BOLT_WATER 54 -#define MS_BOLT_MANA 55 -#define MS_BOLT_PLASMA 56 -#define MS_BOLT_ICE 57 -#define MS_MAGIC_MISSILE 58 -#define MS_SCARE 59 -#define MS_BLIND 60 -#define MS_CONF 61 -#define MS_SLOW 62 -#define MS_SLEEP 63 -#define MS_SPEED 64 -#define MS_HAND_DOOM 65 -#define MS_HEAL 66 -#define MS_INVULNER 67 -#define MS_BLINK 68 -#define MS_TELEPORT 69 -#define MS_WORLD 70 -#define MS_SPECIAL 71 -#define MS_TELE_TO 72 -#define MS_TELE_AWAY 73 -#define MS_TELE_LEVEL 74 -#define MS_PSY_SPEAR 75 -#define MS_DARKNESS 76 -#define MS_MAKE_TRAP 77 -#define MS_FORGET 78 -#define MS_RAISE_DEAD 79 -#define MS_S_KIN 80 -#define MS_S_CYBER 81 -#define MS_S_MONSTER 82 -#define MS_S_MONSTERS 83 -#define MS_S_ANT 84 -#define MS_S_SPIDER 85 -#define MS_S_HOUND 86 -#define MS_S_HYDRA 87 -#define MS_S_ANGEL 88 -#define MS_S_DEMON 89 -#define MS_S_UNDEAD 90 -#define MS_S_DRAGON 91 -#define MS_S_HI_UNDEAD 92 -#define MS_S_HI_DRAGON 93 -#define MS_S_AMBERITE 94 -#define MS_S_UNIQUE 95 - - -#define MON_BEGGAR 12 -#define MON_LEPER 13 -#define MON_BLACK_MARKET 14 -#define MON_LION_HEART 19 -#define MON_GHB 39 -#define MON_NOV_PRIEST 45 -#define MON_GRIP 53 -#define MON_WOLF 54 -#define MON_FANG 55 -#define MON_LOUSE 69 -#define MON_PIRANHA 70 -#define MON_COPPER_COINS 85 -#define MON_NOV_PALADIN 97 -#define MON_GREEN_G 100 -#define MON_NOV_PRIEST_G 109 -#define MON_SILVER_COINS 117 -#define MON_D_ELF 122 -#define MON_MANES 128 -#define MON_LOST_SOUL 133 -#define MON_ROBIN_HOOD 138 -#define MON_NOV_PALADIN_G 147 -#define MON_PHANTOM_W 152 -#define MON_WOUNDED_BEAR 159 -#define MON_D_ELF_MAGE 178 -#define MON_D_ELF_WARRIOR 182 -#define MON_BLUE_HORROR 189 -#define MON_GOLD_COINS 195 -#define MON_VORPAL_BUNNY 205 -#define MON_MASTER_YEEK 224 -#define MON_PRIEST 225 -#define MON_D_ELF_PRIEST 226 -#define MON_TIGER 230 -#define MON_MITHRIL_COINS 239 -#define MON_DRUID 241 -#define MON_PINK_HORROR 242 -#define MON_HILL_GIANT 255 -#define MON_WERERAT 270 -#define MON_UMBER_HULK 283 -#define MON_ORC_CAPTAIN 285 -#define MON_BERSERKER 293 -#define MON_IMP 296 -#define MON_SHAGRAT 314 -#define MON_GORBAG 315 -#define MON_STONE_GIANT 321 -#define MON_LIZARD_KING 332 -#define MON_WYVERN 334 -#define MON_SABRE_TIGER 339 -#define MON_D_ELF_LORD 348 -#define MON_FIRE_VOR 354 -#define MON_WATER_VOR 355 -#define MON_ARCH_VILE 357 -#define MON_COLD_VOR 358 -#define MON_ENERGY_VOR 359 -#define MON_IRON_GOLEM 367 -#define MON_JADE_MONK 370 -#define MON_D_ELF_WARLOCK 375 -#define MON_HAGEN 383 -#define MON_MENELDOR 384 -#define MON_PHANTOM_B 385 -#define MON_C_CRAWLER 395 -#define MON_XICLOTLAN 396 -#define MON_D_ELF_DRUID 400 -#define MON_TROLL_PRIEST 403 -#define MON_GWAIHIR 410 -#define MON_ANGEL 417 -#define MON_ADAMANT_COINS 423 -#define MON_COLBRAN 435 -#define MON_SPIRIT_NAGA 436 -#define MON_GACHAPIN 441 -#define MON_BASILISK 453 -#define MON_ARCHANGEL 456 -#define MON_MITHRIL_GOLEM 464 -#define MON_THORONDOR 468 -#define MON_SHADOW_DRAKE 471 -#define MON_GHOST 477 -#define MON_OGRE_SHAMAN 479 -#define MON_GHOUL_KING 483 -#define MON_NINJA 485 -#define MON_BICLOPS 490 -#define MON_IVORY_MONK 492 -#define MON_LOG_MASTER 498 -#define MON_ETHER_DRAKE 504 -#define MON_GOEMON 505 -#define MON_CHERUB 511 -#define MON_WATER_ELEM 512 -#define MON_JURT 517 -#define MON_LICH 518 -#define MON_BLOODLETTER 523 -#define MON_HALFLING_S 539 -#define MON_GRAV_HOUND 540 -#define MON_REVENANT 555 -#define MON_RAAL 557 -#define MON_COLOSSUS 558 -#define MON_NIGHTBLADE 564 -#define MON_ELDER_THING 569 -#define MON_CRYPT_THING 577 -#define MON_NEXUS_VOR 587 -#define MON_PLASMA_VOR 588 -#define MON_TIME_VOR 589 -#define MON_M_MH_DRAGON 593 -#define MON_MANDOR 598 -#define MON_SHIM_VOR 600 -#define MON_SERAPH 605 -#define MON_BARON_HELL 609 -#define MON_KAVLAX 616 -#define MON_ETTIN 621 -#define MON_VAMPIRE_LORD 623 -#define MON_JUBJUB 640 -#define MON_G_C_DRAKE 646 -#define MON_CLUB_DEMON 648 -#define MON_F_ANGEL 652 -#define MON_D_ELF_SORC 657 -#define MON_MASTER_LICH 658 -#define MON_RINALDO 660 -#define MON_ARCHON 661 -#define MON_UND_BEHOLDER 664 -#define MON_IRON_LICH 666 -#define MON_JACK_SHADOWS 670 -#define MON_LLOIGOR 682 -#define MON_DREADMASTER 690 -#define MON_DROLEM 691 -#define MON_DAWN 693 -#define MON_NAZGUL 696 -#define MON_SMAUG 697 -#define MON_STORMBRINGER 698 -#define MON_ULTRA_PALADIN 699 -#define MON_G_TITAN 702 -#define MON_S_TYRANNO 705 -#define MON_FAFNER 712 -#define MON_G_BALROG 720 -#define MON_TIME_HOUND 725 -#define MON_PLASMA_HOUND 726 -#define MON_BULLGATES 732 -#define MON_SANTACLAUS 733 -#define MON_LORD_CHAOS 737 -#define MON_TINDALOS 739 -#define MON_DEMILICH 742 -#define MON_NIGHTCRAWLER 744 -#define MON_CHAOS_VOR 751 -#define MON_AETHER_VOR 752 -#define MON_FUNDIN 762 -#define MON_DWORKIN 763 -#define MON_NIGHTWALKER 768 -#define MON_RAPHAEL 769 -#define MON_SARUMAN 771 -#define MON_GANDALF 772 -#define MON_BRAND 773 -#define MON_SHADOWLORD 774 -#define MON_ARCHLICH 776 -#define MON_JABBERWOCK 778 -#define MON_CHAOS_HOUND 779 -#define MON_ULT_BEHOLDER 781 -#define MON_SHAMBLER 786 -#define MON_BLEYS 789 -#define MON_FIONA 791 -#define MON_SKY_DRAKE 793 -#define MON_JULIAN 794 -#define MON_BLACK_REAVER 798 -#define MON_CAINE 799 -#define MON_GERARD 807 -#define MON_UNGOLIANT 808 -#define MON_ATLACH_NACHA 809 -#define MON_Y_GOLONAC 810 -#define MON_AETHER_HOUND 811 -#define MON_WARP_DEMON 812 -#define MON_ERIC 813 -#define MON_UNMAKER 815 -#define MON_CYBER 816 -#define MON_KLING 819 -#define MON_CORWIN 820 -#define MON_ANGMAR 825 -#define MON_CANTORAS 830 -#define MON_GODZILLA 832 -#define MON_SPAWN_CTH 836 -#define MON_SURTUR 837 -#define MON_TARRASQUE 838 -#define MON_LUNGORTHIN 839 -#define MON_CYBER_KING 843 -#define MON_WYRM_POWER 847 -#define MON_NODENS 849 -#define MON_JORMUNGAND 854 -#define MON_DESTROYER 855 -#define MON_GOTHMOG 856 -#define MON_G_CTHULHU 857 -#define MON_SAURON 858 -#define MON_UNICORN_ORD 859 -#define MON_OBERON 860 -#define MON_MORGOTH 861 -#define MON_SERPENT 862 -#define MON_ONE_RING 864 -#define MON_CAAWS 866 -#define MON_CULVERIN 867 -#define MON_EBONY_MONK 870 -#define MON_HAGURE 871 -#define MON_OROCHI 872 -#define MON_ECHIZEN 873 -#define MON_SPECT_WYRM 874 -#define MON_DIO 878 -#define MON_OHMU 879 -#define MON_WONG 880 -#define MON_ZOMBI_SERPENT 883 -#define MON_D_ELF_SHADE 886 -#define MON_MANA_HOUND 887 -#define MON_VENOM_WYRM 890 -#define MON_TROLL_KING 894 -#define MON_BAZOOKER 896 -#define MON_SHARD_VOR 897 -#define MON_ELF_LORD 900 -#define MON_MASTER_MYS 916 -#define MON_G_MASTER_MYS 917 -#define MON_IE 921 -#define MON_TSUCHINOKO 926 -#define MON_GCWADL 929 -#define MON_LOCKE_CLONE 930 -#define MON_CALDARM 931 -#define MON_BANORLUPART 932 -#define MON_BANOR 933 -#define MON_LUPART 934 -#define MON_KENSHIROU 936 -#define MON_W_KNIGHT 938 -#define MON_PLANETAR 942 -#define MON_SOLAR 943 -#define MON_BIKETAL 945 -#define MON_RICH 948 -#define MON_IKETA 949 -#define MON_B_DEATH_SWORD 953 -#define MON_YASE_HORSE 955 -#define MON_HORSE 956 -#define MON_BOTEI 963 -#define MON_KAGE 964 -#define MON_JAIAN 967 -#define MON_BELD 973 -#define MON_THAT_BAT 975 -#define MON_SHUTEN 979 -#define MON_FENGHUANG 988 -#define MON_KIRIN 989 -#define MON_BAHAMUT 1000 -#define MON_SUKE 1001 -#define MON_KAKU 1002 -#define MON_GHOST_Q 1003 -#define MON_PIP 1004 -#define MON_A_GOLD 1010 -#define MON_A_SILVER 1011 -#define MON_ROLENTO 1013 -#define MON_RAOU 1018 -#define MON_SHURYUUDAN 1023 -#define MON_WAHHA 1031 -#define MON_DEBBY 1032 -#define MON_KNI_TEMPLAR 1037 -#define MON_PALADIN 1038 -#define MON_CHAMELEON 1040 -#define MON_CHAMELEON_K 1041 -#define MON_TOPAZ_MONK 1047 -#define MON_M_MINDCRAFTER 1056 -#define MON_ELDER_VAMPIRE 1058 -#define MON_NOBORTA 1059 -#define MON_MORI_TROLL 1060 -#define MON_BARNEY 1061 -#define MON_GROO 1062 -#define MON_LOUSY 1063 -#define MON_WYRM_SPACE 1064 -#define MON_JIZOTAKO 1065 -#define MON_TANUKI 1067 -#define MON_ALIEN_JURAL 1082 -#define MON_HATOPOPPO 1083 -#define MON_KOGAN 1096 - -/* Maximum "Nazguls" number */ -#define MAX_NAZGUL_NUM 5 - -#define DO_AUTOPICK 0x01 -#define DO_AUTODESTROY 0x02 -#define DO_DISPLAY 0x04 -#define DONT_AUTOPICK 0x08 -#define ITEM_DISPLAY 0x10 -#define DO_QUERY_AUTOPICK 0x20 - - -#define MAGIC_GLOVE_REDUCE_MANA 0x0001 -#define MAGIC_FAIL_5PERCENT 0x0002 -#define MAGIC_GAIN_EXP 0x0004 - -#define VIRTUE_LARGE 1 -#define VIRTUE_SMALL 2 - -#define SPELL_DD_S 27 -#define SPELL_DD_T 13 -#define SPELL_SW 22 -#define SPELL_KABE 20 - -#define KNOW_STAT 0x01 -#define KNOW_HPRATE 0x02 - -/* - * Music songs - */ -#define MUSIC_NONE 0 -#define MUSIC_SLOW 1 -#define MUSIC_BLESS 2 -#define MUSIC_STUN 3 -#define MUSIC_L_LIFE 4 -#define MUSIC_FEAR 5 -#define MUSIC_HERO 6 -#define MUSIC_MIND 7 -#define MUSIC_STEALTH 8 -#define MUSIC_ID 9 -#define MUSIC_CONF 10 -#define MUSIC_SOUND 11 -#define MUSIC_CHARM 12 -#define MUSIC_WALL 13 -#define MUSIC_RESIST 14 -#define MUSIC_SPEED 15 -#define MUSIC_DISPEL 16 -#define MUSIC_SARUMAN 17 -#define MUSIC_QUAKE 18 -#define MUSIC_STASIS 19 -#define MUSIC_SHERO 20 -#define MUSIC_H_LIFE 21 -#define MUSIC_INVULN 22 -#define MUSIC_PSI 23 - -#define MUSIC_DETECT 101 - -#define SINGING_SONG_EFFECT(P_PTR) ((P_PTR)->magic_num1[0]) -#define INTERUPTING_SONG_EFFECT(P_PTR) ((P_PTR)->magic_num1[1]) -#define SINGING_COUNT(P_PTR) ((P_PTR)->magic_num1[2]) -#define SINGING_SONG_ID(P_PTR) ((P_PTR)->magic_num2[0]) -#define music_singing(X) ((p_ptr->pclass == CLASS_BARD) && (p_ptr->magic_num1[0] == (X))) -#define music_singing_any() ((p_ptr->pclass == CLASS_BARD) && p_ptr->magic_num1[0]) - -/* - * Special essence id for Weapon smith - */ -#define MIN_SPECIAL_ESSENCE 200 - -#define ESSENCE_ATTACK (MIN_SPECIAL_ESSENCE + 0) -#define ESSENCE_AC (MIN_SPECIAL_ESSENCE + 1) -#define ESSENCE_TMP_RES_ACID (MIN_SPECIAL_ESSENCE + 2) -#define ESSENCE_TMP_RES_ELEC (MIN_SPECIAL_ESSENCE + 3) -#define ESSENCE_TMP_RES_FIRE (MIN_SPECIAL_ESSENCE + 4) -#define ESSENCE_TMP_RES_COLD (MIN_SPECIAL_ESSENCE + 5) -#define ESSENCE_SH_FIRE (MIN_SPECIAL_ESSENCE + 6) -#define ESSENCE_SH_ELEC (MIN_SPECIAL_ESSENCE + 7) -#define ESSENCE_SH_COLD (MIN_SPECIAL_ESSENCE + 8) -#define ESSENCE_RESISTANCE (MIN_SPECIAL_ESSENCE + 9) -#define ESSENCE_SUSTAIN (MIN_SPECIAL_ESSENCE + 10) -#define ESSENCE_SLAY_GLOVE (MIN_SPECIAL_ESSENCE + 11) - - -#define DUNGEON_MODE_NONE 0 -#define DUNGEON_MODE_AND 1 -#define DUNGEON_MODE_NAND 2 -#define DUNGEON_MODE_OR 3 -#define DUNGEON_MODE_NOR 4 - -/*** Dungeon type flags -- DG ***/ -#define DF1_WINNER 0x00000001L -#define DF1_MAZE 0x00000002L -#define DF1_SMALLEST 0x00000004L -#define DF1_BEGINNER 0x00000008L -#define DF1_BIG 0x00000010L -#define DF1_NO_DOORS 0x00000020L -#define DF1_WATER_RIVER 0x00000040L -#define DF1_LAVA_RIVER 0x00000080L -#define DF1_CURTAIN 0x00000100L -#define DF1_GLASS_DOOR 0x00000200L -#define DF1_CAVE 0x00000400L -#define DF1_CAVERN 0x00000800L -#define DF1_ARCADE 0x00001000L -#define DF1_LAKE_ACID 0x00002000L -#define DF1_LAKE_POISONOUS 0x00004000L -#define DF1_XXX15 0x00008000L -#define DF1_FORGET 0x00010000L -#define DF1_LAKE_WATER 0x00020000L -#define DF1_LAKE_LAVA 0x00040000L -#define DF1_LAKE_RUBBLE 0x00080000L -#define DF1_LAKE_TREE 0x00100000L -#define DF1_NO_VAULT 0x00200000L -#define DF1_ARENA 0x00400000L -#define DF1_DESTROY 0x00800000L -#define DF1_GLASS_ROOM 0x01000000L -#define DF1_NO_CAVE 0x02000000L -#define DF1_NO_MAGIC 0x04000000L -#define DF1_NO_MELEE 0x08000000L -#define DF1_CHAMELEON 0x10000000L -#define DF1_DARKNESS 0x20000000L -#define DF1_ACID_RIVER 0x40000000L -#define DF1_POISONOUS_RIVER 0x80000000L - -#define DF1_LAKE_MASK (DF1_LAKE_WATER | DF1_LAKE_LAVA | DF1_LAKE_RUBBLE | DF1_LAKE_TREE | DF1_LAKE_POISONOUS | DF1_LAKE_ACID) - -#define DUNGEON_ANGBAND 1 -#define DUNGEON_GALGALS 2 -#define DUNGEON_ORC 3 -#define DUNGEON_MAZE 4 -#define DUNGEON_DRAGON 5 -#define DUNGEON_GRAVE 6 -#define DUNGEON_WOOD 7 -#define DUNGEON_VOLCANO 8 -#define DUNGEON_HELL 9 -#define DUNGEON_HEAVEN 10 -#define DUNGEON_OCEAN 11 -#define DUNGEON_CASTLE 12 -#define DUNGEON_CTH 13 -#define DUNGEON_MOUNTAIN 14 -#define DUNGEON_GOLD 15 -#define DUNGEON_NO_MAGIC 16 -#define DUNGEON_NO_MELEE 17 -#define DUNGEON_CHAMELEON 18 -#define DUNGEON_DARKNESS 19 - - -#define DUNGEON_FEAT_PROB_NUM 3 - - -/* - * Flags for save/load temporal saved floor file - */ -#define SLF_SECOND 0x0001 /* Called from another save/load function */ -#define SLF_NO_KILL 0x0002 /* Don't kill temporal files */ - - -/* - * Flags for wr_item()/rd_item() - */ -#define SAVE_ITEM_PVAL 0x00000001 -#define SAVE_ITEM_DISCOUNT 0x00000002 -#define SAVE_ITEM_NUMBER 0x00000004 -#define SAVE_ITEM_NAME1 0x00000008 -#define SAVE_ITEM_NAME2 0x00000010 -#define SAVE_ITEM_TIMEOUT 0x00000020 -#define SAVE_ITEM_TO_H 0x00000040 -#define SAVE_ITEM_TO_D 0x00000080 -#define SAVE_ITEM_TO_A 0x00000100 -#define SAVE_ITEM_AC 0x00000200 -#define SAVE_ITEM_DD 0x00000400 -#define SAVE_ITEM_DS 0x00000800 -#define SAVE_ITEM_IDENT 0x00001000 -#define SAVE_ITEM_MARKED 0x00002000 -#define SAVE_ITEM_ART_FLAGS0 0x00004000 -#define SAVE_ITEM_ART_FLAGS1 0x00008000 -#define SAVE_ITEM_ART_FLAGS2 0x00010000 -#define SAVE_ITEM_ART_FLAGS3 0x00020000 -#define SAVE_ITEM_CURSE_FLAGS 0x00040000 -#define SAVE_ITEM_HELD_M_IDX 0x00080000 -#define SAVE_ITEM_XTRA1 0x00100000 -#define SAVE_ITEM_XTRA2 0x00200000 -#define SAVE_ITEM_XTRA3 0x00400000 -#define SAVE_ITEM_XTRA4 0x00800000 -#define SAVE_ITEM_XTRA5 0x01000000 -#define SAVE_ITEM_FEELING 0x02000000 -#define SAVE_ITEM_INSCRIPTION 0x04000000 -#define SAVE_ITEM_ART_NAME 0x08000000 -#define SAVE_ITEM_ART_FLAGS4 0x10000000 - - -/* - * Flags for wr_monster()/rd_monster() - */ -#define SAVE_MON_AP_R_IDX 0x00000001 -#define SAVE_MON_SUB_ALIGN 0x00000002 -#define SAVE_MON_CSLEEP 0x00000004 -#define SAVE_MON_FAST 0x00000008 -#define SAVE_MON_SLOW 0x00000010 -#define SAVE_MON_STUNNED 0x00000020 -#define SAVE_MON_CONFUSED 0x00000040 -#define SAVE_MON_MONFEAR 0x00000080 -#define SAVE_MON_TARGET_Y 0x00000100 -#define SAVE_MON_TARGET_X 0x00000200 -#define SAVE_MON_INVULNER 0x00000400 -#define SAVE_MON_SMART 0x00000800 -#define SAVE_MON_EXP 0x00001000 -#define SAVE_MON_MFLAG2 0x00002000 -#define SAVE_MON_NICKNAME 0x00004000 -#define SAVE_MON_PARENT 0x00008000 - - -/* - * Constant for kinds of mimic - */ -#define MIMIC_NONE 0 -#define MIMIC_DEMON 1 -#define MIMIC_DEMON_LORD 2 -#define MIMIC_VAMPIRE 3 - - -#define MIMIC_FLAGS choice -#define MIMIC_IS_NONLIVING 0x00000001 -#define MIMIC_IS_DEMON 0x00000002 -#define MIMIC_IS_UNDEAD 0x00000004 - - -#define prace_is_(A) (!p_ptr->mimic_form && (p_ptr->prace == A)) - -/* Sub-alignment flags for neutral monsters */ -#define SUB_ALIGN_NEUTRAL 0x0000 -#define SUB_ALIGN_EVIL 0x0001 -#define SUB_ALIGN_GOOD 0x0002 - -#define IS_WIZARD_CLASS() \ - (p_ptr->pclass == CLASS_MAGE || p_ptr->pclass == CLASS_HIGH_MAGE || p_ptr->pclass == CLASS_SORCERER || p_ptr->pclass == CLASS_MAGIC_EATER || p_ptr->pclass == CLASS_BLUE_MAGE) - -/* Multishadow effects is determined by current_world_ptr->game_turn */ -#define CHECK_MULTISHADOW() (p_ptr->multishadow && (current_world_ptr->game_turn & 1)) - -/* Is "teleport level" ineffective to this target? */ -#define TELE_LEVEL_IS_INEFF(TARGET) \ - (p_ptr->inside_arena || p_ptr->inside_battle || \ - (p_ptr->inside_quest && !random_quest_number(current_floor_ptr->dun_level)) || \ - (((TARGET) <= 0) && (quest_number(current_floor_ptr->dun_level) || (current_floor_ptr->dun_level >= d_info[p_ptr->dungeon_idx].maxdepth)) && \ - (current_floor_ptr->dun_level >= 1) && ironman_downward)) - - -/* - * Max numbers of macro trigger names - */ -#define MAX_MACRO_MOD 12 -#define MAX_MACRO_TRIG 200 /*!< 登録を許すマクロ(トリガー)の最大数 */ - -/* Max size of screen dump buffer */ -#define SCREEN_BUF_MAX_SIZE (4 * 65536) - - -/* - * Special key code used for inkey_special() - */ -#define SKEY_MOD_MASK 0x0f00 -#define SKEY_MOD_SHIFT 0x0100 -#define SKEY_MOD_CONTROL 0x0200 - -#define SKEY_MASK 0xf000 -#define SKEY_DOWN 0xf001 -#define SKEY_LEFT 0xf002 -#define SKEY_RIGHT 0xf003 -#define SKEY_UP 0xf004 -#define SKEY_PGUP 0xf005 -#define SKEY_PGDOWN 0xf006 -#define SKEY_TOP 0xf007 -#define SKEY_BOTTOM 0xf008 - -/* - * Bit flags for move_player_effect() - */ -#define MPE_STAYING 0x00000001 -#define MPE_FORGET_FLOW 0x00000002 -#define MPE_HANDLE_STUFF 0x00000004 -#define MPE_ENERGY_USE 0x00000008 -#define MPE_DONT_PICKUP 0x00000010 -#define MPE_DO_PICKUP 0x00000020 -#define MPE_BREAK_TRAP 0x00000040 -#define MPE_DONT_SWAP_MON 0x00000080 - - -#define MTIMED_CSLEEP 0 /* Monster is sleeping */ -#define MTIMED_FAST 1 /* Monster is temporarily fast */ -#define MTIMED_SLOW 2 /* Monster is temporarily slow */ -#define MTIMED_STUNNED 3 /* Monster is stunned */ -#define MTIMED_CONFUSED 4 /* Monster is confused */ -#define MTIMED_MONFEAR 5 /* Monster is afraid */ -#define MTIMED_INVULNER 6 /* Monster is temporarily invulnerable */ - -#define MAX_MTIMED 7 - -#define MON_CSLEEP(M_PTR) ((M_PTR)->mtimed[MTIMED_CSLEEP]) -#define MON_FAST(M_PTR) ((M_PTR)->mtimed[MTIMED_FAST]) -#define MON_SLOW(M_PTR) ((M_PTR)->mtimed[MTIMED_SLOW]) -#define MON_STUNNED(M_PTR) ((M_PTR)->mtimed[MTIMED_STUNNED]) -#define MON_CONFUSED(M_PTR) ((M_PTR)->mtimed[MTIMED_CONFUSED]) -#define MON_MONFEAR(M_PTR) ((M_PTR)->mtimed[MTIMED_MONFEAR]) -#define MON_INVULNER(M_PTR) ((M_PTR)->mtimed[MTIMED_INVULNER]) - -/* - * Bit flags for screen_object() - */ -#define SCROBJ_FAKE_OBJECT 0x00000001 -#define SCROBJ_FORCE_DETAIL 0x00000002 - -/* - * For travel command (auto run) - */ -#define TRAVEL - -/* Sniper */ -#define SP_NONE 0 -#define SP_LITE 1 -#define SP_AWAY 2 -#define SP_FIRE 3 -#define SP_KILL_WALL 4 -#define SP_COLD 5 -#define SP_KILL_TRAP 6 -#define SP_ELEC 7 -#define SP_PIERCE 8 -#define SP_RUSH 9 -#define SP_DOUBLE 10 -#define SP_EXPLODE 11 -#define SP_EVILNESS 12 -#define SP_HOLYNESS 13 -#define SP_FINAL 14 -#define SP_NEEDLE 15 - -#define CONCENT_RADAR_THRESHOLD 2 -#define CONCENT_TELE_THRESHOLD 5 - -/* Hex */ -#define hex_spelling_any() \ - ((p_ptr->realm1 == REALM_HEX) && (p_ptr->magic_num1[0])) -#define hex_spelling(X) \ - ((p_ptr->realm1 == REALM_HEX) && (p_ptr->magic_num1[0] & (1L << (X)))) -#define CASTING_HEX_FLAGS(P_PTR) ((P_PTR)->magic_num1[0]) -#define CASTING_HEX_NUM(P_PTR) ((P_PTR)->magic_num2[0]) -#define HEX_REVENGE_POWER(P_PTR) ((P_PTR)->magic_num1[2]) -#define HEX_REVENGE_TURN(P_PTR) ((P_PTR)->magic_num2[2]) -#define HEX_REVENGE_TYPE(P_PTR) ((P_PTR)->magic_num2[1]) - -/* 1st book */ -#define HEX_BLESS 0 -#define HEX_CURE_LIGHT 1 -#define HEX_DEMON_AURA 2 -#define HEX_STINKING_MIST 3 -#define HEX_XTRA_MIGHT 4 -#define HEX_CURSE_WEAPON 5 -#define HEX_DETECT_EVIL 6 -#define HEX_PATIENCE 7 -/* 2nd book */ -#define HEX_ICE_ARMOR 8 -#define HEX_CURE_SERIOUS 9 -#define HEX_INHAIL 10 -#define HEX_VAMP_MIST 11 -#define HEX_RUNESWORD 12 -#define HEX_CONFUSION 13 -#define HEX_BUILDING 14 -#define HEX_ANTI_TELE 15 -/* 3rd book */ -#define HEX_SHOCK_CLOAK 16 -#define HEX_CURE_CRITICAL 17 -#define HEX_RECHARGE 18 -#define HEX_RAISE_DEAD 19 -#define HEX_CURSE_ARMOUR 20 -#define HEX_SHADOW_CLOAK 21 -#define HEX_PAIN_TO_MANA 22 -#define HEX_EYE_FOR_EYE 23 -/* 4th book */ -#define HEX_ANTI_MULTI 24 -#define HEX_RESTORE 25 -#define HEX_DRAIN_CURSE 26 -#define HEX_VAMP_BLADE 27 -#define HEX_STUN_MONSTERS 28 -#define HEX_SHADOW_MOVE 29 -#define HEX_ANTI_MAGIC 30 -#define HEX_REVENGE 31 - -/* - Language selection macro -*/ -#ifdef JP -#define _(JAPANESE,ENGLISH) (JAPANESE) -#else -#define _(JAPANESE,ENGLISH) (ENGLISH) -#endif - -/* Lite flag macro */ -#define have_lite_flag(ARRAY) \ - (have_flag(ARRAY, TR_LITE_1) || have_flag(ARRAY, TR_LITE_2) || have_flag(ARRAY, TR_LITE_3)) - -#define have_dark_flag(ARRAY) \ - (have_flag(ARRAY, TR_LITE_M1) || have_flag(ARRAY, TR_LITE_M2) || have_flag(ARRAY, TR_LITE_M3)) - -/* Spell Type flag */ -#define MONSTER_TO_PLAYER 0x01 -#define MONSTER_TO_MONSTER 0x02 - -/* summoning number */ -#define S_NUM_6 (easy_band ? 2 : 6) -#define S_NUM_4 (easy_band ? 1 : 4) - -/* monster spell number */ -#define RF4_SPELL_START 32 * 3 -#define RF5_SPELL_START 32 * 4 -#define RF6_SPELL_START 32 * 5 - -#define RF4_SPELL_SIZE 32 -#define RF5_SPELL_SIZE 32 -#define RF6_SPELL_SIZE 32 - -/* Spell Damage Calc Flag*/ -#define DAM_ROLL 1 -#define DAM_MAX 2 -#define DAM_MIN 3 -#define DICE_NUM 4 -#define DICE_SIDE 5 -#define DICE_MULT 6 -#define DICE_DIV 7 -#define BASE_DAM 8 - -/* Cheat Info Type */ -#define CHEAT_OBJECT 0 -#define CHEAT_MONSTER 1 -#define CHEAT_DUNGEON 2 -#define CHEAT_MISC 3 - -#define COMMAND_ARG_REST_UNTIL_DONE -2 /*!<休憩コマンド引数 … 必要な分だけ回復 */ -#define COMMAND_ARG_REST_FULL_HEALING -1 /*!<休憩コマンド引数 … HPとMPが全回復するまで */ - -/*! - * チートオプションの最大数 / Number of cheating options - */ -#define CHEAT_MAX 10 diff --git a/src/dungeon.c b/src/dungeon.c deleted file mode 100644 index ac1faed8c..000000000 --- a/src/dungeon.c +++ /dev/null @@ -1,6241 +0,0 @@ -/*! - @file dungeon.c - @brief Angbandゲームエンジン / Angband game engine - @date 2013/12/31 - @author - Copyright (c) 1989 James E. Wilson, Robert A. Koeneke\n - This software may be copied and distributed for educational, research, and\n - not for profit purposes provided that this copyright and statement are\n - included in all such copies.\n - 2013 Deskull rearranged comment for Doxygen. - */ - -#include "angband.h" -#include "cmd-activate.h" -#include "cmd-eat.h" -#include "cmd-hissatsu.h" -#include "cmd-item.h" -#include "cmd-magiceat.h" -#include "cmd-mane.h" -#include "cmd-quaff.h" -#include "cmd-read.h" -#include "cmd-smith.h" -#include "cmd-usestaff.h" -#include "cmd-zaprod.h" -#include "cmd-zapwand.h" -#include "cmd-pet.h" -#include "floor.h" -#include "floor-events.h" -#include "object-curse.h" -#include "store.h" -#include "spells-summon.h" -#include "spells-object.h" -#include "spells-status.h" -#include "spells-floor.h" -#include "monsterrace-hook.h" -#include "world.h" -#include "mutation.h" -#include "quest.h" -#include "artifact.h" -#include "avatar.h" -#include "player-move.h" -#include "player-status.h" -#include "cmd-spell.h" -#include "realm-hex.h" -#include "object-hook.h" -#include "wild.h" -#include "monster-status.h" -#include "floor-save.h" - - -static bool load = TRUE; /*!<ロード処理中の分岐フラグ*/ -static int wild_regen = 20; /*!<広域マップ移動時の自然回復処理カウンタ(広域マップ1マス毎に20回処理を基本とする)*/ - -/*! - * @brief 擬似鑑定を実際に行い判定を反映する - * @param slot 擬似鑑定を行うプレイヤーの所持リストID - * @param heavy 重度の擬似鑑定を行うならばTRUE - * @return なし - */ -static void sense_inventory_aux(INVENTORY_IDX slot, bool heavy) -{ - byte feel; - object_type *o_ptr = &inventory[slot]; - GAME_TEXT o_name[MAX_NLEN]; - - /* We know about it already, do not tell us again */ - if (o_ptr->ident & (IDENT_SENSE))return; - - /* It is fully known, no information needed */ - if (object_is_known(o_ptr)) return; - - /* Check for a feeling */ - feel = (heavy ? value_check_aux1(o_ptr) : value_check_aux2(o_ptr)); - - /* Skip non-feelings */ - if (!feel) return; - - /* Bad luck */ - if ((p_ptr->muta3 & MUT3_BAD_LUCK) && !randint0(13)) - { - switch (feel) - { - case FEEL_TERRIBLE: - { - feel = FEEL_SPECIAL; - break; - } - case FEEL_WORTHLESS: - { - feel = FEEL_EXCELLENT; - break; - } - case FEEL_CURSED: - { - if (heavy) - feel = randint0(3) ? FEEL_GOOD : FEEL_AVERAGE; - else - feel = FEEL_UNCURSED; - break; - } - case FEEL_AVERAGE: - { - feel = randint0(2) ? FEEL_CURSED : FEEL_GOOD; - break; - } - case FEEL_GOOD: - { - if (heavy) - feel = randint0(3) ? FEEL_CURSED : FEEL_AVERAGE; - else - feel = FEEL_CURSED; - break; - } - case FEEL_EXCELLENT: - { - feel = FEEL_WORTHLESS; - break; - } - case FEEL_SPECIAL: - { - feel = FEEL_TERRIBLE; - break; - } - } - } - - /* Stop everything */ - if (disturb_minor) disturb(FALSE, FALSE); - - /* Get an object description */ - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - - /* Message (equipment) */ - if (slot >= INVEN_RARM) - { -#ifdef JP - msg_format("%s%s(%c)は%sという感じがする...", - describe_use(slot),o_name, index_to_label(slot),game_inscriptions[feel]); -#else - msg_format("You feel the %s (%c) you are %s %s %s...", - o_name, index_to_label(slot), describe_use(slot), - ((o_ptr->number == 1) ? "is" : "are"), - game_inscriptions[feel]); -#endif - - } - - /* Message (inventory) */ - else - { -#ifdef JP - msg_format("ザックの中の%s(%c)は%sという感じがする...", - o_name, index_to_label(slot),game_inscriptions[feel]); -#else - msg_format("You feel the %s (%c) in your pack %s %s...", - o_name, index_to_label(slot), - ((o_ptr->number == 1) ? "is" : "are"), - game_inscriptions[feel]); -#endif - - } - - o_ptr->ident |= (IDENT_SENSE); - - /* Set the "inscription" */ - o_ptr->feeling = feel; - - /* Auto-inscription/destroy */ - autopick_alter_item(slot, destroy_feeling); - p_ptr->update |= (PU_COMBINE | PU_REORDER); - - p_ptr->window |= (PW_INVEN | PW_EQUIP); -} - - - -/*! - * @brief 1プレイヤーターン毎に武器、防具の擬似鑑定が行われるかを判定する。 - * @return なし - * @details - * Sense the inventory\n - *\n - * Class 0 = Warrior --> fast and heavy\n - * Class 1 = Mage --> slow and light\n - * Class 2 = Priest --> fast but light\n - * Class 3 = Rogue --> okay and heavy\n - * Class 4 = Ranger --> slow but heavy (changed!)\n - * Class 5 = Paladin --> slow but heavy\n - */ -static void sense_inventory1(void) -{ - INVENTORY_IDX i; - PLAYER_LEVEL plev = p_ptr->lev; - bool heavy = FALSE; - object_type *o_ptr; - - - /*** Check for "sensing" ***/ - - /* No sensing when confused */ - if (p_ptr->confused) return; - - /* Analyze the class */ - switch (p_ptr->pclass) - { - case CLASS_WARRIOR: - case CLASS_ARCHER: - case CLASS_SAMURAI: - case CLASS_CAVALRY: - { - /* Good sensing */ - if (0 != randint0(9000L / (plev * plev + 40))) return; - - /* Heavy sensing */ - heavy = TRUE; - - break; - } - - case CLASS_SMITH: - { - /* Good sensing */ - if (0 != randint0(6000L / (plev * plev + 50))) return; - - /* Heavy sensing */ - heavy = TRUE; - - break; - } - - case CLASS_MAGE: - case CLASS_HIGH_MAGE: - case CLASS_SORCERER: - case CLASS_MAGIC_EATER: - { - /* Very bad (light) sensing */ - if (0 != randint0(240000L / (plev + 5))) return; - - break; - } - - case CLASS_PRIEST: - case CLASS_BARD: - { - /* Good (light) sensing */ - if (0 != randint0(10000L / (plev * plev + 40))) return; - - break; - } - - case CLASS_ROGUE: - case CLASS_NINJA: - { - /* Okay sensing */ - if (0 != randint0(20000L / (plev * plev + 40))) return; - - /* Heavy sensing */ - heavy = TRUE; - - break; - } - - case CLASS_RANGER: - { - /* Bad sensing */ - if (0 != randint0(95000L / (plev * plev + 40))) return; - - /* Changed! */ - heavy = TRUE; - - break; - } - - case CLASS_PALADIN: - case CLASS_SNIPER: - { - /* Bad sensing */ - if (0 != randint0(77777L / (plev * plev + 40))) return; - - /* Heavy sensing */ - heavy = TRUE; - - break; - } - - case CLASS_WARRIOR_MAGE: - case CLASS_RED_MAGE: - { - /* Bad sensing */ - if (0 != randint0(75000L / (plev * plev + 40))) return; - - break; - } - - case CLASS_MINDCRAFTER: - case CLASS_IMITATOR: - case CLASS_BLUE_MAGE: - case CLASS_MIRROR_MASTER: - { - /* Bad sensing */ - if (0 != randint0(55000L / (plev * plev + 40))) return; - - break; - } - - case CLASS_CHAOS_WARRIOR: - { - /* Bad sensing */ - if (0 != randint0(80000L / (plev * plev + 40))) return; - - /* Changed! */ - heavy = TRUE; - - break; - } - - case CLASS_MONK: - case CLASS_FORCETRAINER: - { - /* Okay sensing */ - if (0 != randint0(20000L / (plev * plev + 40))) return; - - break; - } - - case CLASS_TOURIST: - { - /* Good sensing */ - if (0 != randint0(20000L / ((plev+50)*(plev+50)))) return; - - /* Heavy sensing */ - heavy = TRUE; - - break; - } - - case CLASS_BEASTMASTER: - { - /* Bad sensing */ - if (0 != randint0(65000L / (plev * plev + 40))) return; - - break; - } - case CLASS_BERSERKER: - { - /* Heavy sensing */ - heavy = TRUE; - - break; - } - } - - if (compare_virtue(V_KNOWLEDGE, 100, VIRTUE_LARGE)) heavy = TRUE; - - /*** Sense everything ***/ - - /* Check everything */ - for (i = 0; i < INVEN_TOTAL; i++) - { - bool okay = FALSE; - - o_ptr = &inventory[i]; - - /* Skip empty slots */ - if (!o_ptr->k_idx) continue; - - /* Valid "tval" codes */ - switch (o_ptr->tval) - { - case TV_SHOT: - case TV_ARROW: - case TV_BOLT: - case TV_BOW: - case TV_DIGGING: - case TV_HAFTED: - case TV_POLEARM: - case TV_SWORD: - case TV_BOOTS: - case TV_GLOVES: - case TV_HELM: - case TV_CROWN: - case TV_SHIELD: - case TV_CLOAK: - case TV_SOFT_ARMOR: - case TV_HARD_ARMOR: - case TV_DRAG_ARMOR: - case TV_CARD: - { - okay = TRUE; - break; - } - } - - /* Skip non-sense machines */ - if (!okay) continue; - - /* Occasional failure on inventory items */ - if ((i < INVEN_RARM) && (0 != randint0(5))) continue; - - /* Good luck */ - if ((p_ptr->muta3 & MUT3_GOOD_LUCK) && !randint0(13)) - { - heavy = TRUE; - } - - sense_inventory_aux(i, heavy); - } -} - -/*! - * @brief 1プレイヤーターン毎に武器、防具以外の擬似鑑定が行われるかを判定する。 - * @return なし - */ -static void sense_inventory2(void) -{ - INVENTORY_IDX i; - PLAYER_LEVEL plev = p_ptr->lev; - object_type *o_ptr; - - - /*** Check for "sensing" ***/ - - /* No sensing when confused */ - if (p_ptr->confused) return; - - /* Analyze the class */ - switch (p_ptr->pclass) - { - case CLASS_WARRIOR: - case CLASS_ARCHER: - case CLASS_SAMURAI: - case CLASS_CAVALRY: - case CLASS_BERSERKER: - case CLASS_SNIPER: - { - return; - } - - case CLASS_SMITH: - case CLASS_PALADIN: - case CLASS_CHAOS_WARRIOR: - case CLASS_IMITATOR: - case CLASS_BEASTMASTER: - case CLASS_NINJA: - { - /* Very bad (light) sensing */ - if (0 != randint0(240000L / (plev + 5))) return; - - break; - } - - case CLASS_RANGER: - case CLASS_WARRIOR_MAGE: - case CLASS_RED_MAGE: - case CLASS_MONK: - { - /* Bad sensing */ - if (0 != randint0(95000L / (plev * plev + 40))) return; - - break; - } - - case CLASS_PRIEST: - case CLASS_BARD: - case CLASS_ROGUE: - case CLASS_FORCETRAINER: - case CLASS_MINDCRAFTER: - { - /* Good sensing */ - if (0 != randint0(20000L / (plev * plev + 40))) return; - - break; - } - - case CLASS_MAGE: - case CLASS_HIGH_MAGE: - case CLASS_SORCERER: - case CLASS_MAGIC_EATER: - case CLASS_MIRROR_MASTER: - case CLASS_BLUE_MAGE: - { - /* Good sensing */ - if (0 != randint0(9000L / (plev * plev + 40))) return; - - break; - } - - case CLASS_TOURIST: - { - /* Good sensing */ - if (0 != randint0(20000L / ((plev+50)*(plev+50)))) return; - - break; - } - } - - /*** Sense everything ***/ - - /* Check everything */ - for (i = 0; i < INVEN_TOTAL; i++) - { - bool okay = FALSE; - - o_ptr = &inventory[i]; - - /* Skip empty slots */ - if (!o_ptr->k_idx) continue; - - /* Valid "tval" codes */ - switch (o_ptr->tval) - { - case TV_RING: - case TV_AMULET: - case TV_LITE: - case TV_FIGURINE: - { - okay = TRUE; - break; - } - } - - /* Skip non-sense machines */ - if (!okay) continue; - - /* Occasional failure on inventory items */ - if ((i < INVEN_RARM) && (0 != randint0(5))) continue; - - sense_inventory_aux(i, TRUE); - } -} - -/*! - * @brief パターン終点到達時のテレポート処理を行う - * @return なし - */ -static void pattern_teleport(void) -{ - DEPTH min_level = 0; - DEPTH max_level = 99; - - /* Ask for level */ - if (get_check(_("他の階にテレポートしますか?", "Teleport level? "))) - { - char ppp[80]; - char tmp_val[160]; - - /* Only downward in ironman mode */ - if (ironman_downward) - min_level = current_floor_ptr->dun_level; - - /* Maximum level */ - if (p_ptr->dungeon_idx == DUNGEON_ANGBAND) - { - if (current_floor_ptr->dun_level > 100) - max_level = MAX_DEPTH - 1; - else if (current_floor_ptr->dun_level == 100) - max_level = 100; - } - else - { - max_level = d_info[p_ptr->dungeon_idx].maxdepth; - min_level = d_info[p_ptr->dungeon_idx].mindepth; - } - - /* Prompt */ - sprintf(ppp, _("テレポート先:(%d-%d)", "Teleport to level (%d-%d): "), (int)min_level, (int)max_level); - - /* Default */ - sprintf(tmp_val, "%d", (int)current_floor_ptr->dun_level); - - /* Ask for a level */ - if (!get_string(ppp, tmp_val, 10)) return; - - /* Extract request */ - command_arg = (COMMAND_ARG)atoi(tmp_val); - } - else if (get_check(_("通常テレポート?", "Normal teleport? "))) - { - teleport_player(200, 0L); - return; - } - else - { - return; - } - if (command_arg < min_level) command_arg = (COMMAND_ARG)min_level; - if (command_arg > max_level) command_arg = (COMMAND_ARG)max_level; - - /* Accept request */ - msg_format(_("%d 階にテレポートしました。", "You teleport to dungeon level %d."), command_arg); - - if (autosave_l) do_cmd_save_game(TRUE); - - /* Change level */ - current_floor_ptr->dun_level = command_arg; - - leave_quest_check(); - - if (record_stair) do_cmd_write_nikki(NIKKI_PAT_TELE, 0, NULL); - - p_ptr->inside_quest = 0; - free_turn(p_ptr); - - /* - * Clear all saved floors - * and create a first saved floor - */ - prepare_change_floor_mode(CFM_FIRST_FLOOR); - p_ptr->leaving = TRUE; -} - -/*! - * @brief 各種パターン地形上の特別な処理 / Returns TRUE if we are on the Pattern... - * @return 実際にパターン地形上にプレイヤーが居た場合はTRUEを返す。 - */ -static bool pattern_effect(void) -{ - int pattern_type; - - if (!pattern_tile(p_ptr->y, p_ptr->x)) return FALSE; - - if ((prace_is_(RACE_AMBERITE)) && - (p_ptr->cut > 0) && one_in_(10)) - { - wreck_the_pattern(); - } - - pattern_type = f_info[current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].feat].subtype; - - switch (pattern_type) - { - case PATTERN_TILE_END: - (void)set_image(0); - (void)restore_all_status(); - (void)restore_level(); - (void)cure_critical_wounds(1000); - - cave_set_feat(p_ptr->y, p_ptr->x, feat_pattern_old); - msg_print(_("「パターン」のこの部分は他の部分より強力でないようだ。", "This section of the Pattern looks less powerful.")); - - /* - * We could make the healing effect of the - * Pattern center one-time only to avoid various kinds - * of abuse, like luring the win monster into fighting you - * in the middle of the pattern... - */ - break; - - case PATTERN_TILE_OLD: - /* No effect */ - break; - - case PATTERN_TILE_TELEPORT: - pattern_teleport(); - break; - - case PATTERN_TILE_WRECKED: - if (!IS_INVULN()) - take_hit(DAMAGE_NOESCAPE, 200, _("壊れた「パターン」を歩いたダメージ", "walking the corrupted Pattern"), -1); - break; - - default: - if (prace_is_(RACE_AMBERITE) && !one_in_(2)) - return TRUE; - else if (!IS_INVULN()) - take_hit(DAMAGE_NOESCAPE, damroll(1, 3), _("「パターン」を歩いたダメージ", "walking the Pattern"), -1); - break; - } - - return TRUE; -} - - -/*! - * @brief プレイヤーのHP自然回復処理 / Regenerate hit points -RAK- - * @param percent 回復比率 - * @return なし - */ -static void regenhp(int percent) -{ - HIT_POINT new_chp; - u32b new_chp_frac; - HIT_POINT old_chp; - - if (p_ptr->special_defense & KATA_KOUKIJIN) return; - if (p_ptr->action == ACTION_HAYAGAKE) return; - - /* Save the old hitpoints */ - old_chp = p_ptr->chp; - - /* - * Extract the new hitpoints - * - * 'percent' is the Regen factor in unit (1/2^16) - */ - new_chp = 0; - new_chp_frac = (p_ptr->mhp * percent + PY_REGEN_HPBASE); - - /* Convert the unit (1/2^16) to (1/2^32) */ - s64b_LSHIFT(new_chp, new_chp_frac, 16); - - /* Regenerating */ - s64b_add(&(p_ptr->chp), &(p_ptr->chp_frac), new_chp, new_chp_frac); - - - /* Fully healed */ - if (0 < s64b_cmp(p_ptr->chp, p_ptr->chp_frac, p_ptr->mhp, 0)) - { - p_ptr->chp = p_ptr->mhp; - p_ptr->chp_frac = 0; - } - - /* Notice changes */ - if (old_chp != p_ptr->chp) - { - p_ptr->redraw |= (PR_HP); - p_ptr->window |= (PW_PLAYER); - wild_regen = 20; - } -} - - -/*! - * @brief プレイヤーのMP自然回復処理(regen_magic()のサブセット) / Regenerate mana points - * @param upkeep_factor ペット維持によるMPコスト量 - * @param regen_amount 回復量 - * @return なし - */ -static void regenmana(MANA_POINT upkeep_factor, MANA_POINT regen_amount) -{ - MANA_POINT old_csp = p_ptr->csp; - s32b regen_rate = regen_amount * 100 - upkeep_factor * PY_REGEN_NORMAL; - - /* - * Excess mana will decay 32 times faster than normal - * regeneration rate. - */ - if (p_ptr->csp > p_ptr->msp) - { - /* PY_REGEN_NORMAL is the Regen factor in unit (1/2^16) */ - s32b decay = 0; - u32b decay_frac = (p_ptr->msp * 32 * PY_REGEN_NORMAL + PY_REGEN_MNBASE); - - /* Convert the unit (1/2^16) to (1/2^32) */ - s64b_LSHIFT(decay, decay_frac, 16); - - /* Decay */ - s64b_sub(&(p_ptr->csp), &(p_ptr->csp_frac), decay, decay_frac); - - /* Stop decaying */ - if (p_ptr->csp < p_ptr->msp) - { - p_ptr->csp = p_ptr->msp; - p_ptr->csp_frac = 0; - } - } - - /* Regenerating mana (unless the player has excess mana) */ - else if (regen_rate > 0) - { - /* (percent/100) is the Regen factor in unit (1/2^16) */ - MANA_POINT new_mana = 0; - u32b new_mana_frac = (p_ptr->msp * regen_rate / 100 + PY_REGEN_MNBASE); - - /* Convert the unit (1/2^16) to (1/2^32) */ - s64b_LSHIFT(new_mana, new_mana_frac, 16); - - /* Regenerate */ - s64b_add(&(p_ptr->csp), &(p_ptr->csp_frac), new_mana, new_mana_frac); - - /* Must set frac to zero even if equal */ - if (p_ptr->csp >= p_ptr->msp) - { - p_ptr->csp = p_ptr->msp; - p_ptr->csp_frac = 0; - } - } - - - /* Reduce mana (even when the player has excess mana) */ - if (regen_rate < 0) - { - /* PY_REGEN_NORMAL is the Regen factor in unit (1/2^16) */ - s32b reduce_mana = 0; - u32b reduce_mana_frac = (p_ptr->msp * (-1) * regen_rate / 100 + PY_REGEN_MNBASE); - - /* Convert the unit (1/2^16) to (1/2^32) */ - s64b_LSHIFT(reduce_mana, reduce_mana_frac, 16); - - /* Reduce mana */ - s64b_sub(&(p_ptr->csp), &(p_ptr->csp_frac), reduce_mana, reduce_mana_frac); - - /* Check overflow */ - if (p_ptr->csp < 0) - { - p_ptr->csp = 0; - p_ptr->csp_frac = 0; - } - } - - if (old_csp != p_ptr->csp) - { - p_ptr->redraw |= (PR_MANA); - p_ptr->window |= (PW_PLAYER); - p_ptr->window |= (PW_SPELL); - wild_regen = 20; - } -} - -/*! - * @brief プレイヤーのMP自然回復処理 / Regenerate magic regen_amount: PY_REGEN_NORMAL * 2 (if resting) * 2 (if having regenarate) - * @param regen_amount 回復量 - * @return なし - */ -static void regenmagic(int regen_amount) -{ - MANA_POINT new_mana; - int i; - int dev = 30; - int mult = (dev + adj_mag_mana[p_ptr->stat_ind[A_INT]]); /* x1 to x2 speed bonus for recharging */ - - for (i = 0; i < EATER_EXT*2; i++) - { - if (!p_ptr->magic_num2[i]) continue; - if (p_ptr->magic_num1[i] == ((long)p_ptr->magic_num2[i] << 16)) continue; - - /* Increase remaining charge number like float value */ - new_mana = (regen_amount * mult * ((long)p_ptr->magic_num2[i] + 13)) / (dev * 8); - p_ptr->magic_num1[i] += new_mana; - - /* Check maximum charge */ - if (p_ptr->magic_num1[i] > (p_ptr->magic_num2[i] << 16)) - { - p_ptr->magic_num1[i] = ((long)p_ptr->magic_num2[i] << 16); - } - wild_regen = 20; - } - for (i = EATER_EXT*2; i < EATER_EXT*3; i++) - { - if (!p_ptr->magic_num1[i]) continue; - if (!p_ptr->magic_num2[i]) continue; - - /* Decrease remaining period for charging */ - new_mana = (regen_amount * mult * ((long)p_ptr->magic_num2[i] + 10) * EATER_ROD_CHARGE) - / (dev * 16 * PY_REGEN_NORMAL); - p_ptr->magic_num1[i] -= new_mana; - - /* Check minimum remaining period for charging */ - if (p_ptr->magic_num1[i] < 0) p_ptr->magic_num1[i] = 0; - wild_regen = 20; - } -} - - -/*! - * @brief 100ゲームターン毎のモンスターのHP自然回復処理 / Regenerate the monsters (once per 100 game turns) - * @return なし - * @note Should probably be done during monster turns. - */ -static void regen_monsters(void) -{ - int i, frac; - - - /* Regenerate everyone */ - for (i = 1; i < m_max; i++) - { - /* Check the i'th monster */ - monster_type *m_ptr = ¤t_floor_ptr->m_list[i]; - monster_race *r_ptr = &r_info[m_ptr->r_idx]; - - if (!monster_is_valid(m_ptr)) continue; - - /* Allow regeneration (if needed) */ - if (m_ptr->hp < m_ptr->maxhp) - { - /* Hack -- Base regeneration */ - frac = m_ptr->maxhp / 100; - - /* Hack -- Minimal regeneration rate */ - if (!frac) if (one_in_(2)) frac = 1; - - /* Hack -- Some monsters regenerate quickly */ - if (r_ptr->flags2 & RF2_REGENERATE) frac *= 2; - - /* Hack -- Regenerate */ - m_ptr->hp += frac; - - /* Do not over-regenerate */ - if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp; - - /* Redraw (later) if needed */ - if (p_ptr->health_who == i) p_ptr->redraw |= (PR_HEALTH); - if (p_ptr->riding == i) p_ptr->redraw |= (PR_UHEALTH); - } - } -} - - -/*! - * @brief 30ゲームターン毎のボール中モンスターのHP自然回復処理 / Regenerate the captured monsters (once per 30 game turns) - * @return なし - * @note Should probably be done during monster turns. - */ -static void regen_captured_monsters(void) -{ - int i, frac; - bool heal = FALSE; - - /* Regenerate everyone */ - for (i = 0; i < INVEN_TOTAL; i++) - { - monster_race *r_ptr; - object_type *o_ptr = &inventory[i]; - - if (!o_ptr->k_idx) continue; - if (o_ptr->tval != TV_CAPTURE) continue; - if (!o_ptr->pval) continue; - - heal = TRUE; - - r_ptr = &r_info[o_ptr->pval]; - - /* Allow regeneration (if needed) */ - if (o_ptr->xtra4 < o_ptr->xtra5) - { - /* Hack -- Base regeneration */ - frac = o_ptr->xtra5 / 100; - - /* Hack -- Minimal regeneration rate */ - if (!frac) if (one_in_(2)) frac = 1; - - /* Hack -- Some monsters regenerate quickly */ - if (r_ptr->flags2 & RF2_REGENERATE) frac *= 2; - - /* Hack -- Regenerate */ - o_ptr->xtra4 += (XTRA16)frac; - - /* Do not over-regenerate */ - if (o_ptr->xtra4 > o_ptr->xtra5) o_ptr->xtra4 = o_ptr->xtra5; - } - } - - if (heal) - { - /* Combine pack */ - p_ptr->update |= (PU_COMBINE); - p_ptr->window |= (PW_INVEN); - p_ptr->window |= (PW_EQUIP); - wild_regen = 20; - } -} - -/*! - * @brief 寿命つき光源の警告メッセージ処理 - * @param o_ptr 現在光源として使っているオブジェクトの構造体参照ポインタ - * @return なし - */ -static void notice_lite_change(object_type *o_ptr) -{ - /* Hack -- notice interesting fuel steps */ - if ((o_ptr->xtra4 < 100) || (!(o_ptr->xtra4 % 100))) - { - p_ptr->window |= (PW_EQUIP); - } - - /* Hack -- Special treatment when blind */ - if (p_ptr->blind) - { - /* Hack -- save some light for later */ - if (o_ptr->xtra4 == 0) o_ptr->xtra4++; - } - - /* The light is now out */ - else if (o_ptr->xtra4 == 0) - { - disturb(FALSE, TRUE); - msg_print(_("明かりが消えてしまった!", "Your light has gone out!")); - - /* Recalculate torch radius */ - p_ptr->update |= (PU_TORCH); - - /* Some ego light lose its effects without fuel */ - p_ptr->update |= (PU_BONUS); - } - - /* The light is getting dim */ - else if (o_ptr->name2 == EGO_LITE_LONG) - { - if ((o_ptr->xtra4 < 50) && (!(o_ptr->xtra4 % 5)) - && (current_world_ptr->game_turn % (TURNS_PER_TICK*2))) - { - if (disturb_minor) disturb(FALSE, TRUE); - msg_print(_("明かりが微かになってきている。", "Your light is growing faint.")); - } - } - - /* The light is getting dim */ - else if ((o_ptr->xtra4 < 100) && (!(o_ptr->xtra4 % 10))) - { - if (disturb_minor) disturb(FALSE, TRUE); - msg_print(_("明かりが微かになってきている。", "Your light is growing faint.")); - } -} - - -/*! - * @brief !!を刻んだ魔道具の時間経過による再充填を知らせる処理 / If player has inscribed the object with "!!", let him know when it's recharged. -LM- - * @param o_ptr 対象オブジェクトの構造体参照ポインタ - * @return なし - */ -static void recharged_notice(object_type *o_ptr) -{ - GAME_TEXT o_name[MAX_NLEN]; - - concptr s; - - /* No inscription */ - if (!o_ptr->inscription) return; - - /* Find a '!' */ - s = my_strchr(quark_str(o_ptr->inscription), '!'); - - /* Process notification request. */ - while (s) - { - /* Find another '!' */ - if (s[1] == '!') - { - /* Describe (briefly) */ - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - - /* Notify the player */ -#ifdef JP - msg_format("%sは再充填された。", o_name); -#else - if (o_ptr->number > 1) - msg_format("Your %s are recharged.", o_name); - else - msg_format("Your %s is recharged.", o_name); -#endif - - disturb(FALSE, FALSE); - - /* Done. */ - return; - } - - /* Keep looking for '!'s */ - s = my_strchr(s + 1, '!'); - } -} - -/*! - * @brief プレイヤーの歌に関する継続処理 - * @return なし - */ -static void check_music(void) -{ - const magic_type *s_ptr; - int spell; - MANA_POINT need_mana; - u32b need_mana_frac; - - /* Music singed by player */ - if (p_ptr->pclass != CLASS_BARD) return; - if (!SINGING_SONG_EFFECT(p_ptr) && !INTERUPTING_SONG_EFFECT(p_ptr)) return; - - if (p_ptr->anti_magic) - { - stop_singing(p_ptr); - return; - } - - spell = SINGING_SONG_ID(p_ptr); - s_ptr = &technic_info[REALM_MUSIC - MIN_TECHNIC][spell]; - - need_mana = mod_need_mana(s_ptr->smana, spell, REALM_MUSIC); - need_mana_frac = 0; - - /* Divide by 2 */ - s64b_RSHIFT(need_mana, need_mana_frac, 1); - - if (s64b_cmp(p_ptr->csp, p_ptr->csp_frac, need_mana, need_mana_frac) < 0) - { - stop_singing(p_ptr); - return; - } - else - { - s64b_sub(&(p_ptr->csp), &(p_ptr->csp_frac), need_mana, need_mana_frac); - - p_ptr->redraw |= PR_MANA; - if (INTERUPTING_SONG_EFFECT(p_ptr)) - { - SINGING_SONG_EFFECT(p_ptr) = INTERUPTING_SONG_EFFECT(p_ptr); - INTERUPTING_SONG_EFFECT(p_ptr) = MUSIC_NONE; - msg_print(_("歌を再開した。", "You restart singing.")); - p_ptr->action = ACTION_SING; - p_ptr->update |= (PU_BONUS | PU_HP | PU_MONSTERS); - p_ptr->redraw |= (PR_MAP | PR_STATUS | PR_STATE); - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); - } - } - if (p_ptr->spell_exp[spell] < SPELL_EXP_BEGINNER) - p_ptr->spell_exp[spell] += 5; - else if(p_ptr->spell_exp[spell] < SPELL_EXP_SKILLED) - { if (one_in_(2) && (current_floor_ptr->dun_level > 4) && ((current_floor_ptr->dun_level + 10) > p_ptr->lev)) p_ptr->spell_exp[spell] += 1; } - else if(p_ptr->spell_exp[spell] < SPELL_EXP_EXPERT) - { if (one_in_(5) && ((current_floor_ptr->dun_level + 5) > p_ptr->lev) && ((current_floor_ptr->dun_level + 5) > s_ptr->slevel)) p_ptr->spell_exp[spell] += 1; } - else if(p_ptr->spell_exp[spell] < SPELL_EXP_MASTER) - { if (one_in_(5) && ((current_floor_ptr->dun_level + 5) > p_ptr->lev) && (current_floor_ptr->dun_level > s_ptr->slevel)) p_ptr->spell_exp[spell] += 1; } - - /* Do any effects of continual song */ - do_spell(REALM_MUSIC, spell, SPELL_CONT); -} - -/*! - * @brief 現在呪いを保持している装備品を一つランダムに探し出す / Choose one of items that have cursed flag - * @param flag 探し出したい呪いフラグ配列 - * @return 該当の呪いが一つでもあった場合にランダムに選ばれた装備品のオブジェクト構造体参照ポインタを返す。\n - * 呪いがない場合NULLを返す。 - */ -static object_type *choose_cursed_obj_name(BIT_FLAGS flag) -{ - int i; - int choices[INVEN_TOTAL-INVEN_RARM]; - int number = 0; - - /* Paranoia -- Player has no warning-item */ - if (!(p_ptr->cursed & flag)) return NULL; - - /* Search Inventry */ - for (i = INVEN_RARM; i < INVEN_TOTAL; i++) - { - object_type *o_ptr = &inventory[i]; - - if (o_ptr->curse_flags & flag) - { - choices[number] = i; - number++; - } - else if ((flag == TRC_ADD_L_CURSE) || - (flag == TRC_ADD_H_CURSE) || - (flag == TRC_DRAIN_HP) || - (flag == TRC_DRAIN_MANA) || - (flag == TRC_CALL_ANIMAL) || - (flag == TRC_CALL_DEMON) || - (flag == TRC_CALL_DRAGON) || - (flag == TRC_CALL_UNDEAD) || - (flag == TRC_COWARDICE) || - (flag == TRC_LOW_MELEE) || - (flag == TRC_LOW_AC) || - (flag == TRC_LOW_MAGIC) || - (flag == TRC_FAST_DIGEST) || - (flag == TRC_SLOW_REGEN) ) - { - u32b cf = 0L; - BIT_FLAGS flgs[TR_FLAG_SIZE]; - object_flags(o_ptr, flgs); - switch (flag) - { - case TRC_ADD_L_CURSE : cf = TR_ADD_L_CURSE; break; - case TRC_ADD_H_CURSE : cf = TR_ADD_H_CURSE; break; - case TRC_DRAIN_HP : cf = TR_DRAIN_HP; break; - case TRC_DRAIN_MANA : cf = TR_DRAIN_MANA; break; - case TRC_CALL_ANIMAL : cf = TR_CALL_ANIMAL; break; - case TRC_CALL_DEMON : cf = TR_CALL_DEMON; break; - case TRC_CALL_DRAGON : cf = TR_CALL_DRAGON; break; - case TRC_CALL_UNDEAD : cf = TR_CALL_UNDEAD; break; - case TRC_COWARDICE : cf = TR_COWARDICE; break; - case TRC_LOW_MELEE : cf = TR_LOW_MELEE; break; - case TRC_LOW_AC : cf = TR_LOW_AC; break; - case TRC_LOW_MAGIC : cf = TR_LOW_MAGIC; break; - case TRC_FAST_DIGEST : cf = TR_FAST_DIGEST; break; - case TRC_SLOW_REGEN : cf = TR_SLOW_REGEN; break; - default : break; - } - if (have_flag(flgs, cf)) - { - choices[number] = i; - number++; - } - } - } - - /* Choice one of them */ - return (&inventory[choices[randint0(number)]]); -} - -static void process_world_aux_digestion(void) -{ - if (!p_ptr->inside_battle) - { - /* Digest quickly when gorged */ - if (p_ptr->food >= PY_FOOD_MAX) - { - /* Digest a lot of food */ - (void)set_food(p_ptr->food - 100); - } - - /* Digest normally -- Every 50 game turns */ - else if (!(current_world_ptr->game_turn % (TURNS_PER_TICK * 5))) - { - /* Basic digestion rate based on speed */ - int digestion = SPEED_TO_ENERGY(p_ptr->pspeed); - - /* Regeneration takes more food */ - if (p_ptr->regenerate) - digestion += 20; - if (p_ptr->special_defense & (KAMAE_MASK | KATA_MASK)) - digestion += 20; - if (p_ptr->cursed & TRC_FAST_DIGEST) - digestion += 30; - - /* Slow digestion takes less food */ - if (p_ptr->slow_digest) - digestion -= 5; - - /* Minimal digestion */ - if (digestion < 1) digestion = 1; - /* Maximal digestion */ - if (digestion > 100) digestion = 100; - - /* Digest some food */ - (void)set_food(p_ptr->food - digestion); - } - - - /* Getting Faint */ - if ((p_ptr->food < PY_FOOD_FAINT)) - { - /* Faint occasionally */ - if (!p_ptr->paralyzed && (randint0(100) < 10)) - { - msg_print(_("あまりにも空腹で気絶してしまった。", "You faint from the lack of food.")); - disturb(TRUE, TRUE); - - /* Hack -- faint (bypass free action) */ - (void)set_paralyzed(p_ptr->paralyzed + 1 + randint0(5)); - } - - /* Starve to death (slowly) */ - if (p_ptr->food < PY_FOOD_STARVE) - { - /* Calculate damage */ - HIT_POINT dam = (PY_FOOD_STARVE - p_ptr->food) / 10; - - if (!IS_INVULN()) take_hit(DAMAGE_LOSELIFE, dam, _("空腹", "starvation"), -1); - } - } - } -} - -/*! - * @brief 10ゲームターンが進行するごとにプレイヤーのHPとMPの増減処理を行う。 - * / Handle timed damage and regeneration every 10 game turns - * @return なし - */ -static void process_world_aux_hp_and_sp(void) -{ - feature_type *f_ptr = &f_info[current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].feat]; - bool cave_no_regen = FALSE; - int upkeep_factor = 0; - - /* Default regeneration */ - int regen_amount = PY_REGEN_NORMAL; - - - /*** Damage over Time ***/ - - /* Take damage from poison */ - if (p_ptr->poisoned && !IS_INVULN()) - { - take_hit(DAMAGE_NOESCAPE, 1, _("毒", "poison"), -1); - } - - /* Take damage from cuts */ - if (p_ptr->cut && !IS_INVULN()) - { - HIT_POINT dam; - - /* Mortal wound or Deep Gash */ - if (p_ptr->cut > 1000) - { - dam = 200; - } - - else if (p_ptr->cut > 200) - { - dam = 80; - } - - /* Severe cut */ - else if (p_ptr->cut > 100) - { - dam = 32; - } - - else if (p_ptr->cut > 50) - { - dam = 16; - } - - else if (p_ptr->cut > 25) - { - dam = 7; - } - - else if (p_ptr->cut > 10) - { - dam = 3; - } - - /* Other cuts */ - else - { - dam = 1; - } - - take_hit(DAMAGE_NOESCAPE, dam, _("致命傷", "a fatal wound"), -1); - } - - /* (Vampires) Take damage from sunlight */ - if (prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE)) - { - if (!current_floor_ptr->dun_level && !p_ptr->resist_lite && !IS_INVULN() && is_daytime()) - { - if ((current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW) - { - msg_print(_("日光があなたのアンデッドの肉体を焼き焦がした!", "The sun's rays scorch your undead flesh!")); - take_hit(DAMAGE_NOESCAPE, 1, _("日光", "sunlight"), -1); - cave_no_regen = TRUE; - } - } - - if (inventory[INVEN_LITE].tval && (inventory[INVEN_LITE].name2 != EGO_LITE_DARKNESS) && - !p_ptr->resist_lite) - { - object_type * o_ptr = &inventory[INVEN_LITE]; - GAME_TEXT o_name [MAX_NLEN]; - char ouch [MAX_NLEN+40]; - - /* Get an object description */ - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - msg_format(_("%sがあなたのアンデッドの肉体を焼き焦がした!", "The %s scorches your undead flesh!"), o_name); - - cave_no_regen = TRUE; - - /* Get an object description */ - object_desc(o_name, o_ptr, OD_NAME_ONLY); - sprintf(ouch, _("%sを装備したダメージ", "wielding %s"), o_name); - - if (!IS_INVULN()) take_hit(DAMAGE_NOESCAPE, 1, ouch, -1); - } - } - - if (have_flag(f_ptr->flags, FF_LAVA) && !IS_INVULN() && !p_ptr->immune_fire) - { - int damage = 0; - - if (have_flag(f_ptr->flags, FF_DEEP)) - { - damage = 6000 + randint0(4000); - } - else if (!p_ptr->levitation) - { - damage = 3000 + randint0(2000); - } - - if (damage) - { - if(prace_is_(RACE_ENT)) damage += damage / 3; - if(p_ptr->resist_fire) damage = damage / 3; - if(IS_OPPOSE_FIRE()) damage = damage / 3; - if(p_ptr->levitation) damage = damage / 5; - - damage = damage / 100 + (randint0(100) < (damage % 100)); - - if (p_ptr->levitation) - { - msg_print(_("熱で火傷した!", "The heat burns you!")); - take_hit(DAMAGE_NOESCAPE, damage, format(_("%sの上に浮遊したダメージ", "flying over %s"), - f_name + f_info[get_feat_mimic(¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x])].name), -1); - } - else - { - concptr name = f_name + f_info[get_feat_mimic(¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x])].name; - msg_format(_("%sで火傷した!", "The %s burns you!"), name); - take_hit(DAMAGE_NOESCAPE, damage, name, -1); - } - - cave_no_regen = TRUE; - } - } - - if (have_flag(f_ptr->flags, FF_COLD_PUDDLE) && !IS_INVULN() && !p_ptr->immune_cold) - { - int damage = 0; - - if (have_flag(f_ptr->flags, FF_DEEP)) - { - damage = 6000 + randint0(4000); - } - else if (!p_ptr->levitation) - { - damage = 3000 + randint0(2000); - } - - if (damage) - { - if (p_ptr->resist_cold) damage = damage / 3; - if (IS_OPPOSE_COLD()) damage = damage / 3; - if (p_ptr->levitation) damage = damage / 5; - - damage = damage / 100 + (randint0(100) < (damage % 100)); - - if (p_ptr->levitation) - { - msg_print(_("冷気に覆われた!", "The cold engulfs you!")); - take_hit(DAMAGE_NOESCAPE, damage, format(_("%sの上に浮遊したダメージ", "flying over %s"), - f_name + f_info[get_feat_mimic(¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x])].name), -1); - } - else - { - concptr name = f_name + f_info[get_feat_mimic(¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x])].name; - msg_format(_("%sに凍えた!", "The %s frostbites you!"), name); - take_hit(DAMAGE_NOESCAPE, damage, name, -1); - } - - cave_no_regen = TRUE; - } - } - - if (have_flag(f_ptr->flags, FF_ELEC_PUDDLE) && !IS_INVULN() && !p_ptr->immune_elec) - { - int damage = 0; - - if (have_flag(f_ptr->flags, FF_DEEP)) - { - damage = 6000 + randint0(4000); - } - else if (!p_ptr->levitation) - { - damage = 3000 + randint0(2000); - } - - if (damage) - { - if (p_ptr->resist_elec) damage = damage / 3; - if (IS_OPPOSE_ELEC()) damage = damage / 3; - if (p_ptr->levitation) damage = damage / 5; - - damage = damage / 100 + (randint0(100) < (damage % 100)); - - if (p_ptr->levitation) - { - msg_print(_("電撃を受けた!", "The electric shocks you!")); - take_hit(DAMAGE_NOESCAPE, damage, format(_("%sの上に浮遊したダメージ", "flying over %s"), - f_name + f_info[get_feat_mimic(¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x])].name), -1); - } - else - { - concptr name = f_name + f_info[get_feat_mimic(¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x])].name; - msg_format(_("%sに感電した!", "The %s shocks you!"), name); - take_hit(DAMAGE_NOESCAPE, damage, name, -1); - } - - cave_no_regen = TRUE; - } - } - - if (have_flag(f_ptr->flags, FF_ACID_PUDDLE) && !IS_INVULN() && !p_ptr->immune_acid) - { - int damage = 0; - - if (have_flag(f_ptr->flags, FF_DEEP)) - { - damage = 6000 + randint0(4000); - } - else if (!p_ptr->levitation) - { - damage = 3000 + randint0(2000); - } - - if (damage) - { - if (p_ptr->resist_acid) damage = damage / 3; - if (IS_OPPOSE_ACID()) damage = damage / 3; - if (p_ptr->levitation) damage = damage / 5; - - damage = damage / 100 + (randint0(100) < (damage % 100)); - - if (p_ptr->levitation) - { - msg_print(_("酸が飛び散った!", "The acid melt you!")); - take_hit(DAMAGE_NOESCAPE, damage, format(_("%sの上に浮遊したダメージ", "flying over %s"), - f_name + f_info[get_feat_mimic(¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x])].name), -1); - } - else - { - concptr name = f_name + f_info[get_feat_mimic(¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x])].name; - msg_format(_("%sに溶かされた!", "The %s melts you!"), name); - take_hit(DAMAGE_NOESCAPE, damage, name, -1); - } - - cave_no_regen = TRUE; - } - } - - if (have_flag(f_ptr->flags, FF_POISON_PUDDLE) && !IS_INVULN()) - { - int damage = 0; - - if (have_flag(f_ptr->flags, FF_DEEP)) - { - damage = 6000 + randint0(4000); - } - else if (!p_ptr->levitation) - { - damage = 3000 + randint0(2000); - } - - if (damage) - { - if (p_ptr->resist_pois) damage = damage / 3; - if (IS_OPPOSE_POIS()) damage = damage / 3; - if (p_ptr->levitation) damage = damage / 5; - - damage = damage / 100 + (randint0(100) < (damage % 100)); - - if (p_ptr->levitation) - { - msg_print(_("毒気を吸い込んだ!", "The gas poisons you!")); - take_hit(DAMAGE_NOESCAPE, damage, format(_("%sの上に浮遊したダメージ", "flying over %s"), - f_name + f_info[get_feat_mimic(¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x])].name), -1); - if (p_ptr->resist_pois) (void)set_poisoned(p_ptr->poisoned + 1); - } - else - { - concptr name = f_name + f_info[get_feat_mimic(¤t_floor_ptr->grid_array[p_ptr->y][p_ptr->x])].name; - msg_format(_("%sに毒された!", "The %s poisons you!"), name); - take_hit(DAMAGE_NOESCAPE, damage, name, -1); - if (p_ptr->resist_pois) (void)set_poisoned(p_ptr->poisoned + 3); - } - - cave_no_regen = TRUE; - } - } - - if (have_flag(f_ptr->flags, FF_WATER) && have_flag(f_ptr->flags, FF_DEEP) && - !p_ptr->levitation && !p_ptr->can_swim && !p_ptr->resist_water) - { - if (p_ptr->total_weight > weight_limit()) - { - msg_print(_("溺れている!", "You are drowning!")); - take_hit(DAMAGE_NOESCAPE, randint1(p_ptr->lev), _("溺れ", "drowning"), -1); - cave_no_regen = TRUE; - } - } - - if (p_ptr->riding) - { - HIT_POINT damage; - if ((r_info[current_floor_ptr->m_list[p_ptr->riding].r_idx].flags2 & RF2_AURA_FIRE) && !p_ptr->immune_fire) - { - damage = r_info[current_floor_ptr->m_list[p_ptr->riding].r_idx].level / 2; - if (prace_is_(RACE_ENT)) damage += damage / 3; - if (p_ptr->resist_fire) damage = damage / 3; - if (IS_OPPOSE_FIRE()) damage = damage / 3; - msg_print(_("熱い!", "It's hot!")); - take_hit(DAMAGE_NOESCAPE, damage, _("炎のオーラ", "Fire aura"), -1); - } - if ((r_info[current_floor_ptr->m_list[p_ptr->riding].r_idx].flags2 & RF2_AURA_ELEC) && !p_ptr->immune_elec) - { - damage = r_info[current_floor_ptr->m_list[p_ptr->riding].r_idx].level / 2; - if (prace_is_(RACE_ANDROID)) damage += damage / 3; - if (p_ptr->resist_elec) damage = damage / 3; - if (IS_OPPOSE_ELEC()) damage = damage / 3; - msg_print(_("痛い!", "It hurts!")); - take_hit(DAMAGE_NOESCAPE, damage, _("電気のオーラ", "Elec aura"), -1); - } - if ((r_info[current_floor_ptr->m_list[p_ptr->riding].r_idx].flags3 & RF3_AURA_COLD) && !p_ptr->immune_cold) - { - damage = r_info[current_floor_ptr->m_list[p_ptr->riding].r_idx].level / 2; - if (p_ptr->resist_cold) damage = damage / 3; - if (IS_OPPOSE_COLD()) damage = damage / 3; - msg_print(_("冷たい!", "It's cold!")); - take_hit(DAMAGE_NOESCAPE, damage, _("冷気のオーラ", "Cold aura"), -1); - } - } - - /* Spectres -- take damage when moving through walls */ - /* - * Added: ANYBODY takes damage if inside through walls - * without wraith form -- NOTE: Spectres will never be - * reduced below 0 hp by being inside a stone wall; others - * WILL BE! - */ - if (!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) - { - if (!IS_INVULN() && !p_ptr->wraith_form && !p_ptr->kabenuke && ((p_ptr->chp > (p_ptr->lev / 5)) || !p_ptr->pass_wall)) - { - concptr dam_desc; - cave_no_regen = TRUE; - - if (p_ptr->pass_wall) - { - msg_print(_("体の分子が分解した気がする!", "Your molecules feel disrupted!")); - dam_desc = _("密度", "density"); - } - else - { - msg_print(_("崩れた岩に押し潰された!", "You are being crushed!")); - dam_desc = _("硬い岩", "solid rock"); - } - - take_hit(DAMAGE_NOESCAPE, 1 + (p_ptr->lev / 5), dam_desc, -1); - } - } - - - /*** handle regeneration ***/ - - /* Getting Weak */ - if (p_ptr->food < PY_FOOD_WEAK) - { - /* Lower regeneration */ - if (p_ptr->food < PY_FOOD_STARVE) - { - regen_amount = 0; - } - else if (p_ptr->food < PY_FOOD_FAINT) - { - regen_amount = PY_REGEN_FAINT; - } - else - { - regen_amount = PY_REGEN_WEAK; - } - } - - /* Are we walking the pattern? */ - if (pattern_effect()) - { - cave_no_regen = TRUE; - } - else - { - /* Regeneration ability */ - if (p_ptr->regenerate) - { - regen_amount = regen_amount * 2; - } - if (p_ptr->special_defense & (KAMAE_MASK | KATA_MASK)) - { - regen_amount /= 2; - } - if (p_ptr->cursed & TRC_SLOW_REGEN) - { - regen_amount /= 5; - } - } - - - /* Searching or Resting */ - if ((p_ptr->action == ACTION_SEARCH) || (p_ptr->action == ACTION_REST)) - { - regen_amount = regen_amount * 2; - } - - upkeep_factor = calculate_upkeep(); - - /* No regeneration while special action */ - if ((p_ptr->action == ACTION_LEARN) || - (p_ptr->action == ACTION_HAYAGAKE) || - (p_ptr->special_defense & KATA_KOUKIJIN)) - { - upkeep_factor += 100; - } - - /* Regenerate the mana */ - regenmana(upkeep_factor, regen_amount); - - - /* Recharge magic eater's power */ - if (p_ptr->pclass == CLASS_MAGIC_EATER) - { - regenmagic(regen_amount); - } - - if ((p_ptr->csp == 0) && (p_ptr->csp_frac == 0)) - { - while (upkeep_factor > 100) - { - msg_print(_("こんなに多くのペットを制御できない!", "Too many pets to control at once!")); - msg_print(NULL); - do_cmd_pet_dismiss(); - - upkeep_factor = calculate_upkeep(); - - msg_format(_("維持MPは %d%%", "Upkeep: %d%% mana."), upkeep_factor); - msg_print(NULL); - } - } - - /* Poisoned or cut yields no healing */ - if (p_ptr->poisoned) regen_amount = 0; - if (p_ptr->cut) regen_amount = 0; - - /* Special floor -- Pattern, in a wall -- yields no healing */ - if (cave_no_regen) regen_amount = 0; - - regen_amount = (regen_amount * p_ptr->mutant_regenerate_mod) / 100; - - /* Regenerate Hit Points if needed */ - if ((p_ptr->chp < p_ptr->mhp) && !cave_no_regen) - { - regenhp(regen_amount); - } -} - -/*! - * @brief 10ゲームターンが進行するごとに魔法効果の残りターンを減らしていく処理 - * / Handle timeout every 10 game turns - * @return なし - */ -static void process_world_aux_timeout(void) -{ - const int dec_count = (easy_band ? 2 : 1); - - /*** Timeout Various Things ***/ - - /* Mimic */ - if (p_ptr->tim_mimic) - { - (void)set_mimic(p_ptr->tim_mimic - 1, p_ptr->mimic_form, TRUE); - } - - /* Hack -- Hallucinating */ - if (p_ptr->image) - { - (void)set_image(p_ptr->image - dec_count); - } - - /* Blindness */ - if (p_ptr->blind) - { - (void)set_blind(p_ptr->blind - dec_count); - } - - /* Times see-invisible */ - if (p_ptr->tim_invis) - { - (void)set_tim_invis(p_ptr->tim_invis - 1, TRUE); - } - - if (multi_rew) - { - multi_rew = FALSE; - } - - /* Timed esp */ - if (p_ptr->tim_esp) - { - (void)set_tim_esp(p_ptr->tim_esp - 1, TRUE); - } - - /* Timed temporary elemental brands. -LM- */ - if (p_ptr->ele_attack) - { - p_ptr->ele_attack--; - - /* Clear all temporary elemental brands. */ - if (!p_ptr->ele_attack) set_ele_attack(0, 0); - } - - /* Timed temporary elemental immune. -LM- */ - if (p_ptr->ele_immune) - { - p_ptr->ele_immune--; - - /* Clear all temporary elemental brands. */ - if (!p_ptr->ele_immune) set_ele_immune(0, 0); - } - - /* Timed infra-vision */ - if (p_ptr->tim_infra) - { - (void)set_tim_infra(p_ptr->tim_infra - 1, TRUE); - } - - /* Timed stealth */ - if (p_ptr->tim_stealth) - { - (void)set_tim_stealth(p_ptr->tim_stealth - 1, TRUE); - } - - /* Timed levitation */ - if (p_ptr->tim_levitation) - { - (void)set_tim_levitation(p_ptr->tim_levitation - 1, TRUE); - } - - /* Timed sh_touki */ - if (p_ptr->tim_sh_touki) - { - (void)set_tim_sh_touki(p_ptr->tim_sh_touki - 1, TRUE); - } - - /* Timed sh_fire */ - if (p_ptr->tim_sh_fire) - { - (void)set_tim_sh_fire(p_ptr->tim_sh_fire - 1, TRUE); - } - - /* Timed sh_holy */ - if (p_ptr->tim_sh_holy) - { - (void)set_tim_sh_holy(p_ptr->tim_sh_holy - 1, TRUE); - } - - /* Timed eyeeye */ - if (p_ptr->tim_eyeeye) - { - (void)set_tim_eyeeye(p_ptr->tim_eyeeye - 1, TRUE); - } - - /* Timed resist-magic */ - if (p_ptr->resist_magic) - { - (void)set_resist_magic(p_ptr->resist_magic - 1, TRUE); - } - - /* Timed regeneration */ - if (p_ptr->tim_regen) - { - (void)set_tim_regen(p_ptr->tim_regen - 1, TRUE); - } - - /* Timed resist nether */ - if (p_ptr->tim_res_nether) - { - (void)set_tim_res_nether(p_ptr->tim_res_nether - 1, TRUE); - } - - /* Timed resist time */ - if (p_ptr->tim_res_time) - { - (void)set_tim_res_time(p_ptr->tim_res_time - 1, TRUE); - } - - /* Timed reflect */ - if (p_ptr->tim_reflect) - { - (void)set_tim_reflect(p_ptr->tim_reflect - 1, TRUE); - } - - /* Multi-shadow */ - if (p_ptr->multishadow) - { - (void)set_multishadow(p_ptr->multishadow - 1, TRUE); - } - - /* Timed Robe of dust */ - if (p_ptr->dustrobe) - { - (void)set_dustrobe(p_ptr->dustrobe - 1, TRUE); - } - - /* Timed infra-vision */ - if (p_ptr->kabenuke) - { - (void)set_kabenuke(p_ptr->kabenuke - 1, TRUE); - } - - /* Paralysis */ - if (p_ptr->paralyzed) - { - (void)set_paralyzed(p_ptr->paralyzed - dec_count); - } - - /* Confusion */ - if (p_ptr->confused) - { - (void)set_confused(p_ptr->confused - dec_count); - } - - /* Afraid */ - if (p_ptr->afraid) - { - (void)set_afraid(p_ptr->afraid - dec_count); - } - - /* Fast */ - if (p_ptr->fast) - { - (void)set_fast(p_ptr->fast - 1, TRUE); - } - - /* Slow */ - if (p_ptr->slow) - { - (void)set_slow(p_ptr->slow - dec_count, TRUE); - } - - /* Protection from evil */ - if (p_ptr->protevil) - { - (void)set_protevil(p_ptr->protevil - 1, TRUE); - } - - /* Invulnerability */ - if (p_ptr->invuln) - { - (void)set_invuln(p_ptr->invuln - 1, TRUE); - } - - /* Wraith form */ - if (p_ptr->wraith_form) - { - (void)set_wraith_form(p_ptr->wraith_form - 1, TRUE); - } - - /* Heroism */ - if (p_ptr->hero) - { - (void)set_hero(p_ptr->hero - 1, TRUE); - } - - /* Super Heroism */ - if (p_ptr->shero) - { - (void)set_shero(p_ptr->shero - 1, TRUE); - } - - /* Blessed */ - if (p_ptr->blessed) - { - (void)set_blessed(p_ptr->blessed - 1, TRUE); - } - - /* Shield */ - if (p_ptr->shield) - { - (void)set_shield(p_ptr->shield - 1, TRUE); - } - - /* Tsubureru */ - if (p_ptr->tsubureru) - { - (void)set_tsubureru(p_ptr->tsubureru - 1, TRUE); - } - - /* Magicdef */ - if (p_ptr->magicdef) - { - (void)set_magicdef(p_ptr->magicdef - 1, TRUE); - } - - /* Tsuyoshi */ - if (p_ptr->tsuyoshi) - { - (void)set_tsuyoshi(p_ptr->tsuyoshi - 1, TRUE); - } - - /* Oppose Acid */ - if (p_ptr->oppose_acid) - { - (void)set_oppose_acid(p_ptr->oppose_acid - 1, TRUE); - } - - /* Oppose Lightning */ - if (p_ptr->oppose_elec) - { - (void)set_oppose_elec(p_ptr->oppose_elec - 1, TRUE); - } - - /* Oppose Fire */ - if (p_ptr->oppose_fire) - { - (void)set_oppose_fire(p_ptr->oppose_fire - 1, TRUE); - } - - /* Oppose Cold */ - if (p_ptr->oppose_cold) - { - (void)set_oppose_cold(p_ptr->oppose_cold - 1, TRUE); - } - - /* Oppose Poison */ - if (p_ptr->oppose_pois) - { - (void)set_oppose_pois(p_ptr->oppose_pois - 1, TRUE); - } - - if (p_ptr->ult_res) - { - (void)set_ultimate_res(p_ptr->ult_res - 1, TRUE); - } - - /*** Poison and Stun and Cut ***/ - - /* Poison */ - if (p_ptr->poisoned) - { - int adjust = adj_con_fix[p_ptr->stat_ind[A_CON]] + 1; - - /* Apply some healing */ - (void)set_poisoned(p_ptr->poisoned - adjust); - } - - /* Stun */ - if (p_ptr->stun) - { - int adjust = adj_con_fix[p_ptr->stat_ind[A_CON]] + 1; - - /* Apply some healing */ - (void)set_stun(p_ptr->stun - adjust); - } - - /* Cut */ - if (p_ptr->cut) - { - int adjust = adj_con_fix[p_ptr->stat_ind[A_CON]] + 1; - - /* Hack -- Truly "mortal" wound */ - if (p_ptr->cut > 1000) adjust = 0; - - /* Apply some healing */ - (void)set_cut(p_ptr->cut - adjust); - } -} - - -/*! - * @brief 10ゲームターンが進行する毎に光源の寿命を減らす処理 - * / Handle burning fuel every 10 game turns - * @return なし - */ -static void process_world_aux_light(void) -{ - /* Check for light being wielded */ - object_type *o_ptr = &inventory[INVEN_LITE]; - - /* Burn some fuel in the current lite */ - if (o_ptr->tval == TV_LITE) - { - /* Hack -- Use some fuel (except on artifacts) */ - if (!(object_is_fixed_artifact(o_ptr) || o_ptr->sval == SV_LITE_FEANOR) && (o_ptr->xtra4 > 0)) - { - /* Decrease life-span */ - if (o_ptr->name2 == EGO_LITE_LONG) - { - if (current_world_ptr->game_turn % (TURNS_PER_TICK*2)) o_ptr->xtra4--; - } - else o_ptr->xtra4--; - - /* Notice interesting fuel steps */ - notice_lite_change(o_ptr); - } - } -} - - -/*! - * @brief 10ゲームターンが進行するごとに突然変異の発動判定を行う処理 - * / Handle mutation effects once every 10 game turns - * @return なし - */ -static void process_world_aux_mutation(void) -{ - /* No mutation with effects */ - if (!p_ptr->muta2) return; - - /* No effect on monster arena */ - if (p_ptr->inside_battle) return; - - /* No effect on the global map */ - if (p_ptr->wild_mode) return; - - if ((p_ptr->muta2 & MUT2_BERS_RAGE) && one_in_(3000)) - { - disturb(FALSE, TRUE); - msg_print(_("ウガァァア!", "RAAAAGHH!")); - msg_print(_("激怒の発作に襲われた!", "You feel a fit of rage coming over you!")); - (void)set_shero(10 + randint1(p_ptr->lev), FALSE); - (void)set_afraid(0); - } - - if ((p_ptr->muta2 & MUT2_COWARDICE) && (randint1(3000) == 13)) - { - if (!p_ptr->resist_fear) - { - disturb(FALSE, TRUE); - msg_print(_("とても暗い... とても恐い!", "It's so dark... so scary!")); - set_afraid(p_ptr->afraid + 13 + randint1(26)); - } - } - - if ((p_ptr->muta2 & MUT2_RTELEPORT) && (randint1(5000) == 88)) - { - if (!p_ptr->resist_nexus && !(p_ptr->muta1 & MUT1_VTELEPORT) && !p_ptr->anti_tele) - { - disturb(FALSE, TRUE); - msg_print(_("あなたの位置は突然ひじょうに不確定になった...", "Your position suddenly seems very uncertain...")); - msg_print(NULL); - teleport_player(40, TELEPORT_PASSIVE); - } - } - - if ((p_ptr->muta2 & MUT2_ALCOHOL) && (randint1(6400) == 321)) - { - if (!p_ptr->resist_conf && !p_ptr->resist_chaos) - { - disturb(FALSE, TRUE); - p_ptr->redraw |= PR_EXTRA; - msg_print(_("いひきがもーろーとひてきたきがふる...ヒック!", "You feel a SSSCHtupor cOmINg over yOu... *HIC*!")); - } - - if (!p_ptr->resist_conf) - { - (void)set_confused(p_ptr->confused + randint0(20) + 15); - } - - if (!p_ptr->resist_chaos) - { - if (one_in_(20)) - { - msg_print(NULL); - if (one_in_(3)) lose_all_info(); - else wiz_dark(); - (void)teleport_player_aux(100, TELEPORT_NONMAGICAL | TELEPORT_PASSIVE); - wiz_dark(); - msg_print(_("あなたは見知らぬ場所で目が醒めた...頭が痛い。", "You wake up somewhere with a sore head...")); - msg_print(_("何も覚えていない。どうやってここに来たかも分からない!", "You can't remember a thing, or how you got here!")); - } - else - { - if (one_in_(3)) - { - msg_print(_("き~れいなちょおちょらとんれいる~", "Thishcischs GooDSChtuff!")); - (void)set_image(p_ptr->image + randint0(150) + 150); - } - } - } - } - - if ((p_ptr->muta2 & MUT2_HALLU) && (randint1(6400) == 42)) - { - if (!p_ptr->resist_chaos) - { - disturb(FALSE, TRUE); - p_ptr->redraw |= PR_EXTRA; - (void)set_image(p_ptr->image + randint0(50) + 20); - } - } - - if ((p_ptr->muta2 & MUT2_FLATULENT) && (randint1(3000) == 13)) - { - disturb(FALSE, TRUE); - msg_print(_("ブゥーーッ!おっと。", "BRRAAAP! Oops.")); - msg_print(NULL); - fire_ball(GF_POIS, 0, p_ptr->lev, 3); - } - - if ((p_ptr->muta2 & MUT2_PROD_MANA) && - !p_ptr->anti_magic && one_in_(9000)) - { - int dire = 0; - disturb(FALSE, TRUE); - msg_print(_("魔法のエネルギーが突然あなたの中に流れ込んできた!エネルギーを解放しなければならない!", - "Magical energy flows through you! You must release it!")); - - flush(); - msg_print(NULL); - (void)get_hack_dir(&dire); - fire_ball(GF_MANA, dire, p_ptr->lev * 2, 3); - } - - if ((p_ptr->muta2 & MUT2_ATT_DEMON) && !p_ptr->anti_magic && (randint1(6666) == 666)) - { - bool pet = one_in_(6); - BIT_FLAGS mode = PM_ALLOW_GROUP; - - if (pet) mode |= PM_FORCE_PET; - else mode |= (PM_ALLOW_UNIQUE | PM_NO_PET); - - if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, SUMMON_DEMON, mode, '\0')) - { - msg_print(_("あなたはデーモンを引き寄せた!", "You have attracted a demon!")); - disturb(FALSE, TRUE); - } - } - - if ((p_ptr->muta2 & MUT2_SPEED_FLUX) && one_in_(6000)) - { - disturb(FALSE, TRUE); - if (one_in_(2)) - { - msg_print(_("精力的でなくなった気がする。", "You feel less energetic.")); - - if (p_ptr->fast > 0) - { - set_fast(0, TRUE); - } - else - { - set_slow(randint1(30) + 10, FALSE); - } - } - else - { - msg_print(_("精力的になった気がする。", "You feel more energetic.")); - - if (p_ptr->slow > 0) - { - set_slow(0, TRUE); - } - else - { - set_fast(randint1(30) + 10, FALSE); - } - } - msg_print(NULL); - } - if ((p_ptr->muta2 & MUT2_BANISH_ALL) && one_in_(9000)) - { - disturb(FALSE, TRUE); - msg_print(_("突然ほとんど孤独になった気がする。", "You suddenly feel almost lonely.")); - - banish_monsters(100); - if (!current_floor_ptr->dun_level && p_ptr->town_num) - { - int n; - - /* Pick a random shop (except home) */ - do - { - n = randint0(MAX_STORES); - } - while ((n == STORE_HOME) || (n == STORE_MUSEUM)); - - msg_print(_("店の主人が丘に向かって走っている!", "You see one of the shopkeepers running for the hills!")); - store_shuffle(n); - } - msg_print(NULL); - } - - if ((p_ptr->muta2 & MUT2_EAT_LIGHT) && one_in_(3000)) - { - object_type *o_ptr; - - msg_print(_("影につつまれた。", "A shadow passes over you.")); - msg_print(NULL); - - /* Absorb light from the current possition */ - if ((current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW) - { - hp_player(10); - } - - o_ptr = &inventory[INVEN_LITE]; - - /* Absorb some fuel in the current lite */ - if (o_ptr->tval == TV_LITE) - { - /* Use some fuel (except on artifacts) */ - if (!object_is_fixed_artifact(o_ptr) && (o_ptr->xtra4 > 0)) - { - /* Heal the player a bit */ - hp_player(o_ptr->xtra4 / 20); - - /* Decrease life-span of lite */ - o_ptr->xtra4 /= 2; - msg_print(_("光源からエネルギーを吸収した!", "You absorb energy from your light!")); - - /* Notice interesting fuel steps */ - notice_lite_change(o_ptr); - } - } - - /* - * Unlite the area (radius 10) around player and - * do 50 points damage to every affected monster - */ - unlite_area(50, 10); - } - - if ((p_ptr->muta2 & MUT2_ATT_ANIMAL) && !p_ptr->anti_magic && one_in_(7000)) - { - bool pet = one_in_(3); - BIT_FLAGS mode = PM_ALLOW_GROUP; - - if (pet) mode |= PM_FORCE_PET; - else mode |= (PM_ALLOW_UNIQUE | PM_NO_PET); - - if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, SUMMON_ANIMAL, mode, '\0')) - { - msg_print(_("動物を引き寄せた!", "You have attracted an animal!")); - disturb(FALSE, TRUE); - } - } - - if ((p_ptr->muta2 & MUT2_RAW_CHAOS) && !p_ptr->anti_magic && one_in_(8000)) - { - disturb(FALSE, TRUE); - msg_print(_("周りの空間が歪んでいる気がする!", "You feel the world warping around you!")); - - msg_print(NULL); - fire_ball(GF_CHAOS, 0, p_ptr->lev, 8); - } - if ((p_ptr->muta2 & MUT2_NORMALITY) && one_in_(5000)) - { - if (!lose_mutation(0)) - msg_print(_("奇妙なくらい普通になった気がする。", "You feel oddly normal.")); - } - if ((p_ptr->muta2 & MUT2_WRAITH) && !p_ptr->anti_magic && one_in_(3000)) - { - disturb(FALSE, TRUE); - msg_print(_("非物質化した!", "You feel insubstantial!")); - - msg_print(NULL); - set_wraith_form(randint1(p_ptr->lev / 2) + (p_ptr->lev / 2), FALSE); - } - if ((p_ptr->muta2 & MUT2_POLY_WOUND) && one_in_(3000)) - { - do_poly_wounds(); - } - if ((p_ptr->muta2 & MUT2_WASTING) && one_in_(3000)) - { - int which_stat = randint0(A_MAX); - int sustained = FALSE; - - switch (which_stat) - { - case A_STR: - if (p_ptr->sustain_str) sustained = TRUE; - break; - case A_INT: - if (p_ptr->sustain_int) sustained = TRUE; - break; - case A_WIS: - if (p_ptr->sustain_wis) sustained = TRUE; - break; - case A_DEX: - if (p_ptr->sustain_dex) sustained = TRUE; - break; - case A_CON: - if (p_ptr->sustain_con) sustained = TRUE; - break; - case A_CHR: - if (p_ptr->sustain_chr) sustained = TRUE; - break; - default: - msg_print(_("不正な状態!", "Invalid stat chosen!")); - sustained = TRUE; - } - - if (!sustained) - { - disturb(FALSE, TRUE); - msg_print(_("自分が衰弱していくのが分かる!", "You can feel yourself wasting away!")); - msg_print(NULL); - (void)dec_stat(which_stat, randint1(6) + 6, one_in_(3)); - } - } - if ((p_ptr->muta2 & MUT2_ATT_DRAGON) && !p_ptr->anti_magic && one_in_(3000)) - { - bool pet = one_in_(5); - BIT_FLAGS mode = PM_ALLOW_GROUP; - - if (pet) mode |= PM_FORCE_PET; - else mode |= (PM_ALLOW_UNIQUE | PM_NO_PET); - - if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, SUMMON_DRAGON, mode, '\0')) - { - msg_print(_("ドラゴンを引き寄せた!", "You have attracted a dragon!")); - disturb(FALSE, TRUE); - } - } - if ((p_ptr->muta2 & MUT2_WEIRD_MIND) && !p_ptr->anti_magic && one_in_(3000)) - { - if (p_ptr->tim_esp > 0) - { - msg_print(_("精神にもやがかかった!", "Your mind feels cloudy!")); - set_tim_esp(0, TRUE); - } - else - { - msg_print(_("精神が広がった!", "Your mind expands!")); - set_tim_esp(p_ptr->lev, FALSE); - } - } - if ((p_ptr->muta2 & MUT2_NAUSEA) && !p_ptr->slow_digest && one_in_(9000)) - { - disturb(FALSE, TRUE); - msg_print(_("胃が痙攣し、食事を失った!", "Your stomach roils, and you lose your lunch!")); - msg_print(NULL); - set_food(PY_FOOD_WEAK); - if (music_singing_any()) stop_singing(p_ptr); - if (hex_spelling_any()) stop_hex_spell_all(); - } - - if ((p_ptr->muta2 & MUT2_WALK_SHAD) && !p_ptr->anti_magic && one_in_(12000) && !p_ptr->inside_arena) - { - alter_reality(); - } - - if ((p_ptr->muta2 & MUT2_WARNING) && one_in_(1000)) - { - int danger_amount = 0; - MONSTER_IDX monster; - - for (monster = 0; monster < m_max; monster++) - { - monster_type *m_ptr = ¤t_floor_ptr->m_list[monster]; - monster_race *r_ptr = &r_info[m_ptr->r_idx]; - if (!monster_is_valid(m_ptr)) continue; - - if (r_ptr->level >= p_ptr->lev) - { - danger_amount += r_ptr->level - p_ptr->lev + 1; - } - } - - if (danger_amount > 100) - msg_print(_("非常に恐ろしい気がする!", "You feel utterly terrified!")); - else if (danger_amount > 50) - msg_print(_("恐ろしい気がする!", "You feel terrified!")); - else if (danger_amount > 20) - msg_print(_("非常に心配な気がする!", "You feel very worried!")); - else if (danger_amount > 10) - msg_print(_("心配な気がする!", "You feel paranoid!")); - else if (danger_amount > 5) - msg_print(_("ほとんど安全な気がする。", "You feel almost safe.")); - else - msg_print(_("寂しい気がする。", "You feel lonely.")); - } - - if ((p_ptr->muta2 & MUT2_INVULN) && !p_ptr->anti_magic && one_in_(5000)) - { - disturb(FALSE, TRUE); - msg_print(_("無敵な気がする!", "You feel invincible!")); - msg_print(NULL); - (void)set_invuln(randint1(8) + 8, FALSE); - } - - if ((p_ptr->muta2 & MUT2_SP_TO_HP) && one_in_(2000)) - { - MANA_POINT wounds = (MANA_POINT)(p_ptr->mhp - p_ptr->chp); - - if (wounds > 0) - { - HIT_POINT healing = p_ptr->csp; - if (healing > wounds) healing = wounds; - - hp_player(healing); - p_ptr->csp -= healing; - p_ptr->redraw |= (PR_HP | PR_MANA); - } - } - - if ((p_ptr->muta2 & MUT2_HP_TO_SP) && !p_ptr->anti_magic && one_in_(4000)) - { - HIT_POINT wounds = (HIT_POINT)(p_ptr->msp - p_ptr->csp); - - if (wounds > 0) - { - HIT_POINT healing = p_ptr->chp; - if (healing > wounds) healing = wounds; - - p_ptr->csp += healing; - p_ptr->redraw |= (PR_HP | PR_MANA); - take_hit(DAMAGE_LOSELIFE, healing, _("頭に昇った血", "blood rushing to the head"), -1); - } - } - - if ((p_ptr->muta2 & MUT2_DISARM) && one_in_(10000)) - { - INVENTORY_IDX slot = 0; - object_type *o_ptr = NULL; - - disturb(FALSE, TRUE); - msg_print(_("足がもつれて転んだ!", "You trip over your own feet!")); - take_hit(DAMAGE_NOESCAPE, randint1(p_ptr->wt / 6), _("転倒", "tripping"), -1); - - msg_print(NULL); - if (has_melee_weapon(INVEN_RARM)) - { - slot = INVEN_RARM; - o_ptr = &inventory[INVEN_RARM]; - - if (has_melee_weapon(INVEN_LARM) && one_in_(2)) - { - o_ptr = &inventory[INVEN_LARM]; - slot = INVEN_LARM; - } - } - else if (has_melee_weapon(INVEN_LARM)) - { - o_ptr = &inventory[INVEN_LARM]; - slot = INVEN_LARM; - } - if (slot && !object_is_cursed(o_ptr)) - { - msg_print(_("武器を落としてしまった!", "You drop your weapon!")); - inven_drop(slot, 1); - } - } - -} - -/*! - * @brief 10ゲームターンが進行するごとに装備効果の発動判定を行う処理 - * / Handle curse effects once every 10 game turns - * @return なし - */ -static void process_world_aux_curse(void) -{ - if ((p_ptr->cursed & TRC_P_FLAG_MASK) && !p_ptr->inside_battle && !p_ptr->wild_mode) - { - /* - * Hack: Uncursed teleporting items (e.g. Trump Weapons) - * can actually be useful! - */ - if ((p_ptr->cursed & TRC_TELEPORT_SELF) && one_in_(200)) - { - GAME_TEXT o_name[MAX_NLEN]; - object_type *o_ptr; - int i, i_keep = 0, count = 0; - - /* Scan the equipment with random teleport ability */ - for (i = INVEN_RARM; i < INVEN_TOTAL; i++) - { - BIT_FLAGS flgs[TR_FLAG_SIZE]; - o_ptr = &inventory[i]; - - /* Skip non-objects */ - if (!o_ptr->k_idx) continue; - - /* Extract the item flags */ - object_flags(o_ptr, flgs); - - if (have_flag(flgs, TR_TELEPORT)) - { - /* {.} will stop random teleportation. */ - if (!o_ptr->inscription || !my_strchr(quark_str(o_ptr->inscription), '.')) - { - count++; - if (one_in_(count)) i_keep = i; - } - } - } - - o_ptr = &inventory[i_keep]; - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - msg_format(_("%sがテレポートの能力を発動させようとしている。", "Your %s is activating teleportation."), o_name); - if (get_check_strict(_("テレポートしますか?", "Teleport? "), CHECK_OKAY_CANCEL)) - { - disturb(FALSE, TRUE); - teleport_player(50, 0L); - } - else - { - msg_format(_("%sに{.}(ピリオド)と銘を刻むと発動を抑制できます。", - "You can inscribe {.} on your %s to disable random teleportation. "), o_name); - disturb(TRUE, TRUE); - } - } - /* Make a chainsword noise */ - if ((p_ptr->cursed & TRC_CHAINSWORD) && one_in_(CHAINSWORD_NOISE)) - { - char noise[1024]; - if (!get_rnd_line(_("chainswd_j.txt", "chainswd.txt"), 0, noise)) - msg_print(noise); - disturb(FALSE, FALSE); - } - /* TY Curse */ - if ((p_ptr->cursed & TRC_TY_CURSE) && one_in_(TY_CURSE_CHANCE)) - { - int count = 0; - (void)activate_ty_curse(FALSE, &count); - } - /* Handle experience draining */ - if (p_ptr->prace != RACE_ANDROID && ((p_ptr->cursed & TRC_DRAIN_EXP) && one_in_(4))) - { - p_ptr->exp -= (p_ptr->lev + 1) / 2; - if (p_ptr->exp < 0) p_ptr->exp = 0; - p_ptr->max_exp -= (p_ptr->lev + 1) / 2; - if (p_ptr->max_exp < 0) p_ptr->max_exp = 0; - check_experience(); - } - /* Add light curse (Later) */ - if ((p_ptr->cursed & TRC_ADD_L_CURSE) && one_in_(2000)) - { - BIT_FLAGS new_curse; - object_type *o_ptr; - - o_ptr = choose_cursed_obj_name(TRC_ADD_L_CURSE); - - new_curse = get_curse(0, o_ptr); - if (!(o_ptr->curse_flags & new_curse)) - { - GAME_TEXT o_name[MAX_NLEN]; - - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - - o_ptr->curse_flags |= new_curse; - msg_format(_("悪意に満ちた黒いオーラが%sをとりまいた...", "There is a malignant black aura surrounding your %s..."), o_name); - - o_ptr->feeling = FEEL_NONE; - - p_ptr->update |= (PU_BONUS); - } - } - /* Add heavy curse (Later) */ - if ((p_ptr->cursed & TRC_ADD_H_CURSE) && one_in_(2000)) - { - BIT_FLAGS new_curse; - object_type *o_ptr; - - o_ptr = choose_cursed_obj_name(TRC_ADD_H_CURSE); - - new_curse = get_curse(1, o_ptr); - if (!(o_ptr->curse_flags & new_curse)) - { - GAME_TEXT o_name[MAX_NLEN]; - - object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); - - o_ptr->curse_flags |= new_curse; - msg_format(_("悪意に満ちた黒いオーラが%sをとりまいた...", "There is a malignant black aura surrounding your %s..."), o_name); - o_ptr->feeling = FEEL_NONE; - - p_ptr->update |= (PU_BONUS); - } - } - /* Call animal */ - if ((p_ptr->cursed & TRC_CALL_ANIMAL) && one_in_(2500)) - { - if (summon_specific(0, p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, SUMMON_ANIMAL, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0')) - { - GAME_TEXT o_name[MAX_NLEN]; - - object_desc(o_name, choose_cursed_obj_name(TRC_CALL_ANIMAL), (OD_OMIT_PREFIX | OD_NAME_ONLY)); - msg_format(_("%sが動物を引き寄せた!", "Your %s have attracted an animal!"), o_name); - disturb(FALSE, TRUE); - } - } - /* Call demon */ - if ((p_ptr->cursed & TRC_CALL_DEMON) && one_in_(1111)) - { - if (summon_specific(0, p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, SUMMON_DEMON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0')) - { - GAME_TEXT o_name[MAX_NLEN]; - - object_desc(o_name, choose_cursed_obj_name(TRC_CALL_DEMON), (OD_OMIT_PREFIX | OD_NAME_ONLY)); - msg_format(_("%sが悪魔を引き寄せた!", "Your %s have attracted a demon!"), o_name); - disturb(FALSE, TRUE); - } - } - /* Call dragon */ - if ((p_ptr->cursed & TRC_CALL_DRAGON) && one_in_(800)) - { - if (summon_specific(0, p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, SUMMON_DRAGON, - (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0')) - { - GAME_TEXT o_name[MAX_NLEN]; - - object_desc(o_name, choose_cursed_obj_name(TRC_CALL_DRAGON), (OD_OMIT_PREFIX | OD_NAME_ONLY)); - msg_format(_("%sがドラゴンを引き寄せた!", "Your %s have attracted an dragon!"), o_name); - disturb(FALSE, TRUE); - } - } - /* Call undead */ - if ((p_ptr->cursed & TRC_CALL_UNDEAD) && one_in_(1111)) - { - if (summon_specific(0, p_ptr->y, p_ptr->x, current_floor_ptr->dun_level, SUMMON_UNDEAD, - (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0')) - { - GAME_TEXT o_name[MAX_NLEN]; - - object_desc(o_name, choose_cursed_obj_name(TRC_CALL_UNDEAD), (OD_OMIT_PREFIX | OD_NAME_ONLY)); - msg_format(_("%sが死霊を引き寄せた!", "Your %s have attracted an undead!"), o_name); - disturb(FALSE, TRUE); - } - } - if ((p_ptr->cursed & TRC_COWARDICE) && one_in_(1500)) - { - if (!p_ptr->resist_fear) - { - disturb(FALSE, TRUE); - msg_print(_("とても暗い... とても恐い!", "It's so dark... so scary!")); - set_afraid(p_ptr->afraid + 13 + randint1(26)); - } - } - /* Teleport player */ - if ((p_ptr->cursed & TRC_TELEPORT) && one_in_(200) && !p_ptr->anti_tele) - { - disturb(FALSE, TRUE); - - /* Teleport player */ - teleport_player(40, TELEPORT_PASSIVE); - } - /* Handle HP draining */ - if ((p_ptr->cursed & TRC_DRAIN_HP) && one_in_(666)) - { - GAME_TEXT o_name[MAX_NLEN]; - - object_desc(o_name, choose_cursed_obj_name(TRC_DRAIN_HP), (OD_OMIT_PREFIX | OD_NAME_ONLY)); - msg_format(_("%sはあなたの体力を吸収した!", "Your %s drains HP from you!"), o_name); - take_hit(DAMAGE_LOSELIFE, MIN(p_ptr->lev*2, 100), o_name, -1); - } - /* Handle mana draining */ - if ((p_ptr->cursed & TRC_DRAIN_MANA) && p_ptr->csp && one_in_(666)) - { - GAME_TEXT o_name[MAX_NLEN]; - - object_desc(o_name, choose_cursed_obj_name(TRC_DRAIN_MANA), (OD_OMIT_PREFIX | OD_NAME_ONLY)); - msg_format(_("%sはあなたの魔力を吸収した!", "Your %s drains mana from you!"), o_name); - p_ptr->csp -= MIN(p_ptr->lev, 50); - if (p_ptr->csp < 0) - { - p_ptr->csp = 0; - p_ptr->csp_frac = 0; - } - p_ptr->redraw |= PR_MANA; - } - } - - /* Rarely, take damage from the Jewel of Judgement */ - if (one_in_(999) && !p_ptr->anti_magic) - { - object_type *o_ptr = &inventory[INVEN_LITE]; - - if (o_ptr->name1 == ART_JUDGE) - { - if (object_is_known(o_ptr)) - msg_print(_("『審判の宝石』はあなたの体力を吸収した!", "The Jewel of Judgement drains life from you!")); - else - msg_print(_("なにかがあなたの体力を吸収した!", "Something drains life from you!")); - take_hit(DAMAGE_LOSELIFE, MIN(p_ptr->lev, 50), _("審判の宝石", "the Jewel of Judgement"), -1); - } - } -} - - -/*! - * @brief 10ゲームターンが進行するごとに魔道具の自然充填を行う処理 - * / Handle recharging objects once every 10 game turns - * @return なし - */ -static void process_world_aux_recharge(void) -{ - int i; - bool changed; - - /* Process equipment */ - for (changed = FALSE, i = INVEN_RARM; i < INVEN_TOTAL; i++) - { - /* Get the object */ - object_type *o_ptr = &inventory[i]; - - /* Skip non-objects */ - if (!o_ptr->k_idx) continue; - - /* Recharge activatable objects */ - if (o_ptr->timeout > 0) - { - /* Recharge */ - o_ptr->timeout--; - - /* Notice changes */ - if (!o_ptr->timeout) - { - recharged_notice(o_ptr); - changed = TRUE; - } - } - } - - /* Notice changes */ - if (changed) - { - p_ptr->window |= (PW_EQUIP); - wild_regen = 20; - } - - /* - * Recharge rods. Rods now use timeout to control charging status, - * and each charging rod in a stack decreases the stack's timeout by - * one per current_world_ptr->game_turn. -LM- - */ - for (changed = FALSE, i = 0; i < INVEN_PACK; i++) - { - object_type *o_ptr = &inventory[i]; - object_kind *k_ptr = &k_info[o_ptr->k_idx]; - - /* Skip non-objects */ - if (!o_ptr->k_idx) continue; - - /* Examine all charging rods or stacks of charging rods. */ - if ((o_ptr->tval == TV_ROD) && (o_ptr->timeout)) - { - /* Determine how many rods are charging. */ - TIME_EFFECT temp = (o_ptr->timeout + (k_ptr->pval - 1)) / k_ptr->pval; - if (temp > o_ptr->number) temp = (TIME_EFFECT)o_ptr->number; - - /* Decrease timeout by that number. */ - o_ptr->timeout -= temp; - - /* Boundary control. */ - if (o_ptr->timeout < 0) o_ptr->timeout = 0; - - /* Notice changes, provide message if object is inscribed. */ - if (!(o_ptr->timeout)) - { - recharged_notice(o_ptr); - changed = TRUE; - } - - /* One of the stack of rod is charged */ - else if (o_ptr->timeout % k_ptr->pval) - { - changed = TRUE; - } - } - } - - /* Notice changes */ - if (changed) - { - p_ptr->window |= (PW_INVEN); - wild_regen = 20; - } - - /* Process objects on floor */ - for (i = 1; i < o_max; i++) - { - object_type *o_ptr = ¤t_floor_ptr->o_list[i]; - - /* Skip dead objects */ - if (!o_ptr->k_idx) continue; - - /* Recharge rods on the ground. No messages. */ - if ((o_ptr->tval == TV_ROD) && (o_ptr->timeout)) - { - /* Charge it */ - o_ptr->timeout -= (TIME_EFFECT)o_ptr->number; - - /* Boundary control. */ - if (o_ptr->timeout < 0) o_ptr->timeout = 0; - } - } -} - - -/*! - * @brief 10ゲームターンが進行するごとに帰還や現実変容などの残り時間カウントダウンと発動を処理する。 - * / Handle involuntary movement once every 10 game turns - * @return なし - */ -static void process_world_aux_movement(void) -{ - /* Delayed Word-of-Recall */ - if (p_ptr->word_recall) - { - /* - * HACK: Autosave BEFORE resetting the recall counter (rr9) - * The player is yanked up/down as soon as - * he loads the autosaved game. - */ - if (autosave_l && (p_ptr->word_recall == 1) && !p_ptr->inside_battle) - do_cmd_save_game(TRUE); - - /* Count down towards recall */ - p_ptr->word_recall--; - - p_ptr->redraw |= (PR_STATUS); - - /* Activate the recall */ - if (!p_ptr->word_recall) - { - /* Disturbing! */ - disturb(FALSE, TRUE); - - /* Determine the level */ - if (current_floor_ptr->dun_level || p_ptr->inside_quest || p_ptr->enter_dungeon) - { - msg_print(_("上に引っ張りあげられる感じがする!", "You feel yourself yanked upwards!")); - - if (p_ptr->dungeon_idx) p_ptr->recall_dungeon = p_ptr->dungeon_idx; - if (record_stair) - do_cmd_write_nikki(NIKKI_RECALL, current_floor_ptr->dun_level, NULL); - - current_floor_ptr->dun_level = 0; - p_ptr->dungeon_idx = 0; - - leave_quest_check(); - leave_tower_check(); - - p_ptr->inside_quest = 0; - - p_ptr->leaving = TRUE; - } - else - { - msg_print(_("下に引きずり降ろされる感じがする!", "You feel yourself yanked downwards!")); - - p_ptr->dungeon_idx = p_ptr->recall_dungeon; - - if (record_stair) - do_cmd_write_nikki(NIKKI_RECALL, current_floor_ptr->dun_level, NULL); - - /* New depth */ - current_floor_ptr->dun_level = max_dlv[p_ptr->dungeon_idx]; - if (current_floor_ptr->dun_level < 1) current_floor_ptr->dun_level = 1; - - /* Nightmare mode makes recall more dangerous */ - if (ironman_nightmare && !randint0(666) && (p_ptr->dungeon_idx == DUNGEON_ANGBAND)) - { - if (current_floor_ptr->dun_level < 50) - { - current_floor_ptr->dun_level *= 2; - } - else if (current_floor_ptr->dun_level < 99) - { - current_floor_ptr->dun_level = (current_floor_ptr->dun_level + 99) / 2; - } - else if (current_floor_ptr->dun_level > 100) - { - current_floor_ptr->dun_level = d_info[p_ptr->dungeon_idx].maxdepth - 1; - } - } - - if (p_ptr->wild_mode) - { - p_ptr->wilderness_y = p_ptr->y; - p_ptr->wilderness_x = p_ptr->x; - } - else - { - /* Save player position */ - p_ptr->oldpx = p_ptr->x; - p_ptr->oldpy = p_ptr->y; - } - p_ptr->wild_mode = FALSE; - - /* - * Clear all saved floors - * and create a first saved floor - */ - prepare_change_floor_mode(CFM_FIRST_FLOOR); - p_ptr->leaving = TRUE; - - if (p_ptr->dungeon_idx == DUNGEON_ANGBAND) - { - int i; - - for (i = MIN_RANDOM_QUEST; i < MAX_RANDOM_QUEST + 1; i++) - { - quest_type* const q_ptr = &quest[i]; - - - if ((q_ptr->type == QUEST_TYPE_RANDOM) && - (q_ptr->status == QUEST_STATUS_TAKEN) && - (q_ptr->level < current_floor_ptr->dun_level)) - { - q_ptr->status = QUEST_STATUS_FAILED; - q_ptr->complev = (byte)p_ptr->lev; - update_playtime(); - q_ptr->comptime = current_world_ptr->play_time; - r_info[q_ptr->r_idx].flags1 &= ~(RF1_QUESTOR); - } - } - } - } - - sound(SOUND_TPLEVEL); - } - } - - - /* Delayed Alter reality */ - if (p_ptr->alter_reality) - { - if (autosave_l && (p_ptr->alter_reality == 1) && !p_ptr->inside_battle) - do_cmd_save_game(TRUE); - - /* Count down towards alter */ - p_ptr->alter_reality--; - - p_ptr->redraw |= (PR_STATUS); - - /* Activate the alter reality */ - if (!p_ptr->alter_reality) - { - /* Disturbing! */ - disturb(FALSE, TRUE); - - /* Determine the level */ - if (!quest_number(current_floor_ptr->dun_level) && current_floor_ptr->dun_level) - { - msg_print(_("世界が変わった!", "The world changes!")); - - /* - * Clear all saved floors - * and create a first saved floor - */ - prepare_change_floor_mode(CFM_FIRST_FLOOR); - p_ptr->leaving = TRUE; - } - else - { - msg_print(_("世界が少しの間変化したようだ。", "The world seems to change for a moment!")); - } - - sound(SOUND_TPLEVEL); - } - } -} - - -/*! - * @brief 指定したモンスターに隣接しているモンスターの数を返す。 - * / Count number of adjacent monsters - * @param m_idx 隣接数を調べたいモンスターのID - * @return 隣接しているモンスターの数 - */ -static int get_monster_crowd_number(MONSTER_IDX m_idx) -{ - monster_type *m_ptr = ¤t_floor_ptr->m_list[m_idx]; - POSITION my = m_ptr->fy; - POSITION mx = m_ptr->fx; - int i; - int count = 0; - - for (i = 0; i < 7; i++) - { - int ay = my + ddy_ddd[i]; - int ax = mx + ddx_ddd[i]; - - if (!in_bounds(ay, ax)) continue; - - /* Count number of monsters */ - if (current_floor_ptr->grid_array[ay][ax].m_idx > 0) count++; - } - - return count; -} - - - -/*! - * ダンジョンの雰囲気を計算するための非線形基準値 / Dungeon rating is no longer linear - */ -#define RATING_BOOST(delta) (delta * delta + 50 * delta) - -/*! - * @brief ダンジョンの雰囲気を算出する。 - * / Examine all monsters and unidentified objects, and get the feeling of current dungeon floor - * @return 算出されたダンジョンの雰囲気ランク - */ -static byte get_dungeon_feeling(void) -{ - const int base = 10; - int rating = 0; - IDX i; - - /* Hack -- no feeling in the town */ - if (!current_floor_ptr->dun_level) return 0; - - /* Examine each monster */ - for (i = 1; i < m_max; i++) - { - monster_type *m_ptr = ¤t_floor_ptr->m_list[i]; - monster_race *r_ptr; - int delta = 0; - if (!monster_is_valid(m_ptr)) continue; - - /* Ignore pet */ - if (is_pet(m_ptr)) continue; - - r_ptr = &r_info[m_ptr->r_idx]; - - /* Unique monsters */ - if (r_ptr->flags1 & (RF1_UNIQUE)) - { - /* Nearly out-of-depth unique monsters */ - if (r_ptr->level + 10 > current_floor_ptr->dun_level) - { - /* Boost rating by twice delta-depth */ - delta += (r_ptr->level + 10 - current_floor_ptr->dun_level) * 2 * base; - } - } - else - { - /* Out-of-depth monsters */ - if (r_ptr->level > current_floor_ptr->dun_level) - { - /* Boost rating by delta-depth */ - delta += (r_ptr->level - current_floor_ptr->dun_level) * base; - } - } - - /* Unusually crowded monsters get a little bit of rating boost */ - if (r_ptr->flags1 & RF1_FRIENDS) - { - if (5 <= get_monster_crowd_number(i)) delta += 1; - } - else - { - if (2 <= get_monster_crowd_number(i)) delta += 1; - } - - - rating += RATING_BOOST(delta); - } - - /* Examine each unidentified object */ - for (i = 1; i < o_max; i++) - { - object_type *o_ptr = ¤t_floor_ptr->o_list[i]; - object_kind *k_ptr = &k_info[o_ptr->k_idx]; - int delta = 0; - - /* Skip dead objects */ - if (!o_ptr->k_idx) continue; - - /* Skip known objects */ - if (object_is_known(o_ptr)) - { - /* Touched? */ - if (o_ptr->marked & OM_TOUCHED) continue; - } - - /* Skip pseudo-known objects */ - if (o_ptr->ident & IDENT_SENSE) continue; - - /* Ego objects */ - if (object_is_ego(o_ptr)) - { - ego_item_type *e_ptr = &e_info[o_ptr->name2]; - - delta += e_ptr->rating * base; - } - - /* Artifacts */ - if (object_is_artifact(o_ptr)) - { - PRICE cost = object_value_real(o_ptr); - - delta += 10 * base; - if (cost > 10000L) delta += 10 * base; - if (cost > 50000L) delta += 10 * base; - if (cost > 100000L) delta += 10 * base; - - /* Special feeling */ - if (!preserve_mode) return 1; - } - - if (o_ptr->tval == TV_DRAG_ARMOR) delta += 30 * base; - if (o_ptr->tval == TV_SHIELD && o_ptr->sval == SV_DRAGON_SHIELD) delta += 5 * base; - if (o_ptr->tval == TV_GLOVES && o_ptr->sval == SV_SET_OF_DRAGON_GLOVES) delta += 5 * base; - if (o_ptr->tval == TV_BOOTS && o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE) delta += 5 * base; - if (o_ptr->tval == TV_HELM && o_ptr->sval == SV_DRAGON_HELM) delta += 5 * base; - if (o_ptr->tval == TV_RING && o_ptr->sval == SV_RING_SPEED && !object_is_cursed(o_ptr)) delta += 25 * base; - if (o_ptr->tval == TV_RING && o_ptr->sval == SV_RING_LORDLY && !object_is_cursed(o_ptr)) delta += 15 * base; - if (o_ptr->tval == TV_AMULET && o_ptr->sval == SV_AMULET_THE_MAGI && !object_is_cursed(o_ptr)) delta += 15 * base; - - /* Out-of-depth objects */ - if (!object_is_cursed(o_ptr) && !object_is_broken(o_ptr) && k_ptr->level > current_floor_ptr->dun_level) - { - /* Rating increase */ - delta += (k_ptr->level - current_floor_ptr->dun_level) * base; - } - - rating += RATING_BOOST(delta); - } - - - if (rating > RATING_BOOST(1000)) return 2; - if (rating > RATING_BOOST(800)) return 3; - if (rating > RATING_BOOST(600)) return 4; - if (rating > RATING_BOOST(400)) return 5; - if (rating > RATING_BOOST(300)) return 6; - if (rating > RATING_BOOST(200)) return 7; - if (rating > RATING_BOOST(100)) return 8; - if (rating > RATING_BOOST(0)) return 9; - - return 10; -} - -/*! - * @brief ダンジョンの雰囲気を更新し、変化があった場合メッセージを表示する - * / Update dungeon feeling, and announce it if changed - * @return なし - */ -static void update_dungeon_feeling(void) -{ - byte new_feeling; - int quest_num; - int delay; - - /* No feeling on the surface */ - if (!current_floor_ptr->dun_level) return; - - /* No feeling in the arena */ - if (p_ptr->inside_battle) return; - - /* Extract delay time */ - delay = MAX(10, 150 - p_ptr->skill_fos) * (150 - current_floor_ptr->dun_level) * TURNS_PER_TICK / 100; - - /* Not yet felt anything */ - if (current_world_ptr->game_turn < p_ptr->feeling_turn + delay && !cheat_xtra) return; - - /* Extract quest number (if any) */ - quest_num = quest_number(current_floor_ptr->dun_level); - - /* No feeling in a quest */ - if (quest_num && - (is_fixed_quest_idx(quest_num) && - !((quest_num == QUEST_OBERON) || (quest_num == QUEST_SERPENT) || - !(quest[quest_num].flags & QUEST_FLAG_PRESET)))) return; - - - /* Get new dungeon feeling */ - new_feeling = get_dungeon_feeling(); - - /* Remember last time updated */ - p_ptr->feeling_turn = current_world_ptr->game_turn; - - /* No change */ - if (p_ptr->feeling == new_feeling) return; - - /* Dungeon feeling is changed */ - p_ptr->feeling = new_feeling; - - /* Announce feeling */ - do_cmd_feeling(); - - select_floor_music(); - - /* Update the level indicator */ - p_ptr->redraw |= (PR_DEPTH); - - if (disturb_minor) disturb(FALSE, FALSE); -} - -/*! - * @brief 10ゲームターンが進行する毎にゲーム世界全体の処理を行う。 - * / Handle certain things once every 10 game turns - * @return なし - */ -static void process_world(void) -{ - int day, hour, min; - - const s32b A_DAY = TURNS_PER_TICK * TOWN_DAWN; - s32b prev_turn_in_today = ((current_world_ptr->game_turn - TURNS_PER_TICK) % A_DAY + A_DAY / 4) % A_DAY; - int prev_min = (1440 * prev_turn_in_today / A_DAY) % 60; - - extract_day_hour_min(&day, &hour, &min); - - /* Update dungeon feeling, and announce it if changed */ - update_dungeon_feeling(); - - /* 帰還無しモード時のレベルテレポバグ対策 / Fix for level teleport bugs on ironman_downward.*/ - if (ironman_downward && (p_ptr->dungeon_idx != DUNGEON_ANGBAND && p_ptr->dungeon_idx != 0)) - { - current_floor_ptr->dun_level = 0; - p_ptr->dungeon_idx = 0; - prepare_change_floor_mode(CFM_FIRST_FLOOR | CFM_RAND_PLACE); - p_ptr->inside_arena = FALSE; - p_ptr->wild_mode = FALSE; - p_ptr->leaving = TRUE; - } - - /*** Check monster arena ***/ - if (p_ptr->inside_battle && !p_ptr->leaving) - { - int i2, j2; - int win_m_idx = 0; - int number_mon = 0; - - /* Count all hostile monsters */ - for (i2 = 0; i2 < current_floor_ptr->width; ++i2) - for (j2 = 0; j2 < current_floor_ptr->height; j2++) - { - grid_type *g_ptr = ¤t_floor_ptr->grid_array[j2][i2]; - - if ((g_ptr->m_idx > 0) && (g_ptr->m_idx != p_ptr->riding)) - { - number_mon++; - win_m_idx = g_ptr->m_idx; - } - } - - if (number_mon == 0) - { - msg_print(_("相打ちに終わりました。", "They have kill each other at the same time.")); - msg_print(NULL); - p_ptr->energy_need = 0; - battle_monsters(); - } - else if ((number_mon-1) == 0) - { - GAME_TEXT m_name[MAX_NLEN]; - monster_type *wm_ptr; - - wm_ptr = ¤t_floor_ptr->m_list[win_m_idx]; - - monster_desc(m_name, wm_ptr, 0); - msg_format(_("%sが勝利した!", "%s is winner!"), m_name); - msg_print(NULL); - - if (win_m_idx == (sel_monster+1)) - { - msg_print(_("おめでとうございます。", "Congratulations.")); - msg_format(_("%d$を受け取った。", "You received %d gold."), battle_odds); - p_ptr->au += battle_odds; - } - else - { - msg_print(_("残念でした。", "You lost gold.")); - } - msg_print(NULL); - p_ptr->energy_need = 0; - battle_monsters(); - } - else if (current_world_ptr->game_turn - current_floor_ptr->generated_turn == 150 * TURNS_PER_TICK) - { - msg_print(_("申し分けありませんが、この勝負は引き分けとさせていただきます。", "This battle have ended in a draw.")); - p_ptr->au += kakekin; - msg_print(NULL); - p_ptr->energy_need = 0; - battle_monsters(); - } - } - - /* Every 10 game turns */ - if (current_world_ptr->game_turn % TURNS_PER_TICK) return; - - /*** Check the Time and Load ***/ - - if (!(current_world_ptr->game_turn % (50*TURNS_PER_TICK))) - { - /* Check time and load */ - if ((0 != check_time()) || (0 != check_load())) - { - /* Warning */ - if (closing_flag <= 2) - { - disturb(FALSE, TRUE); - - /* Count warnings */ - closing_flag++; - - msg_print(_("アングバンドへの門が閉じかかっています...", "The gates to ANGBAND are closing...")); - msg_print(_("ゲームを終了するかセーブするかして下さい。", "Please finish up and/or save your game.")); - - } - - /* Slam the gate */ - else - { - msg_print(_("今、アングバンドへの門が閉ざされました。", "The gates to ANGBAND are now closed.")); - - /* Stop playing */ - p_ptr->playing = FALSE; - p_ptr->leaving = TRUE; - } - } - } - - /*** Attempt timed autosave ***/ - if (autosave_t && autosave_freq && !p_ptr->inside_battle) - { - if (!(current_world_ptr->game_turn % ((s32b)autosave_freq * TURNS_PER_TICK))) - do_cmd_save_game(TRUE); - } - - if (mon_fight && !ignore_unview) - { - msg_print(_("何かが聞こえた。", "You hear noise.")); - } - - /*** Handle the wilderness/town (sunshine) ***/ - - /* While in town/wilderness */ - if (!current_floor_ptr->dun_level && !p_ptr->inside_quest && !p_ptr->inside_battle && !p_ptr->inside_arena) - { - /* Hack -- Daybreak/Nighfall in town */ - if (!(current_world_ptr->game_turn % ((TURNS_PER_TICK * TOWN_DAWN) / 2))) - { - bool dawn; - - /* Check for dawn */ - dawn = (!(current_world_ptr->game_turn % (TURNS_PER_TICK * TOWN_DAWN))); - - if (dawn) day_break(); - else night_falls(); - - } - } - - /* While in the dungeon (vanilla_town or lite_town mode only) */ - else if ((vanilla_town || (lite_town && !p_ptr->inside_quest && !p_ptr->inside_battle && !p_ptr->inside_arena)) && current_floor_ptr->dun_level) - { - /*** Shuffle the Storekeepers ***/ - - /* Chance is only once a day (while in dungeon) */ - if (!(current_world_ptr->game_turn % (TURNS_PER_TICK * STORE_TICKS))) - { - /* Sometimes, shuffle the shop-keepers */ - if (one_in_(STORE_SHUFFLE)) - { - int n; - FEAT_IDX i; - - /* Pick a random shop (except home and museum) */ - do - { - n = randint0(MAX_STORES); - } - while ((n == STORE_HOME) || (n == STORE_MUSEUM)); - - /* Check every feature */ - for (i = 1; i < max_f_idx; i++) - { - feature_type *f_ptr = &f_info[i]; - - /* Skip empty index */ - if (!f_ptr->name) continue; - - /* Skip non-store features */ - if (!have_flag(f_ptr->flags, FF_STORE)) continue; - - /* Verify store type */ - if (f_ptr->subtype == n) - { - if (cheat_xtra) msg_format(_("%sの店主をシャッフルします。", "Shuffle a Shopkeeper of %s."), f_name + f_ptr->name); - - /* Shuffle it */ - store_shuffle(n); - - break; - } - } - } - } - } - - - /*** Process the monsters ***/ - - /* Check for creature generation. */ - if (one_in_(d_info[p_ptr->dungeon_idx].max_m_alloc_chance) && - !p_ptr->inside_arena && !p_ptr->inside_quest && !p_ptr->inside_battle) - { - /* Make a new monster */ - (void)alloc_monster(MAX_SIGHT + 5, 0); - } - - /* Hack -- Check for creature regeneration */ - if (!(current_world_ptr->game_turn % (TURNS_PER_TICK * 10)) && !p_ptr->inside_battle) regen_monsters(); - if (!(current_world_ptr->game_turn % (TURNS_PER_TICK * 3))) regen_captured_monsters(); - - if (!p_ptr->leaving) - { - int i; - - /* Hack -- Process the counters of monsters if needed */ - for (i = 0; i < MAX_MTIMED; i++) - { - if (current_floor_ptr->mproc_max[i] > 0) process_monsters_mtimed(i); - } - } - - - /* Date changes */ - if (!hour && !min) - { - if (min != prev_min) - { - do_cmd_write_nikki(NIKKI_HIGAWARI, 0, NULL); - determine_today_mon(FALSE); - } - } - - /* - * Nightmare mode activates the TY_CURSE at midnight - * Require exact minute -- Don't activate multiple times in a minute - */ - - if (ironman_nightmare && (min != prev_min)) - { - - /* Every 15 minutes after 11:00 pm */ - if ((hour == 23) && !(min % 15)) - { - disturb(FALSE, TRUE); - - switch (min / 15) - { - case 0: - msg_print(_("遠くで不気味な鐘の音が鳴った。", "You hear a distant bell toll ominously.")); - break; - - case 1: - msg_print(_("遠くで鐘が二回鳴った。", "A distant bell sounds twice.")); - break; - - case 2: - msg_print(_("遠くで鐘が三回鳴った。", "A distant bell sounds three times.")); - break; - - case 3: - msg_print(_("遠くで鐘が四回鳴った。", "A distant bell tolls four times.")); - break; - } - } - - /* TY_CURSE activates at midnight! */ - if (!hour && !min) - { - - disturb(TRUE, TRUE); - msg_print(_("遠くで鐘が何回も鳴り、死んだような静けさの中へ消えていった。", "A distant bell tolls many times, fading into an deathly silence.")); - - if (p_ptr->wild_mode) - { - /* Go into large wilderness view */ - p_ptr->oldpy = randint1(MAX_HGT - 2); - p_ptr->oldpx = randint1(MAX_WID - 2); - change_wild_mode(); - - /* Give first move to monsters */ - take_turn(p_ptr, 100); - - /* HACk -- set the encouter flag for the wilderness generation */ - generate_encounter = TRUE; - } - - invoking_midnight_curse = TRUE; - } - } - - - - /* Check the Food */ - process_world_aux_digestion(); - - /* Process timed damage and regeneration */ - process_world_aux_hp_and_sp(); - - /* Process timeout */ - process_world_aux_timeout(); - - /* Process light */ - process_world_aux_light(); - - /* Process mutation effects */ - process_world_aux_mutation(); - - /* Process curse effects */ - process_world_aux_curse(); - - /* Process recharging */ - process_world_aux_recharge(); - - /* Feel the inventory */ - sense_inventory1(); - sense_inventory2(); - - /* Involuntary Movement */ - process_world_aux_movement(); -} - -/*! - * @brief ウィザードモードへの導入処理 - * / Verify use of "wizard" mode - * @return 実際にウィザードモードへ移行したらTRUEを返す。 - */ -static bool enter_wizard_mode(void) -{ - /* Ask first time */ - if (!p_ptr->noscore) - { - /* Wizard mode is not permitted */ - if (!allow_debug_opts || arg_wizard) - { - msg_print(_("ウィザードモードは許可されていません。 ", "Wizard mode is not permitted.")); - return FALSE; - } - - /* Mention effects */ - msg_print(_("ウィザードモードはデバッグと実験のためのモードです。 ", "Wizard mode is for debugging and experimenting.")); - msg_print(_("一度ウィザードモードに入るとスコアは記録されません。", "The game will not be scored if you enter wizard mode.")); - msg_print(NULL); - - /* Verify request */ - if (!get_check(_("本当にウィザードモードに入りたいのですか? ", "Are you sure you want to enter wizard mode? "))) - { - return (FALSE); - } - - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("ウィザードモードに突入してスコアを残せなくなった。", "give up recording score to enter wizard mode.")); - /* Mark savefile */ - p_ptr->noscore |= 0x0002; - } - - /* Success */ - return (TRUE); -} - - -#ifdef ALLOW_WIZARD - -/*! - * @brief デバッグコマンドへの導入処理 - * / Verify use of "debug" commands - * @return 実際にデバッグコマンドへ移行したらTRUEを返す。 - */ -static bool enter_debug_mode(void) -{ - /* Ask first time */ - if (!p_ptr->noscore) - { - /* Debug mode is not permitted */ - if (!allow_debug_opts) - { - msg_print(_("デバッグコマンドは許可されていません。 ", "Use of debug command is not permitted.")); - return FALSE; - } - - /* Mention effects */ - msg_print(_("デバッグ・コマンドはデバッグと実験のためのコマンドです。 ", "The debug commands are for debugging and experimenting.")); - msg_print(_("デバッグ・コマンドを使うとスコアは記録されません。", "The game will not be scored if you use debug commands.")); - - msg_print(NULL); - - /* Verify request */ - if (!get_check(_("本当にデバッグ・コマンドを使いますか? ", "Are you sure you want to use debug commands? "))) - { - return (FALSE); - } - - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("デバッグモードに突入してスコアを残せなくなった。", "give up sending score to use debug commands.")); - /* Mark savefile */ - p_ptr->noscore |= 0x0008; - } - - /* Success */ - return (TRUE); -} - -/* - * Hack -- Declare the Debug Routines - */ -extern void do_cmd_debug(void); - -#endif /* ALLOW_WIZARD */ - - -#ifdef ALLOW_BORG - -/*! - * @brief ボーグコマンドへの導入処理 - * / Verify use of "borg" commands - * @return 実際にボーグコマンドへ移行したらTRUEを返す。 - */ -static bool enter_borg_mode(void) -{ - /* Ask first time */ - if (!(p_ptr->noscore & 0x0010)) - { - /* Mention effects */ - msg_print(_("ボーグ・コマンドはデバッグと実験のためのコマンドです。 ", "The borg commands are for debugging and experimenting.")); - msg_print(_("ボーグ・コマンドを使うとスコアは記録されません。", "The game will not be scored if you use borg commands.")); - - msg_print(NULL); - - /* Verify request */ - if (!get_check(_("本当にボーグ・コマンドを使いますか? ", "Are you sure you want to use borg commands? "))) - { - return (FALSE); - } - - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("ボーグ・コマンドを使用してスコアを残せなくなった。", "give up recording score to use borg commands.")); - /* Mark savefile */ - p_ptr->noscore |= 0x0010; - } - - /* Success */ - return (TRUE); -} - -/* - * Hack -- Declare the Ben Borg - */ -extern void do_cmd_borg(void); - -#endif /* ALLOW_BORG */ - - -/*! - * @brief プレイヤーから受けた入力コマンドの分岐処理。 - * / Parse and execute the current command Give "Warning" on illegal commands. - * @todo Make some "blocks" - * @return なし - */ -static void process_command(void) -{ - COMMAND_CODE old_now_message = now_message; - - /* Handle repeating the last command */ - repeat_check(); - - now_message = 0; - - /* Sniper */ - if ((p_ptr->pclass == CLASS_SNIPER) && (p_ptr->concent)) - reset_concent = TRUE; - - /* Parse the command */ - switch (command_cmd) - { - /* Ignore */ - case ESCAPE: - case ' ': - { - break; - } - - /* Ignore return */ - case '\r': - case '\n': - { - break; - } - - /*** Wizard Commands ***/ - - /* Toggle Wizard Mode */ - case KTRL('W'): - { - if (p_ptr->wizard) - { - p_ptr->wizard = FALSE; - msg_print(_("ウィザードモード解除。", "Wizard mode off.")); - } - else if (enter_wizard_mode()) - { - p_ptr->wizard = TRUE; - msg_print(_("ウィザードモード突入。", "Wizard mode on.")); - } - p_ptr->update |= (PU_MONSTERS); - - /* Redraw "title" */ - p_ptr->redraw |= (PR_TITLE); - - break; - } - - -#ifdef ALLOW_WIZARD - - /* Special "debug" commands */ - case KTRL('A'): - { - /* Enter debug mode */ - if (enter_debug_mode()) - { - do_cmd_debug(); - } - break; - } - -#endif /* ALLOW_WIZARD */ - - -#ifdef ALLOW_BORG - - /* Special "borg" commands */ - case KTRL('Z'): - { - /* Enter borg mode */ - if (enter_borg_mode()) - { - if (!p_ptr->wild_mode) do_cmd_borg(); - } - - break; - } - -#endif /* ALLOW_BORG */ - - - - /*** Inventory Commands ***/ - - /* Wear/wield equipment */ - case 'w': - { - if (!p_ptr->wild_mode) do_cmd_wield(); - break; - } - - /* Take off equipment */ - case 't': - { - if (!p_ptr->wild_mode) do_cmd_takeoff(); - break; - } - - /* Drop an item */ - case 'd': - { - if (!p_ptr->wild_mode) do_cmd_drop(); - break; - } - - /* Destroy an item */ - case 'k': - { - do_cmd_destroy(); - break; - } - - /* Equipment list */ - case 'e': - { - do_cmd_equip(); - break; - } - - /* Inventory list */ - case 'i': - { - do_cmd_inven(); - break; - } - - - /*** Various commands ***/ - - /* Identify an object */ - case 'I': - { - do_cmd_observe(); - break; - } - - /* Hack -- toggle windows */ - case KTRL('I'): - { - toggle_inven_equip(); - break; - } - - - /*** Standard "Movement" Commands ***/ - - /* Alter a grid */ - case '+': - { - if (!p_ptr->wild_mode) do_cmd_alter(); - break; - } - - /* Dig a tunnel */ - case 'T': - { - if (!p_ptr->wild_mode) do_cmd_tunnel(); - break; - } - - /* Move (usually pick up things) */ - case ';': - { - do_cmd_walk(FALSE); - break; - } - - /* Move (usually do not pick up) */ - case '-': - { - do_cmd_walk(TRUE); - break; - } - - - /*** Running, Resting, Searching, Staying */ - - /* Begin Running -- Arg is Max Distance */ - case '.': - { - if (!p_ptr->wild_mode) do_cmd_run(); - break; - } - - /* Stay still (usually pick things up) */ - case ',': - { - do_cmd_stay(always_pickup); - break; - } - - /* Stay still (usually do not pick up) */ - case 'g': - { - do_cmd_stay(!always_pickup); - break; - } - - /* Rest -- Arg is time */ - case 'R': - { - do_cmd_rest(); - break; - } - - /* Search for traps/doors */ - case 's': - { - do_cmd_search(); - break; - } - - /* Toggle search mode */ - case 'S': - { - if (p_ptr->action == ACTION_SEARCH) set_action(ACTION_NONE); - else set_action(ACTION_SEARCH); - break; - } - - - /*** Stairs and Doors and Chests and Traps ***/ - - /* Enter store */ - case SPECIAL_KEY_STORE: - { - do_cmd_store(); - break; - } - - /* Enter building -KMW- */ - case SPECIAL_KEY_BUILDING: - { - do_cmd_bldg(); - break; - } - - /* Enter quest level -KMW- */ - case SPECIAL_KEY_QUEST: - { - do_cmd_quest(); - break; - } - - /* Go up staircase */ - case '<': - { - if (!p_ptr->wild_mode && !current_floor_ptr->dun_level && !p_ptr->inside_arena && !p_ptr->inside_quest) - { - if (vanilla_town) break; - - if (p_ptr->ambush_flag) - { - msg_print(_("襲撃から逃げるにはマップの端まで移動しなければならない。", "To flee the ambush you have to reach the edge of the map.")); - break; - } - - if (p_ptr->food < PY_FOOD_WEAK) - { - msg_print(_("その前に食事をとらないと。", "You must eat something here.")); - break; - } - - change_wild_mode(); - } - else - do_cmd_go_up(); - break; - } - - /* Go down staircase */ - case '>': - { - if (p_ptr->wild_mode) - change_wild_mode(); - else - do_cmd_go_down(); - break; - } - - /* Open a door or chest */ - case 'o': - { - do_cmd_open(); - break; - } - - /* Close a door */ - case 'c': - { - do_cmd_close(); - break; - } - - /* Jam a door with spikes */ - case 'j': - { - do_cmd_spike(); - break; - } - - /* Bash a door */ - case 'B': - { - do_cmd_bash(); - break; - } - - /* Disarm a trap or chest */ - case 'D': - { - do_cmd_disarm(); - break; - } - - - /*** Magic and Prayers ***/ - - /* Gain new spells/prayers */ - case 'G': - { - if ((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE)) - msg_print(_("呪文を学習する必要はない!", "You don't have to learn spells!")); - else if (p_ptr->pclass == CLASS_SAMURAI) - do_cmd_gain_hissatsu(); - else if (p_ptr->pclass == CLASS_MAGIC_EATER) - import_magic_device(); - else - do_cmd_study(); - break; - } - - /* Browse a book */ - case 'b': - { - if ( (p_ptr->pclass == CLASS_MINDCRAFTER) || - (p_ptr->pclass == CLASS_BERSERKER) || - (p_ptr->pclass == CLASS_NINJA) || - (p_ptr->pclass == CLASS_MIRROR_MASTER) - ) do_cmd_mind_browse(); - else if (p_ptr->pclass == CLASS_SMITH) - do_cmd_kaji(TRUE); - else if (p_ptr->pclass == CLASS_MAGIC_EATER) - do_cmd_magic_eater(TRUE, FALSE); - else if (p_ptr->pclass == CLASS_SNIPER) - do_cmd_snipe_browse(); - else do_cmd_browse(); - break; - } - - /* Cast a spell */ - case 'm': - { - /* -KMW- */ - if (!p_ptr->wild_mode) - { - if ((p_ptr->pclass == CLASS_WARRIOR) || (p_ptr->pclass == CLASS_ARCHER) || (p_ptr->pclass == CLASS_CAVALRY)) - { - msg_print(_("呪文を唱えられない!", "You cannot cast spells!")); - } - else if (current_floor_ptr->dun_level && (d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_MAGIC) && (p_ptr->pclass != CLASS_BERSERKER) && (p_ptr->pclass != CLASS_SMITH)) - { - msg_print(_("ダンジョンが魔法を吸収した!", "The dungeon absorbs all attempted magic!")); - msg_print(NULL); - } - else if (p_ptr->anti_magic && (p_ptr->pclass != CLASS_BERSERKER) && (p_ptr->pclass != CLASS_SMITH)) - { - concptr which_power = _("魔法", "magic"); - if (p_ptr->pclass == CLASS_MINDCRAFTER) - which_power = _("超能力", "psionic powers"); - else if (p_ptr->pclass == CLASS_IMITATOR) - which_power = _("ものまね", "imitation"); - else if (p_ptr->pclass == CLASS_SAMURAI) - which_power = _("必殺剣", "hissatsu"); - else if (p_ptr->pclass == CLASS_MIRROR_MASTER) - which_power = _("鏡魔法", "mirror magic"); - else if (p_ptr->pclass == CLASS_NINJA) - which_power = _("忍術", "ninjutsu"); - else if (mp_ptr->spell_book == TV_LIFE_BOOK) - which_power = _("祈り", "prayer"); - - msg_format(_("反魔法バリアが%sを邪魔した!", "An anti-magic shell disrupts your %s!"), which_power); - free_turn(p_ptr); - } - else if (p_ptr->shero && (p_ptr->pclass != CLASS_BERSERKER)) - { - msg_format(_("狂戦士化していて頭が回らない!", "You cannot think directly!")); - free_turn(p_ptr); - } - else - { - if ((p_ptr->pclass == CLASS_MINDCRAFTER) || - (p_ptr->pclass == CLASS_BERSERKER) || - (p_ptr->pclass == CLASS_NINJA) || - (p_ptr->pclass == CLASS_MIRROR_MASTER) - ) - do_cmd_mind(); - else if (p_ptr->pclass == CLASS_IMITATOR) - do_cmd_mane(FALSE); - else if (p_ptr->pclass == CLASS_MAGIC_EATER) - do_cmd_magic_eater(FALSE, FALSE); - else if (p_ptr->pclass == CLASS_SAMURAI) - do_cmd_hissatsu(); - else if (p_ptr->pclass == CLASS_BLUE_MAGE) - do_cmd_cast_learned(); - else if (p_ptr->pclass == CLASS_SMITH) - do_cmd_kaji(FALSE); - else if (p_ptr->pclass == CLASS_SNIPER) - do_cmd_snipe(); - else - do_cmd_cast(); - } - } - break; - } - - /* Issue a pet command */ - case 'p': - { - do_cmd_pet(); - break; - } - - /*** Use various objects ***/ - - /* Inscribe an object */ - case '{': - { - do_cmd_inscribe(); - break; - } - - /* Uninscribe an object */ - case '}': - { - do_cmd_uninscribe(); - break; - } - - /* Activate an artifact */ - case 'A': - { - do_cmd_activate(); - break; - } - - /* Eat some food */ - case 'E': - { - do_cmd_eat_food(); - break; - } - - /* Fuel your lantern/torch */ - case 'F': - { - do_cmd_refill(); - break; - } - - /* Fire an item */ - case 'f': - { - do_cmd_fire(SP_NONE); - break; - } - - /* Throw an item */ - case 'v': - { - do_cmd_throw(1, FALSE, -1); - break; - } - - /* Aim a wand */ - case 'a': - { - do_cmd_aim_wand(); - break; - } - - /* Zap a rod */ - case 'z': - { - if (use_command && rogue_like_commands) - { - do_cmd_use(); - } - else - { - do_cmd_zap_rod(); - } - break; - } - - /* Quaff a potion */ - case 'q': - { - do_cmd_quaff_potion(); - break; - } - - /* Read a scroll */ - case 'r': - { - do_cmd_read_scroll(); - break; - } - - /* Use a staff */ - case 'u': - { - if (use_command && !rogue_like_commands) - do_cmd_use(); - else - do_cmd_use_staff(); - break; - } - - /* Use racial power */ - case 'U': - { - do_cmd_racial_power(); - break; - } - - - /*** Looking at Things (nearby or on map) ***/ - - /* Full dungeon map */ - case 'M': - { - do_cmd_view_map(); - break; - } - - /* Locate player on map */ - case 'L': - { - do_cmd_locate(); - break; - } - - /* Look around */ - case 'l': - { - do_cmd_look(); - break; - } - - /* Target monster or location */ - case '*': - { - do_cmd_target(); - break; - } - - - - /*** Help and Such ***/ - - /* Help */ - case '?': - { - do_cmd_help(); - break; - } - - /* Identify symbol */ - case '/': - { - do_cmd_query_symbol(); - break; - } - - /* Character description */ - case 'C': - { - do_cmd_change_name(); - break; - } - - - /*** System Commands ***/ - - /* Hack -- User interface */ - case '!': - { - (void)Term_user(0); - break; - } - - /* Single line from a pref file */ - case '"': - { - do_cmd_pref(); - break; - } - - case '$': - { - do_cmd_reload_autopick(); - break; - } - - case '_': - { - do_cmd_edit_autopick(); - break; - } - - /* Interact with macros */ - case '@': - { - do_cmd_macros(); - break; - } - - /* Interact with visuals */ - case '%': - { - do_cmd_visuals(); - do_cmd_redraw(); - break; - } - - /* Interact with colors */ - case '&': - { - do_cmd_colors(); - do_cmd_redraw(); - break; - } - - /* Interact with options */ - case '=': - { - do_cmd_options(); - (void)combine_and_reorder_home(STORE_HOME); - do_cmd_redraw(); - break; - } - - /*** Misc Commands ***/ - - /* Take notes */ - case ':': - { - do_cmd_note(); - break; - } - - /* Version info */ - case 'V': - { - do_cmd_version(); - break; - } - - /* Repeat level feeling */ - case KTRL('F'): - { - do_cmd_feeling(); - break; - } - - /* Show previous message */ - case KTRL('O'): - { - do_cmd_message_one(); - break; - } - - /* Show previous messages */ - case KTRL('P'): - { - do_cmd_messages(old_now_message); - break; - } - - /* Show quest status -KMW- */ - case KTRL('Q'): - { - do_cmd_checkquest(); - break; - } - - /* Redraw the screen */ - case KTRL('R'): - { - now_message = old_now_message; - do_cmd_redraw(); - break; - } - -#ifndef VERIFY_SAVEFILE - - /* Hack -- Save and don't quit */ - case KTRL('S'): - { - do_cmd_save_game(FALSE); - break; - } - -#endif /* VERIFY_SAVEFILE */ - - case KTRL('T'): - { - do_cmd_time(); - break; - } - - /* Save and quit */ - case KTRL('X'): - case SPECIAL_KEY_QUIT: - { - do_cmd_save_and_exit(); - break; - } - - /* Quit (commit suicide) */ - case 'Q': - { - do_cmd_suicide(); - break; - } - - case '|': - { - do_cmd_nikki(); - break; - } - - /* Check artifacts, uniques, objects */ - case '~': - { - do_cmd_knowledge(); - break; - } - - /* Load "screen dump" */ - case '(': - { - do_cmd_load_screen(); - break; - } - - /* Save "screen dump" */ - case ')': - { - do_cmd_save_screen(); - break; - } - - /* Record/stop "Movie" */ - case ']': - { - prepare_movie_hooks(); - break; - } - - /* Make random artifact list */ - case KTRL('V'): - { - spoil_random_artifact("randifact.txt"); - break; - } - -#ifdef TRAVEL - case '`': - { - if (!p_ptr->wild_mode) do_cmd_travel(); - if (p_ptr->special_defense & KATA_MUSOU) - { - set_action(ACTION_NONE); - } - break; - } -#endif - - /* Hack -- Unknown command */ - default: - { - if (flush_failure) flush(); - if (one_in_(2)) - { - char error_m[1024]; - sound(SOUND_ILLEGAL); - if (!get_rnd_line(_("error_j.txt", "error.txt"), 0, error_m)) - msg_print(error_m); - } - else - { - prt(_(" '?' でヘルプが表示されます。", "Type '?' for help."), 0, 0); - } - - break; - } - } - if (!p_ptr->energy_use && !now_message) - now_message = old_now_message; -} - -/*! - * @brief アイテムの所持種類数が超えた場合にアイテムを床に落とす処理 / Hack -- Pack Overflow - * @return なし - */ -static void pack_overflow(void) -{ - if (inventory[INVEN_PACK].k_idx) - { - GAME_TEXT o_name[MAX_NLEN]; - object_type *o_ptr; - - /* Is auto-destroy done? */ - update_creature(p_ptr); - if (!inventory[INVEN_PACK].k_idx) return; - - /* Access the slot to be dropped */ - o_ptr = &inventory[INVEN_PACK]; - - disturb(FALSE, TRUE); - - /* Warning */ - msg_print(_("ザックからアイテムがあふれた!", "Your pack overflows!")); - object_desc(o_name, o_ptr, 0); - - msg_format(_("%s(%c)を落とした。", "You drop %s (%c)."), o_name, index_to_label(INVEN_PACK)); - - /* Drop it (carefully) near the player */ - (void)drop_near(o_ptr, 0, p_ptr->y, p_ptr->x); - - /* Modify, Describe, Optimize */ - inven_item_increase(INVEN_PACK, -255); - inven_item_describe(INVEN_PACK); - inven_item_optimize(INVEN_PACK); - - handle_stuff(); - } -} - -/*! - * @brief プレイヤーの行動エネルギーが充填される(=プレイヤーのターンが回る)毎に行われる処理 / process the effects per 100 energy at player speed. - * @return なし - */ -static void process_upkeep_with_speed(void) -{ - /* Give the player some energy */ - if (!load && p_ptr->enchant_energy_need > 0 && !p_ptr->leaving) - { - p_ptr->enchant_energy_need -= SPEED_TO_ENERGY(p_ptr->pspeed); - } - - /* No current_world_ptr->game_turn yet */ - if (p_ptr->enchant_energy_need > 0) return; - - while (p_ptr->enchant_energy_need <= 0) - { - /* Handle the player song */ - if (!load) check_music(); - - /* Hex - Handle the hex spells */ - if (!load) check_hex(); - if (!load) revenge_spell(); - - /* There is some randomness of needed energy */ - p_ptr->enchant_energy_need += ENERGY_NEED(); - } -} - -/*! - * @brief プレイヤーの行動処理 / Process the player - * @return なし - * @note - * Notice the annoying code to handle "pack overflow", which\n - * must come first just in case somebody manages to corrupt\n - * the savefiles by clever use of menu commands or something.\n - */ -static void process_player(void) -{ - MONSTER_IDX m_idx; - - /*** Apply energy ***/ - - if (hack_mutation) - { - msg_print(_("何か変わった気がする!", "You feel different!")); - - (void)gain_mutation(p_ptr, 0); - hack_mutation = FALSE; - } - - if (invoking_midnight_curse) - { - int count = 0; - activate_ty_curse(FALSE, &count); - invoking_midnight_curse = FALSE; - } - - if (p_ptr->inside_battle) - { - for(m_idx = 1; m_idx < m_max; m_idx++) - { - monster_type *m_ptr = ¤t_floor_ptr->m_list[m_idx]; - - if (!monster_is_valid(m_ptr)) continue; - - m_ptr->mflag2 |= (MFLAG2_MARK | MFLAG2_SHOW); - update_monster(m_idx, FALSE); - } - prt_time(); - } - - /* Give the player some energy */ - else if (!(load && p_ptr->energy_need <= 0)) - { - p_ptr->energy_need -= SPEED_TO_ENERGY(p_ptr->pspeed); - } - - /* No current_world_ptr->game_turn yet */ - if (p_ptr->energy_need > 0) return; - if (!command_rep) prt_time(); - - /*** Check for interupts ***/ - - /* Complete resting */ - if (p_ptr->resting < 0) - { - /* Basic resting */ - if (p_ptr->resting == COMMAND_ARG_REST_FULL_HEALING) - { - /* Stop resting */ - if ((p_ptr->chp == p_ptr->mhp) && - (p_ptr->csp >= p_ptr->msp)) - { - set_action(ACTION_NONE); - } - } - - /* Complete resting */ - else if (p_ptr->resting == COMMAND_ARG_REST_UNTIL_DONE) - { - /* Stop resting */ - if ((p_ptr->chp == p_ptr->mhp) && - (p_ptr->csp >= p_ptr->msp) && - !p_ptr->blind && !p_ptr->confused && - !p_ptr->poisoned && !p_ptr->afraid && - !p_ptr->stun && !p_ptr->cut && - !p_ptr->slow && !p_ptr->paralyzed && - !p_ptr->image && !p_ptr->word_recall && - !p_ptr->alter_reality) - { - set_action(ACTION_NONE); - } - } - } - - if (p_ptr->action == ACTION_FISH) - { - Term_xtra(TERM_XTRA_DELAY, 10); - if (one_in_(1000)) - { - MONRACE_IDX r_idx; - bool success = FALSE; - get_mon_num_prep(monster_is_fishing_target,NULL); - r_idx = get_mon_num(current_floor_ptr->dun_level ? current_floor_ptr->dun_level : wilderness[p_ptr->wilderness_y][p_ptr->wilderness_x].level); - msg_print(NULL); - if (r_idx && one_in_(2)) - { - POSITION y, x; - y = p_ptr->y + ddy[p_ptr->fishing_dir]; - x = p_ptr->x + ddx[p_ptr->fishing_dir]; - if (place_monster_aux(0, y, x, r_idx, PM_NO_KAGE)) - { - GAME_TEXT m_name[MAX_NLEN]; - monster_desc(m_name, ¤t_floor_ptr->m_list[current_floor_ptr->grid_array[y][x].m_idx], 0); - msg_format(_("%sが釣れた!", "You have a good catch!"), m_name); - success = TRUE; - } - } - if (!success) - { - msg_print(_("餌だけ食われてしまった!くっそ~!", "Damn! The fish stole your bait!")); - } - disturb(FALSE, TRUE); - } - } - - /* Handle "abort" */ - if (check_abort) - { - /* Check for "player abort" (semi-efficiently for resting) */ - if (running || travel.run || command_rep || (p_ptr->action == ACTION_REST) || (p_ptr->action == ACTION_FISH)) - { - /* Do not wait */ - inkey_scan = TRUE; - - /* Check for a key */ - if (inkey()) - { - flush(); /* Flush input */ - - disturb(FALSE, TRUE); - - /* Hack -- Show a Message */ - msg_print(_("中断しました。", "Canceled.")); - } - } - } - - if (p_ptr->riding && !p_ptr->confused && !p_ptr->blind) - { - monster_type *m_ptr = ¤t_floor_ptr->m_list[p_ptr->riding]; - monster_race *r_ptr = &r_info[m_ptr->r_idx]; - - if (MON_CSLEEP(m_ptr)) - { - GAME_TEXT m_name[MAX_NLEN]; - - /* Recover fully */ - (void)set_monster_csleep(p_ptr->riding, 0); - monster_desc(m_name, m_ptr, 0); - msg_format(_("%^sを起こした。", "You have waked %s up."), m_name); - } - - if (MON_STUNNED(m_ptr)) - { - /* Hack -- Recover from stun */ - if (set_monster_stunned(p_ptr->riding, - (randint0(r_ptr->level) < p_ptr->skill_exp[GINOU_RIDING]) ? 0 : (MON_STUNNED(m_ptr) - 1))) - { - GAME_TEXT m_name[MAX_NLEN]; - monster_desc(m_name, m_ptr, 0); - msg_format(_("%^sを朦朧状態から立ち直らせた。", "%^s is no longer stunned."), m_name); - } - } - - if (MON_CONFUSED(m_ptr)) - { - /* Hack -- Recover from confusion */ - if (set_monster_confused(p_ptr->riding, - (randint0(r_ptr->level) < p_ptr->skill_exp[GINOU_RIDING]) ? 0 : (MON_CONFUSED(m_ptr) - 1))) - { - GAME_TEXT m_name[MAX_NLEN]; - monster_desc(m_name, m_ptr, 0); - msg_format(_("%^sを混乱状態から立ち直らせた。", "%^s is no longer confused."), m_name); - } - } - - if (MON_MONFEAR(m_ptr)) - { - /* Hack -- Recover from fear */ - if(set_monster_monfear(p_ptr->riding, - (randint0(r_ptr->level) < p_ptr->skill_exp[GINOU_RIDING]) ? 0 : (MON_MONFEAR(m_ptr) - 1))) - { - GAME_TEXT m_name[MAX_NLEN]; - monster_desc(m_name, m_ptr, 0); - msg_format(_("%^sを恐怖から立ち直らせた。", "%^s is no longer fear."), m_name); - } - } - - handle_stuff(); - } - - load = FALSE; - - /* Fast */ - if (p_ptr->lightspeed) - { - (void)set_lightspeed(p_ptr->lightspeed - 1, TRUE); - } - if ((p_ptr->pclass == CLASS_FORCETRAINER) && P_PTR_KI) - { - if(P_PTR_KI < 40) P_PTR_KI = 0; - else P_PTR_KI -= 40; - p_ptr->update |= (PU_BONUS); - } - if (p_ptr->action == ACTION_LEARN) - { - s32b cost = 0L; - u32b cost_frac = (p_ptr->msp + 30L) * 256L; - - /* Convert the unit (1/2^16) to (1/2^32) */ - s64b_LSHIFT(cost, cost_frac, 16); - - if (s64b_cmp(p_ptr->csp, p_ptr->csp_frac, cost, cost_frac) < 0) - { - /* Mana run out */ - p_ptr->csp = 0; - p_ptr->csp_frac = 0; - set_action(ACTION_NONE); - } - else - { - /* Reduce mana */ - s64b_sub(&(p_ptr->csp), &(p_ptr->csp_frac), cost, cost_frac); - } - p_ptr->redraw |= PR_MANA; - } - - if (p_ptr->special_defense & KATA_MASK) - { - if (p_ptr->special_defense & KATA_MUSOU) - { - if (p_ptr->csp < 3) - { - set_action(ACTION_NONE); - } - else - { - p_ptr->csp -= 2; - p_ptr->redraw |= (PR_MANA); - } - } - } - - /*** Handle actual user input ***/ - - /* Repeat until out of energy */ - while (p_ptr->energy_need <= 0) - { - p_ptr->window |= PW_PLAYER; - p_ptr->sutemi = FALSE; - p_ptr->counter = FALSE; - p_ptr->now_damaged = FALSE; - - handle_stuff(); - - /* Place the cursor on the player */ - move_cursor_relative(p_ptr->y, p_ptr->x); - - /* Refresh (optional) */ - if (fresh_before) Term_fresh(); - - /* Hack -- Pack Overflow */ - pack_overflow(); - - /* Hack -- cancel "lurking browse mode" */ - if (!command_new) command_see = FALSE; - - /* Assume free current_world_ptr->game_turn */ - free_turn(p_ptr); - - if (p_ptr->inside_battle) - { - /* Place the cursor on the player */ - move_cursor_relative(p_ptr->y, p_ptr->x); - - command_cmd = SPECIAL_KEY_BUILDING; - - /* Process the command */ - process_command(); - } - - /* Paralyzed or Knocked Out */ - else if (p_ptr->paralyzed || (p_ptr->stun >= 100)) - { - take_turn(p_ptr, 100); - } - - /* Resting */ - else if (p_ptr->action == ACTION_REST) - { - /* Timed rest */ - if (p_ptr->resting > 0) - { - /* Reduce rest count */ - p_ptr->resting--; - - if (!p_ptr->resting) set_action(ACTION_NONE); - p_ptr->redraw |= (PR_STATE); - } - - take_turn(p_ptr, 100); - } - - /* Fishing */ - else if (p_ptr->action == ACTION_FISH) - { - take_turn(p_ptr, 100); - } - - /* Running */ - else if (running) - { - /* Take a step */ - run_step(0); - } - -#ifdef TRAVEL - /* Traveling */ - else if (travel.run) - { - /* Take a step */ - travel_step(); - } -#endif - - /* Repeated command */ - else if (command_rep) - { - /* Count this execution */ - command_rep--; - - p_ptr->redraw |= (PR_STATE); - handle_stuff(); - - /* Hack -- Assume messages were seen */ - msg_flag = FALSE; - - /* Clear the top line */ - prt("", 0, 0); - - /* Process the command */ - process_command(); - } - - /* Normal command */ - else - { - /* Place the cursor on the player */ - move_cursor_relative(p_ptr->y, p_ptr->x); - - if(refresh_mon_list) - { - p_ptr->window |= PW_MONSTER_LIST; - update_output(); - } - - can_save = TRUE; - /* Get a command (normal) */ - request_command(FALSE); - can_save = FALSE; - - /* Process the command */ - process_command(); - } - - /* Hack -- Pack Overflow */ - pack_overflow(); - - /*** Clean up ***/ - - /* Significant */ - if (p_ptr->energy_use) - { - /* Use some energy */ - if (p_ptr->timewalk || p_ptr->energy_use > 400) - { - /* The Randomness is irrelevant */ - p_ptr->energy_need += p_ptr->energy_use * TURNS_PER_TICK / 10; - } - else - { - /* There is some randomness of needed energy */ - p_ptr->energy_need += (s16b)((s32b)p_ptr->energy_use * ENERGY_NEED() / 100L); - } - - /* Hack -- constant hallucination */ - if (p_ptr->image) p_ptr->redraw |= (PR_MAP); - - - /* Shimmer monsters if needed */ - if (shimmer_monsters) - { - /* Clear the flag */ - shimmer_monsters = FALSE; - - /* Shimmer multi-hued monsters */ - for (m_idx = 1; m_idx < m_max; m_idx++) - { - monster_type *m_ptr; - monster_race *r_ptr; - - m_ptr = ¤t_floor_ptr->m_list[m_idx]; - if (!monster_is_valid(m_ptr)) continue; - - /* Skip unseen monsters */ - if (!m_ptr->ml) continue; - - /* Access the monster race */ - r_ptr = &r_info[m_ptr->ap_r_idx]; - - /* Skip non-multi-hued monsters */ - if (!(r_ptr->flags1 & (RF1_ATTR_MULTI | RF1_SHAPECHANGER))) - continue; - - /* Reset the flag */ - shimmer_monsters = TRUE; - - /* Redraw regardless */ - lite_spot(m_ptr->fy, m_ptr->fx); - } - } - - - /* Handle monster detection */ - if (repair_monsters) - { - /* Reset the flag */ - repair_monsters = FALSE; - - /* Rotate detection flags */ - for (m_idx = 1; m_idx < m_max; m_idx++) - { - monster_type *m_ptr; - m_ptr = ¤t_floor_ptr->m_list[m_idx]; - if (!monster_is_valid(m_ptr)) continue; - - /* Nice monsters get mean */ - if (m_ptr->mflag & MFLAG_NICE) - { - /* Nice monsters get mean */ - m_ptr->mflag &= ~(MFLAG_NICE); - } - - /* Handle memorized monsters */ - if (m_ptr->mflag2 & MFLAG2_MARK) - { - /* Maintain detection */ - if (m_ptr->mflag2 & MFLAG2_SHOW) - { - /* Forget flag */ - m_ptr->mflag2 &= ~(MFLAG2_SHOW); - - /* Still need repairs */ - repair_monsters = TRUE; - } - - /* Remove detection */ - else - { - /* Forget flag */ - m_ptr->mflag2 &= ~(MFLAG2_MARK); - - /* Assume invisible */ - m_ptr->ml = FALSE; - update_monster(m_idx, FALSE); - - if (p_ptr->health_who == m_idx) p_ptr->redraw |= (PR_HEALTH); - if (p_ptr->riding == m_idx) p_ptr->redraw |= (PR_UHEALTH); - - /* Redraw regardless */ - lite_spot(m_ptr->fy, m_ptr->fx); - } - } - } - } - if (p_ptr->pclass == CLASS_IMITATOR) - { - int j; - if (p_ptr->mane_num > (p_ptr->lev > 44 ? 3 : p_ptr->lev > 29 ? 2 : 1)) - { - p_ptr->mane_num--; - for (j = 0; j < p_ptr->mane_num; j++) - { - p_ptr->mane_spell[j] = p_ptr->mane_spell[j + 1]; - p_ptr->mane_dam[j] = p_ptr->mane_dam[j + 1]; - } - } - new_mane = FALSE; - p_ptr->redraw |= (PR_IMITATION); - } - if (p_ptr->action == ACTION_LEARN) - { - new_mane = FALSE; - p_ptr->redraw |= (PR_STATE); - } - - if (p_ptr->timewalk && (p_ptr->energy_need > - 1000)) - { - - p_ptr->redraw |= (PR_MAP); - p_ptr->update |= (PU_MONSTERS); - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); - - msg_print(_("「時は動きだす…」", "You feel time flowing around you once more.")); - msg_print(NULL); - p_ptr->timewalk = FALSE; - p_ptr->energy_need = ENERGY_NEED(); - - handle_stuff(); - } - } - - /* Hack -- notice death */ - if (!p_ptr->playing || p_ptr->is_dead) - { - p_ptr->timewalk = FALSE; - break; - } - - /* Sniper */ - if (p_ptr->energy_use && reset_concent) reset_concentration(TRUE); - - /* Handle "leaving" */ - if (p_ptr->leaving) break; - } - - /* Update scent trail */ - update_smell(); -} - -/*! - * @brief 現在プレイヤーがいるダンジョンの全体処理 / Interact with the current dungeon level. - * @return なし - * @details - *

- * この関数から現在の階層を出る、プレイヤーがキャラが死ぬ、 - * ゲームを終了するかのいずれかまでループする。 - *

- *

- * This function will not exit until the level is completed,\n - * the user dies, or the game is terminated.\n - *

- */ -static void dungeon(bool load_game) -{ - int quest_num = 0; - - /* Set the base level */ - current_floor_ptr->base_level = current_floor_ptr->dun_level; - - /* Reset various flags */ - is_loading_now = FALSE; - - /* Not leaving */ - p_ptr->leaving = FALSE; - - /* Reset the "command" vars */ - command_cmd = 0; - -#if 0 /* Don't reset here --- It's used for Arena */ - command_new = 0; -#endif - - command_rep = 0; - command_arg = 0; - command_dir = 0; - - - /* Cancel the target */ - target_who = 0; - pet_t_m_idx = 0; - riding_t_m_idx = 0; - p_ptr->ambush_flag = FALSE; - - /* Cancel the health bar */ - health_track(0); - - /* Check visual effects */ - shimmer_monsters = TRUE; - shimmer_objects = TRUE; - repair_monsters = TRUE; - repair_objects = TRUE; - - - disturb(TRUE, TRUE); - - /* Get index of current quest (if any) */ - quest_num = quest_number(current_floor_ptr->dun_level); - - /* Inside a quest? */ - if (quest_num) - { - /* Mark the quest monster */ - r_info[quest[quest_num].r_idx].flags1 |= RF1_QUESTOR; - } - - /* Track maximum player level */ - if (p_ptr->max_plv < p_ptr->lev) - { - p_ptr->max_plv = p_ptr->lev; - } - - - /* Track maximum dungeon level (if not in quest -KMW-) */ - if ((max_dlv[p_ptr->dungeon_idx] < current_floor_ptr->dun_level) && !p_ptr->inside_quest) - { - max_dlv[p_ptr->dungeon_idx] = current_floor_ptr->dun_level; - if (record_maxdepth) do_cmd_write_nikki(NIKKI_MAXDEAPTH, current_floor_ptr->dun_level, NULL); - } - - (void)calculate_upkeep(); - - /* Validate the panel */ - panel_bounds_center(); - - /* Verify the panel */ - verify_panel(); - - msg_erase(); - - - /* Enter "xtra" mode */ - character_xtra = TRUE; - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER | PW_MONSTER | PW_OVERHEAD | PW_DUNGEON); - p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_EQUIPPY | PR_MAP); - p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_VIEW | PU_LITE | PU_MON_LITE | PU_TORCH | PU_MONSTERS | PU_DISTANCE | PU_FLOW); - - handle_stuff(); - - /* Leave "xtra" mode */ - character_xtra = FALSE; - - p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS); - p_ptr->update |= (PU_COMBINE | PU_REORDER); - handle_stuff(); - Term_fresh(); - - if (quest_num && (is_fixed_quest_idx(quest_num) && - !((quest_num == QUEST_OBERON) || (quest_num == QUEST_SERPENT) || - !(quest[quest_num].flags & QUEST_FLAG_PRESET)))) do_cmd_feeling(); - - if (p_ptr->inside_battle) - { - if (load_game) - { - p_ptr->energy_need = 0; - battle_monsters(); - } - else - { - msg_print(_("試合開始!", "Ready..Fight!")); - msg_print(NULL); - } - } - - if ((p_ptr->pclass == CLASS_BARD) && (SINGING_SONG_EFFECT(p_ptr) > MUSIC_DETECT)) - SINGING_SONG_EFFECT(p_ptr) = MUSIC_DETECT; - - /* Hack -- notice death or departure */ - if (!p_ptr->playing || p_ptr->is_dead) return; - - /* Print quest message if appropriate */ - if (!p_ptr->inside_quest && (p_ptr->dungeon_idx == DUNGEON_ANGBAND)) - { - quest_discovery(random_quest_number(current_floor_ptr->dun_level)); - p_ptr->inside_quest = random_quest_number(current_floor_ptr->dun_level); - } - if ((current_floor_ptr->dun_level == d_info[p_ptr->dungeon_idx].maxdepth) && d_info[p_ptr->dungeon_idx].final_guardian) - { - if (r_info[d_info[p_ptr->dungeon_idx].final_guardian].max_num) -#ifdef JP - msg_format("この階には%sの主である%sが棲んでいる。", - d_name+d_info[p_ptr->dungeon_idx].name, - r_name+r_info[d_info[p_ptr->dungeon_idx].final_guardian].name); -#else - msg_format("%^s lives in this level as the keeper of %s.", - r_name+r_info[d_info[p_ptr->dungeon_idx].final_guardian].name, - d_name+d_info[p_ptr->dungeon_idx].name); -#endif - } - - if (!load_game && (p_ptr->special_defense & NINJA_S_STEALTH)) set_superstealth(FALSE); - - /*** Process this dungeon level ***/ - - /* Reset the monster generation level */ - current_floor_ptr->monster_level = current_floor_ptr->base_level; - - /* Reset the object generation level */ - current_floor_ptr->object_level = current_floor_ptr->base_level; - - is_loading_now = TRUE; - - if (p_ptr->energy_need > 0 && !p_ptr->inside_battle && - (current_floor_ptr->dun_level || p_ptr->leaving_dungeon || p_ptr->inside_arena)) - p_ptr->energy_need = 0; - - /* Not leaving dungeon */ - p_ptr->leaving_dungeon = FALSE; - - /* Initialize monster process */ - mproc_init(); - - /* Main loop */ - while (TRUE) - { - /* Hack -- Compact the monster list occasionally */ - if ((m_cnt + 32 > current_floor_ptr->max_m_idx) && !p_ptr->inside_battle) compact_monsters(64); - - /* Hack -- Compress the monster list occasionally */ - if ((m_cnt + 32 < m_max) && !p_ptr->inside_battle) compact_monsters(0); - - - /* Hack -- Compact the object list occasionally */ - if (o_cnt + 32 > current_floor_ptr->max_o_idx) compact_objects(64); - - /* Hack -- Compress the object list occasionally */ - if (o_cnt + 32 < o_max) compact_objects(0); - - /* Process the player */ - process_player(); - process_upkeep_with_speed(); - - handle_stuff(); - - /* Hack -- Hilite the player */ - move_cursor_relative(p_ptr->y, p_ptr->x); - - /* Optional fresh */ - if (fresh_after) Term_fresh(); - - /* Hack -- Notice death or departure */ - if (!p_ptr->playing || p_ptr->is_dead) break; - - /* Process all of the monsters */ - process_monsters(); - - handle_stuff(); - - /* Hack -- Hilite the player */ - move_cursor_relative(p_ptr->y, p_ptr->x); - - /* Optional fresh */ - if (fresh_after) Term_fresh(); - - /* Hack -- Notice death or departure */ - if (!p_ptr->playing || p_ptr->is_dead) break; - - /* Process the world */ - process_world(); - - handle_stuff(); - - /* Hack -- Hilite the player */ - move_cursor_relative(p_ptr->y, p_ptr->x); - - /* Optional fresh */ - if (fresh_after) Term_fresh(); - - /* Hack -- Notice death or departure */ - if (!p_ptr->playing || p_ptr->is_dead) break; - - /* Count game turns */ - current_world_ptr->game_turn++; - - if (current_world_ptr->dungeon_turn < current_world_ptr->dungeon_turn_limit) - { - if (!p_ptr->wild_mode || wild_regen) current_world_ptr->dungeon_turn++; - else if (p_ptr->wild_mode && !(current_world_ptr->game_turn % ((MAX_HGT + MAX_WID) / 2))) current_world_ptr->dungeon_turn++; - } - - prevent_turn_overflow(); - - /* Handle "leaving" */ - if (p_ptr->leaving) break; - - if (wild_regen) wild_regen--; - } - - /* Inside a quest and non-unique questor? */ - if (quest_num && !(r_info[quest[quest_num].r_idx].flags1 & RF1_UNIQUE)) - { - /* Un-mark the quest monster */ - r_info[quest[quest_num].r_idx].flags1 &= ~RF1_QUESTOR; - } - - /* Not save-and-quit and not dead? */ - if (p_ptr->playing && !p_ptr->is_dead) - { - /* - * Maintain Unique monsters and artifact, save current - * floor, then prepare next floor - */ - leave_floor(); - - /* Forget the flag */ - reinit_wilderness = FALSE; - } - - /* Write about current level on the play record once per level */ - write_level = TRUE; -} - - -/*! - * @brief 全ユーザプロファイルをロードする / Load some "user pref files" - * @return なし - * @note - * Modified by Arcum Dagsson to support - * separate macro files for different realms. - */ -static void load_all_pref_files(void) -{ - char buf[1024]; - - /* Access the "user" pref file */ - sprintf(buf, "user.prf"); - - /* Process that file */ - process_pref_file(buf); - - /* Access the "user" system pref file */ - sprintf(buf, "user-%s.prf", ANGBAND_SYS); - - /* Process that file */ - process_pref_file(buf); - - /* Access the "race" pref file */ - sprintf(buf, "%s.prf", rp_ptr->title); - - /* Process that file */ - process_pref_file(buf); - - /* Access the "class" pref file */ - sprintf(buf, "%s.prf", cp_ptr->title); - - /* Process that file */ - process_pref_file(buf); - - /* Access the "character" pref file */ - sprintf(buf, "%s.prf", player_base); - - /* Process that file */ - process_pref_file(buf); - - /* Access the "realm 1" pref file */ - if (p_ptr->realm1 != REALM_NONE) - { - sprintf(buf, "%s.prf", realm_names[p_ptr->realm1]); - - /* Process that file */ - process_pref_file(buf); - } - - /* Access the "realm 2" pref file */ - if (p_ptr->realm2 != REALM_NONE) - { - sprintf(buf, "%s.prf", realm_names[p_ptr->realm2]); - - /* Process that file */ - process_pref_file(buf); - } - - - /* Load an autopick preference file */ - autopick_load_pref(FALSE); -} - - -/*! - * @brief ビットセットからゲームオプションを展開する / Extract option variables from bit sets - * @return なし - */ -void extract_option_vars(void) -{ - int i; - - for (i = 0; option_info[i].o_desc; i++) - { - int os = option_info[i].o_set; - int ob = option_info[i].o_bit; - - /* Set the "default" options */ - if (option_info[i].o_var) - { - /* Set */ - if (option_flag[os] & (1L << ob)) - { - /* Set */ - (*option_info[i].o_var) = TRUE; - } - - /* Clear */ - else - { - /* Clear */ - (*option_info[i].o_var) = FALSE; - } - } - } -} - - -/*! - * @brief 賞金首となるユニークを確定する / Determine bounty uniques - * @return なし - */ -void determine_bounty_uniques(void) -{ - int i, j; - MONRACE_IDX tmp; - monster_race *r_ptr; - - get_mon_num_prep(NULL, NULL); - for (i = 0; i < MAX_KUBI; i++) - { - while (1) - { - current_world_ptr->bounty_r_idx[i] = get_mon_num(MAX_DEPTH - 1); - r_ptr = &r_info[current_world_ptr->bounty_r_idx[i]]; - - if (!(r_ptr->flags1 & RF1_UNIQUE)) continue; - - if (!(r_ptr->flags9 & (RF9_DROP_CORPSE | RF9_DROP_SKELETON))) continue; - - if (r_ptr->rarity > 100) continue; - - if (no_questor_or_bounty_uniques(current_world_ptr->bounty_r_idx[i])) continue; - - for (j = 0; j < i; j++) - if (current_world_ptr->bounty_r_idx[i] == current_world_ptr->bounty_r_idx[j]) break; - - if (j == i) break; - } - } - - /* Sort them */ - for (i = 0; i < MAX_KUBI - 1; i++) - { - for (j = i; j < MAX_KUBI; j++) - { - if (r_info[current_world_ptr->bounty_r_idx[i]].level > r_info[current_world_ptr->bounty_r_idx[j]].level) - { - tmp = current_world_ptr->bounty_r_idx[i]; - current_world_ptr->bounty_r_idx[i] = current_world_ptr->bounty_r_idx[j]; - current_world_ptr->bounty_r_idx[j] = tmp; - } - } - } -} - - -/*! - * @brief 今日の賞金首を確定する / Determine today's bounty monster - * @return なし - * @note conv_old is used if loaded 0.0.3 or older save file - */ -void determine_today_mon(bool conv_old) -{ - int max_dl = 3, i; - bool old_inside_battle = p_ptr->inside_battle; - monster_race *r_ptr; - - if (!conv_old) - { - for (i = 0; i < max_d_idx; i++) - { - if (max_dlv[i] < d_info[i].mindepth) continue; - if (max_dl < max_dlv[i]) max_dl = max_dlv[i]; - } - } - else max_dl = MAX(max_dlv[DUNGEON_ANGBAND], 3); - - p_ptr->inside_battle = TRUE; - get_mon_num_prep(NULL, NULL); - - while (1) - { - today_mon = get_mon_num(max_dl); - r_ptr = &r_info[today_mon]; - - if (r_ptr->flags1 & RF1_UNIQUE) continue; - if (r_ptr->flags7 & (RF7_NAZGUL | RF7_UNIQUE2)) continue; - if (r_ptr->flags2 & RF2_MULTIPLY) continue; - if ((r_ptr->flags9 & (RF9_DROP_CORPSE | RF9_DROP_SKELETON)) != (RF9_DROP_CORPSE | RF9_DROP_SKELETON)) continue; - if (r_ptr->level < MIN(max_dl / 2, 40)) continue; - if (r_ptr->rarity > 10) continue; - break; - } - - p_ptr->today_mon = 0; - p_ptr->inside_battle = old_inside_battle; -} - -/*! - * @brief 1ゲームプレイの主要ルーチン / Actually play a game - * @return なし - * @note - * If the "new_game" parameter is true, then, after loading the - * savefile, we will commit suicide, if necessary, to allow the - * player to start a new game. - */ -void play_game(bool new_game) -{ - MONSTER_IDX i; - bool load_game = TRUE; - bool init_random_seed = FALSE; - -#ifdef CHUUKEI - if (chuukei_client) - { - reset_visuals(); - browse_chuukei(); - return; - } - - else if (chuukei_server) - { - prepare_chuukei_hooks(); - } -#endif - - if (browsing_movie) - { - reset_visuals(); - browse_movie(); - return; - } - - hack_mutation = FALSE; - - /* Hack -- Character is "icky" */ - character_icky = TRUE; - - /* Make sure main term is active */ - Term_activate(angband_term[0]); - - /* Initialise the resize hooks */ - angband_term[0]->resize_hook = resize_map; - - for (i = 1; i < 8; i++) - { - /* Does the term exist? */ - if (angband_term[i]) - { - /* Add the redraw on resize hook */ - angband_term[i]->resize_hook = redraw_window; - } - } - - /* Hack -- current_world_ptr->game_turn off the cursor */ - (void)Term_set_cursor(0); - - - /* Attempt to load */ - if (!load_player()) - { - quit(_("セーブファイルが壊れています", "broken savefile")); - } - - /* Extract the options */ - extract_option_vars(); - - /* Report waited score */ - if (p_ptr->wait_report_score) - { - char buf[1024]; - bool success; - - if (!get_check_strict(_("待機していたスコア登録を今行ないますか?", "Do you register score now? "), CHECK_NO_HISTORY)) - quit(0); - - p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS); - update_creature(p_ptr); - - p_ptr->is_dead = TRUE; - - start_time = (u32b)time(NULL); - - /* No suspending now */ - signals_ignore_tstp(); - - /* Hack -- Character is now "icky" */ - character_icky = TRUE; - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); - - /* Open the high score file, for reading/writing */ - highscore_fd = fd_open(buf, O_RDWR); - - /* 町名消失バグ対策(#38205) Init the wilderness */ - process_dungeon_file("w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x); - - /* Handle score, show Top scores */ - success = send_world_score(TRUE); - - if (!success && !get_check_strict(_("スコア登録を諦めますか?", "Do you give up score registration? "), CHECK_NO_HISTORY)) - { - prt(_("引き続き待機します。", "standing by for future registration..."), 0, 0); - (void)inkey(); - } - else - { - p_ptr->wait_report_score = FALSE; - top_twenty(); - if (!save_player()) msg_print(_("セーブ失敗!", "death save failed!")); - } - /* Shut the high score file */ - (void)fd_close(highscore_fd); - - /* Forget the high score fd */ - highscore_fd = -1; - - /* Allow suspending now */ - signals_handle_tstp(); - - quit(0); - } - - creating_savefile = new_game; - - /* Nothing loaded */ - if (!character_loaded) - { - /* Make new player */ - new_game = TRUE; - - /* The dungeon is not ready */ - character_dungeon = FALSE; - - /* Prepare to init the RNG */ - init_random_seed = TRUE; - - /* Initialize the saved floors data */ - init_saved_floors(FALSE); - } - - /* Old game is loaded. But new game is requested. */ - else if (new_game) - { - /* Initialize the saved floors data */ - init_saved_floors(TRUE); - } - - /* Process old character */ - if (!new_game) - { - /* Process the player name */ - process_player_name(FALSE); - } - - /* Init the RNG */ - if (init_random_seed) - { - Rand_state_init(); - } - - /* Roll new character */ - if (new_game) - { - /* The dungeon is not ready */ - character_dungeon = FALSE; - - /* Start in town */ - current_floor_ptr->dun_level = 0; - p_ptr->inside_quest = 0; - p_ptr->inside_arena = FALSE; - p_ptr->inside_battle = FALSE; - - write_level = TRUE; - - /* Hack -- seed for flavors */ - seed_flavor = randint0(0x10000000); - - /* Hack -- seed for town layout */ - seed_town = randint0(0x10000000); - - /* Roll up a new character */ - player_birth(); - - counts_write(2,0); - p_ptr->count = 0; - - load = FALSE; - - determine_bounty_uniques(); - determine_today_mon(FALSE); - - /* Initialize object array */ - wipe_o_list(); - } - else - { - write_level = FALSE; - - do_cmd_write_nikki(NIKKI_GAMESTART, 1, - _(" ----ゲーム再開----", - " ---- Restart Game ----")); - -/* - * 1.0.9 以前はセーブ前に p_ptr->riding = -1 としていたので、再設定が必要だった。 - * もう不要だが、以前のセーブファイルとの互換のために残しておく。 - */ - if (p_ptr->riding == -1) - { - p_ptr->riding = 0; - for (i = m_max; i > 0; i--) - { - if (player_bold(current_floor_ptr->m_list[i].fy, current_floor_ptr->m_list[i].fx)) - { - p_ptr->riding = i; - break; - } - } - } - } - - creating_savefile = FALSE; - - p_ptr->teleport_town = FALSE; - p_ptr->sutemi = FALSE; - current_world_ptr->timewalk_m_idx = 0; - p_ptr->now_damaged = FALSE; - now_message = 0; - start_time = time(NULL) - 1; - record_o_name[0] = '\0'; - - /* Reset map panel */ - panel_row_min = current_floor_ptr->height; - panel_col_min = current_floor_ptr->width; - - /* Sexy gal gets bonus to maximum weapon skill of whip */ - if (p_ptr->pseikaku == SEIKAKU_SEXY) - s_info[p_ptr->pclass].w_max[TV_HAFTED-TV_WEAPON_BEGIN][SV_WHIP] = WEAPON_EXP_MASTER; - - /* Fill the arrays of floors and walls in the good proportions */ - set_floor_and_wall(p_ptr->dungeon_idx); - - /* Flavor the objects */ - flavor_init(); - - /* Flash a message */ - prt(_("お待ち下さい...", "Please wait..."), 0, 0); - - /* Flush the message */ - Term_fresh(); - - - /* Hack -- Enter wizard mode */ - if (arg_wizard) - { - if (enter_wizard_mode()) - { - p_ptr->wizard = TRUE; - - if (p_ptr->is_dead || !p_ptr->y || !p_ptr->x) - { - /* Initialize the saved floors data */ - init_saved_floors(TRUE); - - /* Avoid crash */ - p_ptr->inside_quest = 0; - - /* Avoid crash in update_view() */ - p_ptr->y = p_ptr->x = 10; - } - } - else if (p_ptr->is_dead) - { - quit("Already dead."); - } - } - - /* Initialize the town-buildings if necessary */ - if (!current_floor_ptr->dun_level && !p_ptr->inside_quest) - { - /* Init the wilderness */ - - process_dungeon_file("w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x); - - /* Init the town */ - init_flags = INIT_ONLY_BUILDINGS; - - process_dungeon_file("t_info.txt", 0, 0, MAX_HGT, MAX_WID); - - select_floor_music(); - } - - - /* Generate a dungeon level if needed */ - if (!character_dungeon) - { - change_floor(); - } - - else - { - /* HACK -- Restore from panic-save */ - if (p_ptr->panic_save) - { - /* No player? -- Try to regenerate floor */ - if (!p_ptr->y || !p_ptr->x) - { - msg_print(_("プレイヤーの位置がおかしい。フロアを再生成します。", "What a strange player location. Regenerate the dungeon floor.")); - change_floor(); - } - - /* Still no player? -- Try to locate random place */ - if (!p_ptr->y || !p_ptr->x) p_ptr->y = p_ptr->x = 10; - - /* No longer in panic */ - p_ptr->panic_save = 0; - } - } - - /* Character is now "complete" */ - character_generated = TRUE; - - - /* Hack -- Character is no longer "icky" */ - character_icky = FALSE; - - - if (new_game) - { - char buf[80]; - sprintf(buf, _("%sに降り立った。", "You are standing in the %s."), map_name()); - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, buf); - } - - - /* Start game */ - p_ptr->playing = TRUE; - - /* Reset the visual mappings */ - reset_visuals(); - - /* Load the "pref" files */ - load_all_pref_files(); - - /* Give startup outfit (after loading pref files) */ - if (new_game) - { - player_outfit(); - } - - /* React to changes */ - Term_xtra(TERM_XTRA_REACT, 0); - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER); - p_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_DUNGEON | PW_MONSTER | PW_OBJECT); - handle_stuff(); - - /* Set or clear "rogue_like_commands" if requested */ - if (arg_force_original) rogue_like_commands = FALSE; - if (arg_force_roguelike) rogue_like_commands = TRUE; - - /* Hack -- Enforce "delayed death" */ - if (p_ptr->chp < 0) p_ptr->is_dead = TRUE; - - if (p_ptr->prace == RACE_ANDROID) calc_android_exp(); - - if (new_game && ((p_ptr->pclass == CLASS_CAVALRY) || (p_ptr->pclass == CLASS_BEASTMASTER))) - { - monster_type *m_ptr; - IDX pet_r_idx = ((p_ptr->pclass == CLASS_CAVALRY) ? MON_HORSE : MON_YASE_HORSE); - monster_race *r_ptr = &r_info[pet_r_idx]; - place_monster_aux(0, p_ptr->y, p_ptr->x - 1, pet_r_idx, - (PM_FORCE_PET | PM_NO_KAGE)); - m_ptr = ¤t_floor_ptr->m_list[hack_m_idx_ii]; - m_ptr->mspeed = r_ptr->speed; - m_ptr->maxhp = r_ptr->hdice*(r_ptr->hside+1)/2; - m_ptr->max_maxhp = m_ptr->maxhp; - m_ptr->hp = r_ptr->hdice*(r_ptr->hside+1)/2; - m_ptr->dealt_damage = 0; - m_ptr->energy_need = ENERGY_NEED() + ENERGY_NEED(); - } - - (void)combine_and_reorder_home(STORE_HOME); - (void)combine_and_reorder_home(STORE_MUSEUM); - - select_floor_music(); - - /* Process */ - while (TRUE) - { - /* Process the level */ - dungeon(load_game); - - /* Hack -- prevent "icky" message */ - character_xtra = TRUE; - - handle_stuff(); - - character_xtra = FALSE; - - /* Cancel the target */ - target_who = 0; - - /* Cancel the health bar */ - health_track(0); - - forget_lite(); - forget_view(); - clear_mon_lite(); - - /* Handle "quit and save" */ - if (!p_ptr->playing && !p_ptr->is_dead) break; - - /* Erase the old current_floor_ptr->grid_array */ - wipe_o_list(); - if (!p_ptr->is_dead) wipe_m_list(); - - - msg_print(NULL); - - load_game = FALSE; - - /* Accidental Death */ - if (p_ptr->playing && p_ptr->is_dead) - { - if (p_ptr->inside_arena) - { - p_ptr->inside_arena = FALSE; - if (p_ptr->arena_number > MAX_ARENA_MONS) - p_ptr->arena_number++; - else - p_ptr->arena_number = -1 - p_ptr->arena_number; - p_ptr->is_dead = FALSE; - p_ptr->chp = 0; - p_ptr->chp_frac = 0; - p_ptr->exit_bldg = TRUE; - reset_tim_flags(); - - /* Leave through the exit */ - prepare_change_floor_mode(CFM_SAVE_FLOORS | CFM_RAND_CONNECT); - - /* prepare next floor */ - leave_floor(); - } - else - { - /* Mega-Hack -- Allow player to cheat death */ - if ((p_ptr->wizard || cheat_live) && !get_check(_("死にますか? ", "Die? "))) - { - cheat_death(p_ptr); - } - } - } - - /* Handle "death" */ - if (p_ptr->is_dead) break; - - /* Make a new level */ - change_floor(); - } - - /* Close stuff */ - close_game(); - - /* Quit */ - quit(NULL); -} - -/*! - * @brief ゲームターンからの実時間換算を行うための補正をかける - * @param hoge ゲームターン - * @details アンデッド種族は18:00からゲームを開始するので、この修正を予め行う。 - * @return 修正をかけた後のゲームターン - */ -s32b turn_real(s32b hoge) -{ - switch (p_ptr->start_race) - { - case RACE_VAMPIRE: - case RACE_SKELETON: - case RACE_ZOMBIE: - case RACE_SPECTRE: - return hoge - (TURNS_PER_TICK * TOWN_DAWN * 3 / 4); - default: - return hoge; - } -} - -/*! - * @brief ターンのオーバーフローに対する対処 - * @details ターン及びターンを記録する変数をターンの限界の1日前まで巻き戻す. - * @return 修正をかけた後のゲームターン - */ -void prevent_turn_overflow(void) -{ - int rollback_days, i, j; - s32b rollback_turns; - - if (current_world_ptr->game_turn < current_world_ptr->game_turn_limit) return; - - rollback_days = 1 + (current_world_ptr->game_turn - current_world_ptr->game_turn_limit) / (TURNS_PER_TICK * TOWN_DAWN); - rollback_turns = TURNS_PER_TICK * TOWN_DAWN * rollback_days; - - if (current_world_ptr->game_turn > rollback_turns) current_world_ptr->game_turn -= rollback_turns; - else current_world_ptr->game_turn = 1; - if (current_floor_ptr->generated_turn > rollback_turns) current_floor_ptr->generated_turn -= rollback_turns; - else current_floor_ptr->generated_turn = 1; - if (old_battle > rollback_turns) old_battle -= rollback_turns; - else old_battle = 1; - if (p_ptr->feeling_turn > rollback_turns) p_ptr->feeling_turn -= rollback_turns; - else p_ptr->feeling_turn = 1; - - for (i = 1; i < max_towns; i++) - { - for (j = 0; j < MAX_STORES; j++) - { - store_type *st_ptr = &town_info[i].store[j]; - - if (st_ptr->last_visit > -10L * TURNS_PER_TICK * STORE_TICKS) - { - st_ptr->last_visit -= rollback_turns; - if (st_ptr->last_visit < -10L * TURNS_PER_TICK * STORE_TICKS) st_ptr->last_visit = -10L * TURNS_PER_TICK * STORE_TICKS; - } - - if (st_ptr->store_open) - { - st_ptr->store_open -= rollback_turns; - if (st_ptr->store_open < 1) st_ptr->store_open = 1; - } - } - } -} - -/*! - * @brief ゲーム終了処理 / - * Close up the current game (player may or may not be dead) - * @return なし - * @details - *
- * This function is called only from "main.c" and "signals.c".
- * 
- */ -void close_game(void) -{ - char buf[1024]; - bool do_send = TRUE; - - /* concptr p = "[i:キャラクタの情報, f:ファイル書き出し, t:スコア, x:*鑑定*, ESC:ゲーム終了]"; */ - handle_stuff(); - - /* Flush the messages */ - msg_print(NULL); - - /* Flush the input */ - flush(); - - - /* No suspending now */ - signals_ignore_tstp(); - - - /* Hack -- Character is now "icky" */ - character_icky = TRUE; - - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); - - /* Grab permissions */ - safe_setuid_grab(); - - /* Open the high score file, for reading/writing */ - highscore_fd = fd_open(buf, O_RDWR); - - /* Drop permissions */ - safe_setuid_drop(); - - /* Handle death */ - if (p_ptr->is_dead) - { - /* Handle retirement */ - if (p_ptr->total_winner) kingly(); - - /* Save memories */ - if (!cheat_save || get_check(_("死んだデータをセーブしますか? ", "Save death? "))) - { - if (!save_player()) msg_print(_("セーブ失敗!", "death save failed!")); - } - else do_send = FALSE; - - /* You are dead */ - print_tomb(); - - flush(); - - /* Show more info */ - show_info(); - Term_clear(); - - if (check_score()) - { - if ((!send_world_score(do_send))) - { - if (get_check_strict(_("後でスコアを登録するために待機しますか?", "Stand by for later score registration? "), - (CHECK_NO_ESCAPE | CHECK_NO_HISTORY))) - { - p_ptr->wait_report_score = TRUE; - p_ptr->is_dead = FALSE; - if (!save_player()) msg_print(_("セーブ失敗!", "death save failed!")); - } - } - if (!p_ptr->wait_report_score) - (void)top_twenty(); - } - else if (highscore_fd >= 0) - { - display_scores_aux(0, 10, -1, NULL); - } -#if 0 - /* Dump bones file */ - make_bones(); -#endif - } - - /* Still alive */ - else - { - /* Save the game */ - do_cmd_save_game(FALSE); - - /* Prompt for scores */ - prt(_("リターンキーか ESC キーを押して下さい。", "Press Return (or Escape)."), 0, 40); - play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_EXIT); - - /* Predict score (or ESCAPE) */ - if (inkey() != ESCAPE) predict_score(); - } - - - /* Shut the high score file */ - (void)fd_close(highscore_fd); - - /* Forget the high score fd */ - highscore_fd = -1; - - /* Kill all temporal files */ - clear_saved_floor_files(); - - /* Allow suspending now */ - signals_handle_tstp(); -} diff --git a/src/dungeon/dungeon-flag-types.h b/src/dungeon/dungeon-flag-types.h new file mode 100644 index 000000000..768caf2ae --- /dev/null +++ b/src/dungeon/dungeon-flag-types.h @@ -0,0 +1,38 @@ +#pragma once + +typedef enum dungeon_flag_type { + DF1_WINNER = 0x00000001L, + DF1_MAZE = 0x00000002L, + DF1_SMALLEST = 0x00000004L, + DF1_BEGINNER = 0x00000008L, + DF1_BIG = 0x00000010L, + DF1_NO_DOORS = 0x00000020L, + DF1_WATER_RIVER = 0x00000040L, + DF1_LAVA_RIVER = 0x00000080L, + DF1_CURTAIN = 0x00000100L, + DF1_GLASS_DOOR = 0x00000200L, + DF1_CAVE = 0x00000400L, + DF1_CAVERN = 0x00000800L, + DF1_ARCADE = 0x00001000L, + DF1_LAKE_ACID = 0x00002000L, + DF1_LAKE_POISONOUS = 0x00004000L, + DF1_XXX15 = 0x00008000L, + DF1_FORGET = 0x00010000L, + DF1_LAKE_WATER = 0x00020000L, + DF1_LAKE_LAVA = 0x00040000L, + DF1_LAKE_RUBBLE = 0x00080000L, + DF1_LAKE_TREE = 0x00100000L, + DF1_NO_VAULT = 0x00200000L, + DF1_ARENA = 0x00400000L, + DF1_DESTROY = 0x00800000L, + DF1_GLASS_ROOM = 0x01000000L, + DF1_NO_CAVE = 0x02000000L, + DF1_NO_MAGIC = 0x04000000L, + DF1_NO_MELEE = 0x08000000L, + DF1_CHAMELEON = 0x10000000L, + DF1_DARKNESS = 0x20000000L, + DF1_ACID_RIVER = 0x40000000L, + DF1_POISONOUS_RIVER = 0x80000000L, +} dungeon_flag_type; + +#define DF1_LAKE_MASK (DF1_LAKE_WATER | DF1_LAKE_LAVA | DF1_LAKE_RUBBLE | DF1_LAKE_TREE | DF1_LAKE_POISONOUS | DF1_LAKE_ACID) diff --git a/src/dungeon/dungeon-processor.c b/src/dungeon/dungeon-processor.c new file mode 100644 index 000000000..f4e295d84 --- /dev/null +++ b/src/dungeon/dungeon-processor.c @@ -0,0 +1,229 @@ +#include "dungeon/dungeon-processor.h" +#include "cmd-building/cmd-building.h" +#include "cmd-io/cmd-dump.h" +#include "core/disturbance.h" +#include "core/hp-mp-regenerator.h" +#include "core/object-compressor.h" +#include "core/player-processor.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/stuff-handler.h" +#include "core/turn-compensator.h" +#include "core/window-redrawer.h" +#include "dungeon/dungeon.h" +#include "dungeon/quest.h" +#include "floor/floor-leaver.h" +#include "floor/floor-save-util.h" +#include "floor/floor-save.h" +#include "game-option/map-screen-options.h" +#include "game-option/play-record-options.h" +#include "io/cursor.h" +#include "io/input-key-requester.h" +#include "io/write-diary.h" +#include "market/arena.h" +#include "mind/mind-ninja.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster/monster-compaction.h" +#include "monster/monster-processor.h" +#include "monster/monster-status.h" +#include "monster/monster-util.h" +#include "player/special-defense-types.h" +#include "realm/realm-song-numbers.h" +#include "realm/realm-song.h" +#include "system/floor-type-definition.h" +#include "target/target-checker.h" +#include "view/display-messages.h" +#include "world/world-turn-processor.h" +#include "world/world.h" + +/*! + * process_player()、process_world() をcore.c から移設するのが先. + * process_upkeep_with_speed() はこの関数と同じところでOK + * @brief 現在プレイヤーがいるダンジョンの全体処理 / Interact with the current dungeon level. + * @return なし + * @details + *

+ * この関数から現在の階層を出る、プレイヤーがキャラが死ぬ、 + * ゲームを終了するかのいずれかまでループする。 + *

+ *

+ * This function will not exit until the level is completed,\n + * the user dies, or the game is terminated.\n + *

+ */ +void process_dungeon(player_type *player_ptr, bool load_game) +{ + floor_type *floor_ptr = player_ptr->current_floor_ptr; + floor_ptr->base_level = floor_ptr->dun_level; + current_world_ptr->is_loading_now = FALSE; + player_ptr->leaving = FALSE; + + command_cmd = 0; + command_rep = 0; + command_arg = 0; + command_dir = 0; + + target_who = 0; + player_ptr->pet_t_m_idx = 0; + player_ptr->riding_t_m_idx = 0; + player_ptr->ambush_flag = FALSE; + health_track(player_ptr, 0); + repair_monsters = TRUE; + + disturb(player_ptr, TRUE, TRUE); + int quest_num = quest_num = quest_number(player_ptr, floor_ptr->dun_level); + if (quest_num) { + r_info[quest[quest_num].r_idx].flags1 |= RF1_QUESTOR; + } + + if (player_ptr->max_plv < player_ptr->lev) { + player_ptr->max_plv = player_ptr->lev; + } + + if ((max_dlv[player_ptr->dungeon_idx] < floor_ptr->dun_level) && !floor_ptr->inside_quest) { + max_dlv[player_ptr->dungeon_idx] = floor_ptr->dun_level; + if (record_maxdepth) + exe_write_diary(player_ptr, DIARY_MAXDEAPTH, floor_ptr->dun_level, NULL); + } + + (void)calculate_upkeep(player_ptr); + panel_bounds_center(); + verify_panel(player_ptr); + msg_erase(); + + current_world_ptr->character_xtra = TRUE; + player_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER | PW_MONSTER | PW_OVERHEAD | PW_DUNGEON); + player_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_EQUIPPY | PR_MAP); + player_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_VIEW | PU_LITE | PU_MON_LITE | PU_TORCH | PU_MONSTERS | PU_DISTANCE | PU_FLOW); + handle_stuff(player_ptr); + + current_world_ptr->character_xtra = FALSE; + player_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS); + player_ptr->update |= (PU_COMBINE | PU_REORDER); + handle_stuff(player_ptr); + term_fresh(); + + if (quest_num + && (is_fixed_quest_idx(quest_num) && !((quest_num == QUEST_OBERON) || (quest_num == QUEST_SERPENT) || !(quest[quest_num].flags & QUEST_FLAG_PRESET)))) + do_cmd_feeling(player_ptr); + + if (player_ptr->phase_out) { + if (load_game) { + player_ptr->energy_need = 0; + update_gambling_monsters(player_ptr); + } else { + msg_print(_("試合開始!", "Ready..Fight!")); + msg_print(NULL); + } + } + + if ((player_ptr->pclass == CLASS_BARD) && (SINGING_SONG_EFFECT(player_ptr) > MUSIC_DETECT)) + SINGING_SONG_EFFECT(player_ptr) = MUSIC_DETECT; + + if (!player_ptr->playing || player_ptr->is_dead) + return; + + if (!floor_ptr->inside_quest && (player_ptr->dungeon_idx == DUNGEON_ANGBAND)) { + quest_discovery(random_quest_number(player_ptr, floor_ptr->dun_level)); + floor_ptr->inside_quest = random_quest_number(player_ptr, floor_ptr->dun_level); + } + if ((floor_ptr->dun_level == d_info[player_ptr->dungeon_idx].maxdepth) && d_info[player_ptr->dungeon_idx].final_guardian) { + if (r_info[d_info[player_ptr->dungeon_idx].final_guardian].max_num) +#ifdef JP + msg_format("この階には%sの主である%sが棲んでいる。", d_name + d_info[player_ptr->dungeon_idx].name, + r_name + r_info[d_info[player_ptr->dungeon_idx].final_guardian].name); +#else + msg_format("%^s lives in this level as the keeper of %s.", r_name + r_info[d_info[player_ptr->dungeon_idx].final_guardian].name, + d_name + d_info[player_ptr->dungeon_idx].name); +#endif + } + + if (!load_game && (player_ptr->special_defense & NINJA_S_STEALTH)) + set_superstealth(player_ptr, FALSE); + + floor_ptr->monster_level = floor_ptr->base_level; + floor_ptr->object_level = floor_ptr->base_level; + current_world_ptr->is_loading_now = TRUE; + if (player_ptr->energy_need > 0 && !player_ptr->phase_out && (floor_ptr->dun_level || player_ptr->leaving_dungeon || floor_ptr->inside_arena)) + player_ptr->energy_need = 0; + + player_ptr->leaving_dungeon = FALSE; + mproc_init(floor_ptr); + + while (TRUE) { + if ((floor_ptr->m_cnt + 32 > current_world_ptr->max_m_idx) && !player_ptr->phase_out) + compact_monsters(player_ptr, 64); + + if ((floor_ptr->m_cnt + 32 < floor_ptr->m_max) && !player_ptr->phase_out) + compact_monsters(player_ptr, 0); + + if (floor_ptr->o_cnt + 32 > current_world_ptr->max_o_idx) + compact_objects(player_ptr, 64); + + if (floor_ptr->o_cnt + 32 < floor_ptr->o_max) + compact_objects(player_ptr, 0); + + process_player(player_ptr); + process_upkeep_with_speed(player_ptr); + handle_stuff(player_ptr); + + move_cursor_relative(player_ptr->y, player_ptr->x); + if (fresh_after) + term_fresh(); + + if (!player_ptr->playing || player_ptr->is_dead) + break; + + process_monsters(player_ptr); + handle_stuff(player_ptr); + + move_cursor_relative(player_ptr->y, player_ptr->x); + if (fresh_after) + term_fresh(); + + if (!player_ptr->playing || player_ptr->is_dead) + break; + + process_world(player_ptr); + handle_stuff(player_ptr); + + move_cursor_relative(player_ptr->y, player_ptr->x); + if (fresh_after) + term_fresh(); + + if (!player_ptr->playing || player_ptr->is_dead) + break; + + current_world_ptr->game_turn++; + if (current_world_ptr->dungeon_turn < current_world_ptr->dungeon_turn_limit) { + if (!player_ptr->wild_mode || wild_regen) + current_world_ptr->dungeon_turn++; + else if (player_ptr->wild_mode && !(current_world_ptr->game_turn % ((MAX_HGT + MAX_WID) / 2))) + current_world_ptr->dungeon_turn++; + } + + prevent_turn_overflow(player_ptr); + + if (player_ptr->leaving) + break; + + if (wild_regen) + wild_regen--; + } + + if (quest_num && !(r_info[quest[quest_num].r_idx].flags1 & RF1_UNIQUE)) { + r_info[quest[quest_num].r_idx].flags1 &= ~RF1_QUESTOR; + } + + if (player_ptr->playing && !player_ptr->is_dead) { + /* + * Maintain Unique monsters and artifact, save current + * floor, then prepare next floor + */ + leave_floor(player_ptr); + reinit_wilderness = FALSE; + } + + write_level = TRUE; +} diff --git a/src/dungeon/dungeon-processor.h b/src/dungeon/dungeon-processor.h new file mode 100644 index 000000000..1239471e6 --- /dev/null +++ b/src/dungeon/dungeon-processor.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +void process_dungeon(player_type* player_ptr, bool load_game); diff --git a/src/dungeon/dungeon.c b/src/dungeon/dungeon.c new file mode 100644 index 000000000..80d6294a0 --- /dev/null +++ b/src/dungeon/dungeon.c @@ -0,0 +1,104 @@ +#include "dungeon/dungeon.h" +#include "game-option/birth-options.h" +#include "io/input-key-acceptor.h" +#include "main/sound-of-music.h" +#include "monster-race/monster-race.h" +#include "term/screen-processor.h" +#include "util/int-char-converter.h" +#include "view/display-messages.h" +#include "world/world.h" + +/* + * The dungeon arrays + */ +dungeon_type *d_info; +char *d_name; +char *d_text; + +/* + * Maximum number of dungeon in d_info.txt + */ +DEPTH *max_dlv; + + +/*! + * @brief これまでに入ったダンジョンの一覧を表示し、選択させる。 + * @param note ダンジョンに施す処理記述 + * @param y コンソールY座標 + * @param x コンソールX座標 + * @return 選択されたダンジョンID + */ +DUNGEON_IDX choose_dungeon(concptr note, POSITION y, POSITION x) +{ + DUNGEON_IDX select_dungeon; + DUNGEON_IDX i; + int num = 0; + DUNGEON_IDX *dun; + + /* Hack -- No need to choose dungeon in some case */ + if (lite_town || vanilla_town || ironman_downward) + { + if (max_dlv[DUNGEON_ANGBAND]) return DUNGEON_ANGBAND; + else + { + msg_format(_("まだ%sに入ったことはない。", "You haven't entered %s yet."), d_name + d_info[DUNGEON_ANGBAND].name); + msg_print(NULL); + return 0; + } + } + + /* Allocate the "dun" array */ + C_MAKE(dun, current_world_ptr->max_d_idx, DUNGEON_IDX); + + screen_save(); + for (i = 1; i < current_world_ptr->max_d_idx; i++) + { + char buf[80]; + bool seiha = FALSE; + + if (!d_info[i].maxdepth) continue; + if (!max_dlv[i]) continue; + if (d_info[i].final_guardian) + { + if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE; + } + else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE; + + sprintf(buf, _(" %c) %c%-12s : 最大 %d 階", " %c) %c%-16s : Max level %d"), + 'a' + num, seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]); + prt(buf, y + num, x); + dun[num++] = i; + } + + if (!num) + { + prt(_(" 選べるダンジョンがない。", " No dungeon is available."), y, x); + } + + prt(format(_("どのダンジョン%sしますか:", "Which dungeon do you %s?: "), note), 0, 0); + while (TRUE) + { + i = inkey(); + if ((i == ESCAPE) || !num) + { + /* Free the "dun" array */ + C_KILL(dun, current_world_ptr->max_d_idx, DUNGEON_IDX); + + screen_load(); + return 0; + } + if (i >= 'a' && i < ('a' + num)) + { + select_dungeon = dun[i - 'a']; + break; + } + else bell(); + } + screen_load(); + + /* Free the "dun" array */ + C_KILL(dun, current_world_ptr->max_d_idx, DUNGEON_IDX); + + return select_dungeon; +} + diff --git a/src/dungeon/dungeon.h b/src/dungeon/dungeon.h new file mode 100644 index 000000000..bf0a136cc --- /dev/null +++ b/src/dungeon/dungeon.h @@ -0,0 +1,87 @@ +#pragma once + +#include "system/angband.h" +#include "grid/feature.h" + +#define DUNGEON_FEAT_PROB_NUM 3 + +#define DUNGEON_ANGBAND 1 +#define DUNGEON_GALGALS 2 +#define DUNGEON_ORC 3 +#define DUNGEON_MAZE 4 +#define DUNGEON_DRAGON 5 +#define DUNGEON_GRAVE 6 +#define DUNGEON_WOOD 7 +#define DUNGEON_VOLCANO 8 +#define DUNGEON_HELL 9 +#define DUNGEON_HEAVEN 10 +#define DUNGEON_OCEAN 11 +#define DUNGEON_CASTLE 12 +#define DUNGEON_CTH 13 +#define DUNGEON_MOUNTAIN 14 +#define DUNGEON_GOLD 15 +#define DUNGEON_NO_MAGIC 16 +#define DUNGEON_NO_MELEE 17 +#define DUNGEON_CHAMELEON 18 +#define DUNGEON_DARKNESS 19 + +/* A structure for the != dungeon types */ +typedef struct dungeon_type dungeon_type; +struct dungeon_type { + + STR_OFFSET name; /* Name */ + STR_OFFSET text; /* Description */ + + POSITION dy; + POSITION dx; + + feat_prob floor[DUNGEON_FEAT_PROB_NUM]; /* Floor probability */ + feat_prob fill[DUNGEON_FEAT_PROB_NUM]; /* Cave wall probability */ + FEAT_IDX outer_wall; /* Outer wall tile */ + FEAT_IDX inner_wall; /* Inner wall tile */ + FEAT_IDX stream1; /* stream tile */ + FEAT_IDX stream2; /* stream tile */ + + DEPTH mindepth; /* Minimal depth */ + DEPTH maxdepth; /* Maximal depth */ + PLAYER_LEVEL min_plev; /* Minimal plev needed to enter -- it's an anti-cheating mesure */ + BIT_FLAGS16 pit; + BIT_FLAGS16 nest; + BIT_FLAGS8 mode; /* Mode of combinaison of the monster flags */ + + int min_m_alloc_level; /* Minimal number of monsters per level */ + int max_m_alloc_chance; /* There is a 1/max_m_alloc_chance chance per round of creating a new monster */ + + BIT_FLAGS flags1; /* Flags 1 */ + + BIT_FLAGS mflags1; /* The monster flags that are allowed */ + BIT_FLAGS mflags2; + BIT_FLAGS mflags3; + BIT_FLAGS mflags4; + BIT_FLAGS mflags7; + BIT_FLAGS mflags8; + BIT_FLAGS mflags9; + BIT_FLAGS mflagsr; + + BIT_FLAGS m_a_ability_flags1; + BIT_FLAGS m_a_ability_flags2; + BIT_FLAGS m_a_ability_flags3; + BIT_FLAGS m_a_ability_flags4; + + char r_char[5]; /* Monster race allowed */ + KIND_OBJECT_IDX final_object; /* The object you'll find at the bottom */ + ARTIFACT_IDX final_artifact; /* The artifact you'll find at the bottom */ + MONRACE_IDX final_guardian; /* The artifact's guardian. If an artifact is specified, then it's NEEDED */ + + PROB special_div; /* % of monsters affected by the flags/races allowed, to add some variety */ + int tunnel_percent; + int obj_great; + int obj_good; +}; + +extern DEPTH *max_dlv; +extern dungeon_type *d_info; +extern char *d_name; +extern char *d_text; + +extern DUNGEON_IDX choose_dungeon(concptr note, POSITION y, POSITION x); diff --git a/src/dungeon/quest-completion-checker.c b/src/dungeon/quest-completion-checker.c new file mode 100644 index 000000000..7cc8ace95 --- /dev/null +++ b/src/dungeon/quest-completion-checker.c @@ -0,0 +1,179 @@ +#include "dungeon/quest-completion-checker.h" +#include "core/player-update-types.h" +#include "dungeon/quest.h" +#include "effect/effect-characteristics.h" +#include "floor/cave.h" +#include "floor/floor-object.h" +#include "floor/floor-util.h" +#include "grid/feature-flag-types.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "monster/monster-info.h" +#include "object-enchant/item-apply-magic.h" +#include "object/object-generator.h" +#include "system/floor-type-definition.h" +#include "system/monster-type-definition.h" +#include "view/display-messages.h" + +/*! + * @brief 現在フロアに残っている敵モンスターの数を返す / + * @return 現在の敵モンスターの数 + */ +static MONSTER_NUMBER count_all_hostile_monsters(floor_type *floor_ptr) +{ + MONSTER_NUMBER number_mon = 0; + for (POSITION x = 0; x < floor_ptr->width; ++x) { + for (POSITION y = 0; y < floor_ptr->height; ++y) { + MONSTER_IDX m_idx = floor_ptr->grid_array[y][x].m_idx; + if (m_idx > 0 && is_hostile(&floor_ptr->m_list[m_idx])) + ++number_mon; + } + } + + return number_mon; +} + +/*! + * @brief 特定の敵を倒した際にクエスト達成処理 / + * Check for "Quest" completion when a quest monster is killed or charmed. + * @param player_ptr プレーヤーへの参照ポインタ + * @param m_ptr 撃破したモンスターの構造体参照ポインタ + * @return なし + */ +void check_quest_completion(player_type *player_ptr, monster_type *m_ptr) +{ + POSITION y = m_ptr->fy; + POSITION x = m_ptr->fx; + floor_type *floor_ptr = player_ptr->current_floor_ptr; + QUEST_IDX quest_num = floor_ptr->inside_quest; + if (!quest_num) { + QUEST_IDX i; + for (i = max_q_idx - 1; i > 0; i--) { + quest_type *const q_ptr = &quest[i]; + if (q_ptr->status != QUEST_STATUS_TAKEN) + continue; + + if (q_ptr->flags & QUEST_FLAG_PRESET) + continue; + + if ((q_ptr->level != floor_ptr->dun_level) && (q_ptr->type != QUEST_TYPE_KILL_ANY_LEVEL)) + continue; + + if ((q_ptr->type == QUEST_TYPE_FIND_ARTIFACT) || (q_ptr->type == QUEST_TYPE_FIND_EXIT)) + continue; + + if ((q_ptr->type == QUEST_TYPE_KILL_NUMBER) || (q_ptr->type == QUEST_TYPE_TOWER) || (q_ptr->type == QUEST_TYPE_KILL_ALL)) + break; + + if (((q_ptr->type == QUEST_TYPE_KILL_LEVEL) || (q_ptr->type == QUEST_TYPE_KILL_ANY_LEVEL) || (q_ptr->type == QUEST_TYPE_RANDOM)) + && (q_ptr->r_idx == m_ptr->r_idx)) + break; + } + + quest_num = i; + } + + bool create_stairs = FALSE; + bool reward = FALSE; + if (quest_num && (quest[quest_num].status == QUEST_STATUS_TAKEN)) { + quest_type *const q_ptr = &quest[quest_num]; + switch (q_ptr->type) { + case QUEST_TYPE_KILL_NUMBER: { + q_ptr->cur_num++; + if (q_ptr->cur_num >= q_ptr->num_mon) { + complete_quest(player_ptr, quest_num); + q_ptr->cur_num = 0; + } + + break; + } + case QUEST_TYPE_KILL_ALL: { + if (!is_hostile(m_ptr) || count_all_hostile_monsters(floor_ptr) != 1) + break; + + if (q_ptr->flags & QUEST_FLAG_SILENT) { + q_ptr->status = QUEST_STATUS_FINISHED; + } else { + complete_quest(player_ptr, quest_num); + } + + break; + } + case QUEST_TYPE_KILL_LEVEL: + case QUEST_TYPE_RANDOM: { + if (q_ptr->r_idx != m_ptr->r_idx) + break; + + q_ptr->cur_num++; + if (q_ptr->cur_num < q_ptr->max_num) + break; + + complete_quest(player_ptr, quest_num); + if (!(q_ptr->flags & QUEST_FLAG_PRESET)) { + create_stairs = TRUE; + floor_ptr->inside_quest = 0; + } + + if ((quest_num == QUEST_OBERON) || (quest_num == QUEST_SERPENT)) + q_ptr->status = QUEST_STATUS_FINISHED; + + if (q_ptr->type == QUEST_TYPE_RANDOM) { + reward = TRUE; + q_ptr->status = QUEST_STATUS_FINISHED; + } + + break; + } + case QUEST_TYPE_KILL_ANY_LEVEL: { + q_ptr->cur_num++; + if (q_ptr->cur_num >= q_ptr->max_num) { + complete_quest(player_ptr, quest_num); + q_ptr->cur_num = 0; + } + + break; + } + case QUEST_TYPE_TOWER: { + if (!is_hostile(m_ptr)) + break; + + if (count_all_hostile_monsters(floor_ptr) == 1) { + q_ptr->status = QUEST_STATUS_STAGE_COMPLETED; + + if ((quest[QUEST_TOWER1].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[QUEST_TOWER2].status == QUEST_STATUS_STAGE_COMPLETED) + && (quest[QUEST_TOWER3].status == QUEST_STATUS_STAGE_COMPLETED)) { + + complete_quest(player_ptr, QUEST_TOWER1); + } + } + + break; + } + } + } + + if (create_stairs) { + POSITION ny, nx; + while (cave_have_flag_bold(floor_ptr, y, x, FF_PERMANENT) || floor_ptr->grid_array[y][x].o_idx || (floor_ptr->grid_array[y][x].info & CAVE_OBJECT)) { + scatter(player_ptr, &ny, &nx, y, x, 1, PROJECT_NONE); + y = ny; + x = nx; + } + + msg_print(_("魔法の階段が現れた...", "A magical staircase appears...")); + cave_set_feat(player_ptr, y, x, feat_down_stair); + player_ptr->update |= PU_FLOW; + } + + if (!reward) + return; + + object_type forge; + object_type *o_ptr; + for (int i = 0; i < (floor_ptr->dun_level / 15) + 1; i++) { + o_ptr = &forge; + object_wipe(o_ptr); + make_object(player_ptr, o_ptr, AM_GOOD | AM_GREAT); + (void)drop_near(player_ptr, o_ptr, -1, y, x); + } +} diff --git a/src/dungeon/quest-completion-checker.h b/src/dungeon/quest-completion-checker.h new file mode 100644 index 000000000..955a31f42 --- /dev/null +++ b/src/dungeon/quest-completion-checker.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" + +typedef struct monster_type monster_type; +void check_quest_completion(player_type *player_ptr, monster_type *m_ptr); diff --git a/src/dungeon/quest-monster-placer.c b/src/dungeon/quest-monster-placer.c new file mode 100644 index 000000000..73d6e8c1a --- /dev/null +++ b/src/dungeon/quest-monster-placer.c @@ -0,0 +1,81 @@ +#include "dungeon/quest-monster-placer.h" +#include "dungeon/quest.h" +#include "floor/floor-generator-util.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "monster-floor/monster-generator.h" +#include "monster-floor/place-monster-types.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster/monster-info.h" +#include "system/floor-type-definition.h" +#include "util/bit-flags-calculator.h" + +/*! + * @brief クエストに関わるモンスターの配置を行う / Place quest monsters + * @param creature_ptr プレーヤーへの参照ポインタ + * @return 成功したならばTRUEを返す + */ +bool place_quest_monsters(player_type *creature_ptr) +{ + floor_type *floor_ptr = creature_ptr->current_floor_ptr; + for (int i = 0; i < max_q_idx; i++) { + monster_race *r_ptr; + BIT_FLAGS mode; + if (quest[i].status != QUEST_STATUS_TAKEN || (quest[i].type != QUEST_TYPE_KILL_LEVEL && quest[i].type != QUEST_TYPE_RANDOM) + || quest[i].level != floor_ptr->dun_level || creature_ptr->dungeon_idx != quest[i].dungeon || (quest[i].flags & QUEST_FLAG_PRESET)) { + continue; + } + + r_ptr = &r_info[quest[i].r_idx]; + if ((r_ptr->flags1 & RF1_UNIQUE) && (r_ptr->cur_num >= r_ptr->max_num)) + continue; + + mode = PM_NO_KAGE | PM_NO_PET; + if (!(r_ptr->flags1 & RF1_FRIENDS)) + mode |= PM_ALLOW_GROUP; + + for (int j = 0; j < (quest[i].max_num - quest[i].cur_num); j++) { + int k; + for (k = 0; k < SAFE_MAX_ATTEMPTS; k++) { + POSITION x = 0; + POSITION y = 0; + int l; + for (l = SAFE_MAX_ATTEMPTS; l > 0; l--) { + grid_type *g_ptr; + feature_type *f_ptr; + y = randint0(floor_ptr->height); + x = randint0(floor_ptr->width); + g_ptr = &floor_ptr->grid_array[y][x]; + f_ptr = &f_info[g_ptr->feat]; + if (!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) + continue; + + if (!monster_can_enter(creature_ptr, y, x, r_ptr, 0)) + continue; + + if (distance(y, x, creature_ptr->y, creature_ptr->x) < 10) + continue; + + if (g_ptr->info & CAVE_ICKY) + continue; + else + break; + } + + if (l == 0) + return FALSE; + + if (place_monster_aux(creature_ptr, 0, y, x, quest[i].r_idx, mode)) + break; + else + continue; + } + + if (k == SAFE_MAX_ATTEMPTS) + return FALSE; + } + } + + return TRUE; +} diff --git a/src/dungeon/quest-monster-placer.h b/src/dungeon/quest-monster-placer.h new file mode 100644 index 000000000..a4781bffd --- /dev/null +++ b/src/dungeon/quest-monster-placer.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool place_quest_monsters(player_type *creature_ptr); diff --git a/src/dungeon/quest.c b/src/dungeon/quest.c new file mode 100644 index 000000000..a5fd7e039 --- /dev/null +++ b/src/dungeon/quest.c @@ -0,0 +1,345 @@ +#include "dungeon/quest.h" +#include "cmd-io/cmd-dump.h" +#include "core/asking-player.h" +#include "core/player-update-types.h" +#include "dungeon/dungeon.h" +#include "floor/cave.h" +#include "floor/floor-events.h" +#include "floor/floor-mode-changer.h" +#include "floor/floor-object.h" +#include "game-option/play-record-options.h" +#include "grid/feature.h" +#include "grid/grid.h" +#include "io/write-diary.h" +#include "locale/english.h" +#include "main/music-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-race/monster-race-hook.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags7.h" +#include "monster-race/race-flags8.h" +#include "monster/monster-info.h" +#include "monster/monster-list.h" +#include "monster/monster-util.h" +#include "monster/smart-learn-types.h" +#include "object-enchant/item-apply-magic.h" +#include "object-enchant/trg-types.h" +#include "object/object-generator.h" +#include "player/player-personalities-types.h" +#include "player/player-status.h" +#include "system/artifact-type-definition.h" +#include "system/floor-type-definition.h" +#include "system/system-variables.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" +#include "world/world.h" + +quest_type *quest; /*!< Quest info */ +QUEST_IDX max_q_idx; /*!< Maximum number of quests */ +char quest_text[10][80]; /*!< Quest text */ +int quest_text_line; /*!< Current line of the quest text */ +int leaving_quest = 0; + +/*! + * @brief クエスト突入時のメッセージテーブル / Array of places to find an inscription + */ +static concptr find_quest[] = { + _("床にメッセージが刻まれている:", "You find the following inscription in the floor"), + _("壁にメッセージが刻まれている:", "You see a message inscribed in the wall"), + _("メッセージを見つけた:", "There is a sign saying"), + _("何かが階段の上に書いてある:", "Something is written on the staircase"), + _("巻物を見つけた。メッセージが書いてある:", "You find a scroll with the following message"), +}; + +/*! + * @brief ランダムクエストの討伐ユニークを決める / Determine the random quest uniques + * @param q_ptr クエスト構造体の参照ポインタ + * @return なし + */ +void determine_random_questor(player_type *player_ptr, quest_type *q_ptr) +{ + get_mon_num_prep(player_ptr, mon_hook_quest, NULL); + + MONRACE_IDX r_idx; + while (TRUE) { + /* + * Random monster 5 - 10 levels out of depth + * (depending on level) + */ + r_idx = get_mon_num(player_ptr, q_ptr->level + 5 + randint1(q_ptr->level / 10), GMN_ARENA); + monster_race *r_ptr; + r_ptr = &r_info[r_idx]; + + if (!(r_ptr->flags1 & RF1_UNIQUE)) + continue; + if (r_ptr->flags1 & RF1_QUESTOR) + continue; + if (r_ptr->rarity > 100) + continue; + if (r_ptr->flags7 & RF7_FRIENDLY) + continue; + if (r_ptr->flags7 & RF7_AQUATIC) + continue; + if (r_ptr->flags8 & RF8_WILD_ONLY) + continue; + if (no_questor_or_bounty_uniques(r_idx)) + continue; + + /* + * Accept monsters that are 2 - 6 levels + * out of depth depending on the quest level + */ + if (r_ptr->level > (q_ptr->level + (q_ptr->level / 20))) + break; + } + + q_ptr->r_idx = r_idx; +} + +/*! + * @brief クエストを達成状態にする / + * @param player_ptr プレーヤーへの参照ポインタ + * @param quest_num 達成状態にしたいクエストのID + * @return なし + */ +void complete_quest(player_type *player_ptr, QUEST_IDX quest_num) +{ + quest_type *const q_ptr = &quest[quest_num]; + + switch (q_ptr->type) { + case QUEST_TYPE_RANDOM: + if (record_rand_quest) + exe_write_diary(player_ptr, DIARY_RAND_QUEST_C, quest_num, NULL); + break; + default: + if (record_fix_quest) + exe_write_diary(player_ptr, DIARY_FIX_QUEST_C, quest_num, NULL); + break; + } + + q_ptr->status = QUEST_STATUS_COMPLETED; + q_ptr->complev = player_ptr->lev; + update_playtime(); + q_ptr->comptime = current_world_ptr->play_time; + + if (q_ptr->flags & QUEST_FLAG_SILENT) + return; + + play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_QUEST_CLEAR); + msg_print(_("クエストを達成した!", "You just completed your quest!")); + msg_print(NULL); +} + +/*! + * @brief 特定のアーティファクトを入手した際のクエスト達成処理 / + * Check for "Quest" completion when a quest monster is killed or charmed. + * @param player_ptr プレーヤーへの参照ポインタ + * @param o_ptr 入手したオブジェクトの構造体参照ポインタ + * @return なし + */ +void check_find_art_quest_completion(player_type *player_ptr, object_type *o_ptr) +{ + /* Check if completed a quest */ + for (QUEST_IDX i = 0; i < max_q_idx; i++) { + if ((quest[i].type == QUEST_TYPE_FIND_ARTIFACT) && (quest[i].status == QUEST_STATUS_TAKEN) && (quest[i].k_idx == o_ptr->name1)) { + complete_quest(player_ptr, i); + } + } +} + +/*! + * @brief クエストの導入メッセージを表示する / Discover quest + * @param q_idx 開始されたクエストのID + */ +void quest_discovery(QUEST_IDX q_idx) +{ + quest_type *q_ptr = &quest[q_idx]; + monster_race *r_ptr = &r_info[q_ptr->r_idx]; + MONSTER_NUMBER q_num = q_ptr->max_num; + + if (!q_idx) + return; + + GAME_TEXT name[MAX_NLEN]; + strcpy(name, (r_name + r_ptr->name)); + + msg_print(find_quest[rand_range(0, 4)]); + msg_print(NULL); + + if (q_num != 1) { +#ifdef JP +#else + plural_aux(name); +#endif + msg_format(_("注意しろ!この階は%d体の%sによって守られている!", "Be warned, this level is guarded by %d %s!"), q_num, name); + return; + } + + bool is_random_quest_skipped = (r_ptr->flags1 & RF1_UNIQUE) != 0; + is_random_quest_skipped &= r_ptr->max_num == 0; + if (!is_random_quest_skipped) { + msg_format(_("注意せよ!この階は%sによって守られている!", "Beware, this level is protected by %s!"), name); + return; + } + + msg_print(_("この階は以前は誰かによって守られていたようだ…。", "It seems that this level was protected by someone before...")); + quest[q_idx].status = QUEST_STATUS_FINISHED; + q_ptr->complev = 0; + update_playtime(); + q_ptr->comptime = current_world_ptr->play_time; +} + +/*! + * @brief 新しく入ったダンジョンの階層に固定されている一般のクエストを探し出しIDを返す。 + * / Hack -- Check if a level is a "quest" level + * @param player_ptr プレーヤーへの参照ポインタ + * @param level 検索対象になる階 + * @return クエストIDを返す。該当がない場合0を返す。 + */ +QUEST_IDX quest_number(player_type *player_ptr, DEPTH level) +{ + floor_type *floor_ptr = player_ptr->current_floor_ptr; + if (floor_ptr->inside_quest) + return (floor_ptr->inside_quest); + + for (QUEST_IDX i = 0; i < max_q_idx; i++) { + if (quest[i].status != QUEST_STATUS_TAKEN) + continue; + + if ((quest[i].type == QUEST_TYPE_KILL_LEVEL) && !(quest[i].flags & QUEST_FLAG_PRESET) && (quest[i].level == level) + && (quest[i].dungeon == player_ptr->dungeon_idx)) + return i; + } + + return random_quest_number(player_ptr, level); +} + +/*! + * @brief 新しく入ったダンジョンの階層に固定されているランダムクエストを探し出しIDを返す。 + * @param player_ptr プレーヤーへの参照ポインタ + * @param level 検索対象になる階 + * @return クエストIDを返す。該当がない場合0を返す。 + */ +QUEST_IDX random_quest_number(player_type *player_ptr, DEPTH level) +{ + if (player_ptr->dungeon_idx != DUNGEON_ANGBAND) + return 0; + + for (QUEST_IDX i = MIN_RANDOM_QUEST; i < MAX_RANDOM_QUEST + 1; i++) { + if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN) && (quest[i].level == level) + && (quest[i].dungeon == DUNGEON_ANGBAND)) { + return i; + } + } + + return 0; +} + +/*! + * @brief クエスト階層から離脱する際の処理 + * @param player_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void leave_quest_check(player_type *player_ptr) +{ + leaving_quest = player_ptr->current_floor_ptr->inside_quest; + if (!leaving_quest) + return; + + quest_type *const q_ptr = &quest[leaving_quest]; + bool is_one_time_quest = ((q_ptr->flags & QUEST_FLAG_ONCE) || (q_ptr->type == QUEST_TYPE_RANDOM)) && (q_ptr->status == QUEST_STATUS_TAKEN); + if (!is_one_time_quest) + return; + + q_ptr->status = QUEST_STATUS_FAILED; + q_ptr->complev = player_ptr->lev; + update_playtime(); + q_ptr->comptime = current_world_ptr->play_time; + + /* Additional settings */ + switch (q_ptr->type) { + case QUEST_TYPE_TOWER: + quest[QUEST_TOWER1].status = QUEST_STATUS_FAILED; + quest[QUEST_TOWER1].complev = player_ptr->lev; + break; + case QUEST_TYPE_FIND_ARTIFACT: + a_info[q_ptr->k_idx].gen_flags &= ~(TRG_QUESTITEM); + break; + case QUEST_TYPE_RANDOM: + r_info[q_ptr->r_idx].flags1 &= ~(RF1_QUESTOR); + + /* Floor of random quest will be blocked */ + prepare_change_floor_mode(player_ptr, CFM_NO_RETURN); + break; + } + + /* Record finishing a quest */ + if (q_ptr->type == QUEST_TYPE_RANDOM) { + if (record_rand_quest) + exe_write_diary(player_ptr, DIARY_RAND_QUEST_F, leaving_quest, NULL); + return; + } + + if (record_fix_quest) + exe_write_diary(player_ptr, DIARY_FIX_QUEST_F, leaving_quest, NULL); +} + +/*! + * @brief 「塔」クエストの各階層から離脱する際の処理 + * @return なし + */ +void leave_tower_check(player_type *player_ptr) +{ + leaving_quest = player_ptr->current_floor_ptr->inside_quest; + bool is_leaving_from_tower = leaving_quest != 0; + is_leaving_from_tower &= quest[leaving_quest].type == QUEST_TYPE_TOWER; + is_leaving_from_tower &= quest[QUEST_TOWER1].status != QUEST_STATUS_COMPLETED; + if (!is_leaving_from_tower) + return; + if (quest[leaving_quest].type != QUEST_TYPE_TOWER) + return; + + quest[QUEST_TOWER1].status = QUEST_STATUS_FAILED; + quest[QUEST_TOWER1].complev = player_ptr->lev; + update_playtime(); + quest[QUEST_TOWER1].comptime = current_world_ptr->play_time; +} + +/*! + * @brief クエスト入り口にプレイヤーが乗った際の処理 / Do building commands + * @param player_ptr プレーヤーへの参照ポインタ + * @return なし + */ +void do_cmd_quest(player_type *player_ptr) +{ + if (player_ptr->wild_mode) + return; + + take_turn(player_ptr, 100); + + if (!cave_have_flag_bold(player_ptr->current_floor_ptr, player_ptr->y, player_ptr->x, FF_QUEST_ENTER)) { + msg_print(_("ここにはクエストの入口はない。", "You see no quest level here.")); + return; + } + + msg_print(_("ここにはクエストへの入口があります。", "There is an entry of a quest.")); + if (!get_check(_("クエストに入りますか?", "Do you enter? "))) + return; + if (is_echizen(player_ptr)) + msg_print(_("『とにかく入ってみようぜぇ。』", "")); + else if (player_ptr->pseikaku == PERSONALITY_CHARGEMAN) + msg_print("『全滅してやるぞ!』"); + + /* Player enters a new quest */ + player_ptr->oldpy = 0; + player_ptr->oldpx = 0; + + leave_quest_check(player_ptr); + + if (quest[player_ptr->current_floor_ptr->inside_quest].type != QUEST_TYPE_RANDOM) + player_ptr->current_floor_ptr->dun_level = 1; + player_ptr->current_floor_ptr->inside_quest = player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x].special; + + player_ptr->leaving = TRUE; +} diff --git a/src/dungeon/quest.h b/src/dungeon/quest.h new file mode 100644 index 000000000..f9e26b1da --- /dev/null +++ b/src/dungeon/quest.h @@ -0,0 +1,97 @@ +#pragma once + +#include "system/angband.h" +#include "system/monster-type-definition.h" +#include "system/object-type-definition.h" + +/* + * Quest constants + */ +#define MIN_RANDOM_QUEST 40 /* MAX_RANDOM_QUEST)) + +#define QUEST_TOWER1 5 /*current_floor_ptr; + return cave_clean_bold(floor_ptr, y, x) && (floor_ptr->grid_array[y][x].m_idx == 0) && !player_bold(caster_ptr, y, x); +} + +/*! + * @brief 汎用的なビーム/ボルト/ボール系による地形効果処理 / We are called from "project()" to "damage" terrain features + * @param caster_ptr プレーヤーへの参照ポインタ + * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player") + * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball) + * @param y 目標Y座標 / Target y location (or location to travel "towards") + * @param x 目標X座標 / Target x location (or location to travel "towards") + * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player) + * @param typ 効果属性 / Type of damage to apply to monsters (and objects) + * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE + * @details + *
+ * We are called both for "beam" effects and "ball" effects.
+ *
+ * The "r" parameter is the "distance from ground zero".
+ *
+ * Note that we determine if the player can "see" anything that happens
+ * by taking into account: blindness, line-of-sight, and illumination.
+ *
+ * We return "TRUE" if the effect of the projection is "obvious".
+ *
+ * We also "see" grids which are "memorized", probably a hack
+ *
+ * Perhaps we should affect doors?
+ * 
+ */ +bool affect_feature(player_type *caster_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ) +{ + floor_type *floor_ptr = caster_ptr->current_floor_ptr; + grid_type *g_ptr = &floor_ptr->grid_array[y][x]; + feature_type *f_ptr = &f_info[g_ptr->feat]; + + bool obvious = FALSE; + bool known = player_has_los_bold(caster_ptr, y, x); + + who = who ? who : 0; + dam = (dam + r) / (r + 1); + + if (have_flag(f_ptr->flags, FF_TREE)) { + concptr message; + switch (typ) { + case GF_POIS: + case GF_NUKE: + case GF_DEATH_RAY: + message = _("枯れた", "was blasted."); + break; + case GF_TIME: + message = _("縮んだ", "shrank."); + break; + case GF_ACID: + message = _("溶けた", "melted."); + break; + case GF_COLD: + case GF_ICE: + message = _("凍り、砕け散った", "was frozen and smashed."); + break; + case GF_FIRE: + case GF_ELEC: + case GF_PLASMA: + message = _("燃えた", "burns up!"); + break; + case GF_METEOR: + case GF_CHAOS: + case GF_MANA: + case GF_SEEKER: + case GF_SUPER_RAY: + case GF_SHARDS: + case GF_ROCKET: + case GF_SOUND: + case GF_DISENCHANT: + case GF_FORCE: + case GF_GRAVITY: + message = _("粉砕された", "was crushed."); + break; + default: + message = NULL; + break; + } + + if (message) { + msg_format(_("木は%s。", "A tree %s"), message); + cave_set_feat(caster_ptr, y, x, one_in_(3) ? feat_brake : feat_grass); + + /* Observe */ + if (g_ptr->info & (CAVE_MARK)) + obvious = TRUE; + } + } + + /* Analyze the type */ + switch (typ) { + /* Ignore most effects */ + case GF_CAPTURE: + case GF_HAND_DOOM: + case GF_CAUSE_1: + case GF_CAUSE_2: + case GF_CAUSE_3: + case GF_CAUSE_4: + case GF_MIND_BLAST: + case GF_BRAIN_SMASH: + case GF_DRAIN_MANA: + case GF_PSY_SPEAR: + case GF_FORCE: + case GF_HOLY_FIRE: + case GF_HELL_FIRE: + case GF_PSI: + case GF_PSI_DRAIN: + case GF_TELEKINESIS: + case GF_DOMINATION: + case GF_IDENTIFY: + case GF_ATTACK: + case GF_ACID: + case GF_ELEC: + case GF_COLD: + case GF_ICE: + case GF_FIRE: + case GF_PLASMA: + case GF_METEOR: + case GF_CHAOS: + case GF_MANA: + case GF_SEEKER: + case GF_SUPER_RAY: { + break; + } + case GF_KILL_TRAP: { + if (is_hidden_door(caster_ptr, g_ptr)) { + disclose_grid(caster_ptr, y, x); + if (known) { + obvious = TRUE; + } + } + + if (is_trap(caster_ptr, g_ptr->feat)) { + if (known) { + msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!")); + obvious = TRUE; + } + + cave_alter_feat(caster_ptr, y, x, FF_DISARM); + } + + if (is_closed_door(caster_ptr, g_ptr->feat) && f_ptr->power && have_flag(f_ptr->flags, FF_OPEN)) { + FEAT_IDX old_feat = g_ptr->feat; + cave_alter_feat(caster_ptr, y, x, FF_DISARM); + if (known && (old_feat != g_ptr->feat)) { + msg_print(_("カチッと音がした!", "Click!")); + obvious = TRUE; + } + } + + if (caster_ptr->blind || !player_has_los_bold(caster_ptr, y, x)) + break; + + g_ptr->info &= ~(CAVE_UNSAFE); + lite_spot(caster_ptr, y, x); + obvious = TRUE; + break; + } + case GF_KILL_DOOR: { + if (is_trap(caster_ptr, g_ptr->feat) || have_flag(f_ptr->flags, FF_DOOR)) { + if (known) { + msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!")); + obvious = TRUE; + } + + cave_alter_feat(caster_ptr, y, x, FF_TUNNEL); + } + + if (caster_ptr->blind || !player_has_los_bold(caster_ptr, y, x)) + break; + + g_ptr->info &= ~(CAVE_UNSAFE); + lite_spot(caster_ptr, y, x); + obvious = TRUE; + break; + } + case GF_JAM_DOOR: { + if (!have_flag(f_ptr->flags, FF_SPIKE)) + break; + + s16b old_mimic = g_ptr->mimic; + feature_type *mimic_f_ptr = &f_info[get_feat_mimic(g_ptr)]; + + cave_alter_feat(caster_ptr, y, x, FF_SPIKE); + g_ptr->mimic = old_mimic; + + note_spot(caster_ptr, y, x); + lite_spot(caster_ptr, y, x); + + if (!known || !have_flag(mimic_f_ptr->flags, FF_OPEN)) + break; + + msg_format(_("%sに何かがつっかえて開かなくなった。", "The %s seems stuck."), f_name + mimic_f_ptr->name); + obvious = TRUE; + break; + } + case GF_KILL_WALL: { + if (!have_flag(f_ptr->flags, FF_HURT_ROCK)) + break; + + if (known && (g_ptr->info & (CAVE_MARK))) { + msg_format(_("%sが溶けて泥になった!", "The %s turns into mud!"), f_name + f_info[get_feat_mimic(g_ptr)].name); + obvious = TRUE; + } + + cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK); + caster_ptr->update |= (PU_FLOW); + break; + } + case GF_MAKE_DOOR: { + if (!cave_naked_bold(caster_ptr, y, x)) + break; + if (player_bold(caster_ptr, y, x)) + break; + cave_set_feat(caster_ptr, y, x, feat_door[DOOR_DOOR].closed); + if (g_ptr->info & (CAVE_MARK)) + obvious = TRUE; + break; + } + case GF_MAKE_TRAP: { + place_trap(caster_ptr, y, x); + break; + } + case GF_MAKE_TREE: { + if (!cave_naked_bold(caster_ptr, y, x)) + break; + if (player_bold(caster_ptr, y, x)) + break; + cave_set_feat(caster_ptr, y, x, feat_tree); + if (g_ptr->info & (CAVE_MARK)) + obvious = TRUE; + break; + } + case GF_MAKE_GLYPH: { + if (!cave_naked_bold(caster_ptr, y, x)) + break; + g_ptr->info |= CAVE_OBJECT; + g_ptr->mimic = feat_glyph; + note_spot(caster_ptr, y, x); + lite_spot(caster_ptr, y, x); + break; + } + case GF_STONE_WALL: { + if (!cave_naked_bold(caster_ptr, y, x)) + break; + if (player_bold(caster_ptr, y, x)) + break; + cave_set_feat(caster_ptr, y, x, feat_granite); + break; + } + case GF_LAVA_FLOW: { + if (have_flag(f_ptr->flags, FF_PERMANENT)) + break; + if (dam == 1) { + if (!have_flag(f_ptr->flags, FF_FLOOR)) + break; + cave_set_feat(caster_ptr, y, x, feat_shallow_lava); + } else if (dam) { + cave_set_feat(caster_ptr, y, x, feat_deep_lava); + } + + break; + } + case GF_WATER_FLOW: { + if (have_flag(f_ptr->flags, FF_PERMANENT)) + break; + if (dam == 1) { + if (!have_flag(f_ptr->flags, FF_FLOOR)) + break; + cave_set_feat(caster_ptr, y, x, feat_shallow_water); + } else if (dam) { + cave_set_feat(caster_ptr, y, x, feat_deep_water); + } + + break; + } + case GF_LITE_WEAK: + case GF_LITE: { + if ((d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) != 0) + break; + + g_ptr->info |= (CAVE_GLOW); + note_spot(caster_ptr, y, x); + lite_spot(caster_ptr, y, x); + update_local_illumination(caster_ptr, y, x); + + if (player_can_see_bold(caster_ptr, y, x)) + obvious = TRUE; + if (g_ptr->m_idx) + update_monster(caster_ptr, g_ptr->m_idx, FALSE); + + if (caster_ptr->special_defense & NINJA_S_STEALTH) { + if (player_bold(caster_ptr, y, x)) + set_superstealth(caster_ptr, FALSE); + } + + break; + } + case GF_DARK_WEAK: + case GF_DARK: { + bool do_dark = !caster_ptr->phase_out && !is_mirror_grid(g_ptr); + if (!do_dark) + break; + + if ((floor_ptr->dun_level > 0) || !is_daytime()) { + for (int j = 0; j < 9; j++) { + int by = y + ddy_ddd[j]; + int bx = x + ddx_ddd[j]; + + if (!in_bounds2(floor_ptr, by, bx)) + continue; + + grid_type *cc_ptr = &floor_ptr->grid_array[by][bx]; + if (have_flag(f_info[get_feat_mimic(cc_ptr)].flags, FF_GLOW)) { + do_dark = FALSE; + break; + } + } + + if (!do_dark) + break; + } + + g_ptr->info &= ~(CAVE_GLOW); + + /* Hack -- Forget "boring" grids */ + if (!have_flag(f_ptr->flags, FF_REMEMBER)) { + /* Forget */ + g_ptr->info &= ~(CAVE_MARK); + note_spot(caster_ptr, y, x); + } + + lite_spot(caster_ptr, y, x); + + update_local_illumination(caster_ptr, y, x); + + if (player_can_see_bold(caster_ptr, y, x)) + obvious = TRUE; + if (g_ptr->m_idx) + update_monster(caster_ptr, g_ptr->m_idx, FALSE); + + break; + } + case GF_SHARDS: + case GF_ROCKET: { + if (is_mirror_grid(g_ptr)) { + msg_print(_("鏡が割れた!", "The mirror was shattered!")); + sound(SOUND_GLASS); + remove_mirror(caster_ptr, y, x); + project(caster_ptr, 0, 2, y, x, caster_ptr->lev / 2 + 5, GF_SHARDS, + (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI), -1); + } + + if (!have_flag(f_ptr->flags, FF_GLASS) || have_flag(f_ptr->flags, FF_PERMANENT) || (dam < 50)) + break; + + if (known && (g_ptr->info & CAVE_MARK)) { + msg_format(_("%sが割れた!", "The %s crumbled!"), f_name + f_info[get_feat_mimic(g_ptr)].name); + sound(SOUND_GLASS); + } + + cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK); + caster_ptr->update |= (PU_FLOW); + break; + } + case GF_SOUND: { + if (is_mirror_grid(g_ptr) && caster_ptr->lev < 40) { + msg_print(_("鏡が割れた!", "The mirror was shattered!")); + sound(SOUND_GLASS); + remove_mirror(caster_ptr, y, x); + project(caster_ptr, 0, 2, y, x, caster_ptr->lev / 2 + 5, GF_SHARDS, + (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI), -1); + } + + if (!have_flag(f_ptr->flags, FF_GLASS) || have_flag(f_ptr->flags, FF_PERMANENT) || (dam < 200)) + break; + + if (known && (g_ptr->info & CAVE_MARK)) { + msg_format(_("%sが割れた!", "The %s crumbled!"), f_name + f_info[get_feat_mimic(g_ptr)].name); + sound(SOUND_GLASS); + } + + cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK); + caster_ptr->update |= (PU_FLOW); + break; + } + case GF_DISINTEGRATE: { + if (is_mirror_grid(g_ptr) || is_glyph_grid(g_ptr) || is_explosive_rune_grid(g_ptr)) + remove_mirror(caster_ptr, y, x); + + if (!have_flag(f_ptr->flags, FF_HURT_DISI) || have_flag(f_ptr->flags, FF_PERMANENT)) + break; + + cave_alter_feat(caster_ptr, y, x, FF_HURT_DISI); + caster_ptr->update |= (PU_FLOW); + break; + } + } + + lite_spot(caster_ptr, y, x); + return (obvious); +} diff --git a/src/effect/effect-feature.h b/src/effect/effect-feature.h new file mode 100644 index 000000000..a83c5f355 --- /dev/null +++ b/src/effect/effect-feature.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool affect_feature(player_type *caster_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ); diff --git a/src/effect/effect-item.c b/src/effect/effect-item.c new file mode 100644 index 000000000..3f0f2ffe0 --- /dev/null +++ b/src/effect/effect-item.c @@ -0,0 +1,256 @@ +#include "effect/effect-item.h" +#include "autopick/autopick.h" +#include "flavor/flavor-describer.h" +#include "flavor/object-flavor-types.h" +#include "floor/cave.h" +#include "floor/floor-object.h" +#include "monster-floor/monster-summon.h" +#include "monster-floor/place-monster-types.h" +#include "monster/monster-info.h" +#include "object-enchant/tr-types.h" +#include "object-hook/hook-checker.h" +#include "object-hook/hook-enchant.h" +#include "object-hook/hook-expendable.h" +#include "object/object-broken.h" +#include "object/object-flags.h" +#include "object/object-mark-types.h" +#include "perception/object-perception.h" +#include "spell-kind/spells-perception.h" +#include "spell/spell-types.h" +#include "sv-definition/sv-other-types.h" +#include "sv-definition/sv-scroll-types.h" +#include "system/floor-type-definition.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" + +/*! + * @brief 汎用的なビーム/ボルト/ボール系によるアイテムオブジェクトへの効果処理 / Handle a beam/bolt/ball causing damage to a monster. + * @param caster_ptr プレーヤーへの参照ポインタ + * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player") + * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball) + * @param y 目標Y座標 / Target y location (or location to travel "towards") + * @param x 目標X座標 / Target x location (or location to travel "towards") + * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player) + * @param typ 効果属性 / Type of damage to apply to monsters (and objects) + * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE + */ +bool affect_item(player_type *caster_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ) +{ + grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x]; + + bool is_item_affected = FALSE; + bool known = player_has_los_bold(caster_ptr, y, x); + who = who ? who : 0; + dam = (dam + r) / (r + 1); + OBJECT_IDX next_o_idx = 0; + for (OBJECT_IDX this_o_idx = g_ptr->o_idx; this_o_idx != 0; this_o_idx = next_o_idx) { + object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[this_o_idx]; + bool ignore = FALSE; + bool do_kill = FALSE; + concptr note_kill = NULL; + +#ifdef JP +#else + bool plural = (o_ptr->number > 1); +#endif + next_o_idx = o_ptr->next_o_idx; + BIT_FLAGS flags[TR_FLAG_SIZE]; + object_flags(caster_ptr, o_ptr, flags); + bool is_artifact = object_is_artifact(o_ptr); + switch (typ) { + case GF_ACID: { + if (hates_acid(o_ptr)) { + do_kill = TRUE; + note_kill = _("融けてしまった!", (plural ? " melt!" : " melts!")); + if (have_flag(flags, TR_IGNORE_ACID)) + ignore = TRUE; + } + + break; + } + case GF_ELEC: { + if (hates_elec(o_ptr)) { + do_kill = TRUE; + note_kill = _("壊れてしまった!", (plural ? " are destroyed!" : " is destroyed!")); + if (have_flag(flags, TR_IGNORE_ELEC)) + ignore = TRUE; + } + + break; + } + case GF_FIRE: { + if (hates_fire(o_ptr)) { + do_kill = TRUE; + note_kill = _("燃えてしまった!", (plural ? " burn up!" : " burns up!")); + if (have_flag(flags, TR_IGNORE_FIRE)) + ignore = TRUE; + } + + break; + } + case GF_COLD: { + if (hates_cold(o_ptr)) { + note_kill = _("砕け散ってしまった!", (plural ? " shatter!" : " shatters!")); + do_kill = TRUE; + if (have_flag(flags, TR_IGNORE_COLD)) + ignore = TRUE; + } + + break; + } + case GF_PLASMA: { + if (hates_fire(o_ptr)) { + do_kill = TRUE; + note_kill = _("燃えてしまった!", (plural ? " burn up!" : " burns up!")); + if (have_flag(flags, TR_IGNORE_FIRE)) + ignore = TRUE; + } + + if (hates_elec(o_ptr)) { + ignore = FALSE; + do_kill = TRUE; + note_kill = _("壊れてしまった!", (plural ? " are destroyed!" : " is destroyed!")); + if (have_flag(flags, TR_IGNORE_ELEC)) + ignore = TRUE; + } + + break; + } + case GF_METEOR: { + if (hates_fire(o_ptr)) { + do_kill = TRUE; + note_kill = _("燃えてしまった!", (plural ? " burn up!" : " burns up!")); + if (have_flag(flags, TR_IGNORE_FIRE)) + ignore = TRUE; + } + + if (hates_cold(o_ptr)) { + ignore = FALSE; + do_kill = TRUE; + note_kill = _("砕け散ってしまった!", (plural ? " shatter!" : " shatters!")); + if (have_flag(flags, TR_IGNORE_COLD)) + ignore = TRUE; + } + + break; + } + case GF_ICE: + case GF_SHARDS: + case GF_FORCE: + case GF_SOUND: { + if (hates_cold(o_ptr)) { + note_kill = _("砕け散ってしまった!", (plural ? " shatter!" : " shatters!")); + do_kill = TRUE; + } + + break; + } + case GF_MANA: + case GF_SEEKER: + case GF_SUPER_RAY: { + do_kill = TRUE; + note_kill = _("壊れてしまった!", (plural ? " are destroyed!" : " is destroyed!")); + break; + } + case GF_DISINTEGRATE: { + do_kill = TRUE; + note_kill = _("蒸発してしまった!", (plural ? " evaporate!" : " evaporates!")); + break; + } + case GF_CHAOS: { + do_kill = TRUE; + note_kill = _("壊れてしまった!", (plural ? " are destroyed!" : " is destroyed!")); + if (have_flag(flags, TR_RES_CHAOS)) + ignore = TRUE; + else if ((o_ptr->tval == TV_SCROLL) && (o_ptr->sval == SV_SCROLL_CHAOS)) + ignore = TRUE; + break; + } + case GF_HOLY_FIRE: + case GF_HELL_FIRE: { + if (object_is_cursed(o_ptr)) { + do_kill = TRUE; + note_kill = _("壊れてしまった!", (plural ? " are destroyed!" : " is destroyed!")); + } + + break; + } + case GF_IDENTIFY: { + identify_item(caster_ptr, o_ptr); + autopick_alter_item(caster_ptr, (-this_o_idx), FALSE); + break; + } + case GF_KILL_TRAP: + case GF_KILL_DOOR: { + if (o_ptr->tval != TV_CHEST) + break; + if (o_ptr->pval <= 0) + break; + + o_ptr->pval = (0 - o_ptr->pval); + object_known(o_ptr); + if (known && (o_ptr->marked & OM_FOUND)) { + msg_print(_("カチッと音がした!", "Click!")); + is_item_affected = TRUE; + } + + break; + } + case GF_ANIM_DEAD: { + if (o_ptr->tval != TV_CORPSE) + break; + + BIT_FLAGS mode = 0L; + if (!who || is_pet(&caster_ptr->current_floor_ptr->m_list[who])) + mode |= PM_FORCE_PET; + + for (int i = 0; i < o_ptr->number; i++) { + if (((o_ptr->sval == SV_CORPSE) && (randint1(100) > 80)) || ((o_ptr->sval == SV_SKELETON) && (randint1(100) > 60))) { + if (!note_kill) { + note_kill = _("灰になった。", (plural ? " become dust." : " becomes dust.")); + } + + continue; + } else if (summon_named_creature(caster_ptr, who, y, x, o_ptr->pval, mode)) { + note_kill = _("生き返った。", " revived."); + } else if (!note_kill) { + note_kill = _("灰になった。", (plural ? " become dust." : " becomes dust.")); + } + } + + do_kill = TRUE; + is_item_affected = TRUE; + break; + } + } + + if (!do_kill) + continue; + + GAME_TEXT o_name[MAX_NLEN]; + if (known && (o_ptr->marked & OM_FOUND)) { + is_item_affected = TRUE; + describe_flavor(caster_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY)); + } + + if ((is_artifact || ignore)) { + if (known && (o_ptr->marked & OM_FOUND)) + msg_format(_("%sは影響を受けない!", (plural ? "The %s are unaffected!" : "The %s is unaffected!")), o_name); + + continue; + } + + if (known && (o_ptr->marked & OM_FOUND) && note_kill) + msg_format(_("%sは%s", "The %s%s"), o_name, note_kill); + + KIND_OBJECT_IDX k_idx = o_ptr->k_idx; + bool is_potion = object_is_potion(o_ptr); + delete_object_idx(caster_ptr, this_o_idx); + if (is_potion) + (void)potion_smash_effect(caster_ptr, who, y, x, k_idx); + + lite_spot(caster_ptr, y, x); + } + + return is_item_affected; +} diff --git a/src/effect/effect-item.h b/src/effect/effect-item.h new file mode 100644 index 000000000..8b7c5814c --- /dev/null +++ b/src/effect/effect-item.h @@ -0,0 +1,5 @@ +#pragma once + +#include "system/angband.h" + +bool affect_item(player_type *caster_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ); diff --git a/src/effect/effect-monster-charm.c b/src/effect/effect-monster-charm.c new file mode 100644 index 000000000..d995b4267 --- /dev/null +++ b/src/effect/effect-monster-charm.c @@ -0,0 +1,395 @@ +#include "effect/effect-monster-charm.h" +#include "dungeon/quest.h" +#include "effect/effect-monster-util.h" +#include "effect/spells-effect-util.h" +#include "monster-race/monster-race-hook.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags3.h" +#include "monster-race/race-flags7.h" +#include "monster-race/race-indice-types.h" +#include "monster/monster-flag-types.h" +#include "monster/monster-info.h" +#include "monster/monster-list.h" +#include "monster-floor/monster-remover.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "object-enchant/trc-types.h" +#include "pet/pet-fall-off.h" +#include "player-info/avatar.h" +#include "status/bad-status-setter.h" +#include "spell/spells-diceroll.h" +#include "system/floor-type-definition.h" +#include "view/display-messages.h" + +static void effect_monster_charm_resist(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (common_saving_throw_charm(caster_ptr, em_ptr->dam, em_ptr->m_ptr)) { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + + if (one_in_(4)) + em_ptr->m_ptr->mflag2 |= MFLAG2_NOPET; + } else if (caster_ptr->cursed & TRC_AGGRAVATE) { + em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!"); + if (one_in_(4)) + em_ptr->m_ptr->mflag2 |= MFLAG2_NOPET; + } else { + em_ptr->note = _("は突然友好的になったようだ!", " suddenly seems friendly!"); + set_pet(caster_ptr, em_ptr->m_ptr); + + chg_virtue(caster_ptr, V_INDIVIDUALISM, -1); + if (em_ptr->r_ptr->flags3 & RF3_ANIMAL) + chg_virtue(caster_ptr, V_NATURE, 1); + } +} + +process_result effect_monster_charm(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + int vir = virtue_number(caster_ptr, V_HARMONY); + if (vir) { + em_ptr->dam += caster_ptr->virtues[vir - 1] / 10; + } + + vir = virtue_number(caster_ptr, V_INDIVIDUALISM); + if (vir) { + em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20; + } + + if (em_ptr->seen) + em_ptr->obvious = TRUE; + + effect_monster_charm_resist(caster_ptr, em_ptr); + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + +process_result effect_monster_control_undead(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) + em_ptr->obvious = TRUE; + + int vir = virtue_number(caster_ptr, V_UNLIFE); + if (vir) { + em_ptr->dam += caster_ptr->virtues[vir - 1] / 10; + } + + vir = virtue_number(caster_ptr, V_INDIVIDUALISM); + if (vir) { + em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20; + } + + if (common_saving_throw_control(caster_ptr, em_ptr->dam, em_ptr->m_ptr) || !(em_ptr->r_ptr->flags3 & RF3_UNDEAD)) { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + if (one_in_(4)) + em_ptr->m_ptr->mflag2 |= MFLAG2_NOPET; + } else if (caster_ptr->cursed & TRC_AGGRAVATE) { + em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!"); + if (one_in_(4)) + em_ptr->m_ptr->mflag2 |= MFLAG2_NOPET; + } else { + em_ptr->note = _("は既にあなたの奴隷だ!", " is in your thrall!"); + set_pet(caster_ptr, em_ptr->m_ptr); + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + +process_result effect_monster_control_demon(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) + em_ptr->obvious = TRUE; + + int vir = virtue_number(caster_ptr, V_UNLIFE); + if (vir) { + em_ptr->dam += caster_ptr->virtues[vir - 1] / 10; + } + + vir = virtue_number(caster_ptr, V_INDIVIDUALISM); + if (vir) { + em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20; + } + + if (common_saving_throw_control(caster_ptr, em_ptr->dam, em_ptr->m_ptr) || !(em_ptr->r_ptr->flags3 & RF3_DEMON)) { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + if (one_in_(4)) + em_ptr->m_ptr->mflag2 |= MFLAG2_NOPET; + } else if (caster_ptr->cursed & TRC_AGGRAVATE) { + em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!"); + if (one_in_(4)) + em_ptr->m_ptr->mflag2 |= MFLAG2_NOPET; + } else { + em_ptr->note = _("は既にあなたの奴隷だ!", " is in your thrall!"); + set_pet(caster_ptr, em_ptr->m_ptr); + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + +process_result effect_monster_control_animal(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) + em_ptr->obvious = TRUE; + + int vir = virtue_number(caster_ptr, V_NATURE); + if (vir) { + em_ptr->dam += caster_ptr->virtues[vir - 1] / 10; + } + + vir = virtue_number(caster_ptr, V_INDIVIDUALISM); + if (vir) { + em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20; + } + + if (common_saving_throw_control(caster_ptr, em_ptr->dam, em_ptr->m_ptr) || !(em_ptr->r_ptr->flags3 & RF3_ANIMAL)) { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + if (one_in_(4)) + em_ptr->m_ptr->mflag2 |= MFLAG2_NOPET; + } else if (caster_ptr->cursed & TRC_AGGRAVATE) { + em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!"); + if (one_in_(4)) + em_ptr->m_ptr->mflag2 |= MFLAG2_NOPET; + } else { + em_ptr->note = _("はなついた。", " is tamed!"); + set_pet(caster_ptr, em_ptr->m_ptr); + if (em_ptr->r_ptr->flags3 & RF3_ANIMAL) + chg_virtue(caster_ptr, V_NATURE, 1); + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + +process_result effect_monster_charm_living(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + int vir = virtue_number(caster_ptr, V_UNLIFE); + if (em_ptr->seen) + em_ptr->obvious = TRUE; + + vir = virtue_number(caster_ptr, V_UNLIFE); + if (vir) { + em_ptr->dam -= caster_ptr->virtues[vir - 1] / 10; + } + + vir = virtue_number(caster_ptr, V_INDIVIDUALISM); + if (vir) { + em_ptr->dam -= caster_ptr->virtues[vir - 1] / 20; + } + + msg_format(_("%sを見つめた。", "You stare into %s."), em_ptr->m_name); + + if (common_saving_throw_charm(caster_ptr, em_ptr->dam, em_ptr->m_ptr) || !monster_living(em_ptr->m_ptr->r_idx)) { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + if (one_in_(4)) + em_ptr->m_ptr->mflag2 |= MFLAG2_NOPET; + } else if (caster_ptr->cursed & TRC_AGGRAVATE) { + em_ptr->note = _("はあなたに敵意を抱いている!", " hates you too much!"); + if (one_in_(4)) + em_ptr->m_ptr->mflag2 |= MFLAG2_NOPET; + } else { + em_ptr->note = _("を支配した。", " is tamed!"); + set_pet(caster_ptr, em_ptr->m_ptr); + if (em_ptr->r_ptr->flags3 & RF3_ANIMAL) + chg_virtue(caster_ptr, V_NATURE, 1); + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + +static void effect_monster_domination_corrupted_addition(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + switch (randint1(4)) { + case 1: + set_stun(caster_ptr, caster_ptr->stun + em_ptr->dam / 2); + break; + case 2: + set_confused(caster_ptr, caster_ptr->confused + em_ptr->dam / 2); + break; + default: { + if (em_ptr->r_ptr->flags3 & RF3_NO_FEAR) + em_ptr->note = _("には効果がなかった。", " is unaffected."); + else + set_afraid(caster_ptr, caster_ptr->afraid + em_ptr->dam); + } + } +} + +// Powerful demons & undead can turn a mindcrafter's attacks back on them. +static void effect_monster_domination_corrupted(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + bool is_corrupted = ((em_ptr->r_ptr->flags3 & (RF3_UNDEAD | RF3_DEMON)) != 0) && (em_ptr->r_ptr->level > caster_ptr->lev / 2) && (one_in_(2)); + if (!is_corrupted) { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + return; + } + + em_ptr->note = NULL; + msg_format(_("%^sの堕落した精神は攻撃を跳ね返した!", + (em_ptr->seen ? "%^s's corrupted mind backlashes your attack!" : "%^ss corrupted mind backlashes your attack!")), + em_ptr->m_name); + if (randint0(100 + em_ptr->r_ptr->level / 2) < caster_ptr->skill_sav) { + msg_print(_("しかし効力を跳ね返した!", "You resist the effects!")); + return; + } + + effect_monster_domination_corrupted_addition(caster_ptr, em_ptr); +} + +static void effect_monster_domination_addition(effect_monster_type *em_ptr) +{ + switch (randint1(4)) { + case 1: + em_ptr->do_stun = em_ptr->dam / 2; + break; + case 2: + em_ptr->do_conf = em_ptr->dam / 2; + break; + default: + em_ptr->do_fear = em_ptr->dam; + } +} + +process_result effect_monster_domination(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (!is_hostile(em_ptr->m_ptr)) + return PROCESS_CONTINUE; + + if (em_ptr->seen) + em_ptr->obvious = TRUE; + + if ((em_ptr->r_ptr->flags1 & (RF1_UNIQUE | RF1_QUESTOR)) || (em_ptr->r_ptr->flags3 & RF3_NO_CONF) + || (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) { + if (((em_ptr->r_ptr->flags3 & RF3_NO_CONF) != 0) && is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_NO_CONF); + + em_ptr->do_conf = 0; + effect_monster_domination_corrupted(caster_ptr, em_ptr); + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (!common_saving_throw_charm(caster_ptr, em_ptr->dam, em_ptr->m_ptr)) { + em_ptr->note = _("があなたに隷属した。", " is in your thrall!"); + set_pet(caster_ptr, em_ptr->m_ptr); + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + effect_monster_domination_addition(em_ptr); + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + +static bool effect_monster_crusade_domination(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (((em_ptr->r_ptr->flags3 & RF3_GOOD) == 0) || caster_ptr->current_floor_ptr->inside_arena) + return FALSE; + + if (em_ptr->r_ptr->flags3 & RF3_NO_CONF) + em_ptr->dam -= 50; + if (em_ptr->dam < 1) + em_ptr->dam = 1; + + if (is_pet(em_ptr->m_ptr)) { + em_ptr->note = _("の動きが速くなった。", " starts moving faster."); + (void)set_monster_fast(caster_ptr, em_ptr->g_ptr->m_idx, monster_fast_remaining(em_ptr->m_ptr) + 100); + return TRUE; + } + + if ((em_ptr->r_ptr->flags1 & RF1_QUESTOR) || (em_ptr->r_ptr->flags1 & RF1_UNIQUE) || (em_ptr->m_ptr->mflag2 & MFLAG2_NOPET) + || (caster_ptr->cursed & TRC_AGGRAVATE) || ((em_ptr->r_ptr->level + 10) > randint1(em_ptr->dam))) { + if (one_in_(4)) + em_ptr->m_ptr->mflag2 |= MFLAG2_NOPET; + + return FALSE; + } + + em_ptr->note = _("を支配した。", " is tamed!"); + set_pet(caster_ptr, em_ptr->m_ptr); + (void)set_monster_fast(caster_ptr, em_ptr->g_ptr->m_idx, monster_fast_remaining(em_ptr->m_ptr) + 100); + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= RF3_GOOD; + + return TRUE; +} + +process_result effect_monster_crusade(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) + em_ptr->obvious = TRUE; + bool success = effect_monster_crusade_domination(caster_ptr, em_ptr); + if (success) { + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if ((em_ptr->r_ptr->flags3 & RF3_NO_FEAR) == 0) + em_ptr->do_fear = randint1(90) + 10; + else if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= RF3_NO_FEAR; + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + +static bool effect_monster_capture_attemption(player_type *caster_ptr, effect_monster_type *em_ptr, int capturable_hp) +{ + if (em_ptr->m_ptr->hp >= randint0(capturable_hp)) + return FALSE; + + if (em_ptr->m_ptr->mflag2 & MFLAG2_CHAMELEON) + choose_new_monster(caster_ptr, em_ptr->g_ptr->m_idx, FALSE, MON_CHAMELEON); + + msg_format(_("%sを捕えた!", "You capture %^s!"), em_ptr->m_name); + cap_mon = em_ptr->m_ptr->r_idx; + cap_mspeed = em_ptr->m_ptr->mspeed; + cap_hp = em_ptr->m_ptr->hp; + cap_maxhp = em_ptr->m_ptr->max_maxhp; + cap_nickname = em_ptr->m_ptr->nickname; + if ((em_ptr->g_ptr->m_idx == caster_ptr->riding) && process_fall_off_horse(caster_ptr, -1, FALSE)) + msg_format(_("地面に落とされた。", "You have fallen from %s."), em_ptr->m_name); + + delete_monster_idx(caster_ptr, em_ptr->g_ptr->m_idx); + return TRUE; +} + +process_result effect_monster_capture(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + floor_type *floor_ptr = caster_ptr->current_floor_ptr; + int capturable_hp; + if ((floor_ptr->inside_quest && (quest[floor_ptr->inside_quest].type == QUEST_TYPE_KILL_ALL) && !is_pet(em_ptr->m_ptr)) + || (em_ptr->r_ptr->flags1 & (RF1_UNIQUE)) || (em_ptr->r_ptr->flags7 & (RF7_NAZGUL)) || (em_ptr->r_ptr->flags7 & (RF7_UNIQUE2)) + || (em_ptr->r_ptr->flags1 & RF1_QUESTOR) || em_ptr->m_ptr->parent_m_idx) { + msg_format(_("%sには効果がなかった。", "%s is unaffected."), em_ptr->m_name); + em_ptr->skipped = TRUE; + return PROCESS_CONTINUE; + } + + if (is_pet(em_ptr->m_ptr)) + capturable_hp = em_ptr->m_ptr->maxhp * 4L; + else if ((caster_ptr->pclass == CLASS_BEASTMASTER) && monster_living(em_ptr->m_ptr->r_idx)) + capturable_hp = em_ptr->m_ptr->maxhp * 3 / 10; + else + capturable_hp = em_ptr->m_ptr->maxhp * 3 / 20; + + if (em_ptr->m_ptr->hp >= capturable_hp) { + msg_format(_("もっと弱らせないと。", "You need to weaken %s more."), em_ptr->m_name); + em_ptr->skipped = TRUE; + return PROCESS_CONTINUE; + } + + if (effect_monster_capture_attemption(caster_ptr, em_ptr, capturable_hp)) + return PROCESS_TRUE; + + msg_format(_("うまく捕まえられなかった。", "You failed to capture %s."), em_ptr->m_name); + em_ptr->skipped = TRUE; + return PROCESS_CONTINUE; +} diff --git a/src/effect/effect-monster-charm.h b/src/effect/effect-monster-charm.h new file mode 100644 index 000000000..65b5e90b2 --- /dev/null +++ b/src/effect/effect-monster-charm.h @@ -0,0 +1,14 @@ +#pragma once + +#include "system/angband.h" + +typedef enum process_result process_resut; +typedef struct effect_monster_type effect_monster_type; +process_result effect_monster_charm(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_control_undead(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_control_demon(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_control_animal(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_charm_living(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_domination(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_crusade(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_capture(player_type *caster_ptr, effect_monster_type *em_ptr); diff --git a/src/effect/effect-monster-curse.c b/src/effect/effect-monster-curse.c new file mode 100644 index 000000000..c1ad7397c --- /dev/null +++ b/src/effect/effect-monster-curse.c @@ -0,0 +1,65 @@ +#include "effect/effect-monster-curse.h" +#include "effect/effect-monster-util.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-indice-types.h" +#include "view/display-messages.h" + +process_result effect_monster_curse_1(effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (!em_ptr->who) msg_format(_("%sを指差して呪いをかけた。", "You point at %s and curse."), em_ptr->m_name); + if (randint0(100 + (em_ptr->caster_lev / 2)) < (em_ptr->r_ptr->level + 35)) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->dam = 0; + } + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_curse_2(effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (!em_ptr->who) msg_format(_("%sを指差して恐ろしげに呪いをかけた。", "You point at %s and curse horribly."), em_ptr->m_name); + + if (randint0(100 + (em_ptr->caster_lev / 2)) < (em_ptr->r_ptr->level + 35)) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->dam = 0; + } + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_curse_3(effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (!em_ptr->who) msg_format(_("%sを指差し、恐ろしげに呪文を唱えた!", "You point at %s, incanting terribly!"), em_ptr->m_name); + + if (randint0(100 + (em_ptr->caster_lev / 2)) < (em_ptr->r_ptr->level + 35)) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->dam = 0; + } + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_curse_4(effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (!em_ptr->who) + msg_format(_("%sの秘孔を突いて、「お前は既に死んでいる」と叫んだ。", + "You point at %s, screaming the word, 'DIE!'."), em_ptr->m_name); + + if ((randint0(100 + (em_ptr->caster_lev / 2)) < (em_ptr->r_ptr->level + 35)) && ((em_ptr->who <= 0) || (em_ptr->m_caster_ptr->r_idx != MON_KENSHIROU))) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->dam = 0; + } + + return PROCESS_CONTINUE; +} diff --git a/src/effect/effect-monster-curse.h b/src/effect/effect-monster-curse.h new file mode 100644 index 000000000..3673cbdf7 --- /dev/null +++ b/src/effect/effect-monster-curse.h @@ -0,0 +1,10 @@ +#pragma once + +#include "system/angband.h" + +typedef enum process_result process_resut; +typedef struct effect_monster_type effect_monster_type; +process_result effect_monster_curse_1(effect_monster_type *em_ptr); +process_result effect_monster_curse_2(effect_monster_type *em_ptr); +process_result effect_monster_curse_3(effect_monster_type *em_ptr); +process_result effect_monster_curse_4(effect_monster_type *em_ptr); diff --git a/src/effect/effect-monster-evil.c b/src/effect/effect-monster-evil.c new file mode 100644 index 000000000..38f87371b --- /dev/null +++ b/src/effect/effect-monster-evil.c @@ -0,0 +1,267 @@ +#include "effect/effect-monster-evil.h" +#include "effect/effect-monster-util.h" +#include "monster-race/monster-race-hook.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags-resistance.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags3.h" +#include "monster/monster-info.h" + +static bool effect_monster_away_resist(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flagsr & RFR_RES_TELE) == 0) return FALSE; + + if ((em_ptr->r_ptr->flags1 & (RF1_UNIQUE)) || (em_ptr->r_ptr->flagsr & RFR_RES_ALL)) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flagsr |= RFR_RES_TELE; + em_ptr->note = _("には効果がなかった。", " is unaffected."); + return TRUE; + } + + if (em_ptr->r_ptr->level > randint1(100)) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flagsr |= RFR_RES_TELE; + em_ptr->note = _("には耐性がある!", " resists!"); + return TRUE; + } + + return FALSE; +} + + +process_result effect_monster_away_undead(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags3 & (RF3_UNDEAD)) == 0) + { + em_ptr->skipped = TRUE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + bool resists_tele = effect_monster_away_resist(caster_ptr, em_ptr); + if (!resists_tele) + { + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_UNDEAD); + + em_ptr->do_dist = em_ptr->dam; + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_away_evil(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags3 & (RF3_EVIL)) == 0) + { + em_ptr->skipped = TRUE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + bool resists_tele = effect_monster_away_resist(caster_ptr, em_ptr); + if (!resists_tele) + { + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_EVIL); + + em_ptr->do_dist = em_ptr->dam; + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_away_all(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + bool resists_tele = effect_monster_away_resist(caster_ptr, em_ptr); + if (!resists_tele) + { + if (em_ptr->seen) em_ptr->obvious = TRUE; + + em_ptr->do_dist = em_ptr->dam; + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_turn_undead(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags3 & (RF3_UNDEAD)) == 0) + { + em_ptr->skipped = TRUE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags3 |= (RF3_UNDEAD); + + em_ptr->do_fear = damroll(3, (em_ptr->dam / 2)) + 1; + if (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + em_ptr->do_fear = 0; + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_turn_evil(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags3 & (RF3_EVIL)) == 0) + { + em_ptr->skipped = TRUE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags3 |= (RF3_EVIL); + + em_ptr->do_fear = damroll(3, (em_ptr->dam / 2)) + 1; + if (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + em_ptr->do_fear = 0; + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_turn_all(effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + em_ptr->do_fear = damroll(3, (em_ptr->dam / 2)) + 1; + if ((em_ptr->r_ptr->flags1 & (RF1_UNIQUE)) || + (em_ptr->r_ptr->flags3 & (RF3_NO_FEAR)) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + em_ptr->do_fear = 0; + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_disp_undead(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags3 & (RF3_UNDEAD)) == 0) + { + em_ptr->skipped = TRUE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_UNDEAD); + + em_ptr->note = _("は身震いした。", " shudders."); + em_ptr->note_dies = _("はドロドロに溶けた!", " dissolves!"); + return PROCESS_CONTINUE; +} + + +process_result effect_monster_disp_evil(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags3 & (RF3_EVIL)) == 0) + { + em_ptr->skipped = TRUE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags3 |= (RF3_EVIL); + + em_ptr->note = _("は身震いした。", " shudders."); + em_ptr->note_dies = _("はドロドロに溶けた!", " dissolves!"); + return PROCESS_CONTINUE; +} + + +process_result effect_monster_disp_good(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags3 & (RF3_GOOD)) == 0) + { + em_ptr->skipped = TRUE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags3 |= (RF3_GOOD); + + em_ptr->note = _("は身震いした。", " shudders."); + em_ptr->note_dies = _("はドロドロに溶けた!", " dissolves!"); + return PROCESS_CONTINUE; +} + + +process_result effect_monster_disp_living(effect_monster_type *em_ptr) +{ + if (!monster_living(em_ptr->m_ptr->r_idx)) + { + em_ptr->skipped = TRUE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (em_ptr->seen) em_ptr->obvious = TRUE; + + em_ptr->note = _("は身震いした。", " shudders."); + em_ptr->note_dies = _("はドロドロに溶けた!", " dissolves!"); + return PROCESS_CONTINUE; +} + + +process_result effect_monster_disp_demon(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags3 & (RF3_DEMON)) == 0) + { + em_ptr->skipped = TRUE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags3 |= (RF3_DEMON); + + em_ptr->note = _("は身震いした。", " shudders."); + em_ptr->note_dies = _("はドロドロに溶けた!", " dissolves!"); + return PROCESS_CONTINUE; +} + + +process_result effect_monster_disp_all(effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + em_ptr->note = _("は身震いした。", " shudders."); + em_ptr->note_dies = _("はドロドロに溶けた!", " dissolves!"); + return PROCESS_CONTINUE; +} diff --git a/src/effect/effect-monster-evil.h b/src/effect/effect-monster-evil.h new file mode 100644 index 000000000..45162d711 --- /dev/null +++ b/src/effect/effect-monster-evil.h @@ -0,0 +1,18 @@ +#pragma once + +#include "system/angband.h" + +typedef enum process_result process_resut; +typedef struct effect_monster_type effect_monster_type; +process_result effect_monster_away_undead(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_away_evil(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_away_all(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_turn_undead(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_turn_evil(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_turn_all(effect_monster_type *em_ptr); +process_result effect_monster_disp_undead(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_disp_evil(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_disp_good(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_disp_living(effect_monster_type *em_ptr); +process_result effect_monster_disp_demon(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_disp_all(effect_monster_type *em_ptr); diff --git a/src/effect/effect-monster-lite-dark.c b/src/effect/effect-monster-lite-dark.c new file mode 100644 index 000000000..dc1d12718 --- /dev/null +++ b/src/effect/effect-monster-lite-dark.c @@ -0,0 +1,71 @@ +#include "effect/effect-monster-lite-dark.h" +#include "effect/effect-monster-util.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags-resistance.h" +#include "monster-race/race-flags3.h" +#include "monster/monster-info.h" + +process_result effect_monster_lite_weak(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (!em_ptr->dam) + { + em_ptr->skipped = TRUE; + return PROCESS_CONTINUE; + } + + if ((em_ptr->r_ptr->flags3 & RF3_HURT_LITE) == 0) + { + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_HURT_LITE); + + em_ptr->note = _("は光に身をすくめた!", " cringes from the light!"); + em_ptr->note_dies = _("は光を受けてしぼんでしまった!", " shrivels away in the light!"); + return PROCESS_CONTINUE; +} + + +process_result effect_monster_lite(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (em_ptr->r_ptr->flagsr & RFR_RES_LITE) + { + em_ptr->note = _("には耐性がある!", " resists!"); + em_ptr->dam *= 2; em_ptr->dam /= (randint1(6) + 6); + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_LITE); + } + else if (em_ptr->r_ptr->flags3 & (RF3_HURT_LITE)) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_HURT_LITE); + + em_ptr->note = _("は光に身をすくめた!", " cringes from the light!"); + em_ptr->note_dies = _("は光を受けてしぼんでしまった!", " shrivels away in the light!"); + em_ptr->dam *= 2; + } + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_dark(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if ((em_ptr->r_ptr->flagsr & RFR_RES_DARK) == 0) + return PROCESS_CONTINUE; + + em_ptr->note = _("には耐性がある!", " resists!"); + em_ptr->dam *= 2; em_ptr->dam /= (randint1(6) + 6); + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_DARK); + + return PROCESS_CONTINUE; +} diff --git a/src/effect/effect-monster-lite-dark.h b/src/effect/effect-monster-lite-dark.h new file mode 100644 index 000000000..24c638415 --- /dev/null +++ b/src/effect/effect-monster-lite-dark.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" + +typedef enum process_result process_resut; +typedef struct effect_monster_type effect_monster_type; +process_result effect_monster_lite_weak(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_lite(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_dark(player_type *caster_ptr, effect_monster_type *em_ptr); diff --git a/src/effect/effect-monster-oldies.c b/src/effect/effect-monster-oldies.c new file mode 100644 index 000000000..cd39ee801 --- /dev/null +++ b/src/effect/effect-monster-oldies.c @@ -0,0 +1,309 @@ +#include "effect/effect-monster-oldies.h" +#include "core/player-redraw-types.h" +#include "effect/effect-monster-util.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags3.h" +#include "monster-race/race-flags7.h" +#include "monster-race/race-indice-types.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "monster-floor/monster-generator.h" +#include "monster/monster-info.h" +#include "player-info/avatar.h" +#include "system/floor-type-definition.h" +#include "view/display-messages.h" + +// Powerful monsters can resist. +process_result effect_monster_old_poly(effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + em_ptr->do_polymorph = TRUE; + + if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) || + (em_ptr->r_ptr->flags1 & RF1_QUESTOR) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->do_polymorph = FALSE; + em_ptr->obvious = FALSE; + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_old_clone(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if ((caster_ptr->current_floor_ptr->inside_arena) || + is_pet(em_ptr->m_ptr) || + (em_ptr->r_ptr->flags1 & (RF1_UNIQUE | RF1_QUESTOR)) || + (em_ptr->r_ptr->flags7 & (RF7_NAZGUL | RF7_UNIQUE2))) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + em_ptr->m_ptr->hp = em_ptr->m_ptr->maxhp; + if (multiply_monster(caster_ptr, em_ptr->g_ptr->m_idx, TRUE, 0L)) + em_ptr->note = _("が分裂した!", " spawns!"); + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_star_heal(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + (void)set_monster_csleep(caster_ptr, em_ptr->g_ptr->m_idx, 0); + + if (em_ptr->m_ptr->maxhp < em_ptr->m_ptr->max_maxhp) + { + if (em_ptr->seen_msg) + msg_format(_("%^sの強さが戻った。", "%^s recovers %s vitality."), em_ptr->m_name, em_ptr->m_poss); + em_ptr->m_ptr->maxhp = em_ptr->m_ptr->max_maxhp; + } + + if (!em_ptr->dam) + { + if (caster_ptr->health_who == em_ptr->g_ptr->m_idx) + caster_ptr->redraw |= (PR_HEALTH); + if (caster_ptr->riding == em_ptr->g_ptr->m_idx) + caster_ptr->redraw |= (PR_UHEALTH); + + return PROCESS_FALSE; + } + + return PROCESS_TRUE; +} + + +// who == 0ならばプレーヤーなので、それの判定. +static void effect_monster_old_heal_check_player(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->who != 0) return; + + chg_virtue(caster_ptr, V_VITALITY, 1); + if (em_ptr->r_ptr->flags1 & RF1_UNIQUE) + chg_virtue(caster_ptr, V_INDIVIDUALISM, 1); + + if (is_friendly(em_ptr->m_ptr)) + chg_virtue(caster_ptr, V_HONOUR, 1); + else if (!(em_ptr->r_ptr->flags3 & RF3_EVIL)) + { + if (em_ptr->r_ptr->flags3 & RF3_GOOD) + chg_virtue(caster_ptr, V_COMPASSION, 2); + else + chg_virtue(caster_ptr, V_COMPASSION, 1); + } + + if (em_ptr->r_ptr->flags3 & RF3_ANIMAL) + chg_virtue(caster_ptr, V_NATURE, 1); +} + + +static void effect_monster_old_heal_recovery(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (monster_stunned_remaining(em_ptr->m_ptr)) + { + if (em_ptr->seen_msg) + msg_format(_("%^sは朦朧状態から立ち直った。", "%^s is no longer stunned."), em_ptr->m_name); + + (void)set_monster_stunned(caster_ptr, em_ptr->g_ptr->m_idx, 0); + } + + if (monster_confused_remaining(em_ptr->m_ptr)) + { + if (em_ptr->seen_msg) + msg_format(_("%^sは混乱から立ち直った。", "%^s is no longer confused."), em_ptr->m_name); + + (void)set_monster_confused(caster_ptr, em_ptr->g_ptr->m_idx, 0); + } + + if (monster_fear_remaining(em_ptr->m_ptr)) + { + if (em_ptr->seen_msg) + msg_format(_("%^sは勇気を取り戻した。", "%^s recovers %s courage."), em_ptr->m_name, em_ptr->m_poss); + + (void)set_monster_monfear(caster_ptr, em_ptr->g_ptr->m_idx, 0); + } +} + + +// todo サーペントのHPがマジックナンバー扱いになっている +process_result effect_monster_old_heal(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + /* Wake up */ + (void)set_monster_csleep(caster_ptr, em_ptr->g_ptr->m_idx, 0); + effect_monster_old_heal_recovery(caster_ptr, em_ptr); + if (em_ptr->m_ptr->hp < 30000) em_ptr->m_ptr->hp += em_ptr->dam; + if (em_ptr->m_ptr->hp > em_ptr->m_ptr->maxhp) em_ptr->m_ptr->hp = em_ptr->m_ptr->maxhp; + + effect_monster_old_heal_check_player(caster_ptr, em_ptr); + if (em_ptr->m_ptr->r_idx == MON_LEPER) + { + em_ptr->heal_leper = TRUE; + if (!em_ptr->who) chg_virtue(caster_ptr, V_COMPASSION, 5); + } + + if (caster_ptr->health_who == em_ptr->g_ptr->m_idx) caster_ptr->redraw |= (PR_HEALTH); + if (caster_ptr->riding == em_ptr->g_ptr->m_idx) caster_ptr->redraw |= (PR_UHEALTH); + + em_ptr->note = _("は体力を回復したようだ。", " looks healthier."); + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_old_speed(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (set_monster_fast(caster_ptr, em_ptr->g_ptr->m_idx, monster_fast_remaining(em_ptr->m_ptr) + 100)) + { + em_ptr->note = _("の動きが速くなった。", " starts moving faster."); + } + + if (!em_ptr->who) + { + if (em_ptr->r_ptr->flags1 & RF1_UNIQUE) + chg_virtue(caster_ptr, V_INDIVIDUALISM, 1); + if (is_friendly(em_ptr->m_ptr)) + chg_virtue(caster_ptr, V_HONOUR, 1); + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_old_slow(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + /* Powerful monsters can resist */ + if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (set_monster_slow(caster_ptr, em_ptr->g_ptr->m_idx, monster_slow_remaining(em_ptr->m_ptr) + 50)) + em_ptr->note = _("の動きが遅くなった。", " starts moving slower."); + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +/*! + * todo 「ユニークは (魔法では)常に眠らない」はr_infoの趣旨に反すると思われる + * 眠る確率を半分にするとかしておいた方が良さそう + */ +process_result effect_monster_old_sleep(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) || + (em_ptr->r_ptr->flags3 & RF3_NO_SLEEP) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + { + if (em_ptr->r_ptr->flags3 & RF3_NO_SLEEP) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags3 |= (RF3_NO_SLEEP); + } + + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + } + else + { + em_ptr->note = _("は眠り込んでしまった!", " falls asleep!"); + em_ptr->do_sleep = 500; + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +/*! + * todo 「ユニークは (魔法では)常に混乱しない」はr_infoの趣旨に反すると思われる + * 眠る確率を半分にするとかしておいた方が良さそう + */ +process_result effect_monster_old_conf(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + em_ptr->do_conf = damroll(3, (em_ptr->dam / 2)) + 1; + if ((em_ptr->r_ptr->flags1 & (RF1_UNIQUE)) || + (em_ptr->r_ptr->flags3 & (RF3_NO_CONF)) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + { + if (em_ptr->r_ptr->flags3 & (RF3_NO_CONF)) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags3 |= (RF3_NO_CONF); + } + + em_ptr->do_conf = 0; + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_stasis(effect_monster_type *em_ptr, bool to_evil) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + int stasis_damage = (em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10); + bool has_resistance = (em_ptr->r_ptr->flags1 & RF1_UNIQUE) != 0; + has_resistance |= em_ptr->r_ptr->level > randint1(stasis_damage) + 10; + if (to_evil) has_resistance |= (em_ptr->r_ptr->flags3 & RF3_EVIL) == 0; + + if (has_resistance) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + } + else + { + em_ptr->note = _("は動けなくなった!", " is suspended!"); + em_ptr->do_sleep = 500; + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_stun(effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + em_ptr->do_stun = damroll((em_ptr->caster_lev / 20) + 3, (em_ptr->dam)) + 1; + if ((em_ptr->r_ptr->flags1 & (RF1_UNIQUE)) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + { + em_ptr->do_stun = 0; + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} diff --git a/src/effect/effect-monster-oldies.h b/src/effect/effect-monster-oldies.h new file mode 100644 index 000000000..15f1997ca --- /dev/null +++ b/src/effect/effect-monster-oldies.h @@ -0,0 +1,16 @@ +#pragma once + +#include "system/angband.h" + +typedef enum process_result process_resut; +typedef struct effect_monster_type effect_monster_type; +process_result effect_monster_old_poly(effect_monster_type *em_ptr); +process_result effect_monster_old_clone(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_star_heal(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_old_heal(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_old_speed(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_old_slow(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_old_sleep(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_old_conf(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_stasis(effect_monster_type *em_ptr, bool to_evil); +process_result effect_monster_stun(effect_monster_type *em_ptr); diff --git a/src/effect/effect-monster-psi.c b/src/effect/effect-monster-psi.c new file mode 100644 index 000000000..1adac81a8 --- /dev/null +++ b/src/effect/effect-monster-psi.c @@ -0,0 +1,264 @@ +#include "effect/effect-monster-psi.h" +#include "core/player-redraw-types.h" +#include "core/window-redrawer.h" +#include "effect/effect-monster-util.h" +#include "floor/line-of-sight.h" +#include "mind/mind-mirror-master.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags2.h" +#include "monster-race/race-flags3.h" +#include "monster/monster-describer.h" +#include "monster/monster-description-types.h" +#include "monster/monster-info.h" +#include "status/bad-status-setter.h" +#include "player/player-damage.h" +#include "view/display-messages.h" +#include "world/world.h" + +static bool effect_monster_psi_empty_mind(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags2 & RF2_EMPTY_MIND) == 0) return FALSE; + + em_ptr->dam = 0; + em_ptr->note = _("には完全な耐性がある!", " is immune."); + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags2 |= (RF2_EMPTY_MIND); + + return TRUE; +} + + +static bool effect_monster_psi_weird_mind(effect_monster_type *em_ptr) +{ + bool has_resistance = ((em_ptr->r_ptr->flags2 & (RF2_STUPID | RF2_WEIRD_MIND)) != 0) || + ((em_ptr->r_ptr->flags3 & RF3_ANIMAL) != 0) || + (em_ptr->r_ptr->level > randint1(3 * em_ptr->dam)); + if (!has_resistance) return FALSE; + + em_ptr->note = _("には耐性がある!", " resists!"); + em_ptr->dam /= 3; + return TRUE; +} + + +static bool effect_monster_psi_corrupted(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + bool is_powerful = ((em_ptr->r_ptr->flags3 & (RF3_UNDEAD | RF3_DEMON)) != 0) && + (em_ptr->r_ptr->level > caster_ptr->lev / 2) && + one_in_(2); + if (!is_powerful) return FALSE; + + em_ptr->note = NULL; + msg_format(_("%^sの堕落した精神は攻撃を跳ね返した!", + (em_ptr->seen ? "%^s's corrupted mind backlashes your attack!" : + "%^ss corrupted mind backlashes your attack!")), em_ptr->m_name); + return TRUE; +} + + +static void effect_monster_psi_resist_addition(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + switch (randint1(4)) + { + case 1: + set_confused(caster_ptr, caster_ptr->confused + 3 + randint1(em_ptr->dam)); + break; + case 2: + set_stun(caster_ptr, caster_ptr->stun + randint1(em_ptr->dam)); + break; + case 3: + { + if (em_ptr->r_ptr->flags3 & RF3_NO_FEAR) + em_ptr->note = _("には効果がなかった。", " is unaffected."); + else + set_afraid(caster_ptr, caster_ptr->afraid + 3 + randint1(em_ptr->dam)); + + break; + } + default: + if (!caster_ptr->free_act) + (void)set_paralyzed(caster_ptr, caster_ptr->paralyzed + randint1(em_ptr->dam)); + + break; + } +} + + +// Powerful demons & undead can turn a mindcrafter's attacks back on them. +static void effect_monster_psi_resist(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (effect_monster_psi_empty_mind(caster_ptr, em_ptr)) return; + if (effect_monster_psi_weird_mind(em_ptr)) return; + if (!effect_monster_psi_corrupted(caster_ptr, em_ptr)) return; + + if ((randint0(100 + em_ptr->r_ptr->level / 2) < caster_ptr->skill_sav) && !check_multishadow(caster_ptr)) + { + msg_print(_("しかし効力を跳ね返した!", "You resist the effects!")); + em_ptr->dam = 0; + return; + } + + /* Injure +/- confusion */ + monster_desc(caster_ptr, em_ptr->killer, em_ptr->m_ptr, MD_WRONGDOER_NAME); + take_hit(caster_ptr, DAMAGE_ATTACK, em_ptr->dam, em_ptr->killer, -1); + if (!one_in_(4) || check_multishadow(caster_ptr)) + { + em_ptr->dam = 0; + return; + } + + effect_monster_psi_resist_addition(caster_ptr, em_ptr); + em_ptr->dam = 0; +} + + +static void effect_monster_psi_addition(effect_monster_type *em_ptr) +{ + if ((em_ptr->dam <= 0) || !one_in_(4)) return; + + switch (randint1(4)) + { + case 1: + em_ptr->do_conf = 3 + randint1(em_ptr->dam); + break; + case 2: + em_ptr->do_stun = 3 + randint1(em_ptr->dam); + break; + case 3: + em_ptr->do_fear = 3 + randint1(em_ptr->dam); + break; + default: + em_ptr->note = _("は眠り込んでしまった!", " falls asleep!"); + em_ptr->do_sleep = 3 + randint1(em_ptr->dam); + break; + } +} + + +process_result effect_monster_psi(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (!(los(caster_ptr, em_ptr->m_ptr->fy, em_ptr->m_ptr->fx, caster_ptr->y, caster_ptr->x))) + { + if (em_ptr->seen_msg) + msg_format(_("%sはあなたが見えないので影響されない!", "%^s can't see you, and isn't affected!"), em_ptr->m_name); + + em_ptr->skipped = TRUE; + return PROCESS_CONTINUE; + } + + effect_monster_psi_resist(caster_ptr, em_ptr); + effect_monster_psi_addition(em_ptr); + em_ptr->note_dies = _("の精神は崩壊し、肉体は抜け殻となった。", " collapses, a mindless husk."); + return PROCESS_CONTINUE; +} + + +static bool effect_monster_psi_drain_corrupted(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + bool is_corrupted = ((em_ptr->r_ptr->flags3 & (RF3_UNDEAD | RF3_DEMON)) != 0) && + (em_ptr->r_ptr->level > caster_ptr->lev / 2) && + (one_in_(2)); + if (!is_corrupted) return FALSE; + + em_ptr->note = NULL; + msg_format(_("%^sの堕落した精神は攻撃を跳ね返した!", + (em_ptr->seen ? "%^s's corrupted mind backlashes your attack!" : + "%^ss corrupted mind backlashes your attack!")), em_ptr->m_name); + return TRUE; +} + + +// Powerful demons & undead can turn a mindcrafter's attacks back on them. +static void effect_monster_psi_drain_resist(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + em_ptr->note = _("には耐性がある!", " resists!"); + em_ptr->dam /= 3; + if (effect_monster_psi_drain_corrupted(caster_ptr, em_ptr)) return; + + if ((randint0(100 + em_ptr->r_ptr->level / 2) < caster_ptr->skill_sav) && !check_multishadow(caster_ptr)) + { + msg_print(_("あなたは効力を跳ね返した!", "You resist the effects!")); + em_ptr->dam = 0; + return; + } + + monster_desc(caster_ptr, em_ptr->killer, em_ptr->m_ptr, MD_WRONGDOER_NAME); + if (check_multishadow(caster_ptr)) + { + take_hit(caster_ptr, DAMAGE_ATTACK, em_ptr->dam, em_ptr->killer, -1); + em_ptr->dam = 0; + return; + } + + msg_print(_("超能力パワーを吸いとられた!", "Your psychic energy is drained!")); + caster_ptr->csp -= damroll(5, em_ptr->dam) / 2; + if (caster_ptr->csp < 0) caster_ptr->csp = 0; + + caster_ptr->redraw |= PR_MANA; + caster_ptr->window |= (PW_SPELL); + take_hit(caster_ptr, DAMAGE_ATTACK, em_ptr->dam, em_ptr->killer, -1); + em_ptr->dam = 0; +} + + +static void effect_monster_psi_drain_change_power(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + int b = damroll(5, em_ptr->dam) / 4; + concptr str = (caster_ptr->pclass == CLASS_MINDCRAFTER) ? _("超能力パワー", "psychic energy") : _("魔力", "mana"); + concptr msg = _("あなたは%sの苦痛を%sに変換した!", + (em_ptr->seen ? "You convert %s's pain into %s!" : "You convert %ss pain into %s!")); + msg_format(msg, em_ptr->m_name, str); + + b = MIN(caster_ptr->msp, caster_ptr->csp + b); + caster_ptr->csp = b; + caster_ptr->redraw |= PR_MANA; + caster_ptr->window |= (PW_SPELL); +} + + +process_result effect_monster_psi_drain(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (em_ptr->r_ptr->flags2 & RF2_EMPTY_MIND) + { + em_ptr->dam = 0; + em_ptr->note = _("には完全な耐性がある!", " is immune."); + } + else if ((em_ptr->r_ptr->flags2 & (RF2_STUPID | RF2_WEIRD_MIND)) || + (em_ptr->r_ptr->flags3 & RF3_ANIMAL) || + (em_ptr->r_ptr->level > randint1(3 * em_ptr->dam))) + { + effect_monster_psi_drain_resist(caster_ptr, em_ptr); + } + else if (em_ptr->dam > 0) + { + effect_monster_psi_drain_change_power(caster_ptr, em_ptr); + } + + em_ptr->note_dies = _("の精神は崩壊し、肉体は抜け殻となった。", " collapses, a mindless husk."); + return PROCESS_CONTINUE; +} + + +process_result effect_monster_telekinesis(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (one_in_(4)) + { + if (caster_ptr->riding && (em_ptr->g_ptr->m_idx == caster_ptr->riding)) em_ptr->do_dist = 0; + else em_ptr->do_dist = 7; + } + + em_ptr->do_stun = damroll((em_ptr->caster_lev / 20) + 3, em_ptr->dam) + 1; + if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) || + (em_ptr->r_ptr->level > 5 + randint1(em_ptr->dam))) + { + em_ptr->do_stun = 0; + em_ptr->obvious = FALSE; + } + + return PROCESS_CONTINUE; +} diff --git a/src/effect/effect-monster-psi.h b/src/effect/effect-monster-psi.h new file mode 100644 index 000000000..755256411 --- /dev/null +++ b/src/effect/effect-monster-psi.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" + +typedef enum process_result process_resut; +typedef struct effect_monster_type effect_monster_type; +process_result effect_monster_psi(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_psi_drain(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_telekinesis(player_type *caster_ptr, effect_monster_type *em_ptr); diff --git a/src/effect/effect-monster-resist-hurt.c b/src/effect/effect-monster-resist-hurt.c new file mode 100644 index 000000000..fc8c245fb --- /dev/null +++ b/src/effect/effect-monster-resist-hurt.c @@ -0,0 +1,531 @@ +#include "effect/effect-monster-resist-hurt.h" +#include "effect/effect-monster-util.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags-resistance.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags3.h" +#include "monster-race/race-indice-types.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "monster/monster-info.h" + +process_result effect_monster_void(effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + return PROCESS_CONTINUE; +} + +process_result effect_monster_acid(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_IM_ACID) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("にはかなり耐性がある!", " resists a lot."); + em_ptr->dam /= 9; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_IM_ACID); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_elec(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_IM_ELEC) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("にはかなり耐性がある!", " resists a lot."); + em_ptr->dam /= 9; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_IM_ELEC); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_fire(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (em_ptr->r_ptr->flagsr & RFR_IM_FIRE) + { + em_ptr->note = _("にはかなり耐性がある!", " resists a lot."); + em_ptr->dam /= 9; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_IM_FIRE); + + return PROCESS_CONTINUE; + } + + if ((em_ptr->r_ptr->flags3 & (RF3_HURT_FIRE)) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("はひどい痛手をうけた。", " is hit hard."); + em_ptr->dam *= 2; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_HURT_FIRE); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_cold(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (em_ptr->r_ptr->flagsr & RFR_IM_COLD) + { + em_ptr->note = _("にはかなり耐性がある!", " resists a lot."); + em_ptr->dam /= 9; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_IM_COLD); + + return PROCESS_CONTINUE; + } + + if ((em_ptr->r_ptr->flags3 & (RF3_HURT_COLD)) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("はひどい痛手をうけた。", " is hit hard."); + em_ptr->dam *= 2; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_HURT_COLD); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_pois(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_IM_POIS) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("にはかなり耐性がある!", " resists a lot."); + em_ptr->dam /= 9; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_IM_POIS); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_nuke(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (em_ptr->r_ptr->flagsr & RFR_IM_POIS) + { + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_IM_POIS); + + return PROCESS_CONTINUE; + } + + if (one_in_(3)) em_ptr->do_polymorph = TRUE; + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_hell_fire(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flags3 & RF3_GOOD) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("はひどい痛手をうけた。", " is hit hard."); + em_ptr->dam *= 2; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= RF3_GOOD; + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_holy_fire(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flags3 & RF3_EVIL) == 0) + { + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + return PROCESS_CONTINUE; + } + + em_ptr->dam *= 2; + em_ptr->note = _("はひどい痛手をうけた。", " is hit hard."); + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= RF3_EVIL; + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_plasma(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_RES_PLAS) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_PLAS); + + return PROCESS_CONTINUE; +} + + +static bool effect_monster_nether_resist(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flagsr & RFR_RES_NETH) == 0) return FALSE; + + if (em_ptr->r_ptr->flags3 & RF3_UNDEAD) + { + em_ptr->note = _("には完全な耐性がある!", " is immune."); + em_ptr->dam = 0; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_UNDEAD); + } + else + { + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + } + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_NETH); + + return TRUE; +} + + +process_result effect_monster_nether(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (effect_monster_nether_resist(caster_ptr, em_ptr)) return PROCESS_CONTINUE; + if ((em_ptr->r_ptr->flags3 & RF3_EVIL) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("はいくらか耐性を示した。", " resists somewhat."); + em_ptr->dam /= 2; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_EVIL); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_water(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_RES_WATE) == 0) return PROCESS_CONTINUE; + + if ((em_ptr->m_ptr->r_idx == MON_WATER_ELEM) || (em_ptr->m_ptr->r_idx == MON_UNMAKER)) + { + em_ptr->note = _("には完全な耐性がある!", " is immune."); + em_ptr->dam = 0; + } + else + { + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + } + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_WATE); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_chaos(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (em_ptr->r_ptr->flagsr & RFR_RES_CHAO) + { + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_CHAO); + } + else if ((em_ptr->r_ptr->flags3 & RF3_DEMON) && one_in_(3)) + { + em_ptr->note = _("はいくらか耐性を示した。", " resists somewhat."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_DEMON); + } + else + { + em_ptr->do_polymorph = TRUE; + em_ptr->do_conf = (5 + randint1(11) + em_ptr->r) / (em_ptr->r + 1); + } + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_shards(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_RES_SHAR) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_SHAR); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_rocket(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_RES_SHAR) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("はいくらか耐性を示した。", " resists somewhat."); + em_ptr->dam /= 2; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_SHAR); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_sound(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_RES_SOUN) == 0) + { + em_ptr->do_stun = (10 + randint1(15) + em_ptr->r) / (em_ptr->r + 1); + return PROCESS_CONTINUE; + } + + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 2; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_SOUN); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_confusion(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flags3 & RF3_NO_CONF) == 0) + { + em_ptr->do_conf = (10 + randint1(15) + em_ptr->r) / (em_ptr->r + 1); + return PROCESS_CONTINUE; + } + + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_NO_CONF); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_disenchant(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_RES_DISE) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_DISE); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_nexus(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_RES_NEXU) == 0) return PROCESS_CONTINUE; + + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_NEXU); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_force(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_RES_WALL) == 0) + { + em_ptr->do_stun = (randint1(15) + em_ptr->r) / (em_ptr->r + 1); + return PROCESS_CONTINUE; + } + + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_WALL); + + return PROCESS_CONTINUE; +} + + +// Powerful monsters can resists and normal monsters slow down. +process_result effect_monster_inertial(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (em_ptr->r_ptr->flagsr & RFR_RES_INER) + { + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_INER); + + return PROCESS_CONTINUE; + } + + if ((em_ptr->r_ptr->flags1 & (RF1_UNIQUE)) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + { + em_ptr->obvious = FALSE; + return PROCESS_CONTINUE; + } + + if (set_monster_slow(caster_ptr, em_ptr->g_ptr->m_idx, monster_slow_remaining(em_ptr->m_ptr) + 50)) + em_ptr->note = _("の動きが遅くなった。", " starts moving slower."); + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_time(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_RES_TIME) == 0) + { + em_ptr->do_time = (em_ptr->dam + 1) / 2; + return PROCESS_CONTINUE; + } + + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_TIME); + + return PROCESS_CONTINUE; +} + + +static bool effect_monster_gravity_resist_teleport(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flagsr & RFR_RES_TELE) == 0) return FALSE; + + if (em_ptr->r_ptr->flags1 & (RF1_UNIQUE)) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= RFR_RES_TELE; + + em_ptr->note = _("には効果がなかった。", " is unaffected!"); + return TRUE; + } + + if (em_ptr->r_ptr->level <= randint1(100)) return FALSE; + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= RFR_RES_TELE; + + em_ptr->note = _("には耐性がある!", " resists!"); + return TRUE; +} + + +static void effect_monster_gravity_slow(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags1 & (RF1_UNIQUE)) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + em_ptr->obvious = FALSE; + + if (set_monster_slow(caster_ptr, em_ptr->g_ptr->m_idx, monster_slow_remaining(em_ptr->m_ptr) + 50)) + em_ptr->note = _("の動きが遅くなった。", " starts moving slower."); +} + + +static void effect_monster_gravity_stun(effect_monster_type *em_ptr) +{ + em_ptr->do_stun = damroll((em_ptr->caster_lev / 20) + 3, (em_ptr->dam)) + 1; + if ((em_ptr->r_ptr->flags1 & (RF1_UNIQUE)) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + { + em_ptr->do_stun = 0; + em_ptr->note = _("には効果がなかった。", " is unaffected!"); + em_ptr->obvious = FALSE; + } +} + + +/* + * Powerful monsters can resist and normal monsters slow down + * Furthermore, this magic can make non-unique monsters slow/stun. + */ +process_result effect_monster_gravity(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + em_ptr->do_dist = effect_monster_gravity_resist_teleport(caster_ptr, em_ptr) ? 0 : 10; + if (caster_ptr->riding && (em_ptr->g_ptr->m_idx == caster_ptr->riding)) em_ptr->do_dist = 0; + + if (em_ptr->r_ptr->flagsr & RFR_RES_GRAV) + { + em_ptr->note = _("には耐性がある!", " resists!"); + em_ptr->dam *= 3; em_ptr->dam /= randint1(6) + 6; + em_ptr->do_dist = 0; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_GRAV); + + return PROCESS_CONTINUE; + } + + effect_monster_gravity_slow(caster_ptr, em_ptr); + effect_monster_gravity_stun(em_ptr); + return PROCESS_CONTINUE; +} + + +process_result effect_monster_disintegration(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if ((em_ptr->r_ptr->flags3 & RF3_HURT_ROCK) == 0) return PROCESS_CONTINUE; + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_HURT_ROCK); + + em_ptr->note = _("の皮膚がただれた!", " loses some skin!"); + em_ptr->note_dies = _("は蒸発した!", " evaporates!"); + em_ptr->dam *= 2; + return PROCESS_CONTINUE; +} + +process_result effect_monster_icee_bolt(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + em_ptr->do_stun = (randint1(15) + 1) / (em_ptr->r + 1); + if (em_ptr->r_ptr->flagsr & RFR_IM_COLD) + { + em_ptr->note = _("にはかなり耐性がある!", " resists a lot."); + em_ptr->dam /= 9; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_IM_COLD); + } + else if (em_ptr->r_ptr->flags3 & (RF3_HURT_COLD)) + { + em_ptr->note = _("はひどい痛手をうけた。", " is hit hard."); + em_ptr->dam *= 2; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_HURT_COLD); + } + + return PROCESS_CONTINUE; +} diff --git a/src/effect/effect-monster-resist-hurt.h b/src/effect/effect-monster-resist-hurt.h new file mode 100644 index 000000000..a36309f1d --- /dev/null +++ b/src/effect/effect-monster-resist-hurt.h @@ -0,0 +1,31 @@ +#pragma once + +#include "system/angband.h" + +typedef enum process_result process_resut; +typedef struct effect_monster_type effect_monster_type; +process_result effect_monster_void(effect_monster_type *em_ptr); +process_result effect_monster_acid(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_elec(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_fire(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_cold(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_pois(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_nuke(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_hell_fire(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_holy_fire(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_plasma(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_nether(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_water(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_chaos(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_shards(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_rocket(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_sound(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_confusion(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_disenchant(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_nexus(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_force(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_inertial(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_time(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_gravity(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_disintegration(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_icee_bolt(player_type *caster_ptr, effect_monster_type *em_ptr); diff --git a/src/effect/effect-monster-spirit.c b/src/effect/effect-monster-spirit.c new file mode 100644 index 000000000..beac8e1b3 --- /dev/null +++ b/src/effect/effect-monster-spirit.c @@ -0,0 +1,164 @@ +#include "effect/effect-monster-spirit.h" +#include "core/hp-mp-processor.h" +#include "core/player-redraw-types.h" +#include "effect/effect-monster-util.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags2.h" +#include "monster-race/race-flags3.h" +#include "monster-race/race-flags4.h" +#include "monster-race/race-flags-ability1.h" +#include "monster-race/race-flags-ability2.h" +#include "monster/monster-describer.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "monster/monster-info.h" +#include "mspell/mspell-mask-definitions.h" +#include "view/display-messages.h" + +process_result effect_monster_drain_mana(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + bool has_mana = ((em_ptr->r_ptr->flags4 & ~(RF4_NOMAGIC_MASK))) != 0; + has_mana |= ((em_ptr->r_ptr->a_ability_flags1 & ~(RF5_NOMAGIC_MASK))) != 0; + has_mana |= ((em_ptr->r_ptr->a_ability_flags2 & ~(RF6_NOMAGIC_MASK))) != 0; + if (!has_mana) + { + if (em_ptr->see_s_msg) + msg_format(_("%sには効果がなかった。", "%s is unaffected."), em_ptr->m_name); + + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (em_ptr->who <= 0) + { + msg_format(_("%sから精神エネルギーを吸いとった。", "You draw psychic energy from %s."), em_ptr->m_name); + (void)hp_player(caster_ptr, em_ptr->dam); + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (em_ptr->m_caster_ptr->hp >= em_ptr->m_caster_ptr->maxhp) + { + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + em_ptr->m_caster_ptr->hp += em_ptr->dam; + if (em_ptr->m_caster_ptr->hp > em_ptr->m_caster_ptr->maxhp) + em_ptr->m_caster_ptr->hp = em_ptr->m_caster_ptr->maxhp; + + if (caster_ptr->health_who == em_ptr->who) + caster_ptr->redraw |= (PR_HEALTH); + + if (caster_ptr->riding == em_ptr->who) + caster_ptr->redraw |= (PR_UHEALTH); + + if (em_ptr->see_s_msg) + { + monster_desc(caster_ptr, em_ptr->killer, em_ptr->m_caster_ptr, 0); + msg_format(_("%^sは気分が良さそうだ。", "%^s appears healthier."), em_ptr->killer); + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_mind_blast(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (!em_ptr->who) msg_format(_("%sをじっと睨んだ。", "You gaze intently at %s."), em_ptr->m_name); + + if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) || + (em_ptr->r_ptr->flags3 & RF3_NO_CONF) || + (em_ptr->r_ptr->level > randint1((em_ptr->caster_lev - 10) < 1 ? 1 : (em_ptr->caster_lev - 10)) + 10)) + { + if (em_ptr->r_ptr->flags3 & (RF3_NO_CONF)) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags3 |= (RF3_NO_CONF); + } + + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->dam = 0; + } + else if (em_ptr->r_ptr->flags2 & RF2_EMPTY_MIND) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags2 |= (RF2_EMPTY_MIND); + em_ptr->note = _("には完全な耐性がある!", " is immune."); + em_ptr->dam = 0; + } + else if (em_ptr->r_ptr->flags2 & RF2_WEIRD_MIND) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags2 |= (RF2_WEIRD_MIND); + em_ptr->note = _("には耐性がある。", " resists."); + em_ptr->dam /= 3; + } + else + { + em_ptr->note = _("は精神攻撃を食らった。", " is blasted by psionic energy."); + em_ptr->note_dies = _("の精神は崩壊し、肉体は抜け殻となった。", " collapses, a mindless husk."); + + if (em_ptr->who > 0) em_ptr->do_conf = randint0(4) + 4; + else em_ptr->do_conf = randint0(8) + 8; + } + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_brain_smash(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (!em_ptr->who) msg_format(_("%sをじっと睨んだ。", "You gaze intently at %s."), em_ptr->m_name); + + if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) || + (em_ptr->r_ptr->flags3 & RF3_NO_CONF) || + (em_ptr->r_ptr->level > randint1((em_ptr->caster_lev - 10) < 1 ? 1 : (em_ptr->caster_lev - 10)) + 10)) + { + if (em_ptr->r_ptr->flags3 & (RF3_NO_CONF)) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags3 |= (RF3_NO_CONF); + } + + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->dam = 0; + } + else if (em_ptr->r_ptr->flags2 & RF2_EMPTY_MIND) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags2 |= (RF2_EMPTY_MIND); + + em_ptr->note = _("には完全な耐性がある!", " is immune."); + em_ptr->dam = 0; + } + else if (em_ptr->r_ptr->flags2 & RF2_WEIRD_MIND) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flags2 |= (RF2_WEIRD_MIND); + + em_ptr->note = _("には耐性がある!", " resists!"); + em_ptr->dam /= 3; + } + else + { + em_ptr->note = _("は精神攻撃を食らった。", " is blasted by psionic energy."); + em_ptr->note_dies = _("の精神は崩壊し、肉体は抜け殻となった。", " collapses, a mindless husk."); + if (em_ptr->who > 0) + { + em_ptr->do_conf = randint0(4) + 4; + em_ptr->do_stun = randint0(4) + 4; + } + else + { + em_ptr->do_conf = randint0(8) + 8; + em_ptr->do_stun = randint0(8) + 8; + } + + (void)set_monster_slow(caster_ptr, em_ptr->g_ptr->m_idx, monster_slow_remaining(em_ptr->m_ptr) + 10); + } + + return PROCESS_CONTINUE; +} diff --git a/src/effect/effect-monster-spirit.h b/src/effect/effect-monster-spirit.h new file mode 100644 index 000000000..3c724c062 --- /dev/null +++ b/src/effect/effect-monster-spirit.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" + +typedef enum process_result process_resut; +typedef struct effect_monster_type effect_monster_type; +process_result effect_monster_drain_mana(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_mind_blast(player_type *caster_ptr, effect_monster_type *em_ptr); +process_result effect_monster_brain_smash(player_type *caster_ptr, effect_monster_type *em_ptr); diff --git a/src/effect/effect-monster-switcher.c b/src/effect/effect-monster-switcher.c new file mode 100644 index 000000000..0b581a70d --- /dev/null +++ b/src/effect/effect-monster-switcher.c @@ -0,0 +1,460 @@ +/*! + * todo どうしても「その他」に分類せざるを得ない魔法種別が残った + * 本ファイル内の行数はまともなレベルに落ち着いているので、一旦ここに留め置くこととする + * @brief 魔法種別による各種処理切り替え + * @date 2020/04/29 + * @author Hourier + */ + +#include "effect/effect-monster-switcher.h" +#include "cmd-action/cmd-attack.h" +#include "effect/effect-monster-charm.h" +#include "effect/effect-monster-curse.h" +#include "effect/effect-monster-evil.h" +#include "effect/effect-monster-lite-dark.h" +#include "effect/effect-monster-oldies.h" +#include "effect/effect-monster-psi.h" +#include "effect/effect-monster-resist-hurt.h" +#include "effect/effect-monster-spirit.h" +#include "effect/effect-monster-util.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags2.h" +#include "monster-race/race-flags3.h" +#include "monster-race/monster-race-hook.h" +#include "monster-floor/monster-death.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "monster/monster-info.h" +#include "player-info/avatar.h" +#include "player/player-damage.h" +#include "spell-kind/spells-genocide.h" +#include "spell/spell-types.h" +#include "view/display-messages.h" + +process_result effect_monster_hypodynamia(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (monster_living(em_ptr->m_ptr->r_idx)) + { + em_ptr->do_time = (em_ptr->dam + 7) / 8; + return PROCESS_CONTINUE; + } + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + { + if (em_ptr->r_ptr->flags3 & RF3_DEMON) em_ptr->r_ptr->r_flags3 |= (RF3_DEMON); + if (em_ptr->r_ptr->flags3 & RF3_UNDEAD) em_ptr->r_ptr->r_flags3 |= (RF3_UNDEAD); + if (em_ptr->r_ptr->flags3 & RF3_NONLIVING) em_ptr->r_ptr->r_flags3 |= (RF3_NONLIVING); + } + + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +// todo リファクタリング前のコード時点で、単に耐性があるだけでもダメージ0だった. +process_result effect_monster_death_ray(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (!monster_living(em_ptr->m_ptr->r_idx)) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + { + if (em_ptr->r_ptr->flags3 & RF3_DEMON) em_ptr->r_ptr->r_flags3 |= (RF3_DEMON); + if (em_ptr->r_ptr->flags3 & RF3_UNDEAD) em_ptr->r_ptr->r_flags3 |= (RF3_UNDEAD); + if (em_ptr->r_ptr->flags3 & RF3_NONLIVING) em_ptr->r_ptr->r_flags3 |= (RF3_NONLIVING); + } + + em_ptr->note = _("には完全な耐性がある!", " is immune."); + em_ptr->obvious = FALSE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (((em_ptr->r_ptr->flags1 & RF1_UNIQUE) && + (randint1(888) != 666)) || + (((em_ptr->r_ptr->level + randint1(20)) > randint1((em_ptr->caster_lev / 2) + randint1(10))) && + randint1(100) != 66)) + { + em_ptr->note = _("には耐性がある!", " resists!"); + em_ptr->obvious = FALSE; + em_ptr->dam = 0; + } + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_kill_wall(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags3 & (RF3_HURT_ROCK)) == 0) + { + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags3 |= (RF3_HURT_ROCK); + + em_ptr->note = _("の皮膚がただれた!", " loses some skin!"); + em_ptr->note_dies = _("はドロドロに溶けた!", " dissolves!"); + return PROCESS_CONTINUE; +} + + +process_result effect_monster_hand_doom(effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (em_ptr->r_ptr->flags1 & RF1_UNIQUE) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + + if ((em_ptr->who > 0) ? ((em_ptr->caster_lev + randint1(em_ptr->dam)) > (em_ptr->r_ptr->level + 10 + randint1(20))) : + (((em_ptr->caster_lev / 2) + randint1(em_ptr->dam)) > (em_ptr->r_ptr->level + randint1(200)))) + { + em_ptr->dam = ((40 + randint1(20)) * em_ptr->m_ptr->hp) / 100; + if (em_ptr->m_ptr->hp < em_ptr->dam) + em_ptr->dam = em_ptr->m_ptr->hp - 1; + } + else + { + em_ptr->note = _("は破滅の手に耐え切った!", "resists!"); + em_ptr->dam = 0; + } + + return PROCESS_CONTINUE; +} + + +process_result effect_monster_engetsu(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + int effect = 0; + bool done = TRUE; + + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (em_ptr->r_ptr->flags2 & RF2_EMPTY_MIND) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->dam = 0; + em_ptr->skipped = TRUE; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags2 |= (RF2_EMPTY_MIND); + return PROCESS_CONTINUE; + } + + if (monster_csleep_remaining(em_ptr->m_ptr)) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->dam = 0; + em_ptr->skipped = TRUE; + return PROCESS_CONTINUE; + } + + if (one_in_(5)) effect = 1; + else if (one_in_(4)) effect = 2; + else if (one_in_(3)) effect = 3; + else done = FALSE; + + if (effect == 1) + { + if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + } + else + { + if (set_monster_slow(caster_ptr, em_ptr->g_ptr->m_idx, monster_slow_remaining(em_ptr->m_ptr) + 50)) + { + em_ptr->note = _("の動きが遅くなった。", " starts moving slower."); + } + } + } + else if (effect == 2) + { + em_ptr->do_stun = damroll((caster_ptr->lev / 10) + 3, (em_ptr->dam)) + 1; + if ((em_ptr->r_ptr->flags1 & (RF1_UNIQUE)) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + { + em_ptr->do_stun = 0; + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + } + } + else if (effect == 3) + { + if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) || + (em_ptr->r_ptr->flags3 & RF3_NO_SLEEP) || + (em_ptr->r_ptr->level > randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10)) + 10)) + { + if (em_ptr->r_ptr->flags3 & RF3_NO_SLEEP) + { + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags3 |= (RF3_NO_SLEEP); + } + + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->obvious = FALSE; + } + else + { + /* Go to sleep (much) later */ + em_ptr->note = _("は眠り込んでしまった!", " falls asleep!"); + em_ptr->do_sleep = 500; + } + } + + if (!done) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + } + + em_ptr->dam = 0; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_genocide(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + if (genocide_aux(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam, !em_ptr->who, (em_ptr->r_ptr->level + 1) / 2, _("モンスター消滅", "Genocide One"))) + { + if (em_ptr->seen_msg) msg_format(_("%sは消滅した!", "%^s disappeared!"), em_ptr->m_name); + chg_virtue(caster_ptr, V_VITALITY, -1); + return PROCESS_TRUE; + } + + em_ptr->skipped = TRUE; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_photo(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (!em_ptr->who) + msg_format(_("%sを写真に撮った。", "You take a photograph of %s."), em_ptr->m_name); + + if (em_ptr->r_ptr->flags3 & (RF3_HURT_LITE)) + { + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) em_ptr->r_ptr->r_flags3 |= (RF3_HURT_LITE); + + em_ptr->note = _("は光に身をすくめた!", " cringes from the light!"); + em_ptr->note_dies = _("は光を受けてしぼんでしまった!", " shrivels away in the light!"); + } + else + { + em_ptr->dam = 0; + } + + em_ptr->photo = em_ptr->m_ptr->r_idx; + return PROCESS_CONTINUE; +} + + +process_result effect_monster_wounds(effect_monster_type *em_ptr) +{ + if (em_ptr->seen) em_ptr->obvious = TRUE; + + if (randint0(100 + em_ptr->dam) < (em_ptr->r_ptr->level + 50)) + { + em_ptr->note = _("には効果がなかった。", " is unaffected."); + em_ptr->dam = 0; + } + + return PROCESS_CONTINUE; +} + + +/*! + * @brief 魔法の効果によって様々なメッセーを出力したり与えるダメージの増減を行ったりする + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return ここのスイッチングで終るならTRUEかFALSE、後続処理を実行するならCONTINUE + */ +process_result switch_effects_monster(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + switch (em_ptr->effect_type) + { + case GF_PSY_SPEAR: + case GF_MISSILE: + case GF_ARROW: + case GF_MANA: + case GF_METEOR: + case GF_BLOOD_CURSE: + case GF_SEEKER: + case GF_SUPER_RAY: + return effect_monster_void(em_ptr); + case GF_ACID: + return effect_monster_acid(caster_ptr, em_ptr); + case GF_ELEC: + return effect_monster_elec(caster_ptr, em_ptr); + case GF_FIRE: + return effect_monster_fire(caster_ptr, em_ptr); + case GF_COLD: + return effect_monster_cold(caster_ptr, em_ptr); + case GF_POIS: + return effect_monster_pois(caster_ptr, em_ptr); + case GF_NUKE: + return effect_monster_nuke(caster_ptr, em_ptr); + case GF_HELL_FIRE: + return effect_monster_hell_fire(caster_ptr, em_ptr); + case GF_HOLY_FIRE: + return effect_monster_holy_fire(caster_ptr, em_ptr); + case GF_PLASMA: + return effect_monster_plasma(caster_ptr, em_ptr); + case GF_NETHER: + return effect_monster_nether(caster_ptr, em_ptr); + case GF_WATER: + return effect_monster_water(caster_ptr, em_ptr); + case GF_CHAOS: + return effect_monster_chaos(caster_ptr, em_ptr); + case GF_SHARDS: + return effect_monster_shards(caster_ptr, em_ptr); + case GF_ROCKET: + return effect_monster_rocket(caster_ptr, em_ptr); + case GF_SOUND: + return effect_monster_sound(caster_ptr, em_ptr); + case GF_CONFUSION: + return effect_monster_confusion(caster_ptr, em_ptr); + case GF_DISENCHANT: + return effect_monster_disenchant(caster_ptr, em_ptr); + case GF_NEXUS: + return effect_monster_nexus(caster_ptr, em_ptr); + case GF_FORCE: + return effect_monster_force(caster_ptr, em_ptr); + case GF_INERTIAL: + return effect_monster_inertial(caster_ptr, em_ptr); + case GF_TIME: + return effect_monster_time(caster_ptr, em_ptr); + case GF_GRAVITY: + return effect_monster_gravity(caster_ptr, em_ptr); + case GF_DISINTEGRATE: + return effect_monster_disintegration(caster_ptr, em_ptr); + case GF_PSI: + return effect_monster_psi(caster_ptr, em_ptr); + case GF_PSI_DRAIN: + return effect_monster_psi_drain(caster_ptr, em_ptr); + case GF_TELEKINESIS: + return effect_monster_telekinesis(caster_ptr, em_ptr); + case GF_DOMINATION: + return effect_monster_domination(caster_ptr, em_ptr); + case GF_ICE: + return effect_monster_icee_bolt(caster_ptr, em_ptr); + case GF_HYPODYNAMIA: + return effect_monster_hypodynamia(caster_ptr, em_ptr); + case GF_DEATH_RAY: + return effect_monster_death_ray(caster_ptr, em_ptr); + case GF_OLD_POLY: + return effect_monster_old_poly(em_ptr); + case GF_OLD_CLONE: + return effect_monster_old_clone(caster_ptr, em_ptr); + case GF_STAR_HEAL: + if (effect_monster_old_clone(caster_ptr, em_ptr) == PROCESS_TRUE) + return PROCESS_CONTINUE; + /* Fall through */ + case GF_OLD_HEAL: + return effect_monster_old_heal(caster_ptr, em_ptr); + case GF_OLD_SPEED: + return effect_monster_old_speed(caster_ptr, em_ptr); + case GF_OLD_SLOW: + return effect_monster_old_slow(caster_ptr, em_ptr); + case GF_OLD_SLEEP: + return effect_monster_old_sleep(caster_ptr, em_ptr); + case GF_STASIS_EVIL: + return effect_monster_stasis(em_ptr, TRUE); + case GF_STASIS: + return effect_monster_stasis(em_ptr, FALSE); + case GF_CHARM: + return effect_monster_charm(caster_ptr, em_ptr); + case GF_CONTROL_UNDEAD: + return effect_monster_control_undead(caster_ptr, em_ptr); + case GF_CONTROL_DEMON: + return effect_monster_control_demon(caster_ptr, em_ptr); + case GF_CONTROL_ANIMAL: + return effect_monster_control_animal(caster_ptr, em_ptr); + case GF_CHARM_LIVING: + return effect_monster_charm_living(caster_ptr, em_ptr); + case GF_OLD_CONF: + return effect_monster_old_conf(caster_ptr, em_ptr); + case GF_STUN: + return effect_monster_stun(em_ptr); + case GF_LITE_WEAK: + return effect_monster_lite_weak(caster_ptr, em_ptr); + case GF_LITE: + return effect_monster_lite(caster_ptr, em_ptr); + case GF_DARK: + return effect_monster_dark(caster_ptr, em_ptr); + case GF_KILL_WALL: + return effect_monster_kill_wall(caster_ptr, em_ptr); + case GF_AWAY_UNDEAD: + return effect_monster_away_undead(caster_ptr, em_ptr); + case GF_AWAY_EVIL: + return effect_monster_away_evil(caster_ptr, em_ptr); + case GF_AWAY_ALL: + return effect_monster_away_all(caster_ptr, em_ptr); + case GF_TURN_UNDEAD: + return effect_monster_turn_undead(caster_ptr, em_ptr); + case GF_TURN_EVIL: + return effect_monster_turn_evil(caster_ptr, em_ptr); + case GF_TURN_ALL: + return effect_monster_turn_all(em_ptr); + case GF_DISP_UNDEAD: + return effect_monster_disp_undead(caster_ptr, em_ptr); + case GF_DISP_EVIL: + return effect_monster_disp_evil(caster_ptr, em_ptr); + case GF_DISP_GOOD: + return effect_monster_disp_good(caster_ptr, em_ptr); + case GF_DISP_LIVING: + return effect_monster_disp_living(em_ptr); + case GF_DISP_DEMON: + return effect_monster_disp_demon(caster_ptr, em_ptr); + case GF_DISP_ALL: + return effect_monster_disp_all(em_ptr); + case GF_DRAIN_MANA: + return effect_monster_drain_mana(caster_ptr, em_ptr); + case GF_MIND_BLAST: + return effect_monster_mind_blast(caster_ptr, em_ptr); + case GF_BRAIN_SMASH: + return effect_monster_brain_smash(caster_ptr, em_ptr); + case GF_CAUSE_1: + return effect_monster_curse_1(em_ptr); + case GF_CAUSE_2: + return effect_monster_curse_2(em_ptr); + case GF_CAUSE_3: + return effect_monster_curse_3(em_ptr); + case GF_CAUSE_4: + return effect_monster_curse_4(em_ptr); + case GF_HAND_DOOM: + return effect_monster_hand_doom(em_ptr); + case GF_CAPTURE: + return effect_monster_capture(caster_ptr, em_ptr); + case GF_ATTACK: + return (process_result)do_cmd_attack(caster_ptr, em_ptr->y, em_ptr->x, em_ptr->dam); + case GF_ENGETSU: + return effect_monster_engetsu(caster_ptr, em_ptr); + case GF_GENOCIDE: + return effect_monster_genocide(caster_ptr, em_ptr); + case GF_PHOTO: + return effect_monster_photo(caster_ptr, em_ptr); + case GF_CRUSADE: + return effect_monster_crusade(caster_ptr, em_ptr); + case GF_WOUNDS: + return effect_monster_wounds(em_ptr); + default: + { + em_ptr->skipped = TRUE; + em_ptr->dam = 0; + return PROCESS_CONTINUE; + } + } +} diff --git a/src/effect/effect-monster-switcher.h b/src/effect/effect-monster-switcher.h new file mode 100644 index 000000000..740b36e4f --- /dev/null +++ b/src/effect/effect-monster-switcher.h @@ -0,0 +1,7 @@ +#pragma once + +#include "system/angband.h" + +typedef enum process_result process_resut; +typedef struct effect_monster_type effect_monster_type; +process_result switch_effects_monster(player_type *caster_ptr, effect_monster_type *em_ptr); diff --git a/src/effect/effect-monster-util.c b/src/effect/effect-monster-util.c new file mode 100644 index 000000000..7a605cc83 --- /dev/null +++ b/src/effect/effect-monster-util.c @@ -0,0 +1,83 @@ +/*! + * @brief effect_monster_type構造体の初期化処理 + * @date 2020/04/29 + * @author Hourier + */ + +#include "effect/effect-monster-util.h" +#include "monster-floor/monster-death.h" +#include "monster-race/monster-race.h" +#include "monster/monster-info.h" +#include "monster/monster-status.h" +#include "system/floor-type-definition.h" + +/*! + * @brief affect_monster() に亘ってきた引数をeffect_monster_type構造体に代入する + * @param em_ptr モンスター効果構造体への参照ポインタ + * @param who 魔法を発動したモンスター (0ならばプレーヤー) + * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball) + * @param y 目標y座標 / Target y location (or location to travel "towards") + * @param x 目標x座標 / Target x location (or location to travel "towards") + * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player) + * @param effect_type 効果属性 / Type of damage to apply to monsters (and objects) + * @param flag 効果フラグ + * @param see_s_msg TRUEならばメッセージを表示する + * @return なし + */ +static void substitute_effect_monster(effect_monster_type *em_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID effect_type, BIT_FLAGS flag, bool see_s_msg) +{ + em_ptr->who = who; + em_ptr->r = r; + em_ptr->y = y; + em_ptr->x = x; + em_ptr->dam = dam; + em_ptr->effect_type = effect_type; + em_ptr->flag = flag; + em_ptr->see_s_msg = see_s_msg; +} + + +/*! + * @brief effect_monster_type構造体を初期化する + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @param who 魔法を発動したモンスター (0ならばプレーヤー) + * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball) + * @param y 目標y座標 / Target y location (or location to travel "towards") + * @param x 目標x座標 / Target x location (or location to travel "towards") + * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player) + * @param effect_type 効果属性 / Type of damage to apply to monsters (and objects) + * @param flag 効果フラグ + * @param see_s_msg TRUEならばメッセージを表示する + * @return なし + */ +effect_monster_type *initialize_effect_monster(player_type *caster_ptr, effect_monster_type *em_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID effect_type, BIT_FLAGS flag, bool see_s_msg) +{ + substitute_effect_monster(em_ptr, who, r, y, x, dam, effect_type, flag, see_s_msg); + + floor_type *floor_ptr = caster_ptr->current_floor_ptr; + em_ptr->g_ptr = &floor_ptr->grid_array[em_ptr->y][em_ptr->x]; + em_ptr->m_ptr = &floor_ptr->m_list[em_ptr->g_ptr->m_idx]; + em_ptr->m_caster_ptr = (em_ptr->who > 0) ? &floor_ptr->m_list[em_ptr->who] : NULL; + em_ptr->r_ptr = &r_info[em_ptr->m_ptr->r_idx]; + em_ptr->seen = em_ptr->m_ptr->ml; + em_ptr->seen_msg = is_seen(caster_ptr, em_ptr->m_ptr); + em_ptr->slept = (bool)monster_csleep_remaining(em_ptr->m_ptr); + em_ptr->obvious = FALSE; + em_ptr->known = ((em_ptr->m_ptr->cdis <= MAX_SIGHT) || caster_ptr->phase_out); + em_ptr->skipped = FALSE; + em_ptr->get_angry = FALSE; + em_ptr->do_polymorph = FALSE; + em_ptr->do_dist = 0; + em_ptr->do_conf = 0; + em_ptr->do_stun = 0; + em_ptr->do_sleep = 0; + em_ptr->do_fear = 0; + em_ptr->do_time = 0; + em_ptr->heal_leper = FALSE; + em_ptr->photo = 0; + em_ptr->note = NULL; + em_ptr->note_dies = extract_note_dies(real_r_idx(em_ptr->m_ptr)); + em_ptr->caster_lev = (em_ptr->who > 0) ? r_info[em_ptr->m_caster_ptr->r_idx].level : (caster_ptr->lev * 2); + return em_ptr; +} diff --git a/src/effect/effect-monster-util.h b/src/effect/effect-monster-util.h new file mode 100644 index 000000000..adc8c6cf4 --- /dev/null +++ b/src/effect/effect-monster-util.h @@ -0,0 +1,45 @@ +#pragma once + +#include "system/angband.h" +#include "grid/grid.h" +#include "system/monster-type-definition.h" + +typedef struct effect_monster_type { + grid_type *g_ptr; + monster_type *m_ptr; + monster_type *m_caster_ptr; + monster_race *r_ptr; + char killer[80]; + bool seen; + bool seen_msg; + bool slept; + bool obvious; + bool known; + bool skipped; + bool get_angry; + bool do_polymorph; + int do_dist; + int do_conf; + int do_stun; + int do_sleep; + int do_fear; + int do_time; + bool heal_leper; + GAME_TEXT m_name[MAX_NLEN]; + char m_poss[10]; + PARAMETER_VALUE photo; + concptr note; + concptr note_dies; + DEPTH caster_lev; + + MONSTER_IDX who; + POSITION r; + POSITION y; + POSITION x; + HIT_POINT dam; + EFFECT_ID effect_type; + BIT_FLAGS flag; + bool see_s_msg; +} effect_monster_type; + +effect_monster_type *initialize_effect_monster(player_type *caster_ptr, effect_monster_type *em_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID effect_type, BIT_FLAGS flag, bool see_s_msg); diff --git a/src/effect/effect-monster.c b/src/effect/effect-monster.c new file mode 100644 index 000000000..370da83fb --- /dev/null +++ b/src/effect/effect-monster.c @@ -0,0 +1,600 @@ +/*! + * @brief 魔法によるモンスターへの効果まとめ + * @date 2020/04/29 + * @author Hourier + */ + +#include "effect/effect-monster.h" +#include "core/disturbance.h" +#include "core/player-redraw-types.h" +#include "core/stuff-handler.h" +#include "core/window-redrawer.h" +#include "effect/effect-characteristics.h" +#include "effect/effect-monster-switcher.h" +#include "floor/cave.h" +#include "floor/floor-object.h" +#include "game-option/play-record-options.h" +#include "io/write-diary.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-floor/monster-death.h" +#include "monster-floor/monster-move.h" +#include "monster-floor/monster-remover.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags-resistance.h" +#include "monster-race/race-flags1.h" +#include "monster-race/race-flags3.h" +#include "monster-race/race-flags7.h" +#include "monster-race/race-indice-types.h" +#include "monster/monster-describer.h" +#include "monster/monster-description-types.h" +#include "monster/monster-info.h" +#include "monster/monster-status-setter.h" +#include "monster/monster-status.h" +#include "monster/monster-update.h" +#include "object-enchant/special-object-flags.h" +#include "object/object-generator.h" +#include "object/object-kind-hook.h" +#include "player-info/avatar.h" +#include "spell-kind/blood-curse.h" +#include "spell-kind/spells-polymorph.h" +#include "spell-kind/spells-teleport.h" +#include "spell/spell-types.h" +#include "spells-effect-util.h" +#include "sv-definition/sv-other-types.h" +#include "system/floor-type-definition.h" +#include "system/object-type-definition.h" +#include "view/display-messages.h" + +/*! + * @brief ビーム/ボルト/ボール系魔法によるモンスターへの効果があるかないかを判定する + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return 効果が何もないならFALSE、何かあるならTRUE + */ +static bool is_never_effect(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (!em_ptr->g_ptr->m_idx) + return FALSE; + if (em_ptr->who && (em_ptr->g_ptr->m_idx == em_ptr->who)) + return FALSE; + if ((em_ptr->g_ptr->m_idx == caster_ptr->riding) && !em_ptr->who && !(em_ptr->effect_type == GF_OLD_HEAL) && !(em_ptr->effect_type == GF_OLD_SPEED) + && !(em_ptr->effect_type == GF_STAR_HEAL)) + return FALSE; + if (sukekaku && ((em_ptr->m_ptr->r_idx == MON_SUKE) || (em_ptr->m_ptr->r_idx == MON_KAKU))) + return FALSE; + if (em_ptr->m_ptr->hp < 0) + return FALSE; + + return TRUE; +} + +/*! + * @brief 魔法の効果やモンスター種別(MAKE/FEMALE/なし)に応じて表示するメッセージを変更する + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void decide_spell_result_description(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + em_ptr->dam = (em_ptr->dam + em_ptr->r) / (em_ptr->r + 1); + monster_desc(caster_ptr, em_ptr->m_name, em_ptr->m_ptr, 0); + monster_desc(caster_ptr, em_ptr->m_poss, em_ptr->m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE); + if (caster_ptr->riding && (em_ptr->g_ptr->m_idx == caster_ptr->riding)) + disturb(caster_ptr, TRUE, TRUE); +} + +/*! + * @brief 完全な耐性を持っていたら、モンスターへの効果処理をスキップする + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return 完全耐性ならCONTINUE、そうでないなら効果処理の結果 + */ +static process_result process_monster_perfect_resistance(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (((em_ptr->r_ptr->flagsr & RFR_RES_ALL) == 0) || em_ptr->effect_type == GF_OLD_CLONE || em_ptr->effect_type == GF_STAR_HEAL + || em_ptr->effect_type == GF_OLD_HEAL || em_ptr->effect_type == GF_OLD_SPEED || em_ptr->effect_type == GF_CAPTURE || em_ptr->effect_type == GF_PHOTO) + return switch_effects_monster(caster_ptr, em_ptr); + + em_ptr->note = _("には完全な耐性がある!", " is immune."); + em_ptr->dam = 0; + if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr)) + em_ptr->r_ptr->r_flagsr |= (RFR_RES_ALL); + + if (em_ptr->effect_type == GF_LITE_WEAK || em_ptr->effect_type == GF_KILL_WALL) + em_ptr->skipped = TRUE; + + return PROCESS_CONTINUE; +} + +/*! + * @brief ペットの死亡を処理する + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void process_pet_death(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + bool sad = is_pet(em_ptr->m_ptr) && !(em_ptr->m_ptr->ml); + if (em_ptr->known && em_ptr->note) { + monster_desc(caster_ptr, em_ptr->m_name, em_ptr->m_ptr, MD_TRUE_NAME); + if (em_ptr->see_s_msg) + msg_format("%^s%s", em_ptr->m_name, em_ptr->note); + else + caster_ptr->current_floor_ptr->monster_noise = TRUE; + } + + if (em_ptr->who > 0) + monster_gain_exp(caster_ptr, em_ptr->who, em_ptr->m_ptr->r_idx); + + monster_death(caster_ptr, em_ptr->g_ptr->m_idx, FALSE); + delete_monster_idx(caster_ptr, em_ptr->g_ptr->m_idx); + if (sad) + msg_print(_("少し悲しい気分がした。", "You feel sad for a moment.")); +} + +/*! + * @brief モンスターの睡眠を処理する + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void process_monster_sleep(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->note && em_ptr->seen_msg) + msg_format("%^s%s", em_ptr->m_name, em_ptr->note); + else if (em_ptr->see_s_msg) + message_pain(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam); + else + caster_ptr->current_floor_ptr->monster_noise = TRUE; + + if (em_ptr->do_sleep) + (void)set_monster_csleep(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_sleep); +} + +/*! + * @brief モンスターの被ダメージを処理する / If another monster did the damage, hurt the monster by hand + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return モンスターIDがプレーヤー自身だった場合FALSE、モンスターだった場合TRUE + */ +static bool process_monster_damage(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->who <= 0) + return FALSE; + + if (caster_ptr->health_who == em_ptr->g_ptr->m_idx) + caster_ptr->redraw |= (PR_HEALTH); + if (caster_ptr->riding == em_ptr->g_ptr->m_idx) + caster_ptr->redraw |= (PR_UHEALTH); + + (void)set_monster_csleep(caster_ptr, em_ptr->g_ptr->m_idx, 0); + em_ptr->m_ptr->hp -= em_ptr->dam; + if (em_ptr->m_ptr->hp < 0) + process_pet_death(caster_ptr, em_ptr); + else + process_monster_sleep(caster_ptr, em_ptr); + + return TRUE; +} + +/*! + * @brief 不潔な病人の治療処理 + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return 大賞モンスターが不潔な病人だった場合はTRUE、それ以外はFALSE + */ +static bool heal_leaper(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (!em_ptr->heal_leper) + return FALSE; + + if (em_ptr->seen_msg) + msg_print(_("不潔な病人は病気が治った!", "The Mangy looking leper is healed!")); + + if (record_named_pet && is_pet(em_ptr->m_ptr) && em_ptr->m_ptr->nickname) { + char m2_name[MAX_NLEN]; + monster_desc(caster_ptr, m2_name, em_ptr->m_ptr, MD_INDEF_VISIBLE); + exe_write_diary(caster_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_HEAL_LEPER, m2_name); + } + + delete_monster_idx(caster_ptr, em_ptr->g_ptr->m_idx); + return TRUE; +} + +/*! + * @brief モンスターの恐慌処理 / If the player did it, give him experience, check fear + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return モンスターが死んだらTRUE、生きていたらFALSE + */ +static bool process_monster_fear(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + bool fear = FALSE; + if (mon_take_hit(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam, &fear, em_ptr->note_dies)) + return TRUE; + + if (em_ptr->do_sleep) + anger_monster(caster_ptr, em_ptr->m_ptr); + + if (em_ptr->note && em_ptr->seen_msg) + msg_format(_("%s%s", "%^s%s"), em_ptr->m_name, em_ptr->note); + else if (em_ptr->known && (em_ptr->dam || !em_ptr->do_fear)) + message_pain(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam); + + if (((em_ptr->dam > 0) || em_ptr->get_angry) && !em_ptr->do_sleep) + anger_monster(caster_ptr, em_ptr->m_ptr); + + if ((fear || em_ptr->do_fear) && em_ptr->seen) { + sound(SOUND_FLEE); + msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), em_ptr->m_name); + } + + return FALSE; +} + +/*! + * todo 睡眠処理があるので、死に際とは言えない。適切な関数名に要修正 + * @brief モンスターの死に際処理 (魔力吸収を除く) + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void process_monster_last_moment(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->effect_type == GF_DRAIN_MANA) + return; + + if (process_monster_damage(caster_ptr, em_ptr)) + return; + if (heal_leaper(caster_ptr, em_ptr)) + return; + if (process_monster_fear(caster_ptr, em_ptr)) + return; + + if (em_ptr->do_sleep) + (void)set_monster_csleep(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_sleep); +} + +/*! + * @brief 魔法の効果による汎用処理 (変身の有無、現在HPの減算、徳の変化) + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void process_spell_result(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) || (em_ptr->r_ptr->flags1 & RF1_QUESTOR) || (caster_ptr->riding && (em_ptr->g_ptr->m_idx == caster_ptr->riding))) + em_ptr->do_polymorph = FALSE; + + if (((em_ptr->r_ptr->flags1 & (RF1_UNIQUE | RF1_QUESTOR)) || (em_ptr->r_ptr->flags7 & RF7_NAZGUL)) && !caster_ptr->phase_out && (em_ptr->who > 0) + && (em_ptr->dam > em_ptr->m_ptr->hp)) + em_ptr->dam = em_ptr->m_ptr->hp; + + if ((em_ptr->who > 0) || !em_ptr->slept) + return; + + if (!(em_ptr->r_ptr->flags3 & RF3_EVIL) || one_in_(5)) + chg_virtue(caster_ptr, V_COMPASSION, -1); + if (!(em_ptr->r_ptr->flags3 & RF3_EVIL) || one_in_(5)) + chg_virtue(caster_ptr, V_HONOUR, -1); +} + +/*! + * @brief モンスターの朦朧値を蓄積させる + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @param stun_damage 朦朧値 + * @return なし + */ +static void pile_monster_stun(player_type *caster_ptr, effect_monster_type *em_ptr, int *stun_damage) +{ + if ((em_ptr->do_stun == 0) || (em_ptr->r_ptr->flagsr & (RFR_RES_SOUN | RFR_RES_WALL)) || (em_ptr->r_ptr->flags3 & RF3_NO_STUN)) + return; + + if (em_ptr->seen) + em_ptr->obvious = TRUE; + + if (monster_stunned_remaining(em_ptr->m_ptr)) { + em_ptr->note = _("はひどくもうろうとした。", " is more dazed."); + *stun_damage = monster_stunned_remaining(em_ptr->m_ptr) + (em_ptr->do_stun / 2); + } else { + em_ptr->note = _("はもうろうとした。", " is dazed."); + *stun_damage = em_ptr->do_stun; + } + + (void)set_monster_stunned(caster_ptr, em_ptr->g_ptr->m_idx, *stun_damage); + em_ptr->get_angry = TRUE; +} + +/*! + * @brief モンスターの混乱値を蓄積させる + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @param stun_damage 混乱値 + * @return なし + */ +static void pile_monster_conf(player_type *caster_ptr, effect_monster_type *em_ptr, int *conf_damage) +{ + if ((em_ptr->do_conf == 0) || (em_ptr->r_ptr->flags3 & RF3_NO_CONF) || (em_ptr->r_ptr->flagsr & RFR_EFF_RES_CHAO_MASK)) + return; + + if (em_ptr->seen) + em_ptr->obvious = TRUE; + + if (monster_confused_remaining(em_ptr->m_ptr)) { + em_ptr->note = _("はさらに混乱したようだ。", " looks more confused."); + *conf_damage = monster_confused_remaining(em_ptr->m_ptr) + (em_ptr->do_conf / 2); + } else { + em_ptr->note = _("は混乱したようだ。", " looks confused."); + *conf_damage = em_ptr->do_conf; + } + + (void)set_monster_confused(caster_ptr, em_ptr->g_ptr->m_idx, *conf_damage); + em_ptr->get_angry = TRUE; +} + +/*! + * @brief モンスターを衰弱させる + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void process_monster_weakening(effect_monster_type *em_ptr) +{ + if (em_ptr->do_time == 0) + return; + + if (em_ptr->seen) + em_ptr->obvious = TRUE; + + if (em_ptr->do_time >= em_ptr->m_ptr->maxhp) + em_ptr->do_time = em_ptr->m_ptr->maxhp - 1; + + if (em_ptr->do_time) { + em_ptr->note = _("は弱くなったようだ。", " seems weakened."); + em_ptr->m_ptr->maxhp -= em_ptr->do_time; + if ((em_ptr->m_ptr->hp - em_ptr->dam) > em_ptr->m_ptr->maxhp) + em_ptr->dam = em_ptr->m_ptr->hp - em_ptr->m_ptr->maxhp; + } + + em_ptr->get_angry = TRUE; +} + +/*! + * @brief モンスターを変身させる + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void process_monster_polymorph(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (!em_ptr->do_polymorph || (randint1(90) <= em_ptr->r_ptr->level)) + return; + + if (polymorph_monster(caster_ptr, em_ptr->y, em_ptr->x)) { + if (em_ptr->seen) + em_ptr->obvious = TRUE; + + em_ptr->note = _("が変身した!", " changes!"); + em_ptr->dam = 0; + } + + em_ptr->m_ptr = &caster_ptr->current_floor_ptr->m_list[em_ptr->g_ptr->m_idx]; + em_ptr->r_ptr = &r_info[em_ptr->m_ptr->r_idx]; +} + +/*! + * @brief モンスターをテレポートさせる + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void process_monster_teleport(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->do_dist == 0) + return; + + if (em_ptr->seen) + em_ptr->obvious = TRUE; + + em_ptr->note = _("が消え去った!", " disappears!"); + + if (!em_ptr->who) + chg_virtue(caster_ptr, V_VALOUR, -1); + + teleport_away(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_dist, (!em_ptr->who ? TELEPORT_DEC_VALOUR : 0L) | TELEPORT_PASSIVE); + + em_ptr->y = em_ptr->m_ptr->fy; + em_ptr->x = em_ptr->m_ptr->fx; + em_ptr->g_ptr = &caster_ptr->current_floor_ptr->grid_array[em_ptr->y][em_ptr->x]; +} + +/*! + * @brief モンスターの異常状態を処理する + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @parama tmp_damage 朦朧/混乱値 + * @return なし + */ +static void process_monster_bad_status(player_type *caster_ptr, effect_monster_type *em_ptr, int *tmp_damage) +{ + pile_monster_stun(caster_ptr, em_ptr, tmp_damage); + pile_monster_conf(caster_ptr, em_ptr, tmp_damage); + process_monster_weakening(em_ptr); + process_monster_polymorph(caster_ptr, em_ptr); + process_monster_teleport(caster_ptr, em_ptr); + if (em_ptr->do_fear == 0) + return; + + (void)set_monster_monfear(caster_ptr, em_ptr->g_ptr->m_idx, monster_fear_remaining(em_ptr->m_ptr) + em_ptr->do_fear); + em_ptr->get_angry = TRUE; +} + +/*! + * @brief モンスターへのダメージに応じたメッセージを表示させ、異常状態を与える + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void process_monster_bad_stat_damage(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + int tmp_damage = em_ptr->dam; + em_ptr->dam = mon_damage_mod(caster_ptr, em_ptr->m_ptr, em_ptr->dam, (bool)(em_ptr->effect_type == GF_PSY_SPEAR)); + if ((tmp_damage > 0) && (em_ptr->dam == 0)) + em_ptr->note = _("はダメージを受けていない。", " is unharmed."); + + if (em_ptr->dam > em_ptr->m_ptr->hp) + em_ptr->note = em_ptr->note_dies; + else + process_monster_bad_status(caster_ptr, em_ptr, &tmp_damage); +} + +/*! + * todo 関数名が微妙、もっと適切な関数名が欲しい + * @brief モンスターへの影響全般を処理する + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void process_spell(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + process_spell_result(caster_ptr, em_ptr); + process_monster_bad_stat_damage(caster_ptr, em_ptr); + process_monster_last_moment(caster_ptr, em_ptr); + if ((em_ptr->effect_type == GF_BLOOD_CURSE) && one_in_(4)) + blood_curse_to_enemy(caster_ptr, em_ptr->who); +} + +/*! + * @brief モンスター闘技場にいる場合の画面更新処理 + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void update_phase_out_stat(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (!caster_ptr->phase_out) + return; + + caster_ptr->health_who = em_ptr->g_ptr->m_idx; + caster_ptr->redraw |= (PR_HEALTH); + handle_stuff(caster_ptr); +} + +/*! + * @brief 魔法効果がペットに及んだ時の処理 + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void postprocess_spell_pet(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if ((em_ptr->dam <= 0) || is_pet(em_ptr->m_ptr) || is_friendly(em_ptr->m_ptr)) + return; + + if (em_ptr->who == 0) { + if (!(em_ptr->flag & PROJECT_NO_HANGEKI)) + set_target(em_ptr->m_ptr, monster_target_y, monster_target_x); + + return; + } + + if ((em_ptr->who > 0) && is_pet(em_ptr->m_caster_ptr) && !player_bold(caster_ptr, em_ptr->m_ptr->target_y, em_ptr->m_ptr->target_x)) + set_target(em_ptr->m_ptr, em_ptr->m_caster_ptr->fy, em_ptr->m_caster_ptr->fx); +} + +/*! + * @brief 魔法効果が騎乗モンスターに及んだ時の処理 + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void postprocess_spell_riding(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (!caster_ptr->riding || (caster_ptr->riding != em_ptr->g_ptr->m_idx) || (em_ptr->dam <= 0)) + return; + + if (em_ptr->m_ptr->hp > (em_ptr->m_ptr->maxhp / 3)) + em_ptr->dam = (em_ptr->dam + 1) / 2; + + rakubadam_m = (em_ptr->dam > 200) ? 200 : em_ptr->dam; +} + +/*! + * @brief 写真を撮った時の処理 + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + * @details 写真のフラッシュは弱閃光属性 + */ +static void postprocess_spell_photo(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + if (em_ptr->photo == 0) + return; + + object_type *q_ptr; + object_type forge; + q_ptr = &forge; + object_prep(caster_ptr, q_ptr, lookup_kind(TV_STATUE, SV_PHOTO)); + q_ptr->pval = em_ptr->photo; + q_ptr->ident |= (IDENT_FULL_KNOWN); + (void)drop_near(caster_ptr, q_ptr, -1, caster_ptr->y, caster_ptr->x); +} + +/*! + * @brief モンスター効果の後処理 (ペット関係、記念撮影、グローバル変数更新) + * @param caster_ptr プレーヤーへの参照ポインタ + * @param em_ptr モンスター効果構造体への参照ポインタ + * @return なし + */ +static void postprocess_spell(player_type *caster_ptr, effect_monster_type *em_ptr) +{ + postprocess_spell_pet(caster_ptr, em_ptr); + postprocess_spell_riding(caster_ptr, em_ptr); + postprocess_spell_photo(caster_ptr, em_ptr); + project_m_n++; + project_m_x = em_ptr->x; + project_m_y = em_ptr->y; +} + +/*! + * @brief 汎用的なビーム/ボルト/ボール系によるモンスターへの効果処理 / Handle a beam/bolt/ball causing damage to a monster. + * @param caster_ptr プレーヤーへの参照ポインタ + * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player") + * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball) + * @param y 目標y座標 / Target y location (or location to travel "towards") + * @param x 目標x座標 / Target x location (or location to travel "towards") + * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player) + * @param effect_type 効果属性 / Type of damage to apply to monsters (and objects) + * @param flag 効果フラグ + * @param see_s_msg TRUEならばメッセージを表示する + * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE + */ +bool affect_monster( + player_type *caster_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID effect_type, BIT_FLAGS flag, bool see_s_msg) +{ + effect_monster_type tmp_effect; + effect_monster_type *em_ptr = initialize_effect_monster(caster_ptr, &tmp_effect, who, r, y, x, dam, effect_type, flag, see_s_msg); + if (!is_never_effect(caster_ptr, em_ptr)) + return FALSE; + + decide_spell_result_description(caster_ptr, em_ptr); + process_result result = process_monster_perfect_resistance(caster_ptr, em_ptr); + if (result != PROCESS_CONTINUE) + return (bool)result; + + if (em_ptr->skipped) + return FALSE; + + process_spell(caster_ptr, em_ptr); + update_phase_out_stat(caster_ptr, em_ptr); + if (em_ptr->m_ptr->r_idx) + update_monster(caster_ptr, em_ptr->g_ptr->m_idx, FALSE); + + lite_spot(caster_ptr, em_ptr->y, em_ptr->x); + if ((caster_ptr->monster_race_idx == em_ptr->m_ptr->r_idx) && (em_ptr->seen || !em_ptr->m_ptr->r_idx)) + caster_ptr->window |= (PW_MONSTER); + + postprocess_spell(caster_ptr, em_ptr); + return em_ptr->obvious; +} diff --git a/src/effect/effect-monster.h b/src/effect/effect-monster.h new file mode 100644 index 000000000..d9a6835d2 --- /dev/null +++ b/src/effect/effect-monster.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" +#include "effect/effect-monster-util.h" + +bool affect_monster(player_type *caster_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ, BIT_FLAGS flag, bool see_s_msg); diff --git a/src/effect/effect-player-curse.c b/src/effect/effect-player-curse.c new file mode 100644 index 000000000..6483f7794 --- /dev/null +++ b/src/effect/effect-player-curse.c @@ -0,0 +1,57 @@ +#include "effect/effect-player-curse.h" +#include "blue-magic/blue-magic-checker.h" +#include "mind/mind-mirror-master.h" +#include "monster-race/race-indice-types.h" +#include "object-enchant/object-curse.h" +#include "player/player-damage.h" +#include "status/bad-status-setter.h" +#include "view/display-messages.h" +#include "world/world.h" + +void effect_player_curse_1(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) { + msg_print(_("しかし効力を跳ね返した!", "You resist the effects!")); + learn_spell(target_ptr, ep_ptr->monspell); + } else { + if (!check_multishadow(target_ptr)) + curse_equipment(target_ptr, 15, 0); + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + } +} + +void effect_player_curse_2(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) { + msg_print(_("しかし効力を跳ね返した!", "You resist the effects!")); + learn_spell(target_ptr, ep_ptr->monspell); + } else { + if (!check_multishadow(target_ptr)) + curse_equipment(target_ptr, 25, MIN(ep_ptr->rlev / 2 - 15, 5)); + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + } +} + +void effect_player_curse_3(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) { + msg_print(_("しかし効力を跳ね返した!", "You resist the effects!")); + learn_spell(target_ptr, ep_ptr->monspell); + } else { + if (!check_multishadow(target_ptr)) + curse_equipment(target_ptr, 33, MIN(ep_ptr->rlev / 2 - 15, 15)); + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + } +} + +void effect_player_curse_4(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !(ep_ptr->m_ptr->r_idx == MON_KENSHIROU) && !check_multishadow(target_ptr)) { + msg_print(_("しかし秘孔を跳ね返した!", "You resist the effects!")); + learn_spell(target_ptr, ep_ptr->monspell); + } else { + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + if (!check_multishadow(target_ptr)) + (void)set_cut(target_ptr, target_ptr->cut + damroll(10, 10)); + } +} diff --git a/src/effect/effect-player-curse.h b/src/effect/effect-player-curse.h new file mode 100644 index 000000000..06136f4b3 --- /dev/null +++ b/src/effect/effect-player-curse.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" +#include "effect/effect-player-util.h" + +void effect_player_curse_1(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_curse_2(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_curse_3(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_curse_4(player_type *target_ptr, effect_player_type *ep_ptr); diff --git a/src/effect/effect-player-oldies.c b/src/effect/effect-player-oldies.c new file mode 100644 index 000000000..1ccca7af2 --- /dev/null +++ b/src/effect/effect-player-oldies.c @@ -0,0 +1,53 @@ +#include "effect/effect-player-oldies.h" +#include "core/hp-mp-processor.h" +#include "game-option/birth-options.h" +#include "monster-race/race-indice-types.h" +#include "player/eldritch-horror.h" +#include "status/bad-status-setter.h" +#include "status/buff-setter.h" +#include "view/display-messages.h" + +void effect_player_old_heal(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何らかの攻撃によって気分がよくなった。", "You are hit by something invigorating!")); + + (void)hp_player(target_ptr, ep_ptr->dam); + ep_ptr->dam = 0; +} + +void effect_player_old_speed(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何かで攻撃された!", "You are hit by something!")); + + (void)set_fast(target_ptr, target_ptr->fast + randint1(5), FALSE); + ep_ptr->dam = 0; +} + +void effect_player_old_slow(player_type *target_ptr) +{ + if (target_ptr->blind) + msg_print(_("何か遅いもので攻撃された!", "You are hit by something slow!")); + + (void)set_slow(target_ptr, target_ptr->slow + randint0(4) + 4, FALSE); +} + +void effect_player_old_sleep(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->free_act) + return; + + if (target_ptr->blind) + msg_print(_("眠ってしまった!", "You fall asleep!")); + + if (ironman_nightmare) { + msg_print(_("恐ろしい光景が頭に浮かんできた。", "A horrible vision enters your mind.")); + + /* Have some nightmares */ + sanity_blast(target_ptr, NULL, FALSE); + } + + set_paralyzed(target_ptr, target_ptr->paralyzed + ep_ptr->dam); + ep_ptr->dam = 0; +} diff --git a/src/effect/effect-player-oldies.h b/src/effect/effect-player-oldies.h new file mode 100644 index 000000000..29b3f33b5 --- /dev/null +++ b/src/effect/effect-player-oldies.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" +#include "effect/effect-player-util.h" + +void effect_player_old_heal(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_old_speed(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_old_slow(player_type *target_ptr); +void effect_player_old_sleep(player_type *target_ptr, effect_player_type *ep_ptr); diff --git a/src/effect/effect-player-resist-hurt.c b/src/effect/effect-player-resist-hurt.c new file mode 100644 index 000000000..ea2933a86 --- /dev/null +++ b/src/effect/effect-player-resist-hurt.c @@ -0,0 +1,540 @@ +#include "effect/effect-player-resist-hurt.h" +#include "art-definition/art-sword-types.h" +#include "blue-magic/blue-magic-checker.h" +#include "core/hp-mp-processor.h" +#include "core/player-redraw-types.h" +#include "core/player-update-types.h" +#include "core/window-redrawer.h" +#include "inventory/inventory-damage.h" +#include "inventory/inventory-slot-types.h" +#include "mind/mind-mirror-master.h" +#include "monster-race/race-indice-types.h" +#include "mutation/mutation-investor-remover.h" +#include "object/object-broken.h" +#include "player/player-damage.h" +#include "player/player-race-types.h" +#include "player/player-race.h" +#include "spell-kind/spells-equipment.h" +#include "spell-kind/spells-teleport.h" +#include "spell/spells-status.h" +#include "status/bad-status-setter.h" +#include "status/base-status.h" +#include "status/element-resistance.h" +#include "status/experience.h" +#include "status/shape-changer.h" +#include "system/object-type-definition.h" +#include "view/display-messages.h" +#include "world/world.h" + +// 毒を除く4元素. +void effect_player_elements( + player_type *target_ptr, effect_player_type *ep_ptr, concptr attack_message, HIT_POINT (*damage_func)(player_type *, HIT_POINT, concptr, int, bool)) +{ + if (target_ptr->blind) + msg_print(attack_message); + + ep_ptr->get_damage = (*damage_func)(target_ptr, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell, FALSE); +} + +void effect_player_poison(player_type *target_ptr, effect_player_type *ep_ptr) +{ + bool double_resist = is_oppose_pois(target_ptr); + if (target_ptr->blind) + msg_print(_("毒で攻撃された!", "You are hit by poison!")); + + if (target_ptr->resist_pois) + ep_ptr->dam = (ep_ptr->dam + 2) / 3; + if (double_resist) + ep_ptr->dam = (ep_ptr->dam + 2) / 3; + + if ((!(double_resist || target_ptr->resist_pois)) && one_in_(HURT_CHANCE) && !check_multishadow(target_ptr)) { + do_dec_stat(target_ptr, A_CON); + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + + if (!(double_resist || target_ptr->resist_pois) && !check_multishadow(target_ptr)) + set_poisoned(target_ptr, target_ptr->poisoned + randint0(ep_ptr->dam) + 10); +} + +void effect_player_nuke(player_type *target_ptr, effect_player_type *ep_ptr) +{ + bool double_resist = is_oppose_pois(target_ptr); + if (target_ptr->blind) + msg_print(_("放射能で攻撃された!", "You are hit by radiation!")); + + if (target_ptr->resist_pois) + ep_ptr->dam = (2 * ep_ptr->dam + 2) / 5; + if (double_resist) + ep_ptr->dam = (2 * ep_ptr->dam + 2) / 5; + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + if ((double_resist || target_ptr->resist_pois) || check_multishadow(target_ptr)) + return; + + set_poisoned(target_ptr, target_ptr->poisoned + randint0(ep_ptr->dam) + 10); + if (one_in_(5)) /* 6 */ + { + msg_print(_("奇形的な変身を遂げた!", "You undergo a freakish metamorphosis!")); + if (one_in_(4)) /* 4 */ + do_poly_self(target_ptr); + else + status_shuffle(target_ptr); + } + + if (one_in_(6)) + inventory_damage(target_ptr, set_acid_destroy, 2); +} + +void effect_player_missile(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何かで攻撃された!", "You are hit by something!")); + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_holy_fire(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何かで攻撃された!", "You are hit by something!")); + + if (target_ptr->align > 10) + ep_ptr->dam /= 2; + else if (target_ptr->align < -10) + ep_ptr->dam *= 2; + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_hell_fire(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何かで攻撃された!", "You are hit by something!")); + + if (target_ptr->align > 10) + ep_ptr->dam *= 2; + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_arrow(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) { + msg_print(_("何か鋭いもので攻撃された!", "You are hit by something sharp!")); + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + return; + } + + if ((target_ptr->inventory_list[INVEN_RARM].name1 == ART_ZANTETSU) || (target_ptr->inventory_list[INVEN_LARM].name1 == ART_ZANTETSU)) { + msg_print(_("矢を斬り捨てた!", "You cut down the arrow!")); + return; + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_plasma(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何かとても熱いもので攻撃された!", "You are hit by something *HOT*!")); + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + + if (!target_ptr->resist_sound && !check_multishadow(target_ptr)) { + int plus_stun = (randint1((ep_ptr->dam > 40) ? 35 : (ep_ptr->dam * 3 / 4 + 5))); + (void)set_stun(target_ptr, target_ptr->stun + plus_stun); + } + + if (!(target_ptr->resist_fire || is_oppose_fire(target_ptr) || target_ptr->immune_fire)) + inventory_damage(target_ptr, set_acid_destroy, 3); +} + +void effect_player_nether(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("地獄の力で攻撃された!", "You are hit by nether forces!")); + + if (target_ptr->resist_neth) { + if (!is_specific_player_race(target_ptr, RACE_SPECTRE)) + ep_ptr->dam *= 6; + ep_ptr->dam /= (randint1(4) + 7); + } else if (!check_multishadow(target_ptr)) + drain_exp(target_ptr, 200 + (target_ptr->exp / 100), 200 + (target_ptr->exp / 1000), 75); + + if (!is_specific_player_race(target_ptr, RACE_SPECTRE) || check_multishadow(target_ptr)) { + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + return; + } + + msg_print(_("気分がよくなった。", "You feel invigorated!")); + hp_player(target_ptr, ep_ptr->dam / 4); + learn_spell(target_ptr, ep_ptr->monspell); +} + +void effect_player_water(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何か湿ったもので攻撃された!", "You are hit by something wet!")); + if (check_multishadow(target_ptr)) { + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + return; + } + + if (!target_ptr->resist_sound && !target_ptr->resist_water) { + set_stun(target_ptr, target_ptr->stun + randint1(40)); + } + if (!target_ptr->resist_conf && !target_ptr->resist_water) { + set_confused(target_ptr, target_ptr->confused + randint1(5) + 5); + } + + if (one_in_(5) && !target_ptr->resist_water) { + inventory_damage(target_ptr, set_cold_destroy, 3); + } + + if (target_ptr->resist_water) + ep_ptr->get_damage /= 4; + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_chaos(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("無秩序の波動で攻撃された!", "You are hit by a wave of anarchy!")); + if (target_ptr->resist_chaos) { + ep_ptr->dam *= 6; + ep_ptr->dam /= (randint1(4) + 7); + } + + if (check_multishadow(target_ptr)) { + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + return; + } + + if (!target_ptr->resist_conf) { + (void)set_confused(target_ptr, target_ptr->confused + randint0(20) + 10); + } + if (!target_ptr->resist_chaos) { + (void)set_image(target_ptr, target_ptr->image + randint1(10)); + if (one_in_(3)) { + msg_print(_("あなたの身体はカオスの力で捻じ曲げられた!", "Your body is twisted by chaos!")); + (void)gain_mutation(target_ptr, 0); + } + } + if (!target_ptr->resist_neth && !target_ptr->resist_chaos) { + drain_exp(target_ptr, 5000 + (target_ptr->exp / 100), 500 + (target_ptr->exp / 1000), 75); + } + + if (!target_ptr->resist_chaos || one_in_(9)) { + inventory_damage(target_ptr, set_elec_destroy, 2); + inventory_damage(target_ptr, set_fire_destroy, 2); + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_shards(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何か鋭いもので攻撃された!", "You are hit by something sharp!")); + if (target_ptr->resist_shard) { + ep_ptr->dam *= 6; + ep_ptr->dam /= (randint1(4) + 7); + } else if (!check_multishadow(target_ptr)) { + (void)set_cut(target_ptr, target_ptr->cut + ep_ptr->dam); + } + + if (!target_ptr->resist_shard || one_in_(13)) + inventory_damage(target_ptr, set_cold_destroy, 2); + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_sound(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("轟音で攻撃された!", "You are hit by a loud noise!")); + if (target_ptr->resist_sound) { + ep_ptr->dam *= 5; + ep_ptr->dam /= (randint1(4) + 7); + } else if (!check_multishadow(target_ptr)) { + int plus_stun = (randint1((ep_ptr->dam > 90) ? 35 : (ep_ptr->dam / 3 + 5))); + (void)set_stun(target_ptr, target_ptr->stun + plus_stun); + } + + if (!target_ptr->resist_sound || one_in_(13)) + inventory_damage(target_ptr, set_cold_destroy, 2); + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_confusion(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何か混乱するもので攻撃された!", "You are hit by something puzzling!")); + if (target_ptr->resist_conf) { + ep_ptr->dam *= 5; + ep_ptr->dam /= (randint1(4) + 7); + } else if (!check_multishadow(target_ptr)) { + (void)set_confused(target_ptr, target_ptr->confused + randint1(20) + 10); + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_disenchant(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何かさえないもので攻撃された!", "You are hit by something static!")); + if (target_ptr->resist_disen) { + ep_ptr->dam *= 6; + ep_ptr->dam /= (randint1(4) + 7); + } else if (!check_multishadow(target_ptr)) { + (void)apply_disenchant(target_ptr, 0); + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_nexus(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何か奇妙なもので攻撃された!", "You are hit by something strange!")); + if (target_ptr->resist_nexus) { + ep_ptr->dam *= 6; + ep_ptr->dam /= (randint1(4) + 7); + } else if (!check_multishadow(target_ptr)) { + apply_nexus(ep_ptr->m_ptr, target_ptr); + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_force(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("運動エネルギーで攻撃された!", "You are hit by kinetic force!")); + if (!target_ptr->resist_sound && !check_multishadow(target_ptr)) { + (void)set_stun(target_ptr, target_ptr->stun + randint1(20)); + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_rocket(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("爆発があった!", "There is an explosion!")); + if (!target_ptr->resist_sound && !check_multishadow(target_ptr)) { + (void)set_stun(target_ptr, target_ptr->stun + randint1(20)); + } + + if (target_ptr->resist_shard) { + ep_ptr->dam /= 2; + } else if (!check_multishadow(target_ptr)) { + (void)set_cut(target_ptr, target_ptr->cut + (ep_ptr->dam / 2)); + } + + if (!target_ptr->resist_shard || one_in_(12)) { + inventory_damage(target_ptr, set_cold_destroy, 3); + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_inertial(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何か遅いもので攻撃された!", "You are hit by something slow!")); + if (!check_multishadow(target_ptr)) + (void)set_slow(target_ptr, target_ptr->slow + randint0(4) + 4, FALSE); + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_lite(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何かで攻撃された!", "You are hit by something!")); + if (target_ptr->resist_lite) { + ep_ptr->dam *= 4; + ep_ptr->dam /= (randint1(4) + 7); + } else if (!target_ptr->blind && !target_ptr->resist_blind && !check_multishadow(target_ptr)) { + (void)set_blind(target_ptr, target_ptr->blind + randint1(5) + 2); + } + + if (is_specific_player_race(target_ptr, RACE_VAMPIRE) || (target_ptr->mimic_form == MIMIC_VAMPIRE)) { + if (!check_multishadow(target_ptr)) + msg_print(_("光で肉体が焦がされた!", "The light scorches your flesh!")); + ep_ptr->dam *= 2; + } else if (is_specific_player_race(target_ptr, RACE_S_FAIRY)) { + ep_ptr->dam = ep_ptr->dam * 4 / 3; + } + + if (target_ptr->wraith_form) + ep_ptr->dam *= 2; + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + + if (!target_ptr->wraith_form || check_multishadow(target_ptr)) + return; + + target_ptr->wraith_form = 0; + msg_print(_("閃光のため非物質的な影の存在でいられなくなった。", "The light forces you out of your incorporeal shadow form.")); + + target_ptr->redraw |= (PR_MAP | PR_STATUS); + target_ptr->update |= (PU_MONSTERS); + target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); +} + +void effect_player_dark(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何かで攻撃された!", "You are hit by something!")); + if (target_ptr->resist_dark) { + ep_ptr->dam *= 4; + ep_ptr->dam /= (randint1(4) + 7); + + if (is_specific_player_race(target_ptr, RACE_VAMPIRE) || (target_ptr->mimic_form == MIMIC_VAMPIRE) || target_ptr->wraith_form) + ep_ptr->dam = 0; + } else if (!target_ptr->blind && !target_ptr->resist_blind && !check_multishadow(target_ptr)) { + (void)set_blind(target_ptr, target_ptr->blind + randint1(5) + 2); + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +static void effect_player_time_one_disability(player_type *target_ptr) +{ + int k = 0; + concptr act = NULL; + switch (randint1(6)) { + case 1: + k = A_STR; + act = _("強く", "strong"); + break; + case 2: + k = A_INT; + act = _("聡明で", "bright"); + break; + case 3: + k = A_WIS; + act = _("賢明で", "wise"); + break; + case 4: + k = A_DEX; + act = _("器用で", "agile"); + break; + case 5: + k = A_CON; + act = _("健康で", "hale"); + break; + case 6: + k = A_CHR; + act = _("美しく", "beautiful"); + break; + } + + msg_format(_("あなたは以前ほど%sなくなってしまった...。", "You're not as %s as you used to be..."), act); + target_ptr->stat_cur[k] = (target_ptr->stat_cur[k] * 3) / 4; + if (target_ptr->stat_cur[k] < 3) + target_ptr->stat_cur[k] = 3; + + target_ptr->update |= (PU_BONUS); +} + +static void effect_player_time_all_disabilities(player_type *target_ptr) +{ + msg_print(_("あなたは以前ほど力強くなくなってしまった...。", "You're not as powerful as you used to be...")); + for (int k = 0; k < A_MAX; k++) { + target_ptr->stat_cur[k] = (target_ptr->stat_cur[k] * 7) / 8; + if (target_ptr->stat_cur[k] < 3) + target_ptr->stat_cur[k] = 3; + } + + target_ptr->update |= (PU_BONUS); +} + +static void effect_player_time_addition(player_type *target_ptr) +{ + switch (randint1(10)) { + case 1: + case 2: + case 3: + case 4: + case 5: { + if (target_ptr->prace == RACE_ANDROID) + break; + + msg_print(_("人生が逆戻りした気がする。", "You feel like a chunk of the past has been ripped away.")); + lose_exp(target_ptr, 100 + (target_ptr->exp / 100) * MON_DRAIN_LIFE); + break; + } + case 6: + case 7: + case 8: + case 9: + effect_player_time_one_disability(target_ptr); + break; + case 10: + effect_player_time_all_disabilities(target_ptr); + break; + } +} + +void effect_player_time(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("過去からの衝撃に攻撃された!", "You are hit by a blast from the past!")); + + if (target_ptr->resist_time) { + ep_ptr->dam *= 4; + ep_ptr->dam /= (randint1(4) + 7); + msg_print(_("時間が通り過ぎていく気がする。", "You feel as if time is passing you by.")); + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + return; + } + + if (check_multishadow(target_ptr)) { + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + return; + } + + effect_player_time_addition(target_ptr); + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_gravity(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("何か重いもので攻撃された!", "You are hit by something heavy!")); + msg_print(_("周辺の重力がゆがんだ。", "Gravity warps around you.")); + + if (!check_multishadow(target_ptr)) { + teleport_player(target_ptr, 5, TELEPORT_PASSIVE); + if (!target_ptr->levitation) + (void)set_slow(target_ptr, target_ptr->slow + randint0(4) + 4, FALSE); + if (!(target_ptr->resist_sound || target_ptr->levitation)) { + int plus_stun = (randint1((ep_ptr->dam > 90) ? 35 : (ep_ptr->dam / 3 + 5))); + (void)set_stun(target_ptr, target_ptr->stun + plus_stun); + } + } + + if (target_ptr->levitation) { + ep_ptr->dam = (ep_ptr->dam * 2) / 3; + } + + if (!target_ptr->levitation || one_in_(13)) { + inventory_damage(target_ptr, set_cold_destroy, 2); + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_disintegration(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("純粋なエネルギーで攻撃された!", "You are hit by pure energy!")); + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} diff --git a/src/effect/effect-player-resist-hurt.h b/src/effect/effect-player-resist-hurt.h new file mode 100644 index 000000000..e45820122 --- /dev/null +++ b/src/effect/effect-player-resist-hurt.h @@ -0,0 +1,29 @@ +#pragma once + +#include "system/angband.h" +#include "effect/effect-player-util.h" + +void effect_player_elements(player_type *target_ptr, effect_player_type *ep_ptr, concptr attack_message, HIT_POINT (*damage_func)(player_type *, HIT_POINT, concptr, int, bool)); +void effect_player_poison(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_nuke(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_missile(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_holy_fire(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_hell_fire(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_arrow(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_plasma(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_nether(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_water(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_chaos(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_shards(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_sound(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_confusion(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_disenchant(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_nexus(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_force(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_rocket(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_inertial(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_lite(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_dark(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_time(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_gravity(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_disintegration(player_type *target_ptr, effect_player_type *ep_ptr); diff --git a/src/effect/effect-player-spirit.c b/src/effect/effect-player-spirit.c new file mode 100644 index 000000000..8fd361ac9 --- /dev/null +++ b/src/effect/effect-player-spirit.c @@ -0,0 +1,140 @@ +#include "effect/effect-player-spirit.h" +#include "blue-magic/blue-magic-checker.h" +#include "core/player-redraw-types.h" +#include "core/window-redrawer.h" +#include "mind/mind-mirror-master.h" +#include "player/player-damage.h" +#include "status/bad-status-setter.h" +#include "status/base-status.h" +#include "view/display-messages.h" +#include "world/world.h" + +void effect_player_drain_mana(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (check_multishadow(target_ptr)) { + msg_print(_("攻撃は幻影に命中し、あなたには届かなかった。", "The attack hits Shadow, but you are unharmed!")); + ep_ptr->dam = 0; + return; + } + + if (target_ptr->csp == 0) { + ep_ptr->dam = 0; + return; + } + + if (ep_ptr->who > 0) + msg_format(_("%^sに精神エネルギーを吸い取られてしまった!", "%^s draws psychic energy from you!"), ep_ptr->m_name); + else + msg_print(_("精神エネルギーを吸い取られてしまった!", "Your psychic energy is drawn!")); + + if (ep_ptr->dam >= target_ptr->csp) { + ep_ptr->dam = target_ptr->csp; + target_ptr->csp = 0; + target_ptr->csp_frac = 0; + } else { + target_ptr->csp -= ep_ptr->dam; + } + + learn_spell(target_ptr, ep_ptr->monspell); + target_ptr->redraw |= (PR_MANA); + target_ptr->window |= (PW_PLAYER | PW_SPELL); + + if ((ep_ptr->who <= 0) || (ep_ptr->m_ptr->hp >= ep_ptr->m_ptr->maxhp)) { + ep_ptr->dam = 0; + return; + } + + ep_ptr->m_ptr->hp += ep_ptr->dam; + if (ep_ptr->m_ptr->hp > ep_ptr->m_ptr->maxhp) + ep_ptr->m_ptr->hp = ep_ptr->m_ptr->maxhp; + + if (target_ptr->health_who == ep_ptr->who) + target_ptr->redraw |= (PR_HEALTH); + if (target_ptr->riding == ep_ptr->who) + target_ptr->redraw |= (PR_UHEALTH); + + if (ep_ptr->m_ptr->ml) { + msg_format(_("%^sは気分が良さそうだ。", "%^s appears healthier."), ep_ptr->m_name); + } + + ep_ptr->dam = 0; +} + +void effect_player_mind_blast(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if ((randint0(100 + ep_ptr->rlev / 2) < MAX(5, target_ptr->skill_sav)) && !check_multishadow(target_ptr)) { + msg_print(_("しかし効力を跳ね返した!", "You resist the effects!")); + learn_spell(target_ptr, ep_ptr->monspell); + return; + } + + if (check_multishadow(target_ptr)) { + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + return; + } + + msg_print(_("霊的エネルギーで精神が攻撃された。", "Your mind is blasted by psionic energy.")); + if (!target_ptr->resist_conf) { + (void)set_confused(target_ptr, target_ptr->confused + randint0(4) + 4); + } + + if (!target_ptr->resist_chaos && one_in_(3)) { + (void)set_image(target_ptr, target_ptr->image + randint0(250) + 150); + } + + target_ptr->csp -= 50; + if (target_ptr->csp < 0) { + target_ptr->csp = 0; + target_ptr->csp_frac = 0; + } + + target_ptr->redraw |= PR_MANA; + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_brain_smash(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if ((randint0(100 + ep_ptr->rlev / 2) < MAX(5, target_ptr->skill_sav)) && !check_multishadow(target_ptr)) { + msg_print(_("しかし効力を跳ね返した!", "You resist the effects!")); + learn_spell(target_ptr, ep_ptr->monspell); + return; + } + + if (!check_multishadow(target_ptr)) { + msg_print(_("霊的エネルギーで精神が攻撃された。", "Your mind is blasted by psionic energy.")); + + target_ptr->csp -= 100; + if (target_ptr->csp < 0) { + target_ptr->csp = 0; + target_ptr->csp_frac = 0; + } + target_ptr->redraw |= PR_MANA; + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + if (check_multishadow(target_ptr)) + return; + + if (!target_ptr->resist_blind) { + (void)set_blind(target_ptr, target_ptr->blind + 8 + randint0(8)); + } + + if (!target_ptr->resist_conf) { + (void)set_confused(target_ptr, target_ptr->confused + randint0(4) + 4); + } + + if (!target_ptr->free_act) { + (void)set_paralyzed(target_ptr, target_ptr->paralyzed + randint0(4) + 4); + } + + (void)set_slow(target_ptr, target_ptr->slow + randint0(4) + 4, FALSE); + + while (randint0(100 + ep_ptr->rlev / 2) > (MAX(5, target_ptr->skill_sav))) + (void)do_dec_stat(target_ptr, A_INT); + while (randint0(100 + ep_ptr->rlev / 2) > (MAX(5, target_ptr->skill_sav))) + (void)do_dec_stat(target_ptr, A_WIS); + + if (!target_ptr->resist_chaos) { + (void)set_image(target_ptr, target_ptr->image + randint0(250) + 150); + } +} diff --git a/src/effect/effect-player-spirit.h b/src/effect/effect-player-spirit.h new file mode 100644 index 000000000..60aaf97ff --- /dev/null +++ b/src/effect/effect-player-spirit.h @@ -0,0 +1,8 @@ +#pragma once + +#include "effect/effect-player-util.h" +#include "system/angband.h" + +void effect_player_drain_mana(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_mind_blast(player_type *target_ptr, effect_player_type *ep_ptr); +void effect_player_brain_smash(player_type *target_ptr, effect_player_type *ep_ptr); diff --git a/src/effect/effect-player-switcher.c b/src/effect/effect-player-switcher.c new file mode 100644 index 000000000..488430235 --- /dev/null +++ b/src/effect/effect-player-switcher.c @@ -0,0 +1,269 @@ +#include "effect/effect-player-switcher.h" +#include "blue-magic/blue-magic-checker.h" +#include "cmd-action/cmd-attack.h" +#include "effect/effect-player-curse.h" +#include "effect/effect-player-oldies.h" +#include "effect/effect-player-resist-hurt.h" +#include "effect/effect-player-spirit.h" +#include "inventory/inventory-damage.h" +#include "mind/mind-mirror-master.h" +#include "object-enchant/object-curse.h" +#include "object/object-broken.h" +#include "player/mimic-info-table.h" +#include "player/player-damage.h" +#include "player/player-race-types.h" +#include "spell/spell-types.h" +#include "status/bad-status-setter.h" +#include "status/element-resistance.h" +#include "view/display-messages.h" +#include "world/world.h" + +void effect_player_mana(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("–‚–@‚̃I[ƒ‰‚ōUŒ‚‚³‚ꂽI", "You are hit by an aura of magic!")); + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_psy_spear(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("ƒGƒlƒ‹ƒM[‚̉ò‚ōUŒ‚‚³‚ꂽI", "You are hit by an energy!")); + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_FORCE, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); +} + +void effect_player_meteor(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("‰½‚©‚ª‹ó‚©‚ç‚ ‚È‚½‚Ì“ªã‚É—Ž‚¿‚Ä‚«‚½I", "Something falls from the sky on you!")); + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + if (!target_ptr->resist_shard || one_in_(13)) { + if (!target_ptr->immune_fire) + inventory_damage(target_ptr, set_fire_destroy, 2); + inventory_damage(target_ptr, set_cold_destroy, 2); + } +} + +void effect_player_icee(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("‰½‚©‰s‚­—₽‚¢‚à‚̂ōUŒ‚‚³‚ꂽI", "You are hit by something sharp and cold!")); + + ep_ptr->get_damage = cold_dam(target_ptr, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell, FALSE); + if (check_multishadow(target_ptr)) + return; + + if (!target_ptr->resist_shard) { + (void)set_cut(target_ptr, target_ptr->cut + damroll(5, 8)); + } + + if (!target_ptr->resist_sound) { + (void)set_stun(target_ptr, target_ptr->stun + randint1(15)); + } + + if ((!(target_ptr->resist_cold || is_oppose_cold(target_ptr))) || one_in_(12)) { + if (!target_ptr->immune_cold) + inventory_damage(target_ptr, set_cold_destroy, 3); + } +} + +void effect_player_death_ray(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if (target_ptr->blind) + msg_print(_("‰½‚©”ñí‚ɗ₽‚¢‚à‚̂ōUŒ‚‚³‚ꂽI", "You are hit by something extremely cold!")); + + if (target_ptr->mimic_form) { + if (!(mimic_info[target_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING)) + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + + return; + } + + switch (target_ptr->prace) { + case RACE_GOLEM: + case RACE_SKELETON: + case RACE_ZOMBIE: + case RACE_VAMPIRE: + case RACE_BALROG: + case RACE_SPECTRE: { + ep_ptr->dam = 0; + break; + } + default: { + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell); + break; + } + } +} + +void effect_player_hand_doom(player_type *target_ptr, effect_player_type *ep_ptr) +{ + if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) { + msg_print(_("‚µ‚©‚µŒø—͂𒵂˕Ԃµ‚½I", "You resist the effects!")); + learn_spell(target_ptr, ep_ptr->monspell); + } else { + if (!check_multishadow(target_ptr)) { + msg_print(_("‚ ‚È‚½‚Í–½‚ª”–‚Ü‚Á‚Ä‚¢‚­‚悤‚ÉŠ´‚¶‚½I", "You feel your life fade away!")); + curse_equipment(target_ptr, 40, 20); + } + + ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->m_name, ep_ptr->monspell); + + if (target_ptr->chp < 1) + target_ptr->chp = 1; + } +} + +/*! + * @brief + * –‚–@‚ÌŒø‰Ê‚É‚æ‚Á‚Ä—lX‚ȃƒbƒZ[‚ðo—Í‚µ‚½‚è—^‚¦‚éƒ_ƒ[ƒW‚Ì‘Œ¸‚ðs‚Á‚½‚è‚·‚é + * @param target_ptr ƒvƒŒ[ƒ„[‚Ö‚ÌŽQÆƒ|ƒCƒ“ƒ^ + * @param em_ptr ƒvƒŒ[ƒ„[Œø‰Ê\‘¢‘Ì‚Ö‚ÌŽQÆƒ|ƒCƒ“ƒ^ + * @return ‚È‚µ + */ +void switch_effects_player(player_type *target_ptr, effect_player_type *ep_ptr) +{ + switch (ep_ptr->effect_type) { + case GF_ACID: + effect_player_elements(target_ptr, ep_ptr, _("Ž_‚ōUŒ‚‚³‚ꂽI", "You are hit by acid!"), acid_dam); + return; + case GF_FIRE: + effect_player_elements(target_ptr, ep_ptr, _("‰Î‰Š‚ōUŒ‚‚³‚ꂽI", "You are hit by fire!"), fire_dam); + return; + case GF_COLD: + effect_player_elements(target_ptr, ep_ptr, _("—â‹C‚ōUŒ‚‚³‚ꂽI", "You are hit by cold!"), cold_dam); + return; + case GF_ELEC: + effect_player_elements(target_ptr, ep_ptr, _("“dŒ‚‚ōUŒ‚‚³‚ꂽI", "You are hit by lightning!"), elec_dam); + return; + case GF_POIS: + effect_player_poison(target_ptr, ep_ptr); + return; + case GF_NUKE: + effect_player_nuke(target_ptr, ep_ptr); + return; + case GF_MISSILE: + effect_player_missile(target_ptr, ep_ptr); + return; + case GF_HOLY_FIRE: + effect_player_holy_fire(target_ptr, ep_ptr); + return; + case GF_HELL_FIRE: + effect_player_hell_fire(target_ptr, ep_ptr); + return; + case GF_ARROW: + effect_player_arrow(target_ptr, ep_ptr); + return; + case GF_PLASMA: + effect_player_plasma(target_ptr, ep_ptr); + return; + case GF_NETHER: + effect_player_nether(target_ptr, ep_ptr); + return; + case GF_WATER: + effect_player_water(target_ptr, ep_ptr); + return; + case GF_CHAOS: + effect_player_chaos(target_ptr, ep_ptr); + return; + case GF_SHARDS: + effect_player_shards(target_ptr, ep_ptr); + return; + case GF_SOUND: + effect_player_sound(target_ptr, ep_ptr); + return; + case GF_CONFUSION: + effect_player_confusion(target_ptr, ep_ptr); + return; + case GF_DISENCHANT: + effect_player_disenchant(target_ptr, ep_ptr); + return; + case GF_NEXUS: + effect_player_nexus(target_ptr, ep_ptr); + return; + case GF_FORCE: + effect_player_force(target_ptr, ep_ptr); + return; + case GF_ROCKET: + effect_player_rocket(target_ptr, ep_ptr); + return; + case GF_INERTIAL: + effect_player_inertial(target_ptr, ep_ptr); + return; + case GF_LITE: + effect_player_lite(target_ptr, ep_ptr); + return; + case GF_DARK: + effect_player_dark(target_ptr, ep_ptr); + return; + case GF_TIME: + effect_player_time(target_ptr, ep_ptr); + return; + case GF_GRAVITY: + effect_player_gravity(target_ptr, ep_ptr); + return; + case GF_DISINTEGRATE: + effect_player_disintegration(target_ptr, ep_ptr); + return; + case GF_OLD_HEAL: + effect_player_old_heal(target_ptr, ep_ptr); + return; + case GF_OLD_SPEED: + effect_player_old_speed(target_ptr, ep_ptr); + return; + case GF_OLD_SLOW: + effect_player_old_slow(target_ptr); + return; + case GF_OLD_SLEEP: + effect_player_old_sleep(target_ptr, ep_ptr); + return; + case GF_MANA: + case GF_SEEKER: + case GF_SUPER_RAY: + effect_player_mana(target_ptr, ep_ptr); + return; + case GF_PSY_SPEAR: + effect_player_psy_spear(target_ptr, ep_ptr); + return; + case GF_METEOR: + effect_player_meteor(target_ptr, ep_ptr); + return; + case GF_ICE: + effect_player_icee(target_ptr, ep_ptr); + return; + case GF_DEATH_RAY: + effect_player_death_ray(target_ptr, ep_ptr); + return; + case GF_DRAIN_MANA: + effect_player_drain_mana(target_ptr, ep_ptr); + return; + case GF_MIND_BLAST: + effect_player_mind_blast(target_ptr, ep_ptr); + return; + case GF_BRAIN_SMASH: + effect_player_brain_smash(target_ptr, ep_ptr); + return; + case GF_CAUSE_1: + effect_player_curse_1(target_ptr, ep_ptr); + return; + case GF_CAUSE_2: + effect_player_curse_2(target_ptr, ep_ptr); + return; + case GF_CAUSE_3: + effect_player_curse_3(target_ptr, ep_ptr); + return; + case GF_CAUSE_4: + effect_player_curse_4(target_ptr, ep_ptr); + return; + case GF_HAND_DOOM: + effect_player_hand_doom(target_ptr, ep_ptr); + return; + default: { + ep_ptr->dam = 0; + return; + } + } +} diff --git a/src/effect/effect-player-switcher.h b/src/effect/effect-player-switcher.h new file mode 100644 index 000000000..3527844bd --- /dev/null +++ b/src/effect/effect-player-switcher.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" +#include "effect-player-util.h" + +void switch_effects_player(player_type *target_ptr, effect_player_type *ep_ptr); diff --git a/src/effect/effect-player-util.h b/src/effect/effect-player-util.h new file mode 100644 index 000000000..29b31986f --- /dev/null +++ b/src/effect/effect-player-util.h @@ -0,0 +1,19 @@ +#pragma once + +#include "system/angband.h" +#include "system/monster-type-definition.h" + +typedef struct effect_player_type +{ + DEPTH rlev; // モンスターのレベル (但し0のモンスターは1になる). + monster_type *m_ptr; + char killer[80]; + GAME_TEXT m_name[MAX_NLEN]; + int get_damage; + + MONSTER_IDX who; + HIT_POINT dam; + EFFECT_ID effect_type; + BIT_FLAGS flag; + int monspell; +} effect_player_type; diff --git a/src/effect/effect-player.c b/src/effect/effect-player.c new file mode 100644 index 000000000..2a10f4b03 --- /dev/null +++ b/src/effect/effect-player.c @@ -0,0 +1,214 @@ +/*! + * @brief 魔法によるプレーヤーへの効果まとめ + * @date 2020/04/29 + * @author Hourier + */ + +#include "effect/effect-player.h" +#include "core/disturbance.h" +#include "effect/effect-characteristics.h" +#include "effect/effect-player-switcher.h" +#include "effect/effect-player-util.h" +#include "effect/spells-effect-util.h" +#include "floor/cave.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "mind/mind-ninja.h" +#include "monster-race/monster-race.h" +#include "monster/monster-describer.h" +#include "monster/monster-description-types.h" +#include "player/special-defense-types.h" +#include "realm/realm-hex-numbers.h" +#include "spell-realm/spells-crusade.h" +#include "spell-realm/spells-hex.h" +#include "spell/spell-types.h" +#include "system/floor-type-definition.h" +#include "target/projection-path-calculator.h" +#include "view/display-messages.h" + +typedef enum effect_player_check_result { + EP_CHECK_FALSE = 0, + EP_CHECK_TRUE = 1, + EP_CHECK_CONTINUE = 2, +} ep_check_result; + +/*! + * @brief effect_player_type構造体を初期化する + * @param ep_ptr 初期化前の構造体 + * @param who 魔法を唱えたモンスター (0ならプレーヤー自身) + * @param dam 基本威力 + * @param effect_type 効果属性 + * @param flag 効果フラグ + * @param monspell 効果元のモンスター魔法ID + * @return 初期化後の構造体ポインタ + */ +static effect_player_type *initialize_effect_player( + effect_player_type *ep_ptr, MONSTER_IDX who, HIT_POINT dam, EFFECT_ID effect_type, BIT_FLAGS flag, int monspell) +{ + ep_ptr->rlev = 0; + ep_ptr->m_ptr = NULL; + ep_ptr->get_damage = 0; + ep_ptr->who = who; + ep_ptr->dam = dam; + ep_ptr->effect_type = effect_type; + ep_ptr->flag = flag; + ep_ptr->monspell = monspell; + return ep_ptr; +} + +/*! + * @brief ボルト魔法を反射する + * @param target_ptr プレーヤーへの参照ポインタ + * @param ep_ptr プレーヤー効果構造体への参照ポインタ + * @return 当たったらFALSE、反射したらTRUE + */ +static bool process_bolt_reflection(player_type *target_ptr, effect_player_type *ep_ptr, project_func project) +{ + bool can_bolt_hit = target_ptr->reflect || (((target_ptr->special_defense & KATA_FUUJIN) != 0) && !target_ptr->blind); + can_bolt_hit &= (ep_ptr->flag & PROJECT_REFLECTABLE) != 0; + can_bolt_hit &= !one_in_(10); + if (!can_bolt_hit) + return FALSE; + + POSITION t_y, t_x; + int max_attempts = 10; + sound(SOUND_REFLECT); + + if (target_ptr->blind) + msg_print(_("何かが跳ね返った!", "Something bounces!")); + else if (target_ptr->special_defense & KATA_FUUJIN) + msg_print(_("風の如く武器を振るって弾き返した!", "The attack bounces!")); + else + msg_print(_("攻撃が跳ね返った!", "The attack bounces!")); + + if (ep_ptr->who > 0) { + floor_type *floor_ptr = target_ptr->current_floor_ptr; + monster_type m_type = floor_ptr->m_list[ep_ptr->who]; + do { + t_y = m_type.fy - 1 + randint1(3); + t_x = m_type.fx - 1 + randint1(3); + max_attempts--; + } while (max_attempts && in_bounds2u(floor_ptr, t_y, t_x) && !projectable(target_ptr, target_ptr->y, target_ptr->x, t_y, t_x)); + + if (max_attempts < 1) { + t_y = m_type.fy; + t_x = m_type.fx; + } + } else { + t_y = target_ptr->y - 1 + randint1(3); + t_x = target_ptr->x - 1 + randint1(3); + } + + (*project)(target_ptr, 0, 0, t_y, t_x, ep_ptr->dam, ep_ptr->effect_type, (PROJECT_STOP | PROJECT_KILL | PROJECT_REFLECTABLE), ep_ptr->monspell); + disturb(target_ptr, TRUE, TRUE); + return TRUE; +} + +/*! + * @brief 反射・忍者の変わり身などでそもそも当たらない状況を判定する + * @param target_ptr プレーヤーへの参照ポインタ + * @param ep_ptr プレーヤー効果構造体への参照ポインタ + * @param y 目標Y座標 + * @param x 目標X座標 + * @return 当たらなかったらFALSE、反射したらTRUE、当たったらCONTINUE + */ +static ep_check_result check_continue_player_effect(player_type *target_ptr, effect_player_type *ep_ptr, POSITION y, POSITION x, project_func project) +{ + if (!player_bold(target_ptr, y, x)) + return EP_CHECK_FALSE; + + if (((target_ptr->special_defense & NINJA_KAWARIMI) != 0) && (ep_ptr->dam > 0) && (randint0(55) < (target_ptr->lev * 3 / 5 + 20)) && (ep_ptr->who > 0) + && (ep_ptr->who != target_ptr->riding) && kawarimi(target_ptr, TRUE)) + return EP_CHECK_FALSE; + + if ((ep_ptr->who == 0) || (ep_ptr->who == target_ptr->riding)) + return EP_CHECK_FALSE; + + if (process_bolt_reflection(target_ptr, ep_ptr, project)) + return EP_CHECK_TRUE; + + return EP_CHECK_CONTINUE; +} + +/*! + * @brief 魔法を発したモンスター名を記述する + * @param target_ptr プレーヤーへの参照ポインタ + * @param ep_ptr プレーヤー効果構造体への参照ポインタ + * @param who_name モンスター名 + * @return なし + */ +static void describe_effect_source(player_type *target_ptr, effect_player_type *ep_ptr, concptr who_name) +{ + if (ep_ptr->who > 0) { + ep_ptr->m_ptr = &target_ptr->current_floor_ptr->m_list[ep_ptr->who]; + ep_ptr->rlev = (&r_info[ep_ptr->m_ptr->r_idx])->level >= 1 ? (&r_info[ep_ptr->m_ptr->r_idx])->level : 1; + monster_desc(target_ptr, ep_ptr->m_name, ep_ptr->m_ptr, 0); + strcpy(ep_ptr->killer, who_name); + return; + } + + switch (ep_ptr->who) { + case PROJECT_WHO_UNCTRL_POWER: + strcpy(ep_ptr->killer, _("制御できない力の氾流", "uncontrollable power storm")); + break; + case PROJECT_WHO_GLASS_SHARDS: + strcpy(ep_ptr->killer, _("ガラスの破片", "shards of glass")); + break; + default: + strcpy(ep_ptr->killer, _("ç½ ", "a trap")); + break; + } + + strcpy(ep_ptr->m_name, ep_ptr->killer); +} + +/*! + * @brief 汎用的なビーム/ボルト/ボール系によるプレイヤーへの効果処理 / Helper function for "project()" below. + * @param who 魔法を発動したモンスター(0ならばプレイヤー、負値ならば自然発生) / Index of "source" monster (zero for "player") + * @param who_name 効果を起こしたモンスターの名前 + * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball) + * @param y 目標Y座標 / Target y location (or location to travel "towards") + * @param x 目標X座標 / Target x location (or location to travel "towards") + * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player) + * @param effect_type 効果属性 / Type of damage to apply to monsters (and objects) + * @param flag 効果フラグ + * @param monspell 効果元のモンスター魔法ID + * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE + */ +bool affect_player(MONSTER_IDX who, player_type *target_ptr, concptr who_name, int r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID effect_type, + BIT_FLAGS flag, int monspell, project_func project) +{ + effect_player_type tmp_effect; + effect_player_type *ep_ptr = initialize_effect_player(&tmp_effect, who, dam, effect_type, flag, monspell); + ep_check_result check_result = check_continue_player_effect(target_ptr, ep_ptr, y, x, project); + if (check_result != EP_CHECK_CONTINUE) + return check_result; + + if (ep_ptr->dam > 1600) + ep_ptr->dam = 1600; + + ep_ptr->dam = (ep_ptr->dam + r) / (r + 1); + describe_effect_source(target_ptr, ep_ptr, who_name); + switch_effects_player(target_ptr, ep_ptr); + + revenge_store(target_ptr, ep_ptr->get_damage); + if ((target_ptr->tim_eyeeye || hex_spelling(target_ptr, HEX_EYE_FOR_EYE)) && (ep_ptr->get_damage > 0) && !target_ptr->is_dead && (ep_ptr->who > 0)) { + GAME_TEXT m_name_self[80]; + monster_desc(target_ptr, m_name_self, ep_ptr->m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE | MD_OBJECTIVE); + msg_format(_("攻撃が%s自身を傷つけた!", "The attack of %s has wounded %s!"), ep_ptr->m_name, m_name_self); + (*project)(target_ptr, 0, 0, ep_ptr->m_ptr->fy, ep_ptr->m_ptr->fx, ep_ptr->get_damage, GF_MISSILE, PROJECT_KILL, -1); + if (target_ptr->tim_eyeeye) + set_tim_eyeeye(target_ptr, target_ptr->tim_eyeeye - 5, TRUE); + } + + if (target_ptr->riding && ep_ptr->dam > 0) { + rakubadam_p = (ep_ptr->dam > 200) ? 200 : ep_ptr->dam; + } + + disturb(target_ptr, TRUE, TRUE); + if ((target_ptr->special_defense & NINJA_KAWARIMI) && ep_ptr->dam && ep_ptr->who && (ep_ptr->who != target_ptr->riding)) { + (void)kawarimi(target_ptr, FALSE); + } + + return TRUE; +} diff --git a/src/effect/effect-player.h b/src/effect/effect-player.h new file mode 100644 index 000000000..00735eb4c --- /dev/null +++ b/src/effect/effect-player.h @@ -0,0 +1,9 @@ +#pragma once + +#include "system/angband.h" + +typedef bool (*project_func)( + player_type *caster_ptr, MONSTER_IDX who, POSITION rad, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ, BIT_FLAGS flag, int monspell); + +bool affect_player(MONSTER_IDX who, player_type *target_ptr, concptr who_name, int r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ, BIT_FLAGS flag, + int monspell, project_func project); diff --git a/src/effect/effect-processor.c b/src/effect/effect-processor.c new file mode 100644 index 000000000..5d4a400ac --- /dev/null +++ b/src/effect/effect-processor.c @@ -0,0 +1,793 @@ +#include "effect/effect-processor.h" +#include "core/stuff-handler.h" +#include "effect/effect-characteristics.h" +#include "effect/effect-feature.h" +#include "effect/effect-item.h" +#include "effect/effect-monster.h" +#include "effect/effect-player.h" +#include "effect/spells-effect-util.h" +#include "floor/cave.h" +#include "floor/line-of-sight.h" +#include "game-option/special-options.h" +#include "grid/feature-flag-types.h" +#include "io/cursor.h" +#include "io/screen-util.h" +#include "main/sound-definitions-table.h" +#include "main/sound-of-music.h" +#include "monster-race/monster-race.h" +#include "monster-race/race-flags2.h" +#include "monster-race/race-indice-types.h" +#include "monster/monster-describer.h" +#include "monster/monster-description-types.h" +#include "monster/monster-info.h" +#include "pet/pet-fall-off.h" +#include "spell/range-calc.h" +#include "spell/spell-types.h" +#include "system/floor-type-definition.h" +#include "target/projection-path-calculator.h" +#include "term/gameterm.h" +#include "util/bit-flags-calculator.h" +#include "view/display-messages.h" + +/*! + * @brief 配置した鏡リストの次を取得する / + * Get another mirror. for SEEKER + * @param next_y 次の鏡のy座標を返す参照ポインタ + * @param next_x 次の鏡のx座標を返す参照ポインタ + * @param cury 現在の鏡のy座標 + * @param curx 現在の鏡のx座標 + */ +static void next_mirror(player_type *creature_ptr, POSITION *next_y, POSITION *next_x, POSITION cury, POSITION curx) +{ + POSITION mirror_x[10], mirror_y[10]; /* 鏡はもっと少ない */ + int mirror_num = 0; /* 鏡の数 */ + for (POSITION x = 0; x < creature_ptr->current_floor_ptr->width; x++) { + for (POSITION y = 0; y < creature_ptr->current_floor_ptr->height; y++) { + if (is_mirror_grid(&creature_ptr->current_floor_ptr->grid_array[y][x])) { + mirror_y[mirror_num] = y; + mirror_x[mirror_num] = x; + mirror_num++; + } + } + } + + if (mirror_num) { + int num = randint0(mirror_num); + *next_y = mirror_y[num]; + *next_x = mirror_x[num]; + return; + } + + *next_y = cury + randint0(5) - 2; + *next_x = curx + randint0(5) - 2; +} + +/*! + * todo 似たような処理が山ほど並んでいる、何とかならないものか + * todo 引数にそのまま再代入していてカオスすぎる。直すのは簡単ではない + * @brief 汎用的なビーム/ボルト/ボール系処理のルーチン Generic + * "beam"/"bolt"/"ball" projection routine. + * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" + * monster (zero for "player") + * @param rad 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion + * (0 = beam/bolt, 1 to 9 = ball) + * @param y 目標Y座標 / Target y location (or location to travel "towards") + * @param x 目標X座標 / Target x location (or location to travel "towards") + * @param dam 基本威力 / Base damage roll to apply to affected monsters (or + * player) + * @param typ 効果属性 / Type of damage to apply to monsters (and objects) + * @param flag 効果フラグ / Extra bit flags (see PROJECT_xxxx) + * @param monspell 効果元のモンスター魔法ID + * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the + * projection were observed, else FALSE + */ +bool project(player_type *caster_ptr, const MONSTER_IDX who, POSITION rad, POSITION y, POSITION x, const HIT_POINT dam, const EFFECT_ID typ, BIT_FLAGS flag, + const int monspell) +{ + int dist; + POSITION y1; + POSITION x1; + POSITION y2; + POSITION x2; + POSITION y_saver; + POSITION x_saver; + int msec = delay_factor * delay_factor * delay_factor; + bool notice = FALSE; + bool visual = FALSE; + bool drawn = FALSE; + bool breath = FALSE; + bool blind = caster_ptr->blind != 0; + bool old_hide = FALSE; + int path_n = 0; + u16b path_g[512]; + int grids = 0; + POSITION gx[1024]; + POSITION gy[1024]; + POSITION gm[32]; + POSITION gm_rad = rad; + bool jump = FALSE; + GAME_TEXT who_name[MAX_NLEN]; + bool see_s_msg = TRUE; + who_name[0] = '\0'; + rakubadam_p = 0; + rakubadam_m = 0; + monster_target_y = caster_ptr->y; + monster_target_x = caster_ptr->x; + + if (flag & (PROJECT_JUMP)) { + x1 = x; + y1 = y; + flag &= ~(PROJECT_JUMP); + jump = TRUE; + } else if (who <= 0) { + x1 = caster_ptr->x; + y1 = caster_ptr->y; + } else if (who > 0) { + x1 = caster_ptr->current_floor_ptr->m_list[who].fx; + y1 = caster_ptr->current_floor_ptr->m_list[who].fy; + monster_desc(caster_ptr, who_name, &caster_ptr->current_floor_ptr->m_list[who], MD_WRONGDOER_NAME); + } else { + x1 = x; + y1 = y; + } + + y_saver = y1; + x_saver = x1; + y2 = y; + x2 = x; + + if (flag & (PROJECT_THRU)) { + if ((x1 == x2) && (y1 == y2)) { + flag &= ~(PROJECT_THRU); + } + } + + if (rad < 0) { + rad = 0 - rad; + breath = TRUE; + if (flag & PROJECT_HIDE) + old_hide = TRUE; + flag |= PROJECT_HIDE; + } + + for (dist = 0; dist < 32; dist++) + gm[dist] = 0; + + y = y1; + x = x1; + dist = 0; + if (flag & (PROJECT_BEAM)) { + gy[grids] = y; + gx[grids] = x; + grids++; + } + + switch (typ) { + case GF_LITE: + case GF_LITE_WEAK: + if (breath || (flag & PROJECT_BEAM)) + flag |= (PROJECT_LOS); + break; + case GF_DISINTEGRATE: + flag |= (PROJECT_GRID); + if (breath || (flag & PROJECT_BEAM)) + flag |= (PROJECT_DISI); + break; + } + + /* Calculate the projection path */ + path_n = projection_path(caster_ptr, path_g, (project_length ? project_length : get_max_range(caster_ptr)), y1, x1, y2, x2, flag); + handle_stuff(caster_ptr); + + if (typ == GF_SEEKER) { + int j; + int last_i = 0; + project_m_n = 0; + project_m_x = 0; + project_m_y = 0; + for (int i = 0; i < path_n; ++i) { + POSITION oy = y; + POSITION ox = x; + POSITION ny = get_grid_y(path_g[i]); + POSITION nx = get_grid_x(path_g[i]); + y = ny; + x = nx; + gy[grids] = y; + gx[grids] = x; + grids++; + + if (!blind && !(flag & (PROJECT_HIDE))) { + if (panel_contains(y, x) && player_has_los_bold(caster_ptr, y, x)) { + u16b p = bolt_pict(oy, ox, y, x, typ); + TERM_COLOR a = PICT_A(p); + SYMBOL_CODE c = PICT_C(p); + print_rel(caster_ptr, c, a, y, x); + move_cursor_relative(y, x); + term_fresh(); + term_xtra(TERM_XTRA_DELAY, msec); + lite_spot(caster_ptr, y, x); + term_fresh(); + if (flag & (PROJECT_BEAM)) { + p = bolt_pict(y, x, y, x, typ); + a = PICT_A(p); + c = PICT_C(p); + print_rel(caster_ptr, c, a, y, x); + } + + visual = TRUE; + } else if (visual) { + term_xtra(TERM_XTRA_DELAY, msec); + } + } + + if (affect_item(caster_ptr, 0, 0, y, x, dam, GF_SEEKER)) + notice = TRUE; + if (!is_mirror_grid(&caster_ptr->current_floor_ptr->grid_array[y][x])) + continue; + + monster_target_y = y; + monster_target_x = x; + remove_mirror(caster_ptr, y, x); + next_mirror(caster_ptr, &oy, &ox, y, x); + path_n = i + projection_path(caster_ptr, &(path_g[i + 1]), (project_length ? project_length : get_max_range(caster_ptr)), y, x, oy, ox, flag); + for (j = last_i; j <= i; j++) { + y = get_grid_y(path_g[j]); + x = get_grid_x(path_g[j]); + if (affect_monster(caster_ptr, 0, 0, y, x, dam, GF_SEEKER, flag, TRUE)) + notice = TRUE; + if (!who && (project_m_n == 1) && !jump && (caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx > 0)) { + monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx]; + if (m_ptr->ml) { + if (!caster_ptr->image) + monster_race_track(caster_ptr, m_ptr->ap_r_idx); + health_track(caster_ptr, caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx); + } + } + + (void)affect_feature(caster_ptr, 0, 0, y, x, dam, GF_SEEKER); + } + + last_i = i; + } + + for (int i = last_i; i < path_n; i++) { + POSITION py, px; + py = get_grid_y(path_g[i]); + px = get_grid_x(path_g[i]); + if (affect_monster(caster_ptr, 0, 0, py, px, dam, GF_SEEKER, flag, TRUE)) + notice = TRUE; + if (!who && (project_m_n == 1) && !jump) { + if (caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx > 0) { + monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx]; + + if (m_ptr->ml) { + if (!caster_ptr->image) + monster_race_track(caster_ptr, m_ptr->ap_r_idx); + health_track(caster_ptr, caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx); + } + } + } + + (void)affect_feature(caster_ptr, 0, 0, py, px, dam, GF_SEEKER); + } + + return notice; + } else if (typ == GF_SUPER_RAY) { + int j; + int second_step = 0; + project_m_n = 0; + project_m_x = 0; + project_m_y = 0; + for (int i = 0; i < path_n; ++i) { + POSITION oy = y; + POSITION ox = x; + POSITION ny = get_grid_y(path_g[i]); + POSITION nx = get_grid_x(path_g[i]); + y = ny; + x = nx; + gy[grids] = y; + gx[grids] = x; + grids++; + { + if (panel_contains(y, x) && player_has_los_bold(caster_ptr, y, x)) { + u16b p; + TERM_COLOR a; + SYMBOL_CODE c; + p = bolt_pict(oy, ox, y, x, typ); + a = PICT_A(p); + c = PICT_C(p); + print_rel(caster_ptr, c, a, y, x); + move_cursor_relative(y, x); + term_fresh(); + term_xtra(TERM_XTRA_DELAY, msec); + lite_spot(caster_ptr, y, x); + term_fresh(); + if (flag & (PROJECT_BEAM)) { + p = bolt_pict(y, x, y, x, typ); + a = PICT_A(p); + c = PICT_C(p); + print_rel(caster_ptr, c, a, y, x); + } + + visual = TRUE; + } else if (visual) { + term_xtra(TERM_XTRA_DELAY, msec); + } + } + + if (affect_item(caster_ptr, 0, 0, y, x, dam, GF_SUPER_RAY)) + notice = TRUE; + if (!cave_have_flag_bold(caster_ptr->current_floor_ptr, y, x, FF_PROJECT)) { + if (second_step) + continue; + break; + } + + if (is_mirror_grid(&caster_ptr->current_floor_ptr->grid_array[y][x]) && !second_step) { + monster_target_y = y; + monster_target_x = x; + remove_mirror(caster_ptr, y, x); + for (j = 0; j <= i; j++) { + y = get_grid_y(path_g[j]); + x = get_grid_x(path_g[j]); + (void)affect_feature(caster_ptr, 0, 0, y, x, dam, GF_SUPER_RAY); + } + + path_n = i; + second_step = i + 1; + path_n + += projection_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : get_max_range(caster_ptr)), y, x, y - 1, x - 1, flag); + path_n += projection_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : get_max_range(caster_ptr)), y, x, y - 1, x, flag); + path_n + += projection_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : get_max_range(caster_ptr)), y, x, y - 1, x + 1, flag); + path_n += projection_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : get_max_range(caster_ptr)), y, x, y, x - 1, flag); + path_n += projection_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : get_max_range(caster_ptr)), y, x, y, x + 1, flag); + path_n + += projection_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : get_max_range(caster_ptr)), y, x, y + 1, x - 1, flag); + path_n += projection_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : get_max_range(caster_ptr)), y, x, y + 1, x, flag); + path_n + += projection_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : get_max_range(caster_ptr)), y, x, y + 1, x + 1, flag); + } + } + + for (int i = 0; i < path_n; i++) { + POSITION py = get_grid_y(path_g[i]); + POSITION px = get_grid_x(path_g[i]); + (void)affect_monster(caster_ptr, 0, 0, py, px, dam, GF_SUPER_RAY, flag, TRUE); + if (!who && (project_m_n == 1) && !jump) { + if (caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx > 0) { + monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx]; + + if (m_ptr->ml) { + if (!caster_ptr->image) + monster_race_track(caster_ptr, m_ptr->ap_r_idx); + health_track(caster_ptr, caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx); + } + } + } + + (void)affect_feature(caster_ptr, 0, 0, py, px, dam, GF_SUPER_RAY); + } + + return notice; + } + + int k; + for (k = 0; k < path_n; ++k) { + POSITION oy = y; + POSITION ox = x; + POSITION ny = get_grid_y(path_g[k]); + POSITION nx = get_grid_x(path_g[k]); + if (flag & PROJECT_DISI) { + if (cave_stop_disintegration(caster_ptr->current_floor_ptr, ny, nx) && (rad > 0)) + break; + } else if (flag & PROJECT_LOS) { + if (!cave_los_bold(caster_ptr->current_floor_ptr, ny, nx) && (rad > 0)) + break; + } else { + if (!cave_have_flag_bold(caster_ptr->current_floor_ptr, ny, nx, FF_PROJECT) && (rad > 0)) + break; + } + + y = ny; + x = nx; + if (flag & (PROJECT_BEAM)) { + gy[grids] = y; + gx[grids] = x; + grids++; + } + + if (!blind && !(flag & (PROJECT_HIDE | PROJECT_FAST))) { + if (panel_contains(y, x) && player_has_los_bold(caster_ptr, y, x)) { + u16b p; + TERM_COLOR a; + SYMBOL_CODE c; + p = bolt_pict(oy, ox, y, x, typ); + a = PICT_A(p); + c = PICT_C(p); + print_rel(caster_ptr, c, a, y, x); + move_cursor_relative(y, x); + term_fresh(); + term_xtra(TERM_XTRA_DELAY, msec); + lite_spot(caster_ptr, y, x); + term_fresh(); + if (flag & (PROJECT_BEAM)) { + p = bolt_pict(y, x, y, x, typ); + a = PICT_A(p); + c = PICT_C(p); + print_rel(caster_ptr, c, a, y, x); + } + + visual = TRUE; + } else if (visual) { + term_xtra(TERM_XTRA_DELAY, msec); + } + } + } + + path_n = k; + POSITION by = y; + POSITION bx = x; + if (breath && !path_n) { + breath = FALSE; + gm_rad = rad; + if (!old_hide) { + flag &= ~(PROJECT_HIDE); + } + } + + gm[0] = 0; + gm[1] = grids; + dist = path_n; + int dist_hack = dist; + project_length = 0; + + /* If we found a "target", explode there */ + if (dist <= get_max_range(caster_ptr)) { + if ((flag & (PROJECT_BEAM)) && (grids > 0)) + grids--; + + /* + * Create a conical breath attack + * + * *** + * ******** + * D********@** + * ******** + * *** + */ + if (breath) { + flag &= ~(PROJECT_HIDE); + breath_shape(caster_ptr, path_g, dist, &grids, gx, gy, gm, &gm_rad, rad, y1, x1, by, bx, typ); + } else { + for (dist = 0; dist <= rad; dist++) { + for (y = by - dist; y <= by + dist; y++) { + for (x = bx - dist; x <= bx + dist; x++) { + if (!in_bounds2(caster_ptr->current_floor_ptr, y, x)) + continue; + if (distance(by, bx, y, x) != dist) + continue; + + switch (typ) { + case GF_LITE: + case GF_LITE_WEAK: + if (!los(caster_ptr, by, bx, y, x)) + continue; + break; + case GF_DISINTEGRATE: + if (!in_disintegration_range(caster_ptr->current_floor_ptr, by, bx, y, x)) + continue; + break; + default: + if (!projectable(caster_ptr, by, bx, y, x)) + continue; + break; + } + + gy[grids] = y; + gx[grids] = x; + grids++; + } + } + + gm[dist + 1] = grids; + } + } + } + + if (!grids) + return FALSE; + + if (!blind && !(flag & (PROJECT_HIDE))) { + for (int t = 0; t <= gm_rad; t++) { + for (int i = gm[t]; i < gm[t + 1]; i++) { + y = gy[i]; + x = gx[i]; + if (panel_contains(y, x) && player_has_los_bold(caster_ptr, y, x)) { + u16b p; + TERM_COLOR a; + SYMBOL_CODE c; + drawn = TRUE; + p = bolt_pict(y, x, y, x, typ); + a = PICT_A(p); + c = PICT_C(p); + print_rel(caster_ptr, c, a, y, x); + } + } + + move_cursor_relative(by, bx); + term_fresh(); + if (visual || drawn) { + term_xtra(TERM_XTRA_DELAY, msec); + } + } + + if (drawn) { + for (int i = 0; i < grids; i++) { + y = gy[i]; + x = gx[i]; + if (panel_contains(y, x) && player_has_los_bold(caster_ptr, y, x)) { + lite_spot(caster_ptr, y, x); + } + } + + move_cursor_relative(by, bx); + term_fresh(); + } + } + + update_creature(caster_ptr); + + if (flag & PROJECT_KILL) { + see_s_msg = (who > 0) ? is_seen(caster_ptr, &caster_ptr->current_floor_ptr->m_list[who]) + : (!who ? TRUE : (player_can_see_bold(caster_ptr, y1, x1) && projectable(caster_ptr, caster_ptr->y, caster_ptr->x, y1, x1))); + } + + if (flag & (PROJECT_GRID)) { + dist = 0; + for (int i = 0; i < grids; i++) { + if (gm[dist + 1] == i) + dist++; + y = gy[i]; + x = gx[i]; + if (breath) { + int d = dist_to_line(y, x, y1, x1, by, bx); + if (affect_feature(caster_ptr, who, d, y, x, dam, typ)) + notice = TRUE; + } else { + if (affect_feature(caster_ptr, who, dist, y, x, dam, typ)) + notice = TRUE; + } + } + } + + update_creature(caster_ptr); + if (flag & (PROJECT_ITEM)) { + dist = 0; + for (int i = 0; i < grids; i++) { + if (gm[dist + 1] == i) + dist++; + + y = gy[i]; + x = gx[i]; + if (breath) { + int d = dist_to_line(y, x, y1, x1, by, bx); + if (affect_item(caster_ptr, who, d, y, x, dam, typ)) + notice = TRUE; + } else { + if (affect_item(caster_ptr, who, dist, y, x, dam, typ)) + notice = TRUE; + } + } + } + + if (flag & (PROJECT_KILL)) { + project_m_n = 0; + project_m_x = 0; + project_m_y = 0; + dist = 0; + for (int i = 0; i < grids; i++) { + int effective_dist; + if (gm[dist + 1] == i) + dist++; + + y = gy[i]; + x = gx[i]; + if (grids <= 1) { + monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[caster_ptr->current_floor_ptr->grid_array[y][x].m_idx]; + monster_race *ref_ptr = &r_info[m_ptr->r_idx]; + if ((flag & PROJECT_REFLECTABLE) && caster_ptr->current_floor_ptr->grid_array[y][x].m_idx && (ref_ptr->flags2 & RF2_REFLECTING) + && ((caster_ptr->current_floor_ptr->grid_array[y][x].m_idx != caster_ptr->riding) || !(flag & PROJECT_PLAYER)) && (!who || dist_hack > 1) + && !one_in_(10)) { + POSITION t_y, t_x; + int max_attempts = 10; + do { + t_y = y_saver - 1 + randint1(3); + t_x = x_saver - 1 + randint1(3); + max_attempts--; + } while (max_attempts && in_bounds2u(caster_ptr->current_floor_ptr, t_y, t_x) && !projectable(caster_ptr, y, x, t_y, t_x)); + + if (max_attempts < 1) { + t_y = y_saver; + t_x = x_saver; + } + + sound(SOUND_REFLECT); + if (is_seen(caster_ptr, m_ptr)) { + if ((m_ptr->r_idx == MON_KENSHIROU) || (m_ptr->r_idx == MON_RAOU)) + msg_print(_("「北斗神拳奥義・二指真空把!」", "The attack bounces!")); + else if (m_ptr->r_idx == MON_DIO) + msg_print(_("ディオ・ブランドーは指一本で攻撃を弾き返した!", "The attack bounces!")); + else + msg_print(_("攻撃は跳ね返った!", "The attack bounces!")); + } + + if (is_original_ap_and_seen(caster_ptr, m_ptr)) + ref_ptr->r_flags2 |= RF2_REFLECTING; + + if (player_bold(caster_ptr, y, x) || one_in_(2)) + flag &= ~(PROJECT_PLAYER); + else + flag |= PROJECT_PLAYER; + + project(caster_ptr, caster_ptr->current_floor_ptr->grid_array[y][x].m_idx, 0, t_y, t_x, dam, typ, flag, monspell); + continue; + } + } + + /* Find the closest point in the blast */ + if (breath) { + effective_dist = dist_to_line(y, x, y1, x1, by, bx); + } else { + effective_dist = dist; + } + + if (caster_ptr->riding && player_bold(caster_ptr, y, x)) { + if (flag & PROJECT_PLAYER) { + if (flag & (PROJECT_BEAM | PROJECT_REFLECTABLE | PROJECT_AIMED)) { + /* + * A beam or bolt is well aimed + * at the PLAYER! + * So don't affects the mount. + */ + continue; + } else { + /* + * The spell is not well aimed, + * So partly affect the mount too. + */ + effective_dist++; + } + } + + /* + * This grid is the original target. + * Or aimed on your horse. + */ + else if (((y == y2) && (x == x2)) || (flag & PROJECT_AIMED)) { + /* Hit the mount with full damage */ + } + + /* + * Otherwise this grid is not the + * original target, it means that line + * of fire is obstructed by this + * monster. + */ + /* + * A beam or bolt will hit either + * player or mount. Choose randomly. + */ + else if (flag & (PROJECT_BEAM | PROJECT_REFLECTABLE)) { + if (one_in_(2)) { + /* Hit the mount with full damage */ + } else { + flag |= PROJECT_PLAYER; + continue; + } + } + + /* + * The spell is not well aimed, so + * partly affect both player and + * mount. + */ + else { + effective_dist++; + } + } + + if (affect_monster(caster_ptr, who, effective_dist, y, x, dam, typ, flag, see_s_msg)) + notice = TRUE; + } + + /* Player affected one monster (without "jumping") */ + if (!who && (project_m_n == 1) && !jump) { + x = project_m_x; + y = project_m_y; + if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx > 0) { + monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[caster_ptr->current_floor_ptr->grid_array[y][x].m_idx]; + + if (m_ptr->ml) { + if (!caster_ptr->image) + monster_race_track(caster_ptr, m_ptr->ap_r_idx); + health_track(caster_ptr, caster_ptr->current_floor_ptr->grid_array[y][x].m_idx); + } + } + } + } + + if (flag & (PROJECT_KILL)) { + dist = 0; + for (int i = 0; i < grids; i++) { + int effective_dist; + if (gm[dist + 1] == i) + dist++; + + y = gy[i]; + x = gx[i]; + if (!player_bold(caster_ptr, y, x)) + continue; + + /* Find the closest point in the blast */ + if (breath) { + effective_dist = dist_to_line(y, x, y1, x1, by, bx); + } else { + effective_dist = dist; + } + + if (caster_ptr->riding) { + if (flag & PROJECT_PLAYER) { + /* Hit the player with full damage */ + } + + /* + * Hack -- When this grid was not the + * original target, a beam or bolt + * would hit either player or mount, + * and should be choosen randomly. + * + * But already choosen to hit the + * mount at this point. + * + * Or aimed on your horse. + */ + else if (flag & (PROJECT_BEAM | PROJECT_REFLECTABLE | PROJECT_AIMED)) { + /* + * A beam or bolt is well aimed + * at the mount! + * So don't affects the player. + */ + continue; + } else { + /* + * The spell is not well aimed, + * So partly affect the player too. + */ + effective_dist++; + } + } + + if (affect_player(who, caster_ptr, who_name, effective_dist, y, x, dam, typ, flag, monspell, project)) + notice = TRUE; + } + } + + if (caster_ptr->riding) { + GAME_TEXT m_name[MAX_NLEN]; + monster_desc(caster_ptr, m_name, &caster_ptr->current_floor_ptr->m_list[caster_ptr->riding], 0); + if (rakubadam_m > 0) { + if (process_fall_off_horse(caster_ptr, rakubadam_m, FALSE)) { + msg_format(_("%^sに振り落とされた!", "%^s has thrown you off!"), m_name); + } + } + + if (caster_ptr->riding && rakubadam_p > 0) { + if (process_fall_off_horse(caster_ptr, rakubadam_p, FALSE)) { + msg_format(_("%^sから落ちてしまった!", "You have fallen from %s."), m_name); + } + } + } + + return (notice); +} diff --git a/src/effect/effect-processor.h b/src/effect/effect-processor.h new file mode 100644 index 000000000..ab2a9513c --- /dev/null +++ b/src/effect/effect-processor.h @@ -0,0 +1,6 @@ +#pragma once + +#include "system/angband.h" + +bool project(player_type *caster_ptr, const MONSTER_IDX who, POSITION rad, POSITION y, POSITION x, const HIT_POINT dam, const EFFECT_ID typ, BIT_FLAGS flag, + const int monspell); diff --git a/src/effect/spells-effect-util.c b/src/effect/spells-effect-util.c new file mode 100644 index 000000000..8a506d87b --- /dev/null +++ b/src/effect/spells-effect-util.c @@ -0,0 +1,19 @@ +#include "effect/spells-effect-util.h" + +int rakubadam_m; +int rakubadam_p; +bool sukekaku; + +int project_length = 0; + +int cap_mon; +int cap_mspeed; +HIT_POINT cap_hp; +HIT_POINT cap_maxhp; +STR_OFFSET cap_nickname; + +int project_m_n; +POSITION project_m_x; +POSITION project_m_y; +POSITION monster_target_x; +POSITION monster_target_y; diff --git a/src/effect/spells-effect-util.h b/src/effect/spells-effect-util.h new file mode 100644 index 000000000..ef61dc51c --- /dev/null +++ b/src/effect/spells-effect-util.h @@ -0,0 +1,21 @@ +#pragma once + +#include "system/angband.h" + +extern int rakubadam_m; /*!< 振り落とされた際のダメージ量 */ +extern int rakubadam_p; /*!< 落馬した際のダメージ量 */ + +extern int cap_mon; +extern int cap_mspeed; +extern HIT_POINT cap_hp; +extern HIT_POINT cap_maxhp; +extern STR_OFFSET cap_nickname; + +extern bool sukekaku; +extern int project_length; /*!< 投射の射程距離 */ + +extern int project_m_n; /*!< 魔法効果範囲内にいるモンスターの数 */ +extern POSITION project_m_x; /*!< 処理中のモンスターX座標 */ +extern POSITION project_m_y; /*!< 処理中のモンスターY座標 */ +extern POSITION monster_target_x; /*!< モンスターの攻撃目標X座標 */ +extern POSITION monster_target_y; /*!< モンスターの攻撃目標Y座標 */ diff --git a/src/effects.c b/src/effects.c deleted file mode 100644 index e12585251..000000000 --- a/src/effects.c +++ /dev/null @@ -1,4613 +0,0 @@ -/*! - * @file effects.c - * @brief プレイヤーのステータス管理 / effects of various "objects" - * @date 2014/01/01 - * @author - * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n - *\n - * This software may be copied and distributed for educational, research,\n - * and not for profit purposes provided that this copyright and statement\n - * are included in all such copies. Other copyrights may also apply.\n - *\n - * 2013 Deskull rearranged comment for Doxygen.\n - */ - -#include "angband.h" -#include "mutation.h" -#include "quest.h" -#include "avatar.h" -#include "player-status.h" -#include "spells-status.h" -#include "realm-hex.h" -#include "object-hook.h" -#include "wild.h" -#include "spells-floor.h" -#include "player-move.h" - -/*! - * @brief プレイヤーの継続行動を設定する。 - * @param typ 継続行動のID\n - * #ACTION_NONE / #ACTION_SEARCH / #ACTION_REST / #ACTION_LEARN / #ACTION_FISH / #ACTION_KAMAE / #ACTION_KATA / #ACTION_SING / #ACTION_HAYAGAKE / #ACTION_SPELL から選択。 - * @return なし - */ -void set_action(ACTION_IDX typ) -{ - int prev_typ = p_ptr->action; - - if (typ == prev_typ) - { - return; - } - else - { - switch (prev_typ) - { - case ACTION_SEARCH: - { - msg_print(_("探索をやめた。", "You no longer walk carefully.")); - p_ptr->redraw |= (PR_SPEED); - break; - } - case ACTION_REST: - { - p_ptr->resting = 0; - break; - } - case ACTION_LEARN: - { - msg_print(_("学習をやめた。", "You stop Learning")); - new_mane = FALSE; - break; - } - case ACTION_KAMAE: - { - msg_print(_("構えをといた。", "You stop assuming the posture.")); - p_ptr->special_defense &= ~(KAMAE_MASK); - break; - } - case ACTION_KATA: - { - msg_print(_("型を崩した。", "You stop assuming the posture.")); - p_ptr->special_defense &= ~(KATA_MASK); - p_ptr->update |= (PU_MONSTERS); - p_ptr->redraw |= (PR_STATUS); - break; - } - case ACTION_SING: - { - msg_print(_("歌うのをやめた。", "You stop singing.")); - break; - } - case ACTION_HAYAGAKE: - { - msg_print(_("足が重くなった。", "You are no longer walking extremely fast.")); - take_turn(p_ptr, 100); - break; - } - case ACTION_SPELL: - { - msg_print(_("呪文の詠唱を中断した。", "You stopped spelling all spells.")); - break; - } - } - } - - p_ptr->action = typ; - - /* If we are requested other action, stop singing */ - if (prev_typ == ACTION_SING) stop_singing(p_ptr); - if (prev_typ == ACTION_SPELL) stop_hex_spell(); - - switch (p_ptr->action) - { - case ACTION_SEARCH: - { - msg_print(_("注意深く歩き始めた。", "You begin to walk carefully.")); - p_ptr->redraw |= (PR_SPEED); - break; - } - case ACTION_LEARN: - { - msg_print(_("学習を始めた。", "You begin Learning")); - break; - } - case ACTION_FISH: - { - msg_print(_("水面に糸を垂らした...", "You begin fishing...")); - break; - } - case ACTION_HAYAGAKE: - { - msg_print(_("足が羽のように軽くなった。", "You begin to walk extremely fast.")); - break; - } - default: - { - break; - } - } - p_ptr->update |= (PU_BONUS); - p_ptr->redraw |= (PR_STATE); -} - -/*! - * @brief プレイヤーの全ての時限効果をリセットする。 / reset timed flags - * @return なし - */ -void reset_tim_flags(void) -{ - p_ptr->fast = 0; /* Timed -- Fast */ - p_ptr->lightspeed = 0; - p_ptr->slow = 0; /* Timed -- Slow */ - p_ptr->blind = 0; /* Timed -- Blindness */ - p_ptr->paralyzed = 0; /* Timed -- Paralysis */ - p_ptr->confused = 0; /* Timed -- Confusion */ - p_ptr->afraid = 0; /* Timed -- Fear */ - p_ptr->image = 0; /* Timed -- Hallucination */ - p_ptr->poisoned = 0; /* Timed -- Poisoned */ - p_ptr->cut = 0; /* Timed -- Cut */ - p_ptr->stun = 0; /* Timed -- Stun */ - - p_ptr->protevil = 0; /* Timed -- Protection */ - p_ptr->invuln = 0; /* Timed -- Invulnerable */ - p_ptr->ult_res = 0; - p_ptr->hero = 0; /* Timed -- Heroism */ - p_ptr->shero = 0; /* Timed -- Super Heroism */ - p_ptr->shield = 0; /* Timed -- Shield Spell */ - p_ptr->blessed = 0; /* Timed -- Blessed */ - p_ptr->tim_invis = 0; /* Timed -- Invisibility */ - p_ptr->tim_infra = 0; /* Timed -- Infra Vision */ - p_ptr->tim_regen = 0; /* Timed -- Regeneration */ - p_ptr->tim_stealth = 0; /* Timed -- Stealth */ - p_ptr->tim_esp = 0; - p_ptr->wraith_form = 0; /* Timed -- Wraith Form */ - p_ptr->tim_levitation = 0; - p_ptr->tim_sh_touki = 0; - p_ptr->tim_sh_fire = 0; - p_ptr->tim_sh_holy = 0; - p_ptr->tim_eyeeye = 0; - p_ptr->magicdef = 0; - p_ptr->resist_magic = 0; - p_ptr->tsuyoshi = 0; - p_ptr->kabenuke = 0; - p_ptr->tim_res_nether = 0; - p_ptr->tim_res_time = 0; - p_ptr->tim_mimic = 0; - p_ptr->mimic_form = 0; - p_ptr->tim_reflect = 0; - p_ptr->multishadow = 0; - p_ptr->dustrobe = 0; - p_ptr->action = ACTION_NONE; - - p_ptr->oppose_acid = 0; /* Timed -- oppose acid */ - p_ptr->oppose_elec = 0; /* Timed -- oppose lightning */ - p_ptr->oppose_fire = 0; /* Timed -- oppose heat */ - p_ptr->oppose_cold = 0; /* Timed -- oppose cold */ - p_ptr->oppose_pois = 0; /* Timed -- oppose poison */ - - p_ptr->word_recall = 0; - p_ptr->alter_reality = 0; - p_ptr->sutemi = FALSE; - p_ptr->counter = FALSE; - p_ptr->ele_attack = 0; - p_ptr->ele_immune = 0; - p_ptr->special_attack = 0L; - p_ptr->special_defense = 0L; - - while(p_ptr->energy_need < 0) p_ptr->energy_need += ENERGY_NEED(); - p_ptr->timewalk = FALSE; - - if (prace_is_(RACE_DEMON) && (p_ptr->lev > 44)) p_ptr->oppose_fire = 1; - if ((p_ptr->pclass == CLASS_NINJA) && (p_ptr->lev > 44)) p_ptr->oppose_pois = 1; - if (p_ptr->pclass == CLASS_BERSERKER) p_ptr->shero = 1; - - if (p_ptr->riding) - { - (void)set_monster_fast(p_ptr->riding, 0); - (void)set_monster_slow(p_ptr->riding, 0); - (void)set_monster_invulner(p_ptr->riding, 0, FALSE); - } - - if (p_ptr->pclass == CLASS_BARD) - { - SINGING_SONG_EFFECT(p_ptr) = 0; - SINGING_SONG_ID(p_ptr) = 0; - } -} - -/*! - * @brief プレイヤーに魔力消去効果を与える。 - * @return なし - */ -void dispel_player(void) -{ - (void)set_fast(0, TRUE); - (void)set_lightspeed(0, TRUE); - (void)set_slow(0, TRUE); - (void)set_shield(0, TRUE); - (void)set_blessed(0, TRUE); - (void)set_tsuyoshi(0, TRUE); - (void)set_hero(0, TRUE); - (void)set_shero(0, TRUE); - (void)set_protevil(0, TRUE); - (void)set_invuln(0, TRUE); - (void)set_wraith_form(0, TRUE); - (void)set_kabenuke(0, TRUE); - (void)set_tim_res_nether(0, TRUE); - (void)set_tim_res_time(0, TRUE); - /* by henkma */ - (void)set_tim_reflect(0,TRUE); - (void)set_multishadow(0,TRUE); - (void)set_dustrobe(0,TRUE); - - (void)set_tim_invis(0, TRUE); - (void)set_tim_infra(0, TRUE); - (void)set_tim_esp(0, TRUE); - (void)set_tim_regen(0, TRUE); - (void)set_tim_stealth(0, TRUE); - (void)set_tim_levitation(0, TRUE); - (void)set_tim_sh_touki(0, TRUE); - (void)set_tim_sh_fire(0, TRUE); - (void)set_tim_sh_holy(0, TRUE); - (void)set_tim_eyeeye(0, TRUE); - (void)set_magicdef(0, TRUE); - (void)set_resist_magic(0, TRUE); - (void)set_oppose_acid(0, TRUE); - (void)set_oppose_elec(0, TRUE); - (void)set_oppose_fire(0, TRUE); - (void)set_oppose_cold(0, TRUE); - (void)set_oppose_pois(0, TRUE); - (void)set_ultimate_res(0, TRUE); - (void)set_mimic(0, 0, TRUE); - (void)set_ele_attack(0, 0); - (void)set_ele_immune(0, 0); - - /* Cancel glowing hands */ - if (p_ptr->special_attack & ATTACK_CONFUSE) - { - p_ptr->special_attack &= ~(ATTACK_CONFUSE); - msg_print(_("手の輝きがなくなった。", "Your hands stop glowing.")); - } - - if (music_singing_any() || hex_spelling_any()) - { - concptr str = (music_singing_any()) ? _("歌", "singing") : _("呪文", "spelling"); - INTERUPTING_SONG_EFFECT(p_ptr) = SINGING_SONG_EFFECT(p_ptr); - SINGING_SONG_EFFECT(p_ptr) = MUSIC_NONE; - msg_format(_("%sが途切れた。", "Your %s is interrupted."), str); - - p_ptr->action = ACTION_NONE; - p_ptr->update |= (PU_BONUS | PU_HP | PU_MONSTERS); - p_ptr->redraw |= (PR_MAP | PR_STATUS | PR_STATE); - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); - p_ptr->energy_need += ENERGY_NEED(); - } -} - - -/*! - * @brief 変身効果の継続時間と変身先をセットする / Set "p_ptr->tim_mimic", and "p_ptr->mimic_form", notice observable changes - * @param v 継続時間 - * @param p 変身内容 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_mimic(TIME_EFFECT v, IDX p, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_mimic && (p_ptr->mimic_form == p) && !do_dec) - { - if (p_ptr->tim_mimic > v) return FALSE; - } - else if ((!p_ptr->tim_mimic) || (p_ptr->mimic_form != p)) - { - msg_print(_("自分の体が変わってゆくのを感じた。", "You feel that your body changes.")); - p_ptr->mimic_form = p; - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_mimic) - { - msg_print(_("変身が解けた。", "You are no longer transformed.")); - if (p_ptr->mimic_form == MIMIC_DEMON) set_oppose_fire(0, TRUE); - p_ptr->mimic_form=0; - notice = TRUE; - p = 0; - } - } - - /* Use the value */ - p_ptr->tim_mimic = v; - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, TRUE); - - p_ptr->redraw |= (PR_BASIC | PR_STATUS); - p_ptr->update |= (PU_BONUS | PU_HP); - - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 盲目の継続時間をセットする / Set "p_ptr->blind", notice observable changes - * @param v 継続時間 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - * @details - * Note the use of "PU_UN_LITE" and "PU_UN_VIEW", which is needed to\n - * memorize any terrain features which suddenly become "visible".\n - * Note that blindness is currently the only thing which can affect\n - * "player_can_see_bold()".\n - */ -bool set_blind(TIME_EFFECT v) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (!p_ptr->blind) - { - if (p_ptr->prace == RACE_ANDROID) - { - msg_print(_("センサーをやられた!", "You are blind!")); - } - else - { - msg_print(_("目が見えなくなってしまった!", "You are blind!")); - } - - notice = TRUE; - chg_virtue(V_ENLIGHTEN, -1); - } - } - - /* Shut */ - else - { - if (p_ptr->blind) - { - if (p_ptr->prace == RACE_ANDROID) - { - msg_print(_("センサーが復旧した。", "You can see again.")); - } - else - { - msg_print(_("やっと目が見えるようになった。", "You can see again.")); - } - - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->blind = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - if (disturb_state) disturb(FALSE, FALSE); - - /* Fully update the visuals */ - p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_MONSTERS | PU_MON_LITE); - p_ptr->redraw |= (PR_MAP); - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); - handle_stuff(); - return (TRUE); -} - - -/*! - * @brief 混乱の継続時間をセットする / Set "p_ptr->confused", notice observable changes - * @param v 継続時間 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_confused(TIME_EFFECT v) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (!p_ptr->confused) - { - msg_print(_("あなたは混乱した!", "You are confused!")); - - if (p_ptr->action == ACTION_LEARN) - { - msg_print(_("学習が続けられない!", "You cannot continue Learning!")); - new_mane = FALSE; - - p_ptr->redraw |= (PR_STATE); - p_ptr->action = ACTION_NONE; - } - if (p_ptr->action == ACTION_KAMAE) - { - msg_print(_("構えがとけた。", "Your posture gets loose.")); - p_ptr->special_defense &= ~(KAMAE_MASK); - p_ptr->update |= (PU_BONUS); - p_ptr->redraw |= (PR_STATE); - p_ptr->action = ACTION_NONE; - } - else if (p_ptr->action == ACTION_KATA) - { - msg_print(_("型が崩れた。", "Your posture gets loose.")); - p_ptr->special_defense &= ~(KATA_MASK); - p_ptr->update |= (PU_BONUS); - p_ptr->update |= (PU_MONSTERS); - p_ptr->redraw |= (PR_STATE); - p_ptr->redraw |= (PR_STATUS); - p_ptr->action = ACTION_NONE; - } - - /* Sniper */ - if (p_ptr->concent) reset_concentration(TRUE); - - /* Hex */ - if (hex_spelling_any()) stop_hex_spell_all(); - - notice = TRUE; - p_ptr->counter = FALSE; - chg_virtue(V_HARMONY, -1); - } - } - - /* Shut */ - else - { - if (p_ptr->confused) - { - msg_print(_("やっと混乱がおさまった。", "You feel less confused now.")); - p_ptr->special_attack &= ~(ATTACK_SUIKEN); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->confused = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - handle_stuff(); - return (TRUE); -} - - -/*! - * @brief 毒の継続時間をセットする / Set "p_ptr->poisoned", notice observable changes - * @param v 継続時間 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_poisoned(TIME_EFFECT v) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (!p_ptr->poisoned) - { - msg_print(_("毒に侵されてしまった!", "You are poisoned!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->poisoned) - { - msg_print(_("やっと毒の痛みがなくなった。", "You are no longer poisoned.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->poisoned = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - handle_stuff(); - return (TRUE); -} - - -/*! - * @brief 恐怖の継続時間をセットする / Set "p_ptr->afraid", notice observable changes - * @param v 継続時間 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_afraid(TIME_EFFECT v) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (!p_ptr->afraid) - { - msg_print(_("何もかも恐くなってきた!", "You are terrified!")); - - if (p_ptr->special_defense & KATA_MASK) - { - msg_print(_("型が崩れた。", "Your posture gets loose.")); - p_ptr->special_defense &= ~(KATA_MASK); - p_ptr->update |= (PU_BONUS); - p_ptr->update |= (PU_MONSTERS); - p_ptr->redraw |= (PR_STATE); - p_ptr->redraw |= (PR_STATUS); - p_ptr->action = ACTION_NONE; - } - - notice = TRUE; - p_ptr->counter = FALSE; - chg_virtue(V_VALOUR, -1); - } - } - - /* Shut */ - else - { - if (p_ptr->afraid) - { - msg_print(_("やっと恐怖を振り払った。", "You feel bolder now.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->afraid = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 麻痺の継続時間をセットする / Set "p_ptr->paralyzed", notice observable changes - * @param v 継続時間 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_paralyzed(TIME_EFFECT v) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (!p_ptr->paralyzed) - { - msg_print(_("体が麻痺してしまった!", "You are paralyzed!")); - /* Sniper */ - if (p_ptr->concent) reset_concentration(TRUE); - - /* Hex */ - if (hex_spelling_any()) stop_hex_spell_all(); - - p_ptr->counter = FALSE; - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->paralyzed) - { - msg_print(_("やっと動けるようになった。", "You can move again.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->paralyzed = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->redraw |= (PR_STATE); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 幻覚の継続時間をセットする / Set "p_ptr->image", notice observable changes - * @param v 継続時間 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - * @details Note that we must redraw the map when hallucination changes. - */ -bool set_image(TIME_EFFECT v) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - if (p_ptr->pseikaku == SEIKAKU_CHARGEMAN) v = 0; - - - /* Open */ - if (v) - { - set_tsuyoshi(0, TRUE); - if (!p_ptr->image) - { - msg_print(_("ワーオ!何もかも虹色に見える!", "Oh, wow! Everything looks so cosmic now!")); - - /* Sniper */ - if (p_ptr->concent) reset_concentration(TRUE); - - p_ptr->counter = FALSE; - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->image) - { - msg_print(_("やっとはっきりと物が見えるようになった。", "You can see clearly again.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->image = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, TRUE); - - p_ptr->redraw |= (PR_MAP | PR_HEALTH | PR_UHEALTH); - p_ptr->update |= (PU_MONSTERS); - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 加速の継続時間をセットする / Set "p_ptr->fast", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_fast(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->fast && !do_dec) - { - if (p_ptr->fast > v) return FALSE; - } - else if (!IS_FAST() && !p_ptr->lightspeed) - { - msg_print(_("素早く動けるようになった!", "You feel yourself moving much faster!")); - notice = TRUE; - chg_virtue(V_PATIENCE, -1); - chg_virtue(V_DILIGENCE, 1); - } - } - - /* Shut */ - else - { - if (p_ptr->fast && !p_ptr->lightspeed && !music_singing(MUSIC_SPEED) && !music_singing(MUSIC_SHERO)) - { - msg_print(_("動きの素早さがなくなったようだ。", "You feel yourself slow down.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->fast = v; - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 光速移動の継続時間をセットする / Set "p_ptr->lightspeed", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_lightspeed(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - if (p_ptr->wild_mode) v = 0; - - /* Open */ - if (v) - { - if (p_ptr->lightspeed && !do_dec) - { - if (p_ptr->lightspeed > v) return FALSE; - } - else if (!p_ptr->lightspeed) - { - msg_print(_("非常に素早く動けるようになった!", "You feel yourself moving extremely faster!")); - notice = TRUE; - chg_virtue(V_PATIENCE, -1); - chg_virtue(V_DILIGENCE, 1); - } - } - - /* Shut */ - else - { - if (p_ptr->lightspeed) - { - msg_print(_("動きの素早さがなくなったようだ。", "You feel yourself slow down.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->lightspeed = v; - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 減速の継続時間をセットする / Set "p_ptr->slow", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_slow(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->slow && !do_dec) - { - if (p_ptr->slow > v) return FALSE; - } - else if (!p_ptr->slow) - { - msg_print(_("体の動きが遅くなってしまった!", "You feel yourself moving slower!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->slow) - { - msg_print(_("動きの遅さがなくなったようだ。", "You feel yourself speed up.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->slow = v; - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - - -/*! - * @brief 肌石化の継続時間をセットする / Set "p_ptr->shield", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_shield(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->shield && !do_dec) - { - if (p_ptr->shield > v) return FALSE; - } - else if (!p_ptr->shield) - { - msg_print(_("肌が石になった。", "Your skin turns to stone.")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->shield) - { - msg_print(_("肌が元に戻った。", "Your skin returns to normal.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->shield = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - - -/*! - * @brief つぶれるの継続時間をセットする / Set "p_ptr->tsubureru", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tsubureru(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tsubureru && !do_dec) - { - if (p_ptr->tsubureru > v) return FALSE; - } - else if (!p_ptr->tsubureru) - { - msg_print(_("横に伸びた。", "Your body expands horizontally.")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tsubureru) - { - msg_print(_("もう横に伸びていない。", "Your body returns to normal.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tsubureru = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - - -/*! - * @brief 魔法の鎧の継続時間をセットする / Set "p_ptr->magicdef", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_magicdef(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->magicdef && !do_dec) - { - if (p_ptr->magicdef > v) return FALSE; - } - else if (!p_ptr->magicdef) - { - msg_print(_("魔法の防御力が増したような気がする。", "You feel more resistant to magic.")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->magicdef) - { - msg_print(_("魔法の防御力が元に戻った。", "You feel less resistant to magic.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->magicdef = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 祝福の継続時間をセットする / Set "p_ptr->blessed", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_blessed(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->blessed && !do_dec) - { - if (p_ptr->blessed > v) return FALSE; - } - else if (!IS_BLESSED()) - { - msg_print(_("高潔な気分になった!", "You feel righteous!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->blessed && !music_singing(MUSIC_BLESS)) - { - msg_print(_("高潔な気分が消え失せた。", "The prayer has expired.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->blessed = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - - -/*! - * @brief 士気高揚の継続時間をセットする / Set "p_ptr->hero", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_hero(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->hero && !do_dec) - { - if (p_ptr->hero > v) return FALSE; - } - else if (!IS_HERO()) - { - msg_print(_("ヒーローになった気がする!", "You feel like a hero!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->hero && !music_singing(MUSIC_HERO) && !music_singing(MUSIC_SHERO)) - { - msg_print(_("ヒーローの気分が消え失せた。", "The heroism wears off.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->hero = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - - /* Recalculate hitpoints */ - p_ptr->update |= (PU_HP); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 狂戦士化の継続時間をセットする / Set "p_ptr->shero", notice observable changes - * @param v 継続時間/ 0ならば無条件にリセット - * @param do_dec FALSEの場合現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_shero(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - if (p_ptr->pclass == CLASS_BERSERKER) v = 1; - /* Open */ - if (v) - { - if (p_ptr->shero && !do_dec) - { - if (p_ptr->shero > v) return FALSE; - } - else if (!p_ptr->shero) - { - msg_print(_("殺戮マシーンになった気がする!", "You feel like a killing machine!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->shero) - { - msg_print(_("野蛮な気持ちが消え失せた。", "You feel less Berserk.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->shero = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - - /* Recalculate hitpoints */ - p_ptr->update |= (PU_HP); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 対邪悪結界の継続時間をセットする / Set "p_ptr->protevil", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_protevil(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->protevil && !do_dec) - { - if (p_ptr->protevil > v) return FALSE; - } - else if (!p_ptr->protevil) - { - msg_print(_("邪悪なる存在から守られているような感じがする!", "You feel safe from evil!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->protevil) - { - msg_print(_("邪悪なる存在から守られている感じがなくなった。", "You no longer feel safe from evil.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->protevil = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 幽体化の継続時間をセットする / Set "p_ptr->wraith_form", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_wraith_form(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->wraith_form && !do_dec) - { - if (p_ptr->wraith_form > v) return FALSE; - } - else if (!p_ptr->wraith_form) - { - msg_print(_("物質界を離れて幽鬼のような存在になった!", "You leave the physical world and current_world_ptr->game_turn into a wraith-being!")); - notice = TRUE; - chg_virtue(V_UNLIFE, 3); - chg_virtue(V_HONOUR, -2); - chg_virtue(V_SACRIFICE, -2); - chg_virtue(V_VALOUR, -5); - - p_ptr->redraw |= (PR_MAP); - p_ptr->update |= (PU_MONSTERS); - - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); - } - } - - /* Shut */ - else - { - if (p_ptr->wraith_form) - { - msg_print(_("不透明になった感じがする。", "You feel opaque.")); - notice = TRUE; - - p_ptr->redraw |= (PR_MAP); - p_ptr->update |= (PU_MONSTERS); - - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); - } - } - - /* Use the value */ - p_ptr->wraith_form = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); - -} - -/*! - * @brief 無傷球の継続時間をセットする / Set "p_ptr->invuln", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_invuln(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->invuln && !do_dec) - { - if (p_ptr->invuln > v) return FALSE; - } - else if (!IS_INVULN()) - { - msg_print(_("無敵だ!", "Invulnerability!")); - notice = TRUE; - - chg_virtue(V_UNLIFE, -2); - chg_virtue(V_HONOUR, -2); - chg_virtue(V_SACRIFICE, -3); - chg_virtue(V_VALOUR, -5); - - p_ptr->redraw |= (PR_MAP); - p_ptr->update |= (PU_MONSTERS); - - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); - } - } - - /* Shut */ - else - { - if (p_ptr->invuln && !music_singing(MUSIC_INVULN)) - { - msg_print(_("無敵ではなくなった。", "The invulnerability wears off.")); - notice = TRUE; - - p_ptr->redraw |= (PR_MAP); - p_ptr->update |= (PU_MONSTERS); - - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); - - p_ptr->energy_need += ENERGY_NEED(); - } - } - - /* Use the value */ - p_ptr->invuln = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 時限ESPの継続時間をセットする / Set "p_ptr->tim_esp", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tim_esp(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_esp && !do_dec) - { - if (p_ptr->tim_esp > v) return FALSE; - } - else if (!IS_TIM_ESP()) - { - msg_print(_("意識が広がった気がする!", "You feel your consciousness expand!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_esp && !music_singing(MUSIC_MIND)) - { - msg_print(_("意識は元に戻った。", "Your consciousness contracts again.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_esp = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - p_ptr->update |= (PU_MONSTERS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 時限透明視の継続時間をセットする / Set "p_ptr->tim_invis", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tim_invis(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_invis && !do_dec) - { - if (p_ptr->tim_invis > v) return FALSE; - } - else if (!p_ptr->tim_invis) - { - msg_print(_("目が非常に敏感になった気がする!", "Your eyes feel very sensitive!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_invis) - { - msg_print(_("目の敏感さがなくなったようだ。", "Your eyes feel less sensitive.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_invis = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - - /* Update the monsters */ - p_ptr->update |= (PU_MONSTERS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 時限赤外線視力の継続時間をセットする / Set "p_ptr->tim_infra", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tim_infra(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_infra && !do_dec) - { - if (p_ptr->tim_infra > v) return FALSE; - } - else if (!p_ptr->tim_infra) - { - msg_print(_("目がランランと輝き始めた!", "Your eyes begin to tingle!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_infra) - { - msg_print(_("目の輝きがなくなった。", "Your eyes stop tingling.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_infra = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - - /* Update the monsters */ - p_ptr->update |= (PU_MONSTERS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 時限急回復の継続時間をセットする / Set "p_ptr->tim_regen", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tim_regen(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_regen && !do_dec) - { - if (p_ptr->tim_regen > v) return FALSE; - } - else if (!p_ptr->tim_regen) - { - msg_print(_("回復力が上がった!", "You feel yourself regenerating quickly!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_regen) - { - msg_print(_("素早く回復する感じがなくなった。", "You feel yourself regenerating slowly.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_regen = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 隠密の歌の継続時間をセットする / Set "p_ptr->tim_stealth", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tim_stealth(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_stealth && !do_dec) - { - if (p_ptr->tim_stealth > v) return FALSE; - } - else if (!IS_TIM_STEALTH()) - { - msg_print(_("足音が小さくなった!", "You begin to walk silently!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_stealth && !music_singing(MUSIC_STEALTH)) - { - msg_print(_("足音が大きくなった。", "You no longer walk silently.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_stealth = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 超隠密状態をセットする - * @param set TRUEならば超隠密状態になる。 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_superstealth(bool set) -{ - bool notice = FALSE; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (set) - { - if (!(p_ptr->special_defense & NINJA_S_STEALTH)) - { - if (current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].info & CAVE_MNLT) - { - msg_print(_("敵の目から薄い影の中に覆い隠された。", "You are mantled in weak shadow from ordinary eyes.")); - p_ptr->monlite = p_ptr->old_monlite = TRUE; - } - else - { - msg_print(_("敵の目から影の中に覆い隠された!", "You are mantled in shadow from ordinary eyes!")); - p_ptr->monlite = p_ptr->old_monlite = FALSE; - } - - notice = TRUE; - - /* Use the value */ - p_ptr->special_defense |= NINJA_S_STEALTH; - } - } - - /* Shut */ - else - { - if (p_ptr->special_defense & NINJA_S_STEALTH) - { - msg_print(_("再び敵の目にさらされるようになった。", "You are exposed to common sight once more.")); - notice = TRUE; - - /* Use the value */ - p_ptr->special_defense &= ~(NINJA_S_STEALTH); - } - } - - /* Nothing to notice */ - if (!notice) return (FALSE); - p_ptr->redraw |= (PR_STATUS); - - if (disturb_state) disturb(FALSE, FALSE); - return (TRUE); -} - -/*! - * @brief 一時的浮遊の継続時間をセットする / Set "p_ptr->tim_levitation", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tim_levitation(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_levitation && !do_dec) - { - if (p_ptr->tim_levitation > v) return FALSE; - } - else if (!p_ptr->tim_levitation) - { - msg_print(_("体が宙に浮き始めた。", "You begin to fly!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_levitation) - { - msg_print(_("もう宙に浮かべなくなった。", "You stop flying.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_levitation = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 一時的闘気のオーラの継続時間をセットする / Set "p_ptr->tim_sh_touki", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tim_sh_touki(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_sh_touki && !do_dec) - { - if (p_ptr->tim_sh_touki > v) return FALSE; - } - else if (!p_ptr->tim_sh_touki) - { - msg_print(_("体が闘気のオーラで覆われた。", "You have enveloped by the aura of the Force!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_sh_touki) - { - msg_print(_("闘気が消えた。", "Aura of the Force disappeared.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_sh_touki = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 一時的火炎のオーラの継続時間をセットする / Set "p_ptr->tim_sh_fire", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tim_sh_fire(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_sh_fire && !do_dec) - { - if (p_ptr->tim_sh_fire > v) return FALSE; - } - else if (!p_ptr->tim_sh_fire) - { - msg_print(_("体が炎のオーラで覆われた。", "You have enveloped by fiery aura!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_sh_fire) - { - msg_print(_("炎のオーラが消えた。", "Fiery aura disappeared.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_sh_fire = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 一時的聖なるのオーラの継続時間をセットする / Set "p_ptr->tim_sh_holy", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tim_sh_holy(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_sh_holy && !do_dec) - { - if (p_ptr->tim_sh_holy > v) return FALSE; - } - else if (!p_ptr->tim_sh_holy) - { - msg_print(_("体が聖なるオーラで覆われた。", "You have enveloped by holy aura!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_sh_holy) - { - msg_print(_("聖なるオーラが消えた。", "Holy aura disappeared.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_sh_holy = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 目には目をの残り時間をセットする / Set "p_ptr->tim_eyeeye", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tim_eyeeye(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_eyeeye && !do_dec) - { - if (p_ptr->tim_eyeeye > v) return FALSE; - } - else if (!p_ptr->tim_eyeeye) - { - msg_print(_("法の守り手になった気がした!", "You feel like a keeper of commandments!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_eyeeye) - { - msg_print(_("懲罰を執行することができなくなった。", "You no longer feel like a keeper.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_eyeeye = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - - -/*! - * @brief 一時的魔法防御の継続時間をセットする / Set "p_ptr->resist_magic", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_resist_magic(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->resist_magic && !do_dec) - { - if (p_ptr->resist_magic > v) return FALSE; - } - else if (!p_ptr->resist_magic) - { - msg_print(_("魔法への耐性がついた。", "You have been protected from magic!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->resist_magic) - { - msg_print(_("魔法に弱くなった。", "You are no longer protected from magic.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->resist_magic = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 一時的反射の継続時間をセットする / Set "p_ptr->tim_reflect", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tim_reflect(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_reflect && !do_dec) - { - if (p_ptr->tim_reflect > v) return FALSE; - } - else if (!p_ptr->tim_reflect) - { - msg_print(_("体の表面が滑かになった気がする。", "Your body becames smooth.")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_reflect) - { - msg_print(_("体の表面が滑かでなくなった。", "Your body is no longer smooth.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_reflect = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - - -/* - * Set "p_ptr->multishadow", notice observable changes - */ -bool set_multishadow(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->multishadow && !do_dec) - { - if (p_ptr->multishadow > v) return FALSE; - } - else if (!p_ptr->multishadow) - { - msg_print(_("あなたの周りに幻影が生まれた。", "Your Shadow enveloped you.")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->multishadow) - { - msg_print(_("幻影が消えた。", "Your Shadow disappears.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->multishadow = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 一時的破片のオーラの継続時間をセットする / Set "p_ptr->dustrobe", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_dustrobe(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->dustrobe && !do_dec) - { - if (p_ptr->dustrobe > v) return FALSE; - } - else if (!p_ptr->dustrobe) - { - msg_print(_("体が鏡のオーラで覆われた。", "You were enveloped by mirror shards.")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->dustrobe) - { - msg_print(_("鏡のオーラが消えた。", "The mirror shards disappear.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->dustrobe = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 一時的壁抜けの継続時間をセットする / Set "p_ptr->kabenuke", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_kabenuke(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->kabenuke && !do_dec) - { - if (p_ptr->kabenuke > v) return FALSE; - } - else if (!p_ptr->kabenuke) - { - msg_print(_("体が半物質の状態になった。", "You became ethereal form.")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->kabenuke) - { - msg_print(_("体が物質化した。", "You are no longer in an ethereal form.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->kabenuke = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief オクレ兄さんの継続時間をセットする / Set "p_ptr->tsuyoshi", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_tsuyoshi(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tsuyoshi && !do_dec) - { - if (p_ptr->tsuyoshi > v) return FALSE; - } - else if (!p_ptr->tsuyoshi) - { - msg_print(_("「オクレ兄さん!」", "Brother OKURE!")); - notice = TRUE; - chg_virtue(V_VITALITY, 2); - } - } - - /* Shut */ - else - { - if (p_ptr->tsuyoshi) - { - msg_print(_("肉体が急速にしぼんでいった。", "Your body had quickly shriveled.")); - - (void)dec_stat(A_CON, 20, TRUE); - (void)dec_stat(A_STR, 20, TRUE); - - notice = TRUE; - chg_virtue(V_VITALITY, -3); - } - } - - /* Use the value */ - p_ptr->tsuyoshi = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - - /* Recalculate hitpoints */ - p_ptr->update |= (PU_HP); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 一時的元素スレイの継続時間をセットする / Set a temporary elemental brand. Clear all other brands. Print status messages. -LM- - * @param attack_type スレイのタイプID - * @param v 継続時間 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_ele_attack(u32b attack_type, TIME_EFFECT v) -{ - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - /* Clear all elemental attacks (only one is allowed at a time). */ - if ((p_ptr->special_attack & (ATTACK_ACID)) && (attack_type != ATTACK_ACID)) - { - p_ptr->special_attack &= ~(ATTACK_ACID); - msg_print(_("酸で攻撃できなくなった。", "Your temporary acidic brand fades away.")); - } - if ((p_ptr->special_attack & (ATTACK_ELEC)) && (attack_type != ATTACK_ELEC)) - { - p_ptr->special_attack &= ~(ATTACK_ELEC); - msg_print(_("電撃で攻撃できなくなった。", "Your temporary electrical brand fades away.")); - } - if ((p_ptr->special_attack & (ATTACK_FIRE)) && (attack_type != ATTACK_FIRE)) - { - p_ptr->special_attack &= ~(ATTACK_FIRE); - msg_print(_("火炎で攻撃できなくなった。", "Your temporary fiery brand fades away.")); - } - if ((p_ptr->special_attack & (ATTACK_COLD)) && (attack_type != ATTACK_COLD)) - { - p_ptr->special_attack &= ~(ATTACK_COLD); - msg_print(_("冷気で攻撃できなくなった。", "Your temporary frost brand fades away.")); - } - if ((p_ptr->special_attack & (ATTACK_POIS)) && (attack_type != ATTACK_POIS)) - { - p_ptr->special_attack &= ~(ATTACK_POIS); - msg_print(_("毒で攻撃できなくなった。", "Your temporary poison brand fades away.")); - } - - if ((v) && (attack_type)) - { - /* Set attack type. */ - p_ptr->special_attack |= (attack_type); - - /* Set duration. */ - p_ptr->ele_attack = v; - -#ifdef JP - msg_format("%sで攻撃できるようになった!", - ((attack_type == ATTACK_ACID) ? "酸" : - ((attack_type == ATTACK_ELEC) ? "電撃" : - ((attack_type == ATTACK_FIRE) ? "火炎" : - ((attack_type == ATTACK_COLD) ? "冷気" : - ((attack_type == ATTACK_POIS) ? "毒" : - "(なし)")))))); -#else - msg_format("For a while, the blows you deal will %s", - ((attack_type == ATTACK_ACID) ? "melt with acid!" : - ((attack_type == ATTACK_ELEC) ? "shock your foes!" : - ((attack_type == ATTACK_FIRE) ? "burn with fire!" : - ((attack_type == ATTACK_COLD) ? "chill to the bone!" : - ((attack_type == ATTACK_POIS) ? "poison your enemies!" : - "do nothing special.")))))); -#endif - } - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->redraw |= (PR_STATUS); - - p_ptr->update |= (PU_BONUS); - handle_stuff(); - - return (TRUE); -} - -/*! - * @brief 一時的元素免疫の継続時間をセットする / Set a temporary elemental brand. Clear all other brands. Print status messages. -LM- - * @param immune_type 免疫のタイプID - * @param v 継続時間 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_ele_immune(u32b immune_type, TIME_EFFECT v) -{ - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - /* Clear all elemental attacks (only one is allowed at a time). */ - if ((p_ptr->special_defense & (DEFENSE_ACID)) && (immune_type != DEFENSE_ACID)) - { - p_ptr->special_defense &= ~(DEFENSE_ACID); - msg_print(_("酸の攻撃で傷つけられるようになった。。", "You are no longer immune to acid.")); - } - if ((p_ptr->special_defense & (DEFENSE_ELEC)) && (immune_type != DEFENSE_ELEC)) - { - p_ptr->special_defense &= ~(DEFENSE_ELEC); - msg_print(_("電撃の攻撃で傷つけられるようになった。。", "You are no longer immune to electricity.")); - } - if ((p_ptr->special_defense & (DEFENSE_FIRE)) && (immune_type != DEFENSE_FIRE)) - { - p_ptr->special_defense &= ~(DEFENSE_FIRE); - msg_print(_("火炎の攻撃で傷つけられるようになった。。", "You are no longer immune to fire.")); - } - if ((p_ptr->special_defense & (DEFENSE_COLD)) && (immune_type != DEFENSE_COLD)) - { - p_ptr->special_defense &= ~(DEFENSE_COLD); - msg_print(_("冷気の攻撃で傷つけられるようになった。。", "You are no longer immune to cold.")); - } - if ((p_ptr->special_defense & (DEFENSE_POIS)) && (immune_type != DEFENSE_POIS)) - { - p_ptr->special_defense &= ~(DEFENSE_POIS); - msg_print(_("毒の攻撃で傷つけられるようになった。。", "You are no longer immune to poison.")); - } - - if ((v) && (immune_type)) - { - /* Set attack type. */ - p_ptr->special_defense |= (immune_type); - - /* Set duration. */ - p_ptr->ele_immune = v; - - msg_format(_("%sの攻撃を受けつけなくなった!", "For a while, You are immune to %s"), - ((immune_type == DEFENSE_ACID) ? _("酸", "acid!") : - ((immune_type == DEFENSE_ELEC) ? _("電撃", "electricity!") : - ((immune_type == DEFENSE_FIRE) ? _("火炎", "fire!") : - ((immune_type == DEFENSE_COLD) ? _("冷気", "cold!") : - ((immune_type == DEFENSE_POIS) ? _("毒", "poison!") : - _("(なし)", "do nothing special."))))))); - } - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->redraw |= (PR_STATUS); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - - return (TRUE); -} - -/*! - * @brief 一時的酸耐性の継続時間をセットする / Set "p_ptr->oppose_acid", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_oppose_acid(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->oppose_acid && !do_dec) - { - if (p_ptr->oppose_acid > v) return FALSE; - } - else if (!IS_OPPOSE_ACID()) - { - msg_print(_("酸への耐性がついた気がする!", "You feel resistant to acid!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->oppose_acid && !music_singing(MUSIC_RESIST) && !(p_ptr->special_defense & KATA_MUSOU)) - { - msg_print(_("酸への耐性が薄れた気がする。", "You feel less resistant to acid.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->oppose_acid = v; - - /* Nothing to notice */ - if (!notice) return (FALSE); - p_ptr->redraw |= (PR_STATUS); - - if (disturb_state) disturb(FALSE, FALSE); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 一時的電撃耐性の継続時間をセットする / Set "p_ptr->oppose_elec", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_oppose_elec(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->oppose_elec && !do_dec) - { - if (p_ptr->oppose_elec > v) return FALSE; - } - else if (!IS_OPPOSE_ELEC()) - { - msg_print(_("電撃への耐性がついた気がする!", "You feel resistant to electricity!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->oppose_elec && !music_singing(MUSIC_RESIST) && !(p_ptr->special_defense & KATA_MUSOU)) - { - msg_print(_("電撃への耐性が薄れた気がする。", "You feel less resistant to electricity.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->oppose_elec = v; - - /* Nothing to notice */ - if (!notice) return (FALSE); - p_ptr->redraw |= (PR_STATUS); - - if (disturb_state) disturb(FALSE, FALSE); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 一時的火炎耐性の継続時間をセットする / Set "p_ptr->oppose_fire", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_oppose_fire(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - if ((prace_is_(RACE_DEMON) && (p_ptr->lev > 44)) || (p_ptr->mimic_form == MIMIC_DEMON)) v = 1; - /* Open */ - if (v) - { - if (p_ptr->oppose_fire && !do_dec) - { - if (p_ptr->oppose_fire > v) return FALSE; - } - else if (!IS_OPPOSE_FIRE()) - { - msg_print(_("火への耐性がついた気がする!", "You feel resistant to fire!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->oppose_fire && !music_singing(MUSIC_RESIST) && !(p_ptr->special_defense & KATA_MUSOU)) - { - msg_print(_("火への耐性が薄れた気がする。", "You feel less resistant to fire.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->oppose_fire = v; - - /* Nothing to notice */ - if (!notice) return (FALSE); - p_ptr->redraw |= (PR_STATUS); - - if (disturb_state) disturb(FALSE, FALSE); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 一時的冷気耐性の継続時間をセットする / Set "p_ptr->oppose_cold", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_oppose_cold(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->oppose_cold && !do_dec) - { - if (p_ptr->oppose_cold > v) return FALSE; - } - else if (!IS_OPPOSE_COLD()) - { - msg_print(_("冷気への耐性がついた気がする!", "You feel resistant to cold!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->oppose_cold && !music_singing(MUSIC_RESIST) && !(p_ptr->special_defense & KATA_MUSOU)) - { - msg_print(_("冷気への耐性が薄れた気がする。", "You feel less resistant to cold.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->oppose_cold = v; - - /* Nothing to notice */ - if (!notice) return (FALSE); - p_ptr->redraw |= (PR_STATUS); - - if (disturb_state) disturb(FALSE, FALSE); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 一時的毒耐性の継続時間をセットする / Set "p_ptr->oppose_pois", notice observable changes - * @param v 継続時間 - * @param do_dec 現在の継続時間より長い値のみ上書きする - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - */ -bool set_oppose_pois(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if ((p_ptr->pclass == CLASS_NINJA) && (p_ptr->lev > 44)) v = 1; - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->oppose_pois && !do_dec) - { - if (p_ptr->oppose_pois > v) return FALSE; - } - else if (!IS_OPPOSE_POIS()) - { - msg_print(_("毒への耐性がついた気がする!", "You feel resistant to poison!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->oppose_pois && !music_singing(MUSIC_RESIST) && !(p_ptr->special_defense & KATA_MUSOU)) - { - msg_print(_("毒への耐性が薄れた気がする。", "You feel less resistant to poison.")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->oppose_pois = v; - - /* Nothing to notice */ - if (!notice) return (FALSE); - p_ptr->redraw |= (PR_STATUS); - - if (disturb_state) disturb(FALSE, FALSE); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 朦朧の継続時間をセットする / Set "p_ptr->stun", notice observable changes - * @param v 継続時間 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - * @details - * Note the special code to only notice "range" changes. - */ -bool set_stun(TIME_EFFECT v) -{ - int old_aux, new_aux; - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - if (prace_is_(RACE_GOLEM) || ((p_ptr->pclass == CLASS_BERSERKER) && (p_ptr->lev > 34))) v = 0; - - /* Knocked out */ - if (p_ptr->stun > 100) - { - old_aux = 3; - } - - /* Heavy stun */ - else if (p_ptr->stun > 50) - { - old_aux = 2; - } - - /* Stun */ - else if (p_ptr->stun > 0) - { - old_aux = 1; - } - - /* None */ - else - { - old_aux = 0; - } - - /* Knocked out */ - if (v > 100) - { - new_aux = 3; - } - - /* Heavy stun */ - else if (v > 50) - { - new_aux = 2; - } - - /* Stun */ - else if (v > 0) - { - new_aux = 1; - } - - /* None */ - else - { - new_aux = 0; - } - - /* Increase cut */ - if (new_aux > old_aux) - { - /* Describe the state */ - switch (new_aux) - { - /* Stun */ - case 1: msg_print(_("意識がもうろうとしてきた。", "You have been stunned.")); break; - - /* Heavy stun */ - case 2: msg_print(_("意識がひどくもうろうとしてきた。", "You have been heavily stunned.")); break; - - /* Knocked out */ - case 3: msg_print(_("頭がクラクラして意識が遠のいてきた。", "You have been knocked out.")); break; - } - - if (randint1(1000) < v || one_in_(16)) - { - msg_print(_("割れるような頭痛がする。", "A vicious blow hits your head.")); - - if (one_in_(3)) - { - if (!p_ptr->sustain_int) (void)do_dec_stat(A_INT); - if (!p_ptr->sustain_wis) (void)do_dec_stat(A_WIS); - } - else if (one_in_(2)) - { - if (!p_ptr->sustain_int) (void)do_dec_stat(A_INT); - } - else - { - if (!p_ptr->sustain_wis) (void)do_dec_stat(A_WIS); - } - } - if (p_ptr->special_defense & KATA_MASK) - { - msg_print(_("型が崩れた。", "Your posture gets loose.")); - p_ptr->special_defense &= ~(KATA_MASK); - p_ptr->update |= (PU_BONUS); - p_ptr->update |= (PU_MONSTERS); - p_ptr->redraw |= (PR_STATE); - p_ptr->redraw |= (PR_STATUS); - p_ptr->action = ACTION_NONE; - } - - /* Sniper */ - if (p_ptr->concent) reset_concentration(TRUE); - - /* Hex */ - if (hex_spelling_any()) stop_hex_spell_all(); - - notice = TRUE; - } - - /* Decrease cut */ - else if (new_aux < old_aux) - { - /* Describe the state */ - switch (new_aux) - { - /* None */ - case 0: - msg_print(_("やっと朦朧状態から回復した。", "You are no longer stunned.")); - - if (disturb_state) disturb(FALSE, FALSE); - break; - } - - notice = TRUE; - } - - /* Use the value */ - p_ptr->stun = v; - - /* No change */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - - /* Redraw the "stun" */ - p_ptr->redraw |= (PR_STUN); - handle_stuff(); - return (TRUE); -} - - -/*! - * @brief 出血の継続時間をセットする / Set "p_ptr->cut", notice observable changes - * @param v 継続時間 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - * @details - * Note the special code to only notice "range" changes. - */ -bool set_cut(TIME_EFFECT v) -{ - int old_aux, new_aux; - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - if ((p_ptr->prace == RACE_GOLEM || - p_ptr->prace == RACE_SKELETON || - p_ptr->prace == RACE_SPECTRE || - (p_ptr->prace == RACE_ZOMBIE && p_ptr->lev > 11)) && - !p_ptr->mimic_form) - v = 0; - - /* Mortal wound */ - if (p_ptr->cut > 1000) - { - old_aux = 7; - } - - /* Deep gash */ - else if (p_ptr->cut > 200) - { - old_aux = 6; - } - - /* Severe cut */ - else if (p_ptr->cut > 100) - { - old_aux = 5; - } - - /* Nasty cut */ - else if (p_ptr->cut > 50) - { - old_aux = 4; - } - - /* Bad cut */ - else if (p_ptr->cut > 25) - { - old_aux = 3; - } - - /* Light cut */ - else if (p_ptr->cut > 10) - { - old_aux = 2; - } - - /* Graze */ - else if (p_ptr->cut > 0) - { - old_aux = 1; - } - - /* None */ - else - { - old_aux = 0; - } - - /* Mortal wound */ - if (v > 1000) - { - new_aux = 7; - } - - /* Deep gash */ - else if (v > 200) - { - new_aux = 6; - } - - /* Severe cut */ - else if (v > 100) - { - new_aux = 5; - } - - /* Nasty cut */ - else if (v > 50) - { - new_aux = 4; - } - - /* Bad cut */ - else if (v > 25) - { - new_aux = 3; - } - - /* Light cut */ - else if (v > 10) - { - new_aux = 2; - } - - /* Graze */ - else if (v > 0) - { - new_aux = 1; - } - - /* None */ - else - { - new_aux = 0; - } - - /* Increase cut */ - if (new_aux > old_aux) - { - /* Describe the state */ - switch (new_aux) - { - /* Graze */ - case 1: msg_print(_("かすり傷を負ってしまった。", "You have been given a graze.")); break; - - /* Light cut */ - case 2: msg_print(_("軽い傷を負ってしまった。", "You have been given a light cut.")); break; - - /* Bad cut */ - case 3: msg_print(_("ひどい傷を負ってしまった。", "You have been given a bad cut.")); break; - - /* Nasty cut */ - case 4: msg_print(_("大変な傷を負ってしまった。", "You have been given a nasty cut.")); break; - - /* Severe cut */ - case 5: msg_print(_("重大な傷を負ってしまった。", "You have been given a severe cut.")); break; - - /* Deep gash */ - case 6: msg_print(_("ひどい深手を負ってしまった。", "You have been given a deep gash.")); break; - - /* Mortal wound */ - case 7: msg_print(_("致命的な傷を負ってしまった。", "You have been given a mortal wound.")); break; - } - - notice = TRUE; - - if (randint1(1000) < v || one_in_(16)) - { - if (!p_ptr->sustain_chr) - { - msg_print(_("ひどい傷跡が残ってしまった。", "You have been horribly scarred.")); - do_dec_stat(A_CHR); - } - } - } - - /* Decrease cut */ - else if (new_aux < old_aux) - { - /* Describe the state */ - switch (new_aux) - { - /* None */ - case 0: - msg_format(_("やっと%s。", "You are no longer bleeding."), p_ptr->prace == RACE_ANDROID ? "怪我が直った" : "出血が止まった"); - - if (disturb_state) disturb(FALSE, FALSE); - break; - } - - notice = TRUE; - } - - /* Use the value */ - p_ptr->cut = v; - - /* No change */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - - /* Redraw the "cut" */ - p_ptr->redraw |= (PR_CUT); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief 空腹状態をセットする / Set "p_ptr->food", notice observable changes - * @param v 継続時間 - * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。 - * @details - * Set "", notice observable changes\n - *\n - * The "p_ptr->food" variable can get as large as 20000, allowing the - * addition of the most "filling" item, Elvish Waybread, which adds - * 7500 food units, without overflowing the 32767 maximum limit.\n - *\n - * Perhaps we should disturb the player with various messages, - * especially messages about hunger status changes. \n - *\n - * Digestion of food is handled in "dungeon.c", in which, normally, - * the player digests about 20 food units per 100 game turns, more - * when "fast", more when "regenerating", less with "slow digestion", - * but when the player is "gorged", he digests 100 food units per 10 - * game turns, or a full 1000 food units per 100 game turns.\n - *\n - * Note that the player's speed is reduced by 10 units while gorged, - * so if the player eats a single food ration (5000 food units) when - * full (15000 food units), he will be gorged for (5000/100)*10 = 500 - * game turns, or 500/(100/5) = 25 player turns (if nothing else is - * affecting the player speed).\n - */ -bool set_food(TIME_EFFECT v) -{ - int old_aux, new_aux; - - bool notice = FALSE; - v = (v > 20000) ? 20000 : (v < 0) ? 0 : v; - - /* Fainting / Starving */ - if (p_ptr->food < PY_FOOD_FAINT) - { - old_aux = 0; - } - - /* Weak */ - else if (p_ptr->food < PY_FOOD_WEAK) - { - old_aux = 1; - } - - /* Hungry */ - else if (p_ptr->food < PY_FOOD_ALERT) - { - old_aux = 2; - } - - /* Normal */ - else if (p_ptr->food < PY_FOOD_FULL) - { - old_aux = 3; - } - - /* Full */ - else if (p_ptr->food < PY_FOOD_MAX) - { - old_aux = 4; - } - - /* Gorged */ - else - { - old_aux = 5; - } - - /* Fainting / Starving */ - if (v < PY_FOOD_FAINT) - { - new_aux = 0; - } - - /* Weak */ - else if (v < PY_FOOD_WEAK) - { - new_aux = 1; - } - - /* Hungry */ - else if (v < PY_FOOD_ALERT) - { - new_aux = 2; - } - - /* Normal */ - else if (v < PY_FOOD_FULL) - { - new_aux = 3; - } - - /* Full */ - else if (v < PY_FOOD_MAX) - { - new_aux = 4; - } - - /* Gorged */ - else - { - new_aux = 5; - } - - if (old_aux < 1 && new_aux > 0) - chg_virtue(V_PATIENCE, 2); - else if (old_aux < 3 && (old_aux != new_aux)) - chg_virtue(V_PATIENCE, 1); - if (old_aux == 2) - chg_virtue(V_TEMPERANCE, 1); - if (old_aux == 0) - chg_virtue(V_TEMPERANCE, -1); - - /* Food increase */ - if (new_aux > old_aux) - { - /* Describe the state */ - switch (new_aux) - { - /* Weak */ - case 1: msg_print(_("まだ空腹で倒れそうだ。", "You are still weak.")); break; - - /* Hungry */ - case 2: msg_print(_("まだ空腹だ。", "You are still hungry.")); break; - - /* Normal */ - case 3: msg_print(_("空腹感がおさまった。", "You are no longer hungry.")); break; - - /* Full */ - case 4: msg_print(_("満腹だ!", "You are full!")); break; - - /* Bloated */ - case 5: - msg_print(_("食べ過ぎだ!", "You have gorged yourself!")); - chg_virtue(V_HARMONY, -1); - chg_virtue(V_PATIENCE, -1); - chg_virtue(V_TEMPERANCE, -2); - - break; - } - - /* Change */ - notice = TRUE; - } - - /* Food decrease */ - else if (new_aux < old_aux) - { - /* Describe the state */ - switch (new_aux) - { - /* Fainting / Starving */ - case 0: msg_print(_("あまりにも空腹で気を失ってしまった!", "You are getting faint from hunger!")); break; - - /* Weak */ - case 1: msg_print(_("お腹が空いて倒れそうだ。", "You are getting weak from hunger!")); break; - - /* Hungry */ - case 2: msg_print(_("お腹が空いてきた。", "You are getting hungry.")); break; - - /* Normal */ - case 3: msg_print(_("満腹感がなくなった。", "You are no longer full.")); break; - - /* Full */ - case 4: msg_print(_("やっとお腹がきつくなくなった。", "You are no longer gorged.")); break; - } - - if (p_ptr->wild_mode && (new_aux < 2)) - { - change_wild_mode(); - } - - /* Change */ - notice = TRUE; - } - - /* Use the value */ - p_ptr->food = v; - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - - /* Redraw hunger */ - p_ptr->redraw |= (PR_HUNGER); - handle_stuff(); - return (TRUE); -} - -/*! - * @brief プレイヤーの基本能力値を増加させる / Increases a stat by one randomized level -RAK- - * @param stat 上昇させるステータスID - * @return 実際に上昇した場合TRUEを返す。 - * @details - * Note that this function (used by stat potions) now restores\n - * the stat BEFORE increasing it.\n - */ -bool inc_stat(int stat) -{ - BASE_STATUS value, gain; - - /* Then augment the current/max stat */ - value = p_ptr->stat_cur[stat]; - - /* Cannot go above 18/100 */ - if (value < p_ptr->stat_max_max[stat]) - { - /* Gain one (sometimes two) points */ - if (value < 18) - { - gain = ((randint0(100) < 75) ? 1 : 2); - value += gain; - } - - /* Gain 1/6 to 1/3 of distance to 18/100 */ - else if (value < (p_ptr->stat_max_max[stat]-2)) - { - /* Approximate gain value */ - gain = (((p_ptr->stat_max_max[stat]) - value) / 2 + 3) / 2; - if (gain < 1) gain = 1; - - /* Apply the bonus */ - value += randint1(gain) + gain / 2; - - /* Maximal value */ - if (value > (p_ptr->stat_max_max[stat]-1)) value = p_ptr->stat_max_max[stat]-1; - } - - /* Gain one point at a time */ - else - { - value++; - } - - /* Save the new value */ - p_ptr->stat_cur[stat] = value; - - /* Bring up the maximum too */ - if (value > p_ptr->stat_max[stat]) - { - p_ptr->stat_max[stat] = value; - } - p_ptr->update |= (PU_BONUS); - - /* Success */ - return (TRUE); - } - - /* Nothing to gain */ - return (FALSE); -} - -/*! - * @brief プレイヤーの基本能力値を減少させる / Decreases a stat by an amount indended to vary from 0 to 100 percent. - * @param stat 減少させるステータスID - * @param amount 減少させる基本量 - * @param permanent TRUEならば現在の最大値を減少させる - * @return 実際に減少した場合TRUEを返す。 - * @details - *\n - * Amount could be a little higher in extreme cases to mangle very high\n - * stats from massive assaults. -CWS\n - *\n - * Note that "permanent" means that the *given* amount is permanent,\n - * not that the new value becomes permanent. This may not work exactly\n - * as expected, due to "weirdness" in the algorithm, but in general,\n - * if your stat is already drained, the "max" value will not drop all\n - * the way down to the "cur" value.\n - */ -bool dec_stat(int stat, int amount, int permanent) -{ - BASE_STATUS cur, max; - int loss, same; - bool res = FALSE; - - - /* Acquire current value */ - cur = p_ptr->stat_cur[stat]; - max = p_ptr->stat_max[stat]; - - /* Note when the values are identical */ - same = (cur == max); - - /* Damage "current" value */ - if (cur > 3) - { - /* Handle "low" values */ - if (cur <= 18) - { - if (amount > 90) cur--; - if (amount > 50) cur--; - if (amount > 20) cur--; - cur--; - } - - /* Handle "high" values */ - else - { - /* Hack -- Decrement by a random amount between one-quarter */ - /* and one-half of the stat bonus times the percentage, with a */ - /* minimum damage of half the percentage. -CWS */ - loss = (((cur-18) / 2 + 1) / 2 + 1); - if (loss < 1) loss = 1; - - /* Randomize the loss */ - loss = ((randint1(loss) + loss) * amount) / 100; - - /* Maximal loss */ - if (loss < amount/2) loss = amount/2; - - /* Lose some points */ - cur = cur - loss; - - /* Hack -- Only reduce stat to 17 sometimes */ - if (cur < 18) cur = (amount <= 20) ? 18 : 17; - } - - /* Prevent illegal values */ - if (cur < 3) cur = 3; - - /* Something happened */ - if (cur != p_ptr->stat_cur[stat]) res = TRUE; - } - - /* Damage "max" value */ - if (permanent && (max > 3)) - { - chg_virtue(V_SACRIFICE, 1); - if (stat == A_WIS || stat == A_INT) - chg_virtue(V_ENLIGHTEN, -2); - - /* Handle "low" values */ - if (max <= 18) - { - if (amount > 90) max--; - if (amount > 50) max--; - if (amount > 20) max--; - max--; - } - - /* Handle "high" values */ - else - { - /* Hack -- Decrement by a random amount between one-quarter */ - /* and one-half of the stat bonus times the percentage, with a */ - /* minimum damage of half the percentage. -CWS */ - loss = (((max-18) / 2 + 1) / 2 + 1); - loss = ((randint1(loss) + loss) * amount) / 100; - if (loss < amount/2) loss = amount/2; - - /* Lose some points */ - max = max - loss; - - /* Hack -- Only reduce stat to 17 sometimes */ - if (max < 18) max = (amount <= 20) ? 18 : 17; - } - - /* Hack -- keep it clean */ - if (same || (max < cur)) max = cur; - - /* Something happened */ - if (max != p_ptr->stat_max[stat]) res = TRUE; - } - - /* Apply changes */ - if (res) - { - /* Actually set the stat to its new value. */ - p_ptr->stat_cur[stat] = cur; - p_ptr->stat_max[stat] = max; - - p_ptr->redraw |= (PR_STATS); - p_ptr->update |= (PU_BONUS); - } - - return (res); -} - - -/*! - * @brief プレイヤーの基本能力値を回復させる / Restore a stat. Return TRUE only if this actually makes a difference. - * @param stat 回復ステータスID - * @return 実際に回復した場合TRUEを返す。 - */ -bool res_stat(int stat) -{ - /* Restore if needed */ - if (p_ptr->stat_cur[stat] != p_ptr->stat_max[stat]) - { - p_ptr->stat_cur[stat] = p_ptr->stat_max[stat]; - p_ptr->update |= (PU_BONUS); - p_ptr->redraw |= (PR_STATS); - - /* Success */ - return (TRUE); - } - - /* Nothing to restore */ - return (FALSE); -} - - -/* - * Increase players hit points, notice effects - */ -bool hp_player(int num) -{ - int vir; - vir = virtue_number(V_VITALITY); - - if(num <= 0) return (FALSE); - - if(vir) - { - num = num * (p_ptr->virtues[vir - 1] + 1250) / 1250; - } - /* Healing needed */ - if (p_ptr->chp < p_ptr->mhp) - { - if ((num > 0) && (p_ptr->chp < (p_ptr->mhp/3))) - chg_virtue(V_TEMPERANCE, 1); - /* Gain hitpoints */ - p_ptr->chp += num; - - /* Enforce maximum */ - if (p_ptr->chp >= p_ptr->mhp) - { - p_ptr->chp = p_ptr->mhp; - p_ptr->chp_frac = 0; - } - - p_ptr->redraw |= (PR_HP); - - p_ptr->window |= (PW_PLAYER); - - /* Heal 0-4 */ - if (num < 5) - { - msg_print(_("少し気分が良くなった。", "You feel a little better.")); - } - - /* Heal 5-14 */ - else if (num < 15) - { - msg_print(_("気分が良くなった。", "You feel better.")); - } - - /* Heal 15-34 */ - else if (num < 35) - { - msg_print(_("とても気分が良くなった。", "You feel much better.")); - } - - /* Heal 35+ */ - else - { - msg_print(_("ひじょうに気分が良くなった。", "You feel very good.")); - } - - return (TRUE); - } - - /* Ignore */ - return (FALSE); -} - - -/* - * Array of stat "descriptions" - */ -static concptr desc_stat_pos[] = -{ - _("強く", "strong"), - _("知的に", "smart"), - _("賢く", "wise"), - _("器用に", "dextrous"), - _("健康に", "healthy"), - _("美しく", "cute") -}; - - -/* - * Array of stat "descriptions" - */ -static concptr desc_stat_neg[] = -{ - _("弱く", "weak"), - _("無知に", "stupid"), - _("愚かに", "naive"), - _("不器用に", "clumsy"), - _("不健康に", "sickly"), - _("醜く", "ugly") -}; - - -/* - * Lose a "point" - */ -bool do_dec_stat(int stat) -{ - bool sust = FALSE; - - /* Access the "sustain" */ - switch (stat) - { - case A_STR: if (p_ptr->sustain_str) sust = TRUE; break; - case A_INT: if (p_ptr->sustain_int) sust = TRUE; break; - case A_WIS: if (p_ptr->sustain_wis) sust = TRUE; break; - case A_DEX: if (p_ptr->sustain_dex) sust = TRUE; break; - case A_CON: if (p_ptr->sustain_con) sust = TRUE; break; - case A_CHR: if (p_ptr->sustain_chr) sust = TRUE; break; - } - - /* Sustain */ - if (sust && (!ironman_nightmare || randint0(13))) - { - msg_format(_("%sなった気がしたが、すぐに元に戻った。", "You feel %s for a moment, but the feeling passes."), - desc_stat_neg[stat]); - - /* Notice effect */ - return (TRUE); - } - - /* Attempt to reduce the stat */ - if (dec_stat(stat, 10, (ironman_nightmare && !randint0(13)))) - { - msg_format(_("ひどく%sなった気がする。", "You feel very %s."), desc_stat_neg[stat]); - - /* Notice effect */ - return (TRUE); - } - - /* Nothing obvious */ - return (FALSE); -} - - -/* - * Restore lost "points" in a stat - */ -bool do_res_stat(int stat) -{ - /* Attempt to increase */ - if (res_stat(stat)) - { - msg_format(_("元通りに%sなった気がする。", "You feel less %s."), desc_stat_pos[stat]); - - return (TRUE); - } - - /* Nothing obvious */ - return (FALSE); -} - - -/* - * Gain a "point" in a stat - */ -bool do_inc_stat(int stat) -{ - bool res; - - /* Restore strength */ - res = res_stat(stat); - - /* Attempt to increase */ - if (inc_stat(stat)) - { - if (stat == A_WIS) - { - chg_virtue(V_ENLIGHTEN, 1); - chg_virtue(V_FAITH, 1); - } - else if (stat == A_INT) - { - chg_virtue(V_KNOWLEDGE, 1); - chg_virtue(V_ENLIGHTEN, 1); - } - else if (stat == A_CON) - chg_virtue(V_VITALITY, 1); - - msg_format(_("ワーオ!とても%sなった!", "Wow! You feel very %s!"), desc_stat_pos[stat]); - - return (TRUE); - } - - /* Restoration worked */ - if (res) - { - msg_format(_("元通りに%sなった気がする。", "You feel less %s."), desc_stat_pos[stat]); - - return (TRUE); - } - - /* Nothing obvious */ - return (FALSE); -} - - -/* - * Restores any drained experience - */ -bool restore_level(void) -{ - /* Restore experience */ - if (p_ptr->exp < p_ptr->max_exp) - { - msg_print(_("経験値が戻ってきた気がする。", "You feel your experience returning.")); - - /* Restore the experience */ - p_ptr->exp = p_ptr->max_exp; - - /* Check the experience */ - check_experience(); - - /* Did something */ - return (TRUE); - } - - /* No effect */ - return (FALSE); -} - -/* - * Forget everything - */ -bool lose_all_info(void) -{ - int i; - - chg_virtue(V_KNOWLEDGE, -5); - chg_virtue(V_ENLIGHTEN, -5); - - /* Forget info about objects */ - for (i = 0; i < INVEN_TOTAL; i++) - { - object_type *o_ptr = &inventory[i]; - - /* Skip non-objects */ - if (!o_ptr->k_idx) continue; - - /* Allow "protection" by the MENTAL flag */ - if (o_ptr->ident & (IDENT_MENTAL)) continue; - - /* Remove "default inscriptions" */ - o_ptr->feeling = FEEL_NONE; - - /* Hack -- Clear the "empty" flag */ - o_ptr->ident &= ~(IDENT_EMPTY); - - /* Hack -- Clear the "known" flag */ - o_ptr->ident &= ~(IDENT_KNOWN); - - /* Hack -- Clear the "felt" flag */ - o_ptr->ident &= ~(IDENT_SENSE); - } - p_ptr->update |= (PU_BONUS); - p_ptr->update |= (PU_COMBINE | PU_REORDER); - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - /* Mega-Hack -- Forget the map */ - wiz_dark(); - - /* It worked */ - return (TRUE); -} - - -void do_poly_wounds(void) -{ - /* Changed to always provide at least _some_ healing */ - s16b wounds = p_ptr->cut; - s16b hit_p = (p_ptr->mhp - p_ptr->chp); - s16b change = damroll(p_ptr->lev, 5); - bool Nasty_effect = one_in_(5); - - if (!(wounds || hit_p || Nasty_effect)) return; - - msg_print(_("傷がより軽いものに変化した。", "Your wounds are polymorphed into less serious ones.")); - hp_player(change); - if (Nasty_effect) - { - msg_print(_("新たな傷ができた!", "A new wound was created!")); - take_hit(DAMAGE_LOSELIFE, change / 2, _("変化した傷", "a polymorphed wound"), -1); - set_cut(change); - } - else - { - set_cut(p_ptr->cut - (change / 2)); - } -} - - -/* - * Change player race - */ -void change_race(CHARACTER_IDX new_race, concptr effect_msg) -{ - concptr title = race_info[new_race].title; - int old_race = p_ptr->prace; - -#ifdef JP - msg_format("あなたは%s%sに変化した!", effect_msg, title); -#else - msg_format("You current_world_ptr->game_turn into %s %s%s!", (!effect_msg[0] && is_a_vowel(title[0]) ? "an" : "a"), effect_msg, title); -#endif - - chg_virtue(V_CHANCE, 2); - - if (p_ptr->prace < 32) - { - p_ptr->old_race1 |= 1L << p_ptr->prace; - } - else - { - p_ptr->old_race2 |= 1L << (p_ptr->prace - 32); - } - p_ptr->prace = new_race; - rp_ptr = &race_info[p_ptr->prace]; - - /* Experience factor */ - p_ptr->expfact = rp_ptr->r_exp + cp_ptr->c_exp; - - /* - * The speed bonus of Klackons and Sprites are disabled - * and the experience penalty is decreased. - */ - if (((p_ptr->pclass == CLASS_MONK) || (p_ptr->pclass == CLASS_FORCETRAINER) || (p_ptr->pclass == CLASS_NINJA)) && ((p_ptr->prace == RACE_KLACKON) || (p_ptr->prace == RACE_SPRITE))) - p_ptr->expfact -= 15; - - /* Get character's height and weight */ - get_height_weight(); - - /* Hitdice */ - if (p_ptr->pclass == CLASS_SORCERER) - p_ptr->hitdie = rp_ptr->r_mhp/2 + cp_ptr->c_mhp + ap_ptr->a_mhp; - else - p_ptr->hitdie = rp_ptr->r_mhp + cp_ptr->c_mhp + ap_ptr->a_mhp; - - roll_hitdice(p_ptr, 0L); - - /* The experience level may be modified */ - check_experience(); - - p_ptr->redraw |= (PR_BASIC); - - p_ptr->update |= (PU_BONUS); - - handle_stuff(); - - /* Load an autopick preference file */ - if (old_race != p_ptr->prace) autopick_load_pref(FALSE); - - /* Player's graphic tile may change */ - lite_spot(p_ptr->y, p_ptr->x); -} - - -void do_poly_self(void) -{ - int power = p_ptr->lev; - - msg_print(_("あなたは変化の訪れを感じた...", "You feel a change coming over you...")); - chg_virtue(V_CHANCE, 1); - - if ((power > randint0(20)) && one_in_(3) && (p_ptr->prace != RACE_ANDROID)) - { - char effect_msg[80] = ""; - CHARACTER_IDX new_race; - - /* Some form of racial polymorph... */ - power -= 10; - - if ((power > randint0(5)) && one_in_(4)) - { - /* sex change */ - power -= 2; - - if (p_ptr->psex == SEX_MALE) - { - p_ptr->psex = SEX_FEMALE; - sp_ptr = &sex_info[p_ptr->psex]; - sprintf(effect_msg, _("女性の", "female ")); - } - else - { - p_ptr->psex = SEX_MALE; - sp_ptr = &sex_info[p_ptr->psex]; - sprintf(effect_msg, _("男性の", "male ")); - } - } - - if ((power > randint0(30)) && one_in_(5)) - { - int tmp = 0; - - /* Harmful deformity */ - power -= 15; - - while (tmp < A_MAX) - { - if (one_in_(2)) - { - (void)dec_stat(tmp, randint1(6) + 6, one_in_(3)); - power -= 1; - } - tmp++; - } - - /* Deformities are discriminated against! */ - (void)dec_stat(A_CHR, randint1(6), TRUE); - - if (effect_msg[0]) - { - char tmp_msg[10]; - sprintf(tmp_msg,_("%s", "%s "),effect_msg); - sprintf(effect_msg,_("奇形の%s", "deformed %s "),tmp_msg); - } - else - { - sprintf(effect_msg,_("奇形の", "deformed ")); - } - } - - while ((power > randint0(20)) && one_in_(10)) - { - /* Polymorph into a less mutated form */ - power -= 10; - - if (!lose_mutation(0)) - msg_print(_("奇妙なくらい普通になった気がする。", "You feel oddly normal.")); - } - - do - { - new_race = (CHARACTER_IDX)randint0(MAX_RACES); - } - while ((new_race == p_ptr->prace) || (new_race == RACE_ANDROID)); - - change_race(new_race, effect_msg); - } - - if ((power > randint0(30)) && one_in_(6)) - { - int tmp = 0; - - /* Abomination! */ - power -= 20; - msg_format(_("%sの構成が変化した!", "Your internal organs are rearranged!"), p_ptr->prace == RACE_ANDROID ? "機械" : "内臓"); - - while (tmp < A_MAX) - { - (void)dec_stat(tmp, randint1(6) + 6, one_in_(3)); - tmp++; - } - if (one_in_(6)) - { - msg_print(_("現在の姿で生きていくのは困難なようだ!", "You find living difficult in your present form!")); - take_hit(DAMAGE_LOSELIFE, damroll(randint1(10), p_ptr->lev), _("致命的な突然変異", "a lethal mutation"), -1); - - power -= 10; - } - } - - if ((power > randint0(20)) && one_in_(4)) - { - power -= 10; - - get_max_stats(); - roll_hitdice(p_ptr, 0L); - } - - while ((power > randint0(15)) && one_in_(3)) - { - power -= 7; - (void)gain_mutation(p_ptr, 0); - } - - if (power > randint0(5)) - { - power -= 5; - do_poly_wounds(); - } - - /* Note: earlier deductions may have left power < 0 already. */ - while (power > 0) - { - status_shuffle(); - power--; - } -} - - -/* - * Decreases players hit points and sets death flag if necessary - * - * Invulnerability needs to be changed into a "shield" - * - * Hack -- this function allows the user to save (or quit) - * the game when he dies, since the "You die." message is shown before - * setting the player to "dead". - */ - -int take_hit(int damage_type, HIT_POINT damage, concptr hit_from, int monspell) -{ - int old_chp = p_ptr->chp; - - char death_message[1024]; - char tmp[1024]; - - int warning = (p_ptr->mhp * hitpoint_warn / 10); - if (p_ptr->is_dead) return 0; - - if (p_ptr->sutemi) damage *= 2; - if (p_ptr->special_defense & KATA_IAI) damage += (damage + 4) / 5; - - if (easy_band) damage = (damage+1)/2; - - if (damage_type != DAMAGE_USELIFE) - { - disturb(TRUE, TRUE); - if (auto_more) - { - p_ptr->now_damaged = TRUE; - } - } - - if (monspell >= 0) learn_spell(monspell); - - /* Mega-Hack -- Apply "invulnerability" */ - if ((damage_type != DAMAGE_USELIFE) && (damage_type != DAMAGE_LOSELIFE)) - { - if (IS_INVULN() && (damage < 9000)) - { - if (damage_type == DAMAGE_FORCE) - { - msg_print(_("バリアが切り裂かれた!", "The attack cuts your shield of invulnerability open!")); - } - else if (one_in_(PENETRATE_INVULNERABILITY)) - { - msg_print(_("無敵のバリアを破って攻撃された!", "The attack penetrates your shield of invulnerability!")); - } - else - { - return 0; - } - } - - if (CHECK_MULTISHADOW()) - { - if (damage_type == DAMAGE_FORCE) - { - msg_print(_("幻影もろとも体が切り裂かれた!", "The attack hits Shadow together with you!")); - } - else if (damage_type == DAMAGE_ATTACK) - { - msg_print(_("攻撃は幻影に命中し、あなたには届かなかった。", "The attack hits Shadow, you are unharmed!")); - return 0; - } - } - - if (p_ptr->wraith_form) - { - if (damage_type == DAMAGE_FORCE) - { - msg_print(_("半物質の体が切り裂かれた!", "The attack cuts through your ethereal body!")); - } - else - { - damage /= 2; - if ((damage == 0) && one_in_(2)) damage = 1; - } - } - - if (p_ptr->special_defense & KATA_MUSOU) - { - damage /= 2; - if ((damage == 0) && one_in_(2)) damage = 1; - } - } /* not if LOSELIFE USELIFE */ - - /* Hurt the player */ - p_ptr->chp -= damage; - if(damage_type == DAMAGE_GENO && p_ptr->chp < 0) - { - damage += p_ptr->chp; - p_ptr->chp = 0; - } - - /* Display the hitpoints */ - p_ptr->redraw |= (PR_HP); - - p_ptr->window |= (PW_PLAYER); - - if (damage_type != DAMAGE_GENO && p_ptr->chp == 0) - { - chg_virtue(V_SACRIFICE, 1); - chg_virtue(V_CHANCE, 2); - } - - /* Dead player */ - if (p_ptr->chp < 0) - { - bool android = (p_ptr->prace == RACE_ANDROID ? TRUE : FALSE); - -#ifdef JP /* 死んだ時に強制終了して死を回避できなくしてみた by Habu */ - if (!cheat_save) - if(!save_player()) msg_print("セーブ失敗!"); -#endif - - sound(SOUND_DEATH); - - chg_virtue(V_SACRIFICE, 10); - - handle_stuff(); - p_ptr->leaving = TRUE; - - /* Note death */ - p_ptr->is_dead = TRUE; - - if (p_ptr->inside_arena) - { - concptr m_name = r_name+r_info[arena_info[p_ptr->arena_number].r_idx].name; - msg_format(_("あなたは%sの前に敗れ去った。", "You are beaten by %s."), m_name); - msg_print(NULL); - if (record_arena) do_cmd_write_nikki(NIKKI_ARENA, -1 - p_ptr->arena_number, m_name); - } - else - { - QUEST_IDX q_idx = quest_number(current_floor_ptr->dun_level); - bool seppuku = streq(hit_from, "Seppuku"); - bool winning_seppuku = p_ptr->total_winner && seppuku; - - play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_GAMEOVER); - -#ifdef WORLD_SCORE - /* Make screen dump */ - screen_dump = make_screen_dump(); -#endif - - /* Note cause of death */ - if (seppuku) - { - strcpy(p_ptr->died_from, hit_from); -#ifdef JP - if (!winning_seppuku) strcpy(p_ptr->died_from, "切腹"); -#endif - } - else - { - char dummy[1024]; -#ifdef JP - sprintf(dummy, "%s%s%s", !p_ptr->paralyzed ? "" : p_ptr->free_act ? "彫像状態で" : "麻痺状態で", p_ptr->image ? "幻覚に歪んだ" : "", hit_from); -#else - sprintf(dummy, "%s%s", hit_from, !p_ptr->paralyzed ? "" : " while helpless"); -#endif - my_strcpy(p_ptr->died_from, dummy, sizeof p_ptr->died_from); - } - - /* No longer a winner */ - p_ptr->total_winner = FALSE; - - if (winning_seppuku) - { - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("勝利の後切腹した。", "did Seppuku after the winning.")); - } - else - { - char buf[20]; - - if (p_ptr->inside_arena) - strcpy(buf,_("アリーナ", "in the Arena")); - else if (!current_floor_ptr->dun_level) - strcpy(buf,_("地上", "on the surface")); - else if (q_idx && (is_fixed_quest_idx(q_idx) && - !((q_idx == QUEST_OBERON) || (q_idx == QUEST_SERPENT)))) - strcpy(buf,_("クエスト", "in a quest")); - else - sprintf(buf,_("%d階", "level %d"), (int)current_floor_ptr->dun_level); - - sprintf(tmp, _("%sで%sに殺された。", "killed by %s %s."), buf, p_ptr->died_from); - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp); - } - - do_cmd_write_nikki(NIKKI_GAMESTART, 1, _("-------- ゲームオーバー --------", "-------- Game Over --------")); - do_cmd_write_nikki(NIKKI_BUNSHOU, 1, "\n\n\n\n"); - - flush(); - - if (get_check_strict(_("画面を保存しますか?", "Dump the screen? "), CHECK_NO_HISTORY)) - { - do_cmd_save_screen(); - } - - flush(); - - /* Initialize "last message" buffer */ - if (p_ptr->last_message) string_free(p_ptr->last_message); - p_ptr->last_message = NULL; - - /* Hack -- Note death */ - if (!last_words) - { -#ifdef JP - msg_format("あなたは%sました。", android ? "壊れ" : "死に"); -#else - msg_print(android ? "You are broken." : "You die."); -#endif - - msg_print(NULL); - } - else - { - if (winning_seppuku) - { - get_rnd_line(_("seppuku_j.txt", "seppuku.txt"), 0, death_message); - } - else - { - get_rnd_line(_("death_j.txt", "death.txt"), 0, death_message); - } - - do - { -#ifdef JP - while (!get_string(winning_seppuku ? "辞世の句: " : "断末魔の叫び: ", death_message, 1024)) ; -#else - while (!get_string("Last word: ", death_message, 1024)) ; -#endif - } - while (winning_seppuku && !get_check_strict(_("よろしいですか?", "Are you sure? "), CHECK_NO_HISTORY)); - - if (death_message[0] == '\0') - { -#ifdef JP - strcpy(death_message, format("あなたは%sました。", android ? "壊れ" : "死に")); -#else - strcpy(death_message, android ? "You are broken." : "You die."); -#endif - } - else p_ptr->last_message = string_make(death_message); - -#ifdef JP - if (winning_seppuku) - { - int i, len; - int w = Term->wid; - int h = Term->hgt; - int msg_pos_x[9] = { 5, 7, 9, 12, 14, 17, 19, 21, 23}; - int msg_pos_y[9] = { 3, 4, 5, 4, 5, 4, 5, 6, 4}; - concptr str; - char* str2; - - Term_clear(); - - /* 桜散る */ - for (i = 0; i < 40; i++) - Term_putstr(randint0(w / 2) * 2, randint0(h), 2, TERM_VIOLET, "υ"); - - str = death_message; - if (strncmp(str, "「", 2) == 0) str += 2; - - str2 = my_strstr(str, "」"); - if (str2 != NULL) *str2 = '\0'; - - i = 0; - while (i < 9) - { - str2 = my_strstr(str, " "); - if (str2 == NULL) len = strlen(str); - else len = str2 - str; - - if (len != 0) - { - Term_putstr_v(w * 3 / 4 - 2 - msg_pos_x[i] * 2, msg_pos_y[i], len, - TERM_WHITE, str); - if (str2 == NULL) break; - i++; - } - str = str2 + 1; - if (*str == 0) break; - } - - /* Hide cursor */ - Term_putstr(w-1, h-1, 1, TERM_WHITE, " "); - - flush(); -#ifdef WORLD_SCORE - /* Make screen dump */ - screen_dump = make_screen_dump(); -#endif - - /* Wait a key press */ - (void)inkey(); - } - else -#endif - msg_print(death_message); - } - } - - /* Dead */ - return damage; - } - - handle_stuff(); - - /* Hitpoint warning */ - if (p_ptr->chp < warning) - { - /* Hack -- bell on first notice */ - if (old_chp > warning) bell(); - - sound(SOUND_WARN); - - if (record_danger && (old_chp > warning)) - { - if (p_ptr->image && damage_type == DAMAGE_ATTACK) - hit_from = _("何か", "something"); - - sprintf(tmp,_("%sによってピンチに陥った。", "A critical situation because of %s."),hit_from); - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp); - } - - if (auto_more) - { - /* stop auto_more even if DAMAGE_USELIFE */ - p_ptr->now_damaged = TRUE; - } - - msg_print(_("*** 警告:低ヒット・ポイント! ***", "*** LOW HITPOINT WARNING! ***")); - msg_print(NULL); - flush(); - } - if (p_ptr->wild_mode && !p_ptr->leaving && (p_ptr->chp < MAX(warning, p_ptr->mhp/5))) - { - change_wild_mode(); - } - return damage; -} - - -/* - * Gain experience - */ -void gain_exp_64(s32b amount, u32b amount_frac) -{ - if (p_ptr->is_dead) return; - - if (p_ptr->prace == RACE_ANDROID) return; - - /* Gain some experience */ - s64b_add(&(p_ptr->exp), &(p_ptr->exp_frac), amount, amount_frac); - - /* Slowly recover from experience drainage */ - if (p_ptr->exp < p_ptr->max_exp) - { - /* Gain max experience (20%) (was 10%) */ - p_ptr->max_exp += amount / 5; - } - - /* Check Experience */ - check_experience(); -} - - -/* - * Gain experience - */ -void gain_exp(s32b amount) -{ - gain_exp_64(amount, 0L); -} - - -void calc_android_exp(void) -{ - int i; - u32b total_exp = 0; - if (p_ptr->is_dead) return; - - if (p_ptr->prace != RACE_ANDROID) return; - - for (i = INVEN_RARM; i < INVEN_TOTAL; i++) - { - object_type *o_ptr = &inventory[i]; - object_type forge; - object_type *q_ptr = &forge; - u32b value, exp; - DEPTH level = MAX(k_info[o_ptr->k_idx].level - 8, 1); - - if ((i == INVEN_RIGHT) || (i == INVEN_LEFT) || (i == INVEN_NECK) || (i == INVEN_LITE)) continue; - if (!o_ptr->k_idx) continue; - object_wipe(q_ptr); - - object_copy(q_ptr, o_ptr); - q_ptr->discount = 0; - q_ptr->curse_flags = 0L; - - if (object_is_fixed_artifact(o_ptr)) - { - level = (level + MAX(a_info[o_ptr->name1].level - 8, 5)) / 2; - level += MIN(20, a_info[o_ptr->name1].rarity/(a_info[o_ptr->name1].gen_flags & TRG_INSTA_ART ? 10 : 3)); - } - else if (object_is_ego(o_ptr)) - { - level += MAX(3, (e_info[o_ptr->name2].rating - 5)/2); - } - else if (o_ptr->art_name) - { - s32b total_flags = flag_cost(o_ptr, o_ptr->pval); - int fake_level; - - if (!object_is_weapon_ammo(o_ptr)) - { - /* For armors */ - if (total_flags < 15000) fake_level = 10; - else if (total_flags < 35000) fake_level = 25; - else fake_level = 40; - } - else - { - /* For weapons */ - if (total_flags < 20000) fake_level = 10; - else if (total_flags < 45000) fake_level = 25; - else fake_level = 40; - } - - level = MAX(level, (level + MAX(fake_level - 8, 5)) / 2 + 3); - } - - value = object_value_real(q_ptr); - - if (value <= 0) continue; - if ((o_ptr->tval == TV_SOFT_ARMOR) && (o_ptr->sval == SV_ABUNAI_MIZUGI) && (p_ptr->pseikaku != SEIKAKU_SEXY)) value /= 32; - if (value > 5000000L) value = 5000000L; - if ((o_ptr->tval == TV_DRAG_ARMOR) || (o_ptr->tval == TV_CARD)) level /= 2; - - if (object_is_artifact(o_ptr) || object_is_ego(o_ptr) || - (o_ptr->tval == TV_DRAG_ARMOR) || - ((o_ptr->tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM)) || - ((o_ptr->tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD)) || - ((o_ptr->tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES)) || - ((o_ptr->tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE)) || - ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_DIAMOND_EDGE))) - { - if (level > 65) level = 35 + (level - 65) / 5; - else if (level > 35) level = 25 + (level - 35) / 3; - else if (level > 15) level = 15 + (level - 15) / 2; - exp = MIN(100000L, value) / 2 * level * level; - if (value > 100000L) - exp += (value - 100000L) / 8 * level * level; - } - else - { - exp = MIN(100000L, value) * level; - if (value > 100000L) - exp += (value - 100000L) / 4 * level; - } - if ((((i == INVEN_RARM) || (i == INVEN_LARM)) && (has_melee_weapon(i))) || (i == INVEN_BOW)) total_exp += exp / 48; - else total_exp += exp / 16; - if (i == INVEN_BODY) total_exp += exp / 32; - } - p_ptr->exp = p_ptr->max_exp = total_exp; - - /* Check Experience */ - check_experience(); -} - - -/* - * Lose experience - */ -void lose_exp(s32b amount) -{ - if (p_ptr->prace == RACE_ANDROID) return; - - /* Never drop below zero experience */ - if (amount > p_ptr->exp) amount = p_ptr->exp; - - /* Lose some experience */ - p_ptr->exp -= amount; - - /* Check Experience */ - check_experience(); -} - - -/* - * Drain experience - * If resisted to draining, return FALSE - */ -bool drain_exp(s32b drain, s32b slip, int hold_exp_prob) -{ - /* Androids and their mimics are never drained */ - if (p_ptr->prace == RACE_ANDROID) return FALSE; - - if (p_ptr->hold_exp && (randint0(100) < hold_exp_prob)) - { - /* Hold experience */ - msg_print(_("しかし自己の経験値を守りきった!", "You keep hold of your experience!")); - return FALSE; - } - - /* Hold experience failed */ - if (p_ptr->hold_exp) - { - msg_print(_("経験値を少し吸い取られた気がする!", "You feel your experience slipping away!")); - lose_exp(slip); - } - else - { - msg_print(_("経験値が体から吸い取られた気がする!", "You feel your experience draining away!")); - lose_exp(drain); - } - - return TRUE; -} - - -bool set_ultimate_res(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->ult_res && !do_dec) - { - if (p_ptr->ult_res > v) return FALSE; - } - else if (!p_ptr->ult_res) - { - msg_print(_("あらゆることに対して耐性がついた気がする!", "You feel resistant!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->ult_res) - { - msg_print(_("あらゆることに対する耐性が薄れた気がする。", "You feel less resistant")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->ult_res = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -bool set_tim_res_nether(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_res_nether && !do_dec) - { - if (p_ptr->tim_res_nether > v) return FALSE; - } - else if (!p_ptr->tim_res_nether) - { - msg_print(_("地獄の力に対して耐性がついた気がする!", "You feel nether resistant!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_res_nether) - { - msg_print(_("地獄の力に対する耐性が薄れた気がする。", "You feel less nether resistant")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_res_nether = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - -bool set_tim_res_time(TIME_EFFECT v, bool do_dec) -{ - bool notice = FALSE; - v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; - - if (p_ptr->is_dead) return FALSE; - - /* Open */ - if (v) - { - if (p_ptr->tim_res_time && !do_dec) - { - if (p_ptr->tim_res_time > v) return FALSE; - } - else if (!p_ptr->tim_res_time) - { - msg_print(_("時間逆転の力に対して耐性がついた気がする!", "You feel time resistant!")); - notice = TRUE; - } - } - - /* Shut */ - else - { - if (p_ptr->tim_res_time) - { - msg_print(_("時間逆転の力に対する耐性が薄れた気がする。", "You feel less time resistant")); - notice = TRUE; - } - } - - /* Use the value */ - p_ptr->tim_res_time = v; - p_ptr->redraw |= (PR_STATUS); - - /* Nothing to notice */ - if (!notice) return (FALSE); - - if (disturb_state) disturb(FALSE, FALSE); - p_ptr->update |= (PU_BONUS); - handle_stuff(); - return (TRUE); -} - - -/* - * Choose a warrior-mage elemental attack. -LM- - */ -bool choose_ele_attack(void) -{ - int num; - - char choice; - - if (!has_melee_weapon(INVEN_RARM) && !has_melee_weapon(INVEN_LARM)) - { - msg_format(_("武器を持たないと魔法剣は使えない。", "You cannot use temporary branding with no weapon.")); - return FALSE; - } - screen_save(); - - num = (p_ptr->lev - 20) / 5; - c_prt(TERM_RED, _(" a) 焼棄", " a) Fire Brand"), 2, 14); - - if (num >= 2) - c_prt(TERM_L_WHITE,_(" b) 凍結", " b) Cold Brand"), 3, 14); - else - prt("", 3, 14); - - if (num >= 3) - c_prt(TERM_GREEN, _(" c) 毒殺", " c) Poison Brand"), 4, 14); - else - prt("", 4, 14); - - if (num >= 4) - c_prt(TERM_L_DARK, _(" d) 溶解", " d) Acid Brand"), 5, 14); - else - prt("", 5, 14); - - if (num >= 5) - c_prt(TERM_BLUE, _(" e) 電撃", " e) Elec Brand"), 6, 14); - else - prt("", 6, 14); - - prt("", 7, 14); - prt("", 8, 14); - prt("", 9, 14); - - prt("", 1, 0); - prt(_(" どの元素攻撃をしますか?", " Choose a temporary elemental brand "), 1, 14); - - choice = inkey(); - - if ((choice == 'a') || (choice == 'A')) - set_ele_attack(ATTACK_FIRE, p_ptr->lev/2 + randint1(p_ptr->lev/2)); - else if (((choice == 'b') || (choice == 'B')) && (num >= 2)) - set_ele_attack(ATTACK_COLD, p_ptr->lev/2 + randint1(p_ptr->lev/2)); - else if (((choice == 'c') || (choice == 'C')) && (num >= 3)) - set_ele_attack(ATTACK_POIS, p_ptr->lev/2 + randint1(p_ptr->lev/2)); - else if (((choice == 'd') || (choice == 'D')) && (num >= 4)) - set_ele_attack(ATTACK_ACID, p_ptr->lev/2 + randint1(p_ptr->lev/2)); - else if (((choice == 'e') || (choice == 'E')) && (num >= 5)) - set_ele_attack(ATTACK_ELEC, p_ptr->lev/2 + randint1(p_ptr->lev/2)); - else - { - msg_print(_("魔法剣を使うのをやめた。", "You cancel the temporary branding.")); - screen_load(); - return FALSE; - } - screen_load(); - return TRUE; -} - - -/* - * Choose a elemental immune. -LM- - */ -bool choose_ele_immune(TIME_EFFECT immune_turn) -{ - char choice; - screen_save(); - - c_prt(TERM_RED, _(" a) 火炎", " a) Immune Fire"), 2, 14); - c_prt(TERM_L_WHITE,_(" b) 冷気", " b) Immune Cold"), 3, 14); - c_prt(TERM_L_DARK, _(" c) 酸", " c) Immune Acid"), 4, 14); - c_prt(TERM_BLUE, _(" d) 電撃", " d) Immune Elec"), 5, 14); - - prt("", 6, 14); - prt("", 7, 14); - prt("", 8, 14); - prt("", 9, 14); - - prt("", 1, 0); - prt(_(" どの元素の免疫をつけますか?", " Choose a temporary elemental immune "), 1, 14); - - choice = inkey(); - - if ((choice == 'a') || (choice == 'A')) - set_ele_immune(DEFENSE_FIRE, immune_turn); - else if ((choice == 'b') || (choice == 'B')) - set_ele_immune(DEFENSE_COLD, immune_turn); - else if ((choice == 'c') || (choice == 'C')) - set_ele_immune(DEFENSE_ACID, immune_turn); - else if ((choice == 'd') || (choice == 'D')) - set_ele_immune(DEFENSE_ELEC, immune_turn); - else - { - msg_print(_("免疫を付けるのをやめた。", "You cancel the temporary immune.")); - screen_load(); - return FALSE; - } - screen_load(); - return TRUE; -} - diff --git a/src/externs.h b/src/externs.h deleted file mode 100644 index 01beb6bde..000000000 --- a/src/externs.h +++ /dev/null @@ -1,1323 +0,0 @@ -/*! - * @file externs.h - * @brief Angband(変愚蛮怒)基本関数、グローバル変数ヘッダファイル / - * extern declarations (variables and functions) - * @date 2014/08/08 - * @author - * Copyright (c) 1997 Ben Harrison - * @details - * This software may be copied and distributed for educational, research, - * and not for profit purposes provided that this copyright and statement - * are included in all such copies. - * Note that some files have their own header files - * (z-virt.h, z-util.h, z-form.h, term.h, random.h) - */ -#include "geometry.h" - -/* - * Automatically generated "variable" declarations - */ -extern int max_macrotrigger; -extern concptr macro_template; -extern concptr macro_modifier_chr; -extern concptr macro_modifier_name[MAX_MACRO_MOD]; -extern concptr macro_trigger_name[MAX_MACRO_TRIG]; -extern concptr macro_trigger_keycode[2][MAX_MACRO_TRIG]; - -extern int level_up; - -/* - * List for auto-picker/destroyer entries - */ -extern int max_autopick; -extern int max_max_autopick; -extern autopick_type *autopick_list; - -/* tables.c */ -extern const POSITION ddd[9]; -extern const POSITION ddx[10]; -extern const POSITION ddy[10]; -extern const POSITION ddx_ddd[9]; -extern const POSITION ddy_ddd[9]; -extern const POSITION cdd[8]; -extern const POSITION ddx_cdd[8]; -extern const POSITION ddy_cdd[8]; -extern const char hexsym[16]; -extern const char listsym[]; -extern const concptr color_char; -extern const byte adj_mag_study[]; -extern const byte adj_mag_mana[]; -extern const byte adj_mag_fail[]; -extern const byte adj_mag_stat[]; -extern const byte adj_chr_gold[]; -extern const byte adj_int_dev[]; -extern const byte adj_wis_sav[]; -extern const byte adj_dex_dis[]; -extern const byte adj_int_dis[]; -extern const byte adj_dex_ta[]; -extern const byte adj_str_td[]; -extern const byte adj_dex_th[]; -extern const byte adj_str_th[]; -extern const byte adj_str_wgt[]; -extern const byte adj_str_hold[]; -extern const byte adj_str_dig[]; -extern const byte adj_str_blow[]; -extern const byte adj_dex_blow[]; -extern const byte adj_dex_safe[]; -extern const byte adj_con_fix[]; -extern const byte adj_con_mhp[]; -extern const byte adj_chr_chm[]; -extern const byte blows_table[12][12]; -extern const arena_type arena_info[MAX_ARENA_MONS + 2]; -extern const byte extract_energy[200]; -extern const s32b player_exp[PY_MAX_LEVEL]; -extern const s32b player_exp_a[PY_MAX_LEVEL]; -extern const player_sex sex_info[MAX_SEXES]; -extern const player_race race_info[MAX_RACES]; -extern const player_class class_info[MAX_CLASS]; -extern const magic_type technic_info[NUM_TECHNIC][32]; -extern const player_seikaku seikaku_info[MAX_SEIKAKU]; -extern const player_race mimic_info[]; -extern const u32b fake_spell_flags[4]; -extern const s32b realm_choices1[]; -extern const s32b realm_choices2[]; -extern const concptr realm_names[]; -#ifdef JP -extern const concptr E_realm_names[]; -#endif -extern const concptr spell_names[VALID_REALM][32]; -extern const concptr player_title[MAX_CLASS][PY_MAX_LEVEL/5]; -extern const concptr color_names[16]; -extern const concptr stat_names[6]; -extern const concptr stat_names_reduced[6]; -extern const concptr window_flag_desc[32]; -extern const martial_arts ma_blows[MAX_MA]; -extern const int monk_ave_damage[PY_MAX_LEVEL+1][3]; -extern const concptr game_inscriptions[]; -extern const kamae kamae_shurui[MAX_KAMAE]; -extern const kamae kata_shurui[MAX_KATA]; -extern const concptr exp_level_str[5]; -extern const concptr silly_attacks[MAX_SILLY_ATTACK]; -#ifdef JP -extern const concptr silly_attacks2[MAX_SILLY_ATTACK]; -#endif -extern const monster_power monster_powers[MAX_MONSPELLS]; -extern const concptr monster_powers_short[MAX_MONSPELLS]; -extern const concptr ident_info[]; -extern const mbe_info_type mbe_info[]; -extern const byte feature_action_flags[FF_FLAG_MAX]; -extern const dragonbreath_type dragonbreath_info[]; - -extern const option_type option_info[]; -extern const option_type cheat_info[CHEAT_MAX]; -extern const option_type autosave_info[2]; - -/* variable.c */ -extern const concptr copyright[5]; -extern byte h_ver_major; -extern byte h_ver_minor; -extern byte h_ver_patch; -extern byte h_ver_extra; -extern byte sf_extra; -extern u32b sf_system; -extern byte z_major; -extern byte z_minor; -extern byte z_patch; -extern u32b sf_when; -extern u16b sf_lives; -extern u16b sf_saves; -extern bool arg_fiddle; -extern bool arg_wizard; -extern bool arg_music; -extern bool arg_sound; -extern byte arg_graphics; -extern bool arg_monochrome; -extern bool arg_force_original; -extern bool arg_force_roguelike; -extern bool arg_bigtile; -extern bool character_generated; -extern bool character_dungeon; -extern bool character_loaded; -extern bool character_saved; -extern bool character_icky; -extern bool character_xtra; -extern bool creating_savefile; -extern u32b seed_flavor; -extern u32b seed_town; -extern COMMAND_CODE command_cmd; -extern COMMAND_ARG command_arg; -extern s16b command_rep; -extern DIRECTION command_dir; -extern s16b command_see; -extern TERM_LEN command_gap; -extern s16b command_wrk; -extern s16b command_new; -extern bool msg_flag; -extern s16b running; -extern bool invoking_midnight_curse; -extern GAME_TURN old_battle; -extern bool use_sound; -extern bool use_music; -extern bool use_graphics; -extern bool use_bigtile; -extern s16b signal_count; -extern bool inkey_base; -extern bool inkey_xtra; -extern bool inkey_scan; -extern bool inkey_flag; -extern bool get_com_no_macros; -extern OBJECT_SUBTYPE_VALUE coin_type; -extern bool opening_chest; -extern bool shimmer_monsters; -extern bool shimmer_objects; -extern bool repair_monsters; -extern bool repair_objects; -extern s16b inven_cnt; -extern s16b equip_cnt; -extern OBJECT_IDX o_max; -extern OBJECT_IDX o_cnt; -extern MONSTER_IDX m_max; -extern MONSTER_IDX m_cnt; -extern MONSTER_IDX hack_m_idx; -extern MONSTER_IDX hack_m_idx_ii; -extern int total_friends; -extern int leaving_quest; -extern bool reinit_wilderness; -extern bool multi_rew; -extern char summon_kin_type; -extern bool is_loading_now; -extern bool hack_mutation; - - -/* - * Software options (set via the '=' command). See "tables.c" - */ - - -extern char record_o_name[MAX_NLEN]; -extern GAME_TURN record_turn; -extern bool closing_flag; -extern POSITION panel_row_min, panel_row_max; -extern POSITION panel_col_min, panel_col_max; -extern POSITION panel_col_prt, panel_row_prt; -extern MONSTER_IDX target_who; -extern POSITION target_col; -extern POSITION target_row; -extern int player_uid; -extern int player_euid; -extern int player_egid; -extern char player_base[32]; -extern char savefile[1024]; -extern char savefile_base[40]; -extern pos_list tmp_pos; -extern s16b macro__num; -extern concptr *macro__pat; -extern concptr *macro__act; -extern bool *macro__cmd; -extern char *macro__buf; -extern STR_OFFSET quark__num; -extern concptr *quark__str; -extern u32b message__next; -extern u32b message__last; -extern u32b message__head; -extern u32b message__tail; -extern u32b *message__ptr; -extern char *message__buf; -extern BIT_FLAGS option_flag[8]; -extern BIT_FLAGS option_mask[8]; -extern BIT_FLAGS window_flag[8]; -extern BIT_FLAGS window_mask[8]; -extern term *angband_term[8]; -extern const char angband_term_name[8][16]; -extern byte angband_color_table[256][4]; -extern const concptr angband_sound_name[SOUND_MAX]; -extern const concptr angband_music_basic_name[MUSIC_BASIC_MAX]; -extern floor_type *current_floor_ptr; -extern world_type *current_world_ptr; -extern saved_floor_type saved_floors[MAX_SAVED_FLOORS]; -extern FLOOR_IDX max_floor_id; -extern u32b saved_floor_file_sign; -extern TOWN_IDX max_towns; -extern town_type *town_info; -extern object_type *inventory; -extern s16b alloc_kind_size; -extern alloc_entry *alloc_kind_table; -extern s16b alloc_race_size; -extern alloc_entry *alloc_race_table; -extern TERM_COLOR misc_to_attr[256]; -extern SYMBOL_CODE misc_to_char[256]; -extern TERM_COLOR tval_to_attr[128]; -extern SYMBOL_CODE tval_to_char[128]; -extern concptr keymap_act[KEYMAP_MODES][256]; -extern player_type *p_ptr; -extern const player_sex *sp_ptr; -extern const player_race *rp_ptr; -extern const player_class *cp_ptr; -extern const player_seikaku *ap_ptr; -extern const player_magic *mp_ptr; -extern birther previous_char; -extern vault_type *v_info; -extern char *v_name; -extern char *v_text; -extern skill_table *s_info; -extern player_magic *m_info; -extern feature_type *f_info; -extern char *f_name; -extern char *f_tag; -extern object_kind *k_info; -extern char *k_name; -extern char *k_text; -extern artifact_type *a_info; -extern char *a_name; -extern char *a_text; -extern ego_item_type *e_info; -extern char *e_name; -extern char *e_text; -extern monster_race *r_info; -extern char *r_name; -extern char *r_text; -extern dungeon_type *d_info; -extern char *d_name; -extern char *d_text; -extern concptr ANGBAND_SYS; -extern concptr ANGBAND_KEYBOARD; -extern concptr ANGBAND_GRAF; -extern concptr ANGBAND_DIR; -extern concptr ANGBAND_DIR_APEX; -extern concptr ANGBAND_DIR_BONE; -extern concptr ANGBAND_DIR_DATA; -extern concptr ANGBAND_DIR_EDIT; -extern concptr ANGBAND_DIR_SCRIPT; -extern concptr ANGBAND_DIR_FILE; -extern concptr ANGBAND_DIR_HELP; -extern concptr ANGBAND_DIR_INFO; -extern concptr ANGBAND_DIR_PREF; -extern concptr ANGBAND_DIR_SAVE; -extern concptr ANGBAND_DIR_USER; -extern concptr ANGBAND_DIR_XTRA; -extern OBJECT_TYPE_VALUE item_tester_tval; -extern bool (*item_tester_hook)(object_type *o_ptr); -extern monsterrace_hook_type get_mon_num_hook; -extern monsterrace_hook_type get_mon_num2_hook; -extern bool (*get_obj_num_hook)(KIND_OBJECT_IDX k_idx); -extern building_type building[MAX_BLDG]; -extern QUEST_IDX max_q_idx; -extern MONRACE_IDX max_r_idx; -extern KIND_OBJECT_IDX max_k_idx; -extern VAULT_IDX max_v_idx; -extern FEAT_IDX max_f_idx; -extern ARTIFACT_IDX max_a_idx; -extern EGO_IDX max_e_idx; -extern DUNGEON_IDX max_d_idx; -extern quest_type *quest; -extern char quest_text[10][80]; -extern int quest_text_line; -extern TERM_COLOR gf_color[MAX_GF]; -extern int init_flags; -extern int highscore_fd; -extern bool can_save; -extern int cap_mon; -extern int cap_mspeed; -extern HIT_POINT cap_hp; -extern HIT_POINT cap_maxhp; -extern STR_OFFSET cap_nickname; -extern MONRACE_IDX battle_mon[4]; -extern int sel_monster; -extern int battle_odds; -extern PRICE kakekin; -extern u32b mon_odds[4]; -extern MONSTER_IDX pet_t_m_idx; -extern MONSTER_IDX riding_t_m_idx; -extern MONRACE_IDX today_mon; -extern bool write_level; -extern u32b start_time; -extern bool sukekaku; -extern bool new_mane; -extern bool mon_fight; -extern bool generate_encounter; -extern concptr screen_dump; - -/*** Terrain feature variables ***/ -extern FEAT_IDX feat_none; -extern FEAT_IDX feat_floor; -extern FEAT_IDX feat_glyph; -extern FEAT_IDX feat_explosive_rune; -extern FEAT_IDX feat_mirror; -extern FEAT_IDX feat_up_stair; -extern FEAT_IDX feat_down_stair; -extern FEAT_IDX feat_entrance; -extern FEAT_IDX feat_trap_open; -extern FEAT_IDX feat_trap_armageddon; -extern FEAT_IDX feat_trap_piranha; -extern FEAT_IDX feat_rubble; -extern FEAT_IDX feat_magma_vein; -extern FEAT_IDX feat_quartz_vein; -extern FEAT_IDX feat_granite; -extern FEAT_IDX feat_permanent; -extern FEAT_IDX feat_glass_floor; -extern FEAT_IDX feat_glass_wall; -extern FEAT_IDX feat_permanent_glass_wall; -extern FEAT_IDX feat_pattern_start; -extern FEAT_IDX feat_pattern_1; -extern FEAT_IDX feat_pattern_2; -extern FEAT_IDX feat_pattern_3; -extern FEAT_IDX feat_pattern_4; -extern FEAT_IDX feat_pattern_end; -extern FEAT_IDX feat_pattern_old; -extern FEAT_IDX feat_pattern_exit; -extern FEAT_IDX feat_pattern_corrupted; -extern FEAT_IDX feat_black_market; -extern FEAT_IDX feat_town; -extern FEAT_IDX feat_deep_water; -extern FEAT_IDX feat_shallow_water; -extern FEAT_IDX feat_deep_lava; -extern FEAT_IDX feat_shallow_lava; -extern FEAT_IDX feat_heavy_cold_zone; -extern FEAT_IDX feat_cold_zone; -extern FEAT_IDX feat_heavy_electrical_zone; -extern FEAT_IDX feat_electrical_zone; -extern FEAT_IDX feat_deep_acid_puddle; -extern FEAT_IDX feat_shallow_acid_puddle; -extern FEAT_IDX feat_deep_poisonous_puddle; -extern FEAT_IDX feat_shallow_poisonous_puddle; -extern FEAT_IDX feat_dirt; -extern FEAT_IDX feat_grass; -extern FEAT_IDX feat_flower; -extern FEAT_IDX feat_brake; -extern FEAT_IDX feat_tree; -extern FEAT_IDX feat_mountain; -extern FEAT_IDX feat_swamp; -extern FEAT_IDX feat_undetected; - -extern DEPTH *max_dlv; -extern FEAT_IDX feat_wall_outer; -extern FEAT_IDX feat_wall_inner; -extern FEAT_IDX feat_wall_solid; -extern FEAT_IDX feat_ground_type[100], feat_wall_type[100]; -extern COMMAND_CODE now_message; -extern bool use_menu; - -/* autopick.c */ -extern void autopick_load_pref(bool disp_mes); -extern errr process_autopick_file_command(char *buf); -extern concptr autopick_line_from_entry(autopick_type *entry); -extern int is_autopick(object_type *o_ptr); -extern void autopick_alter_item(INVENTORY_IDX item, bool destroy); -extern void autopick_delayed_alter(void); -extern void autopick_pickup_items(grid_type *g_ptr); -extern bool autopick_autoregister(object_type *o_ptr); -extern void do_cmd_edit_autopick(void); - -/* birth.c */ -extern void add_history_from_pref_line(concptr t); -extern void player_birth(void); -extern void get_max_stats(void); -extern void get_height_weight(void); -extern void player_outfit(void); -extern void dump_yourself(FILE *fff); - - -/* grids.c */ -extern POSITION distance(POSITION y1, POSITION x1, POSITION y2, POSITION x2); -extern bool los(POSITION y1, POSITION x1, POSITION y2, POSITION x2); -extern void update_local_illumination(POSITION y, POSITION x); -extern bool player_can_see_bold(POSITION y, POSITION x); -extern bool cave_valid_bold(POSITION y, POSITION x); -extern bool no_lite(void); -extern void apply_default_feat_lighting(TERM_COLOR f_attr[F_LIT_MAX], SYMBOL_CODE f_char[F_LIT_MAX]); -extern void map_info(POSITION y, POSITION x, TERM_COLOR *ap, SYMBOL_CODE *cp, TERM_COLOR *tap, SYMBOL_CODE *tcp); -extern void move_cursor_relative(int row, int col); -extern void print_rel(SYMBOL_CODE c, TERM_COLOR a, TERM_LEN y, TERM_LEN x); -extern void note_spot(POSITION y, POSITION x); -extern void display_dungeon(void); -extern void lite_spot(POSITION y, POSITION x); -extern void prt_map(void); -extern void prt_path(POSITION y, POSITION x); -extern void display_map(int *cy, int *cx); -extern void do_cmd_view_map(void); -extern void forget_lite(void); -extern void update_lite(void); -extern void forget_view(void); -extern void update_view(void); -extern void update_mon_lite(void); -extern void clear_mon_lite(void); -extern void delayed_visual_update(void); -extern void forget_flow(void); -extern void update_flow(void); -extern void update_smell(void); -extern void map_area(POSITION range); -extern void cave_set_feat(POSITION y, POSITION x, FEAT_IDX feat); -extern FEAT_IDX conv_dungeon_feat(FEAT_IDX newfeat); -extern FEAT_IDX feat_state(FEAT_IDX feat, int action); -extern void cave_alter_feat(POSITION y, POSITION x, int action); -extern void remove_mirror(POSITION y, POSITION x); - -extern void mmove2(POSITION *y, POSITION *x, POSITION y1, POSITION x1, POSITION y2, POSITION x2); -extern bool projectable(POSITION y1, POSITION x1, POSITION y2, POSITION x2); -extern void scatter(POSITION *yp, POSITION *xp, POSITION y, POSITION x, POSITION d, BIT_FLAGS mode); -extern void health_track(MONSTER_IDX m_idx); -extern void monster_race_track(MONRACE_IDX r_idx); -extern void object_kind_track(KIND_OBJECT_IDX k_idx); -extern void glow_deep_lava_and_bldg(void); -extern bool cave_monster_teleportable_bold(MONSTER_IDX m_idx, POSITION y, POSITION x, BIT_FLAGS mode); -extern bool cave_player_teleportable_bold(POSITION y, POSITION x, BIT_FLAGS mode); -extern bool is_open(FEAT_IDX feat); - -/* cmd1.c */ -extern HIT_POINT critical_shot(WEIGHT weight, int plus_ammo, int plus_bow, HIT_POINT dam); -extern void search(void); -extern void py_pickup_aux(OBJECT_IDX o_idx); -extern void carry(bool pickup); -extern bool pattern_seq(POSITION c_y, POSITION c_x, POSITION n_y, POSITION n_x); -extern bool player_can_enter(FEAT_IDX feature, BIT_FLAGS16 mode); -extern bool move_player_effect(POSITION ny, POSITION nx, BIT_FLAGS mpe_mode); -extern bool trap_can_be_ignored(FEAT_IDX feat); -extern void move_player(DIRECTION dir, bool do_pickup, bool break_trap); -extern void run_step(DIRECTION dir); -#ifdef TRAVEL -extern void travel_step(void); -#endif - -/* cmd2.c */ -extern bool cmd_limit_cast(player_type *creature_ptr); -extern bool cmd_limit_arena(player_type *creature_ptr); -extern bool cmd_limit_time_walk(player_type *creature_ptr); -extern bool cmd_limit_blind(player_type *creature_ptr); -extern bool cmd_limit_confused(player_type *creature_ptr); -extern bool cmd_limit_image(player_type *creature_ptr); -extern bool cmd_limit_stun(player_type *creature_ptr); -extern void forget_travel_flow(void); -extern void do_cmd_go_up(void); -extern void do_cmd_go_down(void); -extern void do_cmd_search(void); -extern void do_cmd_open(void); -extern void do_cmd_close(void); -extern void do_cmd_tunnel(void); -extern void do_cmd_disarm(void); -extern void do_cmd_bash(void); -extern void do_cmd_alter(void); -extern void do_cmd_spike(void); -extern void do_cmd_walk(bool pickup); -extern void do_cmd_stay(bool pickup); -extern void do_cmd_run(void); -extern void do_cmd_rest(void); -extern void do_cmd_fire(SPELL_IDX snipe_type); -extern void exe_fire(INVENTORY_IDX item, object_type *j_ptr, SPELL_IDX snipe_type); -extern bool do_cmd_throw(int mult, bool boomerang, OBJECT_IDX shuriken); -#ifdef TRAVEL -extern void do_cmd_travel(void); -#endif -extern bool easy_open_door(POSITION y, POSITION x); -extern bool do_cmd_disarm_aux(POSITION y, POSITION x, DIRECTION dir); - -/* cmd4.c */ -#ifndef JP -extern concptr get_ordinal_number_suffix(int num); -#endif -extern errr do_cmd_write_nikki(int type, int num, concptr note); -extern void do_cmd_nikki(void); -extern void do_cmd_redraw(void); -extern void do_cmd_change_name(void); -extern void do_cmd_message_one(void); -extern void do_cmd_messages(int num_now); -extern void do_cmd_options_aux(int page, concptr info); -extern void do_cmd_options(void); -extern void do_cmd_pref(void); -extern void do_cmd_reload_autopick(void); -extern void do_cmd_macros(void); -extern void do_cmd_visuals(void); -extern void do_cmd_colors(void); -extern void do_cmd_note(void); -extern void do_cmd_version(void); -extern void do_cmd_feeling(void); -extern void do_cmd_load_screen(void); -extern void do_cmd_save_screen_html_aux(char *filename, int message); -extern void do_cmd_save_screen(void); -extern void do_cmd_knowledge_quests_completed(FILE *fff, QUEST_IDX quest_num[]); -extern void do_cmd_knowledge_quests_failed(FILE *fff, QUEST_IDX quest_num[]); -extern void do_cmd_knowledge(void); -extern void plural_aux(char * Name); -extern void do_cmd_checkquest(void); -extern void do_cmd_time(void); -extern void do_cmd_suicide(void); - -/* cmd-spell.c */ -extern concptr do_spell(REALM_IDX realm, SPELL_IDX spell, BIT_FLAGS mode); -extern bool trump_summoning(int num, bool pet, POSITION y, POSITION x, DEPTH lev, int type, BIT_FLAGS mode); - -/* dungeon.c */ -extern void extract_option_vars(void); -extern void determine_bounty_uniques(void); -extern void determine_today_mon(bool conv_old); -extern void play_game(bool new_game); -extern s32b turn_real(s32b hoge); -extern void prevent_turn_overflow(void); -extern void close_game(void); - - -/* files.c */ -extern void safe_setuid_drop(void); -extern void safe_setuid_grab(void); -extern s16b tokenize(char *buf, s16b num, char **tokens, BIT_FLAGS mode); -extern void display_player(int mode); -extern errr make_character_dump(FILE *fff); -extern errr file_character(concptr name); -extern errr process_pref_file_command(char *buf); -extern concptr process_pref_file_expr(char **sp, char *fp); -extern errr process_pref_file(concptr name); -extern errr process_autopick_file(concptr name); -extern errr process_histpref_file(concptr name); -extern void print_equippy(void); -extern void display_player_equippy(TERM_LEN y, TERM_LEN x, BIT_FLAGS16 mode); -extern errr check_time_init(void); -extern errr check_load_init(void); -extern errr check_time(void); -extern errr check_load(void); -extern bool show_file(bool show_version, concptr name, concptr what, int line, BIT_FLAGS mode); -extern void do_cmd_help(void); -extern void process_player_name(bool sf); -extern void get_name(void); -extern void do_cmd_save_game(int is_autosave); -extern void do_cmd_save_and_exit(void); -extern long total_points(void); -extern void exit_game_panic(void); -extern void signals_ignore_tstp(void); -extern void signals_handle_tstp(void); -extern void signals_init(void); -extern errr get_rnd_line(concptr file_name, int entry, char *output); -extern void print_tomb(void); -extern void show_info(void); -extern bool check_score(void); - -#ifdef JP -extern errr get_rnd_line_jonly(concptr file_name, int entry, char *output, int count); -#endif -extern errr counts_write(int where, u32b count); -extern u32b counts_read(int where); - -/* flavor.c */ -extern void get_table_name_aux(char *out_string); -extern void get_table_name(char *out_string); -extern void get_table_sindarin_aux(char *out_string); -extern void get_table_sindarin(char *out_string); -extern void flavor_init(void); -extern char *object_desc_kosuu(char *t, object_type *o_ptr); -extern void object_desc(char *buf, object_type *o_ptr, BIT_FLAGS mode); - -/* floors.c */ -extern void clear_saved_floor_files(void); -extern saved_floor_type *get_sf_ptr(FLOOR_IDX floor_id); -extern FLOOR_IDX get_new_floor_id(void); -extern void prepare_change_floor_mode(BIT_FLAGS mode); -extern void precalc_cur_num_of_pet(void); -extern void stair_creation(void); - -/* init1.c */ -extern TERM_COLOR color_char_to_attr(SYMBOL_CODE c); -extern s16b f_tag_to_index(concptr str); -extern errr process_dungeon_file(concptr name, int ymin, int xmin, int ymax, int xmax); - -/* init2.c */ -extern void init_file_paths(char *libpath, char *varpath); -extern concptr err_str[PARSE_ERROR_MAX]; -extern errr init_v_info(void); -extern errr init_buildings(void); -extern s16b f_tag_to_index_in_init(concptr str); -extern void init_angband(void); -extern concptr get_check_sum(void); - -/* load.c */ -extern errr rd_savefile_new(void); -extern bool load_floor(saved_floor_type *sf_ptr, BIT_FLAGS mode); - -/* monster-process.c */ -extern bool test_hit_fire(int chance, monster_type *m_ptr, int vis, char* o_name); -extern void process_monsters(void); -extern void process_monster(MONSTER_IDX m_idx); -extern int get_mproc_idx(MONSTER_IDX m_idx, int mproc_type); -extern void mproc_init(void); -extern bool set_monster_csleep(MONSTER_IDX m_idx, int v); -extern bool set_monster_fast(MONSTER_IDX m_idx, int v); -extern bool set_monster_slow(MONSTER_IDX m_idx, int v); -extern bool set_monster_stunned(MONSTER_IDX m_idx, int v); -extern bool set_monster_confused(MONSTER_IDX m_idx, int v); -extern bool set_monster_monfear(MONSTER_IDX m_idx, int v); -extern bool set_monster_invulner(MONSTER_IDX m_idx, int v, bool energy_need); -extern void process_monsters_mtimed(int mtimed_idx); -extern void dispel_monster_status(MONSTER_IDX m_idx); -extern void mon_take_hit_mon(MONSTER_IDX m_idx, HIT_POINT dam, bool *dead, bool *fear, concptr note, MONSTER_IDX who); -extern bool process_the_world(int num, MONSTER_IDX who, bool vs_player); -extern void monster_gain_exp(MONSTER_IDX m_idx, MONRACE_IDX s_idx); - - -/* monster2.c */ -extern void set_target(monster_type *m_ptr, POSITION y, POSITION x); -extern void reset_target(monster_type *m_ptr); -extern monster_race *real_r_ptr(monster_type *m_ptr); -extern MONRACE_IDX real_r_idx(monster_type *m_ptr); -extern void delete_monster_idx(MONSTER_IDX i); -extern void delete_monster(POSITION y, POSITION x); -extern void compact_monsters(int size); -extern void wipe_m_list(void); -extern MONSTER_IDX m_pop(void); -extern errr get_mon_num_prep(monsterrace_hook_type monster_hook, monsterrace_hook_type monster_hook2); -extern MONRACE_IDX get_mon_num(DEPTH level); -extern int lore_do_probe(MONRACE_IDX r_idx); -extern void lore_treasure(MONSTER_IDX m_idx, ITEM_NUMBER num_item, ITEM_NUMBER num_gold); -extern void update_monster(MONSTER_IDX m_idx, bool full); -extern void update_monsters(bool full); -extern bool multiply_monster(MONSTER_IDX m_idx, bool clone, BIT_FLAGS mode); -extern void update_smart_learn(MONSTER_IDX m_idx, int what); -extern void choose_new_monster(MONSTER_IDX m_idx, bool born, MONRACE_IDX r_idx); -extern SPEED get_mspeed(monster_race *r_ptr); -extern void monster_drop_carried_objects(monster_type *m_ptr); - -/* object1.c */ -extern void reset_visuals(void); -extern void object_flags(object_type *o_ptr, BIT_FLAGS flgs[TR_FLAG_SIZE]); -extern void object_flags_known(object_type *o_ptr, BIT_FLAGS flgs[TR_FLAG_SIZE]); -extern concptr item_activation(object_type *o_ptr); -extern bool screen_object(object_type *o_ptr, BIT_FLAGS mode); -extern char index_to_label(int i); -extern INVENTORY_IDX label_to_inven(int c); -extern INVENTORY_IDX label_to_equip(int c); -extern s16b wield_slot(object_type *o_ptr); -extern concptr mention_use(int i); -extern concptr describe_use(int i); -extern bool check_book_realm(const OBJECT_TYPE_VALUE book_tval, const OBJECT_SUBTYPE_VALUE book_sval); -extern bool item_tester_okay(object_type *o_ptr); -extern void display_inven(void); -extern void display_equip(void); -extern COMMAND_CODE show_inven(int target_item, BIT_FLAGS mode); -extern COMMAND_CODE show_equip(int target_item, BIT_FLAGS mode); -extern void toggle_inven_equip(void); -extern bool can_get_item(void); -extern bool get_item(OBJECT_IDX *cp, concptr pmt, concptr str, BIT_FLAGS mode); -extern object_type *choose_object(OBJECT_IDX *idx, concptr q, concptr s, BIT_FLAGS option); -PERCENTAGE breakage_chance(object_type *o_ptr, SPELL_IDX snipe_type); - -/* object2.c */ -extern void excise_object_idx(OBJECT_IDX o_idx); -extern void delete_object_idx(OBJECT_IDX o_idx); -extern void delete_object(POSITION y, POSITION x); -extern void compact_objects(int size); -extern void wipe_o_list(void); -extern OBJECT_IDX o_pop(void); -extern OBJECT_IDX get_obj_num(DEPTH level); -extern void object_known(object_type *o_ptr); -extern void object_aware(object_type *o_ptr); -extern void object_tried(object_type *o_ptr); -extern byte value_check_aux1(object_type *o_ptr); -extern byte value_check_aux2(object_type *o_ptr); -extern PRICE object_value(object_type *o_ptr); -extern PRICE object_value_real(object_type *o_ptr); -extern void distribute_charges(object_type *o_ptr, object_type *q_ptr, int amt); -extern void reduce_charges(object_type *o_ptr, int amt); -extern int object_similar_part(object_type *o_ptr, object_type *j_ptr); -extern bool object_similar(object_type *o_ptr, object_type *j_ptr); -extern void object_absorb(object_type *o_ptr, object_type *j_ptr); -extern IDX lookup_kind(OBJECT_TYPE_VALUE tval, OBJECT_SUBTYPE_VALUE sval); -extern void object_wipe(object_type *o_ptr); -extern void object_prep(object_type *o_ptr, KIND_OBJECT_IDX k_idx); -extern void object_copy(object_type *o_ptr, object_type *j_ptr); -extern void apply_magic(object_type *o_ptr, DEPTH lev, BIT_FLAGS mode); -extern bool make_object(object_type *j_ptr, BIT_FLAGS mode); -extern void place_object(POSITION y, POSITION x, BIT_FLAGS mode); -extern bool make_gold(object_type *j_ptr); -extern void place_gold(POSITION y, POSITION x); -extern OBJECT_IDX drop_near(object_type *o_ptr, PERCENTAGE chance, POSITION y, POSITION x); -extern void inven_item_charges(INVENTORY_IDX item); -extern void inven_item_describe(INVENTORY_IDX item); -extern void inven_item_increase(INVENTORY_IDX item, ITEM_NUMBER num); -extern void inven_item_optimize(INVENTORY_IDX item); -extern void floor_item_charges(INVENTORY_IDX item); -extern void floor_item_describe(INVENTORY_IDX item); -extern void floor_item_increase(INVENTORY_IDX item, ITEM_NUMBER num); -extern void floor_item_optimize(INVENTORY_IDX item); -extern bool inven_carry_okay(object_type *o_ptr); -extern bool object_sort_comp(object_type *o_ptr, s32b o_value, object_type *j_ptr); -extern s16b inven_carry(object_type *o_ptr); -extern INVENTORY_IDX inven_takeoff(INVENTORY_IDX item, ITEM_NUMBER amt); -extern void inven_drop(INVENTORY_IDX item, ITEM_NUMBER amt); -extern void combine_pack(void); -extern void reorder_pack(void); -extern void display_koff(KIND_OBJECT_IDX k_idx); -extern void torch_flags(object_type *o_ptr, BIT_FLAGS *flgs); -extern void torch_dice(object_type *o_ptr, DICE_NUMBER *dd, DICE_SID *ds); -extern void torch_lost_fuel(object_type *o_ptr); -extern concptr essence_name[]; - -/* racial.c */ -extern void do_cmd_racial_power(void); - -/* save.c */ -extern bool save_player(void); -extern bool load_player(void); -extern void remove_loc(void); -extern bool save_floor(saved_floor_type *sf_ptr, BIT_FLAGS mode); - -/* spells1.c */ -extern PERCENTAGE beam_chance(void); -extern bool in_disintegration_range(POSITION y1, POSITION x1, POSITION y2, POSITION x2); -extern void breath_shape(u16b *path_g, int dist, int *pgrids, POSITION *gx, POSITION *gy, POSITION *gm, POSITION *pgm_rad, POSITION rad, POSITION y1, POSITION x1, POSITION y2, POSITION x2, EFFECT_ID typ); -extern int take_hit(int damage_type, HIT_POINT damage, concptr kb_str, int monspell); -extern u16b bolt_pict(POSITION y, POSITION x, POSITION ny, POSITION nx, EFFECT_ID typ); -extern POSITION dist_to_line(POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION y2, POSITION x2); -extern bool project(MONSTER_IDX who, POSITION rad, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ, BIT_FLAGS flg, int monspell); -extern int project_length; -extern bool binding_field(HIT_POINT dam); -extern void seal_of_mirror(HIT_POINT dam); -extern concptr spell_category_name(OBJECT_TYPE_VALUE tval); - -/* spells2.c */ -extern void message_pain(MONSTER_IDX m_idx, HIT_POINT dam); -extern bool detect_traps(POSITION range, bool known); -extern bool detect_doors(POSITION range); -extern bool detect_stairs(POSITION range); -extern bool detect_treasure(POSITION range); -extern bool detect_objects_gold(POSITION range); -extern bool detect_objects_normal(POSITION range); -extern bool detect_objects_magic(POSITION range); -extern bool detect_monsters_normal(POSITION range); -extern bool detect_monsters_invis(POSITION range); -extern bool detect_monsters_evil(POSITION range); -extern bool detect_monsters_xxx(POSITION range, u32b match_flag); -extern bool detect_monsters_string(POSITION range, concptr); -extern bool detect_monsters_nonliving(POSITION range); -extern bool detect_monsters_mind(POSITION range); -extern bool detect_all(POSITION range); -extern bool wall_stone(void); -extern bool speed_monsters(void); -extern bool slow_monsters(int power); -extern bool sleep_monsters(int power); -extern void aggravate_monsters(MONSTER_IDX who); -extern bool genocide_aux(MONSTER_IDX m_idx, int power, bool player_cast, int dam_side, concptr spell_name); -extern bool symbol_genocide(int power, bool player_cast); -extern bool mass_genocide(int power, bool player_cast); -extern bool mass_genocide_undead(int power, bool player_cast); -extern bool probing(void); -extern bool banish_evil(int dist); -extern bool dispel_evil(HIT_POINT dam); -extern bool dispel_good(HIT_POINT dam); -extern bool dispel_undead(HIT_POINT dam); -extern bool dispel_monsters(HIT_POINT dam); -extern bool dispel_living(HIT_POINT dam); -extern bool dispel_demons(HIT_POINT dam); -extern bool cleansing_nova(player_type *creature_ptr, bool magic, bool powerful); -extern bool unleash_mana_storm(player_type *creature_ptr, bool powerful); -extern bool crusade(void); -extern bool turn_undead(void); -extern bool destroy_area(POSITION y1, POSITION x1, POSITION r, bool in_generate); -extern bool earthquake_aux(POSITION cy, POSITION cx, POSITION r, MONSTER_IDX m_idx); -extern bool earthquake(POSITION cy, POSITION cx, POSITION r); -extern void lite_room(POSITION y1, POSITION x1); -extern bool starlight(bool magic); -extern void unlite_room(POSITION y1, POSITION x1); -extern bool lite_area(HIT_POINT dam, POSITION rad); -extern bool unlite_area(HIT_POINT dam, POSITION rad); -extern bool fire_ball(EFFECT_ID typ, DIRECTION dir, HIT_POINT dam, POSITION rad); -extern bool fire_breath(EFFECT_ID typ, DIRECTION dir, HIT_POINT dam, POSITION rad); -extern bool fire_rocket(EFFECT_ID typ, DIRECTION dir, HIT_POINT dam, POSITION rad); -extern bool fire_ball_hide(EFFECT_ID typ, DIRECTION dir, HIT_POINT dam, POSITION rad); -extern bool fire_meteor(MONSTER_IDX who, EFFECT_ID typ, POSITION x, POSITION y, HIT_POINT dam, POSITION rad); -extern bool fire_bolt(EFFECT_ID typ, DIRECTION dir, HIT_POINT dam); -extern bool fire_blast(EFFECT_ID typ, DIRECTION dir, DICE_NUMBER dd, DICE_SID ds, int num, int dev); -extern void call_chaos(void); -extern bool fire_beam(EFFECT_ID typ, DIRECTION dir, HIT_POINT dam); -extern bool fire_bolt_or_beam(PERCENTAGE prob, EFFECT_ID typ, DIRECTION dir, HIT_POINT dam); -extern bool lite_line(DIRECTION dir, HIT_POINT dam); -extern bool hypodynamic_bolt(DIRECTION dir, HIT_POINT dam); -extern bool death_ray(DIRECTION dir, PLAYER_LEVEL plev); -extern bool wall_to_mud(DIRECTION dir, HIT_POINT dam); -extern bool destroy_door(DIRECTION dir); -extern bool disarm_trap(DIRECTION dir); -extern bool wizard_lock(DIRECTION dir); -extern bool teleport_monster(DIRECTION dir, int distance); -extern bool door_creation(void); -extern bool trap_creation(POSITION y, POSITION x); -extern bool tree_creation(void); -extern bool glyph_creation(void); -extern bool destroy_doors_touch(void); -extern bool disarm_traps_touch(void); -extern bool animate_dead(MONSTER_IDX who, POSITION y, POSITION x); -extern bool sleep_monsters_touch(void); -extern bool activate_ty_curse(bool stop_ty, int *count); -extern int activate_hi_summon(POSITION y, POSITION x, bool can_pet); -extern void wall_breaker(void); -extern bool confuse_monsters(HIT_POINT dam); -extern bool charm_monsters(HIT_POINT dam); -extern bool charm_animals(HIT_POINT dam); -extern bool stun_monsters(HIT_POINT dam); -extern bool stasis_monsters(HIT_POINT dam); -extern bool banish_monsters(int dist); -extern bool turn_monsters(HIT_POINT dam); -extern bool turn_evil(HIT_POINT dam); -extern bool deathray_monsters(void); -extern bool charm_monster(DIRECTION dir, PLAYER_LEVEL plev); -extern bool control_one_undead(DIRECTION dir, PLAYER_LEVEL plev); -extern bool control_one_demon(DIRECTION dir, PLAYER_LEVEL plev); -extern bool charm_animal(DIRECTION dir, PLAYER_LEVEL plev); -extern bool mindblast_monsters(HIT_POINT dam); -extern s32b flag_cost(object_type *o_ptr, int plusses); -extern bool teleport_swap(DIRECTION dir); -extern bool project_hook(EFFECT_ID typ, DIRECTION dir, HIT_POINT dam, BIT_FLAGS flg); -extern bool project_all_los(EFFECT_ID typ, HIT_POINT dam); -extern bool eat_magic(int power); -extern void discharge_minion(void); -extern bool kawarimi(bool success); -extern bool rush_attack(bool *mdeath); -extern void remove_all_mirrors(bool explode); -extern void ring_of_power(DIRECTION dir); -extern void wild_magic(int spell); -extern void cast_meteor(HIT_POINT dam, POSITION rad); -extern bool cast_wrath_of_the_god(HIT_POINT dam, POSITION rad); -extern void cast_wonder(DIRECTION dir); -extern void cast_invoke_spirits(DIRECTION dir); -extern void cast_shuffle(void); -extern void stop_mouth(void); -extern bool_hack vampirism(void); -extern bool panic_hit(void); -extern bool psychometry(void); -extern bool draconian_breath(player_type *creature_ptr); -extern bool android_inside_weapon(player_type *creature_ptr); -extern bool create_ration(player_type *crature_ptr); -extern void hayagake(player_type *creature_ptr); -extern bool double_attack(player_type *creature_ptr); -extern bool comvert_hp_to_mp(player_type *creature_ptr); -extern bool comvert_mp_to_hp(player_type *creature_ptr); -extern bool demonic_breath(player_type *creature_ptr); -extern bool mirror_concentration(player_type *creature_ptr); -extern bool sword_dancing(player_type *creature_ptr); -extern bool confusing_light(player_type *creature_ptr); -extern bool rodeo(player_type *creature_ptr); -extern bool clear_mind(player_type *creature_ptr); -extern bool concentration(player_type *creature_ptr); - -/* spells3.c */ -extern bool teleport_away(MONSTER_IDX m_idx, POSITION dis, BIT_FLAGS mode); -extern void teleport_monster_to(MONSTER_IDX m_idx, POSITION ty, POSITION tx, int power, BIT_FLAGS mode); -extern bool teleport_player_aux(POSITION dis, BIT_FLAGS mode); -extern void teleport_player(POSITION dis, BIT_FLAGS mode); -extern void teleport_player_away(MONSTER_IDX m_idx, POSITION dis); -extern void teleport_player_to(POSITION ny, POSITION nx, BIT_FLAGS mode); -extern void teleport_away_followable(MONSTER_IDX m_idx); -extern bool teleport_level_other(player_type *creature_ptr); -extern void teleport_level(MONSTER_IDX m_idx); -extern DUNGEON_IDX choose_dungeon(concptr note, POSITION y, POSITION x); -extern bool recall_player(player_type *creature_ptr, TIME_EFFECT turns); -extern bool free_level_recall(player_type *creature_ptr); -extern bool reset_recall(void); -extern bool apply_disenchant(BIT_FLAGS mode); -extern void brand_weapon(int brand_type); -extern void call_the_(void); -extern void fetch(DIRECTION dir, WEIGHT wgt, bool require_los); -extern void alter_reality(void); -extern void identify_pack(void); -extern int remove_curse(void); -extern int remove_all_curse(void); -extern bool alchemy(void); -extern bool enchant(object_type *o_ptr, int n, int eflag); -extern bool enchant_spell(HIT_PROB num_hit, HIT_POINT num_dam, ARMOUR_CLASS num_ac); -extern bool artifact_scroll(void); -extern bool ident_spell(bool only_equip); -extern bool mundane_spell(bool only_equip); -extern bool identify_item(object_type *o_ptr); -extern bool identify_fully(bool only_equip); -extern bool recharge(int power); -extern void display_spell_list(void); -extern EXP experience_of_spell(SPELL_IDX spell, REALM_IDX use_realm); -extern MANA_POINT mod_need_mana(MANA_POINT need_mana, SPELL_IDX spell, REALM_IDX realm); -extern PERCENTAGE mod_spell_chance_1(PERCENTAGE chance); -extern PERCENTAGE mod_spell_chance_2(PERCENTAGE chance); -extern PERCENTAGE spell_chance(SPELL_IDX spell, REALM_IDX realm); -extern void print_spells(SPELL_IDX target_spell, SPELL_IDX *spells, int num, TERM_LEN y, TERM_LEN x, REALM_IDX realm); -extern bool polymorph_monster(POSITION y, POSITION x); -extern bool dimension_door(void); -extern bool mirror_tunnel(void); -extern void massacre(void); -extern bool eat_lock(void); -extern bool shock_power(void); -extern bool booze(player_type *creature_ptr); -extern bool detonation(player_type *creature_ptr); -extern void blood_curse_to_enemy(MONSTER_IDX m_idx); -extern bool fire_crimson(void); - - -/* bldg.c */ -extern void battle_monsters(void); -extern void do_cmd_bldg(void); -extern void do_cmd_quest(void); -extern void quest_discovery(QUEST_IDX q_idx); -extern bool tele_town(void); -extern HIT_POINT calc_crit_ratio_shot(HIT_POINT plus_ammo, HIT_POINT plus_bow); -extern HIT_POINT calc_expect_crit_shot(WEIGHT weight, int plus_ammo,int plus_bow, HIT_POINT dam); -extern HIT_POINT calc_expect_crit(WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, bool dokubari); - -/* util.c */ -extern errr path_parse(char *buf, int max, concptr file); -extern errr path_build(char *buf, int max, concptr path, concptr file); -extern FILE *my_fopen(concptr file, concptr mode); -extern FILE *my_fopen_temp(char *buf, int max); -extern errr my_fgets(FILE *fff, char *buf, huge n); -extern errr my_fputs(FILE *fff, concptr buf, huge n); -extern errr my_fclose(FILE *fff); -extern errr fd_kill(concptr file); -extern errr fd_move(concptr file, concptr what); -extern errr fd_copy(concptr file, concptr what); -extern int fd_make(concptr file, BIT_FLAGS mode); -extern int fd_open(concptr file, int flags); -extern errr fd_lock(int fd, int what); -extern errr fd_seek(int fd, huge n); -extern errr fd_chop(int fd, huge n); -extern errr fd_read(int fd, char *buf, huge n); -extern errr fd_write(int fd, concptr buf, huge n); -extern errr fd_close(int fd); -extern void flush(void); -extern void bell(void); -extern errr play_music(int type, int num); -extern void select_floor_music(void); -extern void sound(int num); -extern void move_cursor(int row, int col); -extern void text_to_ascii(char *buf, concptr str); -extern void ascii_to_text(char *buf, concptr str); -extern errr macro_add(concptr pat, concptr act); -extern sint macro_find_exact(concptr pat); -extern char inkey(void); -extern concptr quark_str(STR_OFFSET num); -extern void quark_init(void); -extern u16b quark_add(concptr str); -extern s32b message_num(void); -extern concptr message_str(int age); -extern void message_add(concptr msg); -extern void msg_erase(void); -extern void msg_print(concptr msg); -extern void msg_print_wizard(int cheat_type, concptr msg); -#ifndef SWIG -extern void msg_format(concptr fmt, ...); -extern void msg_format_wizard(int cheat_type, concptr fmt, ...); -#endif /* SWIG */ -extern void screen_save(void); -extern void screen_load(void); -extern void c_put_str(TERM_COLOR attr, concptr str, TERM_LEN row, TERM_LEN col); -extern void put_str(concptr str, TERM_LEN row, TERM_LEN col); -extern void c_prt(TERM_COLOR attr, concptr str, TERM_LEN row, TERM_LEN col); -extern void prt(concptr str, TERM_LEN row, TERM_LEN col); -extern void c_roff(TERM_COLOR attr, concptr str); -extern void roff(concptr str); -extern void clear_from(int row); -extern bool askfor_aux(char *buf, int len, bool numpad_cursor); -extern bool askfor(char *buf, int len); -extern bool get_string(concptr prompt, char *buf, int len); -extern bool get_check(concptr prompt); -extern bool get_check_strict(concptr prompt, BIT_FLAGS mode); -extern bool get_com(concptr prompt, char *command, bool z_escape); -extern QUANTITY get_quantity(concptr prompt, QUANTITY max); -extern void pause_line(int row); -extern void request_command(int shopping); -extern bool is_a_vowel(int ch); -extern int get_keymap_dir(char ch); -extern errr type_string(concptr str, uint len); -extern void roff_to_buf(concptr str, int wlen, char *tbuf, size_t bufsize); - -#ifdef SORT_R_INFO -extern void tag_sort(tag_type elements[], int number); -#endif /* SORT_R_INFO */ - -#ifdef SUPPORT_GAMMA -extern byte gamma_table[256]; -extern void build_gamma_table(int gamma); -#endif /* SUPPORT_GAMMA */ - -extern size_t my_strcpy(char *buf, concptr src, size_t bufsize); -extern size_t my_strcat(char *buf, concptr src, size_t bufsize); -extern char *my_strstr(concptr haystack, concptr needle); -extern char *my_strchr(concptr ptr, char ch); -extern void str_tolower(char *str); -extern int inkey_special(bool numpad_cursor); - - -/* xtra1.c */ -extern void prt_time(void); -extern concptr map_name(void); -extern int bow_tval_ammo(object_type *o_ptr); -extern void handle_stuff(void); -extern void update_output(void); -extern void print_monster_list(TERM_LEN x, TERM_LEN y, TERM_LEN max_lines); -extern void update_playtime(void); - - -/* effects.c */ -extern void set_action(ACTION_IDX typ); -extern void reset_tim_flags(void); -extern void dispel_player(void); -extern bool set_mimic(TIME_EFFECT v, IDX p, bool do_dec); -extern bool set_blind(TIME_EFFECT v); -extern bool set_confused(TIME_EFFECT v); -extern bool set_poisoned(TIME_EFFECT v); -extern bool set_afraid(TIME_EFFECT v); -extern bool set_paralyzed(TIME_EFFECT v); -extern bool set_image(TIME_EFFECT v); -extern bool set_fast(TIME_EFFECT v, bool do_dec); -extern bool set_slow(TIME_EFFECT v, bool do_dec); -extern bool set_shield(TIME_EFFECT v, bool do_dec); -extern bool set_tsubureru(TIME_EFFECT v, bool do_dec); -extern bool set_magicdef(TIME_EFFECT v, bool do_dec); -extern bool set_blessed(TIME_EFFECT v, bool do_dec); -extern bool set_hero(TIME_EFFECT v, bool do_dec); -extern bool set_shero(TIME_EFFECT v, bool do_dec); -extern bool set_protevil(TIME_EFFECT v, bool do_dec); -extern bool set_invuln(TIME_EFFECT v, bool do_dec); -extern bool set_tim_invis(TIME_EFFECT v, bool do_dec); -extern bool set_tim_infra(TIME_EFFECT v, bool do_dec); -extern bool set_tim_regen(TIME_EFFECT v, bool do_dec); -extern bool set_tim_stealth(TIME_EFFECT v, bool do_dec); -extern bool set_lightspeed(TIME_EFFECT v, bool do_dec); -extern bool set_tim_levitation(TIME_EFFECT v, bool do_dec); -extern bool set_tim_sh_touki(TIME_EFFECT v, bool do_dec); -extern bool set_tim_sh_fire(TIME_EFFECT v, bool do_dec); -extern bool set_tim_sh_holy(TIME_EFFECT v, bool do_dec); -extern bool set_tim_eyeeye(TIME_EFFECT v, bool do_dec); -extern bool set_resist_magic(TIME_EFFECT v, bool do_dec); -extern bool set_tim_reflect(TIME_EFFECT v, bool do_dec); -extern bool set_multishadow(TIME_EFFECT v, bool do_dec); -extern bool set_dustrobe(TIME_EFFECT v, bool do_dec); -extern bool set_kabenuke(TIME_EFFECT v, bool do_dec); -extern bool set_tsuyoshi(TIME_EFFECT v, bool do_dec); -extern bool set_ele_attack(u32b attack_type, TIME_EFFECT v); -extern bool set_ele_immune(u32b immune_type, TIME_EFFECT v); -extern bool set_oppose_acid(TIME_EFFECT v, bool do_dec); -extern bool set_oppose_elec(TIME_EFFECT v, bool do_dec); -extern bool set_oppose_fire(TIME_EFFECT v, bool do_dec); -extern bool set_oppose_cold(TIME_EFFECT v, bool do_dec); -extern bool set_oppose_pois(TIME_EFFECT v, bool do_dec); -extern bool set_stun(TIME_EFFECT v); -extern bool set_cut(TIME_EFFECT v); -extern bool set_food(TIME_EFFECT v); -extern bool inc_stat(int stat); -extern bool dec_stat(int stat, int amount, int permanent); -extern bool res_stat(int stat); -extern bool hp_player(int num); -extern bool do_dec_stat(int stat); -extern bool do_res_stat(int stat); -extern bool do_inc_stat(int stat); -extern bool restore_level(void); -extern bool lose_all_info(void); -extern void gain_exp_64(s32b amount, u32b amount_frac); -extern void gain_exp(s32b amount); -extern void calc_android_exp(void); -extern void lose_exp(s32b amount); -extern bool drain_exp(s32b drain, s32b slip, int hold_exp_prob); -extern void do_poly_self(void); -extern bool set_ultimate_res(TIME_EFFECT v, bool do_dec); -extern bool set_tim_res_nether(TIME_EFFECT v, bool do_dec); -extern bool set_tim_res_time(TIME_EFFECT v, bool do_dec); -extern bool choose_ele_attack(void); -extern bool choose_ele_immune(TIME_EFFECT turn); -extern bool set_wraith_form(TIME_EFFECT v, bool do_dec); -extern bool set_tim_esp(TIME_EFFECT v, bool do_dec); -extern bool set_superstealth(bool set); - -/* view-mainwindow.c */ -extern void resize_map(void); -extern void redraw_window(void); -extern bool change_panel(POSITION dy, POSITION dx); - - -/* xtra2.c */ -extern void get_screen_size(TERM_LEN *wid_p, TERM_LEN *hgt_p); -extern void panel_bounds_center(void); -extern void verify_panel(void); -extern bool target_able(MONSTER_IDX m_idx); -extern bool target_okay(void); -extern bool target_set(BIT_FLAGS mode); -extern void target_set_prepare_look(void); -extern bool get_aim_dir(DIRECTION *dp); -extern bool get_hack_dir(DIRECTION *dp); -extern bool get_direction(DIRECTION *dp, bool allow_under, bool with_steed); -extern bool get_rep_dir(DIRECTION *dp, bool under); -extern bool tgt_pt(POSITION *x, POSITION *y); -extern void do_poly_wounds(void); -extern void change_race(CHARACTER_IDX new_race, concptr effect_msg); - -/* scores.c */ -extern void display_scores_aux(int from, int to, int note, high_score *score); -extern void display_scores(int from, int to); -extern void kingly(void); -extern bool send_world_score(bool do_send); -extern errr top_twenty(void); -extern errr predict_score(void); -extern void race_legends(void); -extern void race_score(int race_num); -extern void show_highclass(void); - -/* mind.c */ -extern mind_power const mind_powers[5]; -extern void mindcraft_info(char *p, int use_mind, int power); -extern void do_cmd_mind(void); -extern void do_cmd_mind_browse(void); - - -/* mspells1.c */ -extern bool clean_shot(POSITION y1, POSITION x1, POSITION y2, POSITION x2, bool is_friend); -extern bool summon_possible(POSITION y1, POSITION x1); -extern bool raise_possible(monster_type *m_ptr); -extern bool dispel_check(MONSTER_IDX m_idx); -extern bool spell_is_inate(SPELL_IDX spell); -extern bool make_attack_spell(MONSTER_IDX m_idx); -extern void beam(MONSTER_IDX m_idx, POSITION y, POSITION x, EFFECT_ID typ, int dam_hp, int monspell, int target_type); -extern void bolt(MONSTER_IDX m_idx, POSITION y, POSITION x, EFFECT_ID typ, int dam_hp, int monspell, int target_type); -extern void breath(POSITION y, POSITION x, MONSTER_IDX m_idx, EFFECT_ID typ, int dam_hp, POSITION rad, bool breath, int monspell, int target_type); - -/* mspells2.c */ -extern void get_project_point(POSITION sy, POSITION sx, POSITION *ty, POSITION *tx, BIT_FLAGS flg); -extern bool monst_spell_monst(MONSTER_IDX m_idx); - -/* mspells3.c */ -extern bool do_cmd_cast_learned(void); -extern void learn_spell(int monspell); -extern void set_rf_masks(BIT_FLAGS *f4, BIT_FLAGS *f5, BIT_FLAGS *f6, BIT_FLAGS mode); - -/* mspells4.c */ -extern bool spell_learnable(MONSTER_IDX m_idx); -extern HIT_POINT monspell_to_player(int SPELL_NUM, POSITION y, POSITION x, MONSTER_IDX m_idx); -extern HIT_POINT monspell_to_monster(int SPELL_NUM, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx); -extern HIT_POINT monspell_damage(int SPELL_NUM, MONSTER_IDX m_idx, int TYPE); -extern HIT_POINT monspell_race_damage(int SPELL_NUM, MONRACE_IDX r_idx, int TYPE); -extern HIT_POINT monspell_bluemage_damage(int SPELL_NUM, PLAYER_LEVEL plev, int TYPE); - - -/* - * Hack -- conditional (or "bizarre") externs - */ - -#ifdef SET_UID -/* util.c */ -extern void user_name(char *buf, int id); -#endif - -#if 0 -#ifndef HAS_STRICMP -/* util.c */ -extern int stricmp(concptr a, concptr b); -#endif -#endif - -#ifndef HAVE_USLEEP -/* util.c */ -extern int usleep(huge usecs); -#endif - -#ifdef MACINTOSH -/* main-mac.c */ -/* extern void main(void); */ -#endif - -#if defined(MAC_MPW) || defined(MACH_O_CARBON) -/* Globals needed */ -extern u32b _ftype; -extern u32b _fcreator; -#endif - -#if defined(MAC_MPW) && defined(CARBON) -extern void convert_pathname(char *path); -#endif - -#if defined(MACH_O_CARBON) -extern void fsetfileinfo(concptr path, u32b fcreator, u32b ftype); -#endif - -#ifdef WINDOWS -/* main-win.c */ -/* extern int FAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, ...); */ -#endif - -/* util.c */ -extern void repeat_push(COMMAND_CODE what); -extern bool repeat_pull(COMMAND_CODE *what); -extern void repeat_check(void); - -/* variable.c */ -extern bool easy_open; - - -/* variable.c */ -extern bool easy_disarm; - - -/* object1.c */ -extern ITEM_NUMBER scan_floor(OBJECT_IDX *items, POSITION y, POSITION x, BIT_FLAGS mode); -extern COMMAND_CODE show_floor(int target_item, POSITION y, POSITION x, TERM_LEN *min_width); -extern bool get_item_floor(COMMAND_CODE *cp, concptr pmt, concptr str, BIT_FLAGS mode); -extern void py_pickup_floor(bool pickup); - -/* variable.c */ -extern bool easy_floor; - -/* wizard1.c */ -extern void spoil_random_artifact(concptr fname); - -/* wizard2.c */ -extern void strip_name(char *buf, KIND_OBJECT_IDX k_idx); -extern void cheat_death(player_type *creature_ptr); - - -#ifdef JP -/* japanese.c */ -extern void sindarin_to_kana(char *kana, concptr sindarin); -extern void jverb( concptr in , char *out , int flag); -extern void sjis2euc(char *str); -extern void euc2sjis(char *str); -extern byte codeconv(char *str); -extern bool iskanji2(concptr s, int x); -extern void guess_convert_to_system_encoding(char* strbuf, int buflen); -#endif - -#ifdef WORLD_SCORE -/* report.c */ -extern errr report_score(void); -extern concptr make_screen_dump(void); -#endif - -/* inet.c */ -extern int soc_write(int sd, char *buf, size_t sz); -extern int soc_read(int sd, char *buf, size_t sz); -extern void set_proxy(char *default_url, int default_port); -extern int connect_server(int timeout, concptr host, int port); -extern int disconnect_server(int sd); -extern concptr soc_err(void); - -#ifdef CHUUKEI -/* chuukei.c */ -extern bool chuukei_server; -extern bool chuukei_client; - -extern int connect_chuukei_server(char *server_string); -extern void browse_chuukei(void); -extern void flush_ringbuf(void); -extern void prepare_chuukei_hooks(void); -#endif - -extern void prepare_movie_hooks(void); -extern void prepare_browse_movie_aux(concptr filename); -extern void prepare_browse_movie(concptr filename); -extern void browse_movie(void); -extern bool browsing_movie; - -#ifdef TRAVEL -/* for travel */ -extern travel_type travel; -#endif - -/* variable.c (for snipers) */ -extern bool reset_concent; /* Concentration reset flag */ -extern bool is_fired; - -/* snipe.c */ -extern void reset_concentration(bool msg); -extern void display_snipe_list(void); -extern MULTIPLY tot_dam_aux_snipe (MULTIPLY mult, monster_type *m_ptr, SPELL_IDX snipe_type); -extern void do_cmd_snipe(void); -extern void do_cmd_snipe_browse(void); -extern int boost_concentration_damage(int tdam); - -extern void kamaenaoshi(INVENTORY_IDX item); diff --git a/src/feature.c b/src/feature.c deleted file mode 100644 index 4a8f6dd36..000000000 --- a/src/feature.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "angband.h" -#include "feature.h" - - -/*! - * @brief 地形が罠持ちであるかの判定を行う。 / Return TRUE if the given feature is a trap - * @param feat 地形情報のID - * @return 罠持ちの地形ならばTRUEを返す。 - */ -bool is_trap(FEAT_IDX feat) -{ - return have_flag(f_info[feat].flags, FF_TRAP); -} - -/*! - * @brief 地形が閉じたドアであるかの判定を行う。 / Return TRUE if the given grid is a closed door - * @param feat 地形情報のID - * @return 閉じたドアのある地形ならばTRUEを返す。 - */ -bool is_closed_door(FEAT_IDX feat) -{ - feature_type *f_ptr = &f_info[feat]; - - return (have_flag(f_ptr->flags, FF_OPEN) || have_flag(f_ptr->flags, FF_BASH)) && - !have_flag(f_ptr->flags, FF_MOVE); -} - diff --git a/src/feature.h b/src/feature.h deleted file mode 100644 index 1180ef8e2..000000000 --- a/src/feature.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once -extern bool is_closed_door(FEAT_IDX feat); -extern bool is_trap(FEAT_IDX feat); diff --git a/src/files.c b/src/files.c deleted file mode 100644 index 49b6dd0b4..000000000 --- a/src/files.c +++ /dev/null @@ -1,7364 +0,0 @@ -/*! - * @file files.c - * @brief ファイル入出力管理 / Purpose: code dealing with files (and death) - * @date 2014/01/28 - * @author - *
- * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
- * This software may be copied and distributed for educational, research,
- * and not for profit purposes provided that this copyright and statement
- * are included in all such copies.  Other copyrights may also apply.
- * 2014 Deskull rearranged comment for Doxygen.\n
- * 
- */ - - -#include "angband.h" -#include "world.h" -#include "player-status.h" -#include "sort.h" -#include "mutation.h" -#include "quest.h" -#include "store.h" -#include "artifact.h" -#include "avatar.h" -#include "shoot.h" -#include "player-move.h" -#include "patron.h" -#include "monster.h" -#include "monster-status.h" - - -/* - * You may or may not want to use the following "#undef". - */ -/* #undef _POSIX_SAVED_IDS */ - - -/*! - * @brief ファイルのドロップパーミッションチェック / Hack -- drop permissions - */ -void safe_setuid_drop(void) -{ - -#ifdef SET_UID - -# ifdef SAFE_SETUID - -# ifdef SAFE_SETUID_POSIX - - if (setuid(getuid()) != 0) - { - quit(_("setuid(): 正しく許可が取れません!", "setuid(): cannot set permissions correctly!")); - } - if (setgid(getgid()) != 0) - { - quit(_("setgid(): 正しく許可が取れません!", "setgid(): cannot set permissions correctly!")); - } - -# else - - if (setreuid(geteuid(), getuid()) != 0) - { - quit(_("setreuid(): 正しく許可が取れません!", "setreuid(): cannot set permissions correctly!")); - } - if (setregid(getegid(), getgid()) != 0) - { - quit(_("setregid(): 正しく許可が取れません!", "setregid(): cannot set permissions correctly!")); - } - -# endif - -# endif - -#endif - -} - - -/*! - * @brief ファイルのグラブパーミッションチェック / Hack -- grab permissions - */ -void safe_setuid_grab(void) -{ - -#ifdef SET_UID - -# ifdef SAFE_SETUID - -# ifdef SAFE_SETUID_POSIX - - if (setuid(player_euid) != 0) - { - quit(_("setuid(): 正しく許可が取れません!", "setuid(): cannot set permissions correctly!")); - } - if (setgid(player_egid) != 0) - { - quit(_("setgid(): 正しく許可が取れません!", "setgid(): cannot set permissions correctly!")); - } - -# else - - if (setreuid(geteuid(), getuid()) != 0) - { - quit(_("setreuid(): 正しく許可が取れません!", "setreuid(): cannot set permissions correctly!")); - } - if (setregid(getegid(), getgid()) != 0) - { - quit(_("setregid(): 正しく許可が取れません!", "setregid(): cannot set permissions correctly!")); - } - -# endif /* SAFE_SETUID_POSIX */ - -# endif /* SAFE_SETUID */ - -#endif /* SET_UID */ - -} - - -/*! - * @brief 各種データテキストをトークン単位に分解する / Extract the first few "tokens" from a buffer - * @param buf データテキストの参照ポインタ - * @param num トークンの数 - * @param tokens トークンを保管する文字列参照ポインタ配列 - * @param mode オプション - * @return 解釈した文字列数 - * @details - *
- * This function uses "colon" and "slash" as the delimeter characters.
- * We never extract more than "num" tokens.  The "last" token may include
- * "delimeter" characters, allowing the buffer to include a "string" token.
- * We save pointers to the tokens in "tokens", and return the number found.
- * Hack -- Attempt to handle the 'c' character formalism
- * Hack -- An empty buffer, or a final delimeter, yields an "empty" token.
- * Hack -- We will always extract at least one token
- * 
- */ -s16b tokenize(char *buf, s16b num, char **tokens, BIT_FLAGS mode) -{ - s16b i = 0; - - char *s = buf; - - - /* Process */ - while (i < num - 1) - { - char *t; - - /* Scan the string */ - for (t = s; *t; t++) - { - /* Found a delimiter */ - if ((*t == ':') || (*t == '/')) break; - - /* Handle single quotes */ - if ((mode & TOKENIZE_CHECKQUOTE) && (*t == '\'')) - { - /* Advance */ - t++; - - /* Handle backslash */ - if (*t == '\\') t++; - - /* Require a character */ - if (!*t) break; - - /* Advance */ - t++; - - /* Hack -- Require a close quote */ - if (*t != '\'') *t = '\''; - } - - /* Handle back-slash */ - if (*t == '\\') t++; - } - - /* Nothing left */ - if (!*t) break; - - /* Nuke and advance */ - *t++ = '\0'; - - /* Save the token */ - tokens[i++] = s; - - /* Advance */ - s = t; - } - - /* Save the token */ - tokens[i++] = s; - - /* Number found */ - return (i); -} - - -/* A number with a name */ -typedef struct named_num named_num; - -struct named_num -{ - concptr name; /* The name of this thing */ - int num; /* A number associated with it */ -}; - - -/* Index of spell type names */ -static named_num gf_desc[] = -{ - {"GF_ELEC", GF_ELEC }, - {"GF_POIS", GF_POIS }, - {"GF_ACID", GF_ACID }, - {"GF_COLD", GF_COLD }, - {"GF_FIRE", GF_FIRE }, - {"GF_PSY_SPEAR", GF_PSY_SPEAR }, - {"GF_MISSILE", GF_MISSILE }, - {"GF_ARROW", GF_ARROW }, - {"GF_PLASMA", GF_PLASMA }, - {"GF_WATER", GF_WATER }, - {"GF_LITE", GF_LITE }, - {"GF_DARK", GF_DARK }, - {"GF_LITE_WEAK", GF_LITE_WEAK }, - {"GF_DARK_WEAK", GF_DARK_WEAK }, - {"GF_SHARDS", GF_SHARDS }, - {"GF_SOUND", GF_SOUND }, - {"GF_CONFUSION", GF_CONFUSION }, - {"GF_FORCE", GF_FORCE }, - {"GF_INERTIA", GF_INERTIAL }, - {"GF_MANA", GF_MANA }, - {"GF_METEOR", GF_METEOR }, - {"GF_ICE", GF_ICE }, - {"GF_CHAOS", GF_CHAOS }, - {"GF_NETHER", GF_NETHER }, - {"GF_DISENCHANT", GF_DISENCHANT }, - {"GF_NEXUS", GF_NEXUS }, - {"GF_TIME", GF_TIME }, - {"GF_GRAVITY", GF_GRAVITY }, - {"GF_KILL_WALL", GF_KILL_WALL }, - {"GF_KILL_DOOR", GF_KILL_DOOR }, - {"GF_KILL_TRAP", GF_KILL_TRAP }, - {"GF_MAKE_WALL", GF_MAKE_WALL }, - {"GF_MAKE_DOOR", GF_MAKE_DOOR }, - {"GF_MAKE_TRAP", GF_MAKE_TRAP }, - {"GF_MAKE_TREE", GF_MAKE_TREE }, - {"GF_OLD_CLONE", GF_OLD_CLONE }, - {"GF_OLD_POLY", GF_OLD_POLY }, - {"GF_OLD_HEAL", GF_OLD_HEAL }, - {"GF_OLD_SPEED", GF_OLD_SPEED }, - {"GF_OLD_SLOW", GF_OLD_SLOW }, - {"GF_OLD_CONF", GF_OLD_CONF }, - {"GF_OLD_SLEEP", GF_OLD_SLEEP }, - {"GF_HYPODYNAMIA", GF_HYPODYNAMIA }, - {"GF_AWAY_UNDEAD", GF_AWAY_UNDEAD }, - {"GF_AWAY_EVIL", GF_AWAY_EVIL }, - {"GF_AWAY_ALL", GF_AWAY_ALL }, - {"GF_TURN_UNDEAD", GF_TURN_UNDEAD }, - {"GF_TURN_EVIL", GF_TURN_EVIL }, - {"GF_TURN_ALL", GF_TURN_ALL }, - {"GF_DISP_UNDEAD", GF_DISP_UNDEAD }, - {"GF_DISP_EVIL", GF_DISP_EVIL }, - {"GF_DISP_ALL", GF_DISP_ALL }, - {"GF_DISP_DEMON", GF_DISP_DEMON }, - {"GF_DISP_LIVING", GF_DISP_LIVING }, - {"GF_ROCKET", GF_ROCKET }, - {"GF_NUKE", GF_NUKE }, - {"GF_MAKE_GLYPH", GF_MAKE_GLYPH }, - {"GF_STASIS", GF_STASIS }, - {"GF_STONE_WALL", GF_STONE_WALL }, - {"GF_DEATH_RAY", GF_DEATH_RAY }, - {"GF_STUN", GF_STUN }, - {"GF_HOLY_FIRE", GF_HOLY_FIRE }, - {"GF_HELL_FIRE", GF_HELL_FIRE }, - {"GF_DISINTEGRATE", GF_DISINTEGRATE }, - {"GF_CHARM", GF_CHARM }, - {"GF_CONTROL_UNDEAD", GF_CONTROL_UNDEAD }, - {"GF_CONTROL_ANIMAL", GF_CONTROL_ANIMAL }, - {"GF_PSI", GF_PSI }, - {"GF_PSI_DRAIN", GF_PSI_DRAIN }, - {"GF_TELEKINESIS", GF_TELEKINESIS }, - {"GF_JAM_DOOR", GF_JAM_DOOR }, - {"GF_DOMINATION", GF_DOMINATION }, - {"GF_DISP_GOOD", GF_DISP_GOOD }, - {"GF_DRAIN_MANA", GF_DRAIN_MANA }, - {"GF_MIND_BLAST", GF_MIND_BLAST }, - {"GF_BRAIN_SMASH", GF_BRAIN_SMASH }, - {"GF_CAUSE_1", GF_CAUSE_1 }, - {"GF_CAUSE_2", GF_CAUSE_2 }, - {"GF_CAUSE_3", GF_CAUSE_3 }, - {"GF_CAUSE_4", GF_CAUSE_4 }, - {"GF_HAND_DOOM", GF_HAND_DOOM }, - {"GF_CAPTURE", GF_CAPTURE }, - {"GF_ANIM_DEAD", GF_ANIM_DEAD }, - {"GF_CHARM_LIVING", GF_CHARM_LIVING }, - {"GF_IDENTIFY", GF_IDENTIFY }, - {"GF_ATTACK", GF_ATTACK }, - {"GF_ENGETSU", GF_ENGETSU }, - {"GF_GENOCIDE", GF_GENOCIDE }, - {"GF_PHOTO", GF_PHOTO }, - {"GF_CONTROL_DEMON", GF_CONTROL_DEMON }, - {"GF_LAVA_FLOW", GF_LAVA_FLOW }, - {"GF_BLOOD_CURSE", GF_BLOOD_CURSE }, - {"GF_SEEKER", GF_SEEKER }, - {"GF_SUPER_RAY", GF_SUPER_RAY }, - {"GF_STAR_HEAL", GF_STAR_HEAL }, - {"GF_WATER_FLOW", GF_WATER_FLOW }, - {"GF_CRUSADE", GF_CRUSADE }, - {"GF_STASIS_EVIL", GF_STASIS_EVIL }, - {"GF_WOUNDS", GF_WOUNDS }, - {NULL, 0 } -}; - - -/*! - * @brief 設定ファイルの各行から各種テキスト情報を取得する / - * Parse a sub-file of the "extra info" (format shown below) - * @param buf データテキストの参照ポインタ - * @return エラーコード - * @details - *
- * Each "action" line has an "action symbol" in the first column,
- * followed by a colon, followed by some command specific info,
- * usually in the form of "tokens" separated by colons or slashes.
- * Blank lines, lines starting with white space, and lines starting
- * with pound signs ("#") are ignored (as comments).
- * Note the use of "tokenize()" to allow the use of both colons and
- * slashes as delimeters, while still allowing final tokens which
- * may contain any characters including "delimiters".
- * Note the use of "strtol()" to allow all "integers" to be encoded
- * in decimal, hexidecimal, or octal form.
- * Note that "monster zero" is used for the "player" attr/char, "object
- * zero" will be used for the "stack" attr/char, and "feature zero" is
- * used for the "nothing" attr/char.
- * Parse another file recursively, see below for details
- *   %:\
- * Specify the attr/char values for "monsters" by race index
- *   R:\:\:\
- * Specify the attr/char values for "objects" by kind index
- *   K:\:\:\
- * Specify the attr/char values for "features" by feature index
- *   F:\:\:\
- * Specify the attr/char values for unaware "objects" by kind tval
- *   U:\:\:\
- * Specify the attr/char values for inventory "objects" by kind tval
- *   E:\:\:\
- * Define a macro action, given an encoded macro action
- *   A:\
- * Create a normal macro, given an encoded macro trigger
- *   P:\
- * Create a command macro, given an encoded macro trigger
- *   C:\
- * Create a keyset mapping
- *   S:\:\:\
- * Turn an option off, given its name
- *   X:\
- * Turn an option on, given its name
- *   Y:\
- * Specify visual information, given an index, and some data
- *   V:\:\:\:\:\
- * Specify the set of colors to use when drawing a zapped spell
- *   Z:\:\
- * Specify a macro trigger template and macro trigger names.
- *   T:\:\:\:\:...
- *   T:\:\:\
- * 
- */ -errr process_pref_file_command(char *buf) -{ - int i, j; - TERM_COLOR n1; - SYMBOL_CODE n2; - - - char *zz[16]; - - - /* Require "?:*" format */ - if (buf[1] != ':') return 1; - - - switch (buf[0]) - { - /* Mega-Hack -- read external player's history file */ - /* Process "H:" */ - case 'H': - add_history_from_pref_line(buf + 2); - return 0; - - /* Process "R::/" -- attr/char for monster races */ - case 'R': - if (tokenize(buf+2, 3, zz, TOKENIZE_CHECKQUOTE) == 3) - { - monster_race *r_ptr; - i = (huge)strtol(zz[0], NULL, 0); - n1 = (TERM_COLOR)strtol(zz[1], NULL, 0); - n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0); - if (i >= max_r_idx) return 1; - r_ptr = &r_info[i]; - if (n1 || (!(n2 & 0x80) && n2)) r_ptr->x_attr = n1; /* Allow TERM_DARK text */ - if (n2) r_ptr->x_char = n2; - return 0; - } - break; - - /* Process "K::/" -- attr/char for object kinds */ - case 'K': - if (tokenize(buf+2, 3, zz, TOKENIZE_CHECKQUOTE) == 3) - { - object_kind *k_ptr; - i = (huge)strtol(zz[0], NULL, 0); - n1 = (TERM_COLOR)strtol(zz[1], NULL, 0); - n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0); - if (i >= max_k_idx) return 1; - k_ptr = &k_info[i]; - if (n1 || (!(n2 & 0x80) && n2)) k_ptr->x_attr = n1; /* Allow TERM_DARK text */ - if (n2) k_ptr->x_char = n2; - return 0; - } - break; - - /* Process "F::/" -- attr/char for terrain features */ - /* "F::/" */ - /* "F::/:LIT" */ - /* "F::/:/:/" */ - case 'F': - { - feature_type *f_ptr; - int num = tokenize(buf + 2, F_LIT_MAX * 2 + 1, zz, TOKENIZE_CHECKQUOTE); - - if ((num != 3) && (num != 4) && (num != F_LIT_MAX * 2 + 1)) return 1; - else if ((num == 4) && !streq(zz[3], "LIT")) return 1; - - i = (huge)strtol(zz[0], NULL, 0); - if (i >= max_f_idx) return 1; - f_ptr = &f_info[i]; - - n1 = (TERM_COLOR)strtol(zz[1], NULL, 0); - n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0); - if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[F_LIT_STANDARD] = n1; /* Allow TERM_DARK text */ - if (n2) f_ptr->x_char[F_LIT_STANDARD] = n2; - - /* Mega-hack -- feat supports lighting */ - switch (num) - { - /* No lighting support */ - case 3: - n1 = f_ptr->x_attr[F_LIT_STANDARD]; - n2 = f_ptr->x_char[F_LIT_STANDARD]; - for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++) - { - f_ptr->x_attr[j] = n1; - f_ptr->x_char[j] = n2; - } - break; - - /* Use default lighting */ - case 4: - apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char); - break; - - /* Use desired lighting */ - case F_LIT_MAX * 2 + 1: - for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++) - { - n1 = (TERM_COLOR)strtol(zz[j * 2 + 1], NULL, 0); - n2 = (SYMBOL_CODE)strtol(zz[j * 2 + 2], NULL, 0); - if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[j] = n1; /* Allow TERM_DARK text */ - if (n2) f_ptr->x_char[j] = n2; - } - break; - } - } - return 0; - - /* Process "S::/" -- attr/char for special things */ - case 'S': - if (tokenize(buf+2, 3, zz, TOKENIZE_CHECKQUOTE) == 3) - { - j = (byte)strtol(zz[0], NULL, 0); - n1 = (TERM_COLOR)strtol(zz[1], NULL, 0); - n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0); - misc_to_attr[j] = n1; - misc_to_char[j] = n2; - return 0; - } - break; - - /* Process "U::/" -- attr/char for unaware items */ - case 'U': - if (tokenize(buf+2, 3, zz, TOKENIZE_CHECKQUOTE) == 3) - { - j = (huge)strtol(zz[0], NULL, 0); - n1 = (TERM_COLOR)strtol(zz[1], NULL, 0); - n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0); - for (i = 1; i < max_k_idx; i++) - { - object_kind *k_ptr = &k_info[i]; - if (k_ptr->tval == j) - { - if (n1) k_ptr->d_attr = n1; - if (n2) k_ptr->d_char = n2; - } - } - return 0; - } - break; - - /* Process "E::" -- attribute for inventory objects */ - case 'E': - if (tokenize(buf+2, 2, zz, TOKENIZE_CHECKQUOTE) == 2) - { - j = (byte)strtol(zz[0], NULL, 0) % 128; - n1 = (TERM_COLOR)strtol(zz[1], NULL, 0); - if (n1) tval_to_attr[j] = n1; - return 0; - } - break; - - /* Process "A:" -- save an "action" for later */ - case 'A': - text_to_ascii(macro__buf, buf+2); - return 0; - - /* Process "P:" -- normal macro */ - case 'P': - { - char tmp[1024]; - - text_to_ascii(tmp, buf+2); - macro_add(tmp, macro__buf); - return 0; - } - - /* Process "C:" -- create keymap */ - case 'C': - { - int mode; - char tmp[1024]; - - if (tokenize(buf+2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1; - - mode = strtol(zz[0], NULL, 0); - if ((mode < 0) || (mode >= KEYMAP_MODES)) return 1; - - text_to_ascii(tmp, zz[1]); - if (!tmp[0] || tmp[1]) return 1; - i = (byte)(tmp[0]); - - string_free(keymap_act[mode][i]); - - keymap_act[mode][i] = string_make(macro__buf); - - return 0; - } - - /* Process "V:::::" -- visual info */ - case 'V': - if (tokenize(buf+2, 5, zz, TOKENIZE_CHECKQUOTE) == 5) - { - i = (byte)strtol(zz[0], NULL, 0); - angband_color_table[i][0] = (byte)strtol(zz[1], NULL, 0); - angband_color_table[i][1] = (byte)strtol(zz[2], NULL, 0); - angband_color_table[i][2] = (byte)strtol(zz[3], NULL, 0); - angband_color_table[i][3] = (byte)strtol(zz[4], NULL, 0); - return 0; - } - break; - - /* Process "X:" -- current_world_ptr->game_turn option off */ - /* Process "Y:" -- current_world_ptr->game_turn option on */ - case 'X': - case 'Y': - for (i = 0; option_info[i].o_desc; i++) - { - if (option_info[i].o_var && - option_info[i].o_text && - streq(option_info[i].o_text, buf + 2)) - { - int os = option_info[i].o_set; - int ob = option_info[i].o_bit; - - if ((p_ptr->playing || character_xtra) && - (OPT_PAGE_BIRTH == option_info[i].o_page) && !p_ptr->wizard) - { - msg_format(_("初期オプションは変更できません! '%s'", "Birth options can not changed! '%s'"), buf); - msg_print(NULL); - return 0; - } - - if (buf[0] == 'X') - { - /* Clear */ - option_flag[os] &= ~(1L << ob); - (*option_info[i].o_var) = FALSE; - } - else - { - /* Set */ - option_flag[os] |= (1L << ob); - (*option_info[i].o_var) = TRUE; - } - return 0; - } - } - - /* don't know that option. ignore it.*/ - msg_format(_("オプションの名前が正しくありません: %s", "Ignored invalid option: %s"), buf); - msg_print(NULL); - return 0; - - /* Process "Z::" -- set spell color */ - case 'Z': - { - /* Find the colon */ - char *t = my_strchr(buf + 2, ':'); - - if (!t) return 1; - - /* Nuke the colon */ - *(t++) = '\0'; - - for (i = 0; gf_desc[i].name; i++) - { - /* Match this type */ - if (streq(gf_desc[i].name, buf + 2)) - { - /* Remember this color set */ - gf_color[gf_desc[i].num] = (TERM_COLOR)quark_add(t); - - /* Success */ - return 0; - } - } - - break; - } - - /* Initialize macro trigger names and a template */ - /* Process "T:::" */ - /* Process "T: