OSDN Git Service

Merge pull request #765 from sikabane-works/release/3.0.0Alpha17 3.0.0Alpha17
authorDeskull <61610939+sikabane-works@users.noreply.github.com>
Sun, 11 Apr 2021 09:46:53 +0000 (18:46 +0900)
committerGitHub <noreply@github.com>
Sun, 11 Apr 2021 09:46:53 +0000 (18:46 +0900)
Release/3.0.0 alpha17

215 files changed:
Hengband/Hengband/Hengband.vcxproj
Hengband/Hengband/Hengband.vcxproj.filters
autopick.txt
autopick_eng.txt
doxygen/Hengband.doxyfile
lib/edit/e_info.txt
lib/pref/pref-opt.prf
lib/xtra/music/music.cfg
src/Makefile.am
src/ang_eng.rc
src/ang_jp.rc
src/artifact/fixed-art-generator.cpp
src/autopick/autopick-entry.cpp
src/autopick/autopick-matcher.cpp
src/birth/birth-select-realm.cpp
src/birth/game-play-initializer.cpp
src/birth/quick-start.cpp
src/birth/quick-start.h
src/blue-magic/blue-magic-checker.cpp
src/blue-magic/blue-magic-checker.h
src/blue-magic/learnt-power-getter.cpp
src/cmd-action/cmd-mane.cpp
src/cmd-item/cmd-smith.cpp
src/cmd-visual/cmd-draw.cpp
src/core/game-play.cpp
src/core/player-processor.cpp
src/core/window-redrawer.cpp
src/dungeon/dungeon-processor.cpp
src/dungeon/dungeon.cpp
src/dungeon/dungeon.h
src/effect/effect-monster-charm.cpp
src/effect/effect-monster-spirit.cpp
src/flavor/object-flavor.cpp
src/game-option/birth-options.cpp
src/game-option/birth-options.h
src/game-option/cheat-options.cpp
src/game-option/cheat-options.h
src/game-option/map-screen-options.cpp
src/game-option/map-screen-options.h
src/game-option/option-types-table.cpp
src/game-option/option-types-table.h
src/game-option/text-display-options.cpp
src/grid/feature.cpp
src/grid/feature.h
src/info-reader/dungeon-reader.cpp
src/info-reader/ego-reader.cpp
src/info-reader/kind-info-tokens-table.cpp
src/info-reader/race-info-tokens-table.cpp
src/info-reader/race-info-tokens-table.h
src/info-reader/race-reader.cpp
src/inventory/floor-item-getter.cpp
src/inventory/inventory-curse.cpp
src/inventory/item-getter.cpp
src/io-dump/character-dump.cpp
src/io-dump/special-class-dump.cpp
src/io/input-key-acceptor.cpp
src/io/input-key-processor.cpp
src/io/input-key-requester.cpp
src/io/read-pref-file.cpp
src/io/report.cpp
src/io/signal-handlers.cpp
src/knowledge/knowledge-experiences.cpp
src/knowledge/knowledge-self.cpp
src/load/load-v1-5-0.cpp
src/load/load-v1-5-0.h
src/load/lore-loader.cpp
src/load/option-loader.cpp
src/load/player-info-loader.cpp
src/load/store-loader.cpp
src/lore/lore-calculator.cpp
src/lore/lore-store.cpp
src/lore/lore-util.cpp
src/lore/lore-util.h
src/lore/magic-types-setter.cpp
src/lore/monster-lore.cpp
src/main-win.cpp
src/main-win/main-win-cfg-reader.cpp
src/main-win/main-win-cfg-reader.h
src/main-win/main-win-menuitem.h [new file with mode: 0644]
src/main-win/main-win-music.cpp
src/main-win/main-win-music.h
src/main/info-initializer.cpp
src/main/music-definitions-table.cpp
src/main/music-definitions-table.h
src/main/scene-table-floor.cpp [new file with mode: 0644]
src/main/scene-table-floor.h [new file with mode: 0644]
src/main/scene-table-monster.cpp [new file with mode: 0644]
src/main/scene-table-monster.h [new file with mode: 0644]
src/main/scene-table.cpp
src/main/scene-table.h
src/main/sound-of-music.cpp
src/main/sound-of-music.h
src/market/arena.cpp
src/market/building-initializer.cpp
src/melee/melee-spell-flags-checker.cpp
src/melee/melee-spell-util.cpp
src/melee/melee-spell-util.h
src/melee/melee-spell.cpp
src/mind/mind-elementalist.cpp
src/monster-floor/monster-sweep-grid.cpp
src/monster-floor/quantum-effect.cpp
src/monster-race/monster-race-hook.cpp
src/monster-race/monster-race-hook.h
src/monster-race/monster-race.cpp
src/monster-race/monster-race.h
src/monster-race/race-ability-flags.h [new file with mode: 0644]
src/monster-race/race-ability-mask.cpp [new file with mode: 0644]
src/monster-race/race-ability-mask.h [new file with mode: 0644]
src/monster-race/race-flags-ability1.h [deleted file]
src/monster-race/race-flags-ability2.h [deleted file]
src/monster-race/race-flags4.h [deleted file]
src/monster/monster-processor-util.cpp
src/monster/monster-processor-util.h
src/monster/monster-processor.cpp
src/monster/monster-status.cpp
src/monster/monster-update.cpp
src/monster/monster-util.cpp
src/mspell/assign-monster-spell.cpp
src/mspell/assign-monster-spell.h
src/mspell/element-resistance-checker.cpp
src/mspell/high-resistance-checker.cpp
src/mspell/improper-mspell-remover.cpp
src/mspell/improper-mspell-remover.h
src/mspell/mspell-attack-util.cpp
src/mspell/mspell-attack-util.h
src/mspell/mspell-attack.cpp
src/mspell/mspell-checker.cpp
src/mspell/mspell-checker.h
src/mspell/mspell-judgement.cpp
src/mspell/mspell-lite.cpp
src/mspell/mspell-mask-definitions.h [deleted file]
src/mspell/mspell-selector.cpp
src/mspell/mspell-selector.h
src/mspell/smart-mspell-util.cpp
src/mspell/smart-mspell-util.h
src/mspell/summon-checker.cpp
src/object-enchant/apply-magic-armor.cpp
src/object-enchant/apply-magic-weapon.cpp
src/object-enchant/apply-magic.cpp
src/object-enchant/object-ego.cpp
src/object-enchant/object-ego.h
src/object-enchant/tr-types.h
src/object-enchant/trc-types.h
src/object-hook/hook-magic.cpp
src/object-hook/hook-weapon.cpp
src/object/object-info.cpp
src/object/object-kind.cpp
src/object/object-kind.h
src/object/object-value-calc.cpp
src/object/warning.cpp
src/perception/identification.cpp
src/player-info/avatar.cpp
src/player-info/self-info.cpp
src/player/player-class.cpp
src/player/player-class.h
src/player/player-damage.cpp
src/player/player-skill.cpp
src/player/player-skill.h
src/player/player-status-flags.cpp
src/player/player-status.cpp
src/player/player-status.h
src/player/process-name.cpp
src/player/process-name.h
src/racial/racial-draconian.cpp
src/room/rooms-pit-nest.cpp
src/room/rooms-vault.cpp
src/room/rooms-vault.h
src/save/info-writer.cpp
src/save/monster-writer.cpp
src/save/player-writer.cpp
src/spell-kind/spells-teleport.cpp
src/spell/spells-status.cpp
src/store/articles-on-sale.cpp [moved from src/market/articles-on-sale.cpp with 99% similarity]
src/store/articles-on-sale.h [moved from src/market/articles-on-sale.h with 100% similarity]
src/store/cmd-store.cpp [moved from src/cmd-building/cmd-store.cpp with 98% similarity]
src/store/cmd-store.h [moved from src/cmd-building/cmd-store.h with 100% similarity]
src/store/gold-magnification-table.cpp [moved from src/market/gold-magnification-table.cpp with 99% similarity]
src/store/gold-magnification-table.h [moved from src/market/gold-magnification-table.h with 100% similarity]
src/store/owner-insults.cpp [deleted file]
src/store/owner-insults.h [deleted file]
src/store/pricing.cpp
src/store/pricing.h
src/store/purchase-order.cpp
src/store/say-comments.cpp
src/store/say-comments.h
src/store/sell-order.cpp
src/store/store-key-processor.cpp [moved from src/io/store-key-processor.cpp with 94% similarity]
src/store/store-key-processor.h [moved from src/io/store-key-processor.h with 100% similarity]
src/store/store-owner-comments.cpp
src/store/store-owner-comments.h
src/store/store-owners.cpp
src/store/store-owners.h
src/store/store-util.cpp
src/store/store-util.h
src/store/store.cpp
src/store/store.h
src/system/angband-version.h
src/system/artifact-type-definition.cpp
src/system/artifact-type-definition.h
src/system/monster-race-definition.h
src/term/z-form.cpp
src/term/z-term.h
src/util/flag-group.h
src/util/string-processor.cpp
src/util/string-processor.h
src/view/display-lore.cpp
src/view/display-map.cpp
src/view/display-player.cpp
src/view/display-self-info.cpp
src/view/display-store.cpp
src/view/object-describer.cpp
src/window/display-sub-windows.cpp
src/wizard/wizard-item-modifier.cpp
src/wizard/wizard-special-process.cpp
src/wizard/wizard-spells.cpp

index 6a9990e..126d610 100644 (file)
     <ClCompile Include="..\..\src\cmd-action\cmd-travel.cpp" />\r
     <ClCompile Include="..\..\src\cmd-action\cmd-tunnel.cpp" />\r
     <ClCompile Include="..\..\src\action\movement-execution.cpp" />\r
-    <ClCompile Include="..\..\src\cmd-building\cmd-store.cpp" />\r
+    <ClCompile Include="..\..\src\store\cmd-store.cpp" />\r
     <ClCompile Include="..\..\src\cmd-io\cmd-floor.cpp" />\r
     <ClCompile Include="..\..\src\cmd-io\cmd-lore.cpp" />\r
     <ClCompile Include="..\..\src\cmd-io\cmd-menu-content-table.cpp" />\r
     <ClCompile Include="..\..\src\io\cursor.cpp" />\r
     <ClCompile Include="..\..\src\io\input-key-acceptor.cpp" />\r
     <ClCompile Include="..\..\src\io\input-key-requester.cpp" />\r
-    <ClCompile Include="..\..\src\io\store-key-processor.cpp" />\r
+    <ClCompile Include="..\..\src\store\store-key-processor.cpp" />\r
     <ClCompile Include="..\..\src\load\info-loader.cpp" />\r
     <ClCompile Include="..\..\src\locale\utf-8.cpp" />\r
     <ClCompile Include="..\..\src\main-win\main-win-cfg-reader.cpp" />\r
     <ClCompile Include="..\..\src\main\info-initializer.cpp" />\r
     <ClCompile Include="..\..\src\main\init-error-messages-table.cpp" />\r
     <ClCompile Include="..\..\src\main-win\main-win-bg.cpp" />\r
+    <ClCompile Include="..\..\src\main\scene-table-floor.cpp" />\r
+    <ClCompile Include="..\..\src\main\scene-table-monster.cpp" />\r
     <ClCompile Include="..\..\src\main\scene-table.cpp" />\r
     <ClCompile Include="..\..\src\market\building-initializer.cpp" />\r
     <ClCompile Include="..\..\src\melee\melee-spell-flags-checker.cpp" />\r
     <ClCompile Include="..\..\src\monster-floor\monster-lite-util.cpp" />\r
     <ClCompile Include="..\..\src\monster-floor\monster-lite.cpp" />\r
     <ClCompile Include="..\..\src\monster-floor\special-death-switcher.cpp" />\r
+    <ClCompile Include="..\..\src\monster-race\race-ability-mask.cpp" />\r
     <ClCompile Include="..\..\src\monster\monster-status-setter.cpp" />\r
     <ClCompile Include="..\..\src\mspell\element-resistance-checker.cpp" />\r
     <ClCompile Include="..\..\src\mspell\high-resistance-checker.cpp" />\r
     </ClCompile>\r
     <ClCompile Include="..\..\src\store\home.cpp" />\r
     <ClCompile Include="..\..\src\store\museum.cpp" />\r
-    <ClCompile Include="..\..\src\store\owner-insults.cpp" />\r
     <ClCompile Include="..\..\src\store\pricing.cpp" />\r
     <ClCompile Include="..\..\src\store\purchase-order.cpp" />\r
     <ClCompile Include="..\..\src\store\sell-order.cpp" />\r
     <ClCompile Include="..\..\src\io\tokenizer.cpp" />\r
     <ClCompile Include="..\..\src\io\write-diary.cpp" />\r
     <ClCompile Include="..\..\src\market\arena-info-table.cpp" />\r
-    <ClCompile Include="..\..\src\market\articles-on-sale.cpp" />\r
+    <ClCompile Include="..\..\src\store\articles-on-sale.cpp" />\r
     <ClCompile Include="..\..\src\store\black-market.cpp" />\r
     <ClCompile Include="..\..\src\market\building-util.cpp" />\r
-    <ClCompile Include="..\..\src\market\gold-magnification-table.cpp" />\r
+    <ClCompile Include="..\..\src\store\gold-magnification-table.cpp" />\r
     <ClCompile Include="..\..\src\market\play-gamble.cpp" />\r
     <ClCompile Include="..\..\src\market\poker.cpp" />\r
     <ClCompile Include="..\..\src\store\say-comments.cpp" />\r
     <ClInclude Include="..\..\src\cmd-action\cmd-travel.h" />\r
     <ClInclude Include="..\..\src\cmd-action\cmd-tunnel.h" />\r
     <ClInclude Include="..\..\src\action\movement-execution.h" />\r
-    <ClInclude Include="..\..\src\cmd-building\cmd-store.h" />\r
+    <ClInclude Include="..\..\src\store\cmd-store.h" />\r
     <ClInclude Include="..\..\src\cmd-io\cmd-floor.h" />\r
     <ClInclude Include="..\..\src\cmd-io\cmd-lore.h" />\r
     <ClInclude Include="..\..\src\cmd-io\cmd-menu-content-table.h" />\r
     <ClInclude Include="..\..\src\io\cursor.h" />\r
     <ClInclude Include="..\..\src\io\input-key-acceptor.h" />\r
     <ClInclude Include="..\..\src\io\input-key-requester.h" />\r
-    <ClInclude Include="..\..\src\io\store-key-processor.h" />\r
+    <ClInclude Include="..\..\src\store\store-key-processor.h" />\r
     <ClInclude Include="..\..\src\load\info-loader.h" />\r
     <ClInclude Include="..\..\src\locale\language-switcher.h" />\r
     <ClInclude Include="..\..\src\locale\utf-8.h" />\r
     <ClInclude Include="..\..\src\main-win\main-win-cfg-reader.h" />\r
     <ClInclude Include="..\..\src\main-win\main-win-file-utils.h" />\r
     <ClInclude Include="..\..\src\main-win\main-win-mci.h" />\r
+    <ClInclude Include="..\..\src\main-win\main-win-menuitem.h" />\r
     <ClInclude Include="..\..\src\main-win\main-win-mmsystem.h" />\r
     <ClInclude Include="..\..\src\main-win\main-win-music.h" />\r
     <ClInclude Include="..\..\src\main-win\main-win-sound.h" />\r
     <ClInclude Include="..\..\src\main\init-error-messages-table.h" />\r
     <ClInclude Include="..\..\src\main-win\main-win-bg.h" />\r
     <ClInclude Include="..\..\src\main-win\main-win-windows.h" />\r
+    <ClInclude Include="..\..\src\main\scene-table-floor.h" />\r
+    <ClInclude Include="..\..\src\main\scene-table-monster.h" />\r
     <ClInclude Include="..\..\src\main\scene-table.h" />\r
     <ClInclude Include="..\..\src\market\building-initializer.h" />\r
     <ClInclude Include="..\..\src\melee\melee-spell-flags-checker.h" />\r
     <ClInclude Include="..\..\src\monster-floor\monster-lite-util.h" />\r
     <ClInclude Include="..\..\src\monster-floor\monster-lite.h" />\r
     <ClInclude Include="..\..\src\monster-floor\special-death-switcher.h" />\r
+    <ClInclude Include="..\..\src\monster-race\race-ability-flags.h" />\r
+    <ClInclude Include="..\..\src\monster-race\race-ability-mask.h" />\r
     <ClInclude Include="..\..\src\monster\monster-status-setter.h" />\r
     <ClInclude Include="..\..\src\mspell\element-resistance-checker.h" />\r
     <ClInclude Include="..\..\src\mspell\high-resistance-checker.h" />\r
     <ClInclude Include="..\..\src\mind\stances-table.h" />\r
     <ClInclude Include="..\..\src\mspell\monster-power-table.h" />\r
     <ClInclude Include="..\..\src\mspell\mspell-dispel.h" />\r
-    <ClInclude Include="..\..\src\mspell\mspell-mask-definitions.h" />\r
     <ClInclude Include="..\..\src\mspell\mspell-checker.h" />\r
     <ClInclude Include="..\..\src\mspell\mspell-judgement.h" />\r
     <ClInclude Include="..\..\src\blue-magic\blue-magic-checker.h" />\r
     <ClInclude Include="..\..\src\stdafx.h" />\r
     <ClInclude Include="..\..\src\store\home.h" />\r
     <ClInclude Include="..\..\src\store\museum.h" />\r
-    <ClInclude Include="..\..\src\store\owner-insults.h" />\r
     <ClInclude Include="..\..\src\store\pricing.h" />\r
     <ClInclude Include="..\..\src\store\purchase-order.h" />\r
     <ClInclude Include="..\..\src\store\sell-order.h" />\r
     <ClInclude Include="..\..\src\lore\lore-store.h" />\r
     <ClInclude Include="..\..\src\lore\monster-lore.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-flags8.h" />\r
-    <ClInclude Include="..\..\src\monster-race\race-flags-ability1.h" />\r
-    <ClInclude Include="..\..\src\monster-race\race-flags-ability2.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-flags-resistance.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-flags1.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-flags2.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-flags3.h" />\r
-    <ClInclude Include="..\..\src\monster-race\race-flags4.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-flags7.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-flags9.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-indice-types.h" />\r
     <ClInclude Include="..\..\src\io\tokenizer.h" />\r
     <ClInclude Include="..\..\src\io\write-diary.h" />\r
     <ClInclude Include="..\..\src\market\arena-info-table.h" />\r
-    <ClInclude Include="..\..\src\market\articles-on-sale.h" />\r
+    <ClInclude Include="..\..\src\store\articles-on-sale.h" />\r
     <ClInclude Include="..\..\src\store\black-market.h" />\r
     <ClInclude Include="..\..\src\market\building-util.h" />\r
-    <ClInclude Include="..\..\src\market\gold-magnification-table.h" />\r
+    <ClInclude Include="..\..\src\store\gold-magnification-table.h" />\r
     <ClInclude Include="..\..\src\market\play-gamble.h" />\r
     <ClInclude Include="..\..\src\market\poker.h" />\r
     <ClInclude Include="..\..\src\store\say-comments.h" />\r
     <Error Condition="!Exists('..\packages\Microsoft.NetFramework.Analyzers.3.0.0\build\Microsoft.NetFramework.Analyzers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.NetFramework.Analyzers.3.0.0\build\Microsoft.NetFramework.Analyzers.props'))" />\r
     <Error Condition="!Exists('..\packages\Microsoft.CodeAnalysis.FxCopAnalyzers.3.0.0\build\Microsoft.CodeAnalysis.FxCopAnalyzers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeAnalysis.FxCopAnalyzers.3.0.0\build\Microsoft.CodeAnalysis.FxCopAnalyzers.props'))" />\r
   </Target>\r
-</Project>\r
+</Project>
\ No newline at end of file
index db77d28..83e52d0 100644 (file)
     <ClCompile Include="..\..\src\market\poker.cpp">\r
       <Filter>market</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\src\market\articles-on-sale.cpp">\r
-      <Filter>market</Filter>\r
-    </ClCompile>\r
-    <ClCompile Include="..\..\src\market\gold-magnification-table.cpp">\r
-      <Filter>market</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\src\market\building-util.cpp">\r
       <Filter>market</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\src\store\home.cpp">\r
       <Filter>store</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\src\io\store-key-processor.cpp">\r
-      <Filter>io</Filter>\r
-    </ClCompile>\r
-    <ClCompile Include="..\..\src\cmd-building\cmd-store.cpp">\r
-      <Filter>cmd-building</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\src\store\purchase-order.cpp">\r
       <Filter>store</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\src\store\owner-insults.cpp">\r
-      <Filter>store</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\src\store\sell-order.cpp">\r
       <Filter>store</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\src\main-win\main-win-cfg-reader.cpp">\r
       <Filter>main-win</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\src\monster-race\race-ability-mask.cpp">\r
+      <Filter>monster-race</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\src\store\articles-on-sale.cpp">\r
+      <Filter>store</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\src\store\gold-magnification-table.cpp">\r
+      <Filter>store</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\src\store\cmd-store.cpp">\r
+      <Filter>store</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\src\store\store-key-processor.cpp">\r
+      <Filter>store</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\src\main\scene-table-floor.cpp">\r
+      <Filter>main</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\src\main\scene-table-monster.cpp">\r
+      <Filter>main</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="..\..\src\combat\shoot.h">\r
     <ClInclude Include="..\..\src\market\poker.h">\r
       <Filter>market</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\src\market\articles-on-sale.h">\r
-      <Filter>market</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="..\..\src\market\gold-magnification-table.h">\r
-      <Filter>market</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\src\market\building-util.h">\r
       <Filter>market</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\src\monster-race\race-flags3.h">\r
       <Filter>monster-race</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\src\monster-race\race-flags4.h">\r
-      <Filter>monster-race</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\src\monster-race\race-flags7.h">\r
       <Filter>monster-race</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\src\monster-race\race-flags-resistance.h">\r
       <Filter>monster-race</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\src\monster-race\race-flags-ability1.h">\r
-      <Filter>monster-race</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="..\..\src\monster-race\race-flags-ability2.h">\r
-      <Filter>monster-race</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\src\monster-race\race-flags8.h">\r
       <Filter>monster-race</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\src\mind\mind-blue-mage.h">\r
       <Filter>mind</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\src\mspell\mspell-mask-definitions.h">\r
-      <Filter>mspell</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\src\mspell\monster-power-table.h">\r
       <Filter>mspell</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\src\store\home.h">\r
       <Filter>store</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\src\io\store-key-processor.h">\r
-      <Filter>io</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="..\..\src\cmd-building\cmd-store.h">\r
-      <Filter>cmd-building</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\src\store\purchase-order.h">\r
       <Filter>store</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\src\store\owner-insults.h">\r
-      <Filter>store</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\src\store\sell-order.h">\r
       <Filter>store</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\src\util\point-2d.h">\r
       <Filter>util</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\src\main-win\main-win-menuitem.h">\r
+      <Filter>main-win</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\src\main\scene-table-floor.h">\r
+      <Filter>main</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\src\main\scene-table-monster.h">\r
+      <Filter>main</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\src\monster-race\race-ability-flags.h">\r
+      <Filter>monster-race</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\src\monster-race\race-ability-mask.h">\r
+      <Filter>monster-race</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\src\store\articles-on-sale.h">\r
+      <Filter>store</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\src\store\gold-magnification-table.h">\r
+      <Filter>store</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\src\store\cmd-store.h">\r
+      <Filter>store</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\src\store\store-key-processor.h">\r
+      <Filter>store</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <None Include="..\..\src\wall.bmp" />\r
index 7c4c97c..96a36a2 100644 (file)
 #          Nibelung, Dark-Elf, Draconian, Mindflayer, Imp, Golem,
 #          Skeleton, Zombie, Vampire, Spectre, Sprite, Beastman, Ent,
 #          Archon, Balrog, Dunadan, Shadow-Fairy, Kutar, Android,
+#          Merfolk
 #          のどれか
 #        $CLASS
 #          職業を英語名で返す。
 #          Tourist, Imitator, BeastMaster, Sorcerer, Archer,
 #          Magic-Eater, Bard, Red-Mage, Samurai, ForceTrainer,
 #          Blue-Mage, Cavalry, Berserker, Weaponsmith, Mirror-Master,
-#          Ninja, Sniper
+#          Ninja, Sniper, Elementalist
 #          のどれか
 #        $PLAYER
 #          プレイヤーの名前を返す。ただし、' '(スペース)、'['、']'は
index 277262a..9b30830 100644 (file)
 #          Nibelung, Dark-Elf, Draconian, Mindflayer, Imp, Golem,
 #          Skeleton, Zombie, Vampire, Spectre, Sprite, Beastman, Ent,
 #          Archon, Balrog, Dunadan, Shadow-Fairy, Kutar, Android,
+#          Merfolk
 #
 #        $CLASS
 #         Returns name of player class. One of below:
 #          Tourist, Imitator, BeastMaster, Sorcerer, Archer,
 #          Magic-Eater, Bard, Red-Mage, Samurai, ForceTrainer,
 #          Blue-Mage, Cavalry, Berserker, Weaponsmith, Mirror-Master,
-#          Ninja, Sniper
+#          Ninja, Sniper, Elementalist
 #
 #        $PLAYER
 #         Returns player name.
index e12d117..321a5cd 100644 (file)
@@ -38,7 +38,7 @@ PROJECT_NAME           = Hengband
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 3.0.0Alpha15
+PROJECT_NUMBER         = 3.0.0Alpha17
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
index c6c0365..4033ffe 100644 (file)
@@ -71,6 +71,12 @@ F:INT | WIS |
 F:RES_COLD | RES_POIS | RES_NETHER | SH_COLD | ESP_UNDEAD
 F:IGNORE_COLD |  XTRA_H_RES 
 F:CURSED | RANDOM_CURSE2 | ADD_L_CURSE | DRAIN_EXP
+G:1/3:HEAVY_CURSE
+G:1/9:TY_CURSE
+G:1/3:ADD_H_CURSE
+G:1/6:AGGRAVATE
+G:1/9:NO_MAGIC
+G:1/9:NO_TELE
 
 N:5:悪魔の
 E:of Demon
@@ -80,6 +86,13 @@ C:0:0:11:3
 F:STR | INT | CON |
 F:RES_FIRE | RES_NETHER | ESP_DEMON | SH_FIRE | CURSED | RANDOM_CURSE2 | POWERFUL | 
 F:IGNORE_FIRE | XTRA_RES
+G:1/1:DRAIN_EXP | DRAIN_MANA | DRAIN_HP
+G:1/3:HEAVY_CURSE
+G:1/3:AGGRAVATE
+G:1/3:ADD_L_CURSE
+G:1/5:ADD_H_CURSE
+G:1/5:TY_CURSE
+G:1/5:CALL_DEMON
 
 N:6:ドルイドの
 E:of Druid
@@ -104,6 +117,7 @@ W:0:25:0:12500
 C:0:0:10:0
 F:RES_ACID | RES_ELEC | RES_FIRE | RES_COLD | 
 F:IGNORE_ACID | IGNORE_ELEC | IGNORE_FIRE | IGNORE_COLD | XTRA_H_RES
+G:1/4:RES_POIS
 
 # OnePower
 
@@ -197,6 +211,8 @@ W:0:18:0:12500
 C:0:0:10:0
 F:RES_ACID | RES_ELEC | RES_FIRE | RES_COLD | 
 F:IGNORE_ACID | IGNORE_ELEC | IGNORE_FIRE | IGNORE_COLD
+G:2/3:XTRA_H_RES
+G:1/4:RES_POIS
 
 #JZ#
 N:21:反射の
@@ -229,6 +245,7 @@ C:0:0:8:2
 F:CON|
 F:IGNORE_ACID | IGNORE_ELEC | IGNORE_FIRE | IGNORE_COLD | XTRA_E_RES
 
+
 ### Crowns and Helms ###
 
 N:23:闇の
@@ -261,6 +278,13 @@ W:0:30:0:12000
 F:INT | SEE_INVIS |
 F:RES_FIRE | RES_NETHER | ESP_DEMON | SH_FIRE | CURSED | RANDOM_CURSE2 | POWERFUL | 
 F:IGNORE_FIRE | XTRA_RES
+G:1/1:DRAIN_EXP | DRAIN_MANA | DRAIN_HP
+G:1/3:HEAVY_CURSE
+G:1/3:AGGRAVATE
+G:1/3:ADD_L_CURSE
+G:1/3:ADD_H_CURSE
+G:1/5:TY_CURSE
+G:1/5:CALL_DEMON
 
 # OneAbility
 
@@ -311,6 +335,8 @@ X:33:6
 W:0:18:0:500
 F:LITE_3 | RES_LITE | ACTIVATE
 U:LIGHT
+G:1/3:LITE
+G:1/3:LITE_2
 
 N:33:テレパシーの
 E:of Telepathy
@@ -362,6 +388,12 @@ F:STR | INT | WIS | DEX | CON | CHR | HEAVY_CURSE | CURSED | RANDOM_CURSE2 |
 F:RES_COLD | RES_POIS | RES_NEXUS | RES_NETHER |
 F:SH_COLD | SEE_INVIS | LITE_M1 | XTRA_H_RES | XTRA_POWER | ADD_H_CURSE |
 F:IGNORE_ACID | IGNORE_ELEC | IGNORE_FIRE | IGNORE_COLD
+G:1/3:NO_MAGIC
+G:1/3:NO_TELE
+G:1/3:TY_CURSE
+G:1/3:DRAIN_EXP
+G:1/3:DRAIN_MANA
+G:1/3:DRAIN_HP
 
 N:39:疾病の
 E:of Sickliness
@@ -451,6 +483,10 @@ F:STR | CON | CHR |
 F:SEE_INVIS | RES_COLD | RES_NETHER | SLOW_DIGEST |
 F:CURSED | HEAVY_CURSE | ADD_H_CURSE | ACTIVATE |
 U:WRAITH
+G:1/3:COWARDICE
+G:1/3:CALL_UNDEAD
+G:1/3:SLOW_REGEN
+G:1/3:DRAIN_EXP
 
 
 ### Gloves ###
@@ -519,6 +555,7 @@ E:of Levitation
 X:35:7
 W:0:4:0:250
 F:LEVITATION
+G:1/2:XTRA_H_RES
 
 #J0#
 #J0# 岸さんの訳です
@@ -583,6 +620,7 @@ C:6:6:4:4
 F:WIS | 
 F:SLAY_EVIL | SLAY_UNDEAD | SLAY_DEMON | 
 F:SEE_INVIS | BLESSED | RES_FEAR | ONE_SUSTAIN
+G:1/4:BLOWS
 
 # OneSustain
 
@@ -595,6 +633,8 @@ F:STEALTH |
 F:FREE_ACT | SEE_INVIS | LEVITATION | REGEN | 
 F:RES_ACID | RES_ELEC | RES_FIRE | RES_COLD | ONE_SUSTAIN | XTRA_H_RES |
 F:IGNORE_ACID | IGNORE_ELEC | IGNORE_FIRE | IGNORE_COLD
+G:1/3:RES_POIS
+G:1/3:WARNING
 
 # OneAbility
 
@@ -617,6 +657,7 @@ F:STR | DEX | CON |
 F:SLAY_ORC | SLAY_TROLL | SLAY_GIANT | 
 F:ESP_ORC | ESP_TROLL | ESP_GIANT | 
 F:FREE_ACT | SEE_INVIS
+G:1/3:RES_FEAR
 
 N:69:追加攻撃の
 E:of Extra Attacks
@@ -630,6 +671,8 @@ E:of Slaying
 X:24:15
 W:0:18:0:500
 C:0:0:0:0
+G:1/5:BRAND_POIS
+G:1/3:VORPAL
 
 N:71:理力の
 E:of Force
@@ -780,6 +823,7 @@ X:24:20
 W:0:40:0:7000
 C:0:0:0:3
 F:CON | SLAY_DRAGON | KILL_DRAGON | XTRA_E_RES | XTRA_D_RES | ESP_DRAGON
+G:1/3:RES_POIS
 
 #JZ#
 N:96:(吸血)
@@ -787,6 +831,7 @@ E:(Vampiric)
 X:24:25
 W:0:18:0:10000
 F:VAMPIRIC | HOLD_EXP
+G:1/5:SLAY_HUMAN
 
 N:97:虹色の
 E:of Prism
@@ -804,6 +849,8 @@ C:4:4:0:2
 F:SLAY_EVIL | TELEPORT | FREE_ACT | SEARCH |
 F:REGEN | SLOW_DIGEST | RES_NEXUS | ACTIVATE | XTRA_H_RES
 U:TELEPORT
+G:1/5:SLAY_DEMON
+G:1/7:XTRA_POWER
 
 #JZ#
 N:99:(パターン)
@@ -814,6 +861,9 @@ C:6:6:0:2
 F:STR | CON |
 F:SLAY_EVIL | SLAY_DEMON | SLAY_UNDEAD |
 F:FREE_ACT | SEE_INVIS | XTRA_H_RES
+G:1/3:HOLD_EXP
+G:1/3:DEX
+G:1/5:RES_FEAR
 
 #J0#
 #J0# 岸さんの訳です
@@ -834,6 +884,12 @@ W:0:30:0:15000
 C:6:6:-20:4
 F:INT | BRAND_FIRE | CURSED | POWERFUL |
 F:RES_FIRE | RES_NETHER | SEE_INVIS | ESP_DEMON | XTRA_DICE
+G:1/1:DRAIN_EXP | DRAIN_MANA | DRAIN_HP
+G:1/3:HEAVY_CURSE
+G:1/3:CHAOTIC
+G:1/4:BLOWS
+G:1/5:ADD_H_CURSE
+G:1/5:CALL_DEMON
 
 N:102:モルグルの
 E:of Morgul
@@ -845,6 +901,8 @@ F:SLAY_UNDEAD | BRAND_COLD | BRAND_POIS
 F:RES_COLD | RES_NETHER | SH_COLD
 F:SEE_INVIS | ESP_UNDEAD | AGGRAVATE
 F:RANDOM_CURSE2 | XTRA_DICE | XTRA_POWER
+G:1/3:HEAVY_CURSE
+G:1/6:TY_CURSE
 
 N:103:人喰いの
 E:of Slay Human
index 08edada..3b8e76e 100644 (file)
@@ -101,7 +101,6 @@ X:alert_trap_detect
 
 ##### Birth Options #####
 
-X:manual_haggle
 X:easy_band
 Y:smart_learn
 X:smart_cheat
index 18df031..5d34f59 100644 (file)
@@ -32,6 +32,10 @@ type = MPEGVideo
 # quest_clear       クエストをクリアした時からフロアを移る時まで 
 # final_quest_clear 最終クエスト(*勝利*条件)をクリアした時からフロアを移る時まで
 # ambush    襲撃を受けてフロアを移る時まで
+# unique    ユニークモンスターに遭遇時
+# shadower  あやしい影に遭遇時
+# unk_monster 未知のモンスターに遭遇時
+# hl_monster レベルの高いモンスターに遭遇時
 [Basic]
 gameover = 
 exit = 
@@ -53,6 +57,10 @@ battle =
 quest_clear = 
 final_quest_clear = 
 ambush = 
+unique = 
+shadower = 
+unk_monster = 
+hl_monster = 
 
 # [Town]項目
 # 町の個別BGMを指定します
@@ -78,3 +86,12 @@ ambush =
 [Quest]
 # 001は盗賊の隠れ家です
 # quest001 = quest.mp3
+
+# [Monster]項目
+# モンスターの個別BGMを指定します
+# 以下の区間にmonster[モンスターID] = [ファイル名]の形で設定して下さい
+# IDは0001と四桁で指定して下さい。
+# 特に設定されていない場合、[Basic]の設定に従います
+[Monster]
+# 0001は汚いイタズラ小僧です
+# monster0001 = monster.mp3
index 017b14c..70af4fe 100644 (file)
@@ -99,7 +99,6 @@ hengband_SOURCES = \
        \
        cmd-building/cmd-building.cpp cmd-building/cmd-building.h \
        cmd-building/cmd-inn.cpp cmd-building/cmd-inn.h \
-       cmd-building/cmd-store.cpp cmd-building/cmd-store.h \
        \
        cmd-io/cmd-autopick.cpp cmd-io/cmd-autopick.h \
        cmd-io/cmd-diary.cpp cmd-io/cmd-diary.h \
@@ -306,7 +305,6 @@ hengband_SOURCES = \
        io/report.cpp io/report.h \
        io/screen-util.cpp io/screen-util.h \
        io/signal-handlers.cpp io/signal-handlers.h \
-       io/store-key-processor.cpp io/store-key-processor.h \
        io/tokenizer.cpp io/tokenizer.h \
        io/uid-checker.cpp io/uid-checker.h \
        io/write-diary.cpp io/write-diary.h \
@@ -379,6 +377,8 @@ hengband_SOURCES = \
        main/init-error-messages-table.cpp main/init-error-messages-table.h \
        main/music-definitions-table.cpp main/music-definitions-table.h \
        main/scene-table.cpp main/scene-table.h \
+       main/scene-table-floor.cpp main/scene-table-floor.h \
+       main/scene-table-monster.cpp main/scene-table-monster.h \
        main/sound-definitions-table.cpp main/sound-definitions-table.h \
        main/sound-of-music.cpp main/sound-of-music.h \
        main/x11-gamma-builder.cpp main/x11-gamma-builder.h \
@@ -389,8 +389,6 @@ hengband_SOURCES = \
        market/building-util.cpp market/building-util.h \
        market/play-gamble.cpp market/play-gamble.h \
        market/poker.cpp market/poker.h \
-       market/articles-on-sale.cpp market/articles-on-sale.h \
-       market/gold-magnification-table.cpp market/gold-magnification-table.h \
        market/arena.cpp market/arena.h \
        market/bounty-prize-table.cpp market/bounty-prize-table.h \
        market/bounty.cpp market/bounty.h \
@@ -492,10 +490,11 @@ hengband_SOURCES = \
        \
        monster-race/monster-race.cpp monster-race/monster-race.h \
        monster-race/monster-race-hook.cpp monster-race/monster-race-hook.h \
+       monster-race/race-ability-flags.h \
+       monster-race/race-ability-mask.cpp monster-race/race-ability-mask.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-flags3.h \
        monster-race/race-flags7.h monster-race/race-flags8.h \
        monster-race/race-flags9.h \
        monster-race/race-indice-types.h \
@@ -521,7 +520,6 @@ hengband_SOURCES = \
        mspell/mspell-damage-calculator.cpp mspell/mspell-damage-calculator.h \
        mspell/mspell-learn-checker.cpp mspell/mspell-learn-checker.h \
        mspell/mspell-floor.cpp mspell/mspell-floor.h \
-       mspell/mspell-mask-definitions.h \
        mspell/mspell-special.cpp mspell/mspell-special.h \
        mspell/mspell-status.cpp mspell/mspell-status.h \
        mspell/mspell-particularity.cpp mspell/mspell-particularity.h \
@@ -798,15 +796,18 @@ hengband_SOURCES = \
        \
        store/home.cpp store/home.h \
        store/store.cpp store/store.h \
+       store/articles-on-sale.cpp store/articles-on-sale.h \
        store/black-market.cpp store/black-market.h \
+       store/cmd-store.cpp store/cmd-store.h \
+       store/gold-magnification-table.cpp store/gold-magnification-table.h \
        store/museum.cpp store/museum.h \
        store/pricing.cpp store/pricing.h \
        store/purchase-order.cpp store/purchase-order.h \
-       store/owner-insults.cpp store/owner-insults.h \
        store/rumor.cpp store/rumor.h \
        store/say-comments.cpp store/say-comments.h \
        store/sell-order.cpp store/sell-order.h \
        store/service-checker.cpp store/service-checker.h \
+       store/store-key-processor.cpp store/store-key-processor.h \
        store/store-util.cpp store/store-util.h \
        store/store-owners.cpp store/store-owners.h \
        store/store-owner-comments.cpp store/store-owner-comments.h \
@@ -927,6 +928,7 @@ EXTRA_hengband_SOURCES = \
        main-win/main-win-define.h \
        main-win/main-win-file-utils.cpp main-win/main-win-file-utils.h \
        main-win/main-win-mci.cpp main-win/main-win-mci.h \
+       main-win/main-win-menuitem.h \
        main-win/main-win-mmsystem.h \
        main-win/main-win-music.cpp main-win/main-win-music.h \
        main-win/main-win-sound.cpp main-win/main-win-sound.h \
index b20ca4b..5d192a5 100644 (file)
@@ -133,14 +133,6 @@ ANGBAND MENU
                MENUITEM "Choose BG pict", 441
                MENUITEM "&HTML dump", 450
        }
-
-/*
-       POPUP "&Help"
-       {
-               MENUITEM "&Contents", 901
-               MENUITEM "&Spoilers", 902
-       }
-*/
 }
 
 ANGBAND ICON "angband.ico"
index 0d9e6f9..91f4782 100644 (file)
@@ -133,19 +133,7 @@ ANGBAND MENU
                MENUITEM "\95Ç\8e\86\82ð\8eg\82¤(&B)", 440
                MENUITEM "\95Ç\8e\86\82ð\91I\91ð(&O)...", 441
                MENUITEM "\89æ\96Ê\82ðHTML\82Å\95Û\91¶(&H)...", 450
-               /*  MENUITEM "\92n\90}(&M)", 430 */
-               /*  MENUITEM SEPARATOR
-               MENUITEM "\96¢\8eg\97p", 410
-               MENUITEM "\96¢\8eg\97p", 411*/
        }
-
-       /*
-       POPUP "\83w\83\8b\83v(&H)"
-       {
-               MENUITEM "\88ê\94Ê(&G)",      901
-               MENUITEM "\83X\83|\83C\83\89\81[(&S)", 902
-       }
-       */
 }
 
 ANGBAND ICON "angband.ico"
index 8b8e810..dbd4e61 100644 (file)
 #include "util/bit-flags-calculator.h"
 
 /*!
- * @brief 恐怖の仮面への特殊処理 (一部職業のみ追加能力&耐性、それ以外は反感&太古の怨念)
+ * @brief 恐怖の仮面への特殊処理
  * @param player_ptr プレーヤーへの参照ポインタ
  * @param o_ptr 対象のオブジェクト構造体への参照ポインタ
- * @param give_power 追加能力の有無
- * @param give_resistance 追加耐性の有無
- * @return そもそも対象のオブジェクトが恐怖の仮面ではないか、「その他の職業」であればTRUE
+ * @return 追加能力/耐性がもらえるならtrue、もらえないならfalse
+ * @details
+ * 純戦士系職業は追加能力/耐性がもらえる。
+ * それ以外では、反感、太古の怨念、呪いが付き追加能力/耐性はもらえない。
  */
-static bool invest_terror_mask(player_type *player_ptr, object_type *o_ptr, bool *give_power, bool *give_resistance)
+static bool invest_terror_mask(player_type *player_ptr, object_type *o_ptr)
 {
     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;
+        return false;
+
+    switch (player_ptr->pclass) {
+    case CLASS_WARRIOR:
+    case CLASS_ARCHER:
+    case CLASS_CAVALRY:
+    case CLASS_BERSERKER:
+        return true;
+    default:
+        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 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;
 }
 
 /*!
@@ -79,53 +78,78 @@ static void milim_swimsuit(player_type *player_ptr, object_type *o_ptr)
 }
 
 /*!
- * @brief 固定アーティファクト生成時の特別なハードコーディング処理を行う。.
- * @details random_artifact_resistance()とあるが実際は固定アーティファクトである。
- * 対象は恐怖の仮面、村正、ロビントンのハープ、龍争虎鬪、ブラッディムーン、羽衣、天女の羽衣、ミリム、
- * その他追加耐性、特性追加処理。
+ * @brief 特定の固定アーティファクトの条件付き追加能力/耐性を付加する
  * @attention プレイヤーの各種ステータスに依存した処理がある。
  * @todo 折を見て関数名を変更すること。
  * @param player_ptr プレーヤーへの参照ポインタ
  * @param o_ptr 対象のオブジェクト構造体ポインタ
  * @param a_ptr 生成する固定アーティファクト構造体ポインタ
  * @return なし
+ * @details
+ * 対象は村正、ロビントンのハープ、龍争虎鬪、ブラッディムーン、羽衣、天女の羽衣、ミリム
  */
-static void random_artifact_resistance(player_type *player_ptr, object_type *o_ptr, artifact_type *a_ptr)
+static void invest_special_artifact_abilities(player_type *player_ptr, object_type *o_ptr)
 {
-    bool give_power = FALSE;
-    bool give_resistance = FALSE;
-    if (invest_terror_mask(player_ptr, o_ptr, &give_power, &give_resistance))
+    switch (o_ptr->name1) {
+    case ART_MURAMASA:
+        if (player_ptr->pclass != CLASS_SAMURAI) {
+            add_flag(o_ptr->art_flags, TR_NO_MAGIC);
+            o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
+        }
         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);
+    case ART_ROBINTON:
+        if (player_ptr->pclass == CLASS_BARD)
+            add_flag(o_ptr->art_flags, TR_DEC_MANA);
+        return;
+    case ART_XIAOLONG:
+        if (player_ptr->pclass == CLASS_MONK)
+            add_flag(o_ptr->art_flags, TR_BLOWS);
+        return;
+    case ART_BLOOD:
+        get_bloody_moon_flags(o_ptr);
+        return;
+    case ART_HEAVENLY_MAIDEN:
+        if (player_ptr->psex != SEX_FEMALE)
+            add_flag(o_ptr->art_flags, TR_AGGRAVATE);
+        return;
+    case ART_MILIM:
+        milim_swimsuit(player_ptr, o_ptr);
+        return;
+    default:
+        break;
     }
+}
 
-    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);
+/*!
+ * @brief 固定アーティファクトオブジェクトに追加能力/耐性を付加する
+ * @param player_ptr プレイヤー情報への参照ポインタ
+ * @param a_ptr 固定アーティファクト情報への参照ポインタ
+ * @param q_ptr オブジェクト情報への参照ポインタ
+ * @return なし
+ */
+static void fixed_artifact_random_abilities(player_type *player_ptr, artifact_type *a_ptr, object_type *o_ptr)
+{
+    auto give_power = false;
+    auto give_resistance = false;
 
-    if (o_ptr->name1 == ART_BLOOD)
-        get_bloody_moon_flags(o_ptr);
+    if (invest_terror_mask(player_ptr, o_ptr)) {
+        give_power = true;
+        give_resistance = true;
+    }
 
-    if ((o_ptr->name1 == ART_HEAVENLY_MAIDEN) && (player_ptr->psex != SEX_FEMALE))
-        add_flag(o_ptr->art_flags, TR_AGGRAVATE);
+    invest_special_artifact_abilities(player_ptr, o_ptr);
 
-    milim_swimsuit(player_ptr, o_ptr);
     if (a_ptr->gen_flags.has(TRG::XTRA_POWER))
-        give_power = TRUE;
+        give_power = true;
 
     if (a_ptr->gen_flags.has(TRG::XTRA_H_RES))
-        give_resistance = TRUE;
+        give_resistance = true;
 
     if (a_ptr->gen_flags.has(TRG::XTRA_RES_OR_POWER)) {
         if (one_in_(2))
-            give_resistance = TRUE;
+            give_resistance = true;
         else
-            give_power = TRUE;
+            give_power = true;
     }
 
     if (give_power)
@@ -144,25 +168,60 @@ static void random_artifact_resistance(player_type *player_ptr, object_type *o_p
     }
 }
 
-static void invest_curse_to_fixed_artifact(player_type *player_ptr, artifact_type *a_ptr, object_type *q_ptr)
+/*!
+ * @brief 固定アーティファクトオブジェクトに呪いフラグを付加する
+ * @param player_ptr プレイヤー情報への参照ポインタ
+ * @param a_ptr 固定アーティファクト情報への参照ポインタ
+ * @param q_ptr オブジェクト情報への参照ポインタ
+ * @return なし
+ */
+static void invest_curse_to_fixed_artifact(player_type *player_ptr, artifact_type *a_ptr, object_type *o_ptr)
 {
+    if (!a_ptr->cost)
+        set_bits(o_ptr->ident, IDENT_BROKEN);
+
     if (a_ptr->gen_flags.has(TRG::CURSED))
-        q_ptr->curse_flags |= TRC_CURSED;
+        set_bits(o_ptr->curse_flags, TRC_CURSED);
 
     if (a_ptr->gen_flags.has(TRG::HEAVY_CURSE))
-        q_ptr->curse_flags |= TRC_HEAVY_CURSE;
+        set_bits(o_ptr->curse_flags, TRC_HEAVY_CURSE);
 
     if (a_ptr->gen_flags.has(TRG::PERMA_CURSE))
-        q_ptr->curse_flags |= TRC_PERMA_CURSE;
+        set_bits(o_ptr->curse_flags, TRC_PERMA_CURSE);
 
     if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE0))
-        q_ptr->curse_flags |= get_curse(player_ptr, 0, q_ptr);
+        set_bits(o_ptr->curse_flags, get_curse(player_ptr, 0, o_ptr));
 
     if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE1))
-        q_ptr->curse_flags |= get_curse(player_ptr, 1, q_ptr);
+        set_bits(o_ptr->curse_flags, get_curse(player_ptr, 1, o_ptr));
 
     if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE2))
-        q_ptr->curse_flags |= get_curse(player_ptr, 2, q_ptr);
+        set_bits(o_ptr->curse_flags, get_curse(player_ptr, 2, o_ptr));
+}
+
+/*!
+ * @brief オブジェクトに指定した固定アーティファクトをオブジェクトに割り当てる。
+ * @param player_ptr プレーヤーへの参照ポインタ
+ * @param o_ptr 生成に割り当てたいオブジェクトの構造体参照ポインタ
+ * @return 適用したアーティファクト情報への参照ポインタ
+ */
+artifact_type *apply_artifact(player_type *player_ptr, object_type *o_ptr)
+{
+    auto a_ptr = &a_info[o_ptr->name1];
+    o_ptr->pval = a_ptr->pval;
+    o_ptr->ac = a_ptr->ac;
+    o_ptr->dd = a_ptr->dd;
+    o_ptr->ds = a_ptr->ds;
+    o_ptr->to_a = a_ptr->to_a;
+    o_ptr->to_h = a_ptr->to_h;
+    o_ptr->to_d = a_ptr->to_d;
+    o_ptr->weight = a_ptr->weight;
+    o_ptr->xtra2 = a_ptr->act_idx;
+
+    invest_curse_to_fixed_artifact(player_ptr, a_ptr, o_ptr);
+    fixed_artifact_random_abilities(player_ptr, a_ptr, o_ptr);
+
+    return a_ptr;
 }
 
 /*!
@@ -179,30 +238,22 @@ static void invest_curse_to_fixed_artifact(player_type *player_ptr, artifact_typ
  */
 bool create_named_art(player_type *player_ptr, ARTIFACT_IDX a_idx, POSITION y, POSITION x)
 {
-    artifact_type *a_ptr = &a_info[a_idx];
+    auto a_ptr = &a_info[a_idx];
     if (a_ptr->name.empty())
-        return FALSE;
+        return false;
 
-    KIND_OBJECT_IDX i = lookup_kind(a_ptr->tval, a_ptr->sval);
+    auto i = lookup_kind(a_ptr->tval, a_ptr->sval);
     if (i == 0)
-        return FALSE;
+        return true;
 
     object_type forge;
-    object_type *q_ptr;
-    q_ptr = &forge;
+    auto 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;
+
+    (void)apply_artifact(player_ptr, q_ptr);
+
+    return drop_near(player_ptr, q_ptr, -1, y, x) ? true : false;
 }
 
 /*!
@@ -218,15 +269,16 @@ bool create_named_art(player_type *player_ptr, ARTIFACT_IDX a_idx, POSITION y, P
  */
 bool make_artifact(player_type *player_ptr, object_type *o_ptr)
 {
-    floor_type *floor_ptr = player_ptr->current_floor_ptr;
+    auto floor_ptr = player_ptr->current_floor_ptr;
     if (floor_ptr->dun_level == 0)
-        return FALSE;
+        return false;
 
     if (o_ptr->number != 1)
-        return FALSE;
+        return false;
 
     for (ARTIFACT_IDX i = 0; i < max_a_idx; i++) {
-        artifact_type *a_ptr = &a_info[i];
+        auto a_ptr = &a_info[i];
+
         if (a_ptr->name.empty())
             continue;
 
@@ -255,54 +307,10 @@ bool make_artifact(player_type *player_ptr, object_type *o_ptr)
             continue;
 
         o_ptr->name1 = i;
-        return TRUE;
+        return true;
     }
 
-    return FALSE;
-}
-
-/*!
- * @brief make_artifact()で選択した固定アーティファクトをオブジェクトに割り当てる。
- * @param player_ptr プレーヤーへの参照ポインタ
- * @param o_ptr 生成に割り当てたいオブジェクトの構造体参照ポインタ
- * @return 適用したアーティファクト情報への参照ポインタ
- */
-artifact_type *apply_artifact(player_type *player_ptr, object_type *o_ptr)
-{
-    artifact_type *a_ptr = &a_info[o_ptr->name1];
-    o_ptr->pval = a_ptr->pval;
-    o_ptr->ac = a_ptr->ac;
-    o_ptr->dd = a_ptr->dd;
-    o_ptr->ds = a_ptr->ds;
-    o_ptr->to_a = a_ptr->to_a;
-    o_ptr->to_h = a_ptr->to_h;
-    o_ptr->to_d = a_ptr->to_d;
-    o_ptr->weight = a_ptr->weight;
-    o_ptr->xtra2 = a_ptr->act_idx;
-    random_artifact_resistance(player_ptr, o_ptr, a_ptr);
-
-    if (o_ptr->name1 == ART_MILIM) {
-        if (player_ptr->pseikaku == PERSONALITY_SEXY) {
-            o_ptr->pval = 3;
-        }
-    }
-
-    if (!a_ptr->cost)
-        o_ptr->ident |= (IDENT_BROKEN);
-    if (a_ptr->gen_flags.has(TRG::CURSED))
-        o_ptr->curse_flags |= (TRC_CURSED);
-    if (a_ptr->gen_flags.has(TRG::HEAVY_CURSE))
-        o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
-    if (a_ptr->gen_flags.has(TRG::PERMA_CURSE))
-        o_ptr->curse_flags |= (TRC_PERMA_CURSE);
-    if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE0))
-        o_ptr->curse_flags |= get_curse(player_ptr, 0, o_ptr);
-    if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE1))
-        o_ptr->curse_flags |= get_curse(player_ptr, 1, o_ptr);
-    if (a_ptr->gen_flags.has(TRG::RANDOM_CURSE2))
-        o_ptr->curse_flags |= get_curse(player_ptr, 2, o_ptr);
-
-    return a_ptr;
+    return false;
 }
 
 /*!
@@ -322,17 +330,17 @@ 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;
+    auto floor_ptr = player_ptr->current_floor_ptr;
     if (floor_ptr->dun_level == 0)
-        return FALSE;
+        return false;
 
     /*! @note get_obj_num_hookによる指定がある場合は生成をキャンセルする / Themed object */
     if (get_obj_num_hook)
-        return FALSE;
+        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];
+        auto a_ptr = &a_info[i];
 
         /*! @note アーティファクト名が空の不正なデータは除外する / Skip "empty" artifacts */
         if (a_ptr->name.empty())
@@ -374,9 +382,9 @@ bool make_artifact_special(player_type *player_ptr, object_type *o_ptr)
         object_prep(player_ptr, o_ptr, k_idx);
 
         o_ptr->name1 = i;
-        return TRUE;
+        return true;
     }
 
     /*! @note 全INSTA_ART固定アーティファクトを試行しても決まらなかった場合 FALSEを返す / Failure */
-    return FALSE;
+    return false;
 }
index b8c011d..04a369d 100644 (file)
@@ -393,7 +393,7 @@ void autopick_entry_from_object(player_type *player_ptr, autopick_type *entry, o
             name = FALSE;
     }
 
-    bool realm_except_class = player_ptr->pclass == CLASS_SORCERER || player_ptr->pclass == CLASS_RED_MAGE || player_ptr->pclass == CLASS_ELEMENTALIST;
+    bool realm_except_class = player_ptr->pclass == CLASS_SORCERER || player_ptr->pclass == CLASS_RED_MAGE;
 
     if (get_realm1_book(player_ptr) == o_ptr->tval && !realm_except_class) {
         ADD_FLG(FLG_REALM1);
index 927288f..6b06687 100644 (file)
@@ -180,7 +180,7 @@ bool is_autopick_match(player_type *player_ptr, object_type *o_ptr, autopick_typ
     if (IS_FLG(FLG_UNREADABLE) && (o_ptr->tval < TV_LIFE_BOOK || check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval)))
         return FALSE;
 
-    bool realm_except_class = player_ptr->pclass == CLASS_SORCERER || player_ptr->pclass == CLASS_RED_MAGE || player_ptr->pclass == CLASS_ELEMENTALIST;
+    bool realm_except_class = player_ptr->pclass == CLASS_SORCERER || player_ptr->pclass == CLASS_RED_MAGE;
 
     if (IS_FLG(FLG_REALM1) && (get_realm1_book(player_ptr) != o_ptr->tval || realm_except_class))
         return FALSE;
index 7a73dbb..dd9e22e 100644 (file)
@@ -314,39 +314,43 @@ bool get_player_realms(player_type *creature_ptr)
 
     /* Select the first realm */
     creature_ptr->realm1 = REALM_NONE;
-    creature_ptr->realm2 = REALM_SELECT_CANCEL;
+    creature_ptr->realm2 = REALM_NONE;
 
     if (creature_ptr->pclass == CLASS_ELEMENTALIST) {
-        creature_ptr->realm1 = select_element_realm(creature_ptr);
-        if (creature_ptr->realm1 == REALM_SELECT_CANCEL)
+        creature_ptr->element = select_element_realm(creature_ptr);
+        if (creature_ptr->element == REALM_SELECT_CANCEL)
             return FALSE;
+
+        put_str(_("魔法        :", "Magic       :"), 6, 1);
+        c_put_str(TERM_L_BLUE, get_element_title(creature_ptr->element), 6, 15);
+        return TRUE;
     }
-    else
-        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;
-                }
-            }
+    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;
 
-            if (check_realm_selection(creature_ptr, count))
+        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)
@@ -354,10 +358,7 @@ bool get_player_realms(player_type *creature_ptr)
 
     /* Print the realm */
     put_str(_("魔法        :", "Magic       :"), 6, 1);
-    if (creature_ptr->pclass == CLASS_ELEMENTALIST)
-        c_put_str(TERM_L_BLUE, get_element_title(creature_ptr->realm1), 6, 15);
-    else
-        c_put_str(TERM_L_BLUE, realm_names[creature_ptr->realm1], 6, 15);
+    c_put_str(TERM_L_BLUE, realm_names[creature_ptr->realm1], 6, 15);
 
     /* Select the second realm */
     while (TRUE) {
index 2e86d2d..d919352 100644 (file)
@@ -125,6 +125,7 @@ void player_wipe_without_name(player_type *creature_ptr)
     cheat_save = FALSE;
     cheat_diary_output = FALSE;
     cheat_turn = FALSE;
+    cheat_immortal = FALSE;
 
     current_world_ptr->total_winner = FALSE;
     creature_ptr->timewalk = FALSE;
@@ -152,7 +153,7 @@ void player_wipe_without_name(player_type *creature_ptr)
     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_spell[i] = RF_ABILITY::MAX;
         creature_ptr->mane_dam[i] = 0;
     }
 
index acb3db2..47aaca6 100644 (file)
@@ -62,7 +62,7 @@ bool ask_quick_start(player_type *creature_ptr)
     update_creature(creature_ptr);
     creature_ptr->chp = creature_ptr->mhp;
     creature_ptr->csp = creature_ptr->msp;
-    process_player_name(creature_ptr, FALSE);
+    process_player_name(creature_ptr);
     return TRUE;
 }
 /*!
@@ -76,7 +76,12 @@ void save_prev_data(player_type *creature_ptr, birther *birther_ptr)
     birther_ptr->prace = creature_ptr->prace;
     birther_ptr->pclass = creature_ptr->pclass;
     birther_ptr->pseikaku = creature_ptr->pseikaku;
-    birther_ptr->realm1 = creature_ptr->realm1;
+
+    if (creature_ptr->pclass == CLASS_ELEMENTALIST)
+        birther_ptr->realm1 = creature_ptr->element;
+    else
+        birther_ptr->realm1 = creature_ptr->realm1;
+
     birther_ptr->realm2 = creature_ptr->realm2;
     birther_ptr->age = creature_ptr->age;
     birther_ptr->ht = creature_ptr->ht;
@@ -118,7 +123,12 @@ void load_prev_data(player_type *creature_ptr, bool swap)
     creature_ptr->prace = previous_char.prace;
     creature_ptr->pclass = previous_char.pclass;
     creature_ptr->pseikaku = previous_char.pseikaku;
-    creature_ptr->realm1 = previous_char.realm1;
+
+    if (creature_ptr->pclass == CLASS_ELEMENTALIST)
+        creature_ptr->element = previous_char.realm1;
+    else
+        creature_ptr->realm1 = previous_char.realm1;
+
     creature_ptr->realm2 = previous_char.realm2;
     creature_ptr->age = previous_char.age;
     creature_ptr->ht = previous_char.ht;
index 6e2f4b0..62cf302 100644 (file)
@@ -5,33 +5,33 @@
 /*
  * 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 */
+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;
+    s16b age{};
+    s16b ht{};
+    s16b wt{};
+    s16b sc{};
 
-    PRICE au; /*!< 初期の所持金 */
+    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];
+    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;
+    PATRON_IDX chaos_patron{};
 
-    s16b vir_types[8];
+    s16b vir_types[8]{};
 
-    char history[4][60];
+    char history[4][60]{};
 
-    bool quick_ok;
-} birther;
+    bool quick_ok{};
+};
 
 extern birther previous_char;
 
index b2403db..7e2ef62 100644 (file)
 #include "main/sound-definitions-table.h"
 #include "main/sound-of-music.h"
 #include "mind/mind-blue-mage.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
-#include "monster-race/race-flags4.h"
+#include "monster-race/race-ability-mask.h"
 #include "mspell/monster-power-table.h"
-#include "mspell/mspell-mask-definitions.h"
-#include "mspell/mspell-type.h"
 #include "player/attack-defense-types.h"
 #include "status/experience.h"
 #include "view/display-messages.h"
@@ -59,37 +55,30 @@ void learn_spell(player_type *learner_ptr, int monspell)
  * @return なし
  * @todo f4, f5, f6を構造体にまとめ直す
  */
-void set_rf_masks(BIT_FLAGS *f4, BIT_FLAGS *f5, BIT_FLAGS *f6, blue_magic_type mode)
+void set_rf_masks(FlagGroup<RF_ABILITY>& ability_flags, blue_magic_type mode)
 {
+    ability_flags.clear();
+
     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;
+        ability_flags.set(RF_ABILITY_BOLT_MASK | RF_ABILITY_BEAM_MASK).reset(RF_ABILITY::ROCKET);
         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));
+        ability_flags.set(RF_ABILITY_BALL_MASK).reset(RF_ABILITY_BREATH_MASK);
         break;
 
     case MONSPELL_TYPE_BREATH:
-        *f4 = (BIT_FLAGS)RF4_BREATH_MASK;
-        *f5 = RF5_BREATH_MASK;
-        *f6 = RF6_BREATH_MASK;
+        ability_flags.set(RF_ABILITY_BREATH_MASK);
         break;
 
     case MONSPELL_TYPE_SUMMON:
-        *f4 = RF4_SUMMON_MASK;
-        *f5 = RF5_SUMMON_MASK;
-        *f6 = (BIT_FLAGS)RF6_SUMMON_MASK;
+        ability_flags.set(RF_ABILITY_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);
+        ability_flags.set(RF_ABILITY_ATTACK_MASK);
+        ability_flags.reset(RF_ABILITY_BOLT_MASK | RF_ABILITY_BEAM_MASK | RF_ABILITY_BALL_MASK | RF_ABILITY_INDIRECT_MASK);
         break;
     }
 }
index 59387a8..8feedb1 100644 (file)
@@ -5,4 +5,4 @@
 enum blue_magic_type : int;
 
 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);
+void set_rf_masks(FlagGroup<RF_ABILITY>& ability_flags, blue_magic_type mode);
index e61ccf6..391e83d 100644 (file)
 #include "io/input-key-requester.h"
 #include "main/sound-of-music.h"
 #include "mind/mind-blue-mage.h"
+#include "monster-race/race-ability-flags.h"
 #include "mspell/monster-power-table.h"
+#include "player/player-status-table.h"
 #include "realm/realm-types.h"
 #include "spell/spell-info.h"
 #include "term/screen-processor.h"
+#include "util/flag-group.h"
 #include "util/int-char-converter.h"
 #include "view/display-messages.h"
-#include "player/player-status-table.h"
+
+#include <vector>
 
 typedef struct learnt_magic_type {
     int blue_magic_num;
@@ -27,13 +31,11 @@ typedef struct learnt_magic_type {
     PERCENTAGE chance;
     int ask;
     int mode;
-    int blue_magics[MAX_MONSPELLS];
+    std::vector<int> blue_magics;
     char choice;
     char out_val[160];
     char comment[80];
-    BIT_FLAGS f4;
-    BIT_FLAGS f5;
-    BIT_FLAGS f6;
+    FlagGroup<RF_ABILITY> ability_flags;
     monster_power spell;
     int menu_line;
     bool flag;
@@ -52,9 +54,8 @@ static learnt_magic_type *initialize_lenat_magic_type(player_type *caster_ptr, l
     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->blue_magics.clear();
+    lm_ptr->ability_flags.clear();
     lm_ptr->menu_line = use_menu ? 1 : 0;
     lm_ptr->flag = FALSE;
     lm_ptr->redraw = FALSE;
@@ -170,18 +171,12 @@ static bool check_blue_magic_kind(learnt_magic_type *lm_ptr)
 
 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, static_cast<blue_magic_type>(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 ((0x00000001U << 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 ((0x00000001U << (lm_ptr->blue_magic_num - 32)) & lm_ptr->f5)
-            lm_ptr->blue_magics[lm_ptr->count++] = lm_ptr->blue_magic_num;
+    set_rf_masks(lm_ptr->ability_flags, static_cast<blue_magic_type>(lm_ptr->mode));
 
-    for (; lm_ptr->blue_magic_num < 96; lm_ptr->blue_magic_num++)
-        if ((0x00000001U << (lm_ptr->blue_magic_num - 64)) & lm_ptr->f6)
-            lm_ptr->blue_magics[lm_ptr->count++] = lm_ptr->blue_magic_num;
+    std::vector<RF_ABILITY> spells;
+    FlagGroup<RF_ABILITY>::get_flags(lm_ptr->ability_flags, std::back_inserter(spells));
+    std::transform(spells.begin(), spells.end(), std::back_inserter(lm_ptr->blue_magics), [](RF_ABILITY ability) { return static_cast<int>(ability); });
+    lm_ptr->count = lm_ptr->ability_flags.count();
 
     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)
@@ -355,7 +350,7 @@ static bool ask_cast_blue_magic(learnt_magic_type *lm_ptr)
         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);
+    (void)strnfmt(tmp_val, 78, _("%sの魔法を唱えますか?", "Use %s? "), monster_powers[static_cast<int>(lm_ptr->blue_magics[lm_ptr->blue_magic_num])].name);
     return get_check(tmp_val);
 }
 
index 7deb5a5..51e1bbf 100644 (file)
@@ -34,7 +34,6 @@
 #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-table.h"
 #include "player/player-status.h"
 #include "spell-kind/spells-launcher.h"
@@ -69,35 +68,37 @@ static int damage;
  * @param dam ものまねの威力
  * @return なし
  */
-static void mane_info(player_type *caster_ptr, char *p, int power, HIT_POINT dam)
+static void mane_info(player_type *caster_ptr, char *p, RF_ABILITY power, HIT_POINT dam)
 {
     PLAYER_LEVEL plev = caster_ptr->lev;
 
     strcpy(p, "");
 
-    if ((power > 2 && power < 41) || (power > 41 && power < 59) || (power == 75))
+    const auto power_int = static_cast<int>(power);
+
+    if ((power_int > 2 && power_int < 41) || (power_int > 41 && power_int < 59) || (power == RF_ABILITY::PSY_SPEAR))
         sprintf(p, " %s%d", KWD_DAM, (int)dam);
     else {
         switch (power) {
-        case 41:
+        case RF_ABILITY::DRAIN_MANA:
             sprintf(p, " %sd%d+%d", KWD_HEAL, plev * 3, plev);
             break;
-        case 64:
+        case RF_ABILITY::HASTE:
             sprintf(p, " %sd%d+%d", KWD_DURATION, 20 + plev, plev);
             break;
-        case 66:
+        case RF_ABILITY::HEAL:
             sprintf(p, " %s%d", KWD_HEAL, plev * 6);
             break;
-        case 67:
+        case RF_ABILITY::INVULNER:
             sprintf(p, " %sd7+7", KWD_DURATION);
             break;
-        case 68:
+        case RF_ABILITY::BLINK:
             sprintf(p, " %s10", KWD_SPHERE);
             break;
-        case 69:
+        case RF_ABILITY::TPORT:
             sprintf(p, " %s%d", KWD_SPHERE, plev * 5);
             break;
-        case 79:
+        case RF_ABILITY::RAISE_DEAD:
             sprintf(p, " %s5", KWD_SPHERE);
             break;
         default:
@@ -176,7 +177,7 @@ static int get_mane_power(player_type *caster_ptr, int *sn, bool baigaesi)
                 /* Dump the spells */
                 for (i = 0; i < num; i++) {
                     /* Access the spell */
-                    spell = monster_powers[caster_ptr->mane_spell[i]];
+                    spell = monster_powers[static_cast<size_t>(caster_ptr->mane_spell[i])];
 
                     chance = spell.manefail;
 
@@ -249,14 +250,14 @@ static int get_mane_power(player_type *caster_ptr, int *sn, bool baigaesi)
         }
 
         /* Save the spell index */
-        spell = monster_powers[caster_ptr->mane_spell[i]];
+        spell = monster_powers[static_cast<int>(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);
+            (void)strnfmt(tmp_val, 78, _("%sをまねますか?", "Use %s? "), spell.name);
 
             /* Belay that order */
             if (!get_check(tmp_val))
@@ -292,7 +293,7 @@ static int get_mane_power(player_type *caster_ptr, int *sn, bool baigaesi)
  * @param spell 発動するモンスター攻撃のID
  * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。
  */
-static bool use_mane(player_type *caster_ptr, int spell)
+static bool use_mane(player_type *caster_ptr, RF_ABILITY spell)
 {
     DIRECTION dir;
     PLAYER_LEVEL plev = caster_ptr->lev;
@@ -304,15 +305,15 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
     /* spell code */
     switch (spell) {
-    case MS_SHRIEK:
+    case RF_ABILITY::SHRIEK:
         msg_print(_("かん高い金切り声をあげた。", "You make a high pitched shriek."));
         aggravate_monsters(caster_ptr, 0);
         break;
 
-    case MS_XXX1:
+    case RF_ABILITY::XXX1:
         break;
 
-    case MS_DISPEL: {
+    case RF_ABILITY::DISPEL: {
         MONSTER_IDX m_idx;
 
         if (!target_set(caster_ptr, TARGET_KILL))
@@ -328,7 +329,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         break;
     }
 
-    case MS_ROCKET:
+    case RF_ABILITY::ROCKET:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -336,7 +337,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_rocket(caster_ptr, GF_ROCKET, dir, damage, 2);
         break;
 
-    case MS_SHOOT:
+    case RF_ABILITY::SHOOT:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -344,16 +345,16 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_bolt(caster_ptr, GF_ARROW, dir, damage);
         break;
 
-    case MS_XXX2:
+    case RF_ABILITY::XXX2:
         break;
 
-    case MS_XXX3:
+    case RF_ABILITY::XXX3:
         break;
 
-    case MS_XXX4:
+    case RF_ABILITY::XXX4:
         break;
 
-    case MS_BR_ACID:
+    case RF_ABILITY::BR_ACID:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -361,7 +362,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_ACID, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_ELEC:
+    case RF_ABILITY::BR_ELEC:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -369,7 +370,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_ELEC, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_FIRE:
+    case RF_ABILITY::BR_FIRE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -377,7 +378,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_FIRE, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_COLD:
+    case RF_ABILITY::BR_COLD:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -385,7 +386,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_COLD, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_POIS:
+    case RF_ABILITY::BR_POIS:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -393,7 +394,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_POIS, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_NETHER:
+    case RF_ABILITY::BR_NETH:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -401,7 +402,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_NETHER, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_LITE:
+    case RF_ABILITY::BR_LITE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -409,7 +410,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_LITE, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_DARK:
+    case RF_ABILITY::BR_DARK:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -417,7 +418,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_DARK, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_CONF:
+    case RF_ABILITY::BR_CONF:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -425,7 +426,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_CONFUSION, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_SOUND:
+    case RF_ABILITY::BR_SOUN:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -433,7 +434,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_SOUND, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_CHAOS:
+    case RF_ABILITY::BR_CHAO:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -441,7 +442,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_CHAOS, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_DISEN:
+    case RF_ABILITY::BR_DISE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -449,7 +450,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_DISENCHANT, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_NEXUS:
+    case RF_ABILITY::BR_NEXU:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -457,7 +458,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_NEXUS, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_TIME:
+    case RF_ABILITY::BR_TIME:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -465,7 +466,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_TIME, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_INERTIA:
+    case RF_ABILITY::BR_INER:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -473,7 +474,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_INERTIAL, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_GRAVITY:
+    case RF_ABILITY::BR_GRAV:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -481,7 +482,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_GRAVITY, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_SHARDS:
+    case RF_ABILITY::BR_SHAR:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -489,7 +490,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_SHARDS, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_PLASMA:
+    case RF_ABILITY::BR_PLAS:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -498,7 +499,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_PLASMA, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_FORCE:
+    case RF_ABILITY::BR_WALL:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -507,7 +508,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_FORCE, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BR_MANA:
+    case RF_ABILITY::BR_MANA:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -516,7 +517,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_MANA, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BALL_NUKE:
+    case RF_ABILITY::BA_NUKE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -525,7 +526,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_ball(caster_ptr, GF_NUKE, dir, damage, 2);
         break;
 
-    case MS_BR_NUKE:
+    case RF_ABILITY::BR_NUKE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -534,7 +535,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_breath(caster_ptr, GF_NUKE, dir, damage, (plev > 35 ? 3 : 2));
         break;
 
-    case MS_BALL_CHAOS:
+    case RF_ABILITY::BA_CHAO:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -542,7 +543,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_ball(caster_ptr, GF_CHAOS, dir, damage, 4);
         break;
-    case MS_BR_DISI:
+    case RF_ABILITY::BR_DISI:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -550,7 +551,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_breath(caster_ptr, GF_DISINTEGRATE, dir, damage, (plev > 35 ? 3 : 2));
         break;
-    case MS_BALL_ACID:
+    case RF_ABILITY::BA_ACID:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -558,7 +559,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_ball(caster_ptr, GF_ACID, dir, damage, 2);
         break;
-    case MS_BALL_ELEC:
+    case RF_ABILITY::BA_ELEC:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -566,7 +567,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_ball(caster_ptr, GF_ELEC, dir, damage, 2);
         break;
-    case MS_BALL_FIRE:
+    case RF_ABILITY::BA_FIRE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -574,7 +575,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_ball(caster_ptr, GF_FIRE, dir, damage, 2);
         break;
-    case MS_BALL_COLD:
+    case RF_ABILITY::BA_COLD:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -582,7 +583,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_ball(caster_ptr, GF_COLD, dir, damage, 2);
         break;
-    case MS_BALL_POIS:
+    case RF_ABILITY::BA_POIS:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -590,7 +591,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_ball(caster_ptr, GF_POIS, dir, damage, 2);
         break;
-    case MS_BALL_NETHER:
+    case RF_ABILITY::BA_NETH:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -598,7 +599,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_ball(caster_ptr, GF_NETHER, dir, damage, 2);
         break;
-    case MS_BALL_WATER:
+    case RF_ABILITY::BA_WATE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -606,7 +607,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_ball(caster_ptr, GF_WATER, dir, damage, 4);
         break;
-    case MS_BALL_MANA:
+    case RF_ABILITY::BA_MANA:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -614,7 +615,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_ball(caster_ptr, GF_MANA, dir, damage, 4);
         break;
-    case MS_BALL_DARK:
+    case RF_ABILITY::BA_DARK:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -622,42 +623,42 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_ball(caster_ptr, GF_DARK, dir, damage, 4);
         break;
-    case MS_DRAIN_MANA:
+    case RF_ABILITY::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:
+    case RF_ABILITY::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:
+    case RF_ABILITY::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:
+    case RF_ABILITY::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:
+    case RF_ABILITY::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:
+    case RF_ABILITY::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:
+    case RF_ABILITY::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:
+    case RF_ABILITY::BO_ACID:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -665,7 +666,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_bolt(caster_ptr, GF_ACID, dir, damage);
         break;
-    case MS_BOLT_ELEC:
+    case RF_ABILITY::BO_ELEC:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -673,7 +674,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_bolt(caster_ptr, GF_ELEC, dir, damage);
         break;
-    case MS_BOLT_FIRE:
+    case RF_ABILITY::BO_FIRE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -681,7 +682,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_bolt(caster_ptr, GF_FIRE, dir, damage);
         break;
-    case MS_BOLT_COLD:
+    case RF_ABILITY::BO_COLD:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -689,7 +690,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_bolt(caster_ptr, GF_COLD, dir, damage);
         break;
-    case MS_STARBURST:
+    case RF_ABILITY::BA_LITE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -697,7 +698,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_ball(caster_ptr, GF_LITE, dir, damage, 4);
         break;
-    case MS_BOLT_NETHER:
+    case RF_ABILITY::BO_NETH:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -705,7 +706,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_bolt(caster_ptr, GF_NETHER, dir, damage);
         break;
-    case MS_BOLT_WATER:
+    case RF_ABILITY::BO_WATE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -713,7 +714,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_bolt(caster_ptr, GF_WATER, dir, damage);
         break;
-    case MS_BOLT_MANA:
+    case RF_ABILITY::BO_MANA:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -721,7 +722,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_bolt(caster_ptr, GF_MANA, dir, damage);
         break;
-    case MS_BOLT_PLASMA:
+    case RF_ABILITY::BO_PLAS:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -729,7 +730,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_bolt(caster_ptr, GF_PLASMA, dir, damage);
         break;
-    case MS_BOLT_ICE:
+    case RF_ABILITY::BO_ICEE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -737,7 +738,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_bolt(caster_ptr, GF_ICE, dir, damage);
         break;
-    case MS_MAGIC_MISSILE:
+    case RF_ABILITY::MISSILE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -745,7 +746,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fire_bolt(caster_ptr, GF_MISSILE, dir, damage);
         break;
-    case MS_SCARE:
+    case RF_ABILITY::SCARE:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -753,12 +754,12 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         fear_monster(caster_ptr, dir, plev + 10);
         break;
-    case MS_BLIND:
+    case RF_ABILITY::BLIND:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         confuse_monster(caster_ptr, dir, plev * 2);
         break;
-    case MS_CONF:
+    case RF_ABILITY::CONF:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -766,20 +767,20 @@ static bool use_mane(player_type *caster_ptr, int spell)
 
         confuse_monster(caster_ptr, dir, plev * 2);
         break;
-    case MS_SLOW:
+    case RF_ABILITY::SLOW:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         slow_monster(caster_ptr, dir, plev);
         break;
-    case MS_SLEEP:
+    case RF_ABILITY::HOLD:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         sleep_monster(caster_ptr, dir, plev);
         break;
-    case MS_SPEED:
+    case RF_ABILITY::HASTE:
         (void)set_fast(caster_ptr, randint1(20 + plev) + plev, FALSE);
         break;
-    case MS_HAND_DOOM: {
+    case RF_ABILITY::HAND_DOOM: {
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -788,28 +789,28 @@ static bool use_mane(player_type *caster_ptr, int spell)
         fire_ball_hide(caster_ptr, GF_HAND_DOOM, dir, 200, 0);
         break;
     }
-    case MS_HEAL:
+    case RF_ABILITY::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:
+    case RF_ABILITY::INVULNER:
         msg_print(_("無傷の球の呪文を唱えた。", "You cast a Globe of Invulnerability."));
         (void)set_invuln(caster_ptr, randint1(7) + 7, FALSE);
         break;
-    case MS_BLINK:
+    case RF_ABILITY::BLINK:
         teleport_player(caster_ptr, 10, TELEPORT_SPONTANEOUS);
         break;
-    case MS_TELEPORT:
+    case RF_ABILITY::TPORT:
         teleport_player(caster_ptr, plev * 5, TELEPORT_SPONTANEOUS);
         break;
-    case MS_WORLD:
+    case RF_ABILITY::WORLD:
         (void)time_walk(caster_ptr);
         break;
-    case MS_SPECIAL:
+    case RF_ABILITY::SPECIAL:
         break;
-    case MS_TELE_TO: {
+    case RF_ABILITY::TELE_TO: {
         monster_type *m_ptr;
         monster_race *r_ptr;
         GAME_TEXT m_name[MAX_NLEN];
@@ -846,18 +847,18 @@ static bool use_mane(player_type *caster_ptr, int spell)
             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:
+    case RF_ABILITY::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:
+    case RF_ABILITY::TELE_LEVEL:
         return teleport_level_other(caster_ptr);
         break;
 
-    case MS_PSY_SPEAR:
+    case RF_ABILITY::PSY_SPEAR:
         if (!get_aim_dir(caster_ptr, &dir))
             return FALSE;
         else
@@ -865,25 +866,25 @@ static bool use_mane(player_type *caster_ptr, int spell)
         (void)fire_beam(caster_ptr, GF_PSY_SPEAR, dir, damage);
         break;
 
-    case MS_DARKNESS:
+    case RF_ABILITY::DARKNESS:
         msg_print(_("暗闇の中で手を振った。", "You gesture in shadow."));
         (void)unlite_area(caster_ptr, 10, 3);
         break;
 
-    case MS_MAKE_TRAP:
+    case RF_ABILITY::TRAPS:
         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:
+    case RF_ABILITY::FORGET:
         msg_print(_("しかし何も起きなかった。", "Nothing happens."));
         break;
-    case MS_RAISE_DEAD:
+    case RF_ABILITY::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: {
+    case RF_ABILITY::S_KIN: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -894,7 +895,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
         }
         break;
     }
-    case MS_S_CYBER: {
+    case RF_ABILITY::S_CYBER: {
         int k;
         int max_cyber = (caster_ptr->current_floor_ptr->dun_level / 50) + randint1(3);
         if (!target_set(caster_ptr, TARGET_KILL))
@@ -906,7 +907,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_CYBER, mode);
         break;
     }
-    case MS_S_MONSTER: {
+    case RF_ABILITY::S_MONSTER: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -915,7 +916,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_NONE, (mode | u_mode));
         break;
     }
-    case MS_S_MONSTERS: {
+    case RF_ABILITY::S_MONSTERS: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -924,7 +925,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_NONE, (mode | u_mode));
         break;
     }
-    case MS_S_ANT: {
+    case RF_ABILITY::S_ANT: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -933,7 +934,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_ANT, mode);
         break;
     }
-    case MS_S_SPIDER: {
+    case RF_ABILITY::S_SPIDER: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -942,7 +943,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_SPIDER, mode);
         break;
     }
-    case MS_S_HOUND: {
+    case RF_ABILITY::S_HOUND: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -951,7 +952,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_HOUND, mode);
         break;
     }
-    case MS_S_HYDRA: {
+    case RF_ABILITY::S_HYDRA: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -960,7 +961,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_HYDRA, mode);
         break;
     }
-    case MS_S_ANGEL: {
+    case RF_ABILITY::S_ANGEL: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -969,7 +970,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_ANGEL, mode);
         break;
     }
-    case MS_S_DEMON: {
+    case RF_ABILITY::S_DEMON: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -978,7 +979,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_DEMON, (mode | u_mode));
         break;
     }
-    case MS_S_UNDEAD: {
+    case RF_ABILITY::S_UNDEAD: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -987,7 +988,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_UNDEAD, (mode | u_mode));
         break;
     }
-    case MS_S_DRAGON: {
+    case RF_ABILITY::S_DRAGON: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -996,7 +997,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_DRAGON, (mode | u_mode));
         break;
     }
-    case MS_S_HI_UNDEAD: {
+    case RF_ABILITY::S_HI_UNDEAD: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -1005,7 +1006,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_HI_UNDEAD, (mode | u_mode));
         break;
     }
-    case MS_S_HI_DRAGON: {
+    case RF_ABILITY::S_HI_DRAGON: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -1014,7 +1015,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_HI_DRAGON, (mode | u_mode));
         break;
     }
-    case MS_S_AMBERITE: {
+    case RF_ABILITY::S_AMBERITES: {
         int k;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -1023,7 +1024,7 @@ static bool use_mane(player_type *caster_ptr, int spell)
             summon_specific(caster_ptr, -1, target_row, target_col, plev, SUMMON_AMBERITES, (mode | PM_ALLOW_UNIQUE));
         break;
     }
-    case MS_S_UNIQUE: {
+    case RF_ABILITY::S_UNIQUE: {
         int k, count = 0;
         if (!target_set(caster_ptr, TARGET_KILL))
             return FALSE;
@@ -1079,7 +1080,7 @@ bool do_cmd_mane(player_type *creature_ptr, bool baigaesi)
     if (!get_mane_power(creature_ptr, &n, baigaesi))
         return FALSE;
 
-    spell = monster_powers[creature_ptr->mane_spell[n]];
+    spell = monster_powers[static_cast<int>(creature_ptr->mane_spell[n])];
 
     /* Spell failure chance */
     chance = spell.manefail;
index b46f5ba..3087639 100644 (file)
@@ -320,7 +320,7 @@ static void drain_essence(player_type *creature_ptr)
         dec--;
     if (has_flag(old_flgs, TR_LOW_AC))
         dec--;
-    if (has_flag(old_flgs, TR_LOW_MAGIC))
+    if (has_flag(old_flgs, TR_HARD_SPELL))
         dec--;
     if (has_flag(old_flgs, TR_FAST_DIGEST))
         dec--;
index 5cbf1b1..65eb79f 100644 (file)
@@ -96,7 +96,7 @@ void do_cmd_player_status(player_type *creature_ptr)
                if (c == 'c')
                {
                        get_name(creature_ptr);
-                       process_player_name(creature_ptr, FALSE);
+                       process_player_name(creature_ptr);
                }
                else if (c == 'f')
                {
index af3215a..0774f37 100644 (file)
@@ -150,7 +150,7 @@ static void init_random_seed(player_type *player_ptr, bool new_game)
         init_saved_floors(player_ptr, TRUE);
 
     if (!new_game)
-        process_player_name(player_ptr, FALSE);
+        process_player_name(player_ptr);
 
     if (init_random_seed)
         Rand_state_init();
@@ -425,7 +425,7 @@ void play_game(player_type *player_ptr, bool new_game, bool browsing_movie)
         player_outfit(player_ptr);
 
     init_io(player_ptr);
-    if (player_ptr->chp < 0)
+    if (player_ptr->chp < 0 && !cheat_immortal)
         player_ptr->is_dead = TRUE;
 
     if (player_ptr->prace == RACE_ANDROID)
index 69c0553..671ca9e 100644 (file)
@@ -13,6 +13,7 @@
 #include "floor/wild.h"
 #include "game-option/disturbance-options.h"
 #include "game-option/map-screen-options.h"
+#include "game-option/cheat-options.h"
 #include "grid/grid.h"
 #include "inventory/pack-overflow.h"
 #include "io/cursor.h"
@@ -264,7 +265,7 @@ void process_player(player_type *creature_ptr)
             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)) {
+        } else if ((creature_ptr->paralyzed || creature_ptr->stun >= 100) && !cheat_immortal) {
             take_turn(creature_ptr, 100);
         } else if (creature_ptr->action == ACTION_REST) {
             if (creature_ptr->resting > 0) {
index cb6b513..9bbb051 100644 (file)
@@ -256,10 +256,9 @@ void window_stuff(player_type *player_ptr)
         fix_player(player_ptr);
     }
 
-    if (window_flags & (PW_MONSTER_LIST)) {
-        player_ptr->window_flags &= ~(PW_MONSTER_LIST);
-        fix_monster_list(player_ptr);
-    }
+    // Always call without PW_MONSTER_LIST flag
+    player_ptr->window_flags &= ~(PW_MONSTER_LIST);
+    fix_monster_list(player_ptr);
 
     if (window_flags & (PW_MESSAGE)) {
         player_ptr->window_flags &= ~(PW_MESSAGE);
index 1ae6071..88b4791 100644 (file)
@@ -17,6 +17,7 @@
 #include "floor/floor-save.h"
 #include "game-option/map-screen-options.h"
 #include "game-option/play-record-options.h"
+#include "game-option/cheat-options.h"
 #include "io/cursor.h"
 #include "io/input-key-requester.h"
 #include "io/write-diary.h"
index 6fd852b..b1ebfb2 100644 (file)
@@ -11,7 +11,7 @@
 /*
  * The dungeon arrays
  */
-dungeon_type *d_info;
+std::vector<dungeon_type> d_info;
 
 /*
  * Maximum number of dungeon in d_info.txt
@@ -99,4 +99,3 @@ DUNGEON_IDX choose_dungeon(concptr note, POSITION y, POSITION x)
 
        return select_dungeon;
 }
-
index 22b8f49..59ac78f 100644 (file)
@@ -1,8 +1,13 @@
 #pragma once
 
 #include "system/angband.h"
+
 #include "grid/feature.h"
+#include "monster-race/race-ability-flags.h"
+#include "util/flag-group.h"
+
 #include <string>
+#include <vector>
 
 #define DUNGEON_FEAT_PROB_NUM 3
 
@@ -58,16 +63,12 @@ struct dungeon_type {
        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{};
+       FlagGroup<RF_ABILITY> m_ability_flags;
 
        char r_char[5]{};               /* Monster race allowed */
        KIND_OBJECT_IDX final_object{}; /* The object you'll find at the bottom */
@@ -81,6 +82,6 @@ struct dungeon_type {
 };
 
 extern DEPTH *max_dlv;
-extern dungeon_type *d_info;
+extern std::vector<dungeon_type> d_info;
 
 extern DUNGEON_IDX choose_dungeon(concptr note, POSITION y, POSITION x);
index 6826b98..5d1dc10 100644 (file)
@@ -19,6 +19,7 @@
 #include "player-info/avatar.h"
 #include "player/player-status.h"
 #include "player/player-status-flags.h"
+#include "util/bit-flags-calculator.h"
 #include "spell/spells-diceroll.h"
 #include "status/bad-status-setter.h"
 #include "system/floor-type-definition.h"
@@ -342,11 +343,32 @@ process_result effect_monster_crusade(player_type *caster_ptr, effect_monster_ty
     return PROCESS_CONTINUE;
 }
 
-static bool effect_monster_capture_attemption(player_type *caster_ptr, effect_monster_type *em_ptr, int capturable_hp)
+/*!
+ * @brief モンスターボールで捕まえられる最大HPを計算する
+ * @param caster_ptr プレイヤー情報への参照ポインタ
+ * @param m_ptr モンスター情報への参照ポインタ
+ * @param hp 計算対象のHP
+ * @return 捕まえられる最大HP
+ */
+static HIT_POINT calcutate_capturable_hp(player_type *caster_ptr, monster_type *m_ptr, HIT_POINT hp)
 {
-    if (em_ptr->m_ptr->hp >= randint0(capturable_hp))
-        return FALSE;
+    if (is_pet(m_ptr))
+        return hp * 4L;
+
+    if ((caster_ptr->pclass == CLASS_BEASTMASTER) && monster_living(m_ptr->r_idx))
+        return hp * 3 / 10;
+
+    return hp * 3 / 20;
+}
 
+/*!
+ * @brief モンスターボールで捕らえた処理
+ * @param caster_ptr プレイヤー情報への参照ポインタ
+ * @param em_ptr 効果情報への参照ポインタ
+ * @return なし
+ */
+static void effect_monster_captured(player_type *caster_ptr, effect_monster_type *em_ptr)
+{
     if (em_ptr->m_ptr->mflag2.has(MFLAG2::CHAMELEON))
         choose_new_monster(caster_ptr, em_ptr->g_ptr->m_idx, FALSE, MON_CHAMELEON);
 
@@ -361,36 +383,39 @@ static bool effect_monster_capture_attemption(player_type *caster_ptr, effect_mo
 
     delete_monster_idx(caster_ptr, em_ptr->g_ptr->m_idx);
     calculate_upkeep(caster_ptr);
-    return TRUE;
 }
 
+/*!
+ * @brief モンスターボールで捕らえる効果(GF_CAPTURE)
+ * @param caster_ptr プレイヤー情報への参照ポインタ
+ * @param em_ptr 効果情報への参照ポインタ
+ * @return 効果発動結果
+ */
 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) {
+        || any_bits(em_ptr->r_ptr->flags1, RF1_UNIQUE | RF1_QUESTOR) || any_bits(em_ptr->r_ptr->flags7, RF7_NAZGUL | RF7_UNIQUE2)
+        || 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;
+    auto r_max_hp = em_ptr->r_ptr->hdice * em_ptr->r_ptr->hside;
+    auto threshold_hp = calcutate_capturable_hp(caster_ptr, em_ptr->m_ptr, r_max_hp);
+    auto capturable_hp = MAX(2, calcutate_capturable_hp(caster_ptr, em_ptr->m_ptr, em_ptr->m_ptr->max_maxhp));
 
-    if (em_ptr->m_ptr->hp >= capturable_hp) {
+    if (threshold_hp < 2 || 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))
+    if (em_ptr->m_ptr->hp <= randint1(capturable_hp)) {
+        effect_monster_captured(caster_ptr, em_ptr);
         return PROCESS_TRUE;
+    }
 
     msg_format(_("うまく捕まえられなかった。", "You failed to capture %s."), em_ptr->m_name);
     em_ptr->skipped = TRUE;
index beac8e1..8491342 100644 (file)
@@ -6,22 +6,18 @@
 #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-race/race-ability-mask.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;
+        auto ability_flags = em_ptr->r_ptr->ability_flags;
+        bool has_mana = ability_flags.reset(RF_ABILITY_NOMAGIC_MASK).any();
        if (!has_mana)
        {
                if (em_ptr->see_s_msg)
index 518a8f8..dc1d76c 100644 (file)
@@ -275,7 +275,7 @@ void strip_name(char *buf, KIND_OBJECT_IDX k_idx)
 {
     object_kind *k_ptr = &k_info[k_idx];
     concptr str = k_ptr->name.c_str();
-    while ((*str == ' ') || (*str == '&'))
+    while ((*str == ' ') || (*str == '&') || (*str == '#'))
         str++;
 
     char *t;
@@ -287,7 +287,7 @@ void strip_name(char *buf, KIND_OBJECT_IDX k_idx)
             continue;
         }
 #endif
-        if (*str != '~')
+        if (*str != '~' && *str != '#')
             *t++ = *str;
     }
 
index 6726f30..12f5056 100644 (file)
@@ -1,6 +1,5 @@
 #include "game-option/birth-options.h"
 
-bool manual_haggle; /* Manually haggle in stores */
 bool easy_band; /* Easy Mode (*) */
 bool smart_learn; /* Monsters learn from their mistakes (*) */
 bool smart_cheat; /* Monsters exploit players weaknesses (*) */
@@ -17,8 +16,4 @@ bool preserve_mode; /* Preserve artifacts (*) */
 bool autoroller; /* Allow use of autoroller for stats (*) */
 bool autochara; /* Autoroll for weight, height and social status */
 bool powerup_home; /* Increase capacity of your home (*) */
-bool show_ammo_detail; /* Show Description of ammo damage */
-bool show_ammo_no_crit; /* Show No-crit damage of ammo */
-bool show_ammo_crit_ratio; /* Show critical ratio of ammo */
-bool show_actual_value; /* Show actual value of skill */
 bool keep_savefile; //!< 同一のセーブファイルでゲームを開始する / Start game with same savefile thet is loaded
index 78d5e73..56a6303 100644 (file)
@@ -2,7 +2,6 @@
 
 #include "system/angband.h"
 
-extern bool manual_haggle; /* Manually haggle in stores */
 extern bool easy_band; /* Easy Mode (*) */
 extern bool smart_learn; /* Monsters learn from their mistakes (*) */
 extern bool smart_cheat; /* Monsters exploit players weaknesses (*) */
index 4bf1e1b..dbcf4ed 100644 (file)
@@ -10,3 +10,4 @@ bool cheat_save; /* Ask for saving death */
 bool cheat_diary_output; /* Detailed info to diary */
 bool cheat_turn; /* Peek turn */
 bool cheat_sight;
+bool cheat_immortal;
index 2357da5..1f8d1ae 100644 (file)
@@ -12,3 +12,4 @@ extern bool cheat_save;
 extern bool cheat_diary_output;
 extern bool cheat_turn;
 extern bool cheat_sight;
+extern bool cheat_immortal;
index 63800c7..5799ba4 100644 (file)
@@ -11,6 +11,7 @@ bool view_torch_grids; /* Map remembers all torch-lit grids */
 bool view_unsafe_grids; /* Map marked by detect traps */
 bool view_reduce_view; /* Reduce view-radius in town */
 bool view_hidden_walls; /* Map walls hidden in other walls. */
+bool view_unsafe_walls; /* Map hidden walls not marked by detect traps. */
 bool fresh_before; /* Flush output while in repeated command */
 bool fresh_after; /* Flush output after monster's move */
 bool fresh_once; /* Flush output only once per key input */
index 82cf6d4..b2b4a3a 100644 (file)
@@ -13,6 +13,7 @@ extern bool view_torch_grids; /* Map remembers all torch-lit grids */
 extern bool view_unsafe_grids; /* Map marked by detect traps */
 extern bool view_reduce_view; /* Reduce view-radius in town */
 extern bool view_hidden_walls; /* Map walls hidden in other walls. */
+extern bool view_unsafe_walls; /* Map hidden walls not marked by detect traps. */
 extern bool fresh_before; /* Flush output while continuous command */
 extern bool fresh_after; /* Flush output after monster's move */
 extern bool fresh_once; /* Flush output only once per key input */
index 94e01d4..8edf31b 100644 (file)
@@ -81,6 +81,8 @@ const std::array<const option_type, MAX_OPTION_INFO> option_info = {{
 
     { &view_hidden_walls, FALSE, OPT_PAGE_MAPSCREEN, 1, 2, "view_hidden_walls", _("壁の中に囲まれた壁を表示する", "Map walls hidden in other walls") },
 
+    { &view_unsafe_walls, TRUE, OPT_PAGE_MAPSCREEN, 1, 1, "view_unsafe_walls", _("トラップ未感知の壁の中に囲まれた壁を表示する", "Map hidden walls not marked by detect traps") },
+
     { &view_reduce_view, FALSE, OPT_PAGE_MAPSCREEN, 1, 17, "view_reduce_view", _("街では視野を狭くする", "Reduce view-radius in town") },
 
     { &fresh_before, TRUE, OPT_PAGE_MAPSCREEN, 1, 23, "fresh_before", _("連続コマンド中に画面を再描画し続ける", "Flush output while in repeated command") },
@@ -132,7 +134,7 @@ const std::array<const option_type, MAX_OPTION_INFO> option_info = {{
 
     { &show_ammo_crit_ratio, FALSE, OPT_PAGE_TEXT, 2, 16, "show_ammo_crit_ratio", _("矢弾の会心発生率を表示する", "Show critical ratio of ammo") },
 
-    { &show_actual_value, FALSE, OPT_PAGE_TEXT, 2, 17, "show_actual_vaule", _("各技能値に実値を表示する", "Show actual value of skill") },
+    { &show_actual_value, FALSE, OPT_PAGE_TEXT, 2, 17, "show_actual_value", _("技能値等に実値を並記する", "Show actual values of skills or etc.") },
 
     /*** Game-Play ***/
     { &stack_force_notes, TRUE, OPT_PAGE_GAMEPLAY, 0, 8, "stack_force_notes", _("異なる銘のアイテムをまとめる", "Merge inscriptions when stacking") },
@@ -204,8 +206,6 @@ const std::array<const option_type, MAX_OPTION_INFO> option_info = {{
         _("トラップ感知範囲外に出る直前に警告する", "Alert when leaving trap detected area") },
 
     /*** Birth Options ***/
-    { &manual_haggle, FALSE, OPT_PAGE_BIRTH, 1, 0, "manual_haggle", _("店で値切り交渉をする", "Manually haggle in stores") },
-
     { &easy_band, FALSE, OPT_PAGE_BIRTH, 6, 31, "easy_band", _("初心者用簡単モード(*)", "Easy Mode (*)") },
 
     { &smart_learn, TRUE, OPT_PAGE_BIRTH, 1, 14, "smart_learn", _("モンスターは失敗を学習する(*)", "Monsters learn from their mistakes (*)") },
@@ -319,7 +319,11 @@ const option_type cheat_info[MAX_CHEAT_OPTIONS]
 
           { &cheat_turn, FALSE, 255, 0x81, 0x00, "cheat_turn", _("ゲームメッセージにターン表示を行う", "Put turn in game messages.") },
 
-          { &cheat_sight, FALSE, 255, 0x82, 0x00, "cheat_sight", _("「見る」コマンドを拡張する。", "Expand \"L\"ook command.") } };
+          { &cheat_sight, FALSE, 255, 0x82, 0x00, "cheat_sight", _("「見る」コマンドを拡張する。", "Expand \"L\"ook command.") },
+
+          { &cheat_immortal, FALSE, 255, 0x83, 0x00, "cheat_immortal", _("完全な不滅状態になる。", "Completely immortal.") } };
+
+
 
 /*!
  * 自動セーブオプションテーブル
index 3518237..d492417 100644 (file)
@@ -23,8 +23,8 @@ struct option_type {
     concptr o_desc{};
 };
 
-#define MAX_OPTION_INFO 125
-#define MAX_CHEAT_OPTIONS 10
+#define MAX_OPTION_INFO 126
+#define MAX_CHEAT_OPTIONS 11
 #define MAX_AUTOSAVE_INFO 2
 
 extern const std::array<const option_type, MAX_OPTION_INFO> option_info;
index 65cae17..6fb59c1 100644 (file)
@@ -14,3 +14,7 @@ bool abbrev_extra; /* Describe obj's extra resistances by abbreviation */
 bool abbrev_all; /* Describe obj's all resistances by abbreviation */
 bool exp_need; /* Show the experience needed for next level */
 bool ignore_unview; /* Ignore whenever any monster does */
+bool show_ammo_detail; /* Show Description of ammo damage */
+bool show_ammo_no_crit; /* Show No-crit damage of ammo */
+bool show_ammo_crit_ratio; /* Show critical ratio of ammo */
+bool show_actual_value; /* Show actual value of skill */
index 1cc1a3e..00ed15f 100644 (file)
@@ -17,7 +17,7 @@
 /*** Terrain feature variables ***/
 
 /* The terrain feature arrays */
-feature_type *f_info;
+std::vector<feature_type> f_info;
 
 /* Nothing */
 FEAT_IDX feat_none;
index 4c10955..41f431a 100644 (file)
@@ -1,8 +1,11 @@
 #pragma once
 
-#include "grid/feature-flag-types.h"
 #include "system/angband.h"
+
+#include "grid/feature-flag-types.h"
+
 #include <string>
+#include <vector>
 
 /* Number of feats we change to (Excluding default). Used in f_info.txt. */
 #define MAX_FEAT_STATES         8
@@ -54,7 +57,7 @@ typedef struct feature_type {
 } feature_type;
 
 extern FEAT_IDX max_f_idx;
-extern feature_type *f_info;
+extern std::vector<feature_type> f_info;
 
 /*** Terrain feature variables ***/
 extern FEAT_IDX feat_none;
index 685fe56..a125f72 100644 (file)
@@ -69,13 +69,7 @@ static errr grab_one_basic_monster_flag(dungeon_type *d_ptr, concptr what)
  */
 static errr grab_one_spell_monster_flag(dungeon_type *d_ptr, concptr what)
 {
-    if (grab_one_flag(&d_ptr->mflags4, r_info_flags4, what) == 0)
-        return 0;
-
-    if (grab_one_flag(&d_ptr->m_a_ability_flags1, r_a_ability_flags1, what) == 0)
-        return 0;
-
-    if (grab_one_flag(&d_ptr->m_a_ability_flags2, r_a_ability_flags2, what) == 0)
+    if (FlagGroup<RF_ABILITY>::grab_one_flag(d_ptr->m_ability_flags, r_info_ability_flags, what))
         return 0;
 
     msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
index 7a08c88..df694b1 100644 (file)
@@ -7,6 +7,7 @@
 #include "util/string-processor.h"
 #include "view/display-messages.h"
 #include <string>
+#include <utility>
 
 /*!
  * @brief テキストトークンを走査してフラグを一つ得る(エゴ用) /
@@ -31,6 +32,25 @@ static bool grab_one_ego_item_flag(ego_item_type *e_ptr, concptr what)
     return 1;
 }
 
+static bool grab_ego_generate_flags(ego_generate_type &xtra, concptr what)
+{
+    for (int i = 0; i < TR_FLAG_MAX; i++) {
+        if (streq(what, k_info_flags[i])) {
+            xtra.tr_flags.push_back(static_cast<tr_type>(i));
+            return false;
+        }
+    }
+
+    auto it = k_info_gen_flags.find(what);
+    if (it != k_info_gen_flags.end()) {
+        xtra.trg_flags.push_back(it->second);
+        return false;
+    }
+
+    return true;
+}
+
+
 /*!
  * @brief アイテムエゴ情報(e_info)のパース関数 /
  * Initialize the "e_info" array, by parsing an ascii "template" file
@@ -132,6 +152,35 @@ errr parse_e_info(char *buf, angband_header *head)
 
             s = t;
         }
+    } else if (buf[0] == 'G') {
+        ego_generate_type xtra;
+
+        s = angband_strstr(buf + 2, ":");
+        if (!s)
+            return 1;
+
+        *s++ = '\0';
+
+        if (2 != sscanf(buf + 2, "%d/%d", &xtra.mul, &xtra.dev))
+            return 1;
+
+        for (; *s;) {
+            for (t = s; *t && (*t != ' ') && (*t != '|'); ++t)
+                ;
+
+            if (*t) {
+                *t++ = '\0';
+                while ((*t == ' ') || (*t == '|'))
+                    t++;
+            }
+
+            if (grab_ego_generate_flags(xtra, s))
+                return 5;
+
+            s = t;
+        }
+
+        e_ptr->xtra_flags.push_back(std::move(xtra));
     } else {
         return 6;
     }
index 051814b..0ec6c82 100644 (file)
@@ -145,7 +145,7 @@ concptr k_info_flags[NUM_K_FLAGS] = {
     "COWARDICE",
     "LOW_MELEE",
     "LOW_AC",
-    "LOW_MAGIC",
+    "HARD_SPELL",
     "FAST_DIGEST",
     "SLOW_REGEN",
     "MIGHTY_THROW",
index 5de0e6c..f3e68cc 100644 (file)
@@ -1,6 +1,7 @@
 #include "info-reader/race-info-tokens-table.h"
 #include "monster-attack/monster-attack-effect.h"
 #include "monster-attack/monster-attack-types.h"
+#include "monster-race/race-ability-flags.h"
 
 /*!
   * モンスターの打撃手段トークンの定義 /
@@ -199,121 +200,111 @@ concptr r_info_flags3[NUM_R_FLAGS_3] = {
 };
 
 /*!
- * モンスター特性トークンの定義4 /
+ * モンスター特性トークン (発動型能力) /
  * Monster race flags
  */
-concptr r_info_flags4[NUM_R_FLAGS_4] = {
-       "SHRIEK",
-       "XXX1",
-       "DISPEL",
-       "ROCKET",
-       "SHOOT",
-       "XXX2",
-       "XXX3",
-       "XXX4",
-       "BR_ACID",
-       "BR_ELEC",
-       "BR_FIRE",
-       "BR_COLD",
-       "BR_POIS",
-       "BR_NETH",
-       "BR_LITE",
-       "BR_DARK",
-       "BR_CONF",
-       "BR_SOUN",
-       "BR_CHAO",
-       "BR_DISE",
-       "BR_NEXU",
-       "BR_TIME",
-       "BR_INER",
-       "BR_GRAV",
-       "BR_SHAR",
-       "BR_PLAS",
-       "BR_WALL",
-       "BR_MANA",
-       "BA_NUKE",
-       "BR_NUKE",
-       "BA_CHAO",
-       "BR_DISI",
-};
+/* clang-format off */
+const std::unordered_map<std::string_view, RF_ABILITY> r_info_ability_flags = {
+       {"SHRIEK", RF_ABILITY::SHRIEK },
+       {"XXX1", RF_ABILITY::XXX1 },
+       {"DISPEL", RF_ABILITY::DISPEL },
+       {"ROCKET", RF_ABILITY::ROCKET },
+       {"SHOOT", RF_ABILITY::SHOOT },
+       {"XXX2", RF_ABILITY::XXX2 },
+       {"XXX3", RF_ABILITY::XXX3 },
+       {"XXX4", RF_ABILITY::XXX4 },
+       {"BR_ACID", RF_ABILITY::BR_ACID },
+       {"BR_ELEC", RF_ABILITY::BR_ELEC },
+       {"BR_FIRE", RF_ABILITY::BR_FIRE },
+       {"BR_COLD", RF_ABILITY::BR_COLD },
+       {"BR_POIS", RF_ABILITY::BR_POIS },
+       {"BR_NETH", RF_ABILITY::BR_NETH },
+       {"BR_LITE", RF_ABILITY::BR_LITE },
+       {"BR_DARK", RF_ABILITY::BR_DARK },
+       {"BR_CONF", RF_ABILITY::BR_CONF },
+       {"BR_SOUN", RF_ABILITY::BR_SOUN },
+       {"BR_CHAO", RF_ABILITY::BR_CHAO },
+       {"BR_DISE", RF_ABILITY::BR_DISE },
+       {"BR_NEXU", RF_ABILITY::BR_NEXU },
+       {"BR_TIME", RF_ABILITY::BR_TIME },
+       {"BR_INER", RF_ABILITY::BR_INER },
+       {"BR_GRAV", RF_ABILITY::BR_GRAV },
+       {"BR_SHAR", RF_ABILITY::BR_SHAR },
+       {"BR_PLAS", RF_ABILITY::BR_PLAS },
+       {"BR_WALL", RF_ABILITY::BR_WALL },
+       {"BR_MANA", RF_ABILITY::BR_MANA },
+       {"BA_NUKE", RF_ABILITY::BA_NUKE },
+       {"BR_NUKE", RF_ABILITY::BR_NUKE },
+       {"BA_CHAO", RF_ABILITY::BA_CHAO },
+       {"BR_DISI", RF_ABILITY::BR_DISI },
 
-/*!
- * モンスター特性トークン(発動型能力1) /
- * Monster race flags
- */
-concptr r_a_ability_flags1[NUM_R_ABILITY_FLAGS_1] = {
-       "BA_ACID",
-       "BA_ELEC",
-       "BA_FIRE",
-       "BA_COLD",
-       "BA_POIS",
-       "BA_NETH",
-       "BA_WATE",
-       "BA_MANA",
-       "BA_DARK",
-       "DRAIN_MANA",
-       "MIND_BLAST",
-       "BRAIN_SMASH",
-       "CAUSE_1",
-       "CAUSE_2",
-       "CAUSE_3",
-       "CAUSE_4",
-       "BO_ACID",
-       "BO_ELEC",
-       "BO_FIRE",
-       "BO_COLD",
-       "BA_LITE",
-       "BO_NETH",
-       "BO_WATE",
-       "BO_MANA",
-       "BO_PLAS",
-       "BO_ICEE",
-       "MISSILE",
-       "SCARE",
-       "BLIND",
-       "CONF",
-       "SLOW",
-       "HOLD"
-};
+       {"BA_ACID", RF_ABILITY::BA_ACID },
+       {"BA_ELEC", RF_ABILITY::BA_ELEC },
+       {"BA_FIRE", RF_ABILITY::BA_FIRE },
+       {"BA_COLD", RF_ABILITY::BA_COLD },
+       {"BA_POIS", RF_ABILITY::BA_POIS },
+       {"BA_NETH", RF_ABILITY::BA_NETH },
+       {"BA_WATE", RF_ABILITY::BA_WATE },
+       {"BA_MANA", RF_ABILITY::BA_MANA },
+       {"BA_DARK", RF_ABILITY::BA_DARK },
+       {"DRAIN_MANA", RF_ABILITY::DRAIN_MANA },
+       {"MIND_BLAST", RF_ABILITY::MIND_BLAST },
+       {"BRAIN_SMASH", RF_ABILITY::BRAIN_SMASH },
+       {"CAUSE_1", RF_ABILITY::CAUSE_1 },
+       {"CAUSE_2", RF_ABILITY::CAUSE_2 },
+       {"CAUSE_3", RF_ABILITY::CAUSE_3 },
+       {"CAUSE_4", RF_ABILITY::CAUSE_4 },
+       {"BO_ACID", RF_ABILITY::BO_ACID },
+       {"BO_ELEC", RF_ABILITY::BO_ELEC },
+       {"BO_FIRE", RF_ABILITY::BO_FIRE },
+       {"BO_COLD", RF_ABILITY::BO_COLD },
+       {"BA_LITE", RF_ABILITY::BA_LITE },
+       {"BO_NETH", RF_ABILITY::BO_NETH },
+       {"BO_WATE", RF_ABILITY::BO_WATE },
+       {"BO_MANA", RF_ABILITY::BO_MANA },
+       {"BO_PLAS", RF_ABILITY::BO_PLAS },
+       {"BO_ICEE", RF_ABILITY::BO_ICEE },
+       {"MISSILE", RF_ABILITY::MISSILE },
+       {"SCARE", RF_ABILITY::SCARE },
+       {"BLIND", RF_ABILITY::BLIND },
+       {"CONF", RF_ABILITY::CONF },
+       {"SLOW", RF_ABILITY::SLOW },
+       {"HOLD", RF_ABILITY::HOLD },
 
-/*!
- * モンスター特性トークン(発動型能力2) /
- * Monster race flags
- */
-concptr r_a_ability_flags2[NUM_R_ABILITY_FLAGS_2] = {
-       "HASTE",
-       "HAND_DOOM",
-       "HEAL",
-       "INVULNER",
-       "BLINK",
-       "TPORT",
-       "WORLD",
-       "SPECIAL",
-       "TELE_TO",
-       "TELE_AWAY",
-       "TELE_LEVEL",
-       "PSY_SPEAR",
-       "DARKNESS",
-       "TRAPS",
-       "FORGET",
-       "ANIM_DEAD", /* ToDo: Implement ANIM_DEAD */
-       "S_KIN",
-       "S_CYBER",
-       "S_MONSTER",
-       "S_MONSTERS",
-       "S_ANT",
-       "S_SPIDER",
-       "S_HOUND",
-       "S_HYDRA",
-       "S_ANGEL",
-       "S_DEMON",
-       "S_UNDEAD",
-       "S_DRAGON",
-       "S_HI_UNDEAD",
-       "S_HI_DRAGON",
-       "S_AMBERITES",
-       "S_UNIQUE"
+       {"HASTE", RF_ABILITY::HASTE },
+       {"HAND_DOOM", RF_ABILITY::HAND_DOOM },
+       {"HEAL", RF_ABILITY::HEAL },
+       {"INVULNER", RF_ABILITY::INVULNER },
+       {"BLINK", RF_ABILITY::BLINK },
+       {"TPORT", RF_ABILITY::TPORT },
+       {"WORLD", RF_ABILITY::WORLD },
+       {"SPECIAL", RF_ABILITY::SPECIAL },
+       {"TELE_TO", RF_ABILITY::TELE_TO },
+       {"TELE_AWAY", RF_ABILITY::TELE_AWAY },
+       {"TELE_LEVEL", RF_ABILITY::TELE_LEVEL },
+       {"PSY_SPEAR", RF_ABILITY::PSY_SPEAR },
+       {"DARKNESS", RF_ABILITY::DARKNESS },
+       {"TRAPS", RF_ABILITY::TRAPS },
+       {"FORGET", RF_ABILITY::FORGET },
+       {"ANIM_DEAD", RF_ABILITY::RAISE_DEAD /* ToDo: Implement ANIM_DEAD */ },
+       {"S_KIN", RF_ABILITY::S_KIN },
+       {"S_CYBER", RF_ABILITY::S_CYBER },
+       {"S_MONSTER", RF_ABILITY::S_MONSTER },
+       {"S_MONSTERS", RF_ABILITY::S_MONSTERS },
+       {"S_ANT", RF_ABILITY::S_ANT },
+       {"S_SPIDER", RF_ABILITY::S_SPIDER },
+       {"S_HOUND", RF_ABILITY::S_HOUND },
+       {"S_HYDRA", RF_ABILITY::S_HYDRA },
+       {"S_ANGEL", RF_ABILITY::S_ANGEL },
+       {"S_DEMON", RF_ABILITY::S_DEMON },
+       {"S_UNDEAD", RF_ABILITY::S_UNDEAD },
+       {"S_DRAGON", RF_ABILITY::S_DRAGON },
+       {"S_HI_UNDEAD", RF_ABILITY::S_HI_UNDEAD },
+       {"S_HI_DRAGON", RF_ABILITY::S_HI_DRAGON },
+       {"S_AMBERITES", RF_ABILITY::S_AMBERITES },
+       {"S_UNIQUE", RF_ABILITY::S_UNIQUE },
 };
+/* clang-format on */
 
 /*!
  * モンスター特性トークンの定義7 /
index 06c1358..a5c35e6 100644 (file)
@@ -4,6 +4,9 @@
 #include "monster-attack/monster-attack-types.h"
 #include "system/angband.h"
 
+#include <string_view>
+#include <unordered_map>
+
 #define NUM_R_FLAGS_1 32
 #define NUM_R_FLAGS_2 32
 #define NUM_R_FLAGS_3 32
 #define NUM_R_FLAGS_9 33
 #define NUM_R_FLAGS_R 32
 
+enum class RF_ABILITY;
+
 extern concptr r_info_blow_method[NB_RBM_TYPE + 1];
 extern concptr r_info_blow_effect[NB_RBE_TYPE + 1];
 extern concptr r_info_flags1[NUM_R_FLAGS_1];
 extern concptr r_info_flags2[NUM_R_FLAGS_2];
 extern concptr r_info_flags3[NUM_R_FLAGS_3];
-extern concptr r_info_flags4[NUM_R_FLAGS_4];
-extern concptr r_a_ability_flags1[NUM_R_ABILITY_FLAGS_1];
-extern concptr r_a_ability_flags2[NUM_R_ABILITY_FLAGS_2];
+extern const std::unordered_map<std::string_view, RF_ABILITY> r_info_ability_flags;
 extern concptr r_info_flags7[NUM_R_FLAGS_7];
 extern concptr r_info_flags8[NUM_R_FLAGS_8];
 extern concptr r_info_flags9[NUM_R_FLAGS_9];
index b522a02..d8f0773 100644 (file)
@@ -50,13 +50,7 @@ static errr grab_one_basic_flag(monster_race *r_ptr, concptr what)
  */
 static errr grab_one_spell_flag(monster_race *r_ptr, concptr what)
 {
-    if (grab_one_flag(&r_ptr->flags4, r_info_flags4, what) == 0)
-        return PARSE_ERROR_NONE;
-
-    if (grab_one_flag(&r_ptr->a_ability_flags1, r_a_ability_flags1, what) == 0)
-        return PARSE_ERROR_NONE;
-
-    if (grab_one_flag(&r_ptr->a_ability_flags2, r_a_ability_flags2, what) == 0)
+    if (FlagGroup<RF_ABILITY>::grab_one_flag(r_ptr->ability_flags, r_info_ability_flags, what))
         return PARSE_ERROR_NONE;
 
     msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
index 7fa9b3e..23541f6 100644 (file)
@@ -753,63 +753,54 @@ bool get_item_floor(player_type *owner_ptr, COMMAND_CODE *cp, concptr pmt, concp
         }
             /* Fall through */
         default: {
-            int ver;
+            bool tag_not_found = FALSE;
+
             if (command_wrk != USE_FLOOR) {
-                bool not_found = FALSE;
                 if (!get_tag(owner_ptr, &fis_ptr->k, fis_ptr->which, command_wrk, fis_ptr->tval))
-                    not_found = TRUE;
+                    tag_not_found = TRUE;
                 else if ((fis_ptr->k < INVEN_MAIN_HAND) ? !fis_ptr->inven : !fis_ptr->equip)
-                    not_found = TRUE;
-                else if (!get_item_okay(owner_ptr, fis_ptr->k, fis_ptr->tval))
-                    not_found = TRUE;
+                    tag_not_found = TRUE;
 
-                if (!not_found) {
-                    *cp = fis_ptr->k;
-                    fis_ptr->item = TRUE;
-                    fis_ptr->done = TRUE;
+                if (!tag_not_found)
                     fis_ptr->cur_tag = fis_ptr->which;
-                    break;
-                }
             } else {
                 if (get_tag_floor(owner_ptr->current_floor_ptr, &fis_ptr->k, fis_ptr->which, fis_ptr->floor_list, fis_ptr->floor_num)) {
                     fis_ptr->k = 0 - fis_ptr->floor_list[fis_ptr->k];
-                    *cp = fis_ptr->k;
-                    fis_ptr->item = TRUE;
-                    fis_ptr->done = TRUE;
                     fis_ptr->cur_tag = fis_ptr->which;
-                    break;
-                }
+                } else
+                    tag_not_found = TRUE;
             }
 
-            ver = isupper(fis_ptr->which);
-            fis_ptr->which = (char)tolower(fis_ptr->which);
-            if (command_wrk == (USE_INVEN)) {
-                if (fis_ptr->which == '(')
-                    fis_ptr->k = fis_ptr->i1;
-                else if (fis_ptr->which == ')')
-                    fis_ptr->k = fis_ptr->i2;
-                else
-                    fis_ptr->k = label_to_inventory(owner_ptr, fis_ptr->which);
-            } else if (command_wrk == (USE_EQUIP)) {
-                if (fis_ptr->which == '(')
-                    fis_ptr->k = fis_ptr->e1;
-                else if (fis_ptr->which == ')')
-                    fis_ptr->k = fis_ptr->e2;
-                else
-                    fis_ptr->k = label_to_equipment(owner_ptr, fis_ptr->which);
-            } else if (command_wrk == USE_FLOOR) {
-                if (fis_ptr->which == '(')
-                    fis_ptr->k = 0;
-                else if (fis_ptr->which == ')')
-                    fis_ptr->k = fis_ptr->floor_num - 1;
-                else
-                    fis_ptr->k = islower(fis_ptr->which) ? A2I(fis_ptr->which) : -1;
-                if (fis_ptr->k < 0 || fis_ptr->k >= fis_ptr->floor_num || fis_ptr->k >= 23) {
-                    bell();
-                    break;
-                }
+            if (tag_not_found) {
+                fis_ptr->which = (char)tolower(fis_ptr->which);
+                if (command_wrk == (USE_INVEN)) {
+                    if (fis_ptr->which == '(')
+                        fis_ptr->k = fis_ptr->i1;
+                    else if (fis_ptr->which == ')')
+                        fis_ptr->k = fis_ptr->i2;
+                    else
+                        fis_ptr->k = label_to_inventory(owner_ptr, fis_ptr->which);
+                } else if (command_wrk == (USE_EQUIP)) {
+                    if (fis_ptr->which == '(')
+                        fis_ptr->k = fis_ptr->e1;
+                    else if (fis_ptr->which == ')')
+                        fis_ptr->k = fis_ptr->e2;
+                    else
+                        fis_ptr->k = label_to_equipment(owner_ptr, fis_ptr->which);
+                } else if (command_wrk == USE_FLOOR) {
+                    if (fis_ptr->which == '(')
+                        fis_ptr->k = 0;
+                    else if (fis_ptr->which == ')')
+                        fis_ptr->k = fis_ptr->floor_num - 1;
+                    else
+                        fis_ptr->k = islower(fis_ptr->which) ? A2I(fis_ptr->which) : -1;
+                    if (fis_ptr->k < 0 || fis_ptr->k >= fis_ptr->floor_num || fis_ptr->k >= 23) {
+                        bell();
+                        break;
+                    }
 
-                fis_ptr->k = 0 - fis_ptr->floor_list[fis_ptr->k];
+                    fis_ptr->k = 0 - fis_ptr->floor_list[fis_ptr->k];
+                }
             }
 
             if ((command_wrk != USE_FLOOR) && !get_item_okay(owner_ptr, fis_ptr->k, fis_ptr->tval)) {
@@ -817,6 +808,7 @@ bool get_item_floor(player_type *owner_ptr, COMMAND_CODE *cp, concptr pmt, concp
                 break;
             }
 
+            int ver = isupper(fis_ptr->which);
             if (ver && !verify(owner_ptr, _("本当に", "Try"), fis_ptr->k)) {
                 fis_ptr->done = TRUE;
                 break;
index f42b6fa..81816c3 100644 (file)
@@ -38,7 +38,7 @@ static bool is_specific_curse(BIT_FLAGS flag)
 {
     return (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);
+        || (flag == TRC_LOW_AC) || (flag == TRC_HARD_SPELL) || (flag == TRC_FAST_DIGEST) || (flag == TRC_SLOW_REGEN);
 }
 
 static void choise_cursed_item(player_type *creature_ptr, BIT_FLAGS flag, object_type *o_ptr, int *choices, int *number, int item_num)
@@ -83,8 +83,8 @@ static void choise_cursed_item(player_type *creature_ptr, BIT_FLAGS flag, object
     case TRC_LOW_AC:
         cf = TR_LOW_AC;
         break;
-    case TRC_LOW_MAGIC:
-        cf = TR_LOW_MAGIC;
+    case TRC_HARD_SPELL:
+        cf = TR_HARD_SPELL;
         break;
     case TRC_FAST_DIGEST:
         cf = TR_FAST_DIGEST;
index 115b527..743f77b 100644 (file)
@@ -541,40 +541,33 @@ bool get_item(player_type *owner_ptr, OBJECT_IDX *cp, concptr pmt, concptr str,
         }
             /* Fall through */
         default: {
-            int ver;
-            bool not_found = FALSE;
+            bool tag_not_found = FALSE;
+
             if (!get_tag(owner_ptr, &item_selection_ptr->k, item_selection_ptr->which, command_wrk ? USE_EQUIP : USE_INVEN, item_selection_ptr->tval)) {
-                not_found = TRUE;
+                tag_not_found = TRUE;
             } else if ((item_selection_ptr->k < INVEN_MAIN_HAND) ? !item_selection_ptr->inven : !item_selection_ptr->equip) {
-                not_found = TRUE;
-            } else if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
-                not_found = TRUE;
+                tag_not_found = TRUE;
             }
 
-            if (!not_found) {
-                *item_selection_ptr->cp = item_selection_ptr->k;
-                item_selection_ptr->item = TRUE;
-                item_selection_ptr->done = TRUE;
+            if (!tag_not_found)
                 item_selection_ptr->cur_tag = item_selection_ptr->which;
-                break;
-            }
-
-            ver = isupper(item_selection_ptr->which);
-            item_selection_ptr->which = (char)tolower(item_selection_ptr->which);
-            if (!command_wrk) {
-                if (item_selection_ptr->which == '(')
-                    item_selection_ptr->k = item_selection_ptr->i1;
-                else if (item_selection_ptr->which == ')')
-                    item_selection_ptr->k = item_selection_ptr->i2;
-                else
-                    item_selection_ptr->k = label_to_inventory(owner_ptr, item_selection_ptr->which);
-            } else {
-                if (item_selection_ptr->which == '(')
-                    item_selection_ptr->k = item_selection_ptr->e1;
-                else if (item_selection_ptr->which == ')')
-                    item_selection_ptr->k = item_selection_ptr->e2;
-                else
-                    item_selection_ptr->k = label_to_equipment(owner_ptr, item_selection_ptr->which);
+            else {
+                item_selection_ptr->which = (char)tolower(item_selection_ptr->which);
+                if (!command_wrk) {
+                    if (item_selection_ptr->which == '(')
+                        item_selection_ptr->k = item_selection_ptr->i1;
+                    else if (item_selection_ptr->which == ')')
+                        item_selection_ptr->k = item_selection_ptr->i2;
+                    else
+                        item_selection_ptr->k = label_to_inventory(owner_ptr, item_selection_ptr->which);
+                } else {
+                    if (item_selection_ptr->which == '(')
+                        item_selection_ptr->k = item_selection_ptr->e1;
+                    else if (item_selection_ptr->which == ')')
+                        item_selection_ptr->k = item_selection_ptr->e2;
+                    else
+                        item_selection_ptr->k = label_to_equipment(owner_ptr, item_selection_ptr->which);
+                }
             }
 
             if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
@@ -582,6 +575,7 @@ bool get_item(player_type *owner_ptr, OBJECT_IDX *cp, concptr pmt, concptr str,
                 break;
             }
 
+            int ver = isupper(item_selection_ptr->which);
             if (ver && !verify(owner_ptr, _("本当に", "Try"), item_selection_ptr->k)) {
                 item_selection_ptr->done = TRUE;
                 break;
index 960e52f..c26514c 100644 (file)
@@ -38,6 +38,7 @@
 #include "util/sort.h"
 #include "view/display-messages.h"
 #include "world/world.h"
+#include <string>
 
 /*!
  * @brief プレイヤーのペット情報をファイルにダンプする
@@ -438,7 +439,8 @@ static void dump_aux_virtues(player_type *creature_ptr, FILE *fff)
             fprintf(fff, "%s ???\n", stat_names[v_nr]);
     }
 
-    fprintf(fff, _("\n属性 : %s\n", "\nYour alignment : %s\n"), your_alignment(creature_ptr));
+    std::string alg = your_alignment(creature_ptr);
+    fprintf(fff, _("\n属性 : %s\n", "\nYour alignment : %s\n"), alg.c_str());
     fprintf(fff, "\n");
     dump_virtues(creature_ptr, fff);
 }
index 78fc178..7cedc41 100644 (file)
@@ -9,14 +9,16 @@
 #include "cmd-item/cmd-magiceat.h"
 #include "cmd-item/cmd-smith.h"
 #include "mind/mind-blue-mage.h"
+#include "monster-race/race-ability-flags.h"
 #include "mspell/monster-power-table.h"
 #include "object/object-kind-hook.h"
 #include "object/object-kind.h"
+#include "util/flag-group.h"
+
+#include <vector>
 
 typedef struct {
-    BIT_FLAGS f4;
-    BIT_FLAGS f5;
-    BIT_FLAGS f6;
+    FlagGroup<RF_ABILITY> ability_flags;
 } learnt_spell_table;
 
 /*!
@@ -121,10 +123,8 @@ static void dump_smith(player_type *creature_ptr, FILE *fff)
  */
 static void add_monster_spell_type(char p[][80], int col, blue_magic_type spell_type, learnt_spell_table *learnt_spell_ptr)
 {
-    learnt_spell_ptr->f4 = 0;
-    learnt_spell_ptr->f5 = 0;
-    learnt_spell_ptr->f6 = 0;
-    set_rf_masks(&learnt_spell_ptr->f4, &learnt_spell_ptr->f5, &learnt_spell_ptr->f6, spell_type);
+    learnt_spell_ptr->ability_flags.clear();
+    set_rf_masks(learnt_spell_ptr->ability_flags, spell_type);
     switch (spell_type) {
     case MONSPELL_TYPE_BOLT:
         strcat(p[col], _("\n     [ボルト型]\n", "\n     [Bolt  Type]\n"));
@@ -164,46 +164,33 @@ static void dump_blue_mage(player_type *creature_ptr, FILE *fff)
     int col = 0;
     strcat(p[col], _("\n\n  [学習済みの青魔法]\n", "\n\n  [Learned Blue Magic]\n"));
 
-    int spellnum[MAX_MONSPELLS];
     for (int spell_type = 1; spell_type < 6; spell_type++) {
         col++;
         learnt_spell_table learnt_magic;
         add_monster_spell_type(p, col, static_cast<blue_magic_type>(spell_type), &learnt_magic);
 
-        int num = 0;
-        for (int i = 0; i < 32; i++) {
-            if ((0x00000001U << i) & learnt_magic.f4)
-                spellnum[num++] = i;
-        }
-
-        for (int i = 32; i < 64; i++) {
-            if ((0x00000001U << (i - 32)) & learnt_magic.f5)
-                spellnum[num++] = i;
-        }
-
-        for (int i = 64; i < 96; i++) {
-            if ((0x00000001U << (i - 64)) & learnt_magic.f6)
-                spellnum[num++] = i;
-        }
+        std::vector<RF_ABILITY> learnt_spells;
+        FlagGroup<RF_ABILITY>::get_flags(learnt_magic.ability_flags, std::back_inserter(learnt_spells));
 
         col++;
         bool pcol = FALSE;
         strcat(p[col], "       ");
 
-        for (int i = 0; i < num; i++) {
-            if (creature_ptr->magic_num2[spellnum[i]] == 0)
+        for (auto spell : learnt_spells) {
+            const int spellnum = static_cast<int>(spell);
+            if (creature_ptr->magic_num2[spellnum] == 0)
                 continue;
 
             pcol = TRUE;
             int l1 = strlen(p[col]);
-            int l2 = strlen(monster_powers_short[spellnum[i]]);
+            int l2 = strlen(monster_powers_short[spellnum]);
             if ((l1 + l2) >= 75) {
                 strcat(p[col], "\n");
                 col++;
                 strcat(p[col], "       ");
             }
 
-            strcat(p[col], monster_powers_short[spellnum[i]]);
+            strcat(p[col], monster_powers_short[spellnum]);
             strcat(p[col], ", ");
         }
 
index 684153d..2ec65b9 100644 (file)
@@ -1,5 +1,6 @@
 #include "io/input-key-acceptor.h"
 #include "cmd-io/macro-util.h"
+#include "core/stuff-handler.h"
 #include "core/window-redrawer.h"
 #include "game-option/input-options.h"
 #include "game-option/map-screen-options.h"
@@ -40,6 +41,22 @@ static bool parse_macro = FALSE;
  */
 static bool parse_under = FALSE;
 
+/*!
+ * @brief 全てのウィンドウの再描画を行う
+ * @return なし
+ * @details
+ * カーソル位置がずれるので戻す。
+ */
+static void all_term_fresh(int x, int y)
+{
+    p_ptr->window_flags |= PW_ALL;
+    handle_stuff(p_ptr);
+
+    term_activate(angband_term[0]);
+    term_gotoxy(x, y);
+    term_fresh();
+}
+
 /*
  * Cancel macro action on the queue
  */
@@ -195,6 +212,8 @@ char inkey(void)
     }
 
     term_activate(angband_term[0]);
+    auto y = angband_term[0]->scr->cy;
+    auto x = angband_term[0]->scr->cx;
     char kk;
     while (!ch) {
         if (!inkey_base && inkey_scan && (0 != term_inkey(&kk, FALSE, FALSE))) {
@@ -203,9 +222,7 @@ char inkey(void)
 
         if (!done && (0 != term_inkey(&kk, FALSE, FALSE))) {
             start_term_fresh();
-            term_activate(old);
-            term_fresh();
-            term_activate(angband_term[0]);
+            all_term_fresh(x, y);
             current_world_ptr->character_saved = FALSE;
 
             signal_count = 0;
@@ -398,6 +415,10 @@ int inkey_special(bool numpad_cursor)
     return (int)((unsigned char)key);
 }
 
+/*!
+ * @brief 全てのウィンドウの描画を止める
+ * @return なし
+ */
 void stop_term_fresh(void)
 {
     for (int j = 0; j < 8; j++) {
@@ -406,6 +427,10 @@ void stop_term_fresh(void)
     }
 }
 
+/*!
+ * @brief 全てのウィンドウの描画を再開する
+ * @return なし
+ */
 void start_term_fresh(void)
 {
     for (int j = 0; j < 8; j++) {
index 68fad2c..eef103b 100644 (file)
@@ -20,7 +20,6 @@
 #include "cmd-action/cmd-travel.h"
 #include "cmd-action/cmd-tunnel.h"
 #include "cmd-building/cmd-building.h"
-#include "cmd-building/cmd-store.h"
 #include "cmd-io/cmd-autopick.h"
 #include "cmd-io/cmd-diary.h"
 #include "cmd-io/cmd-dump.h"
@@ -81,6 +80,7 @@
 #include "player/special-defense-types.h"
 #include "status/action-setter.h"
 #include "store/home.h"
+#include "store/cmd-store.h"
 #include "store/store-util.h"
 #include "system/floor-type-definition.h"
 #include "term/screen-processor.h"
index 9a5ab69..9ef20ed 100644 (file)
@@ -211,12 +211,8 @@ void request_command(player_type *player_ptr, int shopping)
         if (!macro_running() && !command_new && auto_debug_save && (!inkey_next || *inkey_next == '\0')) {
             save_player(player_ptr, SAVE_TYPE_DEBUG);
         }
-        if (macro_running() && fresh_once) {
+        if (fresh_once && macro_running()) {
             stop_term_fresh();
-        } else {
-            start_term_fresh();
-            player_ptr->window_flags |= PW_MONSTER_LIST;
-            handle_stuff(player_ptr);
         }
 
         if (command_new) {
index d32344e..a6a070a 100644 (file)
@@ -285,7 +285,7 @@ void load_all_pref_files(player_type *player_ptr)
     process_pref_file(player_ptr, buf, process_autopick_file_command);
     sprintf(buf, "%s.prf", player_ptr->base_name);
     process_pref_file(player_ptr, buf, process_autopick_file_command);
-    if (player_ptr->realm1 != REALM_NONE && player_ptr->pclass != CLASS_ELEMENTALIST) {
+    if (player_ptr->realm1 != REALM_NONE) {
         sprintf(buf, "%s.prf", realm_names[player_ptr->realm1]);
         process_pref_file(player_ptr, buf, process_autopick_file_command);
     }
index 1b03571..7fd90b5 100644 (file)
@@ -418,7 +418,7 @@ errr report_score(player_type *creature_ptr, void (*update_playtime)(void), disp
 #endif
 
     if (creature_ptr->pclass == CLASS_ELEMENTALIST)
-        realm1_name = get_element_title(creature_ptr->realm1);
+        realm1_name = get_element_title(creature_ptr->element);
     else
         realm1_name = realm_names[creature_ptr->realm1];
 
index 12ab887..c84039f 100644 (file)
@@ -11,6 +11,7 @@
 #include "floor/floor-events.h"
 #include "io/write-diary.h"
 #include "monster-floor/monster-lite.h"
+#include "game-option/cheat-options.h"
 #include "save/save.h"
 #include "system/system-variables.h"
 #include "term/term-color-types.h"
@@ -78,7 +79,8 @@ static void handle_signal_simple(int sig)
         forget_view(p_ptr->current_floor_ptr);
         clear_mon_lite(p_ptr->current_floor_ptr);
         p_ptr->playing = FALSE;
-        p_ptr->is_dead = TRUE;
+        if (!cheat_immortal)
+            p_ptr->is_dead = TRUE;
         p_ptr->leaving = TRUE;
         close_game(p_ptr);
         quit(_("強制終了", "interrupt"));
index 65a52d5..3ea7cab 100644 (file)
@@ -73,7 +73,7 @@ void do_cmd_knowledge_spell_exp(player_type *creature_ptr)
     if (!open_temporary_file(&fff, file_name))
         return;
 
-    if (creature_ptr->realm1 != REALM_NONE && creature_ptr->pclass != CLASS_ELEMENTALIST) {
+    if (creature_ptr->realm1 != REALM_NONE) {
         fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[creature_ptr->realm1]);
         for (SPELL_IDX i = 0; i < 32; i++) {
             const magic_type *s_ptr;
index 079fe54..8eb422f 100644 (file)
@@ -21,6 +21,7 @@
 #include "util/buffer-shaper.h"
 #include "util/int-char-converter.h"
 #include "world/world.h"
+#include <string>
 
 /*
  * List virtues & status
@@ -32,7 +33,8 @@ void do_cmd_knowledge_virtues(player_type *creature_ptr)
     if (!open_temporary_file(&fff, file_name))
         return;
 
-    fprintf(fff, _("現在の属性 : %s\n\n", "Your alignment : %s\n\n"), your_alignment(creature_ptr));
+    std::string alg = your_alignment(creature_ptr);
+    fprintf(fff, _("現在の属性 : %s\n\n", "Your alignment : %s\n\n"), alg.c_str());
     dump_virtues(creature_ptr, fff);
     angband_fclose(fff);
     (void)show_file(creature_ptr, TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
@@ -88,7 +90,7 @@ static void dump_yourself(player_type *creature_ptr, FILE *fff)
     }
 
     fprintf(fff, "\n");
-    if (creature_ptr->realm1 && creature_ptr->pclass != CLASS_ELEMENTALIST) {
+    if (creature_ptr->realm1) {
         shape_buffer(realm_explanations[technic2magic(creature_ptr->realm1) - 1], 78, temp, sizeof(temp));
         fprintf(fff, _("魔法: %s\n", "Realm: %s\n"), realm_names[creature_ptr->realm1]);
 
index 12d3b6d..625dfc0 100644 (file)
@@ -488,9 +488,9 @@ static void move_RF3_to_RFR(monster_race *r_ptr, const BIT_FLAGS rf3, const BIT_
     }
 }
 
-static void move_RF4_BR_to_RFR(monster_race *r_ptr, const BIT_FLAGS rf4_br, const BIT_FLAGS rfr)
+static void move_RF4_BR_to_RFR(monster_race *r_ptr, BIT_FLAGS f4, const BIT_FLAGS rf4_br, const BIT_FLAGS rfr)
 {
-    if (r_ptr->r_flags4 & rf4_br)
+    if (f4 & rf4_br)
         r_ptr->r_flagsr |= rfr;
 }
 
@@ -500,7 +500,7 @@ static void move_RF4_BR_to_RFR(monster_race *r_ptr, const BIT_FLAGS rf4_br, cons
  * @param r_idx モンスター種族ID
  * @details 本来はr_idxからr_ptrを決定可能だが、互換性を優先するため元コードのままとする
  */
-void set_old_lore(monster_race *r_ptr, const MONRACE_IDX r_idx)
+void set_old_lore(monster_race *r_ptr, BIT_FLAGS f4, const MONRACE_IDX r_idx)
 {
     r_ptr->r_flagsr = 0L;
     move_RF3_to_RFR(r_ptr, RF3_IM_ACID, RFR_IM_ACID);
@@ -516,17 +516,17 @@ void set_old_lore(monster_race *r_ptr, const MONRACE_IDX r_idx)
     move_RF3_to_RFR(r_ptr, RF3_RES_DISE, RFR_RES_DISE);
     move_RF3_to_RFR(r_ptr, RF3_RES_ALL, RFR_RES_ALL);
 
-    move_RF4_BR_to_RFR(r_ptr, RF4_BR_LITE, RFR_RES_LITE);
-    move_RF4_BR_to_RFR(r_ptr, RF4_BR_DARK, RFR_RES_DARK);
-    move_RF4_BR_to_RFR(r_ptr, RF4_BR_SOUN, RFR_RES_SOUN);
-    move_RF4_BR_to_RFR(r_ptr, RF4_BR_CHAO, RFR_RES_CHAO);
-    move_RF4_BR_to_RFR(r_ptr, RF4_BR_TIME, RFR_RES_TIME);
-    move_RF4_BR_to_RFR(r_ptr, RF4_BR_INER, RFR_RES_INER);
-    move_RF4_BR_to_RFR(r_ptr, RF4_BR_GRAV, RFR_RES_GRAV);
-    move_RF4_BR_to_RFR(r_ptr, RF4_BR_SHAR, RFR_RES_SHAR);
-    move_RF4_BR_to_RFR(r_ptr, RF4_BR_WALL, RFR_RES_WALL);
-
-    if (r_ptr->r_flags4 & RF4_BR_CONF)
+    move_RF4_BR_to_RFR(r_ptr, f4, RF4_BR_LITE, RFR_RES_LITE);
+    move_RF4_BR_to_RFR(r_ptr, f4, RF4_BR_DARK, RFR_RES_DARK);
+    move_RF4_BR_to_RFR(r_ptr, f4, RF4_BR_SOUN, RFR_RES_SOUN);
+    move_RF4_BR_to_RFR(r_ptr, f4, RF4_BR_CHAO, RFR_RES_CHAO);
+    move_RF4_BR_to_RFR(r_ptr, f4, RF4_BR_TIME, RFR_RES_TIME);
+    move_RF4_BR_to_RFR(r_ptr, f4, RF4_BR_INER, RFR_RES_INER);
+    move_RF4_BR_to_RFR(r_ptr, f4, RF4_BR_GRAV, RFR_RES_GRAV);
+    move_RF4_BR_to_RFR(r_ptr, f4, RF4_BR_SHAR, RFR_RES_SHAR);
+    move_RF4_BR_to_RFR(r_ptr, f4, RF4_BR_WALL, RFR_RES_WALL);
+
+    if (f4 & RF4_BR_CONF)
         r_ptr->r_flags3 |= RF3_NO_CONF;
 
     if (r_idx == MON_STORMBRINGER)
index c3bd50b..ec89f9b 100644 (file)
@@ -38,5 +38,5 @@ extern const int QUEST_ROYAL_CRYPT;
 
 void rd_item_old(player_type *player_ptr, object_type *o_ptr);
 void rd_monster_old(player_type *player_ptr, monster_type *m_ptr);
-void set_old_lore(monster_race *r_ptr, const MONRACE_IDX r_idx);
+void set_old_lore(monster_race *r_ptr, BIT_FLAGS f4, const MONRACE_IDX r_idx);
 errr rd_dungeon_old(player_type *player_ptr);
index f99d362..b51fcd7 100644 (file)
@@ -55,13 +55,30 @@ void rd_lore(monster_race *r_ptr, MONRACE_IDX r_idx)
     rd_u32b(&r_ptr->r_flags1);
     rd_u32b(&r_ptr->r_flags2);
     rd_u32b(&r_ptr->r_flags3);
-    rd_u32b(&r_ptr->r_flags4);
-    rd_u32b(&r_ptr->r_flags5);
-    rd_u32b(&r_ptr->r_flags6);
-    if (h_older_than(1, 5, 0, 3))
-        set_old_lore(r_ptr, r_idx);
-    else
+    if (loading_savefile_version_is_older_than(3)) {
+        u32b f4, f5, f6;
+        rd_u32b(&f4);
+        rd_u32b(&f5);
+        rd_u32b(&f6);
+        if (h_older_than(1, 5, 0, 3))
+            set_old_lore(r_ptr, f4, r_idx);
+        else
+            rd_u32b(&r_ptr->r_flagsr);
+
+        auto migrate = [r_ptr](u32b f, int start_idx) {
+            std::bitset<32> flag_bits(f);
+            for (size_t i = 0; i < flag_bits.size(); i++) {
+                auto ability = static_cast<RF_ABILITY>(start_idx + i);
+                r_ptr->r_ability_flags[ability] = flag_bits[i];
+            }
+        };
+        migrate(f4, 0);
+        migrate(f5, 32);
+        migrate(f6, 64);
+    } else {
         rd_u32b(&r_ptr->r_flagsr);
+        rd_FlagGroup(r_ptr->r_ability_flags, rd_byte);
+    }
 
     rd_byte(&tmp8u);
     r_ptr->max_num = (MONSTER_NUMBER)tmp8u;
@@ -72,10 +89,8 @@ void rd_lore(monster_race *r_ptr, MONRACE_IDX r_idx)
     r_ptr->r_flags1 &= r_ptr->flags1;
     r_ptr->r_flags2 &= r_ptr->flags2;
     r_ptr->r_flags3 &= r_ptr->flags3;
-    r_ptr->r_flags4 &= r_ptr->flags4;
-    r_ptr->r_flags5 &= r_ptr->a_ability_flags1;
-    r_ptr->r_flags6 &= r_ptr->a_ability_flags2;
     r_ptr->r_flagsr &= r_ptr->flagsr;
+    r_ptr->r_ability_flags &= r_ptr->ability_flags;
 }
 
 errr load_lore(void)
index f515345..835ca55 100644 (file)
@@ -56,6 +56,7 @@ void rd_options(void)
     cheat_diary_output = (c & 0x8000) ? TRUE : FALSE;
     cheat_turn = (c & 0x0080) ? TRUE : FALSE;
     cheat_sight = (c & 0x0040) ? TRUE : FALSE;
+    cheat_immortal = (c & 0x0020) ? TRUE : FALSE;
 
     rd_byte((byte *)&autosave_l);
     rd_byte((byte *)&autosave_t);
index e27bad0..bee337a 100644 (file)
 #include "load/world-loader.h"
 #include "market/arena.h"
 #include "mutation/mutation-calculator.h"
+#include "monster-race/race-ability-flags.h"
 #include "player/attack-defense-types.h"
 #include "player/player-skill.h"
 #include "system/floor-type-definition.h"
 #include "world/world.h"
 
+/*!
+ * @brief セーブデータから領域情報を読み込む / Read player realms
+ * @param creature_ptr プレーヤーへの参照ポインタ
+ * @return なし
+ */
+static void rd_realms(player_type *creature_ptr)
+{
+    byte tmp8u;
+
+    rd_byte(&tmp8u);
+    if (creature_ptr->pclass == CLASS_ELEMENTALIST)
+        creature_ptr->element = (REALM_IDX)tmp8u;
+    else
+        creature_ptr->realm1 = (REALM_IDX)tmp8u;
+
+    rd_byte(&tmp8u);
+    creature_ptr->realm2 = (REALM_IDX)tmp8u;
+}
+
+/*!
+ * @brief セーブデータからプレイヤー基本情報を読み込む / Read player's basic info
+ * @param creature_ptr プレーヤーへの参照ポインタ
+ * @return なし
+ */
 void rd_base_info(player_type *creature_ptr)
 {
     rd_string(creature_ptr->name, sizeof(creature_ptr->name));
@@ -43,11 +68,8 @@ void rd_base_info(player_type *creature_ptr)
     creature_ptr->pseikaku = (player_personality_type)tmp8u;
 
     rd_byte(&creature_ptr->psex);
-    rd_byte(&tmp8u);
-    creature_ptr->realm1 = (REALM_IDX)tmp8u;
 
-    rd_byte(&tmp8u);
-    creature_ptr->realm2 = (REALM_IDX)tmp8u;
+    rd_realms(creature_ptr);
 
     rd_byte(&tmp8u);
     if (h_older_than(0, 4, 4))
@@ -174,7 +196,7 @@ static void set_imitation(player_type *creature_ptr)
 {
     if (h_older_than(0, 0, 1)) {
         for (int i = 0; i < MAX_MANE; i++) {
-            creature_ptr->mane_spell[i] = -1;
+            creature_ptr->mane_spell[i] = RF_ABILITY::MAX;
             creature_ptr->mane_dam[i] = 0;
         }
 
@@ -191,7 +213,7 @@ static void set_imitation(player_type *creature_ptr)
         }
 
         for (int i = 0; i < MAX_MANE; i++) {
-            creature_ptr->mane_spell[i] = -1;
+            creature_ptr->mane_spell[i] = RF_ABILITY::MAX;
             creature_ptr->mane_dam[i] = 0;
         }
 
@@ -203,7 +225,7 @@ static void set_imitation(player_type *creature_ptr)
     for (int i = 0; i < MAX_MANE; i++) {
         s16b tmp16s;
         rd_s16b(&tmp16s);
-        creature_ptr->mane_spell[i] = (SPELL_IDX)tmp16s;
+        creature_ptr->mane_spell[i] = static_cast<RF_ABILITY>(tmp16s);
         rd_s16b(&tmp16s);
         creature_ptr->mane_dam[i] = (SPELL_IDX)tmp16s;
     }
index 899aa0c..28f07eb 100644 (file)
@@ -36,7 +36,7 @@ static void home_carry_load(player_type *player_ptr, store_type *store_ptr, obje
         return;
     }
 
-    if (store_ptr->stock_num >= STORE_INVEN_MAX * 10)
+    if (store_ptr->stock_num >= store_get_stock_max(STORE_HOME))
         return;
 
     s32b value = object_value(player_ptr, o_ptr);
@@ -74,26 +74,26 @@ static errr rd_store(player_type *player_ptr, int town_number, int store_number)
         store_ptr = &town_info[town_number].store[store_number];
     }
 
-    byte own;
+    byte owner_idx;
     byte tmp8u;
-    s16b num;
+    s16b inven_num;
     rd_s32b(&store_ptr->store_open);
     rd_s16b(&store_ptr->insult_cur);
-    rd_byte(&own);
+    rd_byte(&owner_idx);
     if (h_older_than(1, 0, 4)) {
         rd_byte(&tmp8u);
-        num = tmp8u;
+        inven_num = tmp8u;
     } else {
-        rd_s16b(&num);
+        rd_s16b(&inven_num);
     }
 
     rd_s16b(&store_ptr->good_buy);
     rd_s16b(&store_ptr->bad_buy);
 
     rd_s32b(&store_ptr->last_visit);
-    store_ptr->owner = own;
+    store_ptr->owner = owner_idx;
 
-    for (int j = 0; j < num; j++) {
+    for (int j = 0; j < inven_num; j++) {
         object_type forge;
         object_type *q_ptr;
         q_ptr = &forge;
@@ -101,9 +101,8 @@ static errr rd_store(player_type *player_ptr, int town_number, int store_number)
 
         rd_item(player_ptr, q_ptr);
 
-        bool is_valid_item = store_ptr->stock_num
-            < (store_number == STORE_HOME ? STORE_INVEN_MAX * 10 : store_number == STORE_MUSEUM ? STORE_INVEN_MAX * 50 : STORE_INVEN_MAX);
-        if (!is_valid_item)
+        auto stock_max = store_get_stock_max(static_cast<STORE_TYPE_IDX>(store_number));
+        if (store_ptr->stock_num >= stock_max)
             continue;
 
         if (sort) {
@@ -117,15 +116,25 @@ static errr rd_store(player_type *player_ptr, int town_number, int store_number)
     return 0;
 }
 
+/*!
+ * @brief 店舗情報を読み込む
+ * @param creature_ptr プレイヤー情報への参照ポインタ(未使用)
+ * @return 読み込み終わったら0、失敗したら22
+ */
 errr load_store(player_type *creature_ptr)
 {
+    (void)creature_ptr;
+
     u16b tmp16u;
     rd_u16b(&tmp16u);
-    int town_count = tmp16u;
+    auto town_count = (int)tmp16u;
+
     rd_u16b(&tmp16u);
-    for (int i = 1; i < town_count; i++)
-        for (int j = 0; j < tmp16u; j++)
-            if (rd_store(creature_ptr, i, j))
+    auto store_count = (int)tmp16u;
+
+    for (int town_idx = 1; town_idx < town_count; town_idx++)
+        for (int store_idx = 0; store_idx < store_count; store_idx++)
+            if (rd_store(creature_ptr, town_idx, store_idx))
                 return 22;
 
     return 0;
index 069105d..72e0621 100644 (file)
@@ -146,8 +146,6 @@ void set_drop_flags(lore_type *lore_ptr)
     lore_ptr->flags1 = lore_ptr->r_ptr->flags1;
     lore_ptr->flags2 = lore_ptr->r_ptr->flags2;
     lore_ptr->flags3 = lore_ptr->r_ptr->flags3;
-    lore_ptr->flags4 = lore_ptr->r_ptr->flags4;
-    lore_ptr->a_ability_flags1 = lore_ptr->r_ptr->a_ability_flags1;
-    lore_ptr->a_ability_flags2 = lore_ptr->r_ptr->a_ability_flags2;
+    lore_ptr->ability_flags = lore_ptr->r_ptr->ability_flags;
     lore_ptr->flagsr = lore_ptr->r_ptr->flagsr;
 }
index 706ce18..110969c 100644 (file)
@@ -63,23 +63,18 @@ int lore_do_probe(player_type *player_ptr, MONRACE_IDX r_idx)
             n++;
         if (!(r_ptr->r_flags3 & (1UL << i)) && (r_ptr->flags3 & (1UL << i)))
             n++;
-        if (!(r_ptr->r_flags4 & (1UL << i)) && (r_ptr->flags4 & (1UL << i)))
-            n++;
-        if (!(r_ptr->r_flags5 & (1UL << i)) && (r_ptr->a_ability_flags1 & (1UL << i)))
-            n++;
-        if (!(r_ptr->r_flags6 & (1UL << i)) && (r_ptr->a_ability_flags2 & (1UL << i)))
-            n++;
         if (!(r_ptr->r_flagsr & (1UL << i)) && (r_ptr->flagsr & (1UL << i)))
             n++;
     }
 
+    auto ability_flags = r_ptr->ability_flags;
+    n += ability_flags.reset(r_ptr->r_ability_flags).count();
+
     r_ptr->r_flags1 = r_ptr->flags1;
     r_ptr->r_flags2 = r_ptr->flags2;
     r_ptr->r_flags3 = r_ptr->flags3;
-    r_ptr->r_flags4 = r_ptr->flags4;
-    r_ptr->r_flags5 = r_ptr->a_ability_flags1;
-    r_ptr->r_flags6 = r_ptr->a_ability_flags2;
     r_ptr->r_flagsr = r_ptr->flagsr;
+    r_ptr->r_ability_flags = r_ptr->ability_flags;
 
     if (!(r_ptr->r_xtra1 & MR1_EVOLUTION))
         n++;
index a4e6a3e..c4022e1 100644 (file)
@@ -42,9 +42,7 @@ lore_type *initialize_lore_type(lore_type *lore_ptr, MONRACE_IDX r_idx, monster_
     lore_ptr->flags1 = (lore_ptr->r_ptr->flags1 & lore_ptr->r_ptr->r_flags1);
     lore_ptr->flags2 = (lore_ptr->r_ptr->flags2 & lore_ptr->r_ptr->r_flags2);
     lore_ptr->flags3 = (lore_ptr->r_ptr->flags3 & lore_ptr->r_ptr->r_flags3);
-    lore_ptr->flags4 = (lore_ptr->r_ptr->flags4 & lore_ptr->r_ptr->r_flags4);
-    lore_ptr->a_ability_flags1 = (lore_ptr->r_ptr->a_ability_flags1 & lore_ptr->r_ptr->r_flags5);
-    lore_ptr->a_ability_flags2 = (lore_ptr->r_ptr->a_ability_flags2 & lore_ptr->r_ptr->r_flags6);
+    lore_ptr->ability_flags = (lore_ptr->r_ptr->ability_flags & lore_ptr->r_ptr->r_ability_flags);
     lore_ptr->flags7 = (lore_ptr->r_ptr->flags7 & lore_ptr->r_ptr->flags7);
     lore_ptr->flagsr = (lore_ptr->r_ptr->flagsr & lore_ptr->r_ptr->r_flagsr);
     lore_ptr->reinforce = FALSE;
index f4609c3..f7396ff 100644 (file)
@@ -2,6 +2,9 @@
 
 #include "system/angband.h"
 #include "system/monster-race-definition.h"
+#include "monster-race/race-ability-flags.h"
+#include "util/flag-group.h"
+
 #include <string>
 #include <unordered_map>
 
@@ -25,9 +28,8 @@ typedef struct lore_type {
     BIT_FLAGS flags1;
     BIT_FLAGS flags2;
     BIT_FLAGS flags3;
-    BIT_FLAGS flags4;
-    BIT_FLAGS a_ability_flags1;
-    BIT_FLAGS a_ability_flags2;
+    FlagGroup<RF_ABILITY> ability_flags;
+
     BIT_FLAGS flags7;
     BIT_FLAGS flagsr;
     bool reinforce;
index a76f4de..6333ba8 100644 (file)
@@ -1,9 +1,6 @@
 #include "lore/magic-types-setter.h"
 #include "lore/lore-calculator.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
 #include "monster-race/race-flags3.h"
-#include "monster-race/race-flags4.h"
 #include "monster-race/race-flags7.h"
 #include "mspell/mspell-type.h"
 #include "term/term-color-types.h"
 void set_breath_types(player_type *player_ptr, lore_type *lore_ptr)
 {
     lore_ptr->vn = 0;
-    if (lore_ptr->flags4 & (RF4_BR_ACID)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_ACID)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_ACID), _("酸%s", "acid%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_GREEN;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_ELEC)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_ELEC)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_ELEC), _("稲妻%s", "lightning%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_BLUE;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_FIRE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_FIRE)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_FIRE), _("火炎%s", "fire%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_RED;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_COLD)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_COLD)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_COLD), _("冷気%s", "frost%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_WHITE;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_POIS)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_POIS)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_POIS), _("毒%s", "poison%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_GREEN;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_NETH)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_NETH)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_NETHER), _("地獄%s", "nether%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_DARK;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_LITE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_LITE)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_LITE), _("閃光%s", "light%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_YELLOW;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_DARK)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_DARK)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_DARK), _("暗黒%s", "darkness%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_DARK;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_CONF)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_CONF)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_CONF), _("混乱%s", "confusion%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_UMBER;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_SOUN)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_SOUN)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_SOUND), _("轟音%s", "sound%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_ORANGE;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_CHAO)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_CHAO)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_CHAOS), _("カオス%s", "chaos%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_VIOLET;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_DISE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_DISE)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_DISEN), _("劣化%s", "disenchantment%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_VIOLET;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_NEXU)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_NEXU)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_NEXUS), _("因果混乱%s", "nexus%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_VIOLET;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_TIME)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_TIME)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_TIME), _("時間逆転%s", "time%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_BLUE;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_INER)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_INER)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_INERTIA), _("遅鈍%s", "inertia%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_SLATE;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_GRAV)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_GRAV)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_GRAVITY), _("重力%s", "gravity%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_SLATE;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_SHAR)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_SHAR)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_SHARDS), _("破片%s", "shards%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_UMBER;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_PLAS)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_PLAS)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_PLASMA), _("プラズマ%s", "plasma%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_RED;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_WALL)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_WALL)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_FORCE), _("フォース%s", "force%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_UMBER;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_MANA)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_MANA)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_MANA), _("魔力%s", "mana%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_BLUE;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_NUKE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_NUKE)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_NUKE), _("放射性廃棄物%s", "toxic waste%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_GREEN;
     }
 
-    if (lore_ptr->flags4 & (RF4_BR_DISI)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BR_DISI)) {
         set_damage(player_ptr, lore_ptr, (MS_BR_DISI), _("分解%s", "disintegration%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_SLATE;
@@ -146,73 +143,73 @@ void set_breath_types(player_type *player_ptr, lore_type *lore_ptr)
 
 void set_ball_types(player_type *player_ptr, lore_type *lore_ptr)
 {
-    if (lore_ptr->a_ability_flags1 & (RF5_BA_ACID)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_ACID)) {
         set_damage(player_ptr, lore_ptr, (MS_BALL_ACID), _("アシッド・ボール%s", "produce acid balls%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_GREEN;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BA_ELEC)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_ELEC)) {
         set_damage(player_ptr, lore_ptr, (MS_BALL_ELEC), _("サンダー・ボール%s", "produce lightning balls%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_BLUE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BA_FIRE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_FIRE)) {
         set_damage(player_ptr, lore_ptr, (MS_BALL_FIRE), _("ファイア・ボール%s", "produce fire balls%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_RED;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BA_COLD)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_COLD)) {
         set_damage(player_ptr, lore_ptr, (MS_BALL_COLD), _("アイス・ボール%s", "produce frost balls%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_WHITE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BA_POIS)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_POIS)) {
         set_damage(player_ptr, lore_ptr, (MS_BALL_POIS), _("悪臭雲%s", "produce poison balls%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_GREEN;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BA_NETH)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_NETH)) {
         set_damage(player_ptr, lore_ptr, (MS_BALL_NETHER), _("地獄球%s", "produce nether balls%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_DARK;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BA_WATE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_WATE)) {
         set_damage(player_ptr, lore_ptr, (MS_BALL_WATER), _("ウォーター・ボール%s", "produce water balls%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_BLUE;
     }
 
-    if (lore_ptr->flags4 & (RF4_BA_NUKE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_NUKE)) {
         set_damage(player_ptr, lore_ptr, (MS_BALL_NUKE), _("放射能球%s", "produce balls of radiation%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_GREEN;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BA_MANA)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_MANA)) {
         set_damage(player_ptr, lore_ptr, (MS_BALL_MANA), _("魔力の嵐%s", "invoke mana storms%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_BLUE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BA_DARK)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_DARK)) {
         set_damage(player_ptr, lore_ptr, (MS_BALL_DARK), _("暗黒の嵐%s", "invoke darkness storms%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_DARK;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BA_LITE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_LITE)) {
         set_damage(player_ptr, lore_ptr, (MS_STARBURST), _("スターバースト%s", "invoke starburst%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_YELLOW;
     }
 
-    if (lore_ptr->flags4 & (RF4_BA_CHAO)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BA_CHAO)) {
         set_damage(player_ptr, lore_ptr, (MS_BALL_CHAOS), _("純ログルス%s", "invoke raw Logrus%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_VIOLET;
@@ -221,54 +218,54 @@ void set_ball_types(player_type *player_ptr, lore_type *lore_ptr)
 
 void set_particular_types(player_type *player_ptr, lore_type *lore_ptr)
 {
-    if (lore_ptr->a_ability_flags2 & (RF6_HAND_DOOM)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::HAND_DOOM)) {
         lore_ptr->vp[lore_ptr->vn] = _("破滅の手(40%-60%)", "invoke the Hand of Doom(40%-60%)");
         lore_ptr->color[lore_ptr->vn++] = TERM_VIOLET;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_PSY_SPEAR)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::PSY_SPEAR)) {
         set_damage(player_ptr, lore_ptr, (MS_PSY_SPEAR), _("光の剣%s", "psycho-spear%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_YELLOW;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_DRAIN_MANA)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::DRAIN_MANA)) {
         set_damage(player_ptr, lore_ptr, (MS_DRAIN_MANA), _("魔力吸収%s", "drain mana%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_SLATE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_MIND_BLAST)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::MIND_BLAST)) {
         set_damage(player_ptr, lore_ptr, (MS_MIND_BLAST), _("精神攻撃%s", "cause mind blasting%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_RED;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BRAIN_SMASH)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BRAIN_SMASH)) {
         set_damage(player_ptr, lore_ptr, (MS_BRAIN_SMASH), _("脳攻撃%s", "cause brain smashing%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_RED;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_CAUSE_1)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::CAUSE_1)) {
         set_damage(player_ptr, lore_ptr, (MS_CAUSE_1), _("軽傷+呪い%s", "cause light wounds and cursing%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_WHITE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_CAUSE_2)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::CAUSE_2)) {
         set_damage(player_ptr, lore_ptr, (MS_CAUSE_2), _("重傷+呪い%s", "cause serious wounds and cursing%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_WHITE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_CAUSE_3)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::CAUSE_3)) {
         set_damage(player_ptr, lore_ptr, (MS_CAUSE_3), _("致命傷+呪い%s", "cause critical wounds and cursing%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_WHITE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_CAUSE_4)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::CAUSE_4)) {
         set_damage(player_ptr, lore_ptr, (MS_CAUSE_4), _("秘孔を突く%s", "cause mortal wounds%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_WHITE;
@@ -277,61 +274,61 @@ void set_particular_types(player_type *player_ptr, lore_type *lore_ptr)
 
 void set_bolt_types(player_type *player_ptr, lore_type *lore_ptr)
 {
-    if (lore_ptr->a_ability_flags1 & (RF5_BO_ACID)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BO_ACID)) {
         set_damage(player_ptr, lore_ptr, (MS_BOLT_ACID), _("アシッド・ボルト%s", "produce acid bolts%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_GREEN;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BO_ELEC)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BO_ELEC)) {
         set_damage(player_ptr, lore_ptr, (MS_BOLT_ELEC), _("サンダー・ボルト%s", "produce lightning bolts%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_BLUE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BO_FIRE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BO_FIRE)) {
         set_damage(player_ptr, lore_ptr, (MS_BOLT_FIRE), _("ファイア・ボルト%s", "produce fire bolts%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_RED;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BO_COLD)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BO_COLD)) {
         set_damage(player_ptr, lore_ptr, (MS_BOLT_COLD), _("アイス・ボルト%s", "produce frost bolts%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_WHITE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BO_NETH)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BO_NETH)) {
         set_damage(player_ptr, lore_ptr, (MS_BOLT_NETHER), _("地獄の矢%s", "produce nether bolts%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_DARK;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BO_WATE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BO_WATE)) {
         set_damage(player_ptr, lore_ptr, (MS_BOLT_WATER), _("ウォーター・ボルト%s", "produce water bolts%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_BLUE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BO_MANA)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BO_MANA)) {
         set_damage(player_ptr, lore_ptr, (MS_BOLT_MANA), _("魔力の矢%s", "produce mana bolts%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_BLUE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BO_PLAS)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BO_PLAS)) {
         set_damage(player_ptr, lore_ptr, (MS_BOLT_PLASMA), _("プラズマ・ボルト%s", "produce plasma bolts%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_L_RED;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BO_ICEE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BO_ICEE)) {
         set_damage(player_ptr, lore_ptr, (MS_BOLT_ICE), _("極寒の矢%s", "produce ice bolts%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_WHITE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_MISSILE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::MISSILE)) {
         set_damage(player_ptr, lore_ptr, (MS_MAGIC_MISSILE), _("マジックミサイル%s", "produce magic missiles%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_SLATE;
@@ -340,47 +337,47 @@ void set_bolt_types(player_type *player_ptr, lore_type *lore_ptr)
 
 void set_status_types(lore_type *lore_ptr)
 {
-    if (lore_ptr->a_ability_flags1 & (RF5_SCARE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::SCARE)) {
         lore_ptr->vp[lore_ptr->vn] = _("恐怖", "terrify");
         lore_ptr->color[lore_ptr->vn++] = TERM_SLATE;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_BLIND)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BLIND)) {
         lore_ptr->vp[lore_ptr->vn] = _("目くらまし", "blind");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_DARK;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_CONF)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::CONF)) {
         lore_ptr->vp[lore_ptr->vn] = _("混乱", "confuse");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_UMBER;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_SLOW)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::SLOW)) {
         lore_ptr->vp[lore_ptr->vn] = _("減速", "slow");
         lore_ptr->color[lore_ptr->vn++] = TERM_UMBER;
     }
 
-    if (lore_ptr->a_ability_flags1 & (RF5_HOLD)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::HOLD)) {
         lore_ptr->vp[lore_ptr->vn] = _("麻痺", "paralyze");
         lore_ptr->color[lore_ptr->vn++] = TERM_RED;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_HASTE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::HASTE)) {
         lore_ptr->vp[lore_ptr->vn] = _("加速", "haste-self");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_GREEN;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_HEAL)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::HEAL)) {
         lore_ptr->vp[lore_ptr->vn] = _("治癒", "heal-self");
         lore_ptr->color[lore_ptr->vn++] = TERM_WHITE;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_INVULNER)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::INVULNER)) {
         lore_ptr->vp[lore_ptr->vn] = _("無敵化", "make invulnerable");
         lore_ptr->color[lore_ptr->vn++] = TERM_WHITE;
     }
 
-    if (lore_ptr->flags4 & RF4_DISPEL) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::DISPEL)) {
         lore_ptr->vp[lore_ptr->vn] = _("魔力消去", "dispel-magic");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_WHITE;
     }
@@ -391,32 +388,32 @@ void set_status_types(lore_type *lore_ptr)
  */
 void set_teleport_types(lore_type *lore_ptr)
 {
-    if (lore_ptr->a_ability_flags2 & (RF6_BLINK)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::BLINK)) {
         lore_ptr->vp[lore_ptr->vn] = _("ショートテレポート", "blink-self");
         lore_ptr->color[lore_ptr->vn++] = TERM_UMBER;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_TPORT)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::TPORT)) {
         lore_ptr->vp[lore_ptr->vn] = _("テレポート", "teleport-self");
         lore_ptr->color[lore_ptr->vn++] = TERM_ORANGE;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_WORLD)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::WORLD)) {
         lore_ptr->vp[lore_ptr->vn] = _("時を止める", "stop time");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_BLUE;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_TELE_TO)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::TELE_TO)) {
         lore_ptr->vp[lore_ptr->vn] = _("テレポートバック", "teleport to");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_UMBER;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_TELE_AWAY)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::TELE_AWAY)) {
         lore_ptr->vp[lore_ptr->vn] = _("テレポートアウェイ", "teleport away");
         lore_ptr->color[lore_ptr->vn++] = TERM_UMBER;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_TELE_LEVEL)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::TELE_LEVEL)) {
         lore_ptr->vp[lore_ptr->vn] = _("テレポート・レベル", "teleport level");
         lore_ptr->color[lore_ptr->vn++] = TERM_ORANGE;
     }
@@ -424,7 +421,7 @@ void set_teleport_types(lore_type *lore_ptr)
 
 void set_floor_types(player_type *player_ptr, lore_type *lore_ptr)
 {
-    if (lore_ptr->a_ability_flags2 & (RF6_DARKNESS)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::DARKNESS)) {
         if ((player_ptr->pclass != CLASS_NINJA) || (lore_ptr->r_ptr->flags3 & (RF3_UNDEAD | RF3_HURT_LITE)) || (lore_ptr->r_ptr->flags7 & RF7_DARK_MASK)) {
             lore_ptr->vp[lore_ptr->vn] = _("暗闇", "create darkness");
             lore_ptr->color[lore_ptr->vn++] = TERM_L_DARK;
@@ -434,17 +431,17 @@ void set_floor_types(player_type *player_ptr, lore_type *lore_ptr)
         }
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_TRAPS)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::TRAPS)) {
         lore_ptr->vp[lore_ptr->vn] = _("トラップ", "create traps");
         lore_ptr->color[lore_ptr->vn++] = TERM_BLUE;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_FORGET)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::FORGET)) {
         lore_ptr->vp[lore_ptr->vn] = _("記憶消去", "cause amnesia");
         lore_ptr->color[lore_ptr->vn++] = TERM_BLUE;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_RAISE_DEAD)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::RAISE_DEAD)) {
         lore_ptr->vp[lore_ptr->vn] = _("死者復活", "raise dead");
         lore_ptr->color[lore_ptr->vn++] = TERM_RED;
     }
@@ -452,83 +449,83 @@ void set_floor_types(player_type *player_ptr, lore_type *lore_ptr)
 
 void set_summon_types(lore_type *lore_ptr)
 {
-    if (lore_ptr->a_ability_flags2 & (RF6_S_MONSTER)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_MONSTER)) {
         lore_ptr->vp[lore_ptr->vn] = _("モンスター一体召喚", "summon a monster");
         lore_ptr->color[lore_ptr->vn++] = TERM_SLATE;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_MONSTERS)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_MONSTERS)) {
         lore_ptr->vp[lore_ptr->vn] = _("モンスター複数召喚", "summon monsters");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_WHITE;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_KIN)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_KIN)) {
         lore_ptr->vp[lore_ptr->vn] = _("救援召喚", "summon aid");
         lore_ptr->color[lore_ptr->vn++] = TERM_ORANGE;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_ANT)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_ANT)) {
         lore_ptr->vp[lore_ptr->vn] = _("アリ召喚", "summon ants");
         lore_ptr->color[lore_ptr->vn++] = TERM_RED;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_SPIDER)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_SPIDER)) {
         lore_ptr->vp[lore_ptr->vn] = _("クモ召喚", "summon spiders");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_DARK;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_HOUND)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_HOUND)) {
         lore_ptr->vp[lore_ptr->vn] = _("ハウンド召喚", "summon hounds");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_UMBER;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_HYDRA)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_HYDRA)) {
         lore_ptr->vp[lore_ptr->vn] = _("ヒドラ召喚", "summon hydras");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_GREEN;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_ANGEL)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_ANGEL)) {
         lore_ptr->vp[lore_ptr->vn] = _("天使一体召喚", "summon an angel");
         lore_ptr->color[lore_ptr->vn++] = TERM_YELLOW;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_DEMON)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_DEMON)) {
         lore_ptr->vp[lore_ptr->vn] = _("デーモン一体召喚", "summon a demon");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_RED;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_UNDEAD)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_UNDEAD)) {
         lore_ptr->vp[lore_ptr->vn] = _("アンデッド一体召喚", "summon an undead");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_DARK;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_DRAGON)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_DRAGON)) {
         lore_ptr->vp[lore_ptr->vn] = _("ドラゴン一体召喚", "summon a dragon");
         lore_ptr->color[lore_ptr->vn++] = TERM_ORANGE;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_HI_UNDEAD)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_HI_UNDEAD)) {
         lore_ptr->vp[lore_ptr->vn] = _("強力なアンデッド召喚", "summon Greater Undead");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_DARK;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_HI_DRAGON)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_HI_DRAGON)) {
         lore_ptr->vp[lore_ptr->vn] = _("古代ドラゴン召喚", "summon Ancient Dragons");
         lore_ptr->color[lore_ptr->vn++] = TERM_ORANGE;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_CYBER)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_CYBER)) {
         lore_ptr->vp[lore_ptr->vn] = _("サイバーデーモン召喚", "summon Cyberdemons");
         lore_ptr->color[lore_ptr->vn++] = TERM_UMBER;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_AMBERITES)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_AMBERITES)) {
         lore_ptr->vp[lore_ptr->vn] = _("アンバーの王族召喚", "summon Lords of Amber");
         lore_ptr->color[lore_ptr->vn++] = TERM_VIOLET;
     }
 
-    if (lore_ptr->a_ability_flags2 & (RF6_S_UNIQUE)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::S_UNIQUE)) {
         lore_ptr->vp[lore_ptr->vn] = _("ユニーク・モンスター召喚", "summon Unique Monsters");
         lore_ptr->color[lore_ptr->vn++] = TERM_VIOLET;
     }
-}
\ No newline at end of file
+}
index 9350e7b..f1829fe 100644 (file)
 #include "lore/lore-util.h"
 #include "lore/magic-types-setter.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability2.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-indice-types.h"
 #include "term/term-color-types.h"
 #include "view/display-lore-attacks.h"
@@ -163,13 +161,13 @@ void process_monster_lore(player_type *player_ptr, MONRACE_IDX r_idx, monster_lo
 
     display_monster_collective(lore_ptr);
     lore_ptr->vn = 0;
-    if (lore_ptr->flags4 & RF4_SHRIEK) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::SHRIEK)) {
         lore_ptr->vp[lore_ptr->vn] = _("悲鳴で助けを求める", "shriek for help");
         lore_ptr->color[lore_ptr->vn++] = TERM_L_WHITE;
     }
 
     display_monster_launching(player_ptr, lore_ptr);
-    if (lore_ptr->a_ability_flags2 & (RF6_SPECIAL)) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::SPECIAL)) {
         lore_ptr->vp[lore_ptr->vn] = _("特別な行動をする", "do something");
         lore_ptr->color[lore_ptr->vn++] = TERM_VIOLET;
     }
index 0bb31b2..5044772 100644 (file)
  * </p>
  *
  * <p>
- * Special "Windows Help Files" can be placed into "lib/xtra/help/" for
- * use with the "winhelp.exe" program.  These files *may* be available
- * at the ftp site somewhere, but I have not seen them.
- * </p>
- *
- * <p>
  * Initial framework (and most code) by Ben Harrison (benh@phial.com).
  *
  * Original code by Skirmantas Kligys (kligys@scf.usc.edu).
@@ -91,8 +85,6 @@
 
 #ifdef WINDOWS
 
-#include <cstdlib>
-
 #include "autopick/autopick-pref-processor.h"
 #include "cmd-io/cmd-process-screen.h"
 #include "cmd-io/cmd-save.h"
 #include "main-win/main-win-bg.h"
 #include "main-win/main-win-file-utils.h"
 #include "main-win/main-win-mci.h"
+#include "main-win/main-win-menuitem.h"
 #include "main-win/main-win-music.h"
 #include "main-win/main-win-sound.h"
 #include "main/angband-initializer.h"
 #include "wizard/wizard-spoiler.h"
 #include "world/world.h"
 
+#include <cstdlib>
+#include <locale>
+
 #include <commdlg.h>
 #include <direct.h>
-#include <locale.h>
 
 /*
  * Include the support for loading bitmaps
  */
 #include "term/readdib.h"
 
-#define MOUSE_SENS 40
-
 /*
  * Available graphic modes
  */
 #define GRAPHICS_HENGBAND 3
 
 /*
- * Menu constants -- see "ANGBAND.RC"
- */
-#define IDM_FILE_NEW 100
-#define IDM_FILE_OPEN 101
-#define IDM_FILE_SAVE 110
-#define IDM_FILE_SCORE 120
-#define IDM_FILE_MOVIE 121
-#define IDM_FILE_EXIT 130
-
-#define IDM_WINDOW_VIS_0 200
-#define IDM_WINDOW_VIS_1 201
-#define IDM_WINDOW_VIS_2 202
-#define IDM_WINDOW_VIS_3 203
-#define IDM_WINDOW_VIS_4 204
-#define IDM_WINDOW_VIS_5 205
-#define IDM_WINDOW_VIS_6 206
-#define IDM_WINDOW_VIS_7 207
-
-#define IDM_WINDOW_FONT_0 210
-#define IDM_WINDOW_FONT_1 211
-#define IDM_WINDOW_FONT_2 212
-#define IDM_WINDOW_FONT_3 213
-#define IDM_WINDOW_FONT_4 214
-#define IDM_WINDOW_FONT_5 215
-#define IDM_WINDOW_FONT_6 216
-#define IDM_WINDOW_FONT_7 217
-
-#define IDM_WINDOW_POS_0 220
-#define IDM_WINDOW_POS_1 221
-#define IDM_WINDOW_POS_2 222
-#define IDM_WINDOW_POS_3 223
-#define IDM_WINDOW_POS_4 224
-#define IDM_WINDOW_POS_5 225
-#define IDM_WINDOW_POS_6 226
-#define IDM_WINDOW_POS_7 227
-
-#define IDM_WINDOW_BIZ_0 230
-#define IDM_WINDOW_BIZ_1 231
-#define IDM_WINDOW_BIZ_2 232
-#define IDM_WINDOW_BIZ_3 233
-#define IDM_WINDOW_BIZ_4 234
-#define IDM_WINDOW_BIZ_5 235
-#define IDM_WINDOW_BIZ_6 236
-#define IDM_WINDOW_BIZ_7 237
-
-#define IDM_WINDOW_I_WID_0 240
-#define IDM_WINDOW_I_WID_1 241
-#define IDM_WINDOW_I_WID_2 242
-#define IDM_WINDOW_I_WID_3 243
-#define IDM_WINDOW_I_WID_4 244
-#define IDM_WINDOW_I_WID_5 245
-#define IDM_WINDOW_I_WID_6 246
-#define IDM_WINDOW_I_WID_7 247
-
-#define IDM_WINDOW_D_WID_0 250
-#define IDM_WINDOW_D_WID_1 251
-#define IDM_WINDOW_D_WID_2 252
-#define IDM_WINDOW_D_WID_3 253
-#define IDM_WINDOW_D_WID_4 254
-#define IDM_WINDOW_D_WID_5 255
-#define IDM_WINDOW_D_WID_6 256
-#define IDM_WINDOW_D_WID_7 257
-
-#define IDM_WINDOW_I_HGT_0 260
-#define IDM_WINDOW_I_HGT_1 261
-#define IDM_WINDOW_I_HGT_2 262
-#define IDM_WINDOW_I_HGT_3 263
-#define IDM_WINDOW_I_HGT_4 264
-#define IDM_WINDOW_I_HGT_5 265
-#define IDM_WINDOW_I_HGT_6 266
-#define IDM_WINDOW_I_HGT_7 267
-
-#define IDM_WINDOW_D_HGT_0 270
-#define IDM_WINDOW_D_HGT_1 271
-#define IDM_WINDOW_D_HGT_2 272
-#define IDM_WINDOW_D_HGT_3 273
-#define IDM_WINDOW_D_HGT_4 274
-#define IDM_WINDOW_D_HGT_5 275
-#define IDM_WINDOW_D_HGT_6 276
-#define IDM_WINDOW_D_HGT_7 277
-
-#define IDM_WINDOW_KEEP_SUBWINDOWS 280
-
-#define IDM_OPTIONS_NO_GRAPHICS 400
-#define IDM_OPTIONS_OLD_GRAPHICS 401
-#define IDM_OPTIONS_NEW_GRAPHICS 402
-#define IDM_OPTIONS_NEW2_GRAPHICS 403
-#define IDM_OPTIONS_BIGTILE 409
-#define IDM_OPTIONS_SOUND 410
-#define IDM_OPTIONS_MUSIC 411
-#define IDM_OPTIONS_SAVER 420
-#define IDM_OPTIONS_MAP 430
-#define IDM_OPTIONS_BG 440
-#define IDM_OPTIONS_OPEN_BG 441
-
-#define IDM_DUMP_SCREEN_HTML 450
-
-#define IDM_HELP_CONTENTS 901
-
-/*
  * Foreground color bits
  */
 #define VID_BLACK 0x00
@@ -325,10 +218,6 @@ typedef struct {
     int tile_wid; //!< タイル横幅
     int tile_hgt; //!< タイル縦幅
 
-    uint map_tile_wid;
-    uint map_tile_hgt;
-
-    bool map_active;
     LOGFONT lf;
 
     bool posfix;
@@ -389,11 +278,6 @@ static HPALETTE hPal;
 static int use_bg = 0; //!< 背景使用フラグ、1なら使用。
 #define DEFAULT_BG_FILENAME "bg.bmp"
 
-/*
- * The screen saver window
- */
-static HWND hwndSaver;
-
 /*!
  * 現在使用中のタイルID(0ならば未使用)
  * Flag set once "graphics" has been initialized
@@ -434,7 +318,6 @@ static concptr AngList = "AngList";
  * Directory names
  */
 static concptr ANGBAND_DIR_XTRA_GRAF;
-static concptr ANGBAND_DIR_XTRA_HELP;
 
 /*
  * The "complex" color values
@@ -1065,18 +948,11 @@ static void term_window_pos(term_data *td, HWND hWnd)
     SetWindowPos(td->w, hWnd, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
 }
 
-static void windows_map(player_type *player_ptr);
-
 /*
  * Hack -- redraw a term_data
  */
-static void term_data_redraw(player_type *player_ptr, term_data *td)
+static void term_data_redraw(term_data *td)
 {
-    if (td->map_active) {
-        windows_map(player_ptr);
-        return;
-    }
-
     term_activate(&td->t);
     term_redraw();
     term_activate(term_screen);
@@ -1275,14 +1151,14 @@ static errr term_xtra_win_music(int n, int v)
 /*
  * Hack -- play a music matches a situation
  */
-static errr term_xtra_win_scene()
+static errr term_xtra_win_scene(int v)
 {
     // TODO 場面に合った壁紙変更対応
     if (!use_music) {
         return 1;
     }
 
-    return main_win_music::play_music_scene();
+    return main_win_music::play_music_scene(v);
 }
 
 /*
@@ -1307,14 +1183,15 @@ static errr term_xtra_win(int n, int v)
     case TERM_XTRA_MUSIC_BASIC:
     case TERM_XTRA_MUSIC_DUNGEON:
     case TERM_XTRA_MUSIC_QUEST:
-    case TERM_XTRA_MUSIC_TOWN: {
+    case TERM_XTRA_MUSIC_TOWN:
+    case TERM_XTRA_MUSIC_MONSTER: {
         return term_xtra_win_music(n, v);
     }
     case TERM_XTRA_MUSIC_MUTE: {
         return main_win_music::stop_music();
     }
     case TERM_XTRA_SCENE: {
-        return term_xtra_win_scene();
+        return term_xtra_win_scene(v);
     }
     case TERM_XTRA_SOUND: {
         return (term_xtra_win_sound(v));
@@ -1351,13 +1228,8 @@ static errr term_curs_win(int x, int y)
 {
     term_data *td = (term_data *)(Term->data);
     int tile_wid, tile_hgt;
-    if (td->map_active) {
-        tile_wid = td->map_tile_wid;
-        tile_hgt = td->map_tile_hgt;
-    } else {
-        tile_wid = td->tile_wid;
-        tile_hgt = td->tile_hgt;
-    }
+    tile_wid = td->tile_wid;
+    tile_hgt = td->tile_hgt;
 
     RECT rc;
     rc.left = x * tile_wid + td->size_ow1;
@@ -1380,13 +1252,8 @@ static errr term_bigcurs_win(int x, int y)
 {
     term_data *td = (term_data *)(Term->data);
     int tile_wid, tile_hgt;
-    if (td->map_active) {
-        term_curs_win(x, y);
-        return 0;
-    } else {
-        tile_wid = td->tile_wid;
-        tile_hgt = td->tile_hgt;
-    }
+    tile_wid = td->tile_wid;
+    tile_hgt = td->tile_hgt;
 
     RECT rc;
     rc.left = x * tile_wid + td->size_ow1;
@@ -1566,16 +1433,11 @@ static errr term_pict_win(TERM_LEN x, TERM_LEN y, int n, const TERM_COLOR *ap, c
     TERM_LEN tw1 = infGraph.TileWidth;
     TERM_LEN th1 = infGraph.TileHeight;
     TERM_LEN w2, h2, tw2 = 0;
-    if (td->map_active) {
-        w2 = td->map_tile_wid;
-        h2 = td->map_tile_hgt;
-    } else {
-        w2 = td->tile_wid;
-        h2 = td->tile_hgt;
-        tw2 = w2;
-        if (use_bigtile)
-            tw2 *= 2;
-    }
+    w2 = td->tile_wid;
+    h2 = td->tile_hgt;
+    tw2 = w2;
+    if (use_bigtile)
+        tw2 *= 2;
 
     TERM_LEN x2 = x * w2 + td->size_ow1 + infGraph.OffsetX;
     TERM_LEN y2 = y * h2 + td->size_oh1 + infGraph.OffsetY;
@@ -1639,43 +1501,6 @@ static errr term_pict_win(TERM_LEN x, TERM_LEN y, int n, const TERM_COLOR *ap, c
     return 0;
 }
 
-static void windows_map(player_type *player_ptr)
-{
-    term_data *td = &data[0];
-    TERM_COLOR ta;
-    if (!use_graphics)
-        return;
-
-    term_xtra_win_clear();
-    td->map_tile_wid = (td->tile_wid * td->cols) / MAX_WID;
-    td->map_tile_hgt = (td->tile_hgt * td->rows) / MAX_HGT;
-    td->map_active = TRUE;
-
-    TERM_LEN min_x = 0;
-    TERM_LEN min_y = 0;
-    TERM_LEN max_x = player_ptr->current_floor_ptr->width;
-    TERM_LEN max_y = player_ptr->current_floor_ptr->height;
-
-    char c;
-    for (TERM_LEN x = min_x; x < max_x; x++) {
-        for (TERM_LEN y = min_y; y < max_y; y++) {
-            TERM_COLOR a;
-            char tc;
-            map_info(player_ptr, y, x, &a, (char *)&c, &ta, (char *)&tc);
-            if ((a & 0x80) && (c & 0x80)) {
-                term_pict_win(x - min_x, y - min_y, 1, &a, &c, &ta, &tc);
-            }
-        }
-    }
-
-    term_curs_win(player_ptr->x - min_x, player_ptr->y - min_y);
-    term_inkey(&c, TRUE, TRUE);
-    term_flush();
-    td->map_active = FALSE;
-    term_xtra_win_clear();
-    term_redraw();
-}
-
 /*
  * Create and initialize a "term_data" given a title
  */
@@ -1851,23 +1676,19 @@ static void init_windows(void)
 static void setup_menus(void)
 {
     HMENU hm = GetMenu(data[0].w);
-    EnableMenuItem(hm, IDM_FILE_NEW, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
-    EnableMenuItem(hm, IDM_FILE_OPEN, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
-    EnableMenuItem(hm, IDM_FILE_SAVE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
-    EnableMenuItem(hm, IDM_FILE_EXIT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
-    EnableMenuItem(hm, IDM_FILE_SCORE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
-
-    if (!current_world_ptr->character_generated) {
-        EnableMenuItem(hm, IDM_FILE_NEW, MF_BYCOMMAND | MF_ENABLED);
-        EnableMenuItem(hm, IDM_FILE_OPEN, MF_BYCOMMAND | MF_ENABLED);
-    }
 
     if (current_world_ptr->character_generated) {
+        EnableMenuItem(hm, IDM_FILE_NEW, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+        EnableMenuItem(hm, IDM_FILE_OPEN, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
         EnableMenuItem(hm, IDM_FILE_SAVE, MF_BYCOMMAND | MF_ENABLED);
+    } else {
+        EnableMenuItem(hm, IDM_FILE_NEW, MF_BYCOMMAND | MF_ENABLED);
+        EnableMenuItem(hm, IDM_FILE_OPEN, MF_BYCOMMAND | MF_ENABLED);
+        EnableMenuItem(hm, IDM_FILE_SAVE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
     }
 
-    EnableMenuItem(hm, IDM_FILE_EXIT, MF_BYCOMMAND | MF_ENABLED);
     EnableMenuItem(hm, IDM_FILE_SCORE, MF_BYCOMMAND | MF_ENABLED);
+    EnableMenuItem(hm, IDM_FILE_EXIT, MF_BYCOMMAND | MF_ENABLED);
 
     for (int i = 0; i < MAX_TERM_DATA; i++) {
         EnableMenuItem(hm, IDM_WINDOW_VIS_0 + i, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
@@ -1935,15 +1756,6 @@ static void setup_menus(void)
     EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
     EnableMenuItem(hm, IDM_OPTIONS_BIGTILE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
     EnableMenuItem(hm, IDM_OPTIONS_SOUND, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
-#ifdef JP
-#else
-    EnableMenuItem(hm, IDM_OPTIONS_SAVER, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
-#endif
-
-    if (use_graphics != GRAPHICS_NONE)
-        EnableMenuItem(GetMenu(data[0].w), IDM_OPTIONS_MAP, MF_BYCOMMAND | MF_ENABLED);
-    else
-        EnableMenuItem(GetMenu(data[0].w), IDM_OPTIONS_MAP, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
 
     CheckMenuItem(hm, IDM_OPTIONS_NO_GRAPHICS, (arg_graphics == GRAPHICS_NONE ? MF_CHECKED : MF_UNCHECKED));
     CheckMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS, (arg_graphics == GRAPHICS_ORIGINAL ? MF_CHECKED : MF_UNCHECKED));
@@ -1953,16 +1765,12 @@ static void setup_menus(void)
     CheckMenuItem(hm, IDM_OPTIONS_MUSIC, (arg_music ? MF_CHECKED : MF_UNCHECKED));
     CheckMenuItem(hm, IDM_OPTIONS_SOUND, (arg_sound ? MF_CHECKED : MF_UNCHECKED));
     CheckMenuItem(hm, IDM_OPTIONS_BG, (use_bg ? MF_CHECKED : MF_UNCHECKED));
-#ifdef JP
-#else
-    CheckMenuItem(hm, IDM_OPTIONS_SAVER, (hwndSaver ? MF_CHECKED : MF_UNCHECKED));
-#endif
+
     EnableMenuItem(hm, IDM_OPTIONS_NO_GRAPHICS, MF_ENABLED);
     EnableMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS, MF_ENABLED);
     EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS, MF_ENABLED);
     EnableMenuItem(hm, IDM_OPTIONS_BIGTILE, MF_ENABLED);
     EnableMenuItem(hm, IDM_OPTIONS_SOUND, MF_ENABLED);
-    EnableMenuItem(hm, IDM_OPTIONS_SAVER, MF_BYCOMMAND | MF_ENABLED);
 }
 
 /*
@@ -2132,7 +1940,7 @@ static void process_menus(player_type *player_ptr, WORD wCmd)
         if (!td->visible) {
             td->visible = TRUE;
             ShowWindow(td->w, SW_SHOW);
-            term_data_redraw(player_ptr, td);
+            term_data_redraw(td);
         } else {
             td->visible = FALSE;
             td->posfix = FALSE;
@@ -2428,43 +2236,6 @@ static void process_menus(player_type *player_ptr, WORD wCmd)
 
         break;
     }
-    case IDM_OPTIONS_SAVER: {
-        if (hwndSaver) {
-            DestroyWindow(hwndSaver);
-            hwndSaver = NULL;
-            break;
-        }
-
-        hwndSaver = CreateWindowEx(WS_EX_TOPMOST, "WindowsScreenSaverClass", "Angband Screensaver", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE, 0, 0,
-            GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL);
-
-        if (hwndSaver) {
-            SetWindowPos(hwndSaver, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
-        } else {
-            plog(_("ウィンドウを作成出来ません", "Failed to create saver window"));
-        }
-
-        break;
-    }
-    case IDM_OPTIONS_MAP: {
-        windows_map(player_ptr);
-        break;
-    }
-
-    case IDM_HELP_CONTENTS: {
-        char buf[1024];
-        char tmp[1024];
-        path_build(tmp, sizeof(tmp), ANGBAND_DIR_XTRA_HELP, "zangband.hlp");
-        if (check_file(tmp)) {
-            sprintf(buf, "winhelp.exe %s", tmp);
-            WinExec(buf, SW_NORMAL);
-            break;
-        }
-
-        plog_fmt(_("ヘルプファイル[%s]が見付かりません。", "Cannot find help file: %s"), tmp);
-        plog(_("代わりにオンラインヘルプを使用してください。", "Use the online help files instead."));
-        break;
-    }
     }
 }
 
@@ -2609,7 +2380,7 @@ LRESULT PASCAL AngbandWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
     case WM_PAINT: {
         BeginPaint(hWnd, &ps);
         if (td)
-            term_data_redraw(p_ptr, td);
+            term_data_redraw(td);
         EndPaint(hWnd, &ps);
         ValidateRect(hWnd, NULL);
         return 0;
@@ -2956,7 +2727,7 @@ LRESULT PASCAL AngbandListProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
     case WM_PAINT: {
         BeginPaint(hWnd, &ps);
         if (td)
-            term_data_redraw(p_ptr, td);
+            term_data_redraw(td);
         EndPaint(hWnd, &ps);
         return 0;
     }
@@ -3012,60 +2783,6 @@ LRESULT PASCAL AngbandListProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
     return DefWindowProc(hWnd, uMsg, wParam, lParam);
 }
 
-LRESULT PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-    static int iMouse = 0;
-    static WORD xMouse = 0;
-    static WORD yMouse = 0;
-
-    switch (uMsg) {
-    case WM_NCCREATE: {
-        break;
-    }
-
-    case WM_SETCURSOR: {
-        SetCursor(NULL);
-        return 0;
-    }
-
-    case WM_LBUTTONDOWN:
-    case WM_MBUTTONDOWN:
-    case WM_RBUTTONDOWN:
-    case WM_KEYDOWN: {
-        SendMessage(hWnd, WM_CLOSE, 0, 0);
-        return 0;
-    }
-    case WM_MOUSEMOVE: {
-        if (iMouse) {
-            int dx = LOWORD(lParam) - xMouse;
-            int dy = HIWORD(lParam) - yMouse;
-
-            if (dx < 0)
-                dx = -dx;
-            if (dy < 0)
-                dy = -dy;
-
-            if ((dx > MOUSE_SENS) || (dy > MOUSE_SENS)) {
-                SendMessage(hWnd, WM_CLOSE, 0, 0);
-            }
-        }
-
-        iMouse = 1;
-        xMouse = LOWORD(lParam);
-        yMouse = HIWORD(lParam);
-
-        return 0;
-    }
-    case WM_CLOSE: {
-        DestroyWindow(hwndSaver);
-        hwndSaver = NULL;
-        return 0;
-    }
-    }
-
-    return DefWindowProc(hWnd, uMsg, wParam, lParam);
-}
-
 /*
  * Display warning message (see "z-util.c")
  */
@@ -3210,9 +2927,6 @@ static void init_stuff(void)
     path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "music");
     ANGBAND_DIR_XTRA_MUSIC = string_make(path);
     validate_dir(ANGBAND_DIR_XTRA_MUSIC, FALSE);
-
-    path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "help");
-    ANGBAND_DIR_XTRA_HELP = string_make(path);
 }
 
 /*!
@@ -3309,15 +3023,6 @@ int WINAPI WinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInst, _In_ LPST
 
         if (!RegisterClass(&wc))
             exit(2);
-
-        wc.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_DBLCLKS;
-        wc.lpfnWndProc = AngbandSaverProc;
-        wc.hCursor = NULL;
-        wc.lpszMenuName = NULL;
-        wc.lpszClassName = "WindowsScreenSaverClass";
-
-        if (!RegisterClass(&wc))
-            exit(3);
     }
 
     plog_aux = hack_plog;
index 6a508c6..00fa76c 100644 (file)
@@ -61,6 +61,12 @@ concptr CfgData::get_rand(int key1_type, int key2_val)
     return filenames->at(Rand_external(filenames->size()));
 }
 
+bool CfgData::has_key(int key1_type, int key2_val)
+{
+    auto ite = map->find(make_cfg_key(key1_type, key2_val));
+    return (ite != map->end());
+}
+
 void CfgData::insert(int key1_type, int key2_val, cfg_values *value)
 {
     this->map->insert(std::make_pair(make_cfg_key(key1_type, key2_val), value));
@@ -96,6 +102,7 @@ CfgData *CfgReader::read_sections(std::initializer_list<cfg_section> sections)
 
     for (auto &section : sections) {
     
+        bool has_data = false;
         int index = 0;
         concptr read_key;
         while ((read_key = section.key_at(index, key_buf)) != NULL) {
@@ -112,11 +119,16 @@ CfgData *CfgReader::read_sections(std::initializer_list<cfg_section> sections)
                     delete filenames;
                 } else {
                     result->insert(section.action_type, index, filenames);
+                    has_data = true;
                 }
             }
 
             index++;
         }
+
+        if (section.has_data) {
+            *(section.has_data) = has_data;
+        }
     }
 
     return result;
index 5957b39..d23f3de 100644 (file)
@@ -32,6 +32,8 @@ struct cfg_section {
      * *action-val : the 2nd parameter of "term_xtra()"
      */
     key_name_func key_at;
+    //! 1つでもデータを読み込めた場合にtrueを設定する。(NULLの場合を除く)
+    bool *has_data = NULL;
 };
 
 class CfgData {
@@ -45,6 +47,7 @@ public:
         delete map;
     }
     concptr get_rand(int key1_type, int key2_val);
+    bool has_key(int key1_type, int key2_val);
     void insert(int key1_type, int key2_val, cfg_values *value);
 
 protected:
diff --git a/src/main-win/main-win-menuitem.h b/src/main-win/main-win-menuitem.h
new file mode 100644 (file)
index 0000000..6f68612
--- /dev/null
@@ -0,0 +1,97 @@
+#pragma once
+
+/*
+ * Menu constants -- see "ang_jp.rc", "ang_eng.rc"
+ */
+#define IDM_FILE_NEW 100
+#define IDM_FILE_OPEN 101
+#define IDM_FILE_SAVE 110
+#define IDM_FILE_SCORE 120
+#define IDM_FILE_MOVIE 121
+#define IDM_FILE_EXIT 130
+
+#define IDM_WINDOW_VIS_0 200
+#define IDM_WINDOW_VIS_1 201
+#define IDM_WINDOW_VIS_2 202
+#define IDM_WINDOW_VIS_3 203
+#define IDM_WINDOW_VIS_4 204
+#define IDM_WINDOW_VIS_5 205
+#define IDM_WINDOW_VIS_6 206
+#define IDM_WINDOW_VIS_7 207
+
+#define IDM_WINDOW_FONT_0 210
+#define IDM_WINDOW_FONT_1 211
+#define IDM_WINDOW_FONT_2 212
+#define IDM_WINDOW_FONT_3 213
+#define IDM_WINDOW_FONT_4 214
+#define IDM_WINDOW_FONT_5 215
+#define IDM_WINDOW_FONT_6 216
+#define IDM_WINDOW_FONT_7 217
+
+#define IDM_WINDOW_POS_0 220
+#define IDM_WINDOW_POS_1 221
+#define IDM_WINDOW_POS_2 222
+#define IDM_WINDOW_POS_3 223
+#define IDM_WINDOW_POS_4 224
+#define IDM_WINDOW_POS_5 225
+#define IDM_WINDOW_POS_6 226
+#define IDM_WINDOW_POS_7 227
+
+#define IDM_WINDOW_BIZ_0 230
+#define IDM_WINDOW_BIZ_1 231
+#define IDM_WINDOW_BIZ_2 232
+#define IDM_WINDOW_BIZ_3 233
+#define IDM_WINDOW_BIZ_4 234
+#define IDM_WINDOW_BIZ_5 235
+#define IDM_WINDOW_BIZ_6 236
+#define IDM_WINDOW_BIZ_7 237
+
+#define IDM_WINDOW_I_WID_0 240
+#define IDM_WINDOW_I_WID_1 241
+#define IDM_WINDOW_I_WID_2 242
+#define IDM_WINDOW_I_WID_3 243
+#define IDM_WINDOW_I_WID_4 244
+#define IDM_WINDOW_I_WID_5 245
+#define IDM_WINDOW_I_WID_6 246
+#define IDM_WINDOW_I_WID_7 247
+
+#define IDM_WINDOW_D_WID_0 250
+#define IDM_WINDOW_D_WID_1 251
+#define IDM_WINDOW_D_WID_2 252
+#define IDM_WINDOW_D_WID_3 253
+#define IDM_WINDOW_D_WID_4 254
+#define IDM_WINDOW_D_WID_5 255
+#define IDM_WINDOW_D_WID_6 256
+#define IDM_WINDOW_D_WID_7 257
+
+#define IDM_WINDOW_I_HGT_0 260
+#define IDM_WINDOW_I_HGT_1 261
+#define IDM_WINDOW_I_HGT_2 262
+#define IDM_WINDOW_I_HGT_3 263
+#define IDM_WINDOW_I_HGT_4 264
+#define IDM_WINDOW_I_HGT_5 265
+#define IDM_WINDOW_I_HGT_6 266
+#define IDM_WINDOW_I_HGT_7 267
+
+#define IDM_WINDOW_D_HGT_0 270
+#define IDM_WINDOW_D_HGT_1 271
+#define IDM_WINDOW_D_HGT_2 272
+#define IDM_WINDOW_D_HGT_3 273
+#define IDM_WINDOW_D_HGT_4 274
+#define IDM_WINDOW_D_HGT_5 275
+#define IDM_WINDOW_D_HGT_6 276
+#define IDM_WINDOW_D_HGT_7 277
+
+#define IDM_WINDOW_KEEP_SUBWINDOWS 280
+
+#define IDM_OPTIONS_NO_GRAPHICS 400
+#define IDM_OPTIONS_OLD_GRAPHICS 401
+#define IDM_OPTIONS_NEW_GRAPHICS 402
+#define IDM_OPTIONS_NEW2_GRAPHICS 403
+#define IDM_OPTIONS_BIGTILE 409
+#define IDM_OPTIONS_SOUND 410
+#define IDM_OPTIONS_MUSIC 411
+#define IDM_OPTIONS_BG 440
+#define IDM_OPTIONS_OPEN_BG 441
+
+#define IDM_DUMP_SCREEN_HTML 450
index 8ae3e8f..cde1c70 100644 (file)
@@ -12,6 +12,8 @@
 #include "main-win/main-win-mmsystem.h"
 #include "main-win/main-win-tokenizer.h"
 #include "main/scene-table.h"
+#include "main/sound-of-music.h"
+#include "monster-race/monster-race.h"
 #include "term/z-term.h"
 #include "util/angband-files.h"
 #include "world/world.h"
@@ -109,6 +111,26 @@ static concptr town_key_at(int index, char *buf)
     return buf;
 }
 
+static inline MONRACE_IDX get_monster_count()
+{
+    return max_r_idx;
+}
+
+/*!
+ * @brief action-valに対応する[Monster]セクションのキー名を取得する
+ * @param index "term_xtra()"の第2引数action-valに対応する値
+ * @param buf バッファ
+ * @return 対応するキー名を返す
+ */
+static concptr monster_key_at(int index, char *buf)
+{
+    if (index >= get_monster_count())
+        return NULL;
+
+    sprintf(buf, "monster%04d", index);
+    return buf;
+}
+
 /*!
  * @brief BGMの設定を読み込む。
  * @details
@@ -126,9 +148,20 @@ void load_music_prefs()
         { "Basic", TERM_XTRA_MUSIC_BASIC, basic_key_at },
         { "Dungeon", TERM_XTRA_MUSIC_DUNGEON, dungeon_key_at },
         { "Quest", TERM_XTRA_MUSIC_QUEST, quest_key_at },
-        { "Town", TERM_XTRA_MUSIC_TOWN, town_key_at }
+        { "Town", TERM_XTRA_MUSIC_TOWN, town_key_at },
+        { "Monster", TERM_XTRA_MUSIC_MONSTER, monster_key_at, &has_monster_music }
         });
     // clang-format on
+
+    if (!has_monster_music) {
+        int type = TERM_XTRA_MUSIC_BASIC;
+        for (int val = MUSIC_BASIC_UNIQUE; val <= MUSIC_BASIC_HIGHER_LEVEL_MONSTER; val++) {
+            if (music_cfg_data->has_key(type, val)) {
+                has_monster_music = true;
+                break;
+            }
+        }
+    }
 }
 
 /*
@@ -182,13 +215,15 @@ errr play_music(int type, int val)
 /*
  * Play a music matches a situation
  */
-errr play_music_scene()
+errr play_music_scene(int val)
 {
-    // ã\83\86ã\83¼ã\83\96ã\83«の先頭から順に再生を試み、再生できたら抜ける
-    auto ite = get_scene_table_iterator();
+    // ã\83ªã\82¹ã\83\88の先頭から順に再生を試み、再生できたら抜ける
+    auto list = get_scene_type_list(val);
     const errr err_sucsess = 0;
-    while (play_music(ite->type, ite->val) != err_sucsess) {
-        ++ite;
+    for (auto &item : list) {
+        if (play_music(item.type, item.val) == err_sucsess) {
+            break;
+        }
     }
 
     return 0;
index c37e3b6..e5f5509 100644 (file)
@@ -14,6 +14,6 @@ namespace main_win_music {
 void load_music_prefs();
 errr stop_music(void);
 errr play_music(int type, int val);
-errr play_music_scene();
+errr play_music_scene(int val);
 void on_mci_notify(WPARAM wFlags, LONG lDevID);
 }
index 2048a06..8e194ef 100644 (file)
@@ -66,7 +66,7 @@ static void init_header(angband_header *head, IDX num)
  * even if the string happens to be empty (everyone has a unique '\0').
  */
 template <typename InfoType>
-static errr init_info(concptr filename, angband_header& head, InfoType*& info, parse_info_txt_func parser, void(*retouch)(angband_header *head))
+static errr init_info(concptr filename, angband_header &head, std::vector<InfoType> &info, parse_info_txt_func parser, void (*retouch)(angband_header *head))
 {
     char buf[1024];
     path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, format("%s.txt", filename));
@@ -76,7 +76,7 @@ static errr init_info(concptr filename, angband_header& head, InfoType*& info, p
     if (!fp)
         quit(format(_("'%s.txt'ファイルをオープンできません。", "Cannot open '%s.txt' file."), filename));
 
-    C_MAKE(info, head.info_num, InfoType);
+    info = std::vector<InfoType>(head.info_num);
 
     errr err = init_info_txt(fp, buf, &head, parser);
     angband_fclose(fp);
index 0767cb9..544eb09 100644 (file)
@@ -24,4 +24,8 @@ const concptr angband_music_basic_name[MUSIC_BASIC_MAX] =
        "quest_clear",
        "final_quest_clear",
        "ambush",
+    "unique",
+    "shadower",
+    "unk_monster",
+    "hl_monster",
 };
index badaca0..65430e1 100644 (file)
@@ -22,7 +22,11 @@ enum music_type {
     MUSIC_BASIC_QUEST_CLEAR = 18,
     MUSIC_BASIC_FINAL_QUEST_CLEAR = 19,
     MUSIC_BASIC_AMBUSH = 20,
-    MUSIC_BASIC_MAX = 21, /*!< BGM定義の最大数 */
+    MUSIC_BASIC_UNIQUE = 21,
+    MUSIC_BASIC_SHADOWER = 22,
+    MUSIC_BASIC_UNKNOWN_MONSTER = 23,
+    MUSIC_BASIC_HIGHER_LEVEL_MONSTER = 24,
+    MUSIC_BASIC_MAX = 25, /*!< BGM定義の最大数 */
 };
 
 extern const concptr angband_music_basic_name[MUSIC_BASIC_MAX];
diff --git a/src/main/scene-table-floor.cpp b/src/main/scene-table-floor.cpp
new file mode 100644 (file)
index 0000000..eee38e7
--- /dev/null
@@ -0,0 +1,195 @@
+#include "main/scene-table-floor.h"
+#include "dungeon/quest.h"
+#include "main/music-definitions-table.h"
+#include "system/floor-type-definition.h"
+
+using scene_feel_func = bool (*)(player_type *player_ptr, scene_type *value);
+
+static bool scene_basic(player_type *player_ptr, scene_type *value)
+{
+    if (player_ptr->ambush_flag) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+        value->val = MUSIC_BASIC_AMBUSH;
+        return true;
+    }
+
+    if (player_ptr->wild_mode) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+        value->val = MUSIC_BASIC_WILD;
+        return true;
+    }
+
+    if (player_ptr->current_floor_ptr->inside_arena) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+        value->val = MUSIC_BASIC_ARENA;
+        return true;
+    }
+
+    if (player_ptr->phase_out) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+        value->val = MUSIC_BASIC_BATTLE;
+        return true;
+    }
+
+    return false;
+}
+
+static bool scene_quest(player_type *player_ptr, scene_type *value)
+{
+    const QUEST_IDX quest_id = quest_number(player_ptr, player_ptr->current_floor_ptr->dun_level);
+    const bool enable = (quest_id > 0);
+    if (enable) {
+        value->type = TERM_XTRA_MUSIC_QUEST;
+        value->val = quest_id;
+    }
+
+    return enable;
+}
+
+static bool scene_quest_basic(player_type *player_ptr, scene_type *value)
+{
+    const QUEST_IDX quest_id = quest_number(player_ptr, player_ptr->current_floor_ptr->dun_level);
+    const bool enable = (quest_id > 0);
+    if (enable) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+        value->val = MUSIC_BASIC_QUEST;
+    }
+
+    return enable;
+}
+
+static bool scene_town(player_type *player_ptr, scene_type *value)
+{
+    const bool enable = !is_in_dungeon(player_ptr) && (player_ptr->town_num > 0);
+    if (enable) {
+        value->type = TERM_XTRA_MUSIC_TOWN;
+        value->val = player_ptr->town_num;
+    }
+    return enable;
+}
+
+static bool scene_town_basic(player_type *player_ptr, scene_type *value)
+{
+    const bool enable = !is_in_dungeon(player_ptr) && (player_ptr->town_num > 0);
+    if (enable) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+        value->val = MUSIC_BASIC_TOWN;
+    }
+    return enable;
+}
+
+static bool scene_field(player_type *player_ptr, scene_type *value)
+{
+    const bool enable = !is_in_dungeon(player_ptr);
+    if (enable) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+
+        if (player_ptr->lev >= 45)
+            value->val = MUSIC_BASIC_FIELD3;
+        else if (player_ptr->lev >= 25)
+            value->val = MUSIC_BASIC_FIELD2;
+        else
+            value->val = MUSIC_BASIC_FIELD1;
+    }
+    return enable;
+}
+
+static bool scene_dungeon_feeling(player_type *player_ptr, scene_type *value)
+{
+    const bool enable = (player_ptr->feeling >= 2) && (player_ptr->feeling <= 5);
+    if (enable) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+
+        if (player_ptr->feeling == 2)
+            value->val = MUSIC_BASIC_DUN_FEEL2;
+        else
+            value->val = MUSIC_BASIC_DUN_FEEL1;
+    }
+    return enable;
+}
+
+static bool scene_dungeon(player_type *player_ptr, scene_type *value)
+{
+    const bool enable = (player_ptr->dungeon_idx > 0);
+    if (enable) {
+        value->type = TERM_XTRA_MUSIC_DUNGEON;
+        value->val = player_ptr->dungeon_idx;
+    }
+    return enable;
+}
+
+static bool scene_dungeon_basic(player_type *player_ptr, scene_type *value)
+{
+    const bool enable = is_in_dungeon(player_ptr);
+    if (enable) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+
+        const auto dun_level = player_ptr->current_floor_ptr->dun_level;
+        if (dun_level >= 80)
+            value->val = MUSIC_BASIC_DUN_HIGH;
+        else if (dun_level >= 40)
+            value->val = MUSIC_BASIC_DUN_MED;
+        else
+            value->val = MUSIC_BASIC_DUN_LOW;
+    }
+    return enable;
+}
+
+static bool scene_mute(player_type *player_ptr, scene_type *value)
+{
+    (void)player_ptr;
+    value->type = TERM_XTRA_MUSIC_MUTE;
+    value->val = 0;
+    return true;
+}
+
+/*! シチュエーション選択のフォールバック設定。
+ * 先頭から適用する(先にある方を優先する)。
+ */
+std::vector<scene_feel_func> scene_floor_def_list = {
+    // scene_basic : ambush, wild, arena, battleの判定
+    scene_basic,
+    // scene_quest : questの判定(クエストの個別BGMを指定)
+    scene_quest,
+    // scene_quest_basic : questの判定 (Basicのquest指定)
+    scene_quest_basic,
+    // scene_town : townの判定(町の個別BGMを指定)
+    scene_town,
+    // scene_town_basic : townの判定 (Basicのtown指定)
+    scene_town_basic,
+    // scene_field : field1/2/3の判定(プレイヤーレベル25未満、25以上45未満、45以上時の荒野)
+    scene_field,
+    // scene_dungeon_feeling : feed1/2の判定(ダンジョンの雰囲気が「悪い予感」~「とても危険」、「死の幻」)
+    scene_dungeon_feeling,
+    // scene_dungeon : dungeonの判定(ダンジョンの個別BGMを指定)
+    scene_dungeon,
+    // scene_dungeon_basic : dun_low/med/highの判定(ダンジョンレベルが40未満、40以上80未満、80以上)
+    scene_dungeon_basic,
+    // scene_mute : 最後にミュートを配置する
+    scene_mute
+};
+
+int get_scene_floor_count()
+{
+    return scene_floor_def_list.size();
+}
+
+/*!
+ * @brief 現在の条件でフロアのBGM選曲をリストに設定する。
+ * @details リストのfrom_indexの位置から、get_scene_floor_count()で得られる個数分設定する。
+ * @param player_ptr プレーヤーへの参照ポインタ
+ * @param list BGM選曲リスト
+ * @param from_index リストの更新開始位置
+ */
+void refresh_scene_floor(player_type *player_ptr, scene_type_list &list, int from_index)
+{
+    for (auto func : scene_floor_def_list) {
+        scene_type &item = list[from_index];
+        if (!func(player_ptr, &item)) {
+            // Note -- 特に定義を設けていないが、type = 0は無効な値とする。
+            item.type = 0;
+            item.val = 0;
+        }
+        ++from_index;
+    }
+}
diff --git a/src/main/scene-table-floor.h b/src/main/scene-table-floor.h
new file mode 100644 (file)
index 0000000..efceaf6
--- /dev/null
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "main/scene-table.h"
+#include "system/angband.h"
+
+int get_scene_floor_count();
+void refresh_scene_floor(player_type *player_ptr, scene_type_list &list, int start_index);
diff --git a/src/main/scene-table-monster.cpp b/src/main/scene-table-monster.cpp
new file mode 100644 (file)
index 0000000..7499f0e
--- /dev/null
@@ -0,0 +1,271 @@
+#include "main/scene-table-monster.h"
+#include "dungeon/quest.h"
+#include "main/music-definitions-table.h"
+#include "monster-race/monster-race.h"
+#include "monster-race/race-flags1.h"
+#include "system/floor-type-definition.h"
+#include "util/bit-flags-calculator.h"
+#include "world/world.h"
+
+struct scene_monster_info {
+    MONSTER_IDX m_idx;
+    monster_race *ap_r_ptr;
+    GAME_TURN last_seen; //!< 最後に対象モンスター見たゲームターン
+    u32b mute_until; //!< この時間に到達するまでモンスターBGMは設定しない
+};
+
+scene_monster_info scene_target_monster;
+
+inline static bool has_shadower_flag(monster_type *m_ptr)
+{
+    return m_ptr->mflag2.has(MFLAG2::KAGE);
+}
+
+inline static bool is_unique(monster_race *ap_r_ptr)
+{
+    return any_bits(ap_r_ptr->flags1, RF1_UNIQUE);
+}
+
+inline static bool is_unknown_monster(monster_race *ap_r_ptr)
+{
+    return (ap_r_ptr->r_tkills == 0);
+}
+
+void clear_scene_target_monster()
+{
+    scene_target_monster.ap_r_ptr = NULL;
+}
+
+static GAME_TURN get_game_turn()
+{
+    GAME_TURN ret = current_world_ptr->game_turn;
+    if (ret == current_world_ptr->game_turn_limit) {
+        ret = 0;
+    }
+    return ret;
+}
+
+/*!
+ * @brief モンスターBGMの制限期間を設定する
+ * @details 指定の時間が経過するまでモンスターBGMの再生を制限する
+ * @param msec 制限する時間(秒)
+ */
+void set_temp_mute_scene_monster(int sec)
+{
+    scene_target_monster.mute_until = (u32b)time(NULL) + sec;
+}
+
+/*!
+ * @brief モンスターBGMの制限期間か判定する
+ * @details ダンジョンターン数がscene_target_monster.mute_untilの値になるまで制限期間。
+ * @return モンスターBGMの制限期間の場合trueを返す
+ */
+inline static bool can_mute_scene_monster()
+{
+    return (scene_target_monster.mute_until > time(NULL));
+}
+
+/*!
+ * @brief モンスターの優先判定
+ * @details ユニーク、あやしい影、未知のモンスター、レベルの高さ、モンスターIDで優先を付ける。
+ * @param player_ptr プレーヤーへの参照ポインタ
+ * @param m_idx1 モンスターA(新参)
+ * @param m_idx2 モンスターB(現対象)
+ * @retval true モンスターAが優先
+ * @retval false モンスターBが優先
+ */
+static bool is_high_rate(player_type *player_ptr, MONSTER_IDX m_idx1, MONSTER_IDX m_idx2)
+{
+    // FIXME 視界内モンスターリストの比較関数と同じ処理
+    auto floor_ptr = player_ptr->current_floor_ptr;
+    auto m_ptr1 = &floor_ptr->m_list[m_idx1];
+    auto m_ptr2 = &floor_ptr->m_list[m_idx2];
+    auto ap_r_ptr1 = &r_info[m_ptr1->ap_r_idx];
+    auto ap_r_ptr2 = &r_info[m_ptr2->ap_r_idx];
+
+    /* Unique monsters first */
+    if (any_bits(ap_r_ptr1->flags1, RF1_UNIQUE) != any_bits(ap_r_ptr2->flags1, RF1_UNIQUE))
+        return any_bits(ap_r_ptr1->flags1, RF1_UNIQUE);
+
+    /* Shadowers first (あやしい影) */
+    if (m_ptr1->mflag2.has(MFLAG2::KAGE) != m_ptr2->mflag2.has(MFLAG2::KAGE))
+        return m_ptr1->mflag2.has(MFLAG2::KAGE);
+
+    /* Unknown monsters first */
+    if ((ap_r_ptr1->r_tkills == 0) != (ap_r_ptr2->r_tkills == 0))
+        return (ap_r_ptr1->r_tkills == 0);
+
+    /* Higher level monsters first (if known) */
+    if (ap_r_ptr1->r_tkills && ap_r_ptr2->r_tkills && ap_r_ptr1->level != ap_r_ptr2->level)
+        return ap_r_ptr1->level > ap_r_ptr2->level;
+
+    /* Sort by index if all conditions are same */
+    return m_ptr1->ap_r_idx > m_ptr2->ap_r_idx;
+}
+
+/*!
+ * @brief BGM対象モンスター更新処理
+ * @details 現在の対象と対象候補が同一モンスターの場合、最後に見たゲームターン情報を更新する。
+ * 対象候補が現在の対象よりも上位であれば対象を入れ替える。
+ * ユニーク、あやしい影、未知のモンスター、レベルの高さ、モンスターIDで優先を付ける。
+ * @param player_ptr プレーヤーへの参照ポインタ
+ * @param m_idx BGM対象候補のモンスター
+ */
+static void update_target_monster(player_type *player_ptr, MONSTER_IDX m_idx)
+{
+    if (scene_target_monster.ap_r_ptr && (scene_target_monster.m_idx == m_idx)) {
+        // 同一モンスター。最後に見たゲームターンを更新。
+        scene_target_monster.last_seen = get_game_turn();
+    } else {
+        bool do_dwap = false;
+        if (!scene_target_monster.ap_r_ptr) {
+            // 空席
+            do_dwap = true;
+        } else if (is_high_rate(player_ptr, m_idx, scene_target_monster.m_idx)) {
+            // 入れ替え
+            do_dwap = true;
+        }
+
+        if (do_dwap) {
+            monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
+            monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
+            scene_target_monster.m_idx = m_idx;
+            scene_target_monster.ap_r_ptr = ap_r_ptr;
+            scene_target_monster.last_seen = get_game_turn();
+        }
+    }
+}
+
+using scene_monster_func = bool (*)(player_type *player_ptr, scene_type *value);
+
+static bool scene_monster(player_type *player_ptr, scene_type *value)
+{
+    monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[scene_target_monster.m_idx];
+
+    if (has_shadower_flag(m_ptr)) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+        value->val = MUSIC_BASIC_SHADOWER;
+        return true;
+    } else {
+        value->type = TERM_XTRA_MUSIC_MONSTER;
+        value->val = m_ptr->ap_r_idx;
+        return true;
+    }
+}
+
+static bool scene_unique(player_type *player_ptr, scene_type *value)
+{
+    (void)player_ptr;
+
+    if (is_unique(scene_target_monster.ap_r_ptr)) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+        value->val = MUSIC_BASIC_UNIQUE;
+        return true;
+    }
+
+    return false;
+}
+
+static bool scene_unknown(player_type *player_ptr, scene_type *value)
+{
+    (void)player_ptr;
+    if (is_unknown_monster(scene_target_monster.ap_r_ptr)) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+        value->val = MUSIC_BASIC_UNKNOWN_MONSTER;
+        return true;
+    }
+
+    return false;
+}
+
+static bool scene_high_level(player_type *player_ptr, scene_type *value)
+{
+    if (!is_unknown_monster(scene_target_monster.ap_r_ptr) && (scene_target_monster.ap_r_ptr->level >= player_ptr->lev)) {
+        value->type = TERM_XTRA_MUSIC_BASIC;
+        value->val = MUSIC_BASIC_HIGHER_LEVEL_MONSTER;
+        return true;
+    }
+
+    return false;
+}
+
+/*! モンスターBGMのフォールバック設定。
+ * 先頭から適用する(先にある方を優先する)。
+ */
+std::vector<scene_monster_func> scene_monster_def_list = {
+    // scene_monster : あやしい影 or モンスターID
+    scene_monster,
+    // scene_unique : ユニークモンスター判定
+    scene_unique,
+    // scene_unkown : 未知のモンスター判定
+    scene_unknown,
+    // scene_high_level : 高レベルのモンスター判定
+    scene_high_level,
+};
+
+int get_scene_monster_count()
+{
+    return scene_monster_def_list.size();
+}
+
+/*!
+ * @brief 現在の条件でモンスターのBGM選曲をリストに設定する。
+ * @details リストのfrom_indexの位置から、get_scene_monster_count()で得られる個数分設定する。
+ * 視界内モンスターリスト先頭のモンスターを記憶し、以前のモンスターと比較してより上位のモンスターをBGM選曲の対象とする。
+ * 記憶したモンスターが視界内に存在しない場合、一定のゲームターン経過で忘れる。
+ * @param player_ptr プレーヤーへの参照ポインタ
+ * @param monster_list 視界内モンスターリスト
+ * @param list BGM選曲リスト
+ * @param from_index リストの更新開始位置
+ */
+void refresh_scene_monster(player_type *player_ptr, const std::vector<MONSTER_IDX> &monster_list, scene_type_list &list, int from_index)
+{
+    const bool mute = can_mute_scene_monster();
+
+    if (mute) {
+        // モンスターBGM制限中
+        clear_scene_target_monster();
+    } else {
+        if (scene_target_monster.ap_r_ptr) {
+            // BGM対象から外すチェック
+            if (get_game_turn() - scene_target_monster.last_seen >= 200) {
+                // 最後に見かけてから一定のゲームターンが経過した場合、BGM対象から外す
+                clear_scene_target_monster();
+            } else {
+                monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[scene_target_monster.m_idx];
+                monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
+                if (ap_r_ptr != scene_target_monster.ap_r_ptr) {
+                    // 死亡、チェンジモンスター、etc.
+                    clear_scene_target_monster();
+                }
+            }
+        }
+
+        if (!monster_list.empty()) {
+            // 現在のBGM対象とモンスターリスト先頭を比較し、上位をBGM対象に設定する
+            update_target_monster(player_ptr, monster_list.front());
+        }
+    }
+
+    if (scene_target_monster.ap_r_ptr) {
+        // BGM対象の条件で選曲リストを設定する
+        for (auto func : scene_monster_def_list) {
+            scene_type &item = list[from_index];
+            if (!func(player_ptr, &item)) {
+                // Note -- 特に定義を設けていないが、type = 0は無効な値とする。
+                item.type = 0;
+                item.val = 0;
+            }
+            ++from_index;
+        }
+    } else {
+        // BGM対象なしの場合は0で埋める
+        const int count = get_scene_monster_count();
+        for (int i = 0; i < count; i++) {
+            scene_type &item = list[from_index + i];
+            // Note -- 特に定義を設けていないが、type = 0は無効な値とする。
+            item.type = 0;
+            item.val = 0;
+        }
+    }
+}
diff --git a/src/main/scene-table-monster.h b/src/main/scene-table-monster.h
new file mode 100644 (file)
index 0000000..fe7a0e9
--- /dev/null
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "main/scene-table.h"
+#include "system/angband.h"
+#include "system/monster-race-definition.h"
+
+void clear_scene_target_monster();
+void set_temp_mute_scene_monster(int sec);
+int get_scene_monster_count();
+void refresh_scene_monster(player_type *player_ptr, const std::vector<MONSTER_IDX> &monster_list, scene_type_list &list, int from_index);
index ccf1a26..6517c02 100644 (file)
 #include "main/scene-table.h"
-#include "dungeon/quest.h"
-#include "main/music-definitions-table.h"
+#include "main/scene-table-floor.h"
+#include "main/scene-table-monster.h"
 #include "system/floor-type-definition.h"
+#include "term/z-term.h"
 
-static bool scene_basic(player_type *player_ptr, scene_type *value)
-{
-    if (player_ptr->ambush_flag) {
-        value->type = TERM_XTRA_MUSIC_BASIC;
-        value->val = MUSIC_BASIC_AMBUSH;
-        return true;
-    }
-
-    if (player_ptr->wild_mode) {
-        value->type = TERM_XTRA_MUSIC_BASIC;
-        value->val = MUSIC_BASIC_WILD;
-        return true;
-    }
-
-    if (player_ptr->current_floor_ptr->inside_arena) {
-        value->type = TERM_XTRA_MUSIC_BASIC;
-        value->val = MUSIC_BASIC_ARENA;
-        return true;
-    }
-
-    if (player_ptr->phase_out) {
-        value->type = TERM_XTRA_MUSIC_BASIC;
-        value->val = MUSIC_BASIC_BATTLE;
-        return true;
-    }
-
-    return false;
-}
-
-static bool scene_quest(player_type *player_ptr, scene_type *value)
-{
-    const QUEST_IDX quest_id = quest_number(player_ptr, player_ptr->current_floor_ptr->dun_level);
-    const bool enable = (quest_id > 0);
-    if (enable) {
-        value->type = TERM_XTRA_MUSIC_QUEST;
-        value->val = quest_id;
-    }
+int interrupt_scene_type;
+int interrupt_scene_val;
 
-    return enable;
-}
-
-static bool scene_quest_basic(player_type *player_ptr, scene_type *value)
-{
-    const QUEST_IDX quest_id = quest_number(player_ptr, player_ptr->current_floor_ptr->dun_level);
-    const bool enable = (quest_id > 0);
-    if (enable) {
-        value->type = TERM_XTRA_MUSIC_BASIC;
-        value->val = MUSIC_BASIC_QUEST;
-    }
-
-    return enable;
-}
-
-static bool scene_town(player_type *player_ptr, scene_type *value)
-{
-    const bool enable = !is_in_dungeon(player_ptr) && (player_ptr->town_num > 0);
-    if (enable) {
-        value->type = TERM_XTRA_MUSIC_TOWN;
-        value->val = player_ptr->town_num;
-    }
-    return enable;
-}
+scene_type_list scene_list;
 
-static bool scene_town_basic(player_type *player_ptr, scene_type *value)
+static void resize_scene_list()
 {
-    const bool enable = !is_in_dungeon(player_ptr) && (player_ptr->town_num > 0);
-    if (enable) {
-        value->type = TERM_XTRA_MUSIC_BASIC;
-        value->val = MUSIC_BASIC_TOWN;
-    }
-    return enable;
+    const int monster_def_count = get_scene_monster_count();
+    const int interrupt_def_count = 1;
+    const int floor_def_count = get_scene_floor_count();
+    scene_list.resize(monster_def_count + interrupt_def_count + floor_def_count);
 }
 
-static bool scene_field(player_type *player_ptr, scene_type *value)
-{
-    const bool enable = !is_in_dungeon(player_ptr);
-    if (enable) {
-        value->type = TERM_XTRA_MUSIC_BASIC;
-
-        if (player_ptr->lev >= 45)
-            value->val = MUSIC_BASIC_FIELD3;
-        else if (player_ptr->lev >= 25)
-            value->val = MUSIC_BASIC_FIELD2;
-        else
-            value->val = MUSIC_BASIC_FIELD1;
-    }
-    return enable;
+/*!
+ * @brief 選曲の割り込み通知
+ * @details 選曲テーブル外の曲(クエストクリア等)の再生を取得しておく。
+ * モンスターBGMを含む選曲テーブルを構築する場合に、
+ * 1.モンスターBGM
+ * 2.割り込みBGM
+ * 3.通常BGM
+ * の順に設定する。
+ * 街の施設等で、コマンド実行→視界内モンスターリスト更新(空のリスト:再生なし)→割り込みBGMに戻るようにする。
+ * @param type action-type
+ * @param val action-val
+ */
+void interrupt_scene(int type, int val) {
+    interrupt_scene_type = type;
+    interrupt_scene_val = val;
 }
 
-static bool scene_dungeon_feeling(player_type *player_ptr, scene_type *value)
+/*!
+ * @brief 現在のフロアに合ったBGM選曲
+ * @param player_ptr プレーヤーへの参照ポインタ
+ */
+void refresh_scene_table(player_type *player_ptr)
 {
-    const bool enable = (player_ptr->feeling >= 2) && (player_ptr->feeling <= 5);
-    if (enable) {
-        value->type = TERM_XTRA_MUSIC_BASIC;
-
-        if (player_ptr->feeling == 2)
-            value->val = MUSIC_BASIC_DUN_FEEL2;
-        else
-            value->val = MUSIC_BASIC_DUN_FEEL1;
-    }
-    return enable;
+    // forget BGM-target monster
+    clear_scene_target_monster();
+    // clear interrupt_scene
+    interrupt_scene(0, 0);
+    // モンスターBGMの再生を一時的に抑制する
+    set_temp_mute_scene_monster(2);
+
+    resize_scene_list();
+    refresh_scene_floor(player_ptr, scene_list, 0);
 }
 
-static bool scene_dungeon(player_type *player_ptr, scene_type *value)
+/*!
+ * @brief 見かけたモンスターを含め、現在のフロアに合ったBGM選曲
+ * @param player_ptr プレーヤーへの参照ポインタ
+ * @param monster_list 視界内モンスターリスト
+ */
+void refresh_scene_table(player_type *player_ptr, const std::vector<MONSTER_IDX> &monster_list)
 {
-    const bool enable = (player_ptr->dungeon_idx > 0);
-    if (enable) {
-        value->type = TERM_XTRA_MUSIC_DUNGEON;
-        value->val = player_ptr->dungeon_idx;
-    }
-    return enable;
-}
+    resize_scene_list();
+    int index = 0;
 
-static bool scene_dungeon_basic(player_type *player_ptr, scene_type *value)
-{
-    const bool enable = is_in_dungeon(player_ptr);
-    if (enable) {
-        value->type = TERM_XTRA_MUSIC_BASIC;
+    refresh_scene_monster(player_ptr, monster_list, scene_list, index);
+    index += get_scene_monster_count();
 
-        const auto dun_level = player_ptr->current_floor_ptr->dun_level;
-        if (dun_level >= 80)
-            value->val = MUSIC_BASIC_DUN_HIGH;
-        else if (dun_level >= 40)
-            value->val = MUSIC_BASIC_DUN_MED;
-        else
-            value->val = MUSIC_BASIC_DUN_LOW;
-    }
-    return enable;
-}
+    // interrupt scene
+    scene_type &item = scene_list[index];
+    item.type = interrupt_scene_type;
+    item.val = interrupt_scene_val;
+    ++index;
 
-static bool scene_mute(player_type *player_ptr, scene_type *value)
-{
-    (void)player_ptr;
-    value->type = TERM_XTRA_MUSIC_MUTE;
-    value->val = 0;
-    return true;
+    refresh_scene_floor(player_ptr, scene_list, index);
 }
 
-/*! シチュエーション選択のフォールバック設定。
- * 先頭から適用する(先にある方を優先する)。
+/*!
+ * @brief BGM選曲リスト取得
+ * @param type 未使用
  */
-std::vector<scene_type> playfallback = {
-    // scene_basic : ambush, wild, arena, battleの判定
-    { scene_basic },
-    // scene_quest : questの判定(クエストの個別BGMを指定)
-    { scene_quest },
-    // scene_quest_basic : questの判定 (Basicのquest指定)
-    { scene_quest_basic },
-    // scene_town : townの判定(町の個別BGMを指定)
-    { scene_town },
-    // scene_town_basic : townの判定 (Basicのtown指定)
-    { scene_town_basic },
-    // scene_field : field1/2/3の判定(プレイヤーレベル25未満、25以上45未満、45以上時の荒野)
-    { scene_field },
-    // scene_dungeon_feeling : feed1/2の判定(ダンジョンの雰囲気が「悪い予感」~「とても危険」、「死の幻」)
-    { scene_dungeon_feeling },
-    // scene_dungeon : dungeonの判定(ダンジョンの個別BGMを指定)
-    { scene_dungeon },
-    // scene_dungeon_basic : dun_low/med/highの判定(ダンジョンレベルが40未満、40以上80未満、80以上)
-    { scene_dungeon_basic },
-    // scene_mute : 最後にミュートを配置する
-    { scene_mute }
-};
-
-void refresh_scene_table(player_type *player_ptr)
-{
-    for (auto &item : playfallback) {
-        if (!item.update(player_ptr, &item)) {
-            // Note -- 特に定義を設けていないが、type = 0は無効な値とする。
-            item.type = 0;
-            item.val = 0;
-        }
-    }
-}
-
-scene_iterator get_scene_table_iterator()
+scene_type_list &get_scene_type_list(int type)
 {
-    return playfallback.begin();
+    (void)type;
+    return scene_list;
 }
index cfbac83..2a31676 100644 (file)
@@ -1,32 +1,19 @@
 #pragma once
 
+#include "player/player-status.h"
 #include "system/angband.h"
+#include "system/monster-race-definition.h"
 
-#include <iterator>
 #include <vector>
 
-struct scene_type;
-// シチュエーション判定関数。valueに設定した場合trueを返す。
-using scene_def_func = bool (*)(player_type *player_ptr, scene_type *value);
-
 struct scene_type {
     int type = 0; //!< シチュエーションカテゴリ
     int val = 0; //!< シチュエーション項目
-
-    bool update(player_type *player_ptr, scene_type *value)
-    {
-        return scene_def(player_ptr, value);
-    }
-
-    scene_type(scene_def_func f)
-        : scene_def(f)
-    {
-    }
-
-private:
-    scene_def_func scene_def; //!< シチュエーション判定関数
 };
 
+using scene_type_list = std::vector<scene_type>;
+
+void interrupt_scene(int type, int val);
 void refresh_scene_table(player_type *player_ptr);
-using scene_iterator = std::vector<scene_type>::const_iterator;
-scene_iterator get_scene_table_iterator();
+void refresh_scene_table(player_type *player_ptr, const std::vector<MONSTER_IDX> &monster_list);
+scene_type_list &get_scene_type_list(int val);
index dfde5a4..7637028 100644 (file)
@@ -4,6 +4,9 @@
 #include "main/scene-table.h"
 #include "term/screen-processor.h"
 
+// モンスターBGMの設定有無。設定なし時に関連処理をスキップする。
+bool has_monster_music = false;
+
 /*
  * Flush the screen, make a noise
  */
@@ -36,6 +39,7 @@ errr play_music(int type, int val)
     if (!use_music)
         return 1;
 
+    interrupt_scene(type, val);
     return term_xtra(type, val);
 }
 
@@ -50,5 +54,19 @@ void select_floor_music(player_type *player_ptr)
         return;
 
     refresh_scene_table(player_ptr);
-    play_music(TERM_XTRA_SCENE, 0);
+    term_xtra(TERM_XTRA_SCENE, 0);
+}
+
+/*!
+ * @brief モンスターBGM選曲
+ * @param player_ptr プレーヤーへの参照ポインタ
+ * @param monster_list モンスターリスト
+ */
+void select_monster_music(player_type *player_ptr, const std::vector<MONSTER_IDX> &monster_list)
+{
+    if (!use_music)
+        return;
+
+    refresh_scene_table(player_ptr, monster_list);
+    term_xtra(TERM_XTRA_SCENE, 0);
 }
index 1687b9b..5e96ce5 100644 (file)
@@ -2,7 +2,12 @@
 
 #include "system/angband.h"
 
+#include <vector>
+
+extern bool has_monster_music;
+
 void bell(void);
 void sound(int num);
 errr play_music(int type, int num);
 void select_floor_music(player_type *player_ptr);
+void select_monster_music(player_type *player_ptr, const std::vector<MONSTER_IDX> &monster_list);
index 28c3572..65844c4 100644 (file)
@@ -13,8 +13,6 @@
 #include "market/building-util.h"
 #include "monster-race/monster-race-hook.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
 #include "monster-race/race-flags-resistance.h"
 #include "monster-race/race-flags1.h"
 #include "monster-race/race-flags7.h"
@@ -234,11 +232,11 @@ void update_gambling_monsters(player_type *player_ptr)
                 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)
+            else if (r_ptr->ability_flags.has(RF_ABILITY::INVULNER))
                 power[i] = power[i] * 4 / 3;
-            else if (r_ptr->a_ability_flags2 & RF6_HEAL)
+            else if (r_ptr->ability_flags.has(RF_ABILITY::HEAL))
                 power[i] = power[i] * 4 / 3;
-            else if (r_ptr->a_ability_flags1 & RF5_DRAIN_MANA)
+            else if (r_ptr->ability_flags.has(RF_ABILITY::DRAIN_MANA))
                 power[i] = power[i] * 11 / 10;
             if (r_ptr->flags1 & RF1_RAND_25)
                 power[i] = power[i] * 9 / 10;
index fc89f7e..a88c2af 100644 (file)
@@ -1,8 +1,8 @@
 #include "market/building-initializer.h"
 #include "floor/floor-town.h"
-#include "market/articles-on-sale.h"
 #include "object/object-kind.h"
 #include "object/object-kind-hook.h"
+#include "store/articles-on-sale.h"
 #include "store/store-owners.h"
 #include "store/store-util.h"
 #include "store/store.h"
@@ -28,22 +28,13 @@ errr init_towns(void)
              * 我が家が 20 ページまで使える隠し機能のための準備。
              * オプションが有効でもそうでなくても一応スペースを作っておく。
              */
-            if (j == STORE_HOME) {
-                store_ptr->stock_size = STORE_INVEN_MAX * 10;
-            } else if (j == STORE_MUSEUM) {
-                store_ptr->stock_size = STORE_INVEN_MAX * 50;
-            } else {
-                store_ptr->stock_size = STORE_INVEN_MAX;
-            }
+            store_ptr->stock_size = store_get_stock_max(static_cast<STORE_TYPE_IDX>(j));
 
             C_MAKE(store_ptr->stock, store_ptr->stock_size, object_type);
             if ((j == STORE_BLACK) || (j == STORE_HOME) || (j == STORE_MUSEUM))
                 continue;
 
-            store_ptr->regular_num = 0;
-            store_ptr->regular_size = STORE_INVEN_MAX;
-            C_MAKE(store_ptr->regular, store_ptr->regular_size + 1, KIND_OBJECT_IDX);
-            for (int k = 0; k < store_ptr->regular_size; k++) {
+            for (int k = 0; k < STORE_INVEN_MAX; k++) {
                 int tv = store_regular_table[j][k].tval;
                 int sv = store_regular_table[j][k].sval;
                 if (tv == 0)
@@ -54,13 +45,10 @@ errr init_towns(void)
                 if (k_idx == 0)
                     continue;
 
-                store_ptr->regular[store_ptr->regular_num++] = k_idx;
+                store_ptr->regular.push_back(k_idx);
             }
 
-            store_ptr->table_num = 0;
-            store_ptr->table_size = STORE_CHOICES;
-            C_MAKE(store_ptr->table, store_ptr->table_size + 1, KIND_OBJECT_IDX);
-            for (int k = 0; k < store_ptr->table_size; k++) {
+            for (int k = 0; k < STORE_CHOICES; k++) {
                 int tv = store_table[j][k].tval;
                 int sv = store_table[j][k].sval;
                 if (tv == 0)
@@ -71,7 +59,7 @@ errr init_towns(void)
                 if (k_idx == 0)
                     continue;
 
-                store_ptr->table[store_ptr->table_num++] = k_idx;
+                store_ptr->table.push_back(k_idx);
             }
         }
     }
index 6ca6b7c..f6ad43c 100644 (file)
@@ -6,18 +6,15 @@
 #include "melee/melee-spell-util.h"
 #include "monster-floor/monster-move.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
+#include "monster-race/race-ability-mask.h"
 #include "monster-race/race-flags2.h"
 #include "monster-race/race-flags3.h"
-#include "monster-race/race-flags4.h"
 #include "monster-race/race-flags7.h"
 #include "monster-race/race-indice-types.h"
 #include "monster/monster-info.h"
 #include "monster/monster-status.h"
 #include "mspell/mspell-checker.h"
 #include "mspell/mspell-judgement.h"
-#include "mspell/mspell-mask-definitions.h"
 #include "mspell/mspell-util.h"
 #include "pet/pet-util.h"
 #include "spell-kind/spells-world.h"
@@ -55,9 +52,7 @@ static void decide_indirection_melee_spell(player_type *target_ptr, melee_spell_
     if (projectable(target_ptr, ms_ptr->m_ptr->fy, ms_ptr->m_ptr->fx, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx))
         return;
 
-    ms_ptr->f4 &= RF4_INDIRECT_MASK;
-    ms_ptr->f5 &= RF5_INDIRECT_MASK;
-    ms_ptr->f6 &= RF6_INDIRECT_MASK;
+    ms_ptr->ability_flags &= RF_ABILITY_INDIRECT_MASK;
 }
 
 static bool check_melee_spell_projection(player_type *target_ptr, melee_spell_type *ms_ptr)
@@ -94,7 +89,7 @@ static bool check_melee_spell_projection(player_type *target_ptr, melee_spell_ty
 
 static void check_darkness(player_type *target_ptr, melee_spell_type *ms_ptr)
 {
-    if ((ms_ptr->f6 & RF6_DARKNESS) == 0)
+    if (ms_ptr->ability_flags.has_not(RF_ABILITY::DARKNESS))
         return;
 
     bool vs_ninja = (target_ptr->pclass == CLASS_NINJA) && !is_hostile(ms_ptr->t_ptr);
@@ -103,12 +98,12 @@ static void check_darkness(player_type *target_ptr, melee_spell_type *ms_ptr)
         return;
 
     if (d_info[target_ptr->dungeon_idx].flags1 & DF1_DARKNESS) {
-        ms_ptr->f6 &= ~(RF6_DARKNESS);
+        ms_ptr->ability_flags.reset(RF_ABILITY::DARKNESS);
         return;
     }
 
     if (vs_ninja && !can_use_lite_area)
-        ms_ptr->f6 &= ~(RF6_DARKNESS);
+        ms_ptr->ability_flags.reset(RF_ABILITY::DARKNESS);
 }
 
 static void check_stupid(melee_spell_type *ms_ptr)
@@ -116,9 +111,7 @@ static void check_stupid(melee_spell_type *ms_ptr)
     if (!ms_ptr->in_no_magic_dungeon || ((ms_ptr->r_ptr->flags2 & RF2_STUPID) != 0))
         return;
 
-    ms_ptr->f4 &= (RF4_NOMAGIC_MASK);
-    ms_ptr->f5 &= (RF5_NOMAGIC_MASK);
-    ms_ptr->f6 &= (RF6_NOMAGIC_MASK);
+    ms_ptr->ability_flags &= RF_ABILITY_NOMAGIC_MASK;
 }
 
 static void check_arena(player_type *target_ptr, melee_spell_type *ms_ptr)
@@ -126,112 +119,104 @@ static void check_arena(player_type *target_ptr, melee_spell_type *ms_ptr)
     if (!target_ptr->current_floor_ptr->inside_arena && !target_ptr->phase_out)
         return;
 
-    ms_ptr->f4 &= ~(RF4_SUMMON_MASK);
-    ms_ptr->f5 &= ~(RF5_SUMMON_MASK);
-    ms_ptr->f6 &= ~(RF6_SUMMON_MASK | RF6_TELE_LEVEL);
+    ms_ptr->ability_flags.reset(RF_ABILITY_SUMMON_MASK).reset(RF_ABILITY::TELE_LEVEL);
     if (ms_ptr->m_ptr->r_idx == MON_ROLENTO)
-        ms_ptr->f6 &= ~(RF6_SPECIAL);
+        ms_ptr->ability_flags.reset(RF_ABILITY::SPECIAL);
 }
 
 static void check_melee_spell_distance(player_type *target_ptr, melee_spell_type *ms_ptr)
 {
-    if (((ms_ptr->f4 & (RF4_BALL_MASK & ~(RF4_ROCKET))) == 0) && ((ms_ptr->f5 & RF5_BALL_MASK) == 0) && ((ms_ptr->f6 & RF6_BALL_MASK) == 0))
+    auto ball_mask_except_rocket = RF_ABILITY_BALL_MASK;
+    ball_mask_except_rocket.reset(RF_ABILITY::ROCKET);
+    if (ms_ptr->ability_flags.has_any_of(ball_mask_except_rocket))
         return;
 
     POSITION real_y = ms_ptr->y;
     POSITION real_x = ms_ptr->x;
     get_project_point(target_ptr, ms_ptr->m_ptr->fy, ms_ptr->m_ptr->fx, &real_y, &real_x, 0L);
-    if (!projectable(target_ptr, real_y, real_x, target_ptr->y, target_ptr->x) && ((ms_ptr->f5 & RF5_BA_LITE) != 0)
+    if (!projectable(target_ptr, real_y, real_x, target_ptr->y, target_ptr->x) && ms_ptr->ability_flags.has(RF_ABILITY::BA_LITE)
         && (distance(real_y, real_x, target_ptr->y, target_ptr->x) <= 4) && los(target_ptr, real_y, real_x, target_ptr->y, target_ptr->x)) {
-        ms_ptr->f5 &= ~(RF5_BA_LITE);
+        ms_ptr->ability_flags.reset(RF_ABILITY::BA_LITE);
 
         return;
     }
 
     int dist = distance(real_y, real_x, target_ptr->y, target_ptr->x);
     if (dist <= 2) {
-        ms_ptr->f4 &= ~(RF4_BALL_MASK & ~(RF4_ROCKET));
-        ms_ptr->f5 &= ~(RF5_BALL_MASK);
-        ms_ptr->f6 &= ~(RF6_BALL_MASK);
+        ms_ptr->ability_flags.reset(ball_mask_except_rocket);
         return;
     }
 
     if (dist > 4)
         return;
 
-    ms_ptr->f4 &= ~(RF4_BIG_BALL_MASK);
-    ms_ptr->f5 &= ~(RF5_BIG_BALL_MASK);
-    ms_ptr->f6 &= ~(RF6_BIG_BALL_MASK);
+    ms_ptr->ability_flags.reset(RF_ABILITY_BIG_BALL_MASK);
 }
 
 static void check_melee_spell_rocket(player_type *target_ptr, melee_spell_type *ms_ptr)
 {
-    if ((ms_ptr->f4 & RF4_ROCKET) == 0)
+    if (ms_ptr->ability_flags.has_not(RF_ABILITY::ROCKET))
         return;
 
     POSITION real_y = ms_ptr->y;
     POSITION real_x = ms_ptr->x;
     get_project_point(target_ptr, ms_ptr->m_ptr->fy, ms_ptr->m_ptr->fx, &real_y, &real_x, PROJECT_STOP);
     if (projectable(target_ptr, real_y, real_x, target_ptr->y, target_ptr->x) && (distance(real_y, real_x, target_ptr->y, target_ptr->x) <= 2))
-        ms_ptr->f4 &= ~(RF4_ROCKET);
+        ms_ptr->ability_flags.reset(RF_ABILITY::ROCKET);
 }
 
 static void check_melee_spell_beam(player_type *target_ptr, melee_spell_type *ms_ptr)
 {
-    if ((((ms_ptr->f4 & RF4_BEAM_MASK) == 0) && ((ms_ptr->f5 & RF5_BEAM_MASK) == 0) && ((ms_ptr->f6 & RF6_BEAM_MASK) == 0))
+    if (ms_ptr->ability_flags.has_none_of(RF_ABILITY_BEAM_MASK)
         || direct_beam(target_ptr, ms_ptr->m_ptr->fy, ms_ptr->m_ptr->fx, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx, ms_ptr->m_ptr))
         return;
 
-    ms_ptr->f4 &= ~(RF4_BEAM_MASK);
-    ms_ptr->f5 &= ~(RF5_BEAM_MASK);
-    ms_ptr->f6 &= ~(RF6_BEAM_MASK);
+    ms_ptr->ability_flags.reset(RF_ABILITY_BEAM_MASK);
 }
 
 static void check_melee_spell_breath(player_type *target_ptr, melee_spell_type *ms_ptr)
 {
-    if (((ms_ptr->f4 & RF4_BREATH_MASK) == 0) && ((ms_ptr->f5 & RF5_BREATH_MASK) == 0) && ((ms_ptr->f6 & RF6_BREATH_MASK) == 0))
+    if (ms_ptr->ability_flags.has_none_of(RF_ABILITY_BREATH_MASK))
         return;
 
     POSITION rad = (ms_ptr->r_ptr->flags2 & RF2_POWERFUL) ? 3 : 2;
     if (!breath_direct(target_ptr, ms_ptr->m_ptr->fy, ms_ptr->m_ptr->fx, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx, rad, 0, TRUE)) {
-        ms_ptr->f4 &= ~(RF4_BREATH_MASK);
-        ms_ptr->f5 &= ~(RF5_BREATH_MASK);
-        ms_ptr->f6 &= ~(RF6_BREATH_MASK);
+        ms_ptr->ability_flags.reset(RF_ABILITY_BREATH_MASK);
         return;
     }
 
-    if ((ms_ptr->f4 & RF4_BR_LITE)
+    if (ms_ptr->ability_flags.has(RF_ABILITY::BR_LITE)
         && !breath_direct(target_ptr, ms_ptr->m_ptr->fy, ms_ptr->m_ptr->fx, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx, rad, GF_LITE, TRUE)) {
-        ms_ptr->f4 &= ~(RF4_BR_LITE);
+        ms_ptr->ability_flags.reset(RF_ABILITY::BR_LITE);
         return;
     }
 
-    if ((ms_ptr->f4 & RF4_BR_DISI)
+    if (ms_ptr->ability_flags.has(RF_ABILITY::BR_DISI)
         && !breath_direct(target_ptr, ms_ptr->m_ptr->fy, ms_ptr->m_ptr->fx, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx, rad, GF_DISINTEGRATE, TRUE)) {
-        ms_ptr->f4 &= ~(RF4_BR_DISI);
+        ms_ptr->ability_flags.reset(RF_ABILITY::BR_DISI);
     }
 }
 
 static void check_melee_spell_special(player_type *target_ptr, melee_spell_type *ms_ptr)
 {
-    if ((ms_ptr->f6 & RF6_SPECIAL) == 0)
+    if (ms_ptr->ability_flags.has_not(RF_ABILITY::SPECIAL))
         return;
 
     if (ms_ptr->m_ptr->r_idx == MON_ROLENTO) {
         if ((target_ptr->pet_extra_flags & (PF_ATTACK_SPELL | PF_SUMMON_SPELL)) != (PF_ATTACK_SPELL | PF_SUMMON_SPELL))
-            ms_ptr->f6 &= ~(RF6_SPECIAL);
+            ms_ptr->ability_flags.reset(RF_ABILITY::SPECIAL);
 
         return;
     }
 
     if (ms_ptr->r_ptr->d_char == 'B') {
         if ((target_ptr->pet_extra_flags & (PF_ATTACK_SPELL | PF_TELEPORT)) != (PF_ATTACK_SPELL | PF_TELEPORT))
-            ms_ptr->f6 &= ~(RF6_SPECIAL);
+            ms_ptr->ability_flags.reset(RF_ABILITY::SPECIAL);
 
         return;
     }
 
-    ms_ptr->f6 &= ~(RF6_SPECIAL);
+    ms_ptr->ability_flags.reset(RF_ABILITY::SPECIAL);
 }
 
 static void check_riding(player_type *target_ptr, melee_spell_type *ms_ptr)
@@ -239,9 +224,7 @@ static void check_riding(player_type *target_ptr, melee_spell_type *ms_ptr)
     if (ms_ptr->m_idx != target_ptr->riding)
         return;
 
-    ms_ptr->f4 &= ~(RF4_RIDING_MASK);
-    ms_ptr->f5 &= ~(RF5_RIDING_MASK);
-    ms_ptr->f6 &= ~(RF6_RIDING_MASK);
+    ms_ptr->ability_flags.reset(RF_ABILITY_RIDING_MASK);
 }
 
 static void check_pet(player_type *target_ptr, melee_spell_type *ms_ptr)
@@ -249,21 +232,16 @@ static void check_pet(player_type *target_ptr, melee_spell_type *ms_ptr)
     if (!ms_ptr->pet)
         return;
 
-    ms_ptr->f4 &= ~(RF4_SHRIEK);
-    ms_ptr->f6 &= ~(RF6_DARKNESS | RF6_TRAPS);
+    ms_ptr->ability_flags.reset({ RF_ABILITY::SHRIEK, RF_ABILITY::DARKNESS, RF_ABILITY::TRAPS });
     if (!(target_ptr->pet_extra_flags & PF_TELEPORT))
-        ms_ptr->f6 &= ~(RF6_BLINK | RF6_TPORT | RF6_TELE_TO | RF6_TELE_AWAY | RF6_TELE_LEVEL);
+        ms_ptr->ability_flags.reset({ RF_ABILITY::BLINK, RF_ABILITY::TPORT, RF_ABILITY::TELE_TO, RF_ABILITY::TELE_AWAY, RF_ABILITY::TELE_LEVEL });
 
     if (!(target_ptr->pet_extra_flags & PF_ATTACK_SPELL)) {
-        ms_ptr->f4 &= ~(RF4_ATTACK_MASK);
-        ms_ptr->f5 &= ~(RF5_ATTACK_MASK);
-        ms_ptr->f6 &= ~(RF6_ATTACK_MASK);
+        ms_ptr->ability_flags.reset(RF_ABILITY_ATTACK_MASK);
     }
 
     if (!(target_ptr->pet_extra_flags & PF_SUMMON_SPELL)) {
-        ms_ptr->f4 &= ~(RF4_SUMMON_MASK);
-        ms_ptr->f5 &= ~(RF5_SUMMON_MASK);
-        ms_ptr->f6 &= ~(RF6_SUMMON_MASK);
+        ms_ptr->ability_flags.reset(RF_ABILITY_SUMMON_MASK);
     }
 
     if (!(target_ptr->pet_extra_flags & PF_BALL_SPELL) && (ms_ptr->m_idx != target_ptr->riding)) {
@@ -281,28 +259,24 @@ static void check_non_stupid(player_type *target_ptr, melee_spell_type *ms_ptr)
     if ((ms_ptr->r_ptr->flags2 & RF2_STUPID) != 0)
         return;
 
-    if (((ms_ptr->f4 & RF4_BOLT_MASK) || (ms_ptr->f5 & RF5_BOLT_MASK) || (ms_ptr->f6 & RF6_BOLT_MASK))
+    if (ms_ptr->ability_flags.has_any_of(RF_ABILITY_BOLT_MASK)
         && !clean_shot(target_ptr, ms_ptr->m_ptr->fy, ms_ptr->m_ptr->fx, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx, ms_ptr->pet)) {
-        ms_ptr->f4 &= ~(RF4_BOLT_MASK);
-        ms_ptr->f5 &= ~(RF5_BOLT_MASK);
-        ms_ptr->f6 &= ~(RF6_BOLT_MASK);
+        ms_ptr->ability_flags.reset(RF_ABILITY_BOLT_MASK);
     }
 
-    if (((ms_ptr->f4 & RF4_SUMMON_MASK) || (ms_ptr->f5 & RF5_SUMMON_MASK) || (ms_ptr->f6 & RF6_SUMMON_MASK))
-        && !(summon_possible(target_ptr, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx))) {
-        ms_ptr->f4 &= ~(RF4_SUMMON_MASK);
-        ms_ptr->f5 &= ~(RF5_SUMMON_MASK);
-        ms_ptr->f6 &= ~(RF6_SUMMON_MASK);
+    if (ms_ptr->ability_flags.has_any_of(RF_ABILITY_SUMMON_MASK) && !(summon_possible(target_ptr, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx))) {
+        ms_ptr->ability_flags.reset(RF_ABILITY_SUMMON_MASK);
     }
 
-    if ((ms_ptr->f4 & RF4_DISPEL) && !dispel_check_monster(target_ptr, ms_ptr->m_idx, ms_ptr->target_idx))
-        ms_ptr->f4 &= ~(RF4_DISPEL);
+    if (ms_ptr->ability_flags.has(RF_ABILITY::DISPEL) && !dispel_check_monster(target_ptr, ms_ptr->m_idx, ms_ptr->target_idx))
+        ms_ptr->ability_flags.reset(RF_ABILITY::DISPEL);
 
-    if ((ms_ptr->f6 & RF6_RAISE_DEAD) && !raise_possible(target_ptr, ms_ptr->m_ptr))
-        ms_ptr->f6 &= ~(RF6_RAISE_DEAD);
+    if (ms_ptr->ability_flags.has(RF_ABILITY::RAISE_DEAD) && !raise_possible(target_ptr, ms_ptr->m_ptr))
+        ms_ptr->ability_flags.reset(RF_ABILITY::RAISE_DEAD);
 
-    if (((ms_ptr->f6 & RF6_SPECIAL) != 0) && (ms_ptr->m_ptr->r_idx == MON_ROLENTO) && !summon_possible(target_ptr, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx))
-        ms_ptr->f6 &= ~(RF6_SPECIAL);
+    if (ms_ptr->ability_flags.has(RF_ABILITY::SPECIAL) && (ms_ptr->m_ptr->r_idx == MON_ROLENTO)
+        && !summon_possible(target_ptr, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx))
+        ms_ptr->ability_flags.reset(RF_ABILITY::SPECIAL);
 }
 
 static void check_smart(player_type *target_ptr, melee_spell_type *ms_ptr)
@@ -311,33 +285,22 @@ static void check_smart(player_type *target_ptr, melee_spell_type *ms_ptr)
         return;
 
     if ((ms_ptr->m_ptr->hp < ms_ptr->m_ptr->maxhp / 10) && (randint0(100) < 50)) {
-        ms_ptr->f4 &= (RF4_INT_MASK);
-        ms_ptr->f5 &= (RF5_INT_MASK);
-        ms_ptr->f6 &= (RF6_INT_MASK);
+        ms_ptr->ability_flags &= RF_ABILITY_INT_MASK;
     }
 
-    if ((ms_ptr->f6 & RF6_TELE_LEVEL) && is_teleport_level_ineffective(target_ptr, (ms_ptr->target_idx == target_ptr->riding) ? 0 : ms_ptr->target_idx))
-        ms_ptr->f6 &= ~(RF6_TELE_LEVEL);
+    if (ms_ptr->ability_flags.has(RF_ABILITY::TELE_LEVEL)
+        && is_teleport_level_ineffective(target_ptr, (ms_ptr->target_idx == target_ptr->riding) ? 0 : ms_ptr->target_idx))
+        ms_ptr->ability_flags.reset(RF_ABILITY::TELE_LEVEL);
 }
 
 static bool set_melee_spell_set(player_type *target_ptr, melee_spell_type *ms_ptr)
 {
-    if (!ms_ptr->f4 && !ms_ptr->f5 && !ms_ptr->f6)
+    if (ms_ptr->ability_flags.none())
         return FALSE;
 
-    for (int k = 0; k < 32; k++)
-        if (ms_ptr->f4 & (1UL << k))
-            ms_ptr->spell[ms_ptr->num++] = k + RF4_SPELL_START;
+    FlagGroup<RF_ABILITY>::get_flags(ms_ptr->ability_flags, std::back_inserter(ms_ptr->spells));
 
-    for (int k = 0; k < 32; k++)
-        if (ms_ptr->f5 & (1UL << k))
-            ms_ptr->spell[ms_ptr->num++] = k + RF5_SPELL_START;
-
-    for (int k = 0; k < 32; k++)
-        if (ms_ptr->f6 & (1UL << k))
-            ms_ptr->spell[ms_ptr->num++] = k + RF6_SPELL_START;
-
-    return (ms_ptr->num != 0) && target_ptr->playing && !target_ptr->is_dead && !target_ptr->leaving;
+    return !ms_ptr->spells.empty() && target_ptr->playing && !target_ptr->is_dead && !target_ptr->leaving;
 }
 
 bool check_melee_spell_set(player_type *target_ptr, melee_spell_type *ms_ptr)
@@ -345,9 +308,7 @@ bool check_melee_spell_set(player_type *target_ptr, melee_spell_type *ms_ptr)
     if (monster_confused_remaining(ms_ptr->m_ptr))
         return FALSE;
 
-    ms_ptr->f4 = ms_ptr->r_ptr->flags4;
-    ms_ptr->f5 = ms_ptr->r_ptr->a_ability_flags1;
-    ms_ptr->f6 = ms_ptr->r_ptr->a_ability_flags2;
+    ms_ptr->ability_flags = ms_ptr->r_ptr->ability_flags;
     decide_melee_spell_target(target_ptr, ms_ptr);
     decide_indirection_melee_spell(target_ptr, ms_ptr);
     if (!check_melee_spell_projection(target_ptr, ms_ptr))
@@ -356,18 +317,18 @@ bool check_melee_spell_set(player_type *target_ptr, melee_spell_type *ms_ptr)
     ms_ptr->y = ms_ptr->t_ptr->fy;
     ms_ptr->x = ms_ptr->t_ptr->fx;
     reset_target(ms_ptr->m_ptr);
-    ms_ptr->f6 &= ~(RF6_WORLD | RF6_TRAPS | RF6_FORGET);
-    if (((ms_ptr->f4 & RF4_BR_LITE) != 0) && !los(target_ptr, ms_ptr->m_ptr->fy, ms_ptr->m_ptr->fx, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx))
-        ms_ptr->f4 &= ~(RF4_BR_LITE);
+    ms_ptr->ability_flags.reset({ RF_ABILITY::WORLD, RF_ABILITY::TRAPS, RF_ABILITY::FORGET });
+    if (ms_ptr->ability_flags.has(RF_ABILITY::BR_LITE) && !los(target_ptr, ms_ptr->m_ptr->fy, ms_ptr->m_ptr->fx, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx))
+        ms_ptr->ability_flags.reset(RF_ABILITY::BR_LITE);
 
-    if (((ms_ptr->f6 & RF6_SPECIAL) != 0) && (ms_ptr->m_ptr->r_idx != MON_ROLENTO) && (ms_ptr->r_ptr->d_char != 'B'))
-        ms_ptr->f6 &= ~(RF6_SPECIAL);
+    if (ms_ptr->ability_flags.has(RF_ABILITY::SPECIAL) && (ms_ptr->m_ptr->r_idx != MON_ROLENTO) && (ms_ptr->r_ptr->d_char != 'B'))
+        ms_ptr->ability_flags.reset(RF_ABILITY::SPECIAL);
 
     check_darkness(target_ptr, ms_ptr);
     check_stupid(ms_ptr);
     check_arena(target_ptr, ms_ptr);
     if (target_ptr->phase_out && !one_in_(3))
-        ms_ptr->f6 &= ~(RF6_HEAL);
+        ms_ptr->ability_flags.reset(RF_ABILITY::HEAL);
 
     check_riding(target_ptr, ms_ptr);
     check_pet(target_ptr, ms_ptr);
index 70dc732..7910fc7 100644 (file)
@@ -14,9 +14,8 @@ melee_spell_type *initialize_melee_spell_type(player_type *target_ptr, melee_spe
     ms_ptr->y = 0;
     ms_ptr->x = 0;
     ms_ptr->target_idx = 0;
-    ms_ptr->thrown_spell = 0;
+    ms_ptr->thrown_spell = RF_ABILITY::MAX;
     ms_ptr->dam = 0;
-    ms_ptr->num = 0;
     floor_type *floor_ptr = target_ptr->current_floor_ptr;
     ms_ptr->m_ptr = &floor_ptr->m_list[m_idx];
     ms_ptr->t_ptr = NULL;
index 495d79c..d4a8e48 100644 (file)
@@ -2,16 +2,19 @@
 
 #include "system/angband.h"
 #include "system/monster-type-definition.h"
+#include "monster-race/race-ability-flags.h"
+#include "util/flag-group.h"
+
+#include <vector>
 
 typedef struct melee_spell_type {
     MONSTER_IDX m_idx;
     POSITION y;
     POSITION x;
     MONSTER_IDX target_idx;
-    int thrown_spell;
+    RF_ABILITY thrown_spell;
     HIT_POINT dam;
-    byte spell[96];
-    byte num;
+    std::vector<RF_ABILITY> spells;
     GAME_TEXT m_name[160];
 #ifdef JP
 #else
@@ -26,9 +29,7 @@ typedef struct melee_spell_type {
     bool pet;
     bool in_no_magic_dungeon;
     bool can_remember;
-    BIT_FLAGS f4;
-    BIT_FLAGS f5;
-    BIT_FLAGS f6;
+    FlagGroup<RF_ABILITY> ability_flags;
 } melee_spell_type;
 
 melee_spell_type *initialize_melee_spell_type(player_type *target_ptr, melee_spell_type *ms_ptr, MONSTER_IDX m_idx);
index e0e0ba3..608d0d6 100644 (file)
@@ -54,7 +54,7 @@ static void process_special_melee_spell(player_type *target_ptr, melee_spell_typ
     is_special_magic &= current_world_ptr->timewalk_m_idx == 0;
     is_special_magic &= !target_ptr->blind;
     is_special_magic &= target_ptr->pclass == CLASS_IMITATOR;
-    is_special_magic &= ms_ptr->thrown_spell != 167; /* Not RF6_SPECIAL */
+    is_special_magic &= ms_ptr->thrown_spell != RF_ABILITY::SPECIAL;
     if (!is_special_magic)
         return;
 
@@ -66,7 +66,7 @@ static void process_special_melee_spell(player_type *target_ptr, melee_spell_typ
         }
     }
 
-    target_ptr->mane_spell[target_ptr->mane_num] = ms_ptr->thrown_spell - RF4_SPELL_START;
+    target_ptr->mane_spell[target_ptr->mane_num] = ms_ptr->thrown_spell;
     target_ptr->mane_dam[target_ptr->mane_num] = ms_ptr->dam;
     target_ptr->mane_num++;
     target_ptr->new_mane = TRUE;
@@ -79,27 +79,10 @@ static void process_rememberance(melee_spell_type *ms_ptr)
     if (!ms_ptr->can_remember)
         return;
 
-    if (ms_ptr->thrown_spell < RF4_SPELL_START + RF4_SPELL_SIZE) {
-        ms_ptr->r_ptr->r_flags4 |= (1UL << (ms_ptr->thrown_spell - RF4_SPELL_START));
-        if (ms_ptr->r_ptr->r_cast_spell < MAX_UCHAR)
-            ms_ptr->r_ptr->r_cast_spell++;
+    ms_ptr->r_ptr->r_ability_flags.set(ms_ptr->thrown_spell);
 
-        return;
-    }
-
-    if (ms_ptr->thrown_spell < RF5_SPELL_START + RF5_SPELL_SIZE) {
-        ms_ptr->r_ptr->r_flags5 |= (1UL << (ms_ptr->thrown_spell - RF5_SPELL_START));
-        if (ms_ptr->r_ptr->r_cast_spell < MAX_UCHAR)
-            ms_ptr->r_ptr->r_cast_spell++;
-
-        return;
-    }
-
-    if (ms_ptr->thrown_spell < RF6_SPELL_START + RF6_SPELL_SIZE) {
-        ms_ptr->r_ptr->r_flags6 |= (1UL << (ms_ptr->thrown_spell - RF6_SPELL_START));
-        if (ms_ptr->r_ptr->r_cast_spell < MAX_UCHAR)
-            ms_ptr->r_ptr->r_cast_spell++;
-    }
+    if (ms_ptr->r_ptr->r_cast_spell < MAX_UCHAR)
+        ms_ptr->r_ptr->r_cast_spell++;
 }
 
 static void describe_melee_spell(player_type *target_ptr, melee_spell_type *ms_ptr)
@@ -134,7 +117,7 @@ bool monst_spell_monst(player_type *target_ptr, MONSTER_IDX m_idx)
         return FALSE;
 
     describe_melee_spell(target_ptr, ms_ptr);
-    ms_ptr->thrown_spell = ms_ptr->spell[randint0(ms_ptr->num)];
+    ms_ptr->thrown_spell = ms_ptr->spells[randint0(ms_ptr->spells.size())];
     if (target_ptr->riding && (m_idx == target_ptr->riding))
         disturb(target_ptr, TRUE, TRUE);
 
index c38661d..687c1ad 100644 (file)
@@ -318,7 +318,7 @@ spells_type get_element_type(int realm_idx, int n)
  * @return 属性タイプ
  */
 static spells_type get_element_spells_type(player_type *caster_ptr, int n) {
-    auto realm = element_types.at(static_cast<ElementRealm>(caster_ptr->realm1));
+    auto realm = element_types.at(static_cast<ElementRealm>(caster_ptr->element));
     auto t = realm.type.at(n);
     if (realm.extra.find(t) != realm.extra.end()) {
         if (randint0(100) < caster_ptr->lev * 2)
@@ -357,7 +357,7 @@ concptr get_element_name(int realm_idx, int n)
  */
 static concptr get_element_tip(player_type *caster_ptr, int spell_idx)
 {
-    auto realm = static_cast<ElementRealm>(caster_ptr->realm1);
+    auto realm = static_cast<ElementRealm>(caster_ptr->element);
     auto spell = static_cast<ElementSpells>(spell_idx);
     auto elem = element_powers.at(spell).elem;
     return format(element_tips.at(spell).data(), element_types.at(realm).name[elem].data());
@@ -774,7 +774,7 @@ bool get_element_power(player_type *caster_ptr, SPELL_IDX *sn, bool only_browse)
                     } else
                         sprintf(desc, "  %c) ", I2A(i));
 
-                    concptr s = get_element_name(caster_ptr->realm1, elem);
+                    concptr s = get_element_name(caster_ptr->element, elem);
                     sprintf(name, spell.name, s);
                     strcat(desc,
                         format("%-30s%2d %4d %3d%%%s", name, spell.min_lev, mana_cost, chance, comment));
@@ -808,7 +808,7 @@ bool get_element_power(player_type *caster_ptr, SPELL_IDX *sn, bool only_browse)
             char tmp_val[160];
             elem = get_elemental_elem(caster_ptr, i);
             spell = get_elemental_info(caster_ptr, i);
-            (void)sprintf(name, spell.name, get_element_name(caster_ptr->realm1, elem));
+            (void)sprintf(name, spell.name, get_element_name(caster_ptr->element, elem));
             (void)strnfmt(tmp_val, 78, _("%sを使いますか?", "Use %s? "), name);
             if (!get_check(tmp_val))
                 continue;
@@ -873,7 +873,7 @@ static bool try_cast_element_spell(player_type *caster_ptr, SPELL_IDX spell_idx,
         msg_print(_("元素の力が制御できない氾流となって解放された!",
             "Elemental power unleashes its power in an uncontrollable storm!"));
         project(caster_ptr, PROJECT_WHO_UNCTRL_POWER, 2 + plev / 10, caster_ptr->y, caster_ptr->x, plev * 2,
-            get_element_types(caster_ptr->realm1)[0],
+            get_element_types(caster_ptr->element)[0],
             PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM, -1);
         caster_ptr->csp = MAX(0, caster_ptr->csp - caster_ptr->msp * 10 / (20 + randint1(10)));
 
@@ -1019,8 +1019,8 @@ bool is_elemental_genocide_effective(monster_race *r_ptr, spells_type type)
  */
 process_result effect_monster_elemental_genocide(player_type *caster_ptr, effect_monster_type *em_ptr)
 {
-    auto type = get_element_type(caster_ptr->realm1, 0);
-    auto name = get_element_name(caster_ptr->realm1, 0);
+    auto type = get_element_type(caster_ptr->element, 0);
+    auto name = get_element_name(caster_ptr->element, 0);
     bool b = is_elemental_genocide_effective(em_ptr->r_ptr, type);
 
     if (em_ptr->seen_msg)
@@ -1062,7 +1062,7 @@ bool has_element_resist(player_type *creature_ptr, ElementRealm realm, PLAYER_LE
     if (creature_ptr->pclass != CLASS_ELEMENTALIST)
         return FALSE;
 
-    auto prealm = static_cast<ElementRealm>(creature_ptr->realm1);
+    auto prealm = static_cast<ElementRealm>(creature_ptr->element);
     return (prealm == realm && creature_ptr->lev >= lev);
 }
 
@@ -1243,7 +1243,7 @@ byte select_element_realm(player_type *creature_ptr)
 void switch_element_racial(player_type *creature_ptr, rc_type *rc_ptr)
 {
     auto plev = creature_ptr->lev;
-    auto realm = static_cast<ElementRealm>(creature_ptr->realm1);
+    auto realm = static_cast<ElementRealm>(creature_ptr->element);
     switch (realm) {
     case ElementRealm::FIRE:
         strcpy(rc_ptr->power_desc[rc_ptr->num].racial_name, _("ライト・エリア", "Light area"));
@@ -1326,7 +1326,7 @@ static bool door_to_darkness(player_type *caster_ptr, POSITION dist);
  */
 bool switch_element_execution(player_type *creature_ptr)
 {
-    auto realm = static_cast<ElementRealm>(creature_ptr->realm1);
+    auto realm = static_cast<ElementRealm>(creature_ptr->element);
     PLAYER_LEVEL plev = creature_ptr->lev;
     DIRECTION dir;
 
index c136242..e6eb849 100644 (file)
 #include "grid/grid.h"
 #include "monster-floor/monster-safety-hiding.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
+#include "monster-race/race-ability-mask.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/monster-flag-types.h"
 #include "monster/monster-info.h"
 #include "monster/monster-status.h"
-#include "mspell/mspell-mask-definitions.h"
 #include "player/player-status-flags.h"
 #include "system/floor-type-definition.h"
 #include "target/projection-path-calculator.h"
@@ -182,7 +179,7 @@ static void sweep_movable_grid(player_type *target_ptr, MONSTER_IDX m_idx, POSIT
     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
     monster_race *r_ptr = &r_info[m_ptr->r_idx];
 
-    if (r_ptr->flags4 & (RF4_ATTACK_MASK) || r_ptr->a_ability_flags1 & (RF5_ATTACK_MASK) || r_ptr->a_ability_flags2 & (RF6_ATTACK_MASK)) {
+    if (r_ptr->ability_flags.has_any_of(RF_ABILITY_ATTACK_MASK)) {
         if (sweep_ranged_attack_grid(target_ptr, m_idx, yp, xp))
             return;
     }
@@ -360,7 +357,7 @@ bool get_movable_grid(player_type *target_ptr, MONSTER_IDX m_idx, DIRECTION *mm)
 
             if (floor_ptr->grid_array[target_ptr->y][target_ptr->x].info & CAVE_ROOM)
                 room -= 2;
-            if (!r_ptr->flags4 && !r_ptr->a_ability_flags1 && !r_ptr->a_ability_flags2)
+            if (r_ptr->ability_flags.none())
                 room -= 2;
 
             if (room < (8 * (target_ptr->chp + target_ptr->csp)) / (target_ptr->mhp + target_ptr->msp)) {
index d8c3ec3..93c8e32 100644 (file)
@@ -65,9 +65,8 @@ static void produce_quantum_effect(player_type *target_ptr, MONSTER_IDX m_idx, b
         msg_print(_("量子的効果が起こった!", "A decoherence was produced!"));
 
     bool target = one_in_(2);
-    const int blink = 32 * 5 + 4;
     if (target)
-        (void)monspell_to_monster(target_ptr, blink, m_ptr->fy, m_ptr->fx, m_idx, m_idx, TRUE);
+        (void)monspell_to_monster(target_ptr, RF_ABILITY::BLINK, m_ptr->fy, m_ptr->fx, m_idx, m_idx, TRUE);
     else
         teleport_player_away(m_idx, target_ptr, 10, TRUE);
 }
index 290853d..b61b89a 100644 (file)
@@ -3,19 +3,16 @@
 #include "monster-attack/monster-attack-effect.h"
 #include "monster-attack/monster-attack-types.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
+#include "monster-race/race-ability-mask.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-flags4.h"
 #include "monster-race/race-flags7.h"
 #include "monster-race/race-flags8.h"
 #include "monster-race/race-indice-types.h"
 #include "monster/monster-list.h"
 #include "monster/monster-util.h"
-#include "mspell/mspell-mask-definitions.h"
 #include "system/floor-type-definition.h"
 #include "util/bit-flags-calculator.h"
 #include "util/string-processor.h"
@@ -27,7 +24,7 @@ int vault_aux_race;
 char vault_aux_char;
 
 /*! ブレス属性に基づくドラゴンpit生成時条件マスク / Breath mask for "monster pit (dragon)" */
-BIT_FLAGS vault_aux_dragon_mask4;
+FlagGroup<RF_ABILITY> vault_aux_dragon_mask4;
 
 /*!
  * @brief pit/nestの基準となる単種モンスターを決める /
@@ -64,24 +61,25 @@ void vault_prep_dragon(player_type *player_ptr)
     /* Unused */
     (void)player_ptr;
 
+    vault_aux_dragon_mask4.clear();
     switch (randint0(6)) {
     case 0: /* Black */
-        vault_aux_dragon_mask4 = RF4_BR_ACID;
+        vault_aux_dragon_mask4.set(RF_ABILITY::BR_ACID);
         break;
     case 1: /* Blue */
-        vault_aux_dragon_mask4 = RF4_BR_ELEC;
+        vault_aux_dragon_mask4.set(RF_ABILITY::BR_ELEC);
         break;
     case 2: /* Red */
-        vault_aux_dragon_mask4 = RF4_BR_FIRE;
+        vault_aux_dragon_mask4.set(RF_ABILITY::BR_FIRE);
         break;
     case 3: /* White */
-        vault_aux_dragon_mask4 = RF4_BR_COLD;
+        vault_aux_dragon_mask4.set(RF_ABILITY::BR_COLD);
         break;
     case 4: /* Green */
-        vault_aux_dragon_mask4 = RF4_BR_POIS;
+        vault_aux_dragon_mask4.set(RF_ABILITY::BR_POIS);
         break;
     default: /* Multi-hued */
-        vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS);
+        vault_aux_dragon_mask4.set({ RF_ABILITY::BR_ACID, RF_ABILITY::BR_ELEC, RF_ABILITY::BR_FIRE, RF_ABILITY::BR_COLD, RF_ABILITY::BR_POIS });
         break;
     }
 }
@@ -325,13 +323,13 @@ bool vault_aux_lite(player_type *player_ptr, MONRACE_IDX r_idx)
     if (!vault_monster_okay(player_ptr, r_idx))
         return FALSE;
 
-    if (none_bits(r_ptr->flags4, RF4_BR_LITE) && none_bits(r_ptr->a_ability_flags1, RF5_BA_LITE))
+    if (r_ptr->ability_flags.has_none_of({ RF_ABILITY::BR_LITE, RF_ABILITY::BA_LITE }))
         return FALSE;
 
     if (any_bits(r_ptr->flags2, (RF2_PASS_WALL | RF2_KILL_WALL)))
         return FALSE;
 
-    if (any_bits(r_ptr->flags4, RF4_BR_DISI))
+    if (r_ptr->ability_flags.has(RF_ABILITY::BR_DISI))
         return FALSE;
 
     return TRUE;
@@ -346,7 +344,7 @@ bool vault_aux_shards(player_type *player_ptr, MONRACE_IDX r_idx)
     if (!vault_monster_okay(player_ptr, r_idx))
         return FALSE;
 
-    if (none_bits(r_ptr->flags4, RF4_BR_SHAR))
+    if (r_ptr->ability_flags.has_not(RF_ABILITY::BR_SHAR))
         return FALSE;
 
     return TRUE;
@@ -639,10 +637,10 @@ bool vault_aux_dragon(player_type *player_ptr, MONRACE_IDX r_idx)
     if (any_bits(r_ptr->flags3, RF3_UNDEAD))
         return FALSE;
 
-    BIT_FLAGS flags = RF4_BREATH_MASK;
-    reset_bits(flags, vault_aux_dragon_mask4);
+    auto flags = RF_ABILITY_BREATH_MASK;
+    flags.reset(vault_aux_dragon_mask4);
 
-    if (any_bits(r_ptr->flags4, flags) || !all_bits(r_ptr->flags4, vault_aux_dragon_mask4))
+    if (r_ptr->ability_flags.has_any_of(flags) || !r_ptr->ability_flags.has_all_of(vault_aux_dragon_mask4))
         return FALSE;
 
     return TRUE;
@@ -845,16 +843,14 @@ bool monster_can_entry_arena(player_type *player_ptr, MONRACE_IDX r_idx)
             dam += r_ptr->blow[i].d_dice;
     }
 
-    if (!dam && none_bits(r_ptr->flags4, (RF4_BOLT_MASK | RF4_BEAM_MASK | RF4_BALL_MASK | RF4_BREATH_MASK))
-        && none_bits(r_ptr->a_ability_flags1, (RF5_BOLT_MASK | RF5_BEAM_MASK | RF5_BALL_MASK | RF5_BREATH_MASK))
-        && none_bits(r_ptr->a_ability_flags2, (RF6_BOLT_MASK | RF6_BEAM_MASK | RF6_BALL_MASK | RF6_BREATH_MASK)))
+    if (!dam && r_ptr->ability_flags.has_none_of(RF_ABILITY_BOLT_MASK | RF_ABILITY_BEAM_MASK | RF_ABILITY_BALL_MASK | RF_ABILITY_BREATH_MASK))
         return FALSE;
 
     return TRUE;
 }
 
 /*!
- * @brief モンスターが人形のベースにできるかを返す
+ * モンスターが人形のベースにできるかを返す
  * @param r_idx チェックしたいモンスター種族のID
  * @return 人形にできるならTRUEを返す
  */
index 01bbb86..4bccda1 100644 (file)
@@ -4,7 +4,7 @@
 
 extern int vault_aux_race;
 extern char vault_aux_char;
-extern BIT_FLAGS vault_aux_dragon_mask4;
+extern FlagGroup<RF_ABILITY> vault_aux_dragon_mask4;
 
 bool mon_hook_quest(player_type *player_ptr, MONRACE_IDX r_idx);
 bool mon_hook_dungeon(player_type *player_ptr, MONRACE_IDX r_idx);
index 462df28..bd56dcd 100644 (file)
@@ -1,7 +1,7 @@
 #include "monster-race/monster-race.h"
 
 /* The monster race arrays */
-monster_race *r_info;
+std::vector<monster_race> r_info;
 
 /* Maximum number of monsters in r_info.txt */
 MONRACE_IDX max_r_idx;
index 0f2a196..feefc8c 100644 (file)
@@ -3,5 +3,7 @@
 #include "system/angband.h"
 #include "system/monster-race-definition.h"
 
-extern monster_race *r_info;
+#include <vector>
+
+extern std::vector<monster_race> r_info;
 extern MONRACE_IDX max_r_idx;
diff --git a/src/monster-race/race-ability-flags.h b/src/monster-race/race-ability-flags.h
new file mode 100644 (file)
index 0000000..1da65b2
--- /dev/null
@@ -0,0 +1,103 @@
+#pragma once
+
+enum class RF_ABILITY {
+    SHRIEK = 0, /*!< モンスター能力: 叫ぶ / Shriek for help */
+    XXX1 = 1, /*!< モンスター能力: 未使用 / XXX */
+    DISPEL = 2, /*!< モンスター能力: 魔力消去 / Dispel magic */
+    ROCKET = 3, /*!< モンスター能力: ロケット / TY: Rocket */
+    SHOOT = 4, /*!< モンスター能力: 射撃/ Fire missiles */
+    XXX2 = 5, /*!< モンスター能力: 未使用 / XXX */
+    XXX3 = 6, /*!< モンスター能力: 未使用 / XXX */
+    XXX4 = 7, /*!< モンスター能力: 未使用 / XXX */
+    BR_ACID = 8, /*!< モンスター能力: 酸のブレス / Breathe Acid */
+    BR_ELEC = 9, /*!< モンスター能力: 電撃のブレス / Breathe Elec */
+    BR_FIRE = 10, /*!< モンスター能力: 火炎のブレス / Breathe Fire */
+    BR_COLD = 11, /*!< モンスター能力: 冷気のブレス / Breathe Cold */
+    BR_POIS = 12, /*!< モンスター能力: 毒のブレス / Breathe Poison */
+    BR_NETH = 13, /*!< モンスター能力: 地獄のブレス / Breathe Nether */
+    BR_LITE = 14, /*!< モンスター能力: 閃光のブレス / Breathe Lite */
+    BR_DARK = 15, /*!< モンスター能力: 暗黒のブレス / Breathe Dark */
+    BR_CONF = 16, /*!< モンスター能力: 混乱のブレス / Breathe Confusion */
+    BR_SOUN = 17, /*!< モンスター能力: 轟音のブレス / Breathe Sound */
+    BR_CHAO = 18, /*!< モンスター能力: カオスのブレス / Breathe Chaos */
+    BR_DISE = 19, /*!< モンスター能力: 劣化のブレス / Breathe Disenchant */
+    BR_NEXU = 20, /*!< モンスター能力: 因果混乱のブレス / Breathe Nexus */
+    BR_TIME = 21, /*!< モンスター能力: 時間逆転のブレス / Breathe Time */
+    BR_INER = 22, /*!< モンスター能力: 遅鈍のブレス / Breathe Inertia */
+    BR_GRAV = 23, /*!< モンスター能力: 重力のブレス / Breathe Gravity */
+    BR_SHAR = 24, /*!< モンスター能力: 破片のブレス / Breathe Shards */
+    BR_PLAS = 25, /*!< モンスター能力: プラズマのブレス / Breathe Plasma */
+    BR_WALL = 26, /*!< モンスター能力: フォースのブレス / Breathe Force */
+    BR_MANA = 27, /*!< モンスター能力: 魔力のブレス / Breathe Mana */
+    BA_NUKE = 28, /*!< モンスター能力: 放射能球 / TY: Nuke Ball */
+    BR_NUKE = 29, /*!< モンスター能力: 放射性廃棄物のブレス / TY: Toxic Breath */
+    BA_CHAO = 30, /*!< モンスター能力: ログルス球 / TY: Logrus Ball */
+    BR_DISI = 31, /*!< モンスター能力: 分解のブレス / Breathe Disintegration */
+
+    BA_ACID = 32, /*!< モンスター能力: アシッド・ボール / Acid Ball */
+    BA_ELEC = 33, /*!< モンスター能力: サンダー・ボール / Elec Ball */
+    BA_FIRE = 34, /*!< モンスター能力: ファイア・ボール / Fire Ball */
+    BA_COLD = 35, /*!< モンスター能力: アイス・ボール / Cold Ball */
+    BA_POIS = 36, /*!< モンスター能力: 悪臭雲 / Poison Ball */
+    BA_NETH = 37, /*!< モンスター能力: 地獄球 / Nether Ball */
+    BA_WATE = 38, /*!< モンスター能力: ウォーター・ボール / Water Ball */
+    BA_MANA = 39, /*!< モンスター能力: 魔力の嵐 / Mana Storm */
+    BA_DARK = 40, /*!< モンスター能力: 暗黒の嵐 / Darkness Storm */
+    DRAIN_MANA = 41, /*!< モンスター能力: 魔力吸収 / Drain Mana */
+    MIND_BLAST = 42, /*!< モンスター能力: 精神攻撃 / Blast Mind */
+    BRAIN_SMASH = 43, /*!< モンスター能力: 脳攻撃 / Smash Brain */
+    CAUSE_1 = 44, /*!< モンスター能力: 軽傷の呪い / Cause Light Wound */
+    CAUSE_2 = 45, /*!< モンスター能力: 重症の頃い / Cause Serious Wound */
+    CAUSE_3 = 46, /*!< モンスター能力: 致命傷の呪い / Cause Critical Wound */
+    CAUSE_4 = 47, /*!< モンスター能力: 秘孔を突く / Cause Mortal Wound */
+    BO_ACID = 48, /*!< モンスター能力: アシッド・ボルト / Acid Bolt */
+    BO_ELEC = 49, /*!< モンスター能力: サンダー・ボルト / Elec Bolt */
+    BO_FIRE = 50, /*!< モンスター能力: ファイア・ボルト / Fire Bolt */
+    BO_COLD = 51, /*!< モンスター能力: アイス・ボルト / Cold Bolt */
+    BA_LITE = 52, /*!< モンスター能力: スター・バースト / StarBurst */
+    BO_NETH = 53, /*!< モンスター能力: 地獄の矢 / Nether Bolt */
+    BO_WATE = 54, /*!< モンスター能力: ウォーター・ボルト / Water Bolt */
+    BO_MANA = 55, /*!< モンスター能力: 魔力の矢 / Mana Bolt */
+    BO_PLAS = 56, /*!< モンスター能力: プラズマ・ボルト / Plasma Bolt */
+    BO_ICEE = 57, /*!< モンスター能力: 極寒の矢 / Ice Bolt */
+    MISSILE = 58, /*!< モンスター能力: マジック・ミサイルt / Magic Missile */
+    SCARE = 59, /*!< モンスター能力: 恐慌 / Frighten Player */
+    BLIND = 60, /*!< モンスター能力: 盲目 / Blind Player */
+    CONF = 61, /*!< モンスター能力: 混乱 / Confuse Player */
+    SLOW = 62, /*!< モンスター能力: 減速 / Slow Player */
+    HOLD = 63, /*!< モンスター能力: 麻痺 / Paralyze Player */
+
+    HASTE = 64, /* Speed self */
+    HAND_DOOM = 65, /* Hand of Doom */
+    HEAL = 66, /* Heal self */
+    INVULNER = 67, /* INVULNERABILITY! */
+    BLINK = 68, /* Teleport Short */
+    TPORT = 69, /* Teleport Long */
+    WORLD = 70, /* world */
+    SPECIAL = 71, /* Special Attack */
+    TELE_TO = 72, /* Move player to monster */
+    TELE_AWAY = 73, /* Move player far away */
+    TELE_LEVEL = 74, /* Move player vertically */
+    PSY_SPEAR = 75, /* Psyco-spear */
+    DARKNESS = 76, /* Create Darkness */
+    TRAPS = 77, /* Create Traps */
+    FORGET = 78, /* Cause amnesia */
+    RAISE_DEAD = 79, /* Raise Dead */
+    S_KIN = 80, /* Summon "kin" */
+    S_CYBER = 81, /* Summon Cyberdemons! */
+    S_MONSTER = 82, /* Summon Monster */
+    S_MONSTERS = 83, /* Summon Monsters */
+    S_ANT = 84, /* Summon Ants */
+    S_SPIDER = 85, /* Summon Spiders */
+    S_HOUND = 86, /* Summon Hounds */
+    S_HYDRA = 87, /* Summon Hydras */
+    S_ANGEL = 88, /* Summon Angel */
+    S_DEMON = 89, /* Summon Demon */
+    S_UNDEAD = 90, /* Summon Undead */
+    S_DRAGON = 91, /* Summon Dragon */
+    S_HI_UNDEAD = 92, /* Summon Greater Undead */
+    S_HI_DRAGON = 93, /* Summon Ancient Dragon */
+    S_AMBERITES = 94, /* Summon Amberites */
+    S_UNIQUE = 95, /* Summon Unique Monster */
+    MAX,
+};
diff --git a/src/monster-race/race-ability-mask.cpp b/src/monster-race/race-ability-mask.cpp
new file mode 100644 (file)
index 0000000..abd57f3
--- /dev/null
@@ -0,0 +1,99 @@
+#include "monster-race/race-ability-mask.h"
+
+// clang-format off
+/* "summon" spells currently "summon" spells are included in "intelligent" and "indirect" */
+const FlagGroup<RF_ABILITY> RF_ABILITY_SUMMON_MASK = {
+    RF_ABILITY::S_KIN, RF_ABILITY::S_CYBER, RF_ABILITY::S_MONSTER, RF_ABILITY::S_MONSTERS,
+    RF_ABILITY::S_ANT, RF_ABILITY::S_SPIDER, RF_ABILITY::S_HOUND, RF_ABILITY::S_HYDRA,
+    RF_ABILITY::S_ANGEL, RF_ABILITY::S_DEMON, RF_ABILITY::S_UNDEAD, RF_ABILITY::S_DRAGON,
+    RF_ABILITY::S_HI_UNDEAD, RF_ABILITY::S_HI_DRAGON, RF_ABILITY::S_AMBERITES, RF_ABILITY::S_UNIQUE,
+};
+
+/* Choose "intelligent" spells when desperate Including "summon" spells */
+const FlagGroup<RF_ABILITY> RF_ABILITY_INT_MASK =
+    FlagGroup<RF_ABILITY>(RF_ABILITY_SUMMON_MASK).set({
+    RF_ABILITY::DISPEL, RF_ABILITY::HOLD, RF_ABILITY::SLOW, RF_ABILITY::CONF,
+    RF_ABILITY::BLIND, RF_ABILITY::SCARE, RF_ABILITY::BLINK, RF_ABILITY::TPORT,
+    RF_ABILITY::TELE_LEVEL, RF_ABILITY::TELE_AWAY, RF_ABILITY::HEAL, RF_ABILITY::INVULNER,
+    RF_ABILITY::HASTE, RF_ABILITY::TRAPS,
+});
+
+/* Spells that cannot be used while player riding on the monster */
+const FlagGroup<RF_ABILITY> RF_ABILITY_RIDING_MASK = {
+    RF_ABILITY::SHRIEK, RF_ABILITY::BLINK, RF_ABILITY::TPORT, RF_ABILITY::TRAPS,
+    RF_ABILITY::DARKNESS, RF_ABILITY::SPECIAL,
+};
+
+/*
+ * "bolt" spells that may hurt fellow monsters
+ * Currently "bolt" spells are included in "attack"
+ */
+const FlagGroup<RF_ABILITY> RF_ABILITY_BOLT_MASK = {
+    RF_ABILITY::ROCKET, RF_ABILITY::SHOOT, RF_ABILITY::BO_ACID, RF_ABILITY::BO_ELEC,
+    RF_ABILITY::BO_FIRE, RF_ABILITY::BO_COLD, RF_ABILITY::BO_NETH, RF_ABILITY::BO_WATE,
+    RF_ABILITY::BO_MANA, RF_ABILITY::BO_PLAS, RF_ABILITY::BO_ICEE, RF_ABILITY::MISSILE,
+};
+
+/*
+ * "beam" spells that may hurt fellow monsters
+ * Currently "beam" spells are included in "attack"
+ */
+const FlagGroup<RF_ABILITY> RF_ABILITY_BEAM_MASK = {
+    RF_ABILITY::PSY_SPEAR,
+};
+
+/*
+ * "ball" spells with radius 4 that may hurt friends
+ * Currently "radius 4 ball" spells are included in "ball"
+ */
+const FlagGroup<RF_ABILITY> RF_ABILITY_BIG_BALL_MASK = {
+    RF_ABILITY::BA_CHAO, RF_ABILITY::BA_LITE, RF_ABILITY::BA_DARK, RF_ABILITY::BA_WATE,
+    RF_ABILITY::BA_MANA,
+};
+
+/*
+ * "breath" spells that may hurt friends
+ * Currently "breath" spells are included in "ball" and "non-magic"
+ */
+const FlagGroup<RF_ABILITY> RF_ABILITY_BREATH_MASK = {
+    RF_ABILITY::BR_ACID, RF_ABILITY::BR_ELEC, RF_ABILITY::BR_FIRE, RF_ABILITY::BR_COLD,
+    RF_ABILITY::BR_POIS, RF_ABILITY::BR_NETH, RF_ABILITY::BR_LITE, RF_ABILITY::BR_DARK,
+    RF_ABILITY::BR_CONF, RF_ABILITY::BR_SOUN, RF_ABILITY::BR_CHAO, RF_ABILITY::BR_DISE,
+    RF_ABILITY::BR_NEXU, RF_ABILITY::BR_SHAR, RF_ABILITY::BR_TIME, RF_ABILITY::BR_INER,
+    RF_ABILITY::BR_GRAV, RF_ABILITY::BR_PLAS, RF_ABILITY::BR_WALL, RF_ABILITY::BR_MANA,
+    RF_ABILITY::BR_NUKE, RF_ABILITY::BR_DISI,
+};
+
+/*
+ * "ball" spells that may hurt friends
+ * Including "radius 4 ball" and "breath" spells
+ * Currently "ball" spells are included in "attack"
+ */
+const FlagGroup<RF_ABILITY> RF_ABILITY_BALL_MASK =
+    (RF_ABILITY_BIG_BALL_MASK | RF_ABILITY_BREATH_MASK).set({
+    RF_ABILITY::ROCKET, RF_ABILITY::BA_NUKE, RF_ABILITY::BA_ACID, RF_ABILITY::BA_ELEC,
+    RF_ABILITY::BA_FIRE, RF_ABILITY::BA_COLD, RF_ABILITY::BA_POIS, RF_ABILITY::BA_NETH,
+});
+
+/* "attack" spells including "bolt", "beam" and "ball" spells */
+const FlagGroup<RF_ABILITY> RF_ABILITY_ATTACK_MASK =
+    (RF_ABILITY_BOLT_MASK | RF_ABILITY_BEAM_MASK | RF_ABILITY_BALL_MASK).set({
+    RF_ABILITY::DISPEL, RF_ABILITY::DRAIN_MANA, RF_ABILITY::MIND_BLAST, RF_ABILITY::BRAIN_SMASH,
+    RF_ABILITY::CAUSE_1, RF_ABILITY::CAUSE_2, RF_ABILITY::CAUSE_3, RF_ABILITY::CAUSE_4,
+    RF_ABILITY::SCARE, RF_ABILITY::BLIND, RF_ABILITY::CONF, RF_ABILITY::SLOW, RF_ABILITY::HOLD,
+    RF_ABILITY::HAND_DOOM, RF_ABILITY::TELE_TO, RF_ABILITY::TELE_AWAY, RF_ABILITY::TELE_LEVEL,
+    RF_ABILITY::DARKNESS, RF_ABILITY::TRAPS, RF_ABILITY::FORGET,
+});
+
+/* "indirect" spells Including "summon" spells */
+const FlagGroup<RF_ABILITY> RF_ABILITY_INDIRECT_MASK =
+    FlagGroup<RF_ABILITY>(RF_ABILITY_SUMMON_MASK).set({
+    RF_ABILITY::SHRIEK, RF_ABILITY::HASTE, RF_ABILITY::HEAL, RF_ABILITY::INVULNER,
+    RF_ABILITY::BLINK, RF_ABILITY::WORLD, RF_ABILITY::TPORT, RF_ABILITY::RAISE_DEAD,
+});
+
+/* "non-magic" spells including "breath" spells */
+const FlagGroup<RF_ABILITY> RF_ABILITY_NOMAGIC_MASK =
+    FlagGroup<RF_ABILITY>(RF_ABILITY_BREATH_MASK).set({
+    RF_ABILITY::SHRIEK, RF_ABILITY::ROCKET, RF_ABILITY::SHOOT, RF_ABILITY::SPECIAL,
+});
diff --git a/src/monster-race/race-ability-mask.h b/src/monster-race/race-ability-mask.h
new file mode 100644 (file)
index 0000000..95065b5
--- /dev/null
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "monster-race/race-ability-flags.h"
+#include "util/flag-group.h"
+
+extern const FlagGroup<RF_ABILITY> RF_ABILITY_SUMMON_MASK;
+extern const FlagGroup<RF_ABILITY> RF_ABILITY_INT_MASK;
+extern const FlagGroup<RF_ABILITY> RF_ABILITY_RIDING_MASK;
+extern const FlagGroup<RF_ABILITY> RF_ABILITY_BOLT_MASK;
+extern const FlagGroup<RF_ABILITY> RF_ABILITY_BEAM_MASK;
+extern const FlagGroup<RF_ABILITY> RF_ABILITY_BIG_BALL_MASK;
+extern const FlagGroup<RF_ABILITY> RF_ABILITY_BREATH_MASK;
+extern const FlagGroup<RF_ABILITY> RF_ABILITY_BALL_MASK;
+extern const FlagGroup<RF_ABILITY> RF_ABILITY_ATTACK_MASK;
+extern const FlagGroup<RF_ABILITY> RF_ABILITY_INDIRECT_MASK;
+extern const FlagGroup<RF_ABILITY> RF_ABILITY_NOMAGIC_MASK;
diff --git a/src/monster-race/race-flags-ability1.h b/src/monster-race/race-flags-ability1.h
deleted file mode 100644 (file)
index b158b42..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-enum race_flags_ability {
-       RF5_BA_ACID = 0x00000001, /*!< モンスター能力: アシッド・ボール / Acid Ball */
-    RF5_BA_ELEC = 0x00000002, /*!< モンスター能力: サンダー・ボール / Elec Ball */
-    RF5_BA_FIRE = 0x00000004, /*!< モンスター能力: ファイア・ボール / Fire Ball */
-    RF5_BA_COLD = 0x00000008, /*!< モンスター能力: アイス・ボール / Cold Ball */
-    RF5_BA_POIS = 0x00000010, /*!< モンスター能力: 悪臭雲 / Poison Ball */
-    RF5_BA_NETH = 0x00000020, /*!< モンスター能力: 地獄球 / Nether Ball */
-    RF5_BA_WATE = 0x00000040, /*!< モンスター能力: ウォーター・ボール / Water Ball */
-    RF5_BA_MANA = 0x00000080, /*!< モンスター能力: 魔力の嵐 / Mana Storm */
-    RF5_BA_DARK = 0x00000100, /*!< モンスター能力: 暗黒の嵐 / Darkness Storm */
-    RF5_DRAIN_MANA = 0x00000200, /*!< モンスター能力: 魔力吸収 / Drain Mana */
-    RF5_MIND_BLAST = 0x00000400, /*!< モンスター能力: 精神攻撃 / Blast Mind */
-    RF5_BRAIN_SMASH = 0x00000800, /*!< モンスター能力: 脳攻撃 / Smash Brain */
-    RF5_CAUSE_1 = 0x00001000, /*!< モンスター能力: 軽傷の呪い / Cause Light Wound */
-    RF5_CAUSE_2 = 0x00002000, /*!< モンスター能力: 重症の頃い / Cause Serious Wound */
-    RF5_CAUSE_3 = 0x00004000, /*!< モンスター能力: 致命傷の呪い / Cause Critical Wound */
-    RF5_CAUSE_4 = 0x00008000, /*!< モンスター能力: 秘孔を突く / Cause Mortal Wound */
-    RF5_BO_ACID = 0x00010000, /*!< モンスター能力: アシッド・ボルト / Acid Bolt */
-    RF5_BO_ELEC = 0x00020000, /*!< モンスター能力: サンダー・ボルト / Elec Bolt */
-    RF5_BO_FIRE = 0x00040000, /*!< モンスター能力: ファイア・ボルト / Fire Bolt */
-    RF5_BO_COLD = 0x00080000, /*!< モンスター能力: アイス・ボルト / Cold Bolt */
-    RF5_BA_LITE = 0x00100000, /*!< モンスター能力: スター・バースト / StarBurst */
-    RF5_BO_NETH = 0x00200000, /*!< モンスター能力: 地獄の矢 / Nether Bolt */
-    RF5_BO_WATE = 0x00400000, /*!< モンスター能力: ウォーター・ボルト / Water Bolt */
-    RF5_BO_MANA = 0x00800000, /*!< モンスター能力: 魔力の矢 / Mana Bolt */
-    RF5_BO_PLAS = 0x01000000, /*!< モンスター能力: プラズマ・ボルト / Plasma Bolt */
-    RF5_BO_ICEE = 0x02000000, /*!< モンスター能力: 極寒の矢 / Ice Bolt */
-    RF5_MISSILE = 0x04000000, /*!< モンスター能力: マジック・ミサイルt / Magic Missile */
-    RF5_SCARE = 0x08000000, /*!< モンスター能力: 恐慌 / Frighten Player */
-    RF5_BLIND = 0x10000000, /*!< モンスター能力: 盲目 / Blind Player */
-    RF5_CONF = 0x20000000, /*!< モンスター能力: 混乱 / Confuse Player */
-    RF5_SLOW = 0x40000000, /*!< モンスター能力: 減速 / Slow Player */
-    RF5_HOLD = 0x80000000, /*!< モンスター能力: 麻痺 / Paralyze Player */
-};
diff --git a/src/monster-race/race-flags-ability2.h b/src/monster-race/race-flags-ability2.h
deleted file mode 100644 (file)
index d5fe779..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-enum race_flags_ability2 {
-       RF6_HASTE = 0x00000001, /* Speed self */
-    RF6_HAND_DOOM = 0x00000002, /* Hand of Doom */
-    RF6_HEAL = 0x00000004, /* Heal self */
-    RF6_INVULNER = 0x00000008, /* INVULNERABILITY! */
-    RF6_BLINK = 0x00000010, /* Teleport Short */
-    RF6_TPORT = 0x00000020, /* Teleport Long */
-    RF6_WORLD = 0x00000040, /* world */
-    RF6_SPECIAL = 0x00000080, /* Special Attack */
-    RF6_TELE_TO = 0x00000100, /* Move player to monster */
-    RF6_TELE_AWAY = 0x00000200, /* Move player far away */
-    RF6_TELE_LEVEL = 0x00000400, /* Move player vertically */
-    RF6_PSY_SPEAR = 0x00000800, /* Psyco-spear */
-    RF6_DARKNESS = 0x00001000, /* Create Darkness */
-    RF6_TRAPS = 0x00002000, /* Create Traps */
-    RF6_FORGET = 0x00004000, /* Cause amnesia */
-    RF6_RAISE_DEAD = 0x00008000, /* Raise Dead */
-    RF6_S_KIN = 0x00010000, /* Summon "kin" */
-    RF6_S_CYBER = 0x00020000, /* Summon Cyberdemons! */
-    RF6_S_MONSTER = 0x00040000, /* Summon Monster */
-    RF6_S_MONSTERS = 0x00080000, /* Summon Monsters */
-    RF6_S_ANT = 0x00100000, /* Summon Ants */
-    RF6_S_SPIDER = 0x00200000, /* Summon Spiders */
-    RF6_S_HOUND = 0x00400000, /* Summon Hounds */
-    RF6_S_HYDRA = 0x00800000, /* Summon Hydras */
-    RF6_S_ANGEL = 0x01000000, /* Summon Angel */
-    RF6_S_DEMON = 0x02000000, /* Summon Demon */
-    RF6_S_UNDEAD = 0x04000000, /* Summon Undead */
-    RF6_S_DRAGON = 0x08000000, /* Summon Dragon */
-    RF6_S_HI_UNDEAD = 0x10000000, /* Summon Greater Undead */
-    RF6_S_HI_DRAGON = 0x20000000, /* Summon Ancient Dragon */
-    RF6_S_AMBERITES = 0x40000000, /* Summon Amberites */
-    RF6_S_UNIQUE = 0x80000000, /* Summon Unique Monster */
-};
diff --git a/src/monster-race/race-flags4.h b/src/monster-race/race-flags4.h
deleted file mode 100644 (file)
index 9eee810..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-enum race_flags4 : u32b {
-    RF4_SHRIEK = 0x00000001, /*!< モンスター能力: 叫ぶ / Shriek for help */
-    RF4_XXX1 = 0x00000002, /*!< モンスター能力: 未使用 / XXX */
-    RF4_DISPEL = 0x00000004, /*!< モンスター能力: 魔力消去 / Dispel magic */
-    RF4_ROCKET = 0x00000008, /*!< モンスター能力: ロケット / TY: Rocket */
-    RF4_SHOOT = 0x00000010, /*!< モンスター能力: 射撃/ Fire missiles */
-    RF4_XXX2 = 0x00000020, /*!< モンスター能力: 未使用 / XXX */
-    RF4_XXX3 = 0x00000040, /*!< モンスター能力: 未使用 / XXX */
-    RF4_XXX4 = 0x00000080, /*!< モンスター能力: 未使用 / XXX */
-    RF4_BR_ACID = 0x00000100, /*!< モンスター能力: 酸のブレス / Breathe Acid */
-    RF4_BR_ELEC = 0x00000200, /*!< モンスター能力: 電撃のブレス / Breathe Elec */
-    RF4_BR_FIRE = 0x00000400, /*!< モンスター能力: 火炎のブレス / Breathe Fire */
-    RF4_BR_COLD = 0x00000800, /*!< モンスター能力: 冷気のブレス / Breathe Cold */
-    RF4_BR_POIS = 0x00001000, /*!< モンスター能力: 毒のブレス / Breathe Poison */
-    RF4_BR_NETH = 0x00002000, /*!< モンスター能力: 地獄のブレス / Breathe Nether */
-    RF4_BR_LITE = 0x00004000, /*!< モンスター能力: 閃光のブレス / Breathe Lite */
-    RF4_BR_DARK = 0x00008000, /*!< モンスター能力: 暗黒のブレス / Breathe Dark */
-    RF4_BR_CONF = 0x00010000, /*!< モンスター能力: 混乱のブレス / Breathe Confusion */
-    RF4_BR_SOUN = 0x00020000, /*!< モンスター能力: 轟音のブレス / Breathe Sound */
-    RF4_BR_CHAO = 0x00040000, /*!< モンスター能力: カオスのブレス / Breathe Chaos */
-    RF4_BR_DISE = 0x00080000, /*!< モンスター能力: 劣化のブレス / Breathe Disenchant */
-    RF4_BR_NEXU = 0x00100000, /*!< モンスター能力: 因果混乱のブレス / Breathe Nexus */
-    RF4_BR_TIME = 0x00200000, /*!< モンスター能力: 時間逆転のブレス / Breathe Time */
-    RF4_BR_INER = 0x00400000, /*!< モンスター能力: 遅鈍のブレス / Breathe Inertia */
-    RF4_BR_GRAV = 0x00800000, /*!< モンスター能力: 重力のブレス / Breathe Gravity */
-    RF4_BR_SHAR = 0x01000000, /*!< モンスター能力: 破片のブレス / Breathe Shards */
-    RF4_BR_PLAS = 0x02000000, /*!< モンスター能力: プラズマのブレス / Breathe Plasma */
-    RF4_BR_WALL = 0x04000000, /*!< モンスター能力: フォースのブレス / Breathe Force */
-    RF4_BR_MANA = 0x08000000, /*!< モンスター能力: 魔力のブレス / Breathe Mana */
-    RF4_BA_NUKE = 0x10000000, /*!< モンスター能力: 放射能球 / TY: Nuke Ball */
-    RF4_BR_NUKE = 0x20000000, /*!< モンスター能力: 放射性廃棄物のブレス / TY: Toxic Breath */
-    RF4_BA_CHAO = 0x40000000, /*!< モンスター能力: ログルス球 / TY: Logrus Ball */
-    RF4_BR_DISI = 0x80000000, /*!< モンスター能力: 分解のブレス / Breathe Disintegration */
-};
index f1a6b77..d4539b0 100644 (file)
@@ -44,10 +44,8 @@ old_race_flags *init_old_race_flags(old_race_flags *old_race_flags_ptr)
        old_race_flags_ptr->old_r_flags1 = 0L;
        old_race_flags_ptr->old_r_flags2 = 0L;
        old_race_flags_ptr->old_r_flags3 = 0L;
-       old_race_flags_ptr->old_r_flags4 = 0L;
-       old_race_flags_ptr->old_r_flags5 = 0L;
-       old_race_flags_ptr->old_r_flags6 = 0L;
        old_race_flags_ptr->old_r_flagsr = 0L;
+        old_race_flags_ptr->old_r_ability_flags.clear();
 
        old_race_flags_ptr->old_r_blows0 = 0;
        old_race_flags_ptr->old_r_blows1 = 0;
@@ -339,10 +337,8 @@ void save_old_race_flags(MONRACE_IDX monster_race_idx, old_race_flags *old_race_
        old_race_flags_ptr->old_r_flags1 = r_ptr->r_flags1;
        old_race_flags_ptr->old_r_flags2 = r_ptr->r_flags2;
        old_race_flags_ptr->old_r_flags3 = r_ptr->r_flags3;
-       old_race_flags_ptr->old_r_flags4 = r_ptr->r_flags4;
-       old_race_flags_ptr->old_r_flags5 = r_ptr->r_flags5;
-       old_race_flags_ptr->old_r_flags6 = r_ptr->r_flags6;
        old_race_flags_ptr->old_r_flagsr = r_ptr->r_flagsr;
+       old_race_flags_ptr->old_r_ability_flags = r_ptr->r_ability_flags;
 
        old_race_flags_ptr->old_r_blows0 = r_ptr->r_blows[0];
        old_race_flags_ptr->old_r_blows1 = r_ptr->r_blows[1];
index 0a6f767..44388d3 100644 (file)
@@ -8,6 +8,8 @@
 
 #include "system/angband.h"
 #include "system/monster-type-definition.h"
+#include "monster-race/race-ability-flags.h"
+#include "util/flag-group.h"
 
 typedef struct {
        bool see_m;
@@ -32,10 +34,8 @@ typedef struct {
        BIT_FLAGS old_r_flags1;
        BIT_FLAGS old_r_flags2;
        BIT_FLAGS old_r_flags3;
-       BIT_FLAGS old_r_flags4;
-       BIT_FLAGS old_r_flags5;
-       BIT_FLAGS old_r_flags6;
        BIT_FLAGS old_r_flagsr;
+       FlagGroup<RF_ABILITY> old_r_ability_flags;
 
        byte old_r_blows0;
        byte old_r_blows1;
index 734ae15..1884c54 100644 (file)
@@ -32,7 +32,6 @@
 #include "monster-floor/place-monster-types.h"
 #include "monster-floor/quantum-effect.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability2.h"
 #include "monster-race/race-flags-resistance.h"
 #include "monster-race/race-flags1.h"
 #include "monster-race/race-flags2.h"
@@ -367,7 +366,7 @@ void process_special(player_type *target_ptr, MONSTER_IDX m_idx)
 {
     monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
     monster_race *r_ptr = &r_info[m_ptr->r_idx];
-    if (((r_ptr->a_ability_flags2 & RF6_SPECIAL) == 0) || (m_ptr->r_idx != MON_OHMU) || target_ptr->current_floor_ptr->inside_arena || target_ptr->phase_out
+    if (r_ptr->ability_flags.has_not(RF_ABILITY::SPECIAL) || (m_ptr->r_idx != MON_OHMU) || target_ptr->current_floor_ptr->inside_arena || target_ptr->phase_out
         || (r_ptr->freq_spell == 0) || (randint1(100) > r_ptr->freq_spell))
         return;
 
@@ -383,7 +382,7 @@ void process_special(player_type *target_ptr, MONSTER_IDX m_idx)
     }
 
     if (count && is_original_ap_and_seen(target_ptr, m_ptr))
-        r_ptr->r_flags6 |= (RF6_SPECIAL);
+        r_ptr->r_ability_flags.set(RF_ABILITY::SPECIAL);
 }
 
 /*!
index e4d5c9d..2cbfb8e 100644 (file)
 #include "monster-floor/place-monster-types.h"
 #include "monster-race/monster-race-hook.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability2.h"
+#include "monster-race/race-ability-mask.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-flags4.h"
 #include "monster-race/race-flags7.h"
 #include "monster-race/race-flags8.h"
 #include "monster-race/race-indice-types.h"
@@ -43,7 +42,6 @@
 #include "monster/monster-status-setter.h" //!< @todo 相互依存. 後で何とかする.
 #include "monster/monster-update.h"
 #include "monster/smart-learn-types.h"
-#include "mspell/mspell-mask-definitions.h"
 #include "object-enchant/object-curse.h"
 #include "player-info/avatar.h"
 #include "player/player-personalities-types.h"
@@ -887,8 +885,9 @@ bool mon_take_hit(player_type *target_ptr, MONSTER_IDX m_idx, HIT_POINT dam, boo
             chg_virtue(target_ptr, V_JUSTICE, -1);
         }
 
-        if ((r_ptr->flags3 & RF3_ANIMAL) && !(r_ptr->flags3 & RF3_EVIL) && !(r_ptr->flags4 & ~(RF4_NOMAGIC_MASK))
-            && !(r_ptr->a_ability_flags1 & ~(RF5_NOMAGIC_MASK)) && !(r_ptr->a_ability_flags2 & ~(RF6_NOMAGIC_MASK))) {
+        auto magic_ability_flags = r_ptr->ability_flags;
+        magic_ability_flags.reset(RF_ABILITY_NOMAGIC_MASK);
+        if ((r_ptr->flags3 & RF3_ANIMAL) && !(r_ptr->flags3 & RF3_EVIL) && magic_ability_flags.none()) {
             if (one_in_(4))
                 chg_virtue(target_ptr, V_NATURE, -1);
         }
index 0b9c530..e83afc0 100644 (file)
@@ -150,8 +150,7 @@ void update_player_window(player_type *target_ptr, old_race_flags *old_race_flag
     monster_race *r_ptr;
     r_ptr = &r_info[target_ptr->monster_race_idx];
     if ((old_race_flags_ptr->old_r_flags1 != r_ptr->r_flags1) || (old_race_flags_ptr->old_r_flags2 != r_ptr->r_flags2)
-        || (old_race_flags_ptr->old_r_flags3 != r_ptr->r_flags3) || (old_race_flags_ptr->old_r_flags4 != r_ptr->r_flags4)
-        || (old_race_flags_ptr->old_r_flags5 != r_ptr->r_flags5) || (old_race_flags_ptr->old_r_flags6 != r_ptr->r_flags6)
+        || (old_race_flags_ptr->old_r_flags3 != r_ptr->r_flags3) || (old_race_flags_ptr->old_r_ability_flags != r_ptr->r_ability_flags)
         || (old_race_flags_ptr->old_r_flagsr != r_ptr->r_flagsr) || (old_race_flags_ptr->old_r_blows0 != r_ptr->r_blows[0])
         || (old_race_flags_ptr->old_r_blows1 != r_ptr->r_blows[1]) || (old_race_flags_ptr->old_r_blows2 != r_ptr->r_blows[2])
         || (old_race_flags_ptr->old_r_blows3 != r_ptr->r_blows[3]) || (old_race_flags_ptr->old_r_cast_spell != r_ptr->r_cast_spell)) {
index 3c456d9..57eab7f 100644 (file)
@@ -7,13 +7,10 @@
 #include "grid/grid.h"
 #include "monster-race/monster-race-hook.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
+#include "monster-race/race-ability-mask.h"
 #include "monster-race/race-flags1.h"
-#include "monster-race/race-flags4.h"
 #include "monster-race/race-flags7.h"
 #include "monster-race/race-indice-types.h"
-#include "mspell/mspell-mask-definitions.h"
 #include "spell/summon-types.h"
 #include "system/alloc-entries.h"
 #include "system/floor-type-definition.h"
@@ -62,18 +59,16 @@ static bool restrict_monster_to_dungeon(player_type *player_ptr, MONRACE_IDX r_i
     }
 
     if (d_ptr->flags1 & DF1_NO_MAGIC) {
-        if (r_idx != MON_CHAMELEON && r_ptr->freq_spell && !(r_ptr->flags4 & RF4_NOMAGIC_MASK) && !(r_ptr->a_ability_flags1 & RF5_NOMAGIC_MASK)
-            && !(r_ptr->a_ability_flags2 & RF6_NOMAGIC_MASK))
+        if (r_idx != MON_CHAMELEON && r_ptr->freq_spell && r_ptr->ability_flags.has_none_of(RF_ABILITY_NOMAGIC_MASK))
             return FALSE;
     }
 
     if (d_ptr->flags1 & DF1_NO_MELEE) {
         if (r_idx == MON_CHAMELEON)
             return TRUE;
-        if (!(r_ptr->flags4 & (RF4_BOLT_MASK | RF4_BEAM_MASK | RF4_BALL_MASK))
-            && !(r_ptr->a_ability_flags1
-                & (RF5_BOLT_MASK | RF5_BEAM_MASK | RF5_BALL_MASK | RF5_CAUSE_1 | RF5_CAUSE_2 | RF5_CAUSE_3 | RF5_CAUSE_4 | RF5_MIND_BLAST | RF5_BRAIN_SMASH))
-            && !(r_ptr->a_ability_flags2 & (RF6_BOLT_MASK | RF6_BEAM_MASK | RF6_BALL_MASK)))
+        if (r_ptr->ability_flags.has_none_of(RF_ABILITY_BOLT_MASK | RF_ABILITY_BEAM_MASK | RF_ABILITY_BALL_MASK)
+            && r_ptr->ability_flags.has_none_of(
+                { RF_ABILITY::CAUSE_1, RF_ABILITY::CAUSE_2, RF_ABILITY::CAUSE_3, RF_ABILITY::CAUSE_4, RF_ABILITY::MIND_BLAST, RF_ABILITY::BRAIN_SMASH }))
             return FALSE;
     }
 
@@ -106,18 +101,8 @@ static bool restrict_monster_to_dungeon(player_type *player_ptr, MONRACE_IDX r_i
                 return FALSE;
         }
 
-        if (d_ptr->mflags4) {
-            if ((d_ptr->mflags4 & r_ptr->flags4) != d_ptr->mflags4)
-                return FALSE;
-        }
-
-        if (d_ptr->m_a_ability_flags1) {
-            if ((d_ptr->m_a_ability_flags1 & r_ptr->a_ability_flags1) != d_ptr->m_a_ability_flags1)
-                return FALSE;
-        }
-
-        if (d_ptr->m_a_ability_flags2) {
-            if ((d_ptr->m_a_ability_flags2 & r_ptr->a_ability_flags2) != d_ptr->m_a_ability_flags2)
+        if (d_ptr->m_ability_flags.any()) {
+            if (!r_ptr->ability_flags.has_all_of(d_ptr->m_ability_flags))
                 return FALSE;
         }
 
@@ -163,18 +148,8 @@ static bool restrict_monster_to_dungeon(player_type *player_ptr, MONRACE_IDX r_i
                 return TRUE;
         }
 
-        if (d_ptr->mflags4) {
-            if ((d_ptr->mflags4 & r_ptr->flags4) != d_ptr->mflags4)
-                return TRUE;
-        }
-
-        if (d_ptr->m_a_ability_flags1) {
-            if ((d_ptr->m_a_ability_flags1 & r_ptr->a_ability_flags1) != d_ptr->m_a_ability_flags1)
-                return TRUE;
-        }
-
-        if (d_ptr->m_a_ability_flags2) {
-            if ((d_ptr->m_a_ability_flags2 & r_ptr->a_ability_flags2) != d_ptr->m_a_ability_flags2)
+        if (d_ptr->m_ability_flags.any()) {
+            if (!r_ptr->ability_flags.has_all_of(d_ptr->m_ability_flags))
                 return TRUE;
         }
 
@@ -211,11 +186,7 @@ static bool restrict_monster_to_dungeon(player_type *player_ptr, MONRACE_IDX r_i
             return TRUE;
         if (r_ptr->flags3 & d_ptr->mflags3)
             return TRUE;
-        if (r_ptr->flags4 & d_ptr->mflags4)
-            return TRUE;
-        if (r_ptr->a_ability_flags1 & d_ptr->m_a_ability_flags1)
-            return TRUE;
-        if (r_ptr->a_ability_flags2 & d_ptr->m_a_ability_flags2)
+        if (r_ptr->ability_flags.has_any_of(d_ptr->m_ability_flags))
             return TRUE;
         if (r_ptr->flags7 & d_ptr->mflags7)
             return TRUE;
@@ -238,11 +209,7 @@ static bool restrict_monster_to_dungeon(player_type *player_ptr, MONRACE_IDX r_i
             return FALSE;
         if (r_ptr->flags3 & d_ptr->mflags3)
             return FALSE;
-        if (r_ptr->flags4 & d_ptr->mflags4)
-            return FALSE;
-        if (r_ptr->a_ability_flags1 & d_ptr->m_a_ability_flags1)
-            return FALSE;
-        if (r_ptr->a_ability_flags2 & d_ptr->m_a_ability_flags2)
+        if (r_ptr->ability_flags.has_any_of(d_ptr->m_ability_flags))
             return FALSE;
         if (r_ptr->flags7 & d_ptr->mflags7)
             return FALSE;
@@ -428,4 +395,7 @@ errr get_mon_num_prep(player_type *player_ptr, const monsterrace_hook_type hook1
  *
  * get_mon_num() を呼ぶ前に get_mon_num_prep 系関数のいずれかを呼ぶこと。
  */
-errr get_mon_num_prep_bounty(player_type *player_ptr) { return do_get_mon_num_prep(player_ptr, NULL, NULL, FALSE); }
+errr get_mon_num_prep_bounty(player_type *player_ptr)
+{
+    return do_get_mon_num_prep(player_ptr, NULL, NULL, FALSE);
+}
index 44a51c2..5655c89 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "mspell/assign-monster-spell.h"
 #include "blue-magic/blue-magic-checker.h"
+#include "monster-race/race-ability-flags.h"
 #include "mspell/mspell-ball.h"
 #include "mspell/mspell-bolt.h"
 #include "mspell/mspell-breath.h"
 /*!
  * @brief SPELL_IDX を monster_spell_type に変換する。
  */
-static int spell_idx_to_monster_spell_type(const SPELL_IDX idx)
+static int spell_idx_to_monster_spell_type(const RF_ABILITY idx)
 {
-    return idx - RF4_SPELL_START;
+    return static_cast<int>(idx);
 }
 
-static MonsterSpellResult monspell_to_player_impl(player_type *target_ptr, SPELL_IDX ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx)
+static MonsterSpellResult monspell_to_player_impl(player_type *target_ptr, RF_ABILITY ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx)
 {
     // clang-format off
     switch (ms_type) {
-    case RF4_SPELL_START + 0:  return spell_RF4_SHRIEK(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF4_SHRIEK */
-    case RF4_SPELL_START + 1:  break;   /* RF4_XXX1 */
-    case RF4_SPELL_START + 2:  return spell_RF4_DISPEL(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF4_DISPEL */
-    case RF4_SPELL_START + 3:  return spell_RF4_ROCKET(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF4_ROCKET */
-    case RF4_SPELL_START + 4:  return spell_RF4_SHOOT(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_SHOOT */
-    case RF4_SPELL_START + 5:  break;   /* RF4_XXX2 */
-    case RF4_SPELL_START + 6:  break;   /* RF4_XXX3 */
-    case RF4_SPELL_START + 7:  break;   /* RF4_XXX4 */
-    case RF4_SPELL_START + 8:  return spell_RF4_BREATH(target_ptr, GF_ACID, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_ACID */
-    case RF4_SPELL_START + 9:  return spell_RF4_BREATH(target_ptr, GF_ELEC, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_ELEC */
-    case RF4_SPELL_START + 10: return spell_RF4_BREATH(target_ptr, GF_FIRE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_FIRE */
-    case RF4_SPELL_START + 11: return spell_RF4_BREATH(target_ptr, GF_COLD, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_COLD */
-    case RF4_SPELL_START + 12: return spell_RF4_BREATH(target_ptr, GF_POIS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_POIS */
-    case RF4_SPELL_START + 13: return spell_RF4_BREATH(target_ptr, GF_NETHER, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_NETH */
-    case RF4_SPELL_START + 14: return spell_RF4_BREATH(target_ptr, GF_LITE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_LITE */
-    case RF4_SPELL_START + 15: return spell_RF4_BREATH(target_ptr, GF_DARK, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_DARK */
-    case RF4_SPELL_START + 16: return spell_RF4_BREATH(target_ptr, GF_CONFUSION, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_CONF */
-    case RF4_SPELL_START + 17: return spell_RF4_BREATH(target_ptr, GF_SOUND, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_SOUN */
-    case RF4_SPELL_START + 18: return spell_RF4_BREATH(target_ptr, GF_CHAOS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_CHAO */
-    case RF4_SPELL_START + 19: return spell_RF4_BREATH(target_ptr, GF_DISENCHANT, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_DISE */
-    case RF4_SPELL_START + 20: return spell_RF4_BREATH(target_ptr, GF_NEXUS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_NEXU */
-    case RF4_SPELL_START + 21: return spell_RF4_BREATH(target_ptr, GF_TIME, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_TIME */
-    case RF4_SPELL_START + 22: return spell_RF4_BREATH(target_ptr, GF_INERTIAL, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF4_BR_INER */
-    case RF4_SPELL_START + 23: return spell_RF4_BREATH(target_ptr, GF_GRAVITY, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF4_BR_GRAV */
-    case RF4_SPELL_START + 24: return spell_RF4_BREATH(target_ptr, GF_SHARDS, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_SHAR */
-    case RF4_SPELL_START + 25: return spell_RF4_BREATH(target_ptr, GF_PLASMA, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_PLAS */
-    case RF4_SPELL_START + 26: return spell_RF4_BREATH(target_ptr, GF_FORCE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_WALL */
-    case RF4_SPELL_START + 27: return spell_RF4_BREATH(target_ptr, GF_MANA, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_MANA */
-    case RF4_SPELL_START + 28: return spell_RF4_BA_NUKE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BA_NUKE */
-    case RF4_SPELL_START + 29: return spell_RF4_BREATH(target_ptr, GF_NUKE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_NUKE */
-    case RF4_SPELL_START + 30: return spell_RF4_BA_CHAO(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BA_CHAO */
-    case RF4_SPELL_START + 31: return spell_RF4_BREATH(target_ptr, GF_DISINTEGRATE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_DISI */
-    case RF5_SPELL_START + 0:  return spell_RF5_BA_ACID(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_ACID */
-    case RF5_SPELL_START + 1:  return spell_RF5_BA_ELEC(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_ELEC */
-    case RF5_SPELL_START + 2:  return spell_RF5_BA_FIRE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_FIRE */
-    case RF5_SPELL_START + 3:  return spell_RF5_BA_COLD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_COLD */
-    case RF5_SPELL_START + 4:  return spell_RF5_BA_POIS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_POIS */
-    case RF5_SPELL_START + 5:  return spell_RF5_BA_NETH(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_NETH */
-    case RF5_SPELL_START + 6:  return spell_RF5_BA_WATE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_WATE */
-    case RF5_SPELL_START + 7:  return spell_RF5_BA_MANA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_MANA */
-    case RF5_SPELL_START + 8:  return spell_RF5_BA_DARK(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_DARK */
-    case RF5_SPELL_START + 9:  return spell_RF5_DRAIN_MANA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF5_DRAIN_MANA */
-    case RF5_SPELL_START + 10: return spell_RF5_MIND_BLAST(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF5_MIND_BLAST */
-    case RF5_SPELL_START + 11: return spell_RF5_BRAIN_SMASH(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_MIND_BLAST */
-    case RF5_SPELL_START + 12: return spell_RF5_CAUSE_1(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_1 */
-    case RF5_SPELL_START + 13: return spell_RF5_CAUSE_2(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_2 */
-    case RF5_SPELL_START + 14: return spell_RF5_CAUSE_3(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_3 */
-    case RF5_SPELL_START + 15: return spell_RF5_CAUSE_4(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_4 */
-    case RF5_SPELL_START + 16: return spell_RF5_BO_ACID(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_ACID */
-    case RF5_SPELL_START + 17: return spell_RF5_BO_ELEC(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_ELEC */
-    case RF5_SPELL_START + 18: return spell_RF5_BO_FIRE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_FIRE */
-    case RF5_SPELL_START + 19: return spell_RF5_BO_COLD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_COLD */
-    case RF5_SPELL_START + 20: return spell_RF5_BA_LITE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_LITE */
-    case RF5_SPELL_START + 21: return spell_RF5_BO_NETH(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_NETH */
-    case RF5_SPELL_START + 22: return spell_RF5_BO_WATE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_WATE */
-    case RF5_SPELL_START + 23: return spell_RF5_BO_MANA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_MANA */
-    case RF5_SPELL_START + 24: return spell_RF5_BO_PLAS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_PLAS */
-    case RF5_SPELL_START + 25: return spell_RF5_BO_ICEE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_ICEE */
-    case RF5_SPELL_START + 26: return spell_RF5_MISSILE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_MISSILE */
-    case RF5_SPELL_START + 27: return spell_RF5_SCARE(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_SCARE */
-    case RF5_SPELL_START + 28: return spell_RF5_BLIND(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_BLIND */
-    case RF5_SPELL_START + 29: return spell_RF5_CONF(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_CONF */
-    case RF5_SPELL_START + 30: return spell_RF5_SLOW(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_SLOW */
-    case RF5_SPELL_START + 31: return spell_RF5_HOLD(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_HOLD */
-    case RF6_SPELL_START + 0:  return spell_RF6_HASTE(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_HASTE */
-    case RF6_SPELL_START + 1:  return spell_RF6_HAND_DOOM(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_HAND_DOOM */
-    case RF6_SPELL_START + 2:  return spell_RF6_HEAL(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_HEAL */
-    case RF6_SPELL_START + 3:  return spell_RF6_INVULNER(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_INVULNER */
-    case RF6_SPELL_START + 4:  return spell_RF6_BLINK(target_ptr, m_idx, MONSTER_TO_PLAYER, FALSE); /* RF6_BLINK */
-    case RF6_SPELL_START + 5:  return spell_RF6_TPORT(target_ptr, m_idx, MONSTER_TO_PLAYER); /* RF6_TPORT */
-    case RF6_SPELL_START + 6:  return spell_RF6_WORLD(target_ptr, m_idx); /* RF6_WORLD */
-    case RF6_SPELL_START + 7:  return spell_RF6_SPECIAL(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF6_SPECIAL */
-    case RF6_SPELL_START + 8:  return spell_RF6_TELE_TO(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_TELE_TO */
-    case RF6_SPELL_START + 9:  return spell_RF6_TELE_AWAY(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_TELE_AWAY */
-    case RF6_SPELL_START + 10: return spell_RF6_TELE_LEVEL(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_TELE_LEVEL */
-    case RF6_SPELL_START + 11: return spell_RF6_PSY_SPEAR(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_PSY_SPEAR */
-    case RF6_SPELL_START + 12: return spell_RF6_DARKNESS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_DARKNESS */
-    case RF6_SPELL_START + 13: return spell_RF6_TRAPS(target_ptr, y, x, m_idx); /* RF6_TRAPS */
-    case RF6_SPELL_START + 14: return spell_RF6_FORGET(target_ptr, m_idx); /* RF6_FORGET */
-    case RF6_SPELL_START + 15: return spell_RF6_RAISE_DEAD(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_RAISE_DEAD */
-    case RF6_SPELL_START + 16: return spell_RF6_S_KIN(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_KIN */
-    case RF6_SPELL_START + 17: return spell_RF6_S_CYBER(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_CYBER */
-    case RF6_SPELL_START + 18: return spell_RF6_S_MONSTER(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_MONSTER */
-    case RF6_SPELL_START + 19: return spell_RF6_S_MONSTERS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_MONSTER */
-    case RF6_SPELL_START + 20: return spell_RF6_S_ANT(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_ANT */
-    case RF6_SPELL_START + 21: return spell_RF6_S_SPIDER(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_SPIDER */
-    case RF6_SPELL_START + 22: return spell_RF6_S_HOUND(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HOUND */
-    case RF6_SPELL_START + 23: return spell_RF6_S_HYDRA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HYDRA */
-    case RF6_SPELL_START + 24: return spell_RF6_S_ANGEL(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_ANGEL */
-    case RF6_SPELL_START + 25: return spell_RF6_S_DEMON(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_DEMON */
-    case RF6_SPELL_START + 26: return spell_RF6_S_UNDEAD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_UNDEAD */
-    case RF6_SPELL_START + 27: return spell_RF6_S_DRAGON(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_DRAGON */
-    case RF6_SPELL_START + 28: return spell_RF6_S_HI_UNDEAD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HI_UNDEAD */
-    case RF6_SPELL_START + 29: return spell_RF6_S_HI_DRAGON(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HI_DRAGON */
-    case RF6_SPELL_START + 30: return spell_RF6_S_AMBERITES(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_AMBERITES */
-    case RF6_SPELL_START + 31: return spell_RF6_S_UNIQUE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_UNIQUE */
+    case RF_ABILITY::SHRIEK: return spell_RF4_SHRIEK(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF4_SHRIEK */
+    case RF_ABILITY::XXX1: break;   /* RF4_XXX1 */
+    case RF_ABILITY::DISPEL: return spell_RF4_DISPEL(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF4_DISPEL */
+    case RF_ABILITY::ROCKET: return spell_RF4_ROCKET(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF4_ROCKET */
+    case RF_ABILITY::SHOOT: return spell_RF4_SHOOT(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_SHOOT */
+    case RF_ABILITY::XXX2: break;   /* RF4_XXX2 */
+    case RF_ABILITY::XXX3: break;   /* RF4_XXX3 */
+    case RF_ABILITY::XXX4: break;   /* RF4_XXX4 */
+    case RF_ABILITY::BR_ACID: return spell_RF4_BREATH(target_ptr, GF_ACID, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_ACID */
+    case RF_ABILITY::BR_ELEC: return spell_RF4_BREATH(target_ptr, GF_ELEC, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_ELEC */
+    case RF_ABILITY::BR_FIRE: return spell_RF4_BREATH(target_ptr, GF_FIRE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_FIRE */
+    case RF_ABILITY::BR_COLD: return spell_RF4_BREATH(target_ptr, GF_COLD, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_COLD */
+    case RF_ABILITY::BR_POIS: return spell_RF4_BREATH(target_ptr, GF_POIS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_POIS */
+    case RF_ABILITY::BR_NETH: return spell_RF4_BREATH(target_ptr, GF_NETHER, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_NETH */
+    case RF_ABILITY::BR_LITE: return spell_RF4_BREATH(target_ptr, GF_LITE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_LITE */
+    case RF_ABILITY::BR_DARK: return spell_RF4_BREATH(target_ptr, GF_DARK, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_DARK */
+    case RF_ABILITY::BR_CONF: return spell_RF4_BREATH(target_ptr, GF_CONFUSION, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_CONF */
+    case RF_ABILITY::BR_SOUN: return spell_RF4_BREATH(target_ptr, GF_SOUND, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_SOUN */
+    case RF_ABILITY::BR_CHAO: return spell_RF4_BREATH(target_ptr, GF_CHAOS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_CHAO */
+    case RF_ABILITY::BR_DISE: return spell_RF4_BREATH(target_ptr, GF_DISENCHANT, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_DISE */
+    case RF_ABILITY::BR_NEXU: return spell_RF4_BREATH(target_ptr, GF_NEXUS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_NEXU */
+    case RF_ABILITY::BR_TIME: return spell_RF4_BREATH(target_ptr, GF_TIME, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_TIME */
+    case RF_ABILITY::BR_INER: return spell_RF4_BREATH(target_ptr, GF_INERTIAL, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF4_BR_INER */
+    case RF_ABILITY::BR_GRAV: return spell_RF4_BREATH(target_ptr, GF_GRAVITY, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF4_BR_GRAV */
+    case RF_ABILITY::BR_SHAR: return spell_RF4_BREATH(target_ptr, GF_SHARDS, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_SHAR */
+    case RF_ABILITY::BR_PLAS: return spell_RF4_BREATH(target_ptr, GF_PLASMA, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_PLAS */
+    case RF_ABILITY::BR_WALL: return spell_RF4_BREATH(target_ptr, GF_FORCE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_WALL */
+    case RF_ABILITY::BR_MANA: return spell_RF4_BREATH(target_ptr, GF_MANA, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_MANA */
+    case RF_ABILITY::BA_NUKE: return spell_RF4_BA_NUKE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BA_NUKE */
+    case RF_ABILITY::BR_NUKE: return spell_RF4_BREATH(target_ptr, GF_NUKE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_NUKE */
+    case RF_ABILITY::BA_CHAO: return spell_RF4_BA_CHAO(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BA_CHAO */
+    case RF_ABILITY::BR_DISI: return spell_RF4_BREATH(target_ptr, GF_DISINTEGRATE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_DISI */
+    case RF_ABILITY::BA_ACID: return spell_RF5_BA_ACID(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_ACID */
+    case RF_ABILITY::BA_ELEC: return spell_RF5_BA_ELEC(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_ELEC */
+    case RF_ABILITY::BA_FIRE: return spell_RF5_BA_FIRE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_FIRE */
+    case RF_ABILITY::BA_COLD: return spell_RF5_BA_COLD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_COLD */
+    case RF_ABILITY::BA_POIS: return spell_RF5_BA_POIS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_POIS */
+    case RF_ABILITY::BA_NETH: return spell_RF5_BA_NETH(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_NETH */
+    case RF_ABILITY::BA_WATE: return spell_RF5_BA_WATE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_WATE */
+    case RF_ABILITY::BA_MANA: return spell_RF5_BA_MANA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_MANA */
+    case RF_ABILITY::BA_DARK: return spell_RF5_BA_DARK(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_DARK */
+    case RF_ABILITY::DRAIN_MANA: return spell_RF5_DRAIN_MANA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF5_DRAIN_MANA */
+    case RF_ABILITY::MIND_BLAST: return spell_RF5_MIND_BLAST(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF5_MIND_BLAST */
+    case RF_ABILITY::BRAIN_SMASH: return spell_RF5_BRAIN_SMASH(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_MIND_BLAST */
+    case RF_ABILITY::CAUSE_1: return spell_RF5_CAUSE_1(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_1 */
+    case RF_ABILITY::CAUSE_2: return spell_RF5_CAUSE_2(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_2 */
+    case RF_ABILITY::CAUSE_3: return spell_RF5_CAUSE_3(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_3 */
+    case RF_ABILITY::CAUSE_4: return spell_RF5_CAUSE_4(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_4 */
+    case RF_ABILITY::BO_ACID: return spell_RF5_BO_ACID(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_ACID */
+    case RF_ABILITY::BO_ELEC: return spell_RF5_BO_ELEC(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_ELEC */
+    case RF_ABILITY::BO_FIRE: return spell_RF5_BO_FIRE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_FIRE */
+    case RF_ABILITY::BO_COLD: return spell_RF5_BO_COLD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_COLD */
+    case RF_ABILITY::BA_LITE: return spell_RF5_BA_LITE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_LITE */
+    case RF_ABILITY::BO_NETH: return spell_RF5_BO_NETH(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_NETH */
+    case RF_ABILITY::BO_WATE: return spell_RF5_BO_WATE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_WATE */
+    case RF_ABILITY::BO_MANA: return spell_RF5_BO_MANA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_MANA */
+    case RF_ABILITY::BO_PLAS: return spell_RF5_BO_PLAS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_PLAS */
+    case RF_ABILITY::BO_ICEE: return spell_RF5_BO_ICEE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_ICEE */
+    case RF_ABILITY::MISSILE: return spell_RF5_MISSILE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_MISSILE */
+    case RF_ABILITY::SCARE: return spell_RF5_SCARE(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_SCARE */
+    case RF_ABILITY::BLIND: return spell_RF5_BLIND(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_BLIND */
+    case RF_ABILITY::CONF: return spell_RF5_CONF(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_CONF */
+    case RF_ABILITY::SLOW: return spell_RF5_SLOW(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_SLOW */
+    case RF_ABILITY::HOLD: return spell_RF5_HOLD(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_HOLD */
+    case RF_ABILITY::HASTE: return spell_RF6_HASTE(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_HASTE */
+    case RF_ABILITY::HAND_DOOM: return spell_RF6_HAND_DOOM(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_HAND_DOOM */
+    case RF_ABILITY::HEAL: return spell_RF6_HEAL(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_HEAL */
+    case RF_ABILITY::INVULNER: return spell_RF6_INVULNER(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_INVULNER */
+    case RF_ABILITY::BLINK: return spell_RF6_BLINK(target_ptr, m_idx, MONSTER_TO_PLAYER, FALSE); /* RF6_BLINK */
+    case RF_ABILITY::TPORT: return spell_RF6_TPORT(target_ptr, m_idx, MONSTER_TO_PLAYER); /* RF6_TPORT */
+    case RF_ABILITY::WORLD: return spell_RF6_WORLD(target_ptr, m_idx); /* RF6_WORLD */
+    case RF_ABILITY::SPECIAL: return spell_RF6_SPECIAL(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF6_SPECIAL */
+    case RF_ABILITY::TELE_TO: return spell_RF6_TELE_TO(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_TELE_TO */
+    case RF_ABILITY::TELE_AWAY: return spell_RF6_TELE_AWAY(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_TELE_AWAY */
+    case RF_ABILITY::TELE_LEVEL: return spell_RF6_TELE_LEVEL(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_TELE_LEVEL */
+    case RF_ABILITY::PSY_SPEAR: return spell_RF6_PSY_SPEAR(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_PSY_SPEAR */
+    case RF_ABILITY::DARKNESS: return spell_RF6_DARKNESS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_DARKNESS */
+    case RF_ABILITY::TRAPS: return spell_RF6_TRAPS(target_ptr, y, x, m_idx); /* RF6_TRAPS */
+    case RF_ABILITY::FORGET: return spell_RF6_FORGET(target_ptr, m_idx); /* RF6_FORGET */
+    case RF_ABILITY::RAISE_DEAD: return spell_RF6_RAISE_DEAD(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_RAISE_DEAD */
+    case RF_ABILITY::S_KIN: return spell_RF6_S_KIN(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_KIN */
+    case RF_ABILITY::S_CYBER: return spell_RF6_S_CYBER(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_CYBER */
+    case RF_ABILITY::S_MONSTER: return spell_RF6_S_MONSTER(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_MONSTER */
+    case RF_ABILITY::S_MONSTERS: return spell_RF6_S_MONSTERS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_MONSTER */
+    case RF_ABILITY::S_ANT: return spell_RF6_S_ANT(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_ANT */
+    case RF_ABILITY::S_SPIDER: return spell_RF6_S_SPIDER(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_SPIDER */
+    case RF_ABILITY::S_HOUND: return spell_RF6_S_HOUND(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HOUND */
+    case RF_ABILITY::S_HYDRA: return spell_RF6_S_HYDRA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HYDRA */
+    case RF_ABILITY::S_ANGEL: return spell_RF6_S_ANGEL(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_ANGEL */
+    case RF_ABILITY::S_DEMON: return spell_RF6_S_DEMON(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_DEMON */
+    case RF_ABILITY::S_UNDEAD: return spell_RF6_S_UNDEAD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_UNDEAD */
+    case RF_ABILITY::S_DRAGON: return spell_RF6_S_DRAGON(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_DRAGON */
+    case RF_ABILITY::S_HI_UNDEAD: return spell_RF6_S_HI_UNDEAD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HI_UNDEAD */
+    case RF_ABILITY::S_HI_DRAGON: return spell_RF6_S_HI_DRAGON(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HI_DRAGON */
+    case RF_ABILITY::S_AMBERITES: return spell_RF6_S_AMBERITES(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_AMBERITES */
+    case RF_ABILITY::S_UNIQUE: return spell_RF6_S_UNIQUE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_UNIQUE */
     default: break;
     }
     // clang-format on
@@ -138,106 +139,106 @@ static MonsterSpellResult monspell_to_player_impl(player_type *target_ptr, SPELL
 }
 
 static MonsterSpellResult monspell_to_monster_impl(
-    player_type *target_ptr, SPELL_IDX ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, bool is_special_spell)
+    player_type *target_ptr, RF_ABILITY ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, bool is_special_spell)
 {
     // clang-format off
     switch (ms_type) {
-    case RF4_SPELL_START + 0:  return spell_RF4_SHRIEK(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF4_SHRIEK */
-    case RF4_SPELL_START + 1:  break;   /* RF4_XXX1 */
-    case RF4_SPELL_START + 2:  return spell_RF4_DISPEL(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF4_DISPEL */
-    case RF4_SPELL_START + 3:  return spell_RF4_ROCKET(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_ROCKET */
-    case RF4_SPELL_START + 4:  return spell_RF4_SHOOT(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_SHOOT */
-    case RF4_SPELL_START + 5:  break;   /* RF4_XXX2 */
-    case RF4_SPELL_START + 6:  break;   /* RF4_XXX3 */
-    case RF4_SPELL_START + 7:  break;   /* RF4_XXX4 */
-    case RF4_SPELL_START + 8:  return spell_RF4_BREATH(target_ptr, GF_ACID, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_ACID */
-    case RF4_SPELL_START + 9:  return spell_RF4_BREATH(target_ptr, GF_ELEC, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_ELEC */
-    case RF4_SPELL_START + 10: return spell_RF4_BREATH(target_ptr, GF_FIRE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_FIRE */
-    case RF4_SPELL_START + 11: return spell_RF4_BREATH(target_ptr, GF_COLD, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_COLD */
-    case RF4_SPELL_START + 12: return spell_RF4_BREATH(target_ptr, GF_POIS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_POIS */
-    case RF4_SPELL_START + 13: return spell_RF4_BREATH(target_ptr, GF_NETHER, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_NETH */
-    case RF4_SPELL_START + 14: return spell_RF4_BREATH(target_ptr, GF_LITE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_LITE */
-    case RF4_SPELL_START + 15: return spell_RF4_BREATH(target_ptr, GF_DARK, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_DARK */
-    case RF4_SPELL_START + 16: return spell_RF4_BREATH(target_ptr, GF_CONFUSION, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_CONF */
-    case RF4_SPELL_START + 17: return spell_RF4_BREATH(target_ptr, GF_SOUND, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_SOUN */
-    case RF4_SPELL_START + 18: return spell_RF4_BREATH(target_ptr, GF_CHAOS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_CHAO */
-    case RF4_SPELL_START + 19: return spell_RF4_BREATH(target_ptr, GF_DISENCHANT, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_DISE */
-    case RF4_SPELL_START + 20: return spell_RF4_BREATH(target_ptr, GF_NEXUS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_NEXU */
-    case RF4_SPELL_START + 21: return spell_RF4_BREATH(target_ptr, GF_TIME, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_TIME */
-    case RF4_SPELL_START + 22: return spell_RF4_BREATH(target_ptr, GF_INERTIAL, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_INER */
-    case RF4_SPELL_START + 23: return spell_RF4_BREATH(target_ptr, GF_GRAVITY, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_GRAV */
-    case RF4_SPELL_START + 24: return spell_RF4_BREATH(target_ptr, GF_SHARDS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_SHAR */
-    case RF4_SPELL_START + 25: return spell_RF4_BREATH(target_ptr, GF_PLASMA, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_PLAS */
-    case RF4_SPELL_START + 26: return spell_RF4_BREATH(target_ptr, GF_FORCE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_WALL */
-    case RF4_SPELL_START + 27: return spell_RF4_BREATH(target_ptr, GF_MANA, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_MANA */
-    case RF4_SPELL_START + 28: return spell_RF4_BA_NUKE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BA_NUKE */
-    case RF4_SPELL_START + 29: return spell_RF4_BREATH(target_ptr, GF_NUKE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_NUKE */
-    case RF4_SPELL_START + 30: return spell_RF4_BA_CHAO(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BA_CHAO */
-    case RF4_SPELL_START + 31: return spell_RF4_BREATH(target_ptr, GF_DISINTEGRATE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_DISI */
-    case RF5_SPELL_START + 0:  return spell_RF5_BA_ACID(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_ACID */
-    case RF5_SPELL_START + 1:  return spell_RF5_BA_ELEC(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_ELEC */
-    case RF5_SPELL_START + 2:  return spell_RF5_BA_FIRE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_FIRE */
-    case RF5_SPELL_START + 3:  return spell_RF5_BA_COLD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_COLD */
-    case RF5_SPELL_START + 4:  return spell_RF5_BA_POIS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_POIS */
-    case RF5_SPELL_START + 5:  return spell_RF5_BA_NETH(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_NETH */
-    case RF5_SPELL_START + 6:  return spell_RF5_BA_WATE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_WATE */
-    case RF5_SPELL_START + 7:  return spell_RF5_BA_MANA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_MANA */
-    case RF5_SPELL_START + 8:  return spell_RF5_BA_DARK(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_DARK */
-    case RF5_SPELL_START + 9:  return spell_RF5_DRAIN_MANA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_DRAIN_MANA */
-    case RF5_SPELL_START + 10: return spell_RF5_MIND_BLAST(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_MIND_BLAST */
-    case RF5_SPELL_START + 11: return spell_RF5_BRAIN_SMASH(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BRAIN_SMASH */
-    case RF5_SPELL_START + 12: return spell_RF5_CAUSE_1(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_1 */
-    case RF5_SPELL_START + 13: return spell_RF5_CAUSE_2(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_2 */
-    case RF5_SPELL_START + 14: return spell_RF5_CAUSE_3(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_3 */
-    case RF5_SPELL_START + 15: return spell_RF5_CAUSE_4(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_4 */
-    case RF5_SPELL_START + 16: return spell_RF5_BO_ACID(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_ACID */
-    case RF5_SPELL_START + 17: return spell_RF5_BO_ELEC(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_ELEC */
-    case RF5_SPELL_START + 18: return spell_RF5_BO_FIRE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_FIRE */
-    case RF5_SPELL_START + 19: return spell_RF5_BO_COLD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_COLD */
-    case RF5_SPELL_START + 20: return spell_RF5_BA_LITE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_LITE */
-    case RF5_SPELL_START + 21: return spell_RF5_BO_NETH(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_NETH */
-    case RF5_SPELL_START + 22: return spell_RF5_BO_WATE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_WATE */
-    case RF5_SPELL_START + 23: return spell_RF5_BO_MANA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_MANA */
-    case RF5_SPELL_START + 24: return spell_RF5_BO_PLAS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_PLAS */
-    case RF5_SPELL_START + 25: return spell_RF5_BO_ICEE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_ICEE */
-    case RF5_SPELL_START + 26: return spell_RF5_MISSILE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_MISSILE */
-    case RF5_SPELL_START + 27: return spell_RF5_SCARE(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_SCARE */
-    case RF5_SPELL_START + 28: return spell_RF5_BLIND(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_BLIND */
-    case RF5_SPELL_START + 29: return spell_RF5_CONF(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_CONF */
-    case RF5_SPELL_START + 30: return spell_RF5_SLOW(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_SLOW */
-    case RF5_SPELL_START + 31: return spell_RF5_HOLD(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_HOLD */
-    case RF6_SPELL_START + 0:  return spell_RF6_HASTE(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_HASTE */
-    case RF6_SPELL_START + 1:  return spell_RF6_HAND_DOOM(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_HAND_DOOM */
-    case RF6_SPELL_START + 2:  return spell_RF6_HEAL(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_HEAL */
-    case RF6_SPELL_START + 3:  return spell_RF6_INVULNER(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_INVULNER */
-    case RF6_SPELL_START + 4:  return spell_RF6_BLINK(target_ptr, m_idx, MONSTER_TO_MONSTER, is_special_spell); /* RF6_BLINK */
-    case RF6_SPELL_START + 5:  return spell_RF6_TPORT(target_ptr, m_idx, MONSTER_TO_MONSTER); /* RF6_TPORT */
-    case RF6_SPELL_START + 6:  break; /* RF6_WORLD */
-    case RF6_SPELL_START + 7:  return spell_RF6_SPECIAL(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF6_SPECIAL */
-    case RF6_SPELL_START + 8:  return spell_RF6_TELE_TO(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_TELE_TO */
-    case RF6_SPELL_START + 9:  return spell_RF6_TELE_AWAY(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_TELE_AWAY */
-    case RF6_SPELL_START + 10: return spell_RF6_TELE_LEVEL(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_TELE_LEVEL */
-    case RF6_SPELL_START + 11: return spell_RF6_PSY_SPEAR(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_PSY_SPEAR */
-    case RF6_SPELL_START + 12: return spell_RF6_DARKNESS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_DARKNESS */
-    case RF6_SPELL_START + 13: break; /* RF6_TRAPS */
-    case RF6_SPELL_START + 14: break; /* RF6_FORGET */
-    case RF6_SPELL_START + 15: return spell_RF6_RAISE_DEAD(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_RAISE_DEAD */
-    case RF6_SPELL_START + 16: return spell_RF6_S_KIN(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_KIN */
-    case RF6_SPELL_START + 17: return spell_RF6_S_CYBER(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_CYBER */
-    case RF6_SPELL_START + 18: return spell_RF6_S_MONSTER(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_MONSTER */
-    case RF6_SPELL_START + 19: return spell_RF6_S_MONSTERS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_MONSTER */
-    case RF6_SPELL_START + 20: return spell_RF6_S_ANT(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_ANT */
-    case RF6_SPELL_START + 21: return spell_RF6_S_SPIDER(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_SPIDER */
-    case RF6_SPELL_START + 22: return spell_RF6_S_HOUND(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HOUND */
-    case RF6_SPELL_START + 23: return spell_RF6_S_HYDRA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HYDRA */
-    case RF6_SPELL_START + 24: return spell_RF6_S_ANGEL(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_ANGEL */
-    case RF6_SPELL_START + 25: return spell_RF6_S_DEMON(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_DEMON */
-    case RF6_SPELL_START + 26: return spell_RF6_S_UNDEAD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_UNDEAD */
-    case RF6_SPELL_START + 27: return spell_RF6_S_DRAGON(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_DRAGON */
-    case RF6_SPELL_START + 28: return spell_RF6_S_HI_UNDEAD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HI_UNDEAD */
-    case RF6_SPELL_START + 29: return spell_RF6_S_HI_DRAGON(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HI_DRAGON */
-    case RF6_SPELL_START + 30: return spell_RF6_S_AMBERITES(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_AMBERITES */
-    case RF6_SPELL_START + 31: return spell_RF6_S_UNIQUE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_UNIQUE */
+    case RF_ABILITY::SHRIEK: return spell_RF4_SHRIEK(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF4_SHRIEK */
+    case RF_ABILITY::XXX1: break;   /* RF4_XXX1 */
+    case RF_ABILITY::DISPEL: return spell_RF4_DISPEL(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF4_DISPEL */
+    case RF_ABILITY::ROCKET: return spell_RF4_ROCKET(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_ROCKET */
+    case RF_ABILITY::SHOOT: return spell_RF4_SHOOT(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_SHOOT */
+    case RF_ABILITY::XXX2: break;   /* RF4_XXX2 */
+    case RF_ABILITY::XXX3: break;   /* RF4_XXX3 */
+    case RF_ABILITY::XXX4: break;   /* RF4_XXX4 */
+    case RF_ABILITY::BR_ACID: return spell_RF4_BREATH(target_ptr, GF_ACID, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_ACID */
+    case RF_ABILITY::BR_ELEC: return spell_RF4_BREATH(target_ptr, GF_ELEC, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_ELEC */
+    case RF_ABILITY::BR_FIRE: return spell_RF4_BREATH(target_ptr, GF_FIRE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_FIRE */
+    case RF_ABILITY::BR_COLD: return spell_RF4_BREATH(target_ptr, GF_COLD, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_COLD */
+    case RF_ABILITY::BR_POIS: return spell_RF4_BREATH(target_ptr, GF_POIS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_POIS */
+    case RF_ABILITY::BR_NETH: return spell_RF4_BREATH(target_ptr, GF_NETHER, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_NETH */
+    case RF_ABILITY::BR_LITE: return spell_RF4_BREATH(target_ptr, GF_LITE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_LITE */
+    case RF_ABILITY::BR_DARK: return spell_RF4_BREATH(target_ptr, GF_DARK, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_DARK */
+    case RF_ABILITY::BR_CONF: return spell_RF4_BREATH(target_ptr, GF_CONFUSION, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_CONF */
+    case RF_ABILITY::BR_SOUN: return spell_RF4_BREATH(target_ptr, GF_SOUND, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_SOUN */
+    case RF_ABILITY::BR_CHAO: return spell_RF4_BREATH(target_ptr, GF_CHAOS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_CHAO */
+    case RF_ABILITY::BR_DISE: return spell_RF4_BREATH(target_ptr, GF_DISENCHANT, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_DISE */
+    case RF_ABILITY::BR_NEXU: return spell_RF4_BREATH(target_ptr, GF_NEXUS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_NEXU */
+    case RF_ABILITY::BR_TIME: return spell_RF4_BREATH(target_ptr, GF_TIME, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_TIME */
+    case RF_ABILITY::BR_INER: return spell_RF4_BREATH(target_ptr, GF_INERTIAL, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_INER */
+    case RF_ABILITY::BR_GRAV: return spell_RF4_BREATH(target_ptr, GF_GRAVITY, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_GRAV */
+    case RF_ABILITY::BR_SHAR: return spell_RF4_BREATH(target_ptr, GF_SHARDS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_SHAR */
+    case RF_ABILITY::BR_PLAS: return spell_RF4_BREATH(target_ptr, GF_PLASMA, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_PLAS */
+    case RF_ABILITY::BR_WALL: return spell_RF4_BREATH(target_ptr, GF_FORCE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_WALL */
+    case RF_ABILITY::BR_MANA: return spell_RF4_BREATH(target_ptr, GF_MANA, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_MANA */
+    case RF_ABILITY::BA_NUKE: return spell_RF4_BA_NUKE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BA_NUKE */
+    case RF_ABILITY::BR_NUKE: return spell_RF4_BREATH(target_ptr, GF_NUKE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_NUKE */
+    case RF_ABILITY::BA_CHAO: return spell_RF4_BA_CHAO(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BA_CHAO */
+    case RF_ABILITY::BR_DISI: return spell_RF4_BREATH(target_ptr, GF_DISINTEGRATE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_DISI */
+    case RF_ABILITY::BA_ACID: return spell_RF5_BA_ACID(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_ACID */
+    case RF_ABILITY::BA_ELEC: return spell_RF5_BA_ELEC(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_ELEC */
+    case RF_ABILITY::BA_FIRE: return spell_RF5_BA_FIRE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_FIRE */
+    case RF_ABILITY::BA_COLD: return spell_RF5_BA_COLD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_COLD */
+    case RF_ABILITY::BA_POIS: return spell_RF5_BA_POIS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_POIS */
+    case RF_ABILITY::BA_NETH: return spell_RF5_BA_NETH(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_NETH */
+    case RF_ABILITY::BA_WATE: return spell_RF5_BA_WATE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_WATE */
+    case RF_ABILITY::BA_MANA: return spell_RF5_BA_MANA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_MANA */
+    case RF_ABILITY::BA_DARK: return spell_RF5_BA_DARK(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_DARK */
+    case RF_ABILITY::DRAIN_MANA: return spell_RF5_DRAIN_MANA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_DRAIN_MANA */
+    case RF_ABILITY::MIND_BLAST: return spell_RF5_MIND_BLAST(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_MIND_BLAST */
+    case RF_ABILITY::BRAIN_SMASH: return spell_RF5_BRAIN_SMASH(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BRAIN_SMASH */
+    case RF_ABILITY::CAUSE_1: return spell_RF5_CAUSE_1(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_1 */
+    case RF_ABILITY::CAUSE_2: return spell_RF5_CAUSE_2(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_2 */
+    case RF_ABILITY::CAUSE_3: return spell_RF5_CAUSE_3(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_3 */
+    case RF_ABILITY::CAUSE_4: return spell_RF5_CAUSE_4(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_4 */
+    case RF_ABILITY::BO_ACID: return spell_RF5_BO_ACID(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_ACID */
+    case RF_ABILITY::BO_ELEC: return spell_RF5_BO_ELEC(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_ELEC */
+    case RF_ABILITY::BO_FIRE: return spell_RF5_BO_FIRE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_FIRE */
+    case RF_ABILITY::BO_COLD: return spell_RF5_BO_COLD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_COLD */
+    case RF_ABILITY::BA_LITE: return spell_RF5_BA_LITE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_LITE */
+    case RF_ABILITY::BO_NETH: return spell_RF5_BO_NETH(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_NETH */
+    case RF_ABILITY::BO_WATE: return spell_RF5_BO_WATE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_WATE */
+    case RF_ABILITY::BO_MANA: return spell_RF5_BO_MANA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_MANA */
+    case RF_ABILITY::BO_PLAS: return spell_RF5_BO_PLAS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_PLAS */
+    case RF_ABILITY::BO_ICEE: return spell_RF5_BO_ICEE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_ICEE */
+    case RF_ABILITY::MISSILE: return spell_RF5_MISSILE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_MISSILE */
+    case RF_ABILITY::SCARE: return spell_RF5_SCARE(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_SCARE */
+    case RF_ABILITY::BLIND: return spell_RF5_BLIND(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_BLIND */
+    case RF_ABILITY::CONF: return spell_RF5_CONF(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_CONF */
+    case RF_ABILITY::SLOW: return spell_RF5_SLOW(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_SLOW */
+    case RF_ABILITY::HOLD: return spell_RF5_HOLD(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_HOLD */
+    case RF_ABILITY::HASTE: return spell_RF6_HASTE(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_HASTE */
+    case RF_ABILITY::HAND_DOOM: return spell_RF6_HAND_DOOM(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_HAND_DOOM */
+    case RF_ABILITY::HEAL: return spell_RF6_HEAL(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_HEAL */
+    case RF_ABILITY::INVULNER: return spell_RF6_INVULNER(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_INVULNER */
+    case RF_ABILITY::BLINK: return spell_RF6_BLINK(target_ptr, m_idx, MONSTER_TO_MONSTER, is_special_spell); /* RF6_BLINK */
+    case RF_ABILITY::TPORT: return spell_RF6_TPORT(target_ptr, m_idx, MONSTER_TO_MONSTER); /* RF6_TPORT */
+    case RF_ABILITY::WORLD: break; /* RF6_WORLD */
+    case RF_ABILITY::SPECIAL: return spell_RF6_SPECIAL(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF6_SPECIAL */
+    case RF_ABILITY::TELE_TO: return spell_RF6_TELE_TO(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_TELE_TO */
+    case RF_ABILITY::TELE_AWAY: return spell_RF6_TELE_AWAY(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_TELE_AWAY */
+    case RF_ABILITY::TELE_LEVEL: return spell_RF6_TELE_LEVEL(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_TELE_LEVEL */
+    case RF_ABILITY::PSY_SPEAR: return spell_RF6_PSY_SPEAR(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_PSY_SPEAR */
+    case RF_ABILITY::DARKNESS: return spell_RF6_DARKNESS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_DARKNESS */
+    case RF_ABILITY::TRAPS: break; /* RF6_TRAPS */
+    case RF_ABILITY::FORGET: break; /* RF6_FORGET */
+    case RF_ABILITY::RAISE_DEAD: return spell_RF6_RAISE_DEAD(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_RAISE_DEAD */
+    case RF_ABILITY::S_KIN: return spell_RF6_S_KIN(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_KIN */
+    case RF_ABILITY::S_CYBER: return spell_RF6_S_CYBER(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_CYBER */
+    case RF_ABILITY::S_MONSTER: return spell_RF6_S_MONSTER(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_MONSTER */
+    case RF_ABILITY::S_MONSTERS: return spell_RF6_S_MONSTERS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_MONSTER */
+    case RF_ABILITY::S_ANT: return spell_RF6_S_ANT(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_ANT */
+    case RF_ABILITY::S_SPIDER: return spell_RF6_S_SPIDER(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_SPIDER */
+    case RF_ABILITY::S_HOUND: return spell_RF6_S_HOUND(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HOUND */
+    case RF_ABILITY::S_HYDRA: return spell_RF6_S_HYDRA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HYDRA */
+    case RF_ABILITY::S_ANGEL: return spell_RF6_S_ANGEL(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_ANGEL */
+    case RF_ABILITY::S_DEMON: return spell_RF6_S_DEMON(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_DEMON */
+    case RF_ABILITY::S_UNDEAD: return spell_RF6_S_UNDEAD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_UNDEAD */
+    case RF_ABILITY::S_DRAGON: return spell_RF6_S_DRAGON(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_DRAGON */
+    case RF_ABILITY::S_HI_UNDEAD: return spell_RF6_S_HI_UNDEAD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HI_UNDEAD */
+    case RF_ABILITY::S_HI_DRAGON: return spell_RF6_S_HI_DRAGON(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HI_DRAGON */
+    case RF_ABILITY::S_AMBERITES: return spell_RF6_S_AMBERITES(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_AMBERITES */
+    case RF_ABILITY::S_UNIQUE: return spell_RF6_S_UNIQUE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_UNIQUE */
     default: break;
     }
     // clang-format on
@@ -252,7 +253,7 @@ static MonsterSpellResult monspell_to_monster_impl(
  * @param x 対象の地点のx座標
  * @param m_idx 呪文を唱えるモンスターID
  */
-MonsterSpellResult monspell_to_player(player_type *target_ptr, SPELL_IDX ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx)
+MonsterSpellResult monspell_to_player(player_type *target_ptr, RF_ABILITY ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx)
 {
     // 特技使用前の時点でプレイヤーがモンスターを視認できているかチェック(ラーニングの必要条件)。
     const bool player_could_see_monster = spell_learnable(target_ptr, m_idx);
@@ -282,7 +283,7 @@ MonsterSpellResult monspell_to_player(player_type *target_ptr, SPELL_IDX ms_type
  * @todo モンスターからモンスターへの呪文なのにplayer_typeが引数になり得るのは間違っている……
  */
 MonsterSpellResult monspell_to_monster(
-    player_type *target_ptr, SPELL_IDX ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, bool is_special_spell)
+    player_type *target_ptr, RF_ABILITY ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, bool is_special_spell)
 {
     // 特技使用前の時点でプレイヤーがモンスターを視認できているかチェック(ラーニングの必要条件)。
     const bool player_could_see_monster = spell_learnable(target_ptr, m_idx);
index b454f2e..8036067 100644 (file)
@@ -4,6 +4,8 @@
 
 struct MonsterSpellResult;
 
-MonsterSpellResult monspell_to_player(player_type *target_ptr, SPELL_IDX ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx);
+enum class RF_ABILITY;
+
+MonsterSpellResult monspell_to_player(player_type *target_ptr, RF_ABILITY ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx);
 MonsterSpellResult monspell_to_monster(
-    player_type *target_ptr, SPELL_IDX ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, bool is_special_spell);
+    player_type *target_ptr, RF_ABILITY ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, bool is_special_spell);
index a228cc7..0744813 100644 (file)
@@ -1,7 +1,5 @@
 #include "mspell/element-resistance-checker.h"
 #include "game-option/birth-options.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags4.h"
 #include "monster/smart-learn-types.h"
 #include "mspell/smart-mspell-util.h"
 #include "player/player-status-flags.h"
@@ -56,143 +54,143 @@ void add_cheat_remove_flags_element(player_type *target_ptr, msr_type *msr_ptr)
 static void check_acid_resistance(msr_type *msr_ptr)
 {
     if (msr_ptr->smart.has(SM::IMM_ACID)) {
-        reset_bits(msr_ptr->f4, RF4_BR_ACID);
-        reset_bits(msr_ptr->f5, RF5_BA_ACID);
-        reset_bits(msr_ptr->f5, RF5_BO_ACID);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_ACID);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BA_ACID);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_ACID);
         return;
     }
 
     if (msr_ptr->smart.has_all_of({SM::OPP_ACID, SM::RES_ACID})) {
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f4, RF4_BR_ACID);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BR_ACID);
 
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f5, RF5_BA_ACID);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BA_ACID);
 
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f5, RF5_BO_ACID);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BO_ACID);
 
         return;
     }
 
     if (msr_ptr->smart.has_any_of({SM::OPP_ACID, SM::RES_ACID})) {
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f4, RF4_BR_ACID);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BR_ACID);
 
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f5, RF5_BA_ACID);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BA_ACID);
 
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f5, RF5_BO_ACID);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BO_ACID);
     }
 }
 
 static void check_elec_resistance(msr_type *msr_ptr)
 {
     if (msr_ptr->smart.has(SM::IMM_ELEC)) {
-        reset_bits(msr_ptr->f4, RF4_BR_ELEC);
-        reset_bits(msr_ptr->f5, RF5_BA_ELEC);
-        reset_bits(msr_ptr->f5, RF5_BO_ELEC);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_ELEC);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BA_ELEC);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_ELEC);
         return;
     }
 
     if (msr_ptr->smart.has_all_of({SM::OPP_ELEC, SM::RES_ELEC})) {
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f4, RF4_BR_ELEC);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BR_ELEC);
 
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f5, RF5_BA_ELEC);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BA_ELEC);
 
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f5, RF5_BO_ELEC);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BO_ELEC);
 
         return;
     }
 
     if (msr_ptr->smart.has_any_of({SM::OPP_ELEC, SM::RES_ELEC})) {
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f4, RF4_BR_ELEC);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BR_ELEC);
 
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f5, RF5_BA_ELEC);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BA_ELEC);
 
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f5, RF5_BO_ELEC);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BO_ELEC);
     }
 }
 
 static void check_fire_resistance(msr_type *msr_ptr)
 {
     if (msr_ptr->smart.has(SM::IMM_FIRE)) {
-        reset_bits(msr_ptr->f4, RF4_BR_FIRE);
-        reset_bits(msr_ptr->f5, RF5_BA_FIRE);
-        reset_bits(msr_ptr->f5, RF5_BO_FIRE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_FIRE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BA_FIRE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_FIRE);
         return;
     }
 
     if (msr_ptr->smart.has_all_of({SM::OPP_FIRE, SM::RES_FIRE})) {
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f4, RF4_BR_FIRE);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BR_FIRE);
 
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f5, RF5_BA_FIRE);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BA_FIRE);
 
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f5, RF5_BO_FIRE);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BO_FIRE);
 
         return;
     }
 
     if (msr_ptr->smart.has_any_of({SM::OPP_FIRE, SM::RES_FIRE})) {
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f4, RF4_BR_FIRE);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BR_FIRE);
 
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f5, RF5_BA_FIRE);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BA_FIRE);
 
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f5, RF5_BO_FIRE);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BO_FIRE);
     }
 }
 
 static void check_cold_resistance(msr_type *msr_ptr)
 {
     if (msr_ptr->smart.has(SM::IMM_COLD)) {
-        reset_bits(msr_ptr->f4, RF4_BR_COLD);
-        reset_bits(msr_ptr->f5, RF5_BA_COLD);
-        reset_bits(msr_ptr->f5, RF5_BO_COLD);
-        reset_bits(msr_ptr->f5, RF5_BO_ICEE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_COLD);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BA_COLD);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_COLD);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_ICEE);
         return;
     }
 
     if (msr_ptr->smart.has_all_of({SM::OPP_COLD, SM::RES_COLD})) {
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f4, RF4_BR_COLD);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BR_COLD);
 
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f5, RF5_BA_COLD);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BA_COLD);
 
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f5, RF5_BO_COLD);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BO_COLD);
 
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f5, RF5_BO_ICEE);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BO_ICEE);
 
         return;
     }
 
     if (msr_ptr->smart.has_any_of({SM::OPP_COLD, SM::RES_COLD})) {
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f4, RF4_BR_COLD);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BR_COLD);
 
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f5, RF5_BA_COLD);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BA_COLD);
 
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f5, RF5_BO_COLD);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BO_COLD);
 
         if (int_outof(msr_ptr->r_ptr, 20))
-            reset_bits(msr_ptr->f5, RF5_BO_ICEE);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BO_ICEE);
     }
 }
 
@@ -200,26 +198,26 @@ static void check_pois_resistance(msr_type *msr_ptr)
 {
     if (msr_ptr->smart.has_all_of({SM::OPP_POIS, SM::RES_POIS})) {
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f4, RF4_BR_POIS);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BR_POIS);
 
         if (int_outof(msr_ptr->r_ptr, 80))
-            reset_bits(msr_ptr->f5, RF5_BA_POIS);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BA_POIS);
 
         if (int_outof(msr_ptr->r_ptr, 60))
-            reset_bits(msr_ptr->f4, RF4_BA_NUKE);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BA_NUKE);
 
         if (int_outof(msr_ptr->r_ptr, 60))
-            reset_bits(msr_ptr->f4, RF4_BR_NUKE);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BR_NUKE);
 
         return;
     }
 
     if (msr_ptr->smart.has_any_of({SM::OPP_POIS, SM::RES_POIS})) {
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f4, RF4_BR_POIS);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BR_POIS);
 
         if (int_outof(msr_ptr->r_ptr, 30))
-            reset_bits(msr_ptr->f5, RF5_BA_POIS);
+            msr_ptr->ability_flags.reset(RF_ABILITY::BA_POIS);
     }
 }
 
index 7bc92bc..7ebad85 100644 (file)
@@ -1,7 +1,4 @@
 #include "mspell/high-resistance-checker.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
-#include "monster-race/race-flags4.h"
 #include "monster/smart-learn-types.h"
 #include "mspell/smart-mspell-util.h"
 #include "player/player-race.h"
@@ -59,20 +56,20 @@ static void check_nether_resistance(player_type *target_ptr, msr_type *msr_ptr)
         return;
 
     if (is_specific_player_race(target_ptr, RACE_SPECTRE)) {
-        reset_bits(msr_ptr->f4, RF4_BR_NETH);
-        reset_bits(msr_ptr->f5, RF5_BA_NETH);
-        reset_bits(msr_ptr->f5, RF5_BO_NETH);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_NETH);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BA_NETH);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_NETH);
         return;
     }
 
     if (int_outof(msr_ptr->r_ptr, 20))
-        reset_bits(msr_ptr->f4, RF4_BR_NETH);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_NETH);
 
     if (int_outof(msr_ptr->r_ptr, 50))
-        reset_bits(msr_ptr->f5, RF5_BA_NETH);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BA_NETH);
 
     if (int_outof(msr_ptr->r_ptr, 50))
-        reset_bits(msr_ptr->f5, RF5_BO_NETH);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_NETH);
 }
 
 static void check_lite_resistance(msr_type *msr_ptr)
@@ -81,10 +78,10 @@ static void check_lite_resistance(msr_type *msr_ptr)
         return;
 
     if (int_outof(msr_ptr->r_ptr, 50))
-        reset_bits(msr_ptr->f4, RF4_BR_LITE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_LITE);
 
     if (int_outof(msr_ptr->r_ptr, 50))
-        reset_bits(msr_ptr->f5, RF5_BA_LITE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BA_LITE);
 }
 
 static void check_dark_resistance(player_type *target_ptr, msr_type *msr_ptr)
@@ -93,16 +90,16 @@ static void check_dark_resistance(player_type *target_ptr, msr_type *msr_ptr)
         return;
 
     if (is_specific_player_race(target_ptr, RACE_VAMPIRE)) {
-        reset_bits(msr_ptr->f4, RF4_BR_DARK);
-        reset_bits(msr_ptr->f5, RF5_BA_DARK);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_DARK);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BA_DARK);
         return;
     }
 
     if (int_outof(msr_ptr->r_ptr, 50))
-        reset_bits(msr_ptr->f4, RF4_BR_DARK);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_DARK);
 
     if (int_outof(msr_ptr->r_ptr, 50))
-        reset_bits(msr_ptr->f5, RF5_BA_DARK);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BA_DARK);
 }
 
 static void check_conf_resistance(msr_type *msr_ptr)
@@ -110,9 +107,9 @@ static void check_conf_resistance(msr_type *msr_ptr)
     if (msr_ptr->smart.has_not(SM::RES_CONF))
         return;
 
-    reset_bits(msr_ptr->f5, RF5_CONF);
+    msr_ptr->ability_flags.reset(RF_ABILITY::CONF);
     if (int_outof(msr_ptr->r_ptr, 50))
-        reset_bits(msr_ptr->f4, RF4_BR_CONF);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_CONF);
 }
 
 static void check_chaos_resistance(msr_type *msr_ptr)
@@ -121,10 +118,10 @@ static void check_chaos_resistance(msr_type *msr_ptr)
         return;
 
     if (int_outof(msr_ptr->r_ptr, 20))
-        reset_bits(msr_ptr->f4, RF4_BR_CHAO);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_CHAO);
 
     if (int_outof(msr_ptr->r_ptr, 50))
-        reset_bits(msr_ptr->f4, RF4_BA_CHAO);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BA_CHAO);
 }
 
 static void check_nexus_resistance(msr_type *msr_ptr)
@@ -133,9 +130,9 @@ static void check_nexus_resistance(msr_type *msr_ptr)
         return;
 
     if (int_outof(msr_ptr->r_ptr, 50))
-        reset_bits(msr_ptr->f4, RF4_BR_NEXU);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_NEXU);
 
-    reset_bits(msr_ptr->f6, RF6_TELE_LEVEL);
+    msr_ptr->ability_flags.reset(RF_ABILITY::TELE_LEVEL);
 }
 
 static void check_reflection(msr_type *msr_ptr)
@@ -144,34 +141,34 @@ static void check_reflection(msr_type *msr_ptr)
         return;
 
     if (int_outof(msr_ptr->r_ptr, 150))
-        reset_bits(msr_ptr->f5, RF5_BO_COLD);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_COLD);
 
     if (int_outof(msr_ptr->r_ptr, 150))
-        reset_bits(msr_ptr->f5, RF5_BO_FIRE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_FIRE);
 
     if (int_outof(msr_ptr->r_ptr, 150))
-        reset_bits(msr_ptr->f5, RF5_BO_ACID);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_ACID);
 
     if (int_outof(msr_ptr->r_ptr, 150))
-        reset_bits(msr_ptr->f5, RF5_BO_ELEC);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_ELEC);
 
     if (int_outof(msr_ptr->r_ptr, 150))
-        reset_bits(msr_ptr->f5, RF5_BO_NETH);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_NETH);
 
     if (int_outof(msr_ptr->r_ptr, 150))
-        reset_bits(msr_ptr->f5, RF5_BO_WATE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_WATE);
 
     if (int_outof(msr_ptr->r_ptr, 150))
-        reset_bits(msr_ptr->f5, RF5_BO_MANA);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_MANA);
 
     if (int_outof(msr_ptr->r_ptr, 150))
-        reset_bits(msr_ptr->f5, RF5_BO_PLAS);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_PLAS);
 
     if (int_outof(msr_ptr->r_ptr, 150))
-        reset_bits(msr_ptr->f5, RF5_BO_ICEE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BO_ICEE);
 
     if (int_outof(msr_ptr->r_ptr, 150))
-        reset_bits(msr_ptr->f5, RF5_MISSILE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::MISSILE);
 }
 
 void check_high_resistances(player_type *target_ptr, msr_type *msr_ptr)
@@ -180,29 +177,29 @@ void check_high_resistances(player_type *target_ptr, msr_type *msr_ptr)
     check_lite_resistance(msr_ptr);
     check_dark_resistance(target_ptr, msr_ptr);
     if (msr_ptr->smart.has(SM::RES_FEAR))
-        reset_bits(msr_ptr->f5, RF5_SCARE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::SCARE);
 
     check_conf_resistance(msr_ptr);
     check_chaos_resistance(msr_ptr);
     if (msr_ptr->smart.has(SM::RES_DISEN) && int_outof(msr_ptr->r_ptr, 40))
-        reset_bits(msr_ptr->f4, RF4_BR_DISE);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_DISE);
 
     if (msr_ptr->smart.has(SM::RES_BLIND))
-        reset_bits(msr_ptr->f5, RF5_BLIND);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BLIND);
 
     check_nexus_resistance(msr_ptr);
     if (msr_ptr->smart.has(SM::RES_SOUND) && int_outof(msr_ptr->r_ptr, 50))
-        reset_bits(msr_ptr->f4, RF4_BR_SOUN);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_SOUN);
 
     if (msr_ptr->smart.has(SM::RES_SHARD) && int_outof(msr_ptr->r_ptr, 40))
-        reset_bits(msr_ptr->f4, RF4_BR_SHAR);
+        msr_ptr->ability_flags.reset(RF_ABILITY::BR_SHAR);
 
     check_reflection(msr_ptr);
     if (msr_ptr->smart.has(SM::IMM_FREE)) {
-        reset_bits(msr_ptr->f5, RF5_HOLD);
-        reset_bits(msr_ptr->f5, RF5_SLOW);
+        msr_ptr->ability_flags.reset(RF_ABILITY::HOLD);
+        msr_ptr->ability_flags.reset(RF_ABILITY::SLOW);
     }
 
     if (msr_ptr->smart.has(SM::IMM_MANA))
-        reset_bits(msr_ptr->f5, RF5_DRAIN_MANA);
+        msr_ptr->ability_flags.reset(RF_ABILITY::DRAIN_MANA);
 }
index 3909962..2b5ee02 100644 (file)
@@ -27,10 +27,10 @@ static void add_cheat_remove_flags(player_type *target_ptr, msr_type *msr_ptr)
  * @param f6p モンスター魔法のフラグリスト3
  * @return なし
  */
-void remove_bad_spells(MONSTER_IDX m_idx, player_type *target_ptr, u32b *f4p, u32b *f5p, u32b *f6p)
+void remove_bad_spells(MONSTER_IDX m_idx, player_type *target_ptr, FlagGroup<RF_ABILITY>& ability_flags)
 {
     msr_type tmp_msr;
-    msr_type *msr_ptr = initialize_msr_type(target_ptr, &tmp_msr, m_idx, *f4p, *f5p, *f6p);
+    msr_type *msr_ptr = initialize_msr_type(target_ptr, &tmp_msr, m_idx, ability_flags);
     if (msr_ptr->r_ptr->flags2 & RF2_STUPID)
         return;
 
@@ -52,7 +52,5 @@ void remove_bad_spells(MONSTER_IDX m_idx, player_type *target_ptr, u32b *f4p, u3
 
     check_element_resistance(msr_ptr);
     check_high_resistances(target_ptr, msr_ptr);
-    *f4p = msr_ptr->f4;
-    *f5p = msr_ptr->f5;
-    *f6p = msr_ptr->f6;
+    ability_flags = msr_ptr->ability_flags;
 }
index 7b5bebf..0f5ad81 100644 (file)
@@ -2,4 +2,4 @@
 
 #include "system/angband.h"
 
-void remove_bad_spells(MONSTER_IDX m_idx, player_type *target_ptr, u32b *f4p, u32b *f5p, u32b *f6p);
+void remove_bad_spells(MONSTER_IDX m_idx, player_type *target_ptr, FlagGroup<RF_ABILITY>& ability_flags);
index a6c295c..a0db412 100644 (file)
@@ -9,16 +9,13 @@ msa_type *initialize_msa_type(player_type *target_ptr, msa_type *msa_ptr, MONSTE
     msa_ptr->m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
     msa_ptr->r_ptr = &r_info[msa_ptr->m_ptr->r_idx];
     msa_ptr->no_inate = randint0(100) >= (msa_ptr->r_ptr->freq_spell * 2);
-    msa_ptr->f4 = msa_ptr->r_ptr->flags4;
-    msa_ptr->f5 = msa_ptr->r_ptr->a_ability_flags1;
-    msa_ptr->f6 = msa_ptr->r_ptr->a_ability_flags2;
+    msa_ptr->ability_flags = msa_ptr->r_ptr->ability_flags;
     msa_ptr->x = target_ptr->x;
     msa_ptr->y = target_ptr->y;
     msa_ptr->x_br_lite = 0;
     msa_ptr->y_br_lite = 0;
     msa_ptr->do_spell = DO_SPELL_NONE;
     msa_ptr->dam = 0;
-    msa_ptr->num = 0;
-    msa_ptr->thrown_spell = 0;
+    msa_ptr->thrown_spell = RF_ABILITY::MAX;
     return msa_ptr;
 }
index ba35beb..6c4dadf 100644 (file)
@@ -2,6 +2,11 @@
 
 #include "system/angband.h"
 
+#include "monster-race/race-ability-flags.h"
+#include "util/flag-group.h"
+
+#include <vector>
+
 enum mspell_lite_type {
     DO_SPELL_NONE = 0,
     DO_SPELL_BR_LITE = 1,
@@ -17,9 +22,7 @@ typedef struct msa_type {
     monster_type *m_ptr;
     monster_race *r_ptr;
     bool no_inate;
-    BIT_FLAGS f4;
-    BIT_FLAGS f5;
-    BIT_FLAGS f6;
+    FlagGroup<RF_ABILITY> ability_flags;
     POSITION x;
     POSITION y;
     POSITION x_br_lite;
@@ -27,9 +30,8 @@ typedef struct msa_type {
     mspell_lite_type do_spell;
     bool in_no_magic_dungeon;
     bool success;
-    byte mspells[96];
-    byte num;
-    SPELL_IDX thrown_spell;
+    std::vector<RF_ABILITY> mspells;
+    RF_ABILITY thrown_spell;
     GAME_TEXT m_name[MAX_NLEN];
     bool can_remember;
     int dam;
index bf96453..580f927 100644 (file)
@@ -8,10 +8,8 @@
 #include "floor/cave.h"
 #include "monster-floor/monster-move.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
+#include "monster-race/race-ability-mask.h"
 #include "monster-race/race-flags2.h"
-#include "monster-race/race-flags4.h"
 #include "monster-race/race-indice-types.h"
 #include "monster/monster-describer.h"
 #include "monster/monster-flag-types.h"
@@ -23,7 +21,6 @@
 #include "mspell/mspell-checker.h"
 #include "mspell/mspell-learn-checker.h"
 #include "mspell/mspell-lite.h"
-#include "mspell/mspell-mask-definitions.h"
 #include "mspell/mspell-selector.h"
 #include "mspell/mspell-type.h"
 #include "mspell/mspell-util.h"
@@ -45,9 +42,7 @@ static void set_no_magic_mask(msa_type *msa_ptr)
     if (!msa_ptr->no_inate)
         return;
 
-    msa_ptr->f4 &= ~(RF4_NOMAGIC_MASK);
-    msa_ptr->f5 &= ~(RF5_NOMAGIC_MASK);
-    msa_ptr->f6 &= ~(RF6_NOMAGIC_MASK);
+    msa_ptr->ability_flags.reset(RF_ABILITY_NOMAGIC_MASK);
 }
 
 static void check_mspell_stupid(player_type *target_ptr, msa_type *msa_ptr)
@@ -58,9 +53,7 @@ static void check_mspell_stupid(player_type *target_ptr, msa_type *msa_ptr)
     if (!msa_ptr->in_no_magic_dungeon || ((msa_ptr->r_ptr->flags2 & RF2_STUPID) != 0))
         return;
 
-    msa_ptr->f4 &= RF4_NOMAGIC_MASK;
-    msa_ptr->f5 &= RF5_NOMAGIC_MASK;
-    msa_ptr->f6 &= RF6_NOMAGIC_MASK;
+    msa_ptr->ability_flags &= RF_ABILITY_NOMAGIC_MASK;
 }
 
 static void check_mspell_smart(player_type *target_ptr, msa_type *msa_ptr)
@@ -69,13 +62,11 @@ static void check_mspell_smart(player_type *target_ptr, msa_type *msa_ptr)
         return;
 
     if ((msa_ptr->m_ptr->hp < msa_ptr->m_ptr->maxhp / 10) && (randint0(100) < 50)) {
-        msa_ptr->f4 &= (RF4_INT_MASK);
-        msa_ptr->f5 &= (RF5_INT_MASK);
-        msa_ptr->f6 &= (RF6_INT_MASK);
+        msa_ptr->ability_flags &= RF_ABILITY_INT_MASK;
     }
 
-    if ((msa_ptr->f6 & RF6_TELE_LEVEL) && is_teleport_level_ineffective(target_ptr, 0)) {
-        msa_ptr->f6 &= ~(RF6_TELE_LEVEL);
+    if (msa_ptr->ability_flags.has(RF_ABILITY::TELE_LEVEL) && is_teleport_level_ineffective(target_ptr, 0)) {
+        msa_ptr->ability_flags.reset(RF_ABILITY::TELE_LEVEL);
     }
 }
 
@@ -84,12 +75,10 @@ static void check_mspell_arena(player_type *target_ptr, msa_type *msa_ptr)
     if (!target_ptr->current_floor_ptr->inside_arena && !target_ptr->phase_out)
         return;
 
-    msa_ptr->f4 &= ~(RF4_SUMMON_MASK);
-    msa_ptr->f5 &= ~(RF5_SUMMON_MASK);
-    msa_ptr->f6 &= ~(RF6_SUMMON_MASK | RF6_TELE_LEVEL);
+    msa_ptr->ability_flags.reset(RF_ABILITY_SUMMON_MASK).reset(RF_ABILITY::TELE_LEVEL);
 
     if (msa_ptr->m_ptr->r_idx == MON_ROLENTO)
-        msa_ptr->f6 &= ~(RF6_SPECIAL);
+        msa_ptr->ability_flags.reset(RF_ABILITY::SPECIAL);
 }
 
 static bool check_mspell_non_stupid(player_type *target_ptr, msa_type *msa_ptr)
@@ -98,44 +87,30 @@ static bool check_mspell_non_stupid(player_type *target_ptr, msa_type *msa_ptr)
         return TRUE;
 
     if (!target_ptr->csp)
-        msa_ptr->f5 &= ~(RF5_DRAIN_MANA);
+        msa_ptr->ability_flags.reset(RF_ABILITY::DRAIN_MANA);
 
-    if (((msa_ptr->f4 & RF4_BOLT_MASK) || (msa_ptr->f5 & RF5_BOLT_MASK) || (msa_ptr->f6 & RF6_BOLT_MASK))
+    if (msa_ptr->ability_flags.has_any_of(RF_ABILITY_BOLT_MASK)
         && !clean_shot(target_ptr, msa_ptr->m_ptr->fy, msa_ptr->m_ptr->fx, target_ptr->y, target_ptr->x, FALSE)) {
-        msa_ptr->f4 &= ~(RF4_BOLT_MASK);
-        msa_ptr->f5 &= ~(RF5_BOLT_MASK);
-        msa_ptr->f6 &= ~(RF6_BOLT_MASK);
+        msa_ptr->ability_flags.reset(RF_ABILITY_BOLT_MASK);
     }
 
-    if (((msa_ptr->f4 & RF4_SUMMON_MASK) || (msa_ptr->f5 & RF5_SUMMON_MASK) || (msa_ptr->f6 & RF6_SUMMON_MASK))
+    if (msa_ptr->ability_flags.has_any_of(RF_ABILITY_SUMMON_MASK)
         && !(summon_possible(target_ptr, msa_ptr->y, msa_ptr->x))) {
-        msa_ptr->f4 &= ~(RF4_SUMMON_MASK);
-        msa_ptr->f5 &= ~(RF5_SUMMON_MASK);
-        msa_ptr->f6 &= ~(RF6_SUMMON_MASK);
+        msa_ptr->ability_flags.reset(RF_ABILITY_SUMMON_MASK);
     }
 
-    if ((msa_ptr->f6 & RF6_RAISE_DEAD) && !raise_possible(target_ptr, msa_ptr->m_ptr))
-        msa_ptr->f6 &= ~(RF6_RAISE_DEAD);
+    if (msa_ptr->ability_flags.has(RF_ABILITY::RAISE_DEAD) && !raise_possible(target_ptr, msa_ptr->m_ptr))
+        msa_ptr->ability_flags.reset(RF_ABILITY::RAISE_DEAD);
 
-    if (((msa_ptr->f6 & RF6_SPECIAL) != 0) && (msa_ptr->m_ptr->r_idx == MON_ROLENTO) && !summon_possible(target_ptr, msa_ptr->y, msa_ptr->x))
-        msa_ptr->f6 &= ~(RF6_SPECIAL);
+    if (msa_ptr->ability_flags.has(RF_ABILITY::SPECIAL) && (msa_ptr->m_ptr->r_idx == MON_ROLENTO) && !summon_possible(target_ptr, msa_ptr->y, msa_ptr->x))
+        msa_ptr->ability_flags.reset(RF_ABILITY::SPECIAL);
 
-    return (msa_ptr->f4 != 0) || (msa_ptr->f5 != 0) || (msa_ptr->f6 != 0);
+    return msa_ptr->ability_flags.any();
 }
 
 static void set_mspell_list(msa_type *msa_ptr)
 {
-    for (int k = 0; k < 32; k++)
-        if (msa_ptr->f4 & (1UL << k))
-            msa_ptr->mspells[msa_ptr->num++] = k + RF4_SPELL_START;
-
-    for (int k = 0; k < 32; k++)
-        if (msa_ptr->f5 & (1UL << k))
-            msa_ptr->mspells[msa_ptr->num++] = k + RF5_SPELL_START;
-
-    for (int k = 0; k < 32; k++)
-        if (msa_ptr->f6 & (1UL << k))
-            msa_ptr->mspells[msa_ptr->num++] = k + RF6_SPELL_START;
+    FlagGroup<RF_ABILITY>::get_flags(msa_ptr->ability_flags, std::back_inserter(msa_ptr->mspells));
 }
 
 static void describe_mspell_monster(player_type *target_ptr, msa_type *msa_ptr)
@@ -157,20 +132,20 @@ static bool switch_do_spell(player_type *target_ptr, msa_type *msa_ptr)
         int attempt = 10;
         while (attempt--) {
             msa_ptr->thrown_spell = choose_attack_spell(target_ptr, msa_ptr);
-            if (msa_ptr->thrown_spell)
+            if (msa_ptr->thrown_spell != RF_ABILITY::MAX)
                 break;
         }
 
         return TRUE;
     }
     case DO_SPELL_BR_LITE:
-        msa_ptr->thrown_spell = 96 + 14; /* RF4_BR_LITE */
+        msa_ptr->thrown_spell = RF_ABILITY::BR_LITE;
         return TRUE;
     case DO_SPELL_BR_DISI:
-        msa_ptr->thrown_spell = 96 + 31; /* RF4_BR_DISI */
+        msa_ptr->thrown_spell = RF_ABILITY::BR_DISI;
         return TRUE;
     case DO_SPELL_BA_LITE:
-        msa_ptr->thrown_spell = 128 + 20; /* RF5_BA_LITE */
+        msa_ptr->thrown_spell = RF_ABILITY::BA_LITE;
         return TRUE;
     default:
         return FALSE;
@@ -179,20 +154,20 @@ static bool switch_do_spell(player_type *target_ptr, msa_type *msa_ptr)
 
 static bool check_mspell_continuation(player_type *target_ptr, msa_type *msa_ptr)
 {
-    if ((msa_ptr->f4 == 0) && (msa_ptr->f5 == 0) && (msa_ptr->f6 == 0))
+    if (msa_ptr->ability_flags.none())
         return FALSE;
 
-    remove_bad_spells(msa_ptr->m_idx, target_ptr, &msa_ptr->f4, &msa_ptr->f5, &msa_ptr->f6);
+    remove_bad_spells(msa_ptr->m_idx, target_ptr, msa_ptr->ability_flags);
     check_mspell_arena(target_ptr, msa_ptr);
-    if (((msa_ptr->f4 == 0) && (msa_ptr->f5 == 0) && (msa_ptr->f6 == 0)) || !check_mspell_non_stupid(target_ptr, msa_ptr))
+    if (msa_ptr->ability_flags.none() || !check_mspell_non_stupid(target_ptr, msa_ptr))
         return FALSE;
 
     set_mspell_list(msa_ptr);
-    if ((msa_ptr->num == 0) || !target_ptr->playing || target_ptr->is_dead || target_ptr->leaving)
+    if (msa_ptr->mspells.empty() || !target_ptr->playing || target_ptr->is_dead || target_ptr->leaving)
         return FALSE;
 
     describe_mspell_monster(target_ptr, msa_ptr);
-    if (!switch_do_spell(target_ptr, msa_ptr) || (msa_ptr->thrown_spell == 0))
+    if (!switch_do_spell(target_ptr, msa_ptr) || (msa_ptr->thrown_spell == RF_ABILITY::MAX))
         return FALSE;
 
     return TRUE;
@@ -238,37 +213,37 @@ static bool check_thrown_mspell(player_type *target_ptr, msa_type *msa_ptr)
     // ターゲットがプレイヤー位置からずれているとき、直接の射線を必要とする特技
     // (ボルト系など)は届かないものとみなす。
     switch (msa_ptr->thrown_spell) {
-    case 96 + 2: /* RF4_DISPEL */
-    case 96 + 4: /* RF4_SHOOT */
-    case 128 + 9: /* RF5_DRAIN_MANA */
-    case 128 + 10: /* RF5_MIND_BLAST */
-    case 128 + 11: /* RF5_BRAIN_SMASH */
-    case 128 + 12: /* RF5_CAUSE_1 */
-    case 128 + 13: /* RF5_CAUSE_2 */
-    case 128 + 14: /* RF5_CAUSE_3 */
-    case 128 + 15: /* RF5_CAUSE_4 */
-    case 128 + 16: /* RF5_BO_ACID */
-    case 128 + 17: /* RF5_BO_ELEC */
-    case 128 + 18: /* RF5_BO_FIRE */
-    case 128 + 19: /* RF5_BO_COLD */
-    case 128 + 21: /* RF5_BO_NETH */
-    case 128 + 22: /* RF5_BO_WATE */
-    case 128 + 23: /* RF5_BO_MANA */
-    case 128 + 24: /* RF5_BO_PLAS */
-    case 128 + 25: /* RF5_BO_ICEE */
-    case 128 + 26: /* RF5_MISSILE */
-    case 128 + 27: /* RF5_SCARE */
-    case 128 + 28: /* RF5_BLIND */
-    case 128 + 29: /* RF5_CONF */
-    case 128 + 30: /* RF5_SLOW */
-    case 128 + 31: /* RF5_HOLD */
-    case 160 + 1: /* RF6_HAND_DOOM */
-    case 160 + 8: /* RF6_TELE_TO */
-    case 160 + 9: /* RF6_TELE_AWAY */
-    case 160 + 10: /* RF6_TELE_LEVEL */
-    case 160 + 11: /* RF6_PSY_SPEAR */
-    case 160 + 12: /* RF6_DARKNESS */
-    case 160 + 14: /* RF6_FORGET */
+    case RF_ABILITY::DISPEL:
+    case RF_ABILITY::SHOOT:
+    case RF_ABILITY::DRAIN_MANA:
+    case RF_ABILITY::MIND_BLAST:
+    case RF_ABILITY::BRAIN_SMASH:
+    case RF_ABILITY::CAUSE_1:
+    case RF_ABILITY::CAUSE_2:
+    case RF_ABILITY::CAUSE_3:
+    case RF_ABILITY::CAUSE_4:
+    case RF_ABILITY::BO_ACID:
+    case RF_ABILITY::BO_ELEC:
+    case RF_ABILITY::BO_FIRE:
+    case RF_ABILITY::BO_COLD:
+    case RF_ABILITY::BO_NETH:
+    case RF_ABILITY::BO_WATE:
+    case RF_ABILITY::BO_MANA:
+    case RF_ABILITY::BO_PLAS:
+    case RF_ABILITY::BO_ICEE:
+    case RF_ABILITY::MISSILE:
+    case RF_ABILITY::SCARE:
+    case RF_ABILITY::BLIND:
+    case RF_ABILITY::CONF:
+    case RF_ABILITY::SLOW:
+    case RF_ABILITY::HOLD:
+    case RF_ABILITY::HAND_DOOM:
+    case RF_ABILITY::TELE_TO:
+    case RF_ABILITY::TELE_AWAY:
+    case RF_ABILITY::TELE_LEVEL:
+    case RF_ABILITY::PSY_SPEAR:
+    case RF_ABILITY::DARKNESS:
+    case RF_ABILITY::FORGET:
         return FALSE;
     default:
         return TRUE;
@@ -282,8 +257,8 @@ static void check_mspell_imitation(player_type *target_ptr, msa_type *msa_ptr)
     if (!seen || !can_imitate || (current_world_ptr->timewalk_m_idx != 0) || (target_ptr->pclass != CLASS_IMITATOR))
         return;
 
-    /* Not RF6_SPECIAL */
-    if (msa_ptr->thrown_spell == 167)
+    /* Not RF_ABILITY::SPECIAL */
+    if (msa_ptr->thrown_spell == RF_ABILITY::SPECIAL)
         return;
 
     if (target_ptr->mane_num == MAX_MANE) {
@@ -294,7 +269,7 @@ static void check_mspell_imitation(player_type *target_ptr, msa_type *msa_ptr)
         }
     }
 
-    target_ptr->mane_spell[target_ptr->mane_num] = msa_ptr->thrown_spell - 96;
+    target_ptr->mane_spell[target_ptr->mane_num] = msa_ptr->thrown_spell;
     target_ptr->mane_dam[target_ptr->mane_num] = msa_ptr->dam;
     target_ptr->mane_num++;
     target_ptr->new_mane = TRUE;
@@ -306,27 +281,9 @@ static void remember_mspell(msa_type *msa_ptr)
     if (!msa_ptr->can_remember)
         return;
 
-    if (msa_ptr->thrown_spell < 32 * 4) {
-        msa_ptr->r_ptr->r_flags4 |= (1UL << (msa_ptr->thrown_spell - 32 * 3));
-        if (msa_ptr->r_ptr->r_cast_spell < MAX_UCHAR)
-            msa_ptr->r_ptr->r_cast_spell++;
-
-        return;
-    }
-
-    if (msa_ptr->thrown_spell < 32 * 5) {
-        msa_ptr->r_ptr->r_flags5 |= (1UL << (msa_ptr->thrown_spell - 32 * 4));
-        if (msa_ptr->r_ptr->r_cast_spell < MAX_UCHAR)
-            msa_ptr->r_ptr->r_cast_spell++;
-
-        return;
-    }
-
-    if (msa_ptr->thrown_spell < 32 * 6) {
-        msa_ptr->r_ptr->r_flags6 |= (1UL << (msa_ptr->thrown_spell - 32 * 5));
-        if (msa_ptr->r_ptr->r_cast_spell < MAX_UCHAR)
-            msa_ptr->r_ptr->r_cast_spell++;
-    }
+    msa_ptr->r_ptr->r_ability_flags.set(msa_ptr->thrown_spell);
+    if (msa_ptr->r_ptr->r_cast_spell < MAX_UCHAR)
+        msa_ptr->r_ptr->r_cast_spell++;
 }
 
 /*!
index 9c38511..261d1b4 100644 (file)
 #include "grid/grid.h"
 #include "monster-floor/monster-move.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
+#include "monster-race/race-ability-mask.h"
 #include "monster-race/race-flags2.h"
 #include "monster-race/race-flags3.h"
-#include "monster-race/race-flags4.h"
 #include "monster-race/race-flags7.h"
 #include "monster-race/race-indice-types.h"
 #include "monster/monster-describer.h"
@@ -39,7 +37,6 @@
 #include "mspell/improper-mspell-remover.h"
 #include "mspell/mspell-judgement.h"
 #include "mspell/mspell-learn-checker.h"
-#include "mspell/mspell-mask-definitions.h"
 #include "mspell/mspell-selector.h"
 #include "mspell/mspell-util.h"
 #include "object-enchant/object-curse.h"
@@ -291,21 +288,7 @@ ProjectResult breath(
  * @param spell 判定対象のID
  * @return 非魔術的な特殊技能ならばTRUEを返す。
  */
-bool spell_is_inate(SPELL_IDX spell)
+bool spell_is_inate(RF_ABILITY spell)
 {
-    if (32 * 3 <= spell && spell < 32 * 4) /* Set RF4 */
-    {
-        return ((1UL << (spell - 32 * 3)) & RF4_NOMAGIC_MASK) != 0;
-    }
-    if (32 * 4 <= spell && spell < 32 * 5) /* Set RF5 */
-    {
-        return ((1UL << (spell - 32 * 4)) & RF5_NOMAGIC_MASK) != 0;
-    }
-    if (32 * 5 <= spell && spell < 32 * 6) /* Set RF6 */
-    {
-        return ((1UL << (spell - 32 * 5)) & RF6_NOMAGIC_MASK) != 0;
-    }
-
-    // 無効なモンスタースペルIDが渡されたら FALSE を返す。
-    return FALSE;
+    return RF_ABILITY_NOMAGIC_MASK.has(spell);
 }
index 3ada118..639129d 100644 (file)
@@ -4,11 +4,12 @@
 #include "system/monster-type-definition.h"
 
 struct ProjectResult;
+enum class RF_ABILITY;
 
 bool clean_shot(player_type *target_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2, bool is_friend);
 bool summon_possible(player_type *target_ptr, POSITION y1, POSITION x1);
 bool raise_possible(player_type *target_ptr, monster_type *m_ptr);
-bool spell_is_inate(SPELL_IDX spell);
+bool spell_is_inate(RF_ABILITY spell);
 ProjectResult beam(player_type *target_ptr, MONSTER_IDX m_idx, POSITION y, POSITION x, EFFECT_ID typ, int dam_hp, int monspell, int target_type);
 ProjectResult bolt(player_type *target_ptr, MONSTER_IDX m_idx, POSITION y, POSITION x, EFFECT_ID typ, int dam_hp, int monspell, int target_type);
 ProjectResult breath(
index a091d4b..f78dee9 100644 (file)
@@ -18,7 +18,6 @@
 #include "main/sound-definitions-table.h"
 #include "monster-race/monster-race.h"
 #include "monster-race/race-flags-resistance.h"
-#include "monster-race/race-flags4.h"
 #include "monster/monster-info.h"
 #include "monster/monster-status.h"
 #include "player/attack-defense-types.h"
@@ -254,7 +253,7 @@ bool dispel_check(player_type *creature_ptr, MONSTER_IDX m_idx)
 
     monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx];
     monster_race *r_ptr = &r_info[m_ptr->r_idx];
-    if (r_ptr->flags4 & RF4_BR_ACID) {
+    if (r_ptr->ability_flags.has(RF_ABILITY::BR_ACID)) {
         if (!has_immune_acid(creature_ptr) && (creature_ptr->oppose_acid || music_singing(creature_ptr, MUSIC_RESIST)))
             return TRUE;
 
@@ -262,7 +261,7 @@ bool dispel_check(player_type *creature_ptr, MONSTER_IDX m_idx)
             return TRUE;
     }
 
-    if (r_ptr->flags4 & RF4_BR_FIRE) {
+    if (r_ptr->ability_flags.has(RF_ABILITY::BR_FIRE)) {
         if (!((creature_ptr->prace == RACE_BALROG) && creature_ptr->lev > 44)) {
             if (!has_immune_fire(creature_ptr) && (creature_ptr->oppose_fire || music_singing(creature_ptr, MUSIC_RESIST)))
                 return TRUE;
@@ -272,7 +271,7 @@ bool dispel_check(player_type *creature_ptr, MONSTER_IDX m_idx)
         }
     }
 
-    if (r_ptr->flags4 & RF4_BR_ELEC) {
+    if (r_ptr->ability_flags.has(RF_ABILITY::BR_ELEC)) {
         if (!has_immune_elec(creature_ptr) && (creature_ptr->oppose_elec || music_singing(creature_ptr, MUSIC_RESIST)))
             return TRUE;
 
@@ -280,7 +279,7 @@ bool dispel_check(player_type *creature_ptr, MONSTER_IDX m_idx)
             return TRUE;
     }
 
-    if (r_ptr->flags4 & RF4_BR_COLD) {
+    if (r_ptr->ability_flags.has(RF_ABILITY::BR_COLD)) {
         if (!has_immune_cold(creature_ptr) && (creature_ptr->oppose_cold || music_singing(creature_ptr, MUSIC_RESIST)))
             return TRUE;
 
@@ -288,7 +287,7 @@ bool dispel_check(player_type *creature_ptr, MONSTER_IDX m_idx)
             return TRUE;
     }
 
-    if (((r_ptr->flags4 & (RF4_BR_POIS | RF4_BR_NUKE)) != 0) && !((creature_ptr->pclass == CLASS_NINJA) && (creature_ptr->lev > 44))) {
+    if (r_ptr->ability_flags.has_any_of({ RF_ABILITY::BR_POIS, RF_ABILITY::BR_NUKE }) && !((creature_ptr->pclass == CLASS_NINJA) && (creature_ptr->lev > 44))) {
         if (creature_ptr->oppose_pois || music_singing(creature_ptr, MUSIC_RESIST))
             return TRUE;
 
index 3ee51ab..e803cfb 100644 (file)
 #include "grid/feature.h"
 #include "grid/grid.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
+#include "monster-race/race-ability-mask.h"
 #include "monster-race/race-flags2.h"
 #include "monster-race/race-flags3.h"
-#include "monster-race/race-flags4.h"
 #include "monster-race/race-flags7.h"
 #include "mspell/mspell-attack-util.h"
 #include "mspell/mspell-judgement.h"
-#include "mspell/mspell-mask-definitions.h"
 #include "spell/range-calc.h"
 #include "system/floor-type-definition.h"
 #include "system/monster-type-definition.h"
@@ -72,7 +69,7 @@ bool adjacent_grid_check(player_type *target_ptr, monster_type *m_ptr, POSITION
 
 void decide_lite_range(player_type *target_ptr, msa_type *msa_ptr)
 {
-    if ((msa_ptr->f4 & RF4_BR_LITE) == 0)
+    if (msa_ptr->ability_flags.has_not(RF_ABILITY::BR_LITE))
         return;
 
     msa_ptr->y_br_lite = msa_ptr->y;
@@ -80,11 +77,11 @@ void decide_lite_range(player_type *target_ptr, msa_type *msa_ptr)
     if (los(target_ptr, msa_ptr->m_ptr->fy, msa_ptr->m_ptr->fx, msa_ptr->y_br_lite, msa_ptr->x_br_lite)) {
         feature_type *f_ptr = &f_info[target_ptr->current_floor_ptr->grid_array[msa_ptr->y_br_lite][msa_ptr->x_br_lite].feat];
         if (!has_flag(f_ptr->flags, FF_LOS) && has_flag(f_ptr->flags, FF_PROJECT) && one_in_(2))
-            msa_ptr->f4 &= ~(RF4_BR_LITE);
+            msa_ptr->ability_flags.reset(RF_ABILITY::BR_LITE);
     } else if (!adjacent_grid_check(target_ptr, msa_ptr->m_ptr, &msa_ptr->y_br_lite, &msa_ptr->x_br_lite, FF_LOS, los))
-        msa_ptr->f4 &= ~(RF4_BR_LITE);
+        msa_ptr->ability_flags.reset(RF_ABILITY::BR_LITE);
 
-    if ((msa_ptr->f4 & RF4_BR_LITE) != 0)
+    if (msa_ptr->ability_flags.has(RF_ABILITY::BR_LITE))
         return;
 
     msa_ptr->y_br_lite = 0;
@@ -97,18 +94,18 @@ static void feature_projection(floor_type *floor_ptr, msa_type *msa_ptr)
     if (has_flag(f_ptr->flags, FF_PROJECT))
         return;
 
-    if ((msa_ptr->f4 & RF4_BR_DISI) && has_flag(f_ptr->flags, FF_HURT_DISI) && one_in_(2)) {
+    if (msa_ptr->ability_flags.has(RF_ABILITY::BR_DISI) && has_flag(f_ptr->flags, FF_HURT_DISI) && one_in_(2)) {
         msa_ptr->do_spell = DO_SPELL_BR_DISI;
         return;
     }
 
-    if ((msa_ptr->f4 & RF4_BR_LITE) && has_flag(f_ptr->flags, FF_LOS) && one_in_(2))
+    if (msa_ptr->ability_flags.has(RF_ABILITY::BR_LITE) && has_flag(f_ptr->flags, FF_LOS) && one_in_(2))
         msa_ptr->do_spell = DO_SPELL_BR_LITE;
 }
 
 static void check_lite_area_by_mspell(player_type *target_ptr, msa_type *msa_ptr)
 {
-    if ((msa_ptr->f4 & RF4_BR_DISI) && (msa_ptr->m_ptr->cdis < get_max_range(target_ptr) / 2)
+    if (msa_ptr->ability_flags.has(RF_ABILITY::BR_DISI) && (msa_ptr->m_ptr->cdis < get_max_range(target_ptr) / 2)
         && in_disintegration_range(target_ptr->current_floor_ptr, msa_ptr->m_ptr->fy, msa_ptr->m_ptr->fx, msa_ptr->y, msa_ptr->x)
         && (one_in_(10) || (projectable(target_ptr, msa_ptr->y, msa_ptr->x, msa_ptr->m_ptr->fy, msa_ptr->m_ptr->fx) && one_in_(2)))) {
         msa_ptr->do_spell = DO_SPELL_BR_DISI;
@@ -116,14 +113,14 @@ static void check_lite_area_by_mspell(player_type *target_ptr, msa_type *msa_ptr
         return;
     }
 
-    if ((msa_ptr->f4 & RF4_BR_LITE) && (msa_ptr->m_ptr->cdis < get_max_range(target_ptr) / 2)
+    if (msa_ptr->ability_flags.has(RF_ABILITY::BR_LITE) && (msa_ptr->m_ptr->cdis < get_max_range(target_ptr) / 2)
         && los(target_ptr, msa_ptr->m_ptr->fy, msa_ptr->m_ptr->fx, msa_ptr->y, msa_ptr->x) && one_in_(5)) {
         msa_ptr->do_spell = DO_SPELL_BR_LITE;
         msa_ptr->success = TRUE;
         return;
     }
 
-    if (((msa_ptr->f5 & RF5_BA_LITE) == 0) || (msa_ptr->m_ptr->cdis > get_max_range(target_ptr)))
+    if (msa_ptr->ability_flags.has_not(RF_ABILITY::BA_LITE) || (msa_ptr->m_ptr->cdis > get_max_range(target_ptr)))
         return;
 
     POSITION by = msa_ptr->y, bx = msa_ptr->x;
@@ -142,9 +139,7 @@ static void decide_lite_breath(player_type *target_ptr, msa_type *msa_ptr)
     if (msa_ptr->m_ptr->target_y && msa_ptr->m_ptr->target_x) {
         msa_ptr->y = msa_ptr->m_ptr->target_y;
         msa_ptr->x = msa_ptr->m_ptr->target_x;
-        msa_ptr->f4 &= RF4_INDIRECT_MASK;
-        msa_ptr->f5 &= RF5_INDIRECT_MASK;
-        msa_ptr->f6 &= RF6_INDIRECT_MASK;
+        msa_ptr->ability_flags &= RF_ABILITY_INDIRECT_MASK;
         msa_ptr->success = TRUE;
     }
 
@@ -152,7 +147,7 @@ static void decide_lite_breath(player_type *target_ptr, msa_type *msa_ptr)
         return;
 
     if (msa_ptr->success) {
-        msa_ptr->f4 |= RF4_BR_LITE;
+        msa_ptr->ability_flags.set(RF_ABILITY::BR_LITE);
         return;
     }
 
@@ -180,7 +175,7 @@ bool decide_lite_projection(player_type *target_ptr, msa_type *msa_ptr)
 
 void decide_lite_area(player_type *target_ptr, msa_type *msa_ptr)
 {
-    if ((msa_ptr->f6 & RF6_DARKNESS) == 0)
+    if (msa_ptr->ability_flags.has_not(RF_ABILITY::DARKNESS))
         return;
 
     bool can_use_lite_area = (target_ptr->pclass == CLASS_NINJA) && ((msa_ptr->r_ptr->flags3 & (RF3_UNDEAD | RF3_HURT_LITE)) == 0)
@@ -190,10 +185,10 @@ void decide_lite_area(player_type *target_ptr, msa_type *msa_ptr)
         return;
 
     if (d_info[target_ptr->dungeon_idx].flags1 & DF1_DARKNESS) {
-        msa_ptr->f6 &= ~(RF6_DARKNESS);
+        msa_ptr->ability_flags.reset(RF_ABILITY::DARKNESS);
         return;
     }
 
     if ((target_ptr->pclass == CLASS_NINJA) && !can_use_lite_area)
-        msa_ptr->f6 &= ~(RF6_DARKNESS);
+        msa_ptr->ability_flags.reset(RF_ABILITY::DARKNESS);
 }
diff --git a/src/mspell/mspell-mask-definitions.h b/src/mspell/mspell-mask-definitions.h
deleted file mode 100644 (file)
index 00ef951..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-#pragma once
-
-/* "summon" spells currently "summon" spells are included in "intelligent" and "indirect" */
-#define RF4_SUMMON_MASK 0UL
-
-#define RF5_SUMMON_MASK 0UL
-
-#define RF6_SUMMON_MASK                                                                                                                                        \
-    (RF6_S_KIN | RF6_S_CYBER | RF6_S_MONSTER | RF6_S_MONSTERS | RF6_S_ANT | RF6_S_SPIDER | RF6_S_HOUND | RF6_S_HYDRA | RF6_S_ANGEL | RF6_S_DEMON               \
-        | RF6_S_UNDEAD | RF6_S_DRAGON | RF6_S_HI_UNDEAD | RF6_S_HI_DRAGON | RF6_S_AMBERITES | RF6_S_UNIQUE)
-
-/* Choose "intelligent" spells when desperate Including "summon" spells */
-#define RF4_INT_MASK (RF4_SUMMON_MASK | RF4_DISPEL)
-
-#define RF5_INT_MASK (RF5_SUMMON_MASK | RF5_HOLD | RF5_SLOW | RF5_CONF | RF5_BLIND | RF5_SCARE)
-
-#define RF6_INT_MASK (RF6_SUMMON_MASK | RF6_BLINK | RF6_TPORT | RF6_TELE_LEVEL | RF6_TELE_AWAY | RF6_HEAL | RF6_INVULNER | RF6_HASTE | RF6_TRAPS)
-
-/* Spells that cannot be used while player riding on the monster */
-#define RF4_RIDING_MASK (RF4_SHRIEK)
-
-#define RF5_RIDING_MASK 0UL
-
-#define RF6_RIDING_MASK (RF6_BLINK | RF6_TPORT | RF6_TRAPS | RF6_DARKNESS | RF6_SPECIAL)
-
-/*
- * "bolt" spells that may hurt fellow monsters
- * Currently "bolt" spells are included in "attack"
- */
-#define RF4_BOLT_MASK (RF4_ROCKET | RF4_SHOOT)
-
-#define RF5_BOLT_MASK                                                                                                                                          \
-    (RF5_BO_ACID | RF5_BO_ELEC | RF5_BO_FIRE | RF5_BO_COLD | RF5_BO_NETH | RF5_BO_WATE | RF5_BO_MANA | RF5_BO_PLAS | RF5_BO_ICEE | RF5_MISSILE)
-
-#define RF6_BOLT_MASK 0UL
-
-/*
- * "beam" spells that may hurt fellow monsters
- * Currently "beam" spells are included in "attack"
- */
-#define RF4_BEAM_MASK 0UL
-
-#define RF5_BEAM_MASK 0UL
-
-#define RF6_BEAM_MASK (RF6_PSY_SPEAR)
-
-/*
- * "ball" spells with radius 4 that may hurt friends
- * Currently "radius 4 ball" spells are included in "ball"
- */
-#define RF4_BIG_BALL_MASK (RF4_BA_CHAO)
-
-#define RF5_BIG_BALL_MASK (RF5_BA_LITE | RF5_BA_DARK | RF5_BA_WATE | RF5_BA_MANA)
-
-#define RF6_BIG_BALL_MASK 0UL
-
-/*
- * "ball" spells that may hurt friends
- * Including "radius 4 ball" and "breath" spells
- * Currently "ball" spells are included in "attack"
- */
-#define RF4_BALL_MASK (RF4_BIG_BALL_MASK | RF4_BREATH_MASK | RF4_ROCKET | RF4_BA_NUKE)
-
-#define RF5_BALL_MASK (RF5_BIG_BALL_MASK | RF5_BREATH_MASK | RF5_BA_ACID | RF5_BA_ELEC | RF5_BA_FIRE | RF5_BA_COLD | RF5_BA_POIS | RF5_BA_NETH)
-
-#define RF6_BALL_MASK (RF6_BIG_BALL_MASK | RF6_BREATH_MASK)
-
-/*
- * "breath" spells that may hurt friends
- * Currently "breath" spells are included in "ball" and "non-magic"
- */
-#define RF4_BREATH_MASK                                                                                                                                        \
-    (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS | RF4_BR_NETH | RF4_BR_LITE | RF4_BR_DARK | RF4_BR_CONF | RF4_BR_SOUN | RF4_BR_CHAO   \
-        | RF4_BR_DISE | RF4_BR_NEXU | RF4_BR_SHAR | RF4_BR_TIME | RF4_BR_INER | RF4_BR_GRAV | RF4_BR_PLAS | RF4_BR_WALL | RF4_BR_MANA | RF4_BR_NUKE            \
-        | RF4_BR_DISI)
-
-#define RF5_BREATH_MASK 0UL
-
-#define RF6_BREATH_MASK 0UL
-
-/* "attack" spells including "bolt", "beam" and "ball" spells */
-#define RF4_ATTACK_MASK (RF4_BOLT_MASK | RF4_BEAM_MASK | RF4_BALL_MASK | RF4_DISPEL)
-
-#define RF5_ATTACK_MASK                                                                                                                                        \
-    (RF5_BOLT_MASK | RF5_BEAM_MASK | RF5_BALL_MASK | RF5_DRAIN_MANA | RF5_MIND_BLAST | RF5_BRAIN_SMASH | RF5_CAUSE_1 | RF5_CAUSE_2 | RF5_CAUSE_3 | RF5_CAUSE_4 \
-        | RF5_SCARE | RF5_BLIND | RF5_CONF | RF5_SLOW | RF5_HOLD)
-
-#define RF6_ATTACK_MASK                                                                                                                                        \
-    (RF6_BOLT_MASK | RF6_BEAM_MASK | RF6_BALL_MASK | RF6_HAND_DOOM | RF6_TELE_TO | RF6_TELE_AWAY | RF6_TELE_LEVEL | RF6_DARKNESS | RF6_TRAPS | RF6_FORGET)
-
-/* "indirect" spells Including "summon" spells */
-#define RF4_INDIRECT_MASK (RF4_SUMMON_MASK | RF4_SHRIEK)
-
-#define RF5_INDIRECT_MASK (RF5_SUMMON_MASK)
-
-#define RF6_INDIRECT_MASK (RF6_SUMMON_MASK | RF6_HASTE | RF6_HEAL | RF6_INVULNER | RF6_BLINK | RF6_WORLD | RF6_TPORT | RF6_RAISE_DEAD)
-
-/* "non-magic" spells including "breath" spells */
-#define RF4_NOMAGIC_MASK (RF4_BREATH_MASK | RF4_SHRIEK | RF4_ROCKET | RF4_SHOOT)
-
-#define RF5_NOMAGIC_MASK (RF5_BREATH_MASK)
-
-#define RF6_NOMAGIC_MASK (RF6_BREATH_MASK | RF6_SPECIAL)
index 79a2633..c8353fe 100644 (file)
@@ -8,7 +8,6 @@
 #include "mspell/mspell-selector.h"
 #include "floor/geometry.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability2.h"
 #include "monster-race/race-flags2.h"
 #include "monster-race/race-indice-types.h"
 #include "monster/monster-status.h"
 #include "world/world.h"
 
 /*!
- * @brief ID値が正しいモンスター魔法IDかどうかを返す /
+ * @brief 指定したID値が指定した範囲内のIDかどうかを返す
+ *
+ * enum値に対して範囲で判定するのはあまり好ましくないが、歴史的経緯により仕方がない
+ *
+ * @param spell 判定対象のID
+ * @param start 範囲の開始ID
+ * @param end 範囲の終了ID(このIDも含む)
+ * @return IDが start <= spell <= end なら true、そうでなければ false
+ */
+static bool spell_in_between(RF_ABILITY spell, RF_ABILITY start, RF_ABILITY end)
+{
+    auto spell_int = static_cast<int>(spell);
+    return static_cast<int>(start) <= spell_int && spell_int <= static_cast<int>(end);
+}
+
+/*!
+ * @brief ID値が攻撃魔法のIDかどうかを返す /
  * Return TRUE if a spell is good for hurting the player (directly).
  * @param spell 判定対象のID
  * @return 正しいIDならばTRUEを返す。
  */
-static bool spell_attack(byte spell)
+static bool spell_attack(RF_ABILITY spell)
 {
     /* All RF4 spells hurt (except for shriek and dispel) */
-    if (spell < 128 && spell > 98)
+    if (spell_in_between(spell, RF_ABILITY::ROCKET, RF_ABILITY::BR_DISI))
         return TRUE;
 
     /* Various "ball" spells */
-    if (spell >= 128 && spell <= 128 + 8)
+    if (spell_in_between(spell, RF_ABILITY::BA_ACID, RF_ABILITY::BA_DARK))
         return TRUE;
 
     /* "Cause wounds" and "bolt" spells */
-    if (spell >= 128 + 12 && spell < 128 + 27)
+    if (spell_in_between(spell, RF_ABILITY::CAUSE_1, RF_ABILITY::MISSILE))
         return TRUE;
 
     /* Hand of Doom */
-    if (spell == 160 + 1)
+    if (spell == RF_ABILITY::HAND_DOOM)
         return TRUE;
 
     /* Psycho-Spear */
-    if (spell == 160 + 11)
+    if (spell == RF_ABILITY::PSY_SPEAR)
         return TRUE;
 
     /* Doesn't hurt */
@@ -56,14 +71,14 @@ static bool spell_attack(byte spell)
  * @param spell 判定対象のID
  * @return 適した魔法のIDならばTRUEを返す。
  */
-static bool spell_escape(byte spell)
+static bool spell_escape(RF_ABILITY spell)
 {
     /* Blink or Teleport */
-    if (spell == 160 + 4 || spell == 160 + 5)
+    if (spell == RF_ABILITY::BLINK || spell == RF_ABILITY::TPORT)
         return TRUE;
 
     /* Teleport the player away */
-    if (spell == 160 + 9 || spell == 160 + 10)
+    if (spell == RF_ABILITY::TELE_AWAY || spell == RF_ABILITY::TELE_LEVEL)
         return TRUE;
 
     /* Isn't good for escaping */
@@ -76,30 +91,30 @@ static bool spell_escape(byte spell)
  * @param spell 判定対象のID
  * @return 適した魔法のIDならばTRUEを返す。
  */
-static bool spell_annoy(byte spell)
+static bool spell_annoy(RF_ABILITY spell)
 {
     /* Shriek */
-    if (spell == 96 + 0)
+    if (spell == RF_ABILITY::SHRIEK)
         return TRUE;
 
     /* Brain smash, et al (added curses) */
-    if (spell >= 128 + 9 && spell <= 128 + 14)
+    if (spell_in_between(spell, RF_ABILITY::DRAIN_MANA, RF_ABILITY::CAUSE_4))
         return TRUE;
 
     /* Scare, confuse, blind, slow, paralyze */
-    if (spell >= 128 + 27 && spell <= 128 + 31)
+    if (spell_in_between(spell, RF_ABILITY::SCARE, RF_ABILITY::HOLD))
         return TRUE;
 
     /* Teleport to */
-    if (spell == 160 + 8)
+    if (spell == RF_ABILITY::TELE_TO)
         return TRUE;
 
     /* Teleport level */
-    if (spell == 160 + 10)
+    if (spell == RF_ABILITY::TELE_LEVEL)
         return TRUE;
 
     /* Darkness, make traps, cause amnesia */
-    if (spell >= 160 + 12 && spell <= 160 + 14)
+    if (spell_in_between(spell, RF_ABILITY::TRAPS, RF_ABILITY::RAISE_DEAD))
         return TRUE;
 
     /* Doesn't annoy */
@@ -112,7 +127,10 @@ static bool spell_annoy(byte spell)
  * @param spell 判定対象のID
  * @return 召喚型魔法のIDならばTRUEを返す。
  */
-static bool spell_summon(byte spell) { return spell >= 160 + 16; }
+static bool spell_summon(RF_ABILITY spell)
+{
+    return spell_in_between(spell, RF_ABILITY::S_KIN, RF_ABILITY::S_UNIQUE);
+}
 
 /*!
  * @brief ID値が死者復活処理かどうかを返す /
@@ -120,7 +138,10 @@ static bool spell_summon(byte spell) { return spell >= 160 + 16; }
  * @param spell 判定対象のID
  * @return 死者復活の処理ならばTRUEを返す。
  */
-static bool spell_raise(byte spell) { return spell == 160 + 15; }
+static bool spell_raise(RF_ABILITY spell)
+{
+    return spell == RF_ABILITY::RAISE_DEAD;
+}
 
 /*!
  * @brief ID値が戦術的なモンスター魔法IDかどうかを返す /
@@ -128,7 +149,10 @@ static bool spell_raise(byte spell) { return spell == 160 + 15; }
  * @param spell 判定対象のID
  * @return 戦術的な魔法のIDならばTRUEを返す。
  */
-static bool spell_tactic(byte spell) { return spell == 160 + 4; }
+static bool spell_tactic(RF_ABILITY spell)
+{
+    return spell == RF_ABILITY::BLINK;
+}
 
 /*!
  * @brief ID値が無敵化するモンスター魔法IDかどうかを返す /
@@ -136,7 +160,10 @@ static bool spell_tactic(byte spell) { return spell == 160 + 4; }
  * @param spell 判定対象のID
  * @return 召喚型魔法のIDならばTRUEを返す。
  */
-static bool spell_invulner(byte spell) { return spell == 160 + 3; }
+static bool spell_invulner(RF_ABILITY spell)
+{
+    return spell == RF_ABILITY::INVULNER;
+}
 
 /*!
  * @brief ID値が加速するモンスター魔法IDかどうかを返す /
@@ -144,7 +171,10 @@ static bool spell_invulner(byte spell) { return spell == 160 + 3; }
  * @param spell 判定対象のID
  * @return 召喚型魔法のIDならばTRUEを返す。
  */
-static bool spell_haste(byte spell) { return spell == 160 + 0; }
+static bool spell_haste(RF_ABILITY spell)
+{
+    return spell == RF_ABILITY::HASTE;
+}
 
 /*!
  * @brief ID値が時間停止を行うモンスター魔法IDかどうかを返す /
@@ -152,7 +182,10 @@ static bool spell_haste(byte spell) { return spell == 160 + 0; }
  * @param spell 判定対象のID
  * @return 時間停止魔法のIDならばTRUEを返す。
  */
-static bool spell_world(byte spell) { return spell == 160 + 6; }
+static bool spell_world(RF_ABILITY spell)
+{
+    return spell == RF_ABILITY::WORLD;
+}
 
 /*!
  * @brief ID値が特別効果のモンスター魔法IDかどうかを返す /
@@ -161,12 +194,12 @@ static bool spell_world(byte spell) { return spell == 160 + 6; }
  * @param spell 判定対象のID
  * @return 特別効果魔法のIDならばTRUEを返す。
  */
-static bool spell_special(player_type *target_ptr, byte spell)
+static bool spell_special(player_type *target_ptr, RF_ABILITY spell)
 {
     if (target_ptr->phase_out)
         return FALSE;
 
-    return spell == 160 + 7;
+    return spell == RF_ABILITY::SPECIAL;
 }
 
 /*!
@@ -175,7 +208,10 @@ static bool spell_special(player_type *target_ptr, byte spell)
  * @param spell 判定対象のID
  * @return 光の剣のIDならばTRUEを返す。
  */
-static bool spell_psy_spe(byte spell) { return spell == 160 + 11; }
+static bool spell_psy_spe(RF_ABILITY spell)
+{
+    return spell == RF_ABILITY::PSY_SPEAR;
+}
 
 /*!
  * @brief ID値が治癒魔法かどうかを返す /
@@ -183,7 +219,10 @@ static bool spell_psy_spe(byte spell) { return spell == 160 + 11; }
  * @param spell 判定対象のID
  * @return 治癒魔法のIDならばTRUEを返す。
  */
-static bool spell_heal(byte spell) { return spell == 160 + 2; }
+static bool spell_heal(RF_ABILITY spell)
+{
+    return spell == RF_ABILITY::HEAL;
+}
 
 /*!
  * @brief ID値が魔力消去かどうかを返す /
@@ -191,7 +230,10 @@ static bool spell_heal(byte spell) { return spell == 160 + 2; }
  * @param spell 判定対象のID
  * @return 魔力消去のIDならばTRUEを返す。
  */
-static bool spell_dispel(byte spell) { return spell == 96 + 2; }
+static bool spell_dispel(RF_ABILITY spell)
+{
+    return spell == RF_ABILITY::DISPEL;
+}
 
 /*!
  * @brief モンスターの魔法選択ルーチン
@@ -214,72 +256,72 @@ static bool spell_dispel(byte spell) { return spell == 96 + 2; }
  * This function may well be an efficiency bottleneck.\n
  * @todo 長過ぎる。切り分けが必要
  */
-int choose_attack_spell(player_type *target_ptr, msa_type *msa_ptr)
+RF_ABILITY choose_attack_spell(player_type *target_ptr, msa_type *msa_ptr)
 {
-    byte escape[96], escape_num = 0;
-    byte attack[96], attack_num = 0;
-    byte summon[96], summon_num = 0;
-    byte tactic[96], tactic_num = 0;
-    byte annoy[96], annoy_num = 0;
-    byte invul[96], invul_num = 0;
-    byte haste[96], haste_num = 0;
-    byte world[96], world_num = 0;
-    byte special[96], special_num = 0;
-    byte psy_spe[96], psy_spe_num = 0;
-    byte raise[96], raise_num = 0;
-    byte heal[96], heal_num = 0;
-    byte dispel[96], dispel_num = 0;
+    std::vector<RF_ABILITY> escape;
+    std::vector<RF_ABILITY> attack;
+    std::vector<RF_ABILITY> summon;
+    std::vector<RF_ABILITY> tactic;
+    std::vector<RF_ABILITY> annoy;
+    std::vector<RF_ABILITY> invul;
+    std::vector<RF_ABILITY> haste;
+    std::vector<RF_ABILITY> world;
+    std::vector<RF_ABILITY> special;
+    std::vector<RF_ABILITY> psy_spe;
+    std::vector<RF_ABILITY> raise;
+    std::vector<RF_ABILITY> heal;
+    std::vector<RF_ABILITY> dispel;
 
     monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[msa_ptr->m_idx];
     monster_race *r_ptr = &r_info[m_ptr->r_idx];
     if (r_ptr->flags2 & RF2_STUPID)
-        return (msa_ptr->mspells[randint0(msa_ptr->num)]);
+        return (msa_ptr->mspells[randint0(msa_ptr->mspells.size())]);
 
-    for (int i = 0; i < msa_ptr->num; i++) {
+    for (size_t i = 0; i < msa_ptr->mspells.size(); i++) {
         if (spell_escape(msa_ptr->mspells[i]))
-            escape[escape_num++] = msa_ptr->mspells[i];
+            escape.push_back(msa_ptr->mspells[i]);
 
         if (spell_attack(msa_ptr->mspells[i]))
-            attack[attack_num++] = msa_ptr->mspells[i];
+            attack.push_back(msa_ptr->mspells[i]);
 
         if (spell_summon(msa_ptr->mspells[i]))
-            summon[summon_num++] = msa_ptr->mspells[i];
+            summon.push_back(msa_ptr->mspells[i]);
 
         if (spell_tactic(msa_ptr->mspells[i]))
-            tactic[tactic_num++] = msa_ptr->mspells[i];
+            tactic.push_back(msa_ptr->mspells[i]);
 
         if (spell_annoy(msa_ptr->mspells[i]))
-            annoy[annoy_num++] = msa_ptr->mspells[i];
+            annoy.push_back(msa_ptr->mspells[i]);
 
         if (spell_invulner(msa_ptr->mspells[i]))
-            invul[invul_num++] = msa_ptr->mspells[i];
+            invul.push_back(msa_ptr->mspells[i]);
 
         if (spell_haste(msa_ptr->mspells[i]))
-            haste[haste_num++] = msa_ptr->mspells[i];
+            haste.push_back(msa_ptr->mspells[i]);
 
         if (spell_world(msa_ptr->mspells[i]))
-            world[world_num++] = msa_ptr->mspells[i];
+            world.push_back(msa_ptr->mspells[i]);
 
         if (spell_special(target_ptr, msa_ptr->mspells[i]))
-            special[special_num++] = msa_ptr->mspells[i];
+            special.push_back(msa_ptr->mspells[i]);
 
         if (spell_psy_spe(msa_ptr->mspells[i]))
-            psy_spe[psy_spe_num++] = msa_ptr->mspells[i];
+            psy_spe.push_back(msa_ptr->mspells[i]);
 
         if (spell_raise(msa_ptr->mspells[i]))
-            raise[raise_num++] = msa_ptr->mspells[i];
+            raise.push_back(msa_ptr->mspells[i]);
 
         if (spell_heal(msa_ptr->mspells[i]))
-            heal[heal_num++] = msa_ptr->mspells[i];
+            heal.push_back(msa_ptr->mspells[i]);
 
         if (spell_dispel(msa_ptr->mspells[i]))
-            dispel[dispel_num++] = msa_ptr->mspells[i];
+            dispel.push_back(msa_ptr->mspells[i]);
     }
 
-    if (world_num && (randint0(100) < 15) && !current_world_ptr->timewalk_m_idx)
-        return (world[randint0(world_num)]);
+    if (!world.empty() && (randint0(100) < 15) && !current_world_ptr->timewalk_m_idx)
+        return (world[randint0(world.size())]);
 
-    if (special_num) {
+    if (!special.empty()) {
         bool success = FALSE;
         switch (m_ptr->r_idx) {
         case MON_BANOR:
@@ -292,20 +334,20 @@ int choose_attack_spell(player_type *target_ptr, msa_type *msa_ptr)
         }
 
         if (success)
-            return (special[randint0(special_num)]);
+            return (special[randint0(special.size())]);
     }
 
     if (m_ptr->hp < m_ptr->maxhp / 3 && one_in_(2)) {
-        if (heal_num)
-            return (heal[randint0(heal_num)]);
+        if (!heal.empty())
+            return (heal[randint0(heal.size())]);
     }
 
     if (((m_ptr->hp < m_ptr->maxhp / 3) || monster_fear_remaining(m_ptr)) && one_in_(2)) {
-        if (escape_num)
-            return (escape[randint0(escape_num)]);
+        if (!escape.empty())
+            return (escape[randint0(escape.size())]);
     }
 
-    if (special_num) {
+    if (!special.empty()) {
         bool success = FALSE;
         switch (m_ptr->r_idx) {
         case MON_OHMU:
@@ -326,53 +368,53 @@ int choose_attack_spell(player_type *target_ptr, msa_type *msa_ptr)
             break;
         }
         if (success)
-            return (special[randint0(special_num)]);
+            return (special[randint0(special.size())]);
     }
 
-    if ((distance(target_ptr->y, target_ptr->x, m_ptr->fy, m_ptr->fx) < 4) && (attack_num || (r_ptr->a_ability_flags2 & RF6_TRAPS)) && (randint0(100) < 75)
+    if ((distance(target_ptr->y, target_ptr->x, m_ptr->fy, m_ptr->fx) < 4) && (!attack.empty() || r_ptr->ability_flags.has(RF_ABILITY::TRAPS)) && (randint0(100) < 75)
         && !current_world_ptr->timewalk_m_idx) {
-        if (tactic_num)
-            return (tactic[randint0(tactic_num)]);
+        if (!tactic.empty())
+            return (tactic[randint0(tactic.size())]);
     }
 
-    if (summon_num && (randint0(100) < 40))
-        return (summon[randint0(summon_num)]);
+    if (!summon.empty() && (randint0(100) < 40))
+        return (summon[randint0(summon.size())]);
 
-    if (dispel_num && one_in_(2)) {
+    if (!dispel.empty() && one_in_(2)) {
         if (dispel_check(target_ptr, msa_ptr->m_idx)) {
-            return (dispel[randint0(dispel_num)]);
+            return (dispel[randint0(dispel.size())]);
         }
     }
 
-    if (raise_num && (randint0(100) < 40))
-        return (raise[randint0(raise_num)]);
+    if (!raise.empty() && (randint0(100) < 40))
+        return (raise[randint0(raise.size())]);
 
     if (is_invuln(target_ptr)) {
-        if (psy_spe_num && (randint0(100) < 50)) {
-            return (psy_spe[randint0(psy_spe_num)]);
-        } else if (attack_num && (randint0(100) < 40)) {
-            return (attack[randint0(attack_num)]);
+        if (!psy_spe.empty() && (randint0(100) < 50)) {
+            return (psy_spe[randint0(psy_spe.size())]);
+        } else if (!attack.empty() && (randint0(100) < 40)) {
+            return (attack[randint0(attack.size())]);
         }
-    } else if (attack_num && (randint0(100) < 85)) {
-        return (attack[randint0(attack_num)]);
+    } else if (!attack.empty() && (randint0(100) < 85)) {
+        return (attack[randint0(attack.size())]);
     }
 
-    if (tactic_num && (randint0(100) < 50) && !current_world_ptr->timewalk_m_idx)
-        return (tactic[randint0(tactic_num)]);
+    if (!tactic.empty() && (randint0(100) < 50) && !current_world_ptr->timewalk_m_idx)
+        return (tactic[randint0(tactic.size())]);
 
-    if (invul_num && !m_ptr->mtimed[MTIMED_INVULNER] && (randint0(100) < 50))
-        return (invul[randint0(invul_num)]);
+    if (!invul.empty() && !m_ptr->mtimed[MTIMED_INVULNER] && (randint0(100) < 50))
+        return (invul[randint0(invul.size())]);
 
     if ((m_ptr->hp < m_ptr->maxhp * 3 / 4) && (randint0(100) < 25)) {
-        if (heal_num)
-            return (heal[randint0(heal_num)]);
+        if (!heal.empty())
+            return (heal[randint0(heal.size())]);
     }
 
-    if (haste_num && (randint0(100) < 20) && !monster_fast_remaining(m_ptr))
-        return (haste[randint0(haste_num)]);
+    if (!haste.empty() && (randint0(100) < 20) && !monster_fast_remaining(m_ptr))
+        return (haste[randint0(haste.size())]);
 
-    if (annoy_num && (randint0(100) < 80))
-        return (annoy[randint0(annoy_num)]);
+    if (!annoy.empty() && (randint0(100) < 80))
+        return (annoy[randint0(annoy.size())]);
 
-    return 0;
+    return RF_ABILITY::MAX;
 }
index e9e5b48..d23b0b8 100644 (file)
@@ -3,4 +3,5 @@
 #include "system/angband.h"
 
 typedef struct msa_type msa_type;
-int choose_attack_spell(player_type *target_ptr, msa_type *msa_ptr);
+enum class RF_ABILITY;
+RF_ABILITY choose_attack_spell(player_type *target_ptr, msa_type *msa_ptr);
index b64daa3..229f1d8 100644 (file)
@@ -4,13 +4,11 @@
 #include "system/floor-type-definition.h"
 #include "system/monster-type-definition.h"
 
-msr_type *initialize_msr_type(player_type *target_ptr, msr_type *msr_ptr, MONSTER_IDX m_idx, const u32b f4p, const u32b f5p, const u32b f6p)
+msr_type *initialize_msr_type(player_type *target_ptr, msr_type *msr_ptr, MONSTER_IDX m_idx, const FlagGroup<RF_ABILITY>& ability_flags)
 {
     monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
     msr_ptr->r_ptr = &r_info[m_ptr->r_idx];
-    msr_ptr->f4 = f4p;
-    msr_ptr->f5 = f5p;
-    msr_ptr->f6 = f6p;
+    msr_ptr->ability_flags = ability_flags;
     msr_ptr->smart.clear();
     return msr_ptr;
 }
index 7c17911..f09a404 100644 (file)
@@ -1,18 +1,18 @@
 #pragma once
 
-#include "monster/smart-learn-types.h"
 #include "system/angband.h"
+
+#include "monster-race/race-ability-flags.h"
+#include "monster/smart-learn-types.h"
 #include "util/flag-group.h"
 
 // Monster Spell Remover.
 typedef struct monster_race monster_race;
 typedef struct msr_type {
     monster_race *r_ptr;
-    u32b f4;
-    u32b f5;
-    u32b f6;
+    FlagGroup<RF_ABILITY> ability_flags;
     FlagGroup<SM> smart;
 } msr_type;
 
-msr_type *initialize_msr_type(player_type *target_ptr, msr_type *msr_ptr, MONSTER_IDX m_idx, const u32b f4p, const u32b f5p, const u32b f6p);
+msr_type *initialize_msr_type(player_type *target_ptr, msr_type *msr_ptr, MONSTER_IDX m_idx, const FlagGroup<RF_ABILITY> &ability_flags);
 bool int_outof(monster_race *r_ptr, PERCENTAGE prob);
index c0d8443..ca311db 100644 (file)
@@ -5,7 +5,6 @@
 #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-flags7.h"
 #include "monster-race/race-flags8.h"
 #include "monster-race/race-indice-types.h"
@@ -83,7 +82,7 @@ bool check_summon_specific(player_type *player_ptr, MONRACE_IDX summoner_idx, MO
         is_match = (r_ptr->d_char == 'g');
         break;
     case SUMMON_CYBER:
-        is_match = (r_ptr->d_char == 'U') && ((r_ptr->flags4 & RF4_ROCKET) != 0);
+        is_match = (r_ptr->d_char == 'U') && r_ptr->ability_flags.has(RF_ABILITY::ROCKET);
         break;
     case SUMMON_KIN: {
         SYMBOL_CODE summon_kin_type = summoner_idx > 0 ? r_info[summoner_idx].d_char : get_summon_symbol_from_player(player_ptr);
@@ -99,7 +98,7 @@ bool check_summon_specific(player_type *player_ptr, MONRACE_IDX summoner_idx, MO
     case SUMMON_ANIMAL_RANGER:
         is_match = ((r_ptr->flags3 & (RF3_ANIMAL)) && (angband_strchr("abcflqrwBCHIJKMRS", r_ptr->d_char)) && !(r_ptr->flags3 & (RF3_DRAGON))
             && !(r_ptr->flags3 & (RF3_EVIL)) && !(r_ptr->flags3 & (RF3_UNDEAD)) && !(r_ptr->flags3 & (RF3_DEMON)) && !(r_ptr->flags2 & (RF2_MULTIPLY))
-            && !(r_ptr->flags4 || r_ptr->a_ability_flags1 || r_ptr->a_ability_flags2));
+            && r_ptr->ability_flags.none());
         break;
     case SUMMON_SMALL_MOAI:
         is_match = r_idx == MON_SMALL_MOAI;
index c5f0063..0c30730 100644 (file)
@@ -105,10 +105,6 @@ void apply_magic_armor(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
             }
 
             switch (o_ptr->name2) {
-            case EGO_RESISTANCE:
-                if (one_in_(4))
-                    add_flag(o_ptr->art_flags, TR_RES_POIS);
-                break;
             case EGO_DWARVEN:
                 o_ptr->weight = (2 * k_info[o_ptr->k_idx].weight / 3);
                 o_ptr->ac = k_info[o_ptr->k_idx].ac + 5;
@@ -123,41 +119,7 @@ void apply_magic_armor(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
 
                 switch (o_ptr->name2) {
                 case EGO_A_DEMON:
-                    if (one_in_(3))
-                        o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
-                    one_in_(3) ? add_flag(o_ptr->art_flags, TR_DRAIN_EXP)
-                               : one_in_(2) ? add_flag(o_ptr->art_flags, TR_DRAIN_HP) : add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
-
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_AGGRAVATE);
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_ADD_L_CURSE);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_ADD_H_CURSE);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_DRAIN_HP);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_DRAIN_EXP);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_TY_CURSE);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_CALL_DEMON);
-                    break;
                 case EGO_A_MORGUL:
-                    if (one_in_(3))
-                        o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
-                    if (one_in_(9))
-                        add_flag(o_ptr->art_flags, TR_TY_CURSE);
-                    if (one_in_(4))
-                        add_flag(o_ptr->art_flags, TR_ADD_H_CURSE);
-                    if (one_in_(6))
-                        add_flag(o_ptr->art_flags, TR_AGGRAVATE);
-                    if (one_in_(9))
-                        add_flag(o_ptr->art_flags, TR_NO_MAGIC);
-                    if (one_in_(9))
-                        add_flag(o_ptr->art_flags, TR_NO_TELE);
                     break;
                 default:
                     msg_print(_("エラー:適した呪い鎧エゴがみつかりませんでした.", "Error:Suitable cursed armor ego not found."));
@@ -196,21 +158,16 @@ void apply_magic_armor(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
             }
 
             switch (o_ptr->name2) {
-            case EGO_ENDURANCE:
-                if (!one_in_(3))
-                    one_high_resistance(o_ptr);
-                if (one_in_(4))
-                    add_flag(o_ptr->art_flags, TR_RES_POIS);
-                break;
             case EGO_REFLECTION:
                 if (o_ptr->sval == SV_MIRROR_SHIELD)
                     o_ptr->name2 = 0;
                 break;
-
             case EGO_S_DWARVEN:
                 o_ptr->weight = (2 * k_info[o_ptr->k_idx].weight / 3);
                 o_ptr->ac = k_info[o_ptr->k_idx].ac + 3;
                 break;
+            default:
+                break;
             }
         }
 
@@ -252,14 +209,6 @@ void apply_magic_armor(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
             }
 
             o_ptr->name2 = get_random_ego(INVEN_FEET, TRUE);
-            switch (o_ptr->name2) {
-            case EGO_SLOW_DESCENT:
-                if (one_in_(2)) {
-                    one_high_resistance(o_ptr);
-                }
-
-                break;
-            }
         } else if (power < -1) {
             o_ptr->name2 = get_random_ego(INVEN_FEET, FALSE);
         }
@@ -318,19 +267,7 @@ void apply_magic_armor(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
                 case EGO_H_DEMON:
                     ok_flag = false;
                     break;
-                case EGO_ANCIENT_CURSE:
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_NO_MAGIC);
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_NO_TELE);
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_TY_CURSE);
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_DRAIN_EXP);
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_DRAIN_HP);
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
+                default:
                     break;
                 }
 
@@ -363,6 +300,7 @@ void apply_magic_armor(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
                 case EGO_DARK:
                 case EGO_INFRAVISION:
                 case EGO_H_PROTECTION:
+                case EGO_LITE:
                     break;
                 case EGO_SEEING:
                     if (one_in_(7)) {
@@ -371,13 +309,6 @@ void apply_magic_armor(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
                         else
                             add_esp_weak(o_ptr, FALSE);
                     }
-
-                    break;
-                case EGO_LITE:
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_LITE_1);
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_LITE_2);
                     break;
                 default:
                     /* not existing helm (Magi, Might, etc...)*/
@@ -395,32 +326,11 @@ void apply_magic_armor(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
                 o_ptr->name2 = get_random_ego(INVEN_HEAD, FALSE);
 
                 switch (o_ptr->name2) {
-                case EGO_H_DEMON:
-                    if (one_in_(3))
-                        o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
-                    one_in_(3) ? add_flag(o_ptr->art_flags, TR_DRAIN_EXP)
-                               : one_in_(2) ? add_flag(o_ptr->art_flags, TR_DRAIN_HP) : add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
-
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_AGGRAVATE);
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_ADD_L_CURSE);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_ADD_H_CURSE);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_DRAIN_HP);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_DRAIN_EXP);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_TY_CURSE);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_CALL_DEMON);
-                    break;
                 case EGO_ANCIENT_CURSE:
                     ok_flag = FALSE;
                     break;
+                default:
+                    break;
                 }
 
                 if (ok_flag)
@@ -447,14 +357,6 @@ void apply_magic_armor(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
             case EGO_NAZGUL:
                 o_ptr->to_d -= 3;
                 o_ptr->to_h -= 3;
-                if (one_in_(3))
-                    add_flag(o_ptr->art_flags, TR_COWARDICE);
-                if (one_in_(3))
-                    add_flag(o_ptr->art_flags, TR_CALL_UNDEAD);
-                if (one_in_(3))
-                    add_flag(o_ptr->art_flags, TR_SLOW_REGEN);
-                if (one_in_(3))
-                    add_flag(o_ptr->art_flags, TR_DRAIN_EXP);
                 break;
             }
 
index 0a20dee..3980a24 100644 (file)
@@ -100,24 +100,6 @@ void apply_magic_weapon(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
             }
 
             switch (o_ptr->name2) {
-            case EGO_HA:
-                if (one_in_(4) && (level > 40))
-                    add_flag(o_ptr->art_flags, TR_BLOWS);
-                break;
-            case EGO_DF:
-                if (one_in_(3))
-                    add_flag(o_ptr->art_flags, TR_RES_POIS);
-                if (one_in_(3))
-                    add_flag(o_ptr->art_flags, TR_WARNING);
-                break;
-            case EGO_KILL_DRAGON:
-                if (one_in_(3))
-                    add_flag(o_ptr->art_flags, TR_RES_POIS);
-                break;
-            case EGO_WEST:
-                if (one_in_(3))
-                    add_flag(o_ptr->art_flags, TR_RES_FEAR);
-                break;
             case EGO_SLAYING_WEAPON:
                 if (one_in_(3))
                     o_ptr->dd *= 2;
@@ -130,27 +112,6 @@ void apply_magic_weapon(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
                         o_ptr->ds++;
                     } while (one_in_(o_ptr->ds));
                 }
-
-                if (one_in_(5)) {
-                    add_flag(o_ptr->art_flags, TR_BRAND_POIS);
-                }
-                if (o_ptr->tval == TV_SWORD && one_in_(3)) {
-                    add_flag(o_ptr->art_flags, TR_VORPAL);
-                }
-                break;
-            case EGO_TRUMP:
-                if (one_in_(5))
-                    add_flag(o_ptr->art_flags, TR_SLAY_DEMON);
-                if (one_in_(7))
-                    one_ability(o_ptr);
-                break;
-            case EGO_PATTERN:
-                if (one_in_(3))
-                    add_flag(o_ptr->art_flags, TR_HOLD_EXP);
-                if (one_in_(3))
-                    add_flag(o_ptr->art_flags, TR_DEX);
-                if (one_in_(5))
-                    add_flag(o_ptr->art_flags, TR_RES_FEAR);
                 break;
             case EGO_SHARPNESS:
                 o_ptr->pval = (PARAMETER_VALUE)m_bonus(5, level) + 1;
@@ -161,9 +122,7 @@ void apply_magic_weapon(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
                 else
                     o_ptr->pval = (PARAMETER_VALUE)m_bonus(3, level);
                 break;
-            case EGO_VAMPIRIC:
-                if (one_in_(5))
-                    add_flag(o_ptr->art_flags, TR_SLAY_HUMAN);
+            default:
                 break;
             }
 
@@ -184,31 +143,6 @@ void apply_magic_weapon(player_type *owner_ptr, object_type *o_ptr, DEPTH level,
 
                     break;
                 }
-
-                switch (o_ptr->name2) {
-                case EGO_MORGUL:
-                    if (one_in_(6))
-                        add_flag(o_ptr->art_flags, TR_TY_CURSE);
-                    if (one_in_(3))
-                        o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
-                    break;
-                case EGO_DEMON:
-
-                    if (one_in_(3))
-                        o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
-                    one_in_(3) ? add_flag(o_ptr->art_flags, TR_DRAIN_EXP)
-                               : one_in_(2) ? add_flag(o_ptr->art_flags, TR_DRAIN_HP) : add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
-
-                    if (one_in_(3))
-                        add_flag(o_ptr->art_flags, TR_CHAOTIC);
-                    if (one_in_(4))
-                        add_flag(o_ptr->art_flags, TR_BLOWS);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_ADD_H_CURSE);
-                    if (one_in_(5))
-                        add_flag(o_ptr->art_flags, TR_CALL_DEMON);
-                    break;
-                }
             }
         }
 
index 36a5231..fbb2d71 100644 (file)
 #include "object-enchant/apply-magic-others.h"
 #include "object-enchant/apply-magic-weapon.h"
 #include "object-enchant/item-apply-magic.h"
-#include "object-enchant/object-boost.h"
 #include "object-enchant/object-curse.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-enchant/trg-types.h"
-#include "object-hook/hook-checker.h"
 #include "object-hook/hook-enchant.h"
 #include "object/object-kind.h"
 #include "player/player-status-flags.h"
 #include "world/world.h"
 
 /*!
- * @brief 0 および負数に対応した randint1()
- * @param n
- *
- * n == 0 のとき、常に 0 を返す。
- * n >  0 のとき、[1, n] の乱数を返す。
- * n <  0 のとき、[n,-1] の乱数を返す。
- */
-static int randint1_signed(const int n)
-{
-    if (n == 0)
-        return 0;
-
-    return n > 0 ? randint1(n) : -randint1(-n);
-}
-
-/*!
  * @brief 生成されたベースアイテムに魔法的な強化を与えるメインルーチン
  * Complete the "creation" of an object by applying "magic" to the item
  * @param owner_ptr プレーヤーへの参照ポインタ
@@ -195,133 +177,7 @@ void apply_magic(player_type *owner_ptr, object_type *o_ptr, DEPTH lev, BIT_FLAG
     }
 
     if (object_is_ego(o_ptr)) {
-        ego_item_type *e_ptr = &e_info[o_ptr->name2];
-        if (!e_ptr->cost)
-            o_ptr->ident |= (IDENT_BROKEN);
-
-        if (e_ptr->gen_flags.has(TRG::CURSED))
-            o_ptr->curse_flags |= (TRC_CURSED);
-        if (e_ptr->gen_flags.has(TRG::HEAVY_CURSE))
-            o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
-        if (e_ptr->gen_flags.has(TRG::PERMA_CURSE))
-            o_ptr->curse_flags |= (TRC_PERMA_CURSE);
-        if (e_ptr->gen_flags.has(TRG::RANDOM_CURSE0))
-            o_ptr->curse_flags |= get_curse(owner_ptr, 0, o_ptr);
-        if (e_ptr->gen_flags.has(TRG::RANDOM_CURSE1))
-            o_ptr->curse_flags |= get_curse(owner_ptr, 1, o_ptr);
-        if (e_ptr->gen_flags.has(TRG::RANDOM_CURSE2))
-            o_ptr->curse_flags |= get_curse(owner_ptr, 2, o_ptr);
-
-        if (e_ptr->gen_flags.has(TRG::ONE_SUSTAIN))
-            one_sustain(o_ptr);
-        if (e_ptr->gen_flags.has(TRG::XTRA_POWER))
-            one_ability(o_ptr);
-        if (e_ptr->gen_flags.has(TRG::XTRA_H_RES))
-            one_high_resistance(o_ptr);
-        if (e_ptr->gen_flags.has(TRG::XTRA_E_RES))
-            one_ele_resistance(o_ptr);
-        if (e_ptr->gen_flags.has(TRG::XTRA_D_RES))
-            one_dragon_ele_resistance(o_ptr);
-        if (e_ptr->gen_flags.has(TRG::XTRA_L_RES))
-            one_lordly_high_resistance(o_ptr);
-        if (e_ptr->gen_flags.has(TRG::XTRA_RES))
-            one_resistance(o_ptr);
-        if (e_ptr->gen_flags.has(TRG::XTRA_DICE)) {
-            do {
-                o_ptr->dd++;
-            } while (one_in_(o_ptr->dd));
-
-            if (o_ptr->dd > 9)
-                o_ptr->dd = 9;
-        }
-
-        if (e_ptr->act_idx)
-            o_ptr->xtra2 = (XTRA8)e_ptr->act_idx;
-
-        bool is_powerful = e_ptr->gen_flags.has(TRG::POWERFUL);
-
-        if ((object_is_cursed(o_ptr) || object_is_broken(o_ptr)) && !is_powerful) {
-            if (e_ptr->max_to_h)
-                o_ptr->to_h -= randint1(e_ptr->max_to_h);
-            if (e_ptr->max_to_d)
-                o_ptr->to_d -= randint1(e_ptr->max_to_d);
-            if (e_ptr->max_to_a)
-                o_ptr->to_a -= randint1(e_ptr->max_to_a);
-            if (e_ptr->max_pval)
-                o_ptr->pval -= randint1(e_ptr->max_pval);
-        } else {
-            if (is_powerful) {
-                if (e_ptr->max_to_h > 0 && o_ptr->to_h < 0)
-                    o_ptr->to_h = 0 - o_ptr->to_h;
-                if (e_ptr->max_to_d > 0 && o_ptr->to_d < 0)
-                    o_ptr->to_d = 0 - o_ptr->to_d;
-                if (e_ptr->max_to_a > 0 && o_ptr->to_a < 0)
-                    o_ptr->to_a = 0 - o_ptr->to_a;
-            }
-
-            o_ptr->to_h += (HIT_PROB)randint1_signed(e_ptr->max_to_h);
-            o_ptr->to_d += randint1_signed(e_ptr->max_to_d);
-            o_ptr->to_a += (ARMOUR_CLASS)randint1_signed(e_ptr->max_to_a);
-
-            if (o_ptr->name2 == EGO_ACCURACY) {
-                while (o_ptr->to_h < o_ptr->to_d + 10) {
-                    o_ptr->to_h += 5;
-                    o_ptr->to_d -= 5;
-                }
-                o_ptr->to_h = MAX(o_ptr->to_h, 15);
-            }
-
-            if (o_ptr->name2 == EGO_VELOCITY) {
-                while (o_ptr->to_d < o_ptr->to_h + 10) {
-                    o_ptr->to_d += 5;
-                    o_ptr->to_h -= 5;
-                }
-                o_ptr->to_d = MAX(o_ptr->to_d, 15);
-            }
-
-            if ((o_ptr->name2 == EGO_PROTECTION) || (o_ptr->name2 == EGO_S_PROTECTION) || (o_ptr->name2 == EGO_H_PROTECTION)) {
-                o_ptr->to_a = MAX(o_ptr->to_a, 15);
-            }
-
-            if (e_ptr->max_pval) {
-                if ((o_ptr->name2 == EGO_HA) && (has_flag(o_ptr->art_flags, TR_BLOWS))) {
-                    o_ptr->pval++;
-                    if ((lev > 60) && one_in_(3) && ((o_ptr->dd * (o_ptr->ds + 1)) < 15))
-                        o_ptr->pval++;
-                } else if (o_ptr->name2 == EGO_DEMON) {
-                    if (has_flag(o_ptr->art_flags, TR_BLOWS)) {
-                        o_ptr->pval += randint1(2);
-                    } else {
-                        o_ptr->pval += randint1(e_ptr->max_pval);
-                    }
-                } else if (o_ptr->name2 == EGO_ATTACKS) {
-                    o_ptr->pval = randint1(e_ptr->max_pval * lev / 100 + 1);
-                    if (o_ptr->pval > 3)
-                        o_ptr->pval = 3;
-                    if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_HAYABUSA))
-                        o_ptr->pval += randint1(2);
-                } else if (o_ptr->name2 == EGO_BAT) {
-                    o_ptr->pval = randint1(e_ptr->max_pval);
-                    if (o_ptr->sval == SV_ELVEN_CLOAK)
-                        o_ptr->pval += randint1(2);
-                } else if (o_ptr->name2 == EGO_A_DEMON || o_ptr->name2 == EGO_DRUID || o_ptr->name2 == EGO_OLOG) {
-                    o_ptr->pval = randint1(e_ptr->max_pval);
-                } else {
-                    if (e_ptr->max_pval > 0)
-                        o_ptr->pval += randint1(e_ptr->max_pval);
-                    else if (e_ptr->max_pval < 0)
-                        o_ptr->pval -= randint1(0 - e_ptr->max_pval);
-                }
-            }
-
-            if ((o_ptr->name2 == EGO_SPEED) && (lev < 50)) {
-                o_ptr->pval = randint1(o_ptr->pval);
-            }
-
-            if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_HAYABUSA) && (o_ptr->pval > 2) && (o_ptr->name2 != EGO_ATTACKS))
-                o_ptr->pval = 2;
-        }
-
+        apply_ego(owner_ptr, o_ptr, lev);
         return;
     }
 
index f028412..e1da37a 100644 (file)
@@ -5,7 +5,13 @@
  * @details Ego-Item indexes (see "lib/edit/e_info.txt")
  */
 #include "object-enchant/object-ego.h"
-#include "object-enchant/trg-types.h"
+#include "object-enchant/object-boost.h"
+#include "object-enchant/object-curse.h"
+#include "object-enchant/special-object-flags.h"
+#include "object-enchant/trc-types.h"
+#include "object-hook/hook-checker.h"
+#include "sv-definition/sv-protector-types.h"
+#include "sv-definition/sv-weapon-types.h"
 #include "util/bit-flags-calculator.h"
 #include "util/probability-table.h"
 #include <vector>
@@ -13,7 +19,7 @@
 /*
  * The ego-item arrays
  */
-ego_item_type *e_info;
+std::vector<ego_item_type> e_info;
 
 /*
  * Maximum number of ego-items in e_info.txt
@@ -48,3 +54,183 @@ byte get_random_ego(byte slot, bool good)
 
     return (EGO_IDX)0;
 }
+
+static void ego_invest_curse(player_type* player_ptr, object_type* o_ptr, FlagGroup<TRG>& gen_flags)
+{
+    if (gen_flags.has(TRG::CURSED))
+        o_ptr->curse_flags |= (TRC_CURSED);
+    if (gen_flags.has(TRG::HEAVY_CURSE))
+        o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
+    if (gen_flags.has(TRG::PERMA_CURSE))
+        o_ptr->curse_flags |= (TRC_PERMA_CURSE);
+    if (gen_flags.has(TRG::RANDOM_CURSE0))
+        o_ptr->curse_flags |= get_curse(player_ptr, 0, o_ptr);
+    if (gen_flags.has(TRG::RANDOM_CURSE1))
+        o_ptr->curse_flags |= get_curse(player_ptr, 1, o_ptr);
+    if (gen_flags.has(TRG::RANDOM_CURSE2))
+        o_ptr->curse_flags |= get_curse(player_ptr, 2, o_ptr);
+}
+
+static void ego_invest_extra_abilities(object_type *o_ptr, FlagGroup<TRG> &gen_flags)
+{
+    if (gen_flags.has(TRG::ONE_SUSTAIN))
+        one_sustain(o_ptr);
+    if (gen_flags.has(TRG::XTRA_POWER))
+        one_ability(o_ptr);
+    if (gen_flags.has(TRG::XTRA_H_RES))
+        one_high_resistance(o_ptr);
+    if (gen_flags.has(TRG::XTRA_E_RES))
+        one_ele_resistance(o_ptr);
+    if (gen_flags.has(TRG::XTRA_D_RES))
+        one_dragon_ele_resistance(o_ptr);
+    if (gen_flags.has(TRG::XTRA_L_RES))
+        one_lordly_high_resistance(o_ptr);
+    if (gen_flags.has(TRG::XTRA_RES))
+        one_resistance(o_ptr);
+    if (gen_flags.has(TRG::XTRA_DICE)) {
+        do {
+            o_ptr->dd++;
+        } while (one_in_(o_ptr->dd));
+
+        if (o_ptr->dd > 9)
+            o_ptr->dd = 9;
+    }
+}
+
+static void ego_interpret_extra_abilities(object_type *o_ptr, ego_item_type *e_ptr, FlagGroup<TRG> &gen_flags)
+{
+    for (auto& xtra : e_ptr->xtra_flags) {
+        if (xtra.mul == 0 || xtra.dev == 0)
+            continue;
+
+        if (randint0(xtra.dev) >= xtra.mul) //! @note mul/devで適用
+            continue;
+
+        auto n = xtra.tr_flags.size();
+        if (n > 0) {
+            auto f = xtra.tr_flags[randint0(n)];
+            auto except = (f == TR_VORPAL && o_ptr->tval != TV_SWORD);
+            if (!except)
+                add_flag(o_ptr->art_flags, f);
+        }
+
+        for (auto f : xtra.trg_flags)
+            gen_flags.set(f);
+    }
+}
+
+/*!
+ * @brief 0 および負数に対応した randint1()
+ * @param n
+ *
+ * n == 0 のとき、常に 0 を返す。
+ * n >  0 のとき、[1, n] の乱数を返す。
+ * n <  0 のとき、[n,-1] の乱数を返す。
+ */
+static int randint1_signed(const int n)
+{
+    if (n == 0)
+        return 0;
+
+    return n > 0 ? randint1(n) : -randint1(-n);
+}
+
+void apply_ego(player_type *player_ptr, object_type *o_ptr, DEPTH lev)
+{
+    auto e_ptr = &e_info[o_ptr->name2];
+    auto gen_flags = e_ptr->gen_flags;
+
+    ego_interpret_extra_abilities(o_ptr, e_ptr, gen_flags);
+
+    if (!e_ptr->cost)
+        o_ptr->ident |= (IDENT_BROKEN);
+
+    ego_invest_curse(player_ptr, o_ptr, gen_flags);
+    ego_invest_extra_abilities(o_ptr, gen_flags);
+
+    if (e_ptr->act_idx)
+        o_ptr->xtra2 = (XTRA8)e_ptr->act_idx;
+
+    auto is_powerful = e_ptr->gen_flags.has(TRG::POWERFUL);
+    auto is_cursed = (object_is_cursed(o_ptr) || object_is_broken(o_ptr)) && !is_powerful;
+    if (is_cursed) {
+        if (e_ptr->max_to_h)
+            o_ptr->to_h -= randint1(e_ptr->max_to_h);
+        if (e_ptr->max_to_d)
+            o_ptr->to_d -= randint1(e_ptr->max_to_d);
+        if (e_ptr->max_to_a)
+            o_ptr->to_a -= randint1(e_ptr->max_to_a);
+        if (e_ptr->max_pval)
+            o_ptr->pval -= randint1(e_ptr->max_pval);
+    } else {
+        if (is_powerful) {
+            if (e_ptr->max_to_h > 0 && o_ptr->to_h < 0)
+                o_ptr->to_h = 0 - o_ptr->to_h;
+            if (e_ptr->max_to_d > 0 && o_ptr->to_d < 0)
+                o_ptr->to_d = 0 - o_ptr->to_d;
+            if (e_ptr->max_to_a > 0 && o_ptr->to_a < 0)
+                o_ptr->to_a = 0 - o_ptr->to_a;
+        }
+
+        o_ptr->to_h += (HIT_PROB)randint1_signed(e_ptr->max_to_h);
+        o_ptr->to_d += randint1_signed(e_ptr->max_to_d);
+        o_ptr->to_a += (ARMOUR_CLASS)randint1_signed(e_ptr->max_to_a);
+        if (o_ptr->name2 == EGO_ACCURACY) {
+            while (o_ptr->to_h < o_ptr->to_d + 10) {
+                o_ptr->to_h += 5;
+                o_ptr->to_d -= 5;
+            }
+            o_ptr->to_h = MAX(o_ptr->to_h, 15);
+        }
+
+        if (o_ptr->name2 == EGO_VELOCITY) {
+            while (o_ptr->to_d < o_ptr->to_h + 10) {
+                o_ptr->to_d += 5;
+                o_ptr->to_h -= 5;
+            }
+            o_ptr->to_d = MAX(o_ptr->to_d, 15);
+        }
+
+        if ((o_ptr->name2 == EGO_PROTECTION) || (o_ptr->name2 == EGO_S_PROTECTION) || (o_ptr->name2 == EGO_H_PROTECTION)) {
+            o_ptr->to_a = MAX(o_ptr->to_a, 15);
+        }
+
+        if (e_ptr->max_pval) {
+            if ((o_ptr->name2 == EGO_HA) && (has_flag(o_ptr->art_flags, TR_BLOWS))) {
+                o_ptr->pval++;
+                if ((lev > 60) && one_in_(3) && ((o_ptr->dd * (o_ptr->ds + 1)) < 15))
+                    o_ptr->pval++;
+            } else if (o_ptr->name2 == EGO_DEMON) {
+                if (has_flag(o_ptr->art_flags, TR_BLOWS)) {
+                    o_ptr->pval += randint1(2);
+                } else {
+                    o_ptr->pval += randint1(e_ptr->max_pval);
+                }
+            } else if (o_ptr->name2 == EGO_ATTACKS) {
+                o_ptr->pval = randint1(e_ptr->max_pval * lev / 100 + 1);
+                if (o_ptr->pval > 3)
+                    o_ptr->pval = 3;
+                if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_HAYABUSA))
+                    o_ptr->pval += randint1(2);
+            } else if (o_ptr->name2 == EGO_BAT) {
+                o_ptr->pval = randint1(e_ptr->max_pval);
+                if (o_ptr->sval == SV_ELVEN_CLOAK)
+                    o_ptr->pval += randint1(2);
+            } else if (o_ptr->name2 == EGO_A_DEMON || o_ptr->name2 == EGO_DRUID || o_ptr->name2 == EGO_OLOG) {
+                o_ptr->pval = randint1(e_ptr->max_pval);
+            } else {
+                if (e_ptr->max_pval > 0)
+                    o_ptr->pval += randint1(e_ptr->max_pval);
+                else if (e_ptr->max_pval < 0)
+                    o_ptr->pval -= randint1(0 - e_ptr->max_pval);
+            }
+        }
+
+        if ((o_ptr->name2 == EGO_SPEED) && (lev < 50)) {
+            o_ptr->pval = randint1(o_ptr->pval);
+        }
+
+        if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_HAYABUSA) && (o_ptr->pval > 2) && (o_ptr->name2 != EGO_ATTACKS))
+            o_ptr->pval = 2;
+    }
+}
index 3ebe574..30fba5c 100644 (file)
@@ -1,10 +1,14 @@
 #pragma once
 
-#include "object-enchant/trg-types.h"
 #include "system/angband.h"
+
+#include "object-enchant/tr-types.h"
+#include "object-enchant/trg-types.h"
 #include "system/object-type-definition.h"
 #include "util/flag-group.h"
+
 #include <string>
+#include <vector>
 
 /* Body Armor */
 #define EGO_A_MORGUL            4
 #define EGO_AMU_NAIVETY         237
 // MAX 240
 
+struct ego_generate_type {
+    int mul{}; //<! 確率分子
+    int dev{}; //<! 確率分母
+    std::vector<tr_type> tr_flags{};
+    std::vector<TRG> trg_flags{};
+};
+
 /*
  * Information about "ego-items".
  */
-typedef struct ego_item_type {
-    std::string name; /* Name (offset) */
-    std::string text; /* Text (offset) */
+struct ego_item_type {
+    std::string name; //!< エゴの名前
+    std::string text; //!< フレーバーテキスト
 
-    INVENTORY_IDX slot{}; /*!< 装備部位 / Standard slot value */
-    PRICE rating{}; /*!< ベースアイテムからの価値加速 / Rating boost */
+    INVENTORY_IDX slot{}; //!< 装備部位 / Standard slot value
+    PRICE rating{}; //!< レーティングボーナス(雰囲気に影響) / Rating boost
 
-    DEPTH level{}; /* Minimum level */
-    RARITY rarity{}; /* Object rarity */
+    DEPTH level{}; //!< 生成レベル
+    RARITY rarity{}; //<! レアリティ
 
-    HIT_PROB max_to_h{}; /* Maximum to-hit bonus */
-    HIT_POINT max_to_d{}; /* Maximum to-dam bonus */
-    ARMOUR_CLASS max_to_a{}; /* Maximum to-ac bonus */
+    HIT_PROB max_to_h{}; //!< 最大ボーナス命中修正
+    HIT_POINT max_to_d{}; //!< 最大ボーナスダメージ修正
+    ARMOUR_CLASS max_to_a{}; //!< 最大ボーナスAC修正
 
-    PARAMETER_VALUE max_pval{}; /* Maximum pval */
+    PARAMETER_VALUE max_pval{}; //!< 最大pval
 
-    PRICE cost{}; /* Ego-item "cost" */
+    PRICE cost{}; //!< コスト
 
-    BIT_FLAGS flags[TR_FLAG_SIZE]{}; /* Ego-Item Flags */
-    FlagGroup<TRG> gen_flags; /* flags for generate */
+    BIT_FLAGS flags[TR_FLAG_SIZE]{}; //!< 能力/耐性フラグ
+    FlagGroup<TRG> gen_flags; //!< 生成時適用フラグ
+    std::vector<ego_generate_type> xtra_flags{}; //!< 追加能力/耐性フラグ
 
-    IDX act_idx{}; /* Activative ability index */
-} ego_item_type;
+    IDX act_idx{}; //!< 発動番号 / Activative ability index
+};
 
 extern EGO_IDX max_e_idx;
-extern ego_item_type *e_info;
+extern std::vector<ego_item_type> e_info;
 
 byte get_random_ego(byte slot, bool good);
+void apply_ego(player_type *player_ptr, object_type *o_ptr, DEPTH lev);
index e3ce647..42e659a 100644 (file)
@@ -143,7 +143,7 @@ enum tr_type {
     TR_COWARDICE = 132,
     TR_LOW_MELEE = 133,
     TR_LOW_AC = 134,
-    TR_LOW_MAGIC = 135,
+    TR_HARD_SPELL = 135,
     TR_FAST_DIGEST = 136,
     TR_SLOW_REGEN = 137,
     TR_MIGHTY_THROW = 138,
index 73a6742..89e6f10 100644 (file)
@@ -19,7 +19,7 @@ enum trc_curse_type {
     TRC_TELEPORT = 0x00004000L,
     TRC_LOW_MELEE = 0x00008000L,
     TRC_LOW_AC = 0x00010000L,
-    TRC_LOW_MAGIC = 0x00020000L,
+    TRC_HARD_SPELL = 0x00020000L,
     TRC_FAST_DIGEST = 0x00040000L,
     TRC_DRAIN_HP = 0x00080000L,
     TRC_DRAIN_MANA = 0x00100000L,
index 235fa32..683ef96 100644 (file)
@@ -96,9 +96,6 @@ bool item_tester_hook_recharge(player_type *player_ptr, object_type *o_ptr)
  */
 bool item_tester_learn_spell(player_type *player_ptr, object_type *o_ptr)
 {
-    if (player_ptr->pclass == CLASS_ELEMENTALIST)
-        return FALSE;
-
     s32b choices = realm_choices2[player_ptr->pclass];
     if (player_ptr->pclass == CLASS_PRIEST) {
         if (is_good_realm(player_ptr->realm1)) {
index f2e2a7a..7e91a70 100644 (file)
@@ -149,6 +149,11 @@ bool object_is_favorite(player_type *player_ptr, object_type *o_ptr)
         break;
     }
 
+    case CLASS_SORCERER:
+        if (s_info[player_ptr->pclass].w_max[o_ptr->tval - TV_WEAPON_BEGIN][o_ptr->sval] < WEAPON_EXP_MASTER)
+            return FALSE;
+        break;
+
     case CLASS_NINJA:
         /* Icky to wield? */
         if (s_info[player_ptr->pclass].w_max[o_ptr->tval - TV_WEAPON_BEGIN][o_ptr->sval] <= WEAPON_EXP_BEGINNER)
index 3bd50a1..e386cdf 100644 (file)
@@ -276,8 +276,6 @@ bool check_book_realm(player_type *owner_ptr, const tval_type book_tval, const O
 {
     if (book_tval < TV_LIFE_BOOK)
         return FALSE;
-    if (owner_ptr->pclass == CLASS_ELEMENTALIST)
-        return FALSE;
     if (owner_ptr->pclass == CLASS_SORCERER) {
         return is_magic(tval2realm(book_tval));
     } else if (owner_ptr->pclass == CLASS_RED_MAGE) {
index 5b1356a..50ede42 100644 (file)
@@ -12,7 +12,7 @@
 /*
  * The object kind arrays
  */
-object_kind *k_info;
+std::vector<object_kind> k_info;
 
 /*
  * Maximum number of items in k_info.txt
index 5e5d4bb..fb61fca 100644 (file)
@@ -1,10 +1,13 @@
 #pragma once
 
-#include "object-enchant/trg-types.h"
 #include "system/angband.h"
+
+#include "object-enchant/trg-types.h"
 #include "system/object-type-definition.h"
 #include "util/flag-group.h"
+
 #include <string>
+#include <vector>
 
 typedef struct object_kind {
     std::string name; /*!< ベースアイテム名参照のためのネームバッファオフセット値 / Name (offset) */
@@ -53,7 +56,7 @@ typedef struct object_kind {
     ACTIVATION_IDX act_idx{}; /*!< 発動能力のID /  Activative ability index */
 } object_kind;
 
-extern object_kind *k_info;
+extern std::vector<object_kind> k_info;
 extern KIND_OBJECT_IDX max_k_idx;
 
 SYMBOL_CODE object_char(object_type *o_ptr);
index 6b81fae..44d5857 100644 (file)
@@ -400,7 +400,7 @@ PRICE flag_cost(player_type *player_ptr, object_type *o_ptr, int plusses)
         total -= 5000;
     if (has_flag(flgs, TR_LOW_AC))
         total -= 5000;
-    if (has_flag(flgs, TR_LOW_MAGIC))
+    if (has_flag(flgs, TR_HARD_SPELL))
         total -= 15000;
     if (has_flag(flgs, TR_FAST_DIGEST))
         total -= 10000;
index 1652ddb..08d00a0 100644 (file)
 #include "monster-attack/monster-attack-effect.h"
 #include "monster-attack/monster-attack-types.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability1.h"
-#include "monster-race/race-flags-ability2.h"
 #include "monster-race/race-flags1.h"
-#include "monster-race/race-flags4.h"
 #include "monster-race/race-indice-types.h"
 #include "monster/monster-info.h"
 #include "monster/monster-status.h"
@@ -245,7 +242,7 @@ static void spell_damcalc(player_type *target_ptr, monster_type *m_ptr, EFFECT_I
 /*!
  * @brief 警告基準を定めるために魔法の効果属性に基づいて最大魔法ダメージを計算する。 /
  * Calculate spell damages
- * @param spell_num RF4ならRF4_SPELL_STARTのように32区切りのベースとなる数値
+ * @param spell_num RF4ならRF_ABILITY::SPELL_STARTのように32区切りのベースとなる数値
  * @param typ 効果属性のID
  * @param m_idx 魔法を行使するモンスターのID
  * @param max 算出した最大ダメージを返すポインタ
@@ -375,70 +372,68 @@ bool process_warning(player_type *creature_ptr, POSITION xx, POSITION yy)
 
             /* Monster spells (only powerful ones)*/
             if (projectable(creature_ptr, my, mx, yy, xx)) {
-                BIT_FLAGS f4 = r_ptr->flags4;
-                BIT_FLAGS f5 = r_ptr->a_ability_flags1;
-                BIT_FLAGS f6 = r_ptr->a_ability_flags2;
+                const auto flags = r_ptr->ability_flags;
 
                 if (!(d_info[creature_ptr->dungeon_idx].flags1 & DF1_NO_MAGIC)) {
-                    if (f4 & RF4_BA_CHAO)
+                    if (flags.has(RF_ABILITY::BA_CHAO))
                         spell_damcalc_by_spellnum(creature_ptr, MS_BALL_CHAOS, GF_CHAOS, g_ptr->m_idx, &dam_max0);
-                    if (f5 & RF5_BA_MANA)
+                    if (flags.has(RF_ABILITY::BA_MANA))
                         spell_damcalc_by_spellnum(creature_ptr, MS_BALL_MANA, GF_MANA, g_ptr->m_idx, &dam_max0);
-                    if (f5 & RF5_BA_DARK)
+                    if (flags.has(RF_ABILITY::BA_DARK))
                         spell_damcalc_by_spellnum(creature_ptr, MS_BALL_DARK, GF_DARK, g_ptr->m_idx, &dam_max0);
-                    if (f5 & RF5_BA_LITE)
+                    if (flags.has(RF_ABILITY::BA_LITE))
                         spell_damcalc_by_spellnum(creature_ptr, MS_STARBURST, GF_LITE, g_ptr->m_idx, &dam_max0);
-                    if (f6 & RF6_HAND_DOOM)
+                    if (flags.has(RF_ABILITY::HAND_DOOM))
                         spell_damcalc_by_spellnum(creature_ptr, MS_HAND_DOOM, GF_HAND_DOOM, g_ptr->m_idx, &dam_max0);
-                    if (f6 & RF6_PSY_SPEAR)
+                    if (flags.has(RF_ABILITY::PSY_SPEAR))
                         spell_damcalc_by_spellnum(creature_ptr, MS_PSY_SPEAR, GF_PSY_SPEAR, g_ptr->m_idx, &dam_max0);
                 }
 
-                if (f4 & RF4_ROCKET)
+                if (flags.has(RF_ABILITY::ROCKET))
                     spell_damcalc_by_spellnum(creature_ptr, MS_ROCKET, GF_ROCKET, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_ACID)
+                if (flags.has(RF_ABILITY::BR_ACID))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_ACID, GF_ACID, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_ELEC)
+                if (flags.has(RF_ABILITY::BR_ELEC))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_ELEC, GF_ELEC, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_FIRE)
+                if (flags.has(RF_ABILITY::BR_FIRE))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_FIRE, GF_FIRE, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_COLD)
+                if (flags.has(RF_ABILITY::BR_COLD))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_COLD, GF_COLD, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_POIS)
+                if (flags.has(RF_ABILITY::BR_POIS))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_POIS, GF_POIS, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_NETH)
+                if (flags.has(RF_ABILITY::BR_NETH))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_NETHER, GF_NETHER, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_LITE)
+                if (flags.has(RF_ABILITY::BR_LITE))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_LITE, GF_LITE, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_DARK)
+                if (flags.has(RF_ABILITY::BR_DARK))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_DARK, GF_DARK, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_CONF)
+                if (flags.has(RF_ABILITY::BR_CONF))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_CONF, GF_CONFUSION, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_SOUN)
+                if (flags.has(RF_ABILITY::BR_SOUN))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_SOUND, GF_SOUND, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_CHAO)
+                if (flags.has(RF_ABILITY::BR_CHAO))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_CHAOS, GF_CHAOS, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_DISE)
+                if (flags.has(RF_ABILITY::BR_DISE))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_DISEN, GF_DISENCHANT, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_NEXU)
+                if (flags.has(RF_ABILITY::BR_NEXU))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_NEXUS, GF_NEXUS, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_TIME)
+                if (flags.has(RF_ABILITY::BR_TIME))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_TIME, GF_TIME, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_INER)
+                if (flags.has(RF_ABILITY::BR_INER))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_INERTIA, GF_INERTIAL, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_GRAV)
+                if (flags.has(RF_ABILITY::BR_GRAV))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_GRAVITY, GF_GRAVITY, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_SHAR)
+                if (flags.has(RF_ABILITY::BR_SHAR))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_SHARDS, GF_SHARDS, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_PLAS)
+                if (flags.has(RF_ABILITY::BR_PLAS))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_PLASMA, GF_PLASMA, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_WALL)
+                if (flags.has(RF_ABILITY::BR_WALL))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_FORCE, GF_FORCE, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_MANA)
+                if (flags.has(RF_ABILITY::BR_MANA))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_MANA, GF_MANA, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_NUKE)
+                if (flags.has(RF_ABILITY::BR_NUKE))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_NUKE, GF_NUKE, g_ptr->m_idx, &dam_max0);
-                if (f4 & RF4_BR_DISI)
+                if (flags.has(RF_ABILITY::BR_DISI))
                     spell_damcalc_by_spellnum(creature_ptr, MS_BR_DISI, GF_DISINTEGRATE, g_ptr->m_idx, &dam_max0);
             }
 
index ce60449..65cf19b 100644 (file)
@@ -102,7 +102,7 @@ bool screen_object(player_type *player_ptr, object_type *o_ptr, BIT_FLAGS mode)
         info[i++] = _("それは物を強く投げることを可能にする。", "It provides great strength when you throw an item.");
     }
 
-    if (has_flag(flgs, TR_LOW_MAGIC)) {
+    if (has_flag(flgs, TR_DOWN_SAVING)) {
         info[i++] = _("それは魔法抵抗力を下げる。", "It decreases your magic resistance.");
     }
 
@@ -634,7 +634,7 @@ bool screen_object(player_type *player_ptr, object_type *o_ptr, BIT_FLAGS mode)
         info[i++] = _("それは攻撃を受けやすい。", "It helps your enemies' blows.");
     }
 
-    if ((has_flag(flgs, TR_LOW_MAGIC)) || (o_ptr->curse_flags & TRC_LOW_MAGIC)) {
+    if ((has_flag(flgs, TR_HARD_SPELL)) || (o_ptr->curse_flags & TRC_HARD_SPELL)) {
         info[i++] = _("それは魔法を唱えにくくする。", "It encumbers you while spellcasting.");
     }
 
index 3f342be..22c2cf6 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "player-info/avatar.h"
 #include "core/player-update-types.h"
+#include "game-option/text-display-options.h"
 #include "player/player-class.h"
 #include "player/player-race-types.h"
 #include "realm/realm-names-table.h"
@@ -524,35 +525,36 @@ void dump_virtues(player_type *creature_ptr, FILE *out_file)
         GAME_TEXT vir_name[20];
         int tester = creature_ptr->virtues[v_nr];
         strcpy(vir_name, virtue[(creature_ptr->vir_types[v_nr]) - 1]);
+        concptr vir_val = show_actual_value ? format(" (%d)", tester) : "";
         if (creature_ptr->vir_types[v_nr] == 0 || creature_ptr->vir_types[v_nr] > MAX_VIRTUE)
             fprintf(out_file, _("おっと。%sの情報なし。", "Oops. No info about %s."), vir_name);
 
         else if (tester < -100)
-            fprintf(out_file, _("[%s]の対極", "You are the polar opposite of %s."), vir_name);
+            fprintf(out_file, _("[%s]の対極%s", "You are the polar opposite of %s.%s"), vir_name, vir_val);
         else if (tester < -80)
-            fprintf(out_file, _("[%s]の大敵", "You are an arch-enemy of %s."), vir_name);
+            fprintf(out_file, _("[%s]の大敵%s", "You are an arch-enemy of %s.%s"), vir_name, vir_val);
         else if (tester < -60)
-            fprintf(out_file, _("[%s]の強敵", "You are a bitter enemy of %s."), vir_name);
+            fprintf(out_file, _("[%s]の強敵%s", "You are a bitter enemy of %s.%s"), vir_name, vir_val);
         else if (tester < -40)
-            fprintf(out_file, _("[%s]の敵", "You are an enemy of %s."), vir_name);
+            fprintf(out_file, _("[%s]の敵%s", "You are an enemy of %s.%s"), vir_name, vir_val);
         else if (tester < -20)
-            fprintf(out_file, _("[%s]の罪者", "You have sinned against %s."), vir_name);
+            fprintf(out_file, _("[%s]の罪者%s", "You have sinned against %s.%s"), vir_name, vir_val);
         else if (tester < 0)
-            fprintf(out_file, _("[%s]の迷道者", "You have strayed from the path of %s."), vir_name);
+            fprintf(out_file, _("[%s]の迷道者%s", "You have strayed from the path of %s.%s"), vir_name, vir_val);
         else if (tester == 0)
-            fprintf(out_file, _("[%s]の中立者", "You are neutral to %s."), vir_name);
+            fprintf(out_file, _("[%s]の中立者%s", "You are neutral to %s.%s"), vir_name, vir_val);
         else if (tester < 20)
-            fprintf(out_file, _("[%s]の小徳者", "You are somewhat virtuous in %s."), vir_name);
+            fprintf(out_file, _("[%s]の小徳者%s", "You are somewhat virtuous in %s.%s"), vir_name, vir_val);
         else if (tester < 40)
-            fprintf(out_file, _("[%s]の中徳者", "You are virtuous in %s."), vir_name);
+            fprintf(out_file, _("[%s]の中徳者%s", "You are virtuous in %s.%s"), vir_name, vir_val);
         else if (tester < 60)
-            fprintf(out_file, _("[%s]の高徳者", "You are very virtuous in %s."), vir_name);
+            fprintf(out_file, _("[%s]の高徳者%s", "You are very virtuous in %s.%s"), vir_name, vir_val);
         else if (tester < 80)
-            fprintf(out_file, _("[%s]の覇者", "You are a champion of %s."), vir_name);
+            fprintf(out_file, _("[%s]の覇者%s", "You are a champion of %s.%s"), vir_name, vir_val);
         else if (tester < 100)
-            fprintf(out_file, _("[%s]の偉大な覇者", "You are a great champion of %s."), vir_name);
+            fprintf(out_file, _("[%s]の偉大な覇者%s", "You are a great champion of %s.%s"), vir_name, vir_val);
         else
-            fprintf(out_file, _("[%s]の具現者", "You are the living embodiment of %s."), vir_name);
+            fprintf(out_file, _("[%s]の具現者%s", "You are the living embodiment of %s.%s"), vir_name, vir_val);
 
         fprintf(out_file, "\n");
     }
index b9c36dc..50c5cbd 100644 (file)
@@ -92,7 +92,7 @@ static void set_curse_info(player_type *creature_ptr, self_info_type *self_ptr)
     if (creature_ptr->cursed & TRC_LOW_AC)
         self_ptr->info[self_ptr->line++] = _("あなたは攻撃を受けやすい。", "You are subject to be hit.");
 
-    if (creature_ptr->cursed & TRC_LOW_MAGIC)
+    if (creature_ptr->cursed & TRC_HARD_SPELL)
         self_ptr->info[self_ptr->line++] = _("あなたは魔法を失敗しやすい。", "Your spells fail more frequently.");
 
     if (creature_ptr->cursed & TRC_FAST_DIGEST)
index 3871cb3..0232d4c 100644 (file)
@@ -14,8 +14,7 @@
  * The magic info
  */
 const player_magic *mp_ptr;
-player_magic *m_info;
-
+std::vector<player_magic> m_info;
 
 const player_class *cp_ptr;
 
index 79518c0..b640078 100644 (file)
@@ -1,12 +1,15 @@
 #pragma once
 
 /* 人畜無害なenumヘッダを先に読み込む */
-#include "player/player-classes-types.h"
+#include "system/angband.h"
+
 #include "object/tval-types.h"
+#include "player/player-classes-types.h"
 #include "realm/realm-types.h"
-#include "system/angband.h"
 #include "spell/technic-info-table.h"
+
 #include <string>
+#include <vector>
 
 /** m_info.txtでMPの無い職業に設定される */
 #define SPELL_FIRST_NO_SPELL 99
@@ -30,7 +33,7 @@ typedef struct player_magic {
     magic_type info[MAX_MAGIC][32]{}; /* The available spells */
 } player_magic;
 
-extern player_magic *m_info;
+extern std::vector<player_magic> m_info;
 extern const player_magic *mp_ptr;
 
 /*
index 44da0a6..5f05c20 100644 (file)
@@ -327,6 +327,8 @@ int take_hit(player_type *creature_ptr, int damage_type, HIT_POINT damage, concp
     }
 
     creature_ptr->chp -= damage;
+    if (creature_ptr->chp < -9999)
+        creature_ptr->chp = -9999;
     if (damage_type == DAMAGE_GENO && creature_ptr->chp < 0) {
         damage += creature_ptr->chp;
         creature_ptr->chp = 0;
@@ -340,7 +342,7 @@ int take_hit(player_type *creature_ptr, int damage_type, HIT_POINT damage, concp
         chg_virtue(creature_ptr, V_CHANCE, 2);
     }
 
-    if (creature_ptr->chp < 0) {
+    if (creature_ptr->chp < 0 && !cheat_immortal) {
         bool android = (creature_ptr->prace == RACE_ANDROID ? TRUE : FALSE);
 
 #ifdef JP
@@ -353,7 +355,7 @@ int take_hit(player_type *creature_ptr, int damage_type, HIT_POINT damage, concp
         chg_virtue(creature_ptr, V_SACRIFICE, 10);
         handle_stuff(creature_ptr);
         creature_ptr->leaving = TRUE;
-        creature_ptr->is_dead = TRUE;
+        if(!cheat_immortal) creature_ptr->is_dead = TRUE;
         if (creature_ptr->current_floor_ptr->inside_arena) {
             concptr m_name = r_info[arena_info[creature_ptr->arena_number].r_idx].name.c_str();
             msg_format(_("あなたは%sの前に敗れ去った。", "You are beaten by %s."), m_name);
index 6a52eeb..19d7c18 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * The skill table
  */
-skill_table *s_info;
+std::vector<skill_table> s_info;
 
 /*!
  * @brief 技能値到達表記テーブル
index 48df491..aa2b794 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "system/angband.h"
 #include <string>
+#include <vector>
 
 #define GINOU_SUDE 0
 #define GINOU_NITOURYU 1
@@ -49,4 +50,4 @@ typedef struct skill_table {
     SUB_EXP s_max[10]{}; /* max skill */
 } skill_table;
 
-extern skill_table *s_info;
+extern std::vector<skill_table> s_info;
index f40dfd3..eaf812f 100644 (file)
@@ -377,7 +377,7 @@ BIT_FLAGS get_player_flags(player_type *creature_ptr, tr_type tr_flag)
     case TR_COWARDICE:
     case TR_LOW_MELEE:
     case TR_LOW_AC:
-    case TR_LOW_MAGIC:
+    case TR_HARD_SPELL:
     case TR_FAST_DIGEST:
     case TR_SLOW_REGEN:
         return check_equipment_flags(creature_ptr, tr_flag);
@@ -694,7 +694,7 @@ void check_no_flowed(player_type *creature_ptr)
         return;
     }
 
-    if (!creature_ptr->realm1 || creature_ptr->pclass == CLASS_ELEMENTALIST) {
+    if (!creature_ptr->realm1) {
         creature_ptr->no_flowed = FALSE;
         return;
     }
@@ -1284,8 +1284,8 @@ void update_curses(player_type *creature_ptr)
             creature_ptr->cursed |= TRC_LOW_MELEE;
         if (has_flag(flgs, TR_LOW_AC))
             creature_ptr->cursed |= TRC_LOW_AC;
-        if (has_flag(flgs, TR_LOW_MAGIC))
-            creature_ptr->cursed |= TRC_LOW_MAGIC;
+        if (has_flag(flgs, TR_HARD_SPELL))
+            creature_ptr->cursed |= TRC_HARD_SPELL;
         if (has_flag(flgs, TR_FAST_DIGEST))
             creature_ptr->cursed |= TRC_FAST_DIGEST;
         if (has_flag(flgs, TR_SLOW_REGEN))
index 6238af9..c3adf83 100644 (file)
@@ -21,6 +21,7 @@
 #include "floor/floor-save.h"
 #include "floor/floor-util.h"
 #include "game-option/birth-options.h"
+#include "game-option/text-display-options.h"
 #include "grid/feature.h"
 #include "inventory/inventory-object.h"
 #include "inventory/inventory-slot-types.h"
@@ -150,11 +151,11 @@ player_type p_body;
 player_type *p_ptr = &p_body;
 
 /*!
- * @brief クリーチャーの抽象的善悪アライメントの表記を返す。 / Return alignment title
+ * @brief クリーチャーの抽象的善悪アライメントの表記名のみを返す。 / Return only alignment title
  * @param creature_ptr 算出するクリーチャーの参照ポインタ。
- * @return アライメントの表記を返す。
+ * @return アライメントの表記
  */
-concptr your_alignment(player_type *creature_ptr)
+concptr alignment_label(player_type *creature_ptr)
 {
     if (creature_ptr->align > 150)
         return _("大善", "Lawful");
@@ -173,6 +174,20 @@ concptr your_alignment(player_type *creature_ptr)
 }
 
 /*!
+ * @brief クリーチャーの抽象的善悪アライメントの表記を返す。 / Return alignment title
+ * @param creature_ptr 算出するクリーチャーの参照ポインタ。
+ * @return アライメントの表記を返す。
+ */
+concptr your_alignment(player_type *creature_ptr, bool with_value)
+{
+    auto s = alignment_label(creature_ptr);
+    if (with_value || show_actual_value)
+        return format(_("%s(%ld)", "%s (%ld)"), s, static_cast<long>(creature_ptr->align));
+
+    return s;
+}
+
+/*!
  * @brief 武器や各種スキル(騎乗以外)の抽象的表現ランクを返す。 /  Return proficiency level of weapons and misc. skills (except riding)
  * @param weapon_exp 経験値
  * @return ランク値
@@ -1715,7 +1730,7 @@ static s16b calc_num_blow(player_type *creature_ptr, int i)
  * * 性格きれものなら減算(-3)
  * * 性格ちからじまんとがまんづよいなら加算(+1)
  * * 性格チャージマンなら加算(+5)
- * * 装備品にTRC_LOW_MAGICがあるなら加算(軽い呪いなら+3/重い呪いなら+10)
+ * * 装備品にTRC_HARD_SPELLがあるなら加算(軽い呪いなら+3/重い呪いなら+10)
  */
 static s16b calc_to_magic_chance(player_type *creature_ptr)
 {
@@ -1737,7 +1752,7 @@ static s16b calc_to_magic_chance(player_type *creature_ptr)
         if (!o_ptr->k_idx)
             continue;
         object_flags(creature_ptr, o_ptr, flgs);
-        if (any_bits(o_ptr->curse_flags, TRC_LOW_MAGIC)) {
+        if (any_bits(o_ptr->curse_flags, TRC_HARD_SPELL)) {
             if (any_bits(o_ptr->curse_flags, TRC_HEAVY_CURSE)) {
                 chance += 10;
             } else {
index bfba5d6..e67bb7d 100644 (file)
@@ -65,6 +65,9 @@ enum player_hand { PLAYER_HAND_MAIN = 0x0000, PLAYER_HAND_SUB = 0x0001, PLAYER_H
 
 typedef struct floor_type floor_type;
 typedef struct object_type object_type;
+
+enum class RF_ABILITY;
+
 typedef struct player_type {
     int player_uid{};
     int player_euid{};
@@ -80,6 +83,7 @@ typedef struct player_type {
     player_personality_type pseikaku{}; /* Seikaku index */
     REALM_IDX realm1{}; /* First magic realm */
     REALM_IDX realm2{}; /* Second magic realm */
+    REALM_IDX element{}; //!< 元素使い領域番号 / Elementalist system index
     player_personality_type oops{}; /* Unused */
 
     DICE_SID hitdie{}; /* Hit dice (sides) */
@@ -235,7 +239,7 @@ typedef struct player_type {
     MAGIC_NUM1 magic_num1[MAX_SPELLS]{}; /*!< Array for non-spellbook type magic */
     MAGIC_NUM2 magic_num2[MAX_SPELLS]{}; /*!< 魔道具術師の取り込み済魔道具使用回数 / Flags for non-spellbook type magics */
 
-    SPELL_IDX mane_spell[MAX_MANE]{};
+    RF_ABILITY mane_spell[MAX_MANE]{};
     HIT_POINT mane_dam[MAX_MANE]{};
     s16b mane_num{};
     bool new_mane{};
@@ -468,7 +472,7 @@ typedef struct player_type {
 
 extern player_type *p_ptr;
 
-extern concptr your_alignment(player_type *creature_ptr);
+extern concptr your_alignment(player_type *creature_ptr, bool with_value = false);
 extern int weapon_exp_level(int weapon_exp);
 extern int riding_exp_level(int riding_exp);
 extern int spell_exp_level(int spell_exp);
index 76a16fa..6399326 100644 (file)
@@ -20,7 +20,7 @@
  * Extract a clean "base name".
  * Build the savefile name if needed.
  */
-void process_player_name(player_type *creature_ptr, bool sf)
+void process_player_name(player_type *creature_ptr, bool is_new_savefile)
 {
     char old_player_base[32] = "";
     if (current_world_ptr->character_generated)
@@ -81,39 +81,36 @@ void process_player_name(player_type *creature_ptr, bool sf)
     if (!creature_ptr->base_name[0])
         strcpy(creature_ptr->base_name, "PLAYER");
 
-    if (!keep_savefile || !savefile[0]) {
-#ifdef SAVEFILE_MUTABLE
-        sf = TRUE;
-#endif
-        if (!savefile_base[0] && savefile[0]) {
-            concptr s = savefile;
-            while (TRUE) {
-                concptr t;
-                t = angband_strstr(s, PATH_SEP);
-                if (!t)
-                    break;
-                s = t + 1;
-            }
-
-            strcpy(savefile_base, s);
-        }
+    auto is_modified = false;
+    if (is_new_savefile && (!savefile[0] || !keep_savefile)) {
+        char temp[128];
 
-        if (!savefile_base[0] || !savefile[0])
-            sf = TRUE;
+#ifdef SAVEFILE_USE_UID
+        /* Rename the savefile, using the creature_ptr->player_uid and creature_ptr->base_name */
+        (void)sprintf(temp, "%d.%s", creature_ptr->player_uid, creature_ptr->base_name);
+#else
+        /* Rename the savefile, using the creature_ptr->base_name */
+        (void)sprintf(temp, "%s", creature_ptr->base_name);
+#endif
+        path_build(savefile, sizeof(savefile), ANGBAND_DIR_SAVE, temp);
+        is_modified = true;
+    }
 
-        if (sf) {
-            char temp[128];
-            strcpy(savefile_base, creature_ptr->base_name);
+    if (is_modified  || !savefile_base[0]) {
+        concptr s = savefile;
+        while (TRUE) {
+            concptr t;
+            t = angband_strstr(s, PATH_SEP);
+            if (!t)
+                break;
+            s = t + 1;
+        }
 
 #ifdef SAVEFILE_USE_UID
-            /* Rename the savefile, using the creature_ptr->player_uid and creature_ptr->base_name */
-            (void)sprintf(temp, "%d.%s", creature_ptr->player_uid, creature_ptr->base_name);
+        strcpy(savefile_base, angband_strstr(s, ".") + 1);
 #else
-            /* Rename the savefile, using the creature_ptr->base_name */
-            (void)sprintf(temp, "%s", creature_ptr->base_name);
+        strcpy(savefile_base, s);
 #endif
-            path_build(savefile, sizeof(savefile), ANGBAND_DIR_SAVE, temp);
-        }
     }
 
     if (current_world_ptr->character_generated && !streq(old_player_base, creature_ptr->base_name)) {
index 6e5d4bc..1f6fb66 100644 (file)
@@ -1,6 +1,6 @@
-#pragma once
+#pragma once
 
 #include "system/angband.h"
 
-void process_player_name(player_type *creature_ptr, bool sf);
+void process_player_name(player_type *creature_ptr, bool is_new_savefile = false);
 void get_name(player_type *creature_ptr);
index 5096ad1..c5f30d7 100644 (file)
@@ -109,8 +109,8 @@ static void decide_breath_kind(player_type *creature_ptr, int *breath_type, conc
 
         break;
     case CLASS_ELEMENTALIST:
-        *breath_type = get_element_type(creature_ptr->realm1, 0);
-        *breath_type_description = get_element_name(creature_ptr->realm1, 0);
+        *breath_type = get_element_type(creature_ptr->element, 0);
+        *breath_type_description = get_element_name(creature_ptr->element, 0);
         break;
     default:
         break;
index 0c12210..1edcde0 100644 (file)
@@ -14,7 +14,6 @@
 #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-flags7.h"
 #include "monster/monster-info.h"
 #include "monster/monster-list.h"
@@ -85,28 +84,20 @@ static concptr pit_subtype_string(int type, bool nest)
         sprintf(inner_buf, "(%c)", vault_aux_char);
         break;
     case PIT_TYPE_DRAGON:
-        switch (vault_aux_dragon_mask4) {
-        case RF4_BR_ACID:
+        if (vault_aux_dragon_mask4.has_all_of({ RF_ABILITY::BR_ACID, RF_ABILITY::BR_ELEC, RF_ABILITY::BR_FIRE, RF_ABILITY::BR_COLD, RF_ABILITY::BR_POIS })) {
+            strcpy(inner_buf, _("(万色)", "(multi-hued)"));
+        } else if (vault_aux_dragon_mask4.has(RF_ABILITY::BR_ACID)) {
             strcpy(inner_buf, _("(酸)", "(acid)"));
-            break;
-        case RF4_BR_ELEC:
+        }else if (vault_aux_dragon_mask4.has(RF_ABILITY::BR_ELEC)) {
             strcpy(inner_buf, _("(稲妻)", "(lightning)"));
-            break;
-        case RF4_BR_FIRE:
+        }else if (vault_aux_dragon_mask4.has(RF_ABILITY::BR_FIRE)) {
             strcpy(inner_buf, _("(火炎)", "(fire)"));
-            break;
-        case RF4_BR_COLD:
+        }else if (vault_aux_dragon_mask4.has(RF_ABILITY::BR_COLD)) {
             strcpy(inner_buf, _("(冷気)", "(frost)"));
-            break;
-        case RF4_BR_POIS:
+        }else if (vault_aux_dragon_mask4.has(RF_ABILITY::BR_POIS)) {
             strcpy(inner_buf, _("(毒)", "(poison)"));
-            break;
-        case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
-            strcpy(inner_buf, _("(万色)", "(multi-hued)"));
-            break;
-        default:
+        } else {
             strcpy(inner_buf, _("(未定義)", "(undefined)"));
-            break;
         }
         break;
     }
index 56b2b6d..a31c98c 100644 (file)
@@ -35,7 +35,7 @@
 /*
  * The vault generation arrays
  */
-vault_type *v_info;
+std::vector<vault_type> v_info;
 
 /*
  * Maximum number of vaults in v_info.txt
index 88d2f9f..0231d41 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "system/angband.h"
 #include <string>
+#include <vector>
 
 typedef struct vault_type {
     std::string name; /* Name (offset) */
@@ -13,7 +14,7 @@ typedef struct vault_type {
     POSITION wid{}; /* Vault width */
 } vault_type;
 
-extern vault_type *v_info;
+extern std::vector<vault_type> v_info;
 extern VAULT_IDX max_v_idx;
 
 typedef struct dun_data_type dun_data_type;
index 5716ace..61f757d 100644 (file)
@@ -90,6 +90,9 @@ void wr_options(save_type type)
     if (cheat_diary_output)
         c |= 0x8000;
 
+    if (cheat_immortal)
+        c |= 0x0020;
+
     if (type == SAVE_TYPE_DEBUG)
         c |= 0xFFFF;
 
index e3a4696..0f7c1d8 100644 (file)
@@ -181,10 +181,8 @@ void wr_lore(MONRACE_IDX r_idx)
     wr_u32b(r_ptr->r_flags1);
     wr_u32b(r_ptr->r_flags2);
     wr_u32b(r_ptr->r_flags3);
-    wr_u32b(r_ptr->r_flags4);
-    wr_u32b(r_ptr->r_flags5);
-    wr_u32b(r_ptr->r_flags6);
     wr_u32b(r_ptr->r_flagsr);
+    wr_FlagGroup(r_ptr->r_ability_flags, wr_byte);
 
     wr_byte((byte)r_ptr->max_num);
     wr_s16b(r_ptr->floor_id);
index d0cd053..4fb8608 100644 (file)
@@ -9,6 +9,20 @@
 #include "world/world.h"
 
 /*!
+ * @brief セーブデータに領域情報を書き込む / Write player realms
+ * @param creature_ptr プレーヤーへの参照ポインタ
+ * @return なし
+ */
+static void wr_relams(player_type *creature_ptr)
+{
+    if (creature_ptr->pclass == CLASS_ELEMENTALIST)
+        wr_byte((byte)creature_ptr->element);
+    else
+        wr_byte((byte)creature_ptr->realm1);
+    wr_byte((byte)creature_ptr->realm2);
+}
+
+/*!
  * @brief セーブデータにプレーヤー情報を書き込む / Write some "player" info
  * @param creature_ptr プレーヤーへの参照ポインタ
  * @return なし
@@ -27,8 +41,7 @@ void wr_player(player_type *creature_ptr)
     wr_byte((byte)creature_ptr->pclass);
     wr_byte((byte)creature_ptr->pseikaku);
     wr_byte((byte)creature_ptr->psex);
-    wr_byte((byte)creature_ptr->realm1);
-    wr_byte((byte)creature_ptr->realm2);
+    wr_relams(creature_ptr);
     wr_byte(0);
 
     wr_byte((byte)creature_ptr->hitdie);
index b20866a..501efb8 100644 (file)
@@ -17,7 +17,6 @@
 #include "main/sound-of-music.h"
 #include "monster-floor/monster-move.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags-ability2.h"
 #include "monster-race/race-flags-resistance.h"
 #include "monster-race/race-flags7.h"
 #include "monster/monster-info.h"
@@ -384,7 +383,7 @@ void teleport_player(player_type *creature_ptr, POSITION dis, BIT_FLAGS mode)
                 monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[tmp_m_idx];
                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
 
-                bool is_resistible = (r_ptr->a_ability_flags2 & RF6_TPORT) != 0;
+                bool is_resistible = r_ptr->ability_flags.has(RF_ABILITY::TPORT);
                 is_resistible &= (r_ptr->flagsr & RFR_RES_TELE) == 0;
                 is_resistible &= monster_csleep_remaining(m_ptr) == 0;
                 if (is_resistible) {
@@ -424,7 +423,7 @@ void teleport_player_away(MONSTER_IDX m_idx, player_type *target_ptr, POSITION d
             monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[tmp_m_idx];
             monster_race *r_ptr = &r_info[m_ptr->r_idx];
 
-            bool is_resistible = (r_ptr->a_ability_flags2 & RF6_TPORT) != 0;
+            bool is_resistible = r_ptr->ability_flags.has(RF_ABILITY::TPORT);
             is_resistible &= (r_ptr->flagsr & RFR_RES_TELE) == 0;
             is_resistible &= monster_csleep_remaining(m_ptr) == 0;
             if (is_resistible) {
index 50f1cda..62d2570 100644 (file)
@@ -276,6 +276,7 @@ bool life_stream(player_type *creature_ptr, bool message, bool virtue_change)
     (void)set_image(creature_ptr, 0);
     (void)set_stun(creature_ptr, 0);
     (void)set_cut(creature_ptr, 0);
+    (void)set_paralyzed(creature_ptr, 0);
     (void)restore_all_status(creature_ptr);
     (void)set_shero(creature_ptr, 0, TRUE);
     handle_stuff(creature_ptr);
similarity index 99%
rename from src/market/articles-on-sale.cpp
rename to src/store/articles-on-sale.cpp
index 6cd4302..898655a 100644 (file)
@@ -1,4 +1,4 @@
-#include "market/articles-on-sale.h"
+#include "store/articles-on-sale.h"
 #include "sv-definition/sv-amulet-types.h"
 #include "sv-definition/sv-armor-types.h"
 #include "sv-definition/sv-bow-types.h"
similarity index 98%
rename from src/cmd-building/cmd-store.cpp
rename to src/store/cmd-store.cpp
index 71558a5..14ad4f0 100644 (file)
@@ -1,5 +1,4 @@
-#include "cmd-building/cmd-store.h"
-#include "cmd-io/macro-util.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 "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/cmd-store.h"
 #include "store/home.h"
+#include "store/store-key-processor.h"
 #include "store/store-util.h"
 #include "store/store.h"
 #include "system/floor-type-definition.h"
similarity index 99%
rename from src/market/gold-magnification-table.cpp
rename to src/store/gold-magnification-table.cpp
index 1d3e019..7133c20 100644 (file)
@@ -1,4 +1,4 @@
-#include "market/gold-magnification-table.h"
+#include "store/gold-magnification-table.h"
 
 /*
  * Buying and selling adjustments for race combinations.
diff --git a/src/store/owner-insults.cpp b/src/store/owner-insults.cpp
deleted file mode 100644 (file)
index 0827f87..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-#include "store/owner-insults.h"
-#include "core/asking-player.h"
-#include "game-option/birth-options.h"
-#include "store/say-comments.h"
-#include "store/store.h"
-#include "store/store-util.h"
-#include "term/screen-processor.h"
-#include "view/display-messages.h"
-#include "world/world.h"
-
-/* Last "increment" during haggling */
-static s32b last_inc = 0L;
-
-/*!
- * @brief 店主の不満度を増やし、プレイヤーを締め出す判定と処理を行う /
- * Increase the insult counter and get angry if too many -RAK-
- * @return プレイヤーを締め出す場合TRUEを返す
- */
-int increase_insults(void)
-{
-    st_ptr->insult_cur++;
-    if (st_ptr->insult_cur <= ot_ptr->insult_max)
-        return FALSE;
-
-    say_comment_4();
-    st_ptr->insult_cur = 0;
-    st_ptr->good_buy = 0;
-    st_ptr->bad_buy = 0;
-    st_ptr->store_open = current_world_ptr->game_turn + TURNS_PER_TICK * TOWN_DAWN / 8 + randint1(TURNS_PER_TICK * TOWN_DAWN / 8);
-    return TRUE;
-}
-
-/*!
- * @brief 店主の不満度を減らす /
- * Decrease insults                            -RAK-
- * @return プレイヤーを締め出す場合TRUEを返す
- */
-void decrease_insults(void)
-{
-    if (st_ptr->insult_cur)
-        st_ptr->insult_cur--;
-}
-
-/*!
- * @brief 店主の不満度が増えた場合のみのメッセージを表示する /
- * Have insulted while haggling                        -RAK-
- * @return プレイヤーを締め出す場合TRUEを返す
- */
-int haggle_insults(void)
-{
-    if (increase_insults())
-        return TRUE;
-
-    say_comment_5();
-    return FALSE;
-}
-
-/*!
- * @brief 店主の持つプレイヤーに対する売買の良し悪し経験を記憶する /
- * Update the bargain info
- * @param price 実際の取引価格
- * @param minprice 店主の提示した価格
- * @param num 売買数
- * @return なし
- */
-void updatebargain(PRICE price, PRICE minprice, int num)
-{
-    if (!manual_haggle)
-        return;
-    if ((minprice / num) < 10L)
-        return;
-    if (price == minprice) {
-        if (st_ptr->good_buy < MAX_SHORT) {
-            st_ptr->good_buy++;
-        }
-    } else {
-        if (st_ptr->bad_buy < MAX_SHORT) {
-            st_ptr->bad_buy++;
-        }
-    }
-}
-
-/*!
- * @brief 交渉価格を確認と認証の是非を行う /
- * Get a haggle
- * @param pmt メッセージ
- * @param poffer 別途価格提示をした場合の値を返す参照ポインタ
- * @param price 現在の交渉価格
- * @param final 最終確定価格ならばTRUE
- * @return プレイヤーを締め出す場合TRUEを返す
- */
-static int get_haggle(concptr pmt, s32b *poffer, PRICE price, int final)
-{
-    GAME_TEXT buf[128];
-    if (!allow_inc)
-        last_inc = 0L;
-
-    if (final) {
-        sprintf(buf, _("%s [承諾] ", "%s [accept] "), pmt);
-    } else if (last_inc < 0) {
-        sprintf(buf, _("%s [-$%ld] ", "%s [-%ld] "), pmt, (long)(ABS(last_inc)));
-    } else if (last_inc > 0) {
-        sprintf(buf, _("%s [+$%ld] ", "%s [+%ld] "), pmt, (long)(ABS(last_inc)));
-    } else {
-        sprintf(buf, "%s ", pmt);
-    }
-
-    msg_print(NULL);
-    GAME_TEXT out_val[160];
-    while (TRUE) {
-        bool res;
-        prt(buf, 0, 0);
-        strcpy(out_val, "");
-
-        /*
-         * Ask the user for a response.
-         * Don't allow to use numpad as cursor key.
-         */
-        res = askfor_aux(out_val, 32, FALSE);
-        prt("", 0, 0);
-        if (!res)
-            return FALSE;
-
-        concptr p;
-        for (p = out_val; *p == ' '; p++) /* loop */
-            ;
-
-        if (*p == '\0') {
-            if (final) {
-                *poffer = price;
-                last_inc = 0L;
-                break;
-            }
-
-            if (allow_inc && last_inc) {
-                *poffer += last_inc;
-                break;
-            }
-
-            msg_print(_("値がおかしいです。", "Invalid response."));
-            msg_print(NULL);
-            continue;
-        }
-
-        s32b i = atol(p);
-        if ((*p == '+' || *p == '-')) {
-            if (allow_inc) {
-                *poffer += i;
-                last_inc = i;
-                break;
-            }
-        } else {
-            *poffer = i;
-            last_inc = 0L;
-            break;
-        }
-    }
-
-    return TRUE;
-}
-
-/*!
- * @brief 店主がプレイヤーからの交渉価格を判断する /
- * Receive an offer (from the player)
- * @param pmt メッセージ
- * @param poffer 店主からの交渉価格を返す参照ポインタ
- * @param last_offer 現在の交渉価格
- * @param factor 店主の価格基準倍率
- * @param price アイテムの実価値
- * @param final 最終価格確定ならばTRUE
- * @return プレイヤーの価格に対して不服ならばTRUEを返す /
- * Return TRUE if offer is NOT okay
- */
-bool receive_offer(concptr pmt, s32b *poffer, s32b last_offer, int factor, PRICE price, int final)
-{
-    while (TRUE) {
-        if (!get_haggle(pmt, poffer, price, final))
-            return TRUE;
-
-        if (((*poffer) * factor) >= (last_offer * factor))
-            break;
-
-        if (haggle_insults())
-            return TRUE;
-
-        *poffer = last_offer;
-    }
-
-    return FALSE;
-}
diff --git a/src/store/owner-insults.h b/src/store/owner-insults.h
deleted file mode 100644 (file)
index 18d1887..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-
-#include "system/angband.h"
-
-int increase_insults(void);
-void decrease_insults(void);
-int haggle_insults(void);
-void updatebargain(PRICE price, PRICE minprice, int num);
-bool receive_offer(concptr pmt, s32b *poffer, s32b last_offer, int factor, PRICE price, int final);
index 05aed0d..42a59c2 100644 (file)
@@ -1,7 +1,7 @@
 #include "store/pricing.h"
-#include "market/gold-magnification-table.h"
 #include "object/object-value.h"
 #include "player/player-status-table.h"
+#include "store/gold-magnification-table.h"
 #include "store/store-util.h"
 #include "store/store.h"
 
@@ -61,16 +61,3 @@ PRICE price_item(player_type *player_ptr, object_type *o_ptr, int greed, bool fl
 
     return price;
 }
-
-/*!
- * @brief 店舗の割引対象外にするかどうかを判定 /
- * Eliminate need to bargain if player has haggled well in the past
- * @param minprice アイテムの最低販売価格
- * @return 割引を禁止するならTRUEを返す。
- */
-bool noneedtobargain(PRICE minprice)
-{
-    PRICE good = st_ptr->good_buy;
-    PRICE bad = st_ptr->bad_buy;
-    return (minprice < 10L) || (good == MAX_SHORT) || (good > ((3 * bad) + (5 + (minprice / 50))));
-}
index bf92616..b869b71 100644 (file)
@@ -2,5 +2,6 @@
 
 #include "system/angband.h"
 
+#define LOW_PRICE_THRESHOLD 10L
+
 PRICE price_item(player_type *player_ptr, object_type *o_ptr, int greed, bool flip);
-bool noneedtobargain(PRICE minprice);
index e37a5bc..d419c16 100644 (file)
@@ -21,7 +21,6 @@
 #include "player-info/avatar.h"
 #include "player/race-info-table.h"
 #include "store/home.h"
-#include "store/owner-insults.h"
 #include "store/pricing.h"
 #include "store/say-comments.h"
 #include "store/store-util.h"
 #include "view/display-messages.h"
 #include "view/display-store.h"
 #include "world/world.h"
-
-typedef struct haggle_type {
-    object_type *o_ptr;
-    s32b *price;
-    s32b cur_ask;
-    s32b final_ask;
-    int noneed;
-    bool final;
-    concptr pmt;
-    s32b min_per;
-    s32b max_per;
-    s32b last_offer;
-    s32b offer;
-    bool flag;
-    int annoyed;
-    bool cancel;
-} haggle_type;
-
-static haggle_type *initialize_haggle_type(player_type *player_ptr, haggle_type *haggle_ptr, object_type *o_ptr, s32b *price)
-{
-    haggle_ptr->o_ptr = o_ptr;
-    haggle_ptr->price = price;
-    haggle_ptr->cur_ask = price_item(player_ptr, o_ptr, ot_ptr->max_inflate, FALSE);
-    haggle_ptr->final_ask = price_item(player_ptr, o_ptr, ot_ptr->min_inflate, FALSE);
-    haggle_ptr->noneed = noneedtobargain(haggle_ptr->final_ask);
-    haggle_ptr->final = FALSE;
-    haggle_ptr->pmt = _("提示価格", "Asking");
-    return haggle_ptr;
-}
-
-static void settle_haggle_result(haggle_type *haggle_ptr)
-{
-    if (!haggle_ptr->noneed && manual_haggle)
-        return;
-
-    if (haggle_ptr->noneed) {
-        msg_print(_("結局この金額にまとまった。", "You eventually agree upon the price."));
-        msg_print(NULL);
-    } else {
-        msg_print(_("すんなりとこの金額にまとまった。", "You quickly agree upon the price."));
-        msg_print(NULL);
-        haggle_ptr->final_ask += haggle_ptr->final_ask / 10;
-    }
-
-    haggle_ptr->cur_ask = haggle_ptr->final_ask;
-    haggle_ptr->pmt = _("最終提示価格", "Final Offer");
-    haggle_ptr->final = TRUE;
-}
-
-static void decide_haggle_offer(player_type *player_ptr, haggle_type *haggle_ptr)
-{
-    haggle_ptr->cur_ask *= haggle_ptr->o_ptr->number;
-    haggle_ptr->final_ask *= haggle_ptr->o_ptr->number;
-    haggle_ptr->min_per = ot_ptr->haggle_per;
-    haggle_ptr->max_per = haggle_ptr->min_per * 3;
-    haggle_ptr->last_offer = object_value(player_ptr, haggle_ptr->o_ptr) * haggle_ptr->o_ptr->number;
-    haggle_ptr->last_offer = haggle_ptr->last_offer * (200 - (int)(ot_ptr->max_inflate)) / 100L;
-    if (haggle_ptr->last_offer <= 0)
-        haggle_ptr->last_offer = 1;
-}
-
-static void initialize_haggle_offer(haggle_type *haggle_ptr)
-{
-    haggle_ptr->offer = 0;
-    allow_inc = FALSE;
-    haggle_ptr->flag = FALSE;
-    haggle_ptr->annoyed = 0;
-    haggle_ptr->cancel = FALSE;
-    *haggle_ptr->price = 0;
-}
-
-static void suggest_haggle_offer(haggle_type *haggle_ptr)
-{
-    bool loop_flag = TRUE;
-    while (!haggle_ptr->flag && loop_flag) {
-        char out_val[160];
-        (void)sprintf(out_val, "%s :  %ld", haggle_ptr->pmt, (long)haggle_ptr->cur_ask);
-        put_str(out_val, 1, 0);
-        haggle_ptr->cancel
-            = receive_offer(_("提示する金額? ", "What do you offer? "), &haggle_ptr->offer, haggle_ptr->last_offer, 1, haggle_ptr->cur_ask, haggle_ptr->final);
-        if (haggle_ptr->cancel) {
-            haggle_ptr->flag = TRUE;
-        } else if (haggle_ptr->offer > haggle_ptr->cur_ask) {
-            say_comment_6();
-            haggle_ptr->offer = haggle_ptr->last_offer;
-        } else if (haggle_ptr->offer == haggle_ptr->cur_ask) {
-            haggle_ptr->flag = TRUE;
-            *haggle_ptr->price = haggle_ptr->offer;
-        } else {
-            loop_flag = FALSE;
-        }
-    }
-}
-
-static void final_haggle_offer(haggle_type *haggle_ptr)
-{
-    haggle_ptr->final = TRUE;
-    haggle_ptr->cur_ask = haggle_ptr->final_ask;
-    haggle_ptr->pmt = _("最終提示価格", "What do you offer? ");
-    haggle_ptr->annoyed++;
-    if (haggle_ptr->annoyed <= 3)
-        return;
-
-    (void)increase_insults();
-    haggle_ptr->cancel = TRUE;
-    haggle_ptr->flag = TRUE;
-}
-
-static void show_last_haggle_offer(haggle_type *haggle_ptr)
-{
-    haggle_ptr->last_offer = haggle_ptr->offer;
-    allow_inc = TRUE;
-    prt("", 1, 0);
-    char out_val[160];
-    (void)sprintf(out_val, _("前回の提示金額: $%ld", "Your last offer: %ld"), (long)haggle_ptr->last_offer);
-    put_str(out_val, 1, 39);
-    say_comment_2(haggle_ptr->cur_ask, haggle_ptr->annoyed);
-}
+#include <optional>
 
 /*!
  * @brief プレイヤーが購入する時の値切り処理メインルーチン /
@@ -159,106 +41,88 @@ static void show_last_haggle_offer(haggle_type *haggle_ptr)
  * @return プレイヤーの価格に対して店主が不服ならばTRUEを返す /
  * Return TRUE if purchase is NOT successful
  */
-static bool purchase_haggle(player_type *player_ptr, object_type *o_ptr, s32b *price)
+static std::optional<PRICE> prompt_to_buy(player_type *player_ptr, object_type *o_ptr)
 {
-    haggle_type tmp_haggle;
-    haggle_type *haggle_ptr = initialize_haggle_type(player_ptr, &tmp_haggle, o_ptr, price);
-    settle_haggle_result(haggle_ptr);
-    decide_haggle_offer(player_ptr, haggle_ptr);
-    initialize_haggle_offer(haggle_ptr);
-    while (!haggle_ptr->flag) {
-        suggest_haggle_offer(haggle_ptr);
-        if (haggle_ptr->flag)
-            continue;
-
-        s32b x1 = 100 * (haggle_ptr->offer - haggle_ptr->last_offer) / (haggle_ptr->cur_ask - haggle_ptr->last_offer);
-        if (x1 < haggle_ptr->min_per) {
-            if (haggle_insults()) {
-                haggle_ptr->flag = TRUE;
-                haggle_ptr->cancel = TRUE;
-            }
-        } else if (x1 > haggle_ptr->max_per) {
-            x1 = x1 * 3 / 4;
-            if (x1 < haggle_ptr->max_per)
-                x1 = haggle_ptr->max_per;
-        }
+    auto price_ask = price_item(player_ptr, o_ptr, ot_ptr->inflate, FALSE);
+    auto is_low_price = price_ask < LOW_PRICE_THRESHOLD;
 
-        s32b x2 = rand_range(x1 - 2, x1 + 2);
-        s32b x3 = ((haggle_ptr->cur_ask - haggle_ptr->offer) * x2 / 100L) + 1;
-        if (x3 < 0)
-            x3 = 0;
-        haggle_ptr->cur_ask -= x3;
-
-        if (haggle_ptr->cur_ask < haggle_ptr->final_ask)
-            final_haggle_offer(haggle_ptr);
-        else if (haggle_ptr->offer >= haggle_ptr->cur_ask) {
-            haggle_ptr->flag = TRUE;
-            *haggle_ptr->price = haggle_ptr->offer;
-        }
+    if (!is_low_price)
+        price_ask += price_ask / 10;
 
-        if (haggle_ptr->flag)
-            continue;
+    msg_print(_("すんなりとこの金額にまとまった。", "You quickly agree upon the price."));
+    msg_print(NULL);
 
-        show_last_haggle_offer(haggle_ptr);
+    price_ask *= o_ptr->number;
+    concptr s = format(_("買値 $%ld で買いますか?", "Do you buy for $%ld?"), static_cast<long>(price_ask));
+    if (get_check_strict(player_ptr, s, CHECK_DEFAULT_Y)) {
+        return price_ask;
     }
 
-    if (haggle_ptr->cancel)
-        return TRUE;
-
-    updatebargain(*price, haggle_ptr->final_ask, o_ptr->number);
-    return FALSE;
+    return std::nullopt;
 }
 
+    /*!
+ * @brief 店舗から購入する際のアイテム選択プロンプト
+ * @param item 店舗インベントリ番号(アドレス渡し)
+ * @param i 店舗インベントリストック数
+ * @return 選択したらtrue、しなかったらfalse
+ * @details
+ * 選択したインベントリ番号はitemに返る。
+ * ブラックマーケットの時は別のメッセージ。
+ */
 static bool show_store_select_item(COMMAND_CODE *item, const int i)
 {
     char out_val[160];
-#ifdef JP
-    /* ブラックマーケットの時は別のメッセージ */
+
     switch (cur_store_num) {
-    case 7:
-        sprintf(out_val, "どのアイテムを取りますか? ");
+    case STORE_HOME:
+        sprintf(out_val, _("どのアイテムを取りますか? ", "Which item do you want to take? "));
         break;
-    case 6:
-        sprintf(out_val, "どれ? ");
+    case STORE_BLACK:
+        sprintf(out_val, _("どれ? ", "Which item, huh? "));
         break;
     default:
-        sprintf(out_val, "どの品物が欲しいんだい? ");
+        sprintf(out_val, _("どの品物が欲しいんだい? ", "Which item are you interested in? "));
         break;
     }
-#else
-    if (cur_store_num == STORE_HOME) {
-        sprintf(out_val, "Which item do you want to take? ");
-    } else {
-        sprintf(out_val, "Which item are you interested in? ");
-    }
-#endif
 
     return get_stock(item, out_val, 0, i - 1) != 0;
 }
 
-static bool process_purchase_result(player_type *player_ptr, object_type *o_ptr, object_type *j_ptr, COMMAND_CODE *item_new,const int amt, int *i, const COMMAND_CODE item)
+/*!
+ * @brief 家のアイテムを取得する
+ * @param player_ptr プレイヤー情報の参照ポインタ
+ * @param o_ptr 取得元オブジェクト
+ * @param j_ptr 取得先オブジェクト(指定数量分)
+ * @param item_new 取得先インベントリ番号(アドレス渡し)
+ * @param amt 数量
+ * @param i お店のストック数(アドレス渡し)
+ * @param 取得元インベントリ番号
+ * @return なし
+ */
+static void take_item_from_home(player_type *player_ptr, object_type *o_ptr, object_type *j_ptr, const COMMAND_CODE item)
 {
-    if (cur_store_num != STORE_HOME)
-        return FALSE;
-
-    bool combined_or_reordered;
+    const int amt = j_ptr->number;
     distribute_charges(o_ptr, j_ptr, amt);
-    *item_new = store_item_to_inventory(player_ptr, j_ptr);
+
     GAME_TEXT o_name[MAX_NLEN];
-    describe_flavor(player_ptr, o_name, &player_ptr->inventory_list[*item_new], 0);
+    auto item_new = store_item_to_inventory(player_ptr, j_ptr);
+    describe_flavor(player_ptr, o_name, &player_ptr->inventory_list[item_new], 0);
     handle_stuff(player_ptr);
-    msg_format(_("%s(%c)を取った。", "You have %s (%c)."), o_name, index_to_label(*item_new));
-    *i = st_ptr->stock_num;
+    msg_format(_("%s(%c)を取った。", "You have %s (%c)."), o_name, index_to_label(item_new));
+
+    auto i = st_ptr->stock_num;
     store_item_increase(item, -amt);
     store_item_optimize(item);
-    combined_or_reordered = combine_and_reorder_home(player_ptr, STORE_HOME);
-    if (*i == st_ptr->stock_num) {
+
+    auto combined_or_reordered = combine_and_reorder_home(player_ptr, STORE_HOME);
+
+    if (i == st_ptr->stock_num) {
         if (combined_or_reordered)
             display_store_inventory(player_ptr);
         else
             display_entry(player_ptr, item);
-
-        return TRUE;
+        return;
     }
 
     if (st_ptr->stock_num == 0)
@@ -268,7 +132,6 @@ static bool process_purchase_result(player_type *player_ptr, object_type *o_ptr,
 
     display_store_inventory(player_ptr);
     chg_virtue(player_ptr, V_SACRIFICE, 1);
-    return TRUE;
 }
 
 static void shuffle_store(player_type *player_ptr)
@@ -298,7 +161,7 @@ static void switch_store_stock(player_type *player_ptr, const int i, const COMMA
         display_store_inventory(player_ptr);
         return;
     }
-    
+
     if (st_ptr->stock_num != i) {
         if (store_top >= st_ptr->stock_num)
             store_top -= store_bottom;
@@ -342,10 +205,10 @@ void store_purchase(player_type *player_ptr)
     item = item + store_top;
     object_type *o_ptr;
     o_ptr = &st_ptr->stock[item];
+
     ITEM_NUMBER amt = 1;
     object_type forge;
-    object_type *j_ptr;
-    j_ptr = &forge;
+    object_type *j_ptr = &forge;
     object_copy(j_ptr, o_ptr);
 
     /*
@@ -359,7 +222,7 @@ void store_purchase(player_type *player_ptr)
         return;
     }
 
-    PRICE best = price_item(player_ptr, j_ptr, ot_ptr->min_inflate, FALSE);
+    PRICE best = price_item(player_ptr, j_ptr, ot_ptr->inflate, FALSE);
     if (o_ptr->number > 1) {
         if ((cur_store_num != STORE_HOME) && (o_ptr->ident & IDENT_FIXED)) {
             msg_format(_("一つにつき $%ldです。", "That costs %ld gold per item."), (long)(best));
@@ -384,27 +247,29 @@ void store_purchase(player_type *player_ptr)
         return;
     }
 
-    COMMAND_CODE item_new;
-    if (process_purchase_result(player_ptr, o_ptr, j_ptr, &item_new, amt, &i, item))
+    if (cur_store_num == STORE_HOME) {
+        take_item_from_home(player_ptr, o_ptr, j_ptr, item);
         return;
+    }
 
-    int choice;
+    COMMAND_CODE item_new;
     PRICE price;
     if (o_ptr->ident & (IDENT_FIXED)) {
-        choice = 0;
         price = (best * j_ptr->number);
     } else {
         GAME_TEXT o_name[MAX_NLEN];
         describe_flavor(player_ptr, o_name, j_ptr, 0);
         msg_format(_("%s(%c)を購入する。", "Buying %s (%c)."), o_name, I2A(item));
         msg_print(NULL);
-        choice = purchase_haggle(player_ptr, j_ptr, &price);
+
+        auto res = prompt_to_buy(player_ptr, j_ptr);
         if (st_ptr->store_open >= current_world_ptr->game_turn)
             return;
-    }
+        if (!res)
+            return;
 
-    if (choice != 0)
-        return;
+        price = res.value();
+    }
 
     if (price == (best * j_ptr->number))
         o_ptr->ident |= (IDENT_FIXED);
@@ -414,21 +279,20 @@ void store_purchase(player_type *player_ptr)
         return;
     }
 
-    say_comment_1(player_ptr);
+    store_owner_says_comment(player_ptr);
     if (cur_store_num == STORE_BLACK)
         chg_virtue(player_ptr, V_JUSTICE, -1);
     if ((o_ptr->tval == TV_BOTTLE) && (cur_store_num != STORE_HOME))
         chg_virtue(player_ptr, V_NATURE, -1);
 
     sound(SOUND_BUY);
-    decrease_insults();
     player_ptr->au -= price;
     store_prt_gold(player_ptr);
     object_aware(player_ptr, j_ptr);
     j_ptr->ident &= ~(IDENT_FIXED);
+
     GAME_TEXT o_name[MAX_NLEN];
     describe_flavor(player_ptr, o_name, j_ptr, 0);
-
     msg_format(_("%sを $%ldで購入しました。", "You bought %s for %ld gold."), o_name, (long)price);
 
     strcpy(record_o_name, o_name);
@@ -436,6 +300,7 @@ void store_purchase(player_type *player_ptr)
 
     if (record_buy)
         exe_write_diary(player_ptr, DIARY_BUY, 0, o_name);
+
     describe_flavor(player_ptr, o_name, o_ptr, OD_NAME_ONLY);
     if (record_rand_art && o_ptr->art_name)
         exe_write_diary(player_ptr, DIARY_ART, 0, o_name);
index 0adca12..cb4402b 100644 (file)
  * @param player_ptr プレーヤーへの参照ポインタ
  * @return なし
  */
-void say_comment_1(player_type *player_ptr)
+void store_owner_says_comment(player_type *player_ptr)
 {
-#ifdef JP
        if (cur_store_num == STORE_BLACK)
-       {
                msg_print(comment_1_B[randint0(MAX_COMMENT_1)]);
-       }
        else
-       {
                msg_print(comment_1[randint0(MAX_COMMENT_1)]);
-       }
-#else
-       msg_print(comment_1[randint0(MAX_COMMENT_1)]);
-#endif
 
        if (one_in_(RUMOR_CHANCE))
        {
@@ -38,135 +30,6 @@ void say_comment_1(player_type *player_ptr)
        }
 }
 
-
-/*!
- * @brief プレイヤーがアイテムを買う時の価格代案メッセージ処理 /
- * Continue haggling (player is buying)
- * @param value 店主の提示価格
- * @param annoyed 店主のいらつき度
- * @return なし
- */
-void say_comment_2(PRICE value, int annoyed)
-{
-       char tmp_val[80];
-       sprintf(tmp_val, "%ld", (long)value);
-
-       if (annoyed > 0)
-       {
-               msg_format(comment_2a[randint0(MAX_COMMENT_2A)], tmp_val);
-               return;
-       }
-
-#ifdef JP
-       if (cur_store_num == STORE_BLACK)
-       {
-               msg_format(comment_2b_B[randint0(MAX_COMMENT_2B)], tmp_val);
-       }
-       else
-       {
-               msg_format(comment_2b[randint0(MAX_COMMENT_2B)], tmp_val);
-       }
-#else
-       msg_format(comment_2b[randint0(MAX_COMMENT_2B)], tmp_val);
-#endif
-}
-
-
-/*!
- * @brief プレイヤーがアイテムを売る時の価格代案メッセージ処理 /
- * ブラックマーケットのときは別のメッセージを出す
- * Continue haggling (player is selling)
- * @param value 店主の提示価格
- * @param annoyed 店主のいらつき度
- * @return なし
- */
-void say_comment_3(PRICE value, int annoyed)
-{
-       char tmp_val[80];
-       sprintf(tmp_val, "%ld", (long)value);
-       if (annoyed > 0)
-       {
-               msg_format(comment_3a[randint0(MAX_COMMENT_3A)], tmp_val);
-       }
-       else
-       {
-#ifdef JP
-               if (cur_store_num == STORE_BLACK)
-               {
-                       msg_format(comment_3b_B[randint0(MAX_COMMENT_3B)], tmp_val);
-               }
-               else
-               {
-                       msg_format(comment_3b[randint0(MAX_COMMENT_3B)], tmp_val);
-               }
-#else
-               msg_format(comment_3b[randint0(MAX_COMMENT_3B)], tmp_val);
-#endif
-       }
-}
-
-
-/*!
- * @brief 店主がプレイヤーを追い出す時のメッセージ処理 /
- * ブラックマーケットの時は別のメッセージを出す
- * Kick 'da bum out.                                   -RAK-
- * @return なし
- */
-void say_comment_4(void)
-{
-#ifdef JP
-       if (cur_store_num == STORE_BLACK)
-       {
-               msg_print(comment_4a_B[randint0(MAX_COMMENT_4A)]);
-               msg_print(comment_4b_B[randint0(MAX_COMMENT_4B)]);
-       }
-       else
-       {
-               msg_print(comment_4a[randint0(MAX_COMMENT_4A)]);
-               msg_print(comment_4b[randint0(MAX_COMMENT_4B)]);
-       }
-#else
-       msg_print(comment_4a[randint0(MAX_COMMENT_4A)]);
-       msg_print(comment_4b[randint0(MAX_COMMENT_4B)]);
-#endif
-
-}
-
-
-/*!
- * @brief 店主がプレイヤーに取り合わない時のメッセージ処理 /
- * ブラックマーケットの時は別のメッセージを出す
- * You are insulting me
- * @return なし
- */
-void say_comment_5(void)
-{
-#ifdef JP
-       if (cur_store_num == STORE_BLACK)
-       {
-               msg_print(comment_5_B[randint0(MAX_COMMENT_5)]);
-       }
-       else
-       {
-               msg_print(comment_5[randint0(MAX_COMMENT_5)]);
-       }
-#else
-       msg_print(comment_5[randint0(MAX_COMMENT_5)]);
-#endif
-
-}
-
-
-/*!
- * @brief 店主がプレイヤーの提示を理解できなかった時のメッセージ処理 /
- * That makes no sense.
- * @return なし
- */
-void say_comment_6(void)
-{
-       msg_print(comment_6[randint0(MAX_COMMENT_6)]);
-}
-
 /*!
  * @brief 店主が交渉を終えた際の反応を返す処理 /
  * Let a shop-keeper React to a purchase
index 60e84e4..bf2bf2f 100644 (file)
@@ -2,10 +2,5 @@
 
 #include "system/angband.h"
 
-void say_comment_1(player_type *player_ptr);
-void say_comment_2(PRICE value, int annoyed);
-void say_comment_3(PRICE value, int annoyed);
-void say_comment_4(void);
-void say_comment_5(void);
-void say_comment_6(void);
+void store_owner_says_comment(player_type *player_ptr);
 void purchase_analyze(player_type *player_ptr, PRICE price, PRICE value, PRICE guess);
index c94d73d..8960ca4 100644 (file)
@@ -28,7 +28,6 @@
 #include "racial/racial-android.h"
 #include "spell-kind/spells-perception.h"
 #include "store/home.h"
-#include "store/owner-insults.h"
 #include "store/pricing.h"
 #include "store/say-comments.h"
 #include "store/service-checker.h"
 #include "store/store.h"
 #include "system/object-type-definition.h"
 #include "term/screen-processor.h"
+#include "util/bit-flags-calculator.h"
 #include "view/display-messages.h"
 #include "view/display-store.h"
 #include "view/object-describer.h"
-#include "util/bit-flags-calculator.h"
 #include "world/world.h"
+#include <optional>
 
 /*!
- * @brief プレイヤーが売却する時の値切り処理メインルーチン /
- * Haggling routine                            -RAK-
+ * @brief プレイヤーが売却する時の確認プロンプト / Prompt to sell for the price
  * @param player_ptr プレーヤーへの参照ポインタ
  * @param o_ptr オブジェクトの構造体参照ポインタ
- * @param price 最終価格を返す参照ポインタ
- * @return プレイヤーの価格に対して店主が不服ならばTRUEを返す /
- * Return TRUE if purchase is NOT successful
+ * @return 売るなら(true,売値)、売らないなら(false,0)のタプル
  */
-static bool sell_haggle(player_type *player_ptr, object_type *o_ptr, s32b *price)
+static std::optional<PRICE> prompt_to_sell(player_type *player_ptr, object_type *o_ptr)
 {
-    s32b cur_ask = price_item(player_ptr, o_ptr, ot_ptr->max_inflate, TRUE);
-    s32b final_ask = price_item(player_ptr, o_ptr, ot_ptr->min_inflate, TRUE);
-    int noneed = noneedtobargain(final_ask);
-    s32b purse = (s32b)(ot_ptr->max_cost);
-    bool final = FALSE;
-    concptr pmt = _("提示金額", "Offer");
-    if (noneed || !manual_haggle || (final_ask >= purse)) {
-        if (!manual_haggle && !noneed) {
-            final_ask -= final_ask / 10;
-        }
+    auto price_ask = price_item(player_ptr, o_ptr, ot_ptr->inflate, TRUE);
+    auto is_low_price = price_ask < LOW_PRICE_THRESHOLD;
 
-        if (final_ask >= purse) {
-            msg_print(_("即座にこの金額にまとまった。", "You instantly agree upon the price."));
-            msg_print(NULL);
-            final_ask = purse;
-        } else if (noneed) {
-            msg_print(_("結局この金額にまとまった。", "You eventually agree upon the price."));
-            msg_print(NULL);
-        } else {
-            msg_print(_("すんなりとこの金額にまとまった。", "You quickly agree upon the price."));
-            msg_print(NULL);
-        }
+    if (!is_low_price)
+        price_ask -= price_ask / 10;
 
-        cur_ask = final_ask;
-        final = TRUE;
-        pmt = _("最終提示金額", "Final Offer");
-    }
-
-    cur_ask *= o_ptr->number;
-    final_ask *= o_ptr->number;
-
-    s32b min_per = ot_ptr->haggle_per;
-    s32b max_per = min_per * 3;
-    s32b last_offer = object_value(player_ptr, o_ptr) * o_ptr->number;
-    last_offer = last_offer * ot_ptr->max_inflate / 100L;
-    s32b offer = 0;
-    allow_inc = FALSE;
-    bool flag = FALSE;
-    bool loop_flag;
-    int annoyed = 0;
-    bool cancel = FALSE;
-    *price = 0;
-    while (!flag) {
-        while (TRUE) {
-            loop_flag = TRUE;
-
-            char out_val[160];
-            (void)sprintf(out_val, "%s :  %ld", pmt, (long)cur_ask);
-            put_str(out_val, 1, 0);
-            cancel = receive_offer(_("提示する価格? ", "What price do you ask? "), &offer, last_offer, -1, cur_ask, final);
-
-            if (cancel) {
-                flag = TRUE;
-            } else if (offer < cur_ask) {
-                say_comment_6();
-                offer = last_offer;
-            } else if (offer == cur_ask) {
-                flag = TRUE;
-                *price = offer;
-            } else {
-                loop_flag = FALSE;
-            }
-
-            if (flag || !loop_flag)
-                break;
-        }
+    auto max_price = (PRICE)ot_ptr->max_cost;
 
-        if (flag)
-            continue;
-
-        s32b x1 = 100 * (last_offer - offer) / (last_offer - cur_ask);
-        if (x1 < min_per) {
-            if (haggle_insults()) {
-                flag = TRUE;
-                cancel = TRUE;
-            }
-        } else if (x1 > max_per) {
-            x1 = x1 * 3 / 4;
-            if (x1 < max_per)
-                x1 = max_per;
-        }
-
-        s32b x2 = rand_range(x1 - 2, x1 + 2);
-        s32b x3 = ((offer - cur_ask) * x2 / 100L) + 1;
-        if (x3 < 0)
-            x3 = 0;
-        cur_ask += x3;
-
-        if (cur_ask > final_ask) {
-            cur_ask = final_ask;
-            final = TRUE;
-            pmt = _("最終提示金額", "Final Offer");
-
-            annoyed++;
-            if (annoyed > 3) {
-                flag = TRUE;
-#ifdef JP
-                /* 追加 $0 で買い取られてしまうのを防止 By FIRST*/
-                cancel = TRUE;
-#endif
-                (void)(increase_insults());
-            }
-        } else if (offer <= cur_ask) {
-            flag = TRUE;
-            *price = offer;
-        }
-
-        last_offer = offer;
-        allow_inc = TRUE;
-        prt("", 1, 0);
-        char out_val[160];
-        (void)sprintf(out_val, _("前回の提示価格 $%ld", "Your last bid %ld"), (long)last_offer);
-        put_str(out_val, 1, 39);
-        say_comment_3(cur_ask, annoyed);
+    if (price_ask > max_price) {
+        msg_print(_("即座にこの金額にまとまった。", "You instantly agree upon the price."));
+        msg_print(NULL);
+        price_ask = max_price;
+    } else {
+        msg_print(_("すんなりとこの金額にまとまった。", "You quickly agree upon the price."));
+        msg_print(NULL);
     }
 
-    if (cancel)
-        return TRUE;
+    price_ask *= o_ptr->number;
+    concptr s = format(_("売値 $%ld で売りますか?", "Do you sell for $%ld?"), static_cast<long>(price_ask));
+    if (get_check_strict(player_ptr, s, CHECK_DEFAULT_Y)) {
+        return price_ask;
+    }
 
-    updatebargain(*price, final_ask, o_ptr->number);
-    return FALSE;
+    return std::nullopt;
 }
 
 /*!
@@ -184,29 +84,32 @@ static bool sell_haggle(player_type *player_ptr, object_type *o_ptr, s32b *price
  */
 void store_sell(player_type *owner_ptr)
 {
-    concptr q;
-    if (cur_store_num == STORE_HOME)
+    concptr q; //!< @note プロンプトメッセージ
+    concptr s_none; //!< @note 売る/置くものがない場合のメッセージ
+    concptr s_full; //!< @note もう置けない場合のメッセージ
+    switch (cur_store_num) {
+    case STORE_HOME:
         q = _("どのアイテムを置きますか? ", "Drop which item? ");
-    else if (cur_store_num == STORE_MUSEUM)
+        s_none = _("置けるアイテムを持っていません。", "You don't have any items to drop.");
+        s_full = _("我が家にはもう置く場所がない。", "Your home is full.");
+        break;
+    case STORE_MUSEUM:
         q = _("どのアイテムを寄贈しますか? ", "Give which item? ");
-    else
+        s_none = _("寄贈できるアイテムを持っていません。", "You don't have any items to give.");
+        s_full = _("博物館はもう満杯だ。", "The Museum is full.");
+        break;
+    default:
         q = _("どのアイテムを売りますか? ", "Sell which item? ");
+        s_none = _("欲しい物がないですねえ。", "You have nothing that I want.");
+        s_full = _("すいませんが、店にはもう置く場所がありません。", "I have not the room in my store to keep it.");
+        break;
+    }
 
     item_tester_hook = store_will_buy;
 
-    /* 我が家でおかしなメッセージが出るオリジナルのバグを修正 */
-    concptr s;
-    if (cur_store_num == STORE_HOME) {
-        s = _("置けるアイテムを持っていません。", "You don't have any items to drop.");
-    } else if (cur_store_num == STORE_MUSEUM) {
-        s = _("寄贈できるアイテムを持っていません。", "You don't have any items to give.");
-    } else {
-        s = _("欲しい物がないですねえ。", "You have nothing that I want.");
-    }
-
     OBJECT_IDX item;
     object_type *o_ptr;
-    o_ptr = choose_object(owner_ptr, &item, q, s, USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT, TV_NONE);
+    o_ptr = choose_object(owner_ptr, &item, q, s_none, USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT, TV_NONE);
     if (!o_ptr)
         return;
 
@@ -223,10 +126,10 @@ void store_sell(player_type *owner_ptr)
     }
 
     object_type forge;
-    object_type *q_ptr;
-    q_ptr = &forge;
+    object_type *q_ptr = &forge;
     object_copy(q_ptr, o_ptr);
     q_ptr->number = amt;
+
     if ((o_ptr->tval == TV_ROD) || (o_ptr->tval == TV_WAND))
         q_ptr->pval = o_ptr->pval * amt / o_ptr->number;
 
@@ -238,53 +141,44 @@ void store_sell(player_type *owner_ptr)
     }
 
     if (!store_check_num(q_ptr)) {
-        if (cur_store_num == STORE_HOME)
-            msg_print(_("我が家にはもう置く場所がない。", "Your home is full."));
-
-        else if (cur_store_num == STORE_MUSEUM)
-            msg_print(_("博物館はもう満杯だ。", "The Museum is full."));
-
-        else
-            msg_print(_("すいませんが、店にはもう置く場所がありません。", "I have not the room in my store to keep it."));
-
+        msg_print(s_full);
         return;
     }
 
-    int choice;
-    PRICE price, value, dummy;
+    bool placed = false;
     if ((cur_store_num != STORE_HOME) && (cur_store_num != STORE_MUSEUM)) {
         msg_format(_("%s(%c)を売却する。", "Selling %s (%c)."), o_name, index_to_label(item));
         msg_print(NULL);
 
-        choice = sell_haggle(owner_ptr, q_ptr, &price);
-        if (st_ptr->store_open >= current_world_ptr->game_turn)
-            return;
+        auto res = prompt_to_sell(owner_ptr, q_ptr);
+        placed = res.has_value();
+        if (placed) {
+            PRICE price = res.value();
+            store_owner_says_comment(owner_ptr);
 
-        if (choice == 0) {
-            say_comment_1(owner_ptr);
             sound(SOUND_SELL);
             if (cur_store_num == STORE_BLACK)
                 chg_virtue(owner_ptr, V_JUSTICE, -1);
 
             if ((o_ptr->tval == TV_BOTTLE) && (cur_store_num != STORE_HOME))
                 chg_virtue(owner_ptr, V_NATURE, 1);
-            decrease_insults();
 
             owner_ptr->au += price;
             store_prt_gold(owner_ptr);
-            dummy = object_value(owner_ptr, q_ptr) * q_ptr->number;
+            PRICE dummy = object_value(owner_ptr, q_ptr) * q_ptr->number;
 
             identify_item(owner_ptr, o_ptr);
             q_ptr = &forge;
             object_copy(q_ptr, o_ptr);
             q_ptr->number = amt;
             q_ptr->ident |= IDENT_STORE;
+
             if ((o_ptr->tval == TV_ROD) || (o_ptr->tval == TV_WAND))
                 q_ptr->pval = o_ptr->pval * amt / o_ptr->number;
 
-            value = object_value(owner_ptr, q_ptr) * q_ptr->number;
+            PRICE value = object_value(owner_ptr, q_ptr) * q_ptr->number;
             describe_flavor(owner_ptr, o_name, q_ptr, 0);
-            msg_format(_("%sを $%ldで売却しました。", "You sold %s for %ld gold."), o_name, (long)price);
+            msg_format(_("%sを $%ldで売却しました。", "You sold %s for %ld gold."), o_name, static_cast<long>(price));
 
             if (record_sell)
                 exe_write_diary(owner_ptr, DIARY_SELL, 0, o_name);
@@ -314,7 +208,7 @@ void store_sell(player_type *owner_ptr)
             msg_print(_("それと同じ品物は既に博物館にあるようです。", "The Museum already has one of those items."));
         else
             msg_print(_("博物館に寄贈したものは取り出すことができません!!", "You cannot take back items which have been donated to the Museum!!"));
-        
+
         if (!get_check(format(_("本当に%sを寄贈しますか?", "Really give %s to the Museum? "), o2_name)))
             return;
 
@@ -323,7 +217,7 @@ void store_sell(player_type *owner_ptr)
 
         distribute_charges(o_ptr, q_ptr, amt);
         msg_format(_("%sを置いた。(%c)", "You drop %s (%c)."), o_name, index_to_label(item));
-        choice = 0;
+        placed = true;
 
         vary_item(owner_ptr, item, -amt);
 
@@ -335,7 +229,7 @@ void store_sell(player_type *owner_ptr)
     } else {
         distribute_charges(o_ptr, q_ptr, amt);
         msg_format(_("%sを置いた。(%c)", "You drop %s (%c)."), o_name, index_to_label(item));
-        choice = 0;
+        placed = true;
         vary_item(owner_ptr, item, -amt);
         int item_pos = home_carry(owner_ptr, q_ptr);
         if (item_pos >= 0) {
@@ -348,7 +242,7 @@ void store_sell(player_type *owner_ptr)
     set_bits(owner_ptr->window_flags, PW_PLAYER);
     handle_stuff(owner_ptr);
 
-    if ((choice == 0) && (item >= INVEN_MAIN_HAND)) {
+    if (placed && (item >= INVEN_MAIN_HAND)) {
         calc_android_exp(owner_ptr);
         verify_equip_slot(owner_ptr, item);
     }
similarity index 94%
rename from src/io/store-key-processor.cpp
rename to src/store/store-key-processor.cpp
index 265bab2..0151d1f 100644 (file)
@@ -1,4 +1,4 @@
-#include "io/store-key-processor.h"
+#include "store/store-key-processor.h"
 #include "autopick/autopick-pref-processor.h"
 #include "cmd-action/cmd-mind.h"
 #include "cmd-action/cmd-spell.h"
@@ -85,18 +85,14 @@ void store_process_command(player_type *client_ptr)
             msg_print(_("これで全部です。", "Entire inventory is shown."));
         } else {
             store_top += store_bottom;
+
             /*
              * 隠しオプション(powerup_home)がセットされていないときは
              * 我が家では 2 ページまでしか表示しない
              */
-            if ((cur_store_num == STORE_HOME) && (powerup_home == FALSE) && (st_ptr->stock_num >= STORE_INVEN_MAX)) {
-                if (store_top >= (STORE_INVEN_MAX - 1)) {
-                    store_top = 0;
-                }
-            } else {
-                if (store_top >= st_ptr->stock_num)
-                    store_top = 0;
-            }
+            auto inven_max = store_get_stock_max(STORE_HOME, powerup_home);
+            if (store_top >= st_ptr->stock_num || store_top >= inven_max)
+                store_top = 0;
 
             display_store_inventory(client_ptr);
         }
index ef96495..113a634 100644 (file)
 #include "store/store-owner-comments.h"
 
-/*!
- * @todo _() でまとめる
- */
 concptr comment_1[MAX_COMMENT_1] =
 {
-#ifdef JP
-       "オーケーだ。",
-       "結構だ。",
-       "そうしよう!",
-       "賛成だ!",
-       "よし!",
-       "わかった!"
-#else
-       "Okay.",
-       "Fine.",
-       "Accepted!",
-       "Agreed!",
-       "Done!",
-       "Taken!"
-#endif
+       _("オーケーだ。", "Okay."),
+    _("結構だ。", "Fine."),
+       _("そうしよう!", "Accepted!"),
+       _("賛成だ!", "Agreed!"),
+       _("よし!", "Done!"),
+       _("わかった!", "Taken!")
 };
 
-#ifdef JP
 /*! ブラックマーケット追加メッセージ(承諾) */
 concptr comment_1_B[MAX_COMMENT_1] = {
-       "まあ、それでいいや。",
-       "今日はそれで勘弁してやる。",
-       "分かったよ。",
-       "しょうがない。",
-       "それで我慢するよ。",
-       "こんなもんだろう。"
-};
-#endif
-
-concptr comment_2a[MAX_COMMENT_2A] =
-{
-#ifdef JP
-       "私の忍耐力を試しているのかい? $%s が最後だ。",
-       "我慢にも限度があるぞ。 $%s が最後だ。"
-#else
-       "You try my patience.  %s is final.",
-       "My patience grows thin.  %s is final."
-#endif
-};
-
-concptr comment_2b[MAX_COMMENT_2B] =
-{
-#ifdef JP
-       " $%s ぐらいは出さなきゃダメだよ。",
-       " $%s なら受け取ってもいいが。",
-       "ハ! $%s 以下はないね。",
-       "何て奴だ! $%s 以下はあり得ないぞ。",
-       "それじゃ少なすぎる! $%s は欲しいところだ。",
-       "バカにしている! $%s はもらわないと。",
-       "嘘だろう! $%s でどうだい?",
-       "おいおい! $%s を考えてくれないか?",
-       "1000匹のオークのノミに苦しめられるがいい! $%s だ。",
-       "お前の大切なものに災いあれ! $%s でどうだ。",
-       "モルゴスに賞味されるがいい!本当は $%s なんだろう?",
-       "お前の母親はオーガか! $%s は出すつもりなんだろ?"
-#else
-       "I can take no less than %s gold pieces.",
-       "I will accept no less than %s gold pieces.",
-       "Ha!  No less than %s gold pieces.",
-       "You knave!  No less than %s gold pieces.",
-       "That's a pittance!  I want %s gold pieces.",
-       "That's an insult!  I want %s gold pieces.",
-       "As if!  How about %s gold pieces?",
-       "My arse!  How about %s gold pieces?",
-       "May the fleas of 1000 orcs molest you!  Try %s gold pieces.",
-       "May your most favourite parts go moldy!  Try %s gold pieces.",
-       "May Morgoth find you tasty!  Perhaps %s gold pieces?",
-       "Your mother was an Ogre!  Perhaps %s gold pieces?"
-#endif
-};
-
-#ifdef JP
-/*! ブラックマーケット用追加メッセージ(売るとき) */
-concptr comment_2b_B[MAX_COMMENT_2B] = {
-       "いくら俺様がお人好しとはいえ $%s が限界だね。嫌なら帰りな。",
-       "金がないのかい、あんた?まずは家に帰って $%s 揃えてきな。",
-       "物の価値が分からん奴だな。これは $%s が普通なんだよ。",
-       "俺の付けた値段に文句があるのか? $%s が限界だ。",
-       "ひょっとして新手の冗談かい? $%s 持ってないなら帰りな。",
-       "うちは他の店とは違うんだよ。$%s ぐらいは出しな。",
-       "買う気がないなら帰りな。 $%s だと言っているんだ。",
-       "話にならないね。 $%s くらい持っているんだろ?",
-       "は?なんだそりゃ? $%s の間違いか、ひょっとして?",
-       "出口はあっちだよ。それとも $%s 出せるのかい、あんたに。",
-       "命知らずな奴だな。 $%s 出せば今日の所は勘弁してやるよ。",
-       "うちの店は貧乏人お断りだ。 $%s ぐらい出せないのかい?"
-};
-#endif
-
-concptr comment_3a[MAX_COMMENT_3A] =
-{
-#ifdef JP
-       "私の忍耐力を試しているのかい? $%s が最後だ。",
-       "我慢にも限度があるぞ。 $%s が最後だ。"
-#else
-       "You try my patience.  %s is final.",
-       "My patience grows thin.  %s is final."
-#endif
-};
-
-concptr comment_3b[MAX_COMMENT_3B] =
-{
-#ifdef JP
-       "本音を言うと $%s でいいんだろ?",
-       " $%s でどうだい?",
-       " $%s ぐらいなら出してもいいが。",
-       " $%s 以上払うなんて考えられないね。",
-       "まあ落ちついて。 $%s でどうだい?",
-       "そのガラクタなら $%s で引き取るよ。",
-       "それじゃ高すぎる! $%s がいいとこだろ。",
-       "どうせいらないんだろ! $%s でいいだろ?",
-       "だめだめ! $%s がずっとお似合いだよ。",
-       "バカにしている! $%s がせいぜいだ。",
-       " $%s なら嬉しいところだがなあ。",
-       " $%s 、それ以上はビタ一文出さないよ!"
-#else
-       "Perhaps %s gold pieces?",
-       "How about %s gold pieces?",
-       "I will pay no more than %s gold pieces.",
-       "I can afford no more than %s gold pieces.",
-       "Be reasonable.  How about %s gold pieces?",
-       "I'll buy it as scrap for %s gold pieces.",
-       "That is too much!  How about %s gold pieces?",
-       "That looks war surplus!  Say %s gold pieces?",
-       "Never!  %s is more like it.",
-       "That's an insult!  %s is more like it.",
-       "%s gold pieces and be thankful for it!",
-       "%s gold pieces and not a copper more!"
-#endif
-};
-
-#ifdef JP
-/*! ブラックマーケット用追加メッセージ(買い取り) */
-concptr comment_3b_B[MAX_COMMENT_3B] = {
-       " $%s ってところだね。そのどうしようもないガラクタは。",
-       "この俺が $%s って言っているんだから、その通りにした方が身のためだぞ。",
-       "俺の優しさに甘えるのもいい加減にしておけ。 $%s だ。",
-       "その品なら $%s で売ってくれているがね、常識ある紳士はみんな。",
-       "こりゃまた、がめつい奴だな。いくら俺が温厚とはいえ $%s が限界だ。",
-       " $%s だ。別に俺はそんなガラクタ欲しくはないんだから。",
-       "俺の鑑定額が気に入らないのか? $%s 、嫌なら帰りな。",
-       " $%s で引き取ってやるよ。喜んで受け取りな、貧乏人。",
-       "物の価値が分からん奴は始末におえんな。それは $%s なんだよ。",
-       "そんなに金が欲しいのか、あんた? $%s で満足できんのか?",
-       "入る店間違えてんじゃないのか? $%s で嫌なら他をあたってくれ。",
-       "俺の言い値にケチをつける奴がいるとは! その度胸に免じて $%s だ。"
-};
-#endif
-
-concptr comment_4a[MAX_COMMENT_4A] =
-{
-#ifdef JP
-       "もうたくさんだ!何度も私をわずらわせないでくれ!",
-       "うがー!一日の我慢の限度を超えている!",
-       "もういい!時間の無駄以外のなにものでもない!",
-       "もうやってられないよ!顔も見たくない!"
-#else
-       "Enough!  You have abused me once too often!",
-       "Arghhh!  I have had enough abuse for one day!",
-       "That does it!  You shall waste my time no more!",
-       "This is getting nowhere!  I'm going to Londis!"
-#endif
-};
-
-#ifdef JP
-/*! ブラックマーケット用追加メッセージ(怒りの頂点) */
-concptr comment_4a_B[MAX_COMMENT_4A] = {
-       "なめやがって!温厚な俺様でも限界があるってことを知れ!",
-       "俺をここまで怒らせて...命があるだけでもありがたいと思え!",
-       "ふざけてるのか!冷やかしなら相手を見てからにしろ!",
-       "いいかげんにしろ!今度こんなまねしたらただじゃおかねえぞ!"
-};
-#endif
-
-concptr comment_4b[MAX_COMMENT_4B] =
-{
-#ifdef JP
-       "店から出て行け!",
-       "俺の前から消え失せろ!",
-       "どっかに行っちまえ!",
-       "出ろ、出ろ、出て行け!"
-#else
-       "Leave my store!",
-       "Get out of my sight!",
-       "Begone, you scoundrel!",
-       "Out, out, out!"
-#endif
-};
-
-#ifdef JP
-/*! ブラックマーケット用追加メッセージ(追い出し) */
-concptr comment_4b_B[MAX_COMMENT_4B] = {
-       "二度とうちに来るんじゃねえ!!",
-       "とっとと、どっかへ失せろ!!",
-       "今すぐ消え失せろ!!",
-       "出ていけ!出ていけ!!"
-};
-#endif
-
-concptr comment_5[MAX_COMMENT_5] =
-{
-#ifdef JP
-       "考え直してくれ。",
-       "そりゃおかしい!",
-       "もっと真面目に言ってくれ!",
-       "交渉する気があるのかい?",
-       "冷やかしに来たのか!",
-       "悪い冗談だ!",
-       "我慢くらべかい。",
-       "ふーむ、良い天気だ。"
-#else
-       "Try again.",
-       "Ridiculous!",
-       "You will have to do better than that!",
-       "Do you wish to do business or not?",
-       "You've got to be kidding!",
-       "You'd better be kidding!",
-       "You try my patience.",
-       "Hmmm, nice weather we're having."
-#endif
-};
-
-#ifdef JP
-/*! ブラックマーケット用追加メッセージ(怒り) */
-concptr comment_5_B[MAX_COMMENT_5] = {
-       "時間の無駄だな、これは。",
-       "厄介なお客様だな!",
-       "話して分かる相手じゃなさそうだ。",
-       "痛い目にあいたいらしいな!",
-       "なんて強欲な奴だ!",
-       "話にならん輩だ!",
-       "どうしようもない貧乏人だ!",
-       "喧嘩を売っているのか?"
-};
-#endif
-
-concptr comment_6[MAX_COMMENT_6] =
-{
-#ifdef JP
-       "どうやら聞き間違えたらしい。",
-       "失礼、よく聞こえなかったよ。",
-       "すまない、何だって?",
-       "悪い、もう一度言ってくれる?"
-#else
-       "I must have heard you wrong.",
-       "I'm sorry, I missed that.",
-       "I'm sorry, what was that?",
-       "Sorry, what was that again?"
-#endif
+       _("まあ、それでいいや。", "Ah, ok."),
+       _("今日はそれで勘弁してやる。", "I forgive you today."),
+       _("分かったよ。", "I see."),
+       _("しょうがない。", "Oh well."),
+       _("それで我慢するよ。", "I endure."),
+       _("こんなもんだろう。", "Like this.")
 };
 
 concptr comment_7a[MAX_COMMENT_7A] =
 {
-#ifdef JP
-       "うわああぁぁ!",
-       "なんてこった!",
-       "誰かがむせび泣く声が聞こえる...。",
-       "店主が悔しげにわめいている!"
-#else
-       "Arrgghh!",
-       "You bastard!",
-       "You hear someone sobbing...",
-       "The shopkeeper howls in agony!"
-#endif
-
+    _("うわああぁぁ!", "Arrgghh!"),
+       _("なんてこった!", "You bastard!"),
+       _("誰かがむせび泣く声が聞こえる...。", "You hear someone sobbing..."),
+       _("店主が悔しげにわめいている!", "The shopkeeper howls in agony!"),
+       _("1000匹のオークのノミに苦しめられるがいい!", "May the fleas of 1000 orcs molest you!"),
+    _("お前の大切なものに災いあれ!", "May your most favourite parts go moldy!"),
+    _("モルゴスに賞味されるがいい!", "May Morgoth find you tasty!"),
+    _("悪い冗談だ!", "You'd better be kidding!")
 };
 
 concptr comment_7b[MAX_COMMENT_7B] =
 {
-#ifdef JP
-       "くそう!",
-       "この悪魔め!",
-       "店主が恨めしそうに見ている。",
-       "店主が睨んでいる。"
-#else
-       "Damn!",
-       "You fiend!",
-       "The shopkeeper curses at you.",
-       "The shopkeeper glares at you."
-#endif
-
+    _("くそう!", "Damn!"),
+       _("この悪魔め!", "You fiend!"),
+       _("店主が恨めしそうに見ている。", "The shopkeeper curses at you."),
+       _("店主が睨んでいる。", "The shopkeeper glares at you."),
+       _("店から出て行け!", "Leave my store!"),
+       _("俺の前から消え失せろ!", "Get out of my sight!"),
+       _("どっかに行っちまえ!", "Begone, you scoundrel!"),
+       _("出ろ、出ろ、出て行け!", "Out, out, out!")
 };
 
 concptr comment_7c[MAX_COMMENT_7C] =
 {
-#ifdef JP
-       "すばらしい!",
-       "君が天使に見えるよ!",
-       "店主がクスクス笑っている。",
-       "店主が大声で笑っている。"
-#else
-       "Cool!",
-       "You've made my day!",
-       "The shopkeeper giggles.",
-       "The shopkeeper laughs loudly."
-#endif
+    _("すばらしい!", "Cool!"),
+       _("君が天使に見えるよ!", "You've made my day!"),
+       _("店主がクスクス笑っている。", "The shopkeeper giggles."),
+       _("店主が大声で笑っている。", "The shopkeeper laughs loudly.")
 };
 
 concptr comment_7d[MAX_COMMENT_7D] =
 {
-#ifdef JP
-       "やっほぅ!",
-       "こんなおいしい思いをしたら、真面目に働けなくなるなぁ。",
-       "店主は嬉しくて跳ね回っている。",
-       "店主は満面に笑みをたたえている。"
-#else
-       "Yipee!",
-       "I think I'll retire!",
-       "The shopkeeper jumps for joy.",
-       "The shopkeeper smiles gleefully."
-#endif
+    _("やっほぅ!", "Yipee!"),
+       _("こんなおいしい思いをしたら、真面目に働けなくなるなぁ。", "I think I'll retire!"),
+       _("店主は嬉しくて跳ね回っている。", "The shopkeeper jumps for joy."),
+       _("店主は満面に笑みをたたえている。", "The shopkeeper smiles gleefully.")
 };
index 9ac6d6a..018ce3d 100644 (file)
@@ -3,34 +3,13 @@
 #include "system/angband.h"
 
 #define MAX_COMMENT_1  6
-#define MAX_COMMENT_2A 2
-#define MAX_COMMENT_2B 12
-#define MAX_COMMENT_3A 2
-#define MAX_COMMENT_3B 12
-#define MAX_COMMENT_4A 4
-#define MAX_COMMENT_4B 4
-#define MAX_COMMENT_5  8
-#define MAX_COMMENT_6  4
-#define MAX_COMMENT_7A 4
-#define MAX_COMMENT_7B 4
+#define MAX_COMMENT_7A 8
+#define MAX_COMMENT_7B 8
 #define MAX_COMMENT_7C 4
 #define MAX_COMMENT_7D 4
 
 extern concptr comment_1[MAX_COMMENT_1];
 extern concptr comment_1_B[MAX_COMMENT_1];
-extern concptr comment_2a[MAX_COMMENT_2A];
-extern concptr comment_2b[MAX_COMMENT_2B];
-extern concptr comment_2b_B[MAX_COMMENT_2B];
-extern concptr comment_3a[MAX_COMMENT_3A];
-extern concptr comment_3b[MAX_COMMENT_3B];
-extern concptr comment_3b_B[MAX_COMMENT_3B];
-extern concptr comment_4a[MAX_COMMENT_4A];
-extern concptr comment_4a_B[MAX_COMMENT_4A];
-extern concptr comment_4b[MAX_COMMENT_4B];
-extern concptr comment_4b_B[MAX_COMMENT_4B];
-extern concptr comment_5[MAX_COMMENT_5];
-extern concptr comment_5_B[MAX_COMMENT_5];
-extern concptr comment_6[MAX_COMMENT_6];
 extern concptr comment_7a[MAX_COMMENT_7A];
 extern concptr comment_7b[MAX_COMMENT_7B];
 extern concptr comment_7c[MAX_COMMENT_7C];
index 339bf74..607ca4d 100644 (file)
 /*!
  * @todo _() でまとめる
  */
-const owner_type owners[MAX_STORES][MAX_OWNERS] =
-{
-       {
-               /* General store - 32 unique names */
-               /*
-                 Raistlin は dragonlance の powerful wizard 。
-                 Rincewind the Chicken は Terry Pratchett の Discworld の登場人物 上記のパロディ?、
-                 { "憶病者ラストリン",       200,    175,  108,   4,  12,  RACE_HUMAN},
-                 { "Raistlin the Chicken",       200,    175, 108,  4, 12, RACE_HUMAN},
-               */
-
+const owner_type owners[MAX_STORES][MAX_OWNERS] = {
+    {
+        /* General store - 32 unique names */
+        /*
+          Raistlin は dragonlance の powerful wizard 。
+          Rincewind the Chicken は Terry Pratchett の Discworld の登場人物 上記のパロディ?、
+          { "憶病者ラストリン",  200, 108, RACE_HUMAN},
+          { "Raistlin the Chicken", 200, 108, RACE_HUMAN},
+        */
 #ifdef JP
-               { "フレンドリーなビルボ",       200,    170,  108,   5,  15,  RACE_HOBBIT},
-               { "憶病者リンスウィンド",       200,    175,  108,   4,  12,  RACE_HUMAN},
-               { "背の低いサルタン",             300,    170,  107,   5,  15,  RACE_GNOME},
-               { "ハンサムなライア=エル",      300,    165,  107,   6,  18,  RACE_ELF},
-               { "親切なファリルマウエン",         250,    170, 108,  5, 15, RACE_HOBBIT},
-               { "臆病者ヴォワラン",       500,    175, 108,  4, 12, RACE_HUMAN},
-               { "チビのエラシュナク",          750,    170, 107,  5, 15, RACE_BEASTMAN},
-               { "ハンサムなグラッグ",        1000,    165, 107,  6, 18, RACE_HALF_TITAN},
-               { "ケチなフォロビア",         250,    170, 108,  5, 15, RACE_HUMAN},
-               { "馬鹿のエリス",       500,    175, 108,  4, 12, RACE_HUMAN},
-               { "腹ペコのフィルバート",          750,    170, 107,  5, 15, RACE_VAMPIRE},
-               { "スナーグル・サシグア",        1000,    165, 107,  6, 18, RACE_MIND_FLAYER},
-               { "長死きエロワーズ",         250,    170, 108,  5, 15, RACE_SPECTRE},
-               { "ノロマのフンディ",       500,    175, 108,  4, 12, RACE_ZOMBIE},
-               { "グランサス",          750,    170, 107,  5, 15, RACE_SKELETON},
-               { "丁寧なロラックス",        1000,    165, 107,  6, 18, RACE_VAMPIRE},
-               { "ブッチ",         250,    170, 108,  5, 15, RACE_HALF_ORC},
-               { "美しきエルベレス",       500,    175, 108,  4, 12, RACE_HIGH_ELF},
-               { "こそこそサーレス",          750,    170, 107,  5, 15, RACE_GNOME},
-               { "ナーロック",        1000,    165, 107,  6, 18, RACE_DWARF},
-               { "チビのヘイネッカ",         250,    170, 108,  5, 15, RACE_GNOME},
-               { "きちがいロワラン",       500,    175, 108,  4, 12, RACE_HALF_GIANT},
-               { "毒息のウート",          750,    170, 107,  5, 15, RACE_DRACONIAN},
-               { "でぶっちょアラァカ",        1000,    165, 107,  6, 18, RACE_DRACONIAN},
-               { "低能なプーゴー",         250,    170, 108,  5, 15, RACE_BEASTMAN},
-               { "フェロールフィリアン",       500,    175, 108,  4, 12, RACE_ELF},
-               { "年寄りマロカ",          750,    170, 107,  5, 15, RACE_GNOME},
-               { "勇敢なサシン",        1000,    165, 107,  6, 18, RACE_HALF_GIANT},
-               { "田舎者アビエマール",         250,    170, 108,  5, 15, RACE_HUMAN},
-               { "貧乏なハーク",       500,    175, 108,  4, 12, RACE_HALF_ORC},
-               { "みじめなソアリン",          750,    170, 107,  5, 15, RACE_ZOMBIE},
-               { "質素なメルラ",        1000,    165, 107,  6, 18, RACE_ELF},
+        { "フレンドリーなビルボ", 30000, 108, RACE_HOBBIT },
+        { "憶病者リンスウィンド", 30000, 108, RACE_HUMAN },
+        { "背の低いサルタン", 30000, 107, RACE_GNOME },
+        { "ハンサムなライア=エル", 30000, 107, RACE_ELF },
+        { "親切なファリルマウエン", 30000, 108, RACE_HOBBIT },
+        { "臆病者ヴォワラン", 30000, 108, RACE_HUMAN },
+        { "チビのエラシュナク", 30000, 107, RACE_BEASTMAN },
+        { "ハンサムなグラッグ", 30000, 107, RACE_HALF_TITAN },
+        { "ケチなフォロビア", 30000, 108, RACE_HUMAN },
+        { "馬鹿のエリス", 30000, 108, RACE_HUMAN },
+        { "腹ペコのフィルバート", 30000, 107, RACE_VAMPIRE },
+        { "スナーグル・サシグア", 30000, 107, RACE_MIND_FLAYER },
+        { "長死きエロワーズ", 30000, 108, RACE_SPECTRE },
+        { "ノロマのフンディ", 30000, 108, RACE_ZOMBIE },
+        { "グランサス", 30000, 107, RACE_SKELETON },
+        { "丁寧なロラックス", 30000, 107, RACE_VAMPIRE },
+        { "ブッチ", 30000, 108, RACE_HALF_ORC },
+        { "美しきエルベレス", 30000, 108, RACE_HIGH_ELF },
+        { "こそこそサーレス", 30000, 107, RACE_GNOME },
+        { "ナーロック", 30000, 107, RACE_DWARF },
+        { "チビのヘイネッカ", 30000, 108, RACE_GNOME },
+        { "きちがいロワラン", 30000, 108, RACE_HALF_GIANT },
+        { "毒息のウート", 30000, 107, RACE_DRACONIAN },
+        { "でぶっちょアラァカ", 30000, 107, RACE_DRACONIAN },
+        { "低能なプーゴー", 30000, 108, RACE_BEASTMAN },
+        { "フェロールフィリアン", 30000, 108, RACE_ELF },
+        { "年寄りマロカ", 30000, 107, RACE_GNOME },
+        { "勇敢なサシン", 30000, 107, RACE_HALF_GIANT },
+        { "田舎者アビエマール", 30000, 108, RACE_HUMAN },
+        { "貧乏なハーク", 30000, 108, RACE_HALF_ORC },
+        { "みじめなソアリン", 30000, 107, RACE_ZOMBIE },
+        { "質素なメルラ", 30000, 107, RACE_ELF },
 #else
-               { "Bilbo the Friendly",         200,    170, 108,  5, 15, RACE_HOBBIT},
-               { "Rincewind the Chicken",       200,    175, 108,  4, 12, RACE_HUMAN},
-               { "Sultan the Midget",          300,    170, 107,  5, 15, RACE_GNOME},
-               { "Lyar-el the Comely",         300,    165, 107,  6, 18, RACE_ELF},
-               { "Falilmawen the Friendly",         250,    170, 108,  5, 15, RACE_HOBBIT},
-               { "Voirin the Cowardly",       500,    175, 108,  4, 12, RACE_HUMAN},
-               { "Erashnak the Midget",          750,    170, 107,  5, 15, RACE_BEASTMAN},
-               { "Grug the Comely",        1000,    165, 107,  6, 18, RACE_HALF_TITAN},
-               { "Forovir the Cheap",         250,    170, 108,  5, 15, RACE_HUMAN},
-               { "Ellis the Fool",       500,    175, 108,  4, 12, RACE_HUMAN},
-               { "Filbert the Hungry",          750,    170, 107,  5, 15, RACE_VAMPIRE},
-               { "Fthnargl Psathiggua",        1000,    165, 107,  6, 18, RACE_MIND_FLAYER},
-               { "Eloise Long-Dead",         250,    170, 108,  5, 15, RACE_SPECTRE},
-               { "Fundi the Slow",       500,    175, 108,  4, 12, RACE_ZOMBIE},
-               { "Granthus",          750,    170, 107,  5, 15, RACE_SKELETON},
-               { "Lorax the Suave",        1000,    165, 107,  6, 18, RACE_VAMPIRE},
-               { "Butch",         250,    170, 108,  5, 15, RACE_HALF_ORC},
-               { "Elbereth the Beautiful",       500,    175, 108,  4, 12, RACE_HIGH_ELF},
-               { "Sarleth the Sneaky",          750,    170, 107,  5, 15, RACE_GNOME},
-               { "Narlock",        1000,    165, 107,  6, 18, RACE_DWARF},
-               { "Haneka the Small",         250,    170, 108,  5, 15, RACE_GNOME},
-               { "Loirin the Mad",       500,    175, 108,  4, 12, RACE_HALF_GIANT},
-               { "Wuto Poisonbreath",          750,    170, 107,  5, 15, RACE_DRACONIAN},
-               { "Araaka the Rotund",        1000,    165, 107,  6, 18, RACE_DRACONIAN},
-               { "Poogor the Dumb",         250,    170, 108,  5, 15, RACE_BEASTMAN},
-               { "Felorfiliand",       500,    175, 108,  4, 12, RACE_ELF},
-               { "Maroka the Aged",          750,    170, 107,  5, 15, RACE_GNOME},
-               { "Sasin the Bold",        1000,    165, 107,  6, 18, RACE_HALF_GIANT},
-               { "Abiemar the Peasant",         250,    170, 108,  5, 15, RACE_HUMAN},
-               { "Hurk the Poor",       500,    175, 108,  4, 12, RACE_HALF_ORC},
-               { "Soalin the Wretched",          750,    170, 107,  5, 15, RACE_ZOMBIE},
-               { "Merulla the Humble",        1000,    165, 107,  6, 18, RACE_ELF},
+        { "Bilbo the Friendly", 30000, 108, RACE_HOBBIT },
+        { "Rincewind the Chicken", 30000, 108, RACE_HUMAN },
+        { "Sultan the Midget", 30000, 107, RACE_GNOME },
+        { "Lyar-el the Comely", 30000, 107, RACE_ELF },
+        { "Falilmawen the Friendly", 30000, 108, RACE_HOBBIT },
+        { "Voirin the Cowardly", 30000, 108, RACE_HUMAN },
+        { "Erashnak the Midget", 30000, 107, RACE_BEASTMAN },
+        { "Grug the Comely", 30000, 107, RACE_HALF_TITAN },
+        { "Forovir the Cheap", 30000, 108, RACE_HUMAN },
+        { "Ellis the Fool", 30000, 108, RACE_HUMAN },
+        { "Filbert the Hungry", 30000, 107, RACE_VAMPIRE },
+        { "Fthnargl Psathiggua", 30000, 107, RACE_MIND_FLAYER },
+        { "Eloise Long-Dead", 30000, 108, RACE_SPECTRE },
+        { "Fundi the Slow", 30000, 108, RACE_ZOMBIE },
+        { "Granthus", 30000, 107, RACE_SKELETON },
+        { "Lorax the Suave", 30000, 107, RACE_VAMPIRE },
+        { "Butch", 30000, 108, RACE_HALF_ORC },
+        { "Elbereth the Beautiful", 30000, 108, RACE_HIGH_ELF },
+        { "Sarleth the Sneaky", 30000, 107, RACE_GNOME },
+        { "Narlock", 30000, 107, RACE_DWARF },
+        { "Haneka the Small", 30000, 108, RACE_GNOME },
+        { "Loirin the Mad", 30000, 108, RACE_HALF_GIANT },
+        { "Wuto Poisonbreath", 30000, 107, RACE_DRACONIAN },
+        { "Araaka the Rotund", 30000, 107, RACE_DRACONIAN },
+        { "Poogor the Dumb", 30000, 108, RACE_BEASTMAN },
+        { "Felorfiliand", 30000, 108, RACE_ELF },
+        { "Maroka the Aged", 30000, 107, RACE_GNOME },
+        { "Sasin the Bold", 30000, 107, RACE_HALF_GIANT },
+        { "Abiemar the Peasant", 30000, 108, RACE_HUMAN },
+        { "Hurk the Poor", 30000, 108, RACE_HALF_ORC },
+        { "Soalin the Wretched", 30000, 107, RACE_ZOMBIE },
+        { "Merulla the Humble", 30000, 107, RACE_ELF },
 #endif
-       },
-       {
-               /* Armoury - 28 unique names */
+    },
+    {
+        /* Armoury - 28 unique names */
 #ifdef JP
-               { "醜悪コン=ダー",      5000,   210,  115,   5,   7,  RACE_HALF_ORC},
-               { "頑固者ダーグ=ロウ",  10000,  190,  111,   4,   9,  RACE_HUMAN},
-               { "賢者デカド",                 25000,  200,  112,   4,  10,  RACE_DUNADAN},
-               { "鍛冶屋のウィーランド",   30000,  200,  112,   4,   5,  RACE_DWARF},
-               { "醜悪コン=ダー",           10000,   210, 115,  5,  7, RACE_HALF_ORC},
-               { "頑固者ダーグ=ロウ",          15000,  190, 111,  4,  9, RACE_HUMAN},
-               { "ハンサムなデカド",            25000,  200, 112,  4, 10, RACE_AMBERITE},
-               { "エロー・ドラゴンスケイル",          30000,  200, 112,  4,  5, RACE_ELF},
-               { "デリカトス",           10000,   210, 115,  5,  7, RACE_SPRITE},
-               { "巨大なグルース",          15000,  190, 111,  4,  9, RACE_HALF_GIANT},
-               { "アニムス",            25000,  200, 112,  4, 10, RACE_GOLEM},
-               { "マルヴァス",          30000,  200, 112,  4,  5, RACE_HALF_TITAN},
-               { "セラクシス",           10000,   210, 115,  5,  7, RACE_ZOMBIE},
-               { "デス・チル",          5000,  190, 111,  4,  9, RACE_SPECTRE},
-               { "微かなドリオス",            25000,  200, 112,  4, 10, RACE_SPECTRE},
-               { "冷たいバスリック",          30000,  200, 112,  4,  5, RACE_VAMPIRE},
-               { "冷酷ヴェンジェラ",           10000,   210, 115,  5,  7, RACE_HALF_TROLL},
-               { "強者ウィラナ",          15000,  190, 111,  4,  9, RACE_HUMAN},
-               { "ヨジョ二世",            25000,  200, 112,  4, 10, RACE_DWARF},
-               { "優しいラナラー",          30000,  200, 112,  4,  5, RACE_AMBERITE},
-               { "不浄のホルバグ",           5000,   210, 115,  5,  7, RACE_HALF_ORC},
-               { "テレパスのエレレン",          15000,  190, 111,  4,  9, RACE_DARK_ELF},
-               { "イスドリリアス",            25000,  200, 112,  4, 10, RACE_SPRITE},
-               { "一つ目ヴェグナー",          5000,  200, 112,  4,  5, RACE_CYCLOPS},
-               { "混沌のロディッシュ",           10000,   210, 115,  5,  7, RACE_BEASTMAN},
-               { "剣豪ヘジン",          15000,  190, 111,  4,  9, RACE_NIBELUNG},
-               { "ずる屋のエルベレリス",           10000,  200, 112,  4, 10, RACE_DARK_ELF},
-               { "インプのザサス",          30000,  200, 112,  4,  5, RACE_IMP},
-               { "醜悪コン=ダー",           5000,   210, 115,  5,  7, RACE_HALF_ORC},
-               { "頑固者ダーグ=ロウ",          10000,  190, 111,  4,  9, RACE_HUMAN},
-               { "ハンサムなデカド",            25000,  200, 112,  4, 10, RACE_AMBERITE},
-               { "鍛冶屋のウィーランド",          30000,  200, 112,  4,  5, RACE_DWARF},
+        { "醜悪コン=ダー", 30000, 115, RACE_HALF_ORC },
+        { "頑固者ダーグ=ロウ", 30000, 111, RACE_HUMAN },
+        { "賢者デカド", 30000, 112, RACE_DUNADAN },
+        { "鍛冶屋のウィーランド", 30000, 112, RACE_DWARF },
+        { "醜悪コン=ダー", 30000, 115, RACE_HALF_ORC },
+        { "頑固者ダーグ=ロウ", 30000, 111, RACE_HUMAN },
+        { "ハンサムなデカド", 30000, 112, RACE_AMBERITE },
+        { "エロー・ドラゴンスケイル", 30000, 112, RACE_ELF },
+        { "デリカトス", 30000, 115, RACE_SPRITE },
+        { "巨大なグルース", 30000, 111, RACE_HALF_GIANT },
+        { "アニムス", 30000, 112, RACE_GOLEM },
+        { "マルヴァス", 30000, 112, RACE_HALF_TITAN },
+        { "セラクシス", 30000, 115, RACE_ZOMBIE },
+        { "デス・チル", 30000, 111, RACE_SPECTRE },
+        { "微かなドリオス", 30000, 112, RACE_SPECTRE },
+        { "冷たいバスリック", 30000, 112, RACE_VAMPIRE },
+        { "冷酷ヴェンジェラ", 30000, 115, RACE_HALF_TROLL },
+        { "強者ウィラナ", 30000, 111, RACE_HUMAN },
+        { "ヨジョ二世", 30000, 112, RACE_DWARF },
+        { "優しいラナラー", 30000, 112, RACE_AMBERITE },
+        { "不浄のホルバグ", 30000, 115, RACE_HALF_ORC },
+        { "テレパスのエレレン", 30000, 111, RACE_DARK_ELF },
+        { "イスドリリアス", 30000, 112, RACE_SPRITE },
+        { "一つ目ヴェグナー", 30000, 112, RACE_CYCLOPS },
+        { "混沌のロディッシュ", 30000, 115, RACE_BEASTMAN },
+        { "剣豪ヘジン", 30000, 111, RACE_NIBELUNG },
+        { "ずる屋のエルベレリス", 30000, 112, RACE_DARK_ELF },
+        { "インプのザサス", 30000, 112, RACE_IMP },
+        { "醜悪コン=ダー", 30000, 115, RACE_HALF_ORC },
+        { "頑固者ダーグ=ロウ", 30000, 111, RACE_HUMAN },
+        { "ハンサムなデカド", 30000, 112, RACE_AMBERITE },
+        { "鍛冶屋のウィーランド", 30000, 112, RACE_DWARF },
 #else
-               { "Kon-Dar the Ugly",           5000,   210, 115,  5,  7, RACE_HALF_ORC},
-               { "Darg-Low the Grim",          10000,  190, 111,  4,  9, RACE_HUMAN},
-               { "Decado the Handsome",            25000,  200, 112,  4, 10, RACE_DUNADAN},
-               { "Wieland the Smith",          30000,  200, 112,  4,  5, RACE_DWARF},
-               { "Kon-Dar the Ugly",           10000,   210, 115,  5,  7, RACE_HALF_ORC},
-               { "Darg-Low the Grim",          15000,  190, 111,  4,  9, RACE_HUMAN},
-               { "Decado the Handsome",            25000,  200, 112,  4, 10, RACE_AMBERITE},
-               { "Elo Dragonscale",          30000,  200, 112,  4,  5, RACE_ELF},
-               { "Delicatus",           10000,   210, 115,  5,  7, RACE_SPRITE},
-               { "Gruce the Huge",          15000,  190, 111,  4,  9, RACE_HALF_GIANT},
-               { "Animus",            25000,  200, 112,  4, 10, RACE_GOLEM},
-               { "Malvus",          30000,  200, 112,  4,  5, RACE_HALF_TITAN},
-               { "Selaxis",           10000,   210, 115,  5,  7, RACE_ZOMBIE},
-               { "Deathchill",          5000,  190, 111,  4,  9, RACE_SPECTRE},
-               { "Drios the Faint",            25000,  200, 112,  4, 10, RACE_SPECTRE},
-               { "Bathric the Cold",          30000,  200, 112,  4,  5, RACE_VAMPIRE},
-               { "Vengella the Cruel",           10000,   210, 115,  5,  7, RACE_HALF_TROLL},
-               { "Wyrana the Mighty",          15000,  190, 111,  4,  9, RACE_HUMAN},
-               { "Yojo II",            25000,  200, 112,  4, 10, RACE_DWARF},
-               { "Ranalar the Sweet",          30000,  200, 112,  4,  5, RACE_AMBERITE},
-               { "Horbag the Unclean",           5000,   210, 115,  5,  7, RACE_HALF_ORC},
-               { "Elelen the Telepath",          15000,  190, 111,  4,  9, RACE_DARK_ELF},
-               { "Isedrelias",            25000,  200, 112,  4, 10, RACE_SPRITE},
-               { "Vegnar One-eye",          5000,  200, 112,  4,  5, RACE_CYCLOPS},
-               { "Rodish the Chaotic",           10000,   210, 115,  5,  7, RACE_BEASTMAN},
-               { "Hesin Swordmaster",          15000,  190, 111,  4,  9, RACE_NIBELUNG},
-               { "Elvererith the Cheat",           10000,  200, 112,  4, 10, RACE_DARK_ELF},
-               { "Zzathath the Imp",          30000,  200, 112,  4,  5, RACE_IMP},
-               { "Kon-Dar the Ugly",           5000,   210, 115,  5,  7, RACE_HALF_ORC},
-               { "Darg-Low the Grim",          10000,  190, 111,  4,  9, RACE_HUMAN},
-               { "Decado the Handsome",            25000,  200, 112,  4, 10, RACE_AMBERITE},
-               { "Wieland the Smith",          30000,  200, 112,  4,  5, RACE_DWARF},
+        { "Kon-Dar the Ugly", 30000, 115, RACE_HALF_ORC },
+        { "Darg-Low the Grim", 30000, 111, RACE_HUMAN },
+        { "Decado the Handsome", 30000, 112, RACE_DUNADAN },
+        { "Wieland the Smith", 30000, 112, RACE_DWARF },
+        { "Kon-Dar the Ugly", 30000, 115, RACE_HALF_ORC },
+        { "Darg-Low the Grim", 30000, 111, RACE_HUMAN },
+        { "Decado the Handsome", 30000, 112, RACE_AMBERITE },
+        { "Elo Dragonscale", 30000, 112, RACE_ELF },
+        { "Delicatus", 30000, 115, RACE_SPRITE },
+        { "Gruce the Huge", 30000, 111, RACE_HALF_GIANT },
+        { "Animus", 30000, 112, RACE_GOLEM },
+        { "Malvus", 30000, 112, RACE_HALF_TITAN },
+        { "Selaxis", 30000, 115, RACE_ZOMBIE },
+        { "Deathchill", 30000, 111, RACE_SPECTRE },
+        { "Drios the Faint", 30000, 112, RACE_SPECTRE },
+        { "Bathric the Cold", 30000, 112, RACE_VAMPIRE },
+        { "Vengella the Cruel", 30000, 115, RACE_HALF_TROLL },
+        { "Wyrana the Mighty", 30000, 111, RACE_HUMAN },
+        { "Yojo II", 30000, 112, RACE_DWARF },
+        { "Ranalar the Sweet", 30000, 112, RACE_AMBERITE },
+        { "Horbag the Unclean", 30000, 115, RACE_HALF_ORC },
+        { "Elelen the Telepath", 30000, 111, RACE_DARK_ELF },
+        { "Isedrelias", 30000, 112, RACE_SPRITE },
+        { "Vegnar One-eye", 30000, 112, RACE_CYCLOPS },
+        { "Rodish the Chaotic", 30000, 115, RACE_BEASTMAN },
+        { "Hesin Swordmaster", 30000, 111, RACE_NIBELUNG },
+        { "Elvererith the Cheat", 30000, 112, RACE_DARK_ELF },
+        { "Zzathath the Imp", 30000, 112, RACE_IMP },
+        { "Kon-Dar the Ugly", 30000, 115, RACE_HALF_ORC },
+        { "Darg-Low the Grim", 30000, 111, RACE_HUMAN },
+        { "Decado the Handsome", 30000, 112, RACE_AMBERITE },
+        { "Wieland the Smith", 30000, 112, RACE_DWARF },
 #endif
-       },
+    },
 
-       {
-               /* Weapon Smith - 28 unique names */
+    {
+        /* Weapon Smith - 28 unique names */
 #ifdef JP
-               { "残忍なるアーノルド",        5000,   210,  115,   6,   6,  RACE_HALF_TROLL},
-               { "獣殺しのアーンダル", 10000,  185,  110,   5,   9,  RACE_HALF_ELF},
-               { "獣マスターのエディー", 25000,  190,  115,   5,   7,  RACE_HOBBIT},
-               { "竜殺しのオグライン", 30000,  195,  112,   4,   8,  RACE_DWARF},
-               { "熟練者ドリュー",      10000,   210, 115,  6,  6, RACE_HUMAN},
-               { "龍の子オラックス",        15000,  185, 110,  5,  9, RACE_DRACONIAN},
-               { "病気持ちのアンスラックス",         25000,  190, 115,  5,  7, RACE_BEASTMAN},
-               { "頑丈者アルコス",       30000,  195, 112,  4,  8, RACE_DWARF},
-               { "腐れ者のサリアス",      5000,   210, 115,  6,  6, RACE_ZOMBIE},
-               { "晒し骨のトゥエシク",        15000,  185, 110,  5,  9, RACE_SKELETON},
-               { "ビリオス",         25000,  190, 115,  5,  7, RACE_BEASTMAN},
-               { "ファスガル",       30000,  195, 112,  4,  8, RACE_ZOMBIE},
-               { "パラディンのエレフリス",      10000,   210, 115,  6,  6, RACE_BARBARIAN},
-               { "キ'トリッ'ク",        15000,  185, 110,  5,  9, RACE_KLACKON},
-               { "蜘蛛の友ドゥロカス",         25000,  190, 115,  5,  7, RACE_DARK_ELF},
-               { "巨人殺しのフングス",       30000,  195, 112,  4,  8, RACE_DWARF},
-               { "デランサ",      10000,   210, 115,  6,  6, RACE_ELF},
-               { "レンジャーのソルビスタニ",        15000,  185, 110,  5,  9, RACE_HALF_ELF},
-               { "ノロマのゾリル",         25000,  190, 115,  5,  7, RACE_GOLEM},
-               { "イーオン・フラックス",       20000,  195, 112,  4,  8, RACE_HALF_ELF},
-               { "強者ナドック",      10000,   210, 115,  6,  6, RACE_HOBBIT},
-               { "弱虫エラモグ",        15000,  185, 110,  5,  9, RACE_KOBOLD},
-               { "公正なエオウィリス",         25000,  190, 115,  5,  7, RACE_VAMPIRE},
-               { "バルログ殺しのヒュイモグ",       30000,  195, 112,  4,  8, RACE_HALF_ORC},
-               { "冷酷ピーダス",      5000,   210, 115,  6,  6, RACE_HUMAN},
-               { "ヴァモグ スレイヤー",        15000,  185, 110,  5,  9, RACE_HALF_OGRE},
-               { "性悪フーシュナク",         25000,  190, 115,  5,  7, RACE_BEASTMAN},
-               { "舞闘バレン",       30000,  195, 112,  4,  8, RACE_BARBARIAN},
-               { "残忍なるアーノルド",      5000,   210, 115,  6,  6, RACE_BARBARIAN},
-               { "獣殺しのアーンダル",        10000,  185, 110,  5,  9, RACE_HALF_ELF},
-               { "ビーストマスター・エディー",         25000,  190, 115,  5,  7, RACE_HALF_ORC},
-               { "竜殺しのオグライン",       30000,  195, 112,  4,  8, RACE_DWARF},
+        { "残忍なるアーノルド", 30000, 115, RACE_HALF_TROLL },
+        { "獣殺しのアーンダル", 30000, 110, RACE_HALF_ELF },
+        { "獣マスターのエディー", 30000, 115, RACE_HOBBIT },
+        { "竜殺しのオグライン", 30000, 112, RACE_DWARF },
+        { "熟練者ドリュー", 30000, 115, RACE_HUMAN },
+        { "龍の子オラックス", 30000, 110, RACE_DRACONIAN },
+        { "病気持ちのアンスラックス", 30000, 115, RACE_BEASTMAN },
+        { "頑丈者アルコス", 30000, 112, RACE_DWARF },
+        { "腐れ者のサリアス", 30000, 115, RACE_ZOMBIE },
+        { "晒し骨のトゥエシク", 30000, 110, RACE_SKELETON },
+        { "ビリオス", 30000, 115, RACE_BEASTMAN },
+        { "ファスガル", 30000, 112, RACE_ZOMBIE },
+        { "パラディンのエレフリス", 30000, 115, RACE_BARBARIAN },
+        { "キ'トリッ'ク", 30000, 110, RACE_KLACKON },
+        { "蜘蛛の友ドゥロカス", 30000, 115, RACE_DARK_ELF },
+        { "巨人殺しのフングス", 30000, 112, RACE_DWARF },
+        { "デランサ", 30000, 115, RACE_ELF },
+        { "レンジャーのソルビスタニ", 30000, 110, RACE_HALF_ELF },
+        { "ノロマのゾリル", 30000, 115, RACE_GOLEM },
+        { "イーオン・フラックス", 30000, 112, RACE_HALF_ELF },
+        { "強者ナドック", 30000, 115, RACE_HOBBIT },
+        { "弱虫エラモグ", 30000, 110, RACE_KOBOLD },
+        { "公正なエオウィリス", 30000, 115, RACE_VAMPIRE },
+        { "バルログ殺しのヒュイモグ", 30000, 112, RACE_HALF_ORC },
+        { "冷酷ピーダス", 30000, 115, RACE_HUMAN },
+        { "ヴァモグ スレイヤー", 30000, 110, RACE_HALF_OGRE },
+        { "性悪フーシュナク", 30000, 115, RACE_BEASTMAN },
+        { "舞闘バレン", 30000, 112, RACE_BARBARIAN },
+        { "残忍なるアーノルド", 30000, 115, RACE_BARBARIAN },
+        { "獣殺しのアーンダル", 30000, 110, RACE_HALF_ELF },
+        { "ビーストマスター・エディー", 30000, 115, RACE_HALF_ORC },
+        { "竜殺しのオグライン", 30000, 112, RACE_DWARF },
 #else
-               { "Arnold the Beastly",      5000,   210, 115,  6,  6, RACE_BARBARIAN},
-               { "Arndal Beast-Slayer",        10000,  185, 110,  5,  9, RACE_HALF_ELF},
-               { "Eddie Beast-Master",         25000,  190, 115,  5,  7, RACE_HALF_ORC},
-               { "Oglign Dragon-Slayer",       30000,  195, 112,  4,  8, RACE_DWARF},
-               { "Drew the Skilled",      10000,   210, 115,  6,  6, RACE_HUMAN},
-               { "Orrax Dragonson",        15000,  185, 110,  5,  9, RACE_DRACONIAN},
-               { "Anthrax Disease-Carrier",         25000,  190, 115,  5,  7, RACE_BEASTMAN},
-               { "Arkhoth the Stout",       30000,  195, 112,  4,  8, RACE_DWARF},
-               { "Sarlyas the Rotten",      5000,   210, 115,  6,  6, RACE_ZOMBIE},
-               { "Tuethic Bare-Bones",        15000,  185, 110,  5,  9, RACE_SKELETON},
-               { "Bilious",         25000,  190, 115,  5,  7, RACE_BEASTMAN},
-               { "Fasgul",       30000,  195, 112,  4,  8, RACE_ZOMBIE},
-               { "Ellefris the Paladin",      10000,   210, 115,  6,  6, RACE_BARBARIAN},
-               { "K'trrik'k",        15000,  185, 110,  5,  9, RACE_KLACKON},
-               { "Drocus Spiderfriend",         25000,  190, 115,  5,  7, RACE_DARK_ELF},
-               { "Fungus Giant-Slayer",       30000,  195, 112,  4,  8, RACE_DWARF},
-               { "Delantha",      10000,   210, 115,  6,  6, RACE_ELF},
-               { "Solvistani the Ranger",        15000,  185, 110,  5,  9, RACE_HALF_ELF},
-               { "Xoril the Slow",         25000,  190, 115,  5,  7, RACE_GOLEM},
-               { "Aeon Flux",       20000,  195, 112,  4,  8, RACE_HALF_ELF},
-               { "Nadoc the Strong",      10000,   210, 115,  6,  6, RACE_HOBBIT},
-               { "Eramog the Weak",        15000,  185, 110,  5,  9, RACE_KOBOLD},
-               { "Eowilith the Fair",         25000,  190, 115,  5,  7, RACE_VAMPIRE},
-               { "Huimog Balrog-Slayer",       30000,  195, 112,  4,  8, RACE_HALF_ORC},
-               { "Peadus the Cruel",      5000,   210, 115,  6,  6, RACE_HUMAN},
-               { "Vamog Slayer",        15000,  185, 110,  5,  9, RACE_HALF_OGRE},
-               { "Hooshnak the Vicious",         25000,  190, 115,  5,  7, RACE_BEASTMAN},
-               { "Balenn War-Dancer",       30000,  195, 112,  4,  8, RACE_BARBARIAN},
-               { "Arnold the Beastly",      5000,   210, 115,  6,  6, RACE_BARBARIAN},
-               { "Arndal Beast-Slayer",        10000,  185, 110,  5,  9, RACE_HALF_ELF},
-               { "Eddie Beast-Master",         25000,  190, 115,  5,  7, RACE_HALF_ORC},
-               { "Oglign Dragon-Slayer",       30000,  195, 112,  4,  8, RACE_DWARF},
+        { "Arnold the Beastly", 30000, 115, RACE_BARBARIAN },
+        { "Arndal Beast-Slayer", 30000, 110, RACE_HALF_ELF },
+        { "Eddie Beast-Master", 30000, 115, RACE_HALF_ORC },
+        { "Oglign Dragon-Slayer", 30000, 112, RACE_DWARF },
+        { "Drew the Skilled", 30000, 115, RACE_HUMAN },
+        { "Orrax Dragonson", 30000, 110, RACE_DRACONIAN },
+        { "Anthrax Disease-Carrier", 30000, 115, RACE_BEASTMAN },
+        { "Arkhoth the Stout", 30000, 112, RACE_DWARF },
+        { "Sarlyas the Rotten", 30000, 115, RACE_ZOMBIE },
+        { "Tuethic Bare-Bones", 30000, 110, RACE_SKELETON },
+        { "Bilious", 30000, 115, RACE_BEASTMAN },
+        { "Fasgul", 30000, 112, RACE_ZOMBIE },
+        { "Ellefris the Paladin", 30000, 115, RACE_BARBARIAN },
+        { "K'trrik'k", 30000, 110, RACE_KLACKON },
+        { "Drocus Spiderfriend", 30000, 115, RACE_DARK_ELF },
+        { "Fungus Giant-Slayer", 30000, 112, RACE_DWARF },
+        { "Delantha", 30000, 115, RACE_ELF },
+        { "Solvistani the Ranger", 30000, 110, RACE_HALF_ELF },
+        { "Xoril the Slow", 30000, 115, RACE_GOLEM },
+        { "Aeon Flux", 30000, 112, RACE_HALF_ELF },
+        { "Nadoc the Strong", 30000, 115, RACE_HOBBIT },
+        { "Eramog the Weak", 30000, 110, RACE_KOBOLD },
+        { "Eowilith the Fair", 30000, 115, RACE_VAMPIRE },
+        { "Huimog Balrog-Slayer", 30000, 112, RACE_HALF_ORC },
+        { "Peadus the Cruel", 30000, 115, RACE_HUMAN },
+        { "Vamog Slayer", 30000, 110, RACE_HALF_OGRE },
+        { "Hooshnak the Vicious", 30000, 115, RACE_BEASTMAN },
+        { "Balenn War-Dancer", 30000, 112, RACE_BARBARIAN },
+        { "Arnold the Beastly", 30000, 115, RACE_BARBARIAN },
+        { "Arndal Beast-Slayer", 30000, 110, RACE_HALF_ELF },
+        { "Eddie Beast-Master", 30000, 115, RACE_HALF_ORC },
+        { "Oglign Dragon-Slayer", 30000, 112, RACE_DWARF },
 #endif
-       },
-       {
-               /* Temple - 22 unique names */
+    },
+    {
+        /* Temple - 22 unique names */
 #ifdef JP
-               { "質素なルードヴィヒ",         5000,   175,  109,   6,  15,  RACE_HUMAN},
-               { "パラディンのガンナー",       10000,  185,  110,   5,  23,  RACE_HUMAN},
-               { "選ばれしトリン",                     25000,  180,  107,   6,  20,  RACE_ELF},
-               { "賢明なるサラストロ",                     30000,  185,  109,   5,  15,  RACE_DWARF},
-               { "パーシヴァル卿",           25000,  180, 107,  6, 20, RACE_HIGH_ELF},
-               { "神聖なるアセナス",          30000,  185, 109,  5, 15, RACE_HUMAN},
-               { "マッキノン",         10000,   175, 109,  6, 15, RACE_HUMAN},
-               { "謹み婦人",         15000,  185, 110,  5, 23, RACE_HIGH_ELF},
-               { "ドルイドのハシュニック",           25000,  180, 107,  6, 20, RACE_HOBBIT},
-               { "フィナク",          30000,  185, 109,  5, 15, RACE_YEEK},
-               { "クリキック",         10000,   175, 109,  6, 15, RACE_KLACKON},
-               { "荒くれ者モリヴァル",         15000,  185, 110,  5, 23, RACE_ELF},
-               { "暗きホシャック",           25000,  180, 107,  6, 20, RACE_IMP},
-               { "賢者アタール",          30000,  185, 109,  5, 15, RACE_HUMAN},
-               { "清きイベニッド",         10000,   175, 109,  6, 15, RACE_HUMAN},
-               { "エリディシュ",         15000,  185, 110,  5, 23, RACE_HALF_TROLL},
-               { "呪術師ヴルドゥシュ",           25000,  180, 107,  6, 20, RACE_HALF_OGRE},
-               { "狂戦士ハオブ",          30000,  185, 109,  5, 15, RACE_BARBARIAN},
-               { "若きプルーグディシュ",         10000,   175, 109,  6, 15, RACE_HALF_OGRE},
-               { "きちがいラムワイズ",         15000,  185, 110,  5, 23, RACE_YEEK},
-               { "有徳者ムワート",           25000,  180, 107,  6, 20, RACE_KOBOLD},
-               { "弱虫ダードバード",          30000,  185, 109,  5, 15, RACE_SPECTRE},
-               { "質素なルードヴィヒ",         5000,   175,  109,   6,  15,  RACE_HUMAN},
-               { "パラディンのガンナー",       10000,  185,  110,   5,  23,  RACE_HUMAN},
-               { "選ばれしトリン",                     25000,  180,  107,   6,  20,  RACE_ELF},
-               { "賢明なるサラストロ",                     30000,  185,  109,   5,  15,  RACE_DWARF},
-               { "パーシヴァル卿",           25000,  180, 107,  6, 20, RACE_HIGH_ELF},
-               { "神聖なるアセナス",          30000,  185, 109,  5, 15, RACE_HUMAN},
-               { "マッキノン",         10000,   175, 109,  6, 15, RACE_HUMAN},
-               { "謹み婦人",         15000,  185, 110,  5, 23, RACE_HIGH_ELF},
-               { "ドルイドのハシュニック",           25000,  180, 107,  6, 20, RACE_HOBBIT},
-               { "フィナク",          30000,  185, 109,  5, 15, RACE_YEEK},
+        { "質素なルードヴィヒ", 30000, 109, RACE_HUMAN },
+        { "パラディンのガンナー", 30000, 110, RACE_HUMAN },
+        { "選ばれしトリン", 30000, 107, RACE_ELF },
+        { "賢明なるサラストロ", 30000, 109, RACE_DWARF },
+        { "パーシヴァル卿", 30000, 107, RACE_HIGH_ELF },
+        { "神聖なるアセナス", 30000, 109, RACE_HUMAN },
+        { "マッキノン", 30000, 109, RACE_HUMAN },
+        { "謹み婦人", 30000, 110, RACE_HIGH_ELF },
+        { "ドルイドのハシュニック", 30000, 107, RACE_HOBBIT },
+        { "フィナク", 30000, 109, RACE_YEEK },
+        { "クリキック", 30000, 109, RACE_KLACKON },
+        { "荒くれ者モリヴァル", 30000, 110, RACE_ELF },
+        { "暗きホシャック", 30000, 107, RACE_IMP },
+        { "賢者アタール", 30000, 109, RACE_HUMAN },
+        { "清きイベニッド", 30000, 109, RACE_HUMAN },
+        { "エリディシュ", 30000, 110, RACE_HALF_TROLL },
+        { "呪術師ヴルドゥシュ", 30000, 107, RACE_HALF_OGRE },
+        { "狂戦士ハオブ", 30000, 109, RACE_BARBARIAN },
+        { "若きプルーグディシュ", 30000, 109, RACE_HALF_OGRE },
+        { "きちがいラムワイズ", 30000, 110, RACE_YEEK },
+        { "有徳者ムワート", 30000, 107, RACE_KOBOLD },
+        { "弱虫ダードバード", 30000, 109, RACE_SPECTRE },
+        { "質素なルードヴィヒ", 30000, 109, RACE_HUMAN },
+        { "パラディンのガンナー", 30000, 110, RACE_HUMAN },
+        { "選ばれしトリン", 30000, 107, RACE_ELF },
+        { "賢明なるサラストロ", 30000, 109, RACE_DWARF },
+        { "パーシヴァル卿", 30000, 107, RACE_HIGH_ELF },
+        { "神聖なるアセナス", 30000, 109, RACE_HUMAN },
+        { "マッキノン", 30000, 109, RACE_HUMAN },
+        { "謹み婦人", 30000, 110, RACE_HIGH_ELF },
+        { "ドルイドのハシュニック", 30000, 107, RACE_HOBBIT },
+        { "フィナク", 30000, 109, RACE_YEEK },
 #else
-               { "Ludwig the Humble",          5000,   175, 109,  6, 15, RACE_DWARF},
-               { "Gunnar the Paladin",         10000,  185, 110,  5, 23, RACE_HALF_TROLL},
-               { "Torin the Chosen",           25000,  180, 107,  6, 20, RACE_HIGH_ELF},
-               { "Sarastro the Wise",          30000,  185, 109,  5, 15, RACE_HUMAN},
-               { "Sir Parsival the Pure",           25000,  180, 107,  6, 20, RACE_HIGH_ELF},
-               { "Asenath the Holy",          30000,  185, 109,  5, 15, RACE_HUMAN},
-               { "McKinnon",         10000,   175, 109,  6, 15, RACE_HUMAN},
-               { "Mistress Chastity",         15000,  185, 110,  5, 23, RACE_HIGH_ELF},
-               { "Hashnik the Druid",           25000,  180, 107,  6, 20, RACE_HOBBIT},
-               { "Finak",          30000,  185, 109,  5, 15, RACE_YEEK},
-               { "Krikkik",         10000,   175, 109,  6, 15, RACE_KLACKON},
-               { "Morival the Wild",         15000,  185, 110,  5, 23, RACE_ELF},
-               { "Hoshak the Dark",           25000,  180, 107,  6, 20, RACE_IMP},
-               { "Atal the Wise",          30000,  185, 109,  5, 15, RACE_HUMAN},
-               { "Ibenidd the Chaste",         10000,   175, 109,  6, 15, RACE_HUMAN},
-               { "Eridish",         15000,  185, 110,  5, 23, RACE_HALF_TROLL},
-               { "Vrudush the Shaman",           25000,  180, 107,  6, 20, RACE_HALF_OGRE},
-               { "Haob the Berserker",          30000,  185, 109,  5, 15, RACE_BARBARIAN},
-               { "Proogdish the Youthfull",         10000,   175, 109,  6, 15, RACE_HALF_OGRE},
-               { "Lumwise the Mad",         15000,  185, 110,  5, 23, RACE_YEEK},
-               { "Muirt the Virtuous",           25000,  180, 107,  6, 20, RACE_KOBOLD},
-               { "Dardobard the Weak",          30000,  185, 109,  5, 15, RACE_SPECTRE},
-               { "Ludwig the Humble",          5000,   175, 109,  6, 15, RACE_DWARF},
-               { "Gunnar the Paladin",         10000,  185, 110,  5, 23, RACE_HALF_TROLL},
-               { "Torin the Chosen",           25000,  180, 107,  6, 20, RACE_HIGH_ELF},
-               { "Sarastro the Wise",          30000,  185, 109,  5, 15, RACE_HUMAN},
-               { "Sir Parsival the Pure",           25000,  180, 107,  6, 20, RACE_HIGH_ELF},
-               { "Asenath the Holy",          30000,  185, 109,  5, 15, RACE_HUMAN},
-               { "McKinnon",         10000,   175, 109,  6, 15, RACE_HUMAN},
-               { "Mistress Chastity",         15000,  185, 110,  5, 23, RACE_HIGH_ELF},
-               { "Hashnik the Druid",           25000,  180, 107,  6, 20, RACE_HOBBIT},
-               { "Finak",          30000,  185, 109,  5, 15, RACE_YEEK},
+        { "Ludwig the Humble", 30000, 109, RACE_DWARF },
+        { "Gunnar the Paladin", 30000, 110, RACE_HALF_TROLL },
+        { "Torin the Chosen", 30000, 107, RACE_HIGH_ELF },
+        { "Sarastro the Wise", 30000, 109, RACE_HUMAN },
+        { "Sir Parsival the Pure", 30000, 107, RACE_HIGH_ELF },
+        { "Asenath the Holy", 30000, 109, RACE_HUMAN },
+        { "McKinnon", 30000, 109, RACE_HUMAN },
+        { "Mistress Chastity", 30000, 110, RACE_HIGH_ELF },
+        { "Hashnik the Druid", 30000, 107, RACE_HOBBIT },
+        { "Finak", 30000, 109, RACE_YEEK },
+        { "Krikkik", 30000, 109, RACE_KLACKON },
+        { "Morival the Wild", 30000, 110, RACE_ELF },
+        { "Hoshak the Dark", 30000, 107, RACE_IMP },
+        { "Atal the Wise", 30000, 109, RACE_HUMAN },
+        { "Ibenidd the Chaste", 30000, 109, RACE_HUMAN },
+        { "Eridish", 30000, 110, RACE_HALF_TROLL },
+        { "Vrudush the Shaman", 30000, 107, RACE_HALF_OGRE },
+        { "Haob the Berserker", 30000, 109, RACE_BARBARIAN },
+        { "Proogdish the Youthfull", 30000, 109, RACE_HALF_OGRE },
+        { "Lumwise the Mad", 30000, 110, RACE_YEEK },
+        { "Muirt the Virtuous", 30000, 107, RACE_KOBOLD },
+        { "Dardobard the Weak", 30000, 109, RACE_SPECTRE },
+        { "Ludwig the Humble", 30000, 109, RACE_DWARF },
+        { "Gunnar the Paladin", 30000, 110, RACE_HALF_TROLL },
+        { "Torin the Chosen", 30000, 107, RACE_HIGH_ELF },
+        { "Sarastro the Wise", 30000, 109, RACE_HUMAN },
+        { "Sir Parsival the Pure", 30000, 107, RACE_HIGH_ELF },
+        { "Asenath the Holy", 30000, 109, RACE_HUMAN },
+        { "McKinnon", 30000, 109, RACE_HUMAN },
+        { "Mistress Chastity", 30000, 110, RACE_HIGH_ELF },
+        { "Hashnik the Druid", 30000, 107, RACE_HOBBIT },
+        { "Finak", 30000, 109, RACE_YEEK },
 #endif
-       },
-       {
-               /* Alchemist - 26 unique names */
+    },
+    {
+        /* Alchemist - 26 unique names */
 #ifdef JP
-               { "化学者マウザー",             10000,  190,  111,   5,   8,  RACE_HALF_ELF},
-               { "カオスのウィズル",   10000,  190,  110,   6,   8,  RACE_HOBBIT},
-               { "強欲ミダス",              15000,  200,  116,   6,   9,  RACE_GNOME},
-               { "貧弱ジャ=ファー",                   15000,  220,  111,   4,   9,  RACE_ELF},/*FIRST*/
-               { "カカルラカカル",           15000,  200, 116,  6,  9, RACE_KLACKON},
-               { "錬金術師ジャル=エス",       15000,  220, 111,  4,  9, RACE_ELF},
-               { "用心深いファネラス",         10000,  190, 111,  5,  8, RACE_DWARF},
-               { "キチガイのルンシー",         10000,  190, 110,  6,  8, RACE_HUMAN},
-               { "グランブルワース",           15000,  200, 116,  6,  9, RACE_GNOME},
-               { "フリッター",       15000,  220, 111,  4,  9, RACE_SPRITE},
-               { "ザリルス",         10000,  190, 111,  5,  8, RACE_HUMAN},
-               { "古きエグバート",         10000,  190, 110,  6,  8, RACE_DWARF},
-               { "誇り高きヴァリンドラ",           15000,  200, 116,  6,  9, RACE_HIGH_ELF},
-               { "錬金術師タエン",       15000,  220, 111,  4,  9, RACE_HUMAN},
-               { "巧言カイド",         10000,  190, 111,  5,  8, RACE_VAMPIRE},
-               { "暗きフリア",         10000,  190, 110,  6,  8, RACE_NIBELUNG},
-               { "質素なドムリ",           15000,  200, 116,  6,  9, RACE_DWARF},
-               { "魔の子ヤァジュッカ",       15000,  220, 111,  4,  9, RACE_IMP},
-               { "薬草師ジェララルドール",         10000,  190, 111,  5,  8, RACE_HIGH_ELF},
-               { "賢者オレラルダン",         10000,  190, 110,  6,  8, RACE_BARBARIAN},
-               { "デモニシストのフゾグロ",           15000,  200, 116,  6,  9, RACE_IMP},
-               { "錬金術師ドゥリアシュ",       15000,  220, 111,  4,  9, RACE_HALF_ORC},
-               { "強者ネリア",         10000,  190, 111,  5,  8, RACE_CYCLOPS},
-               { "辛口リグナス",         10000,  190, 110,  6,  8, RACE_HALF_ORC},
-               { "ティルバ",           15000,  200, 116,  6,  9, RACE_HOBBIT},
-               { "金持ちミリルドリック",       15000,  220, 111,  4,  9, RACE_HUMAN},
+        { "化学者マウザー", 30000, 111, RACE_HALF_ELF },
+        { "カオスのウィズル", 30000, 110, RACE_HOBBIT },
+        { "強欲ミダス", 30000, 116, RACE_GNOME },
+        { "貧弱ジャ=ファー", 30000, 111, RACE_ELF }, /*FIRST*/
+        { "カカルラカカル", 30000, 116, RACE_KLACKON },
+        { "錬金術師ジャル=エス", 30000, 111, RACE_ELF },
+        { "用心深いファネラス", 30000, 111, RACE_DWARF },
+        { "キチガイのルンシー", 30000, 110, RACE_HUMAN },
+        { "グランブルワース", 30000, 116, RACE_GNOME },
+        { "フリッター", 30000, 111, RACE_SPRITE },
+        { "ザリルス", 30000, 111, RACE_HUMAN },
+        { "古きエグバート", 30000, 110, RACE_DWARF },
+        { "誇り高きヴァリンドラ", 30000, 116, RACE_HIGH_ELF },
+        { "錬金術師タエン", 30000, 111, RACE_HUMAN },
+        { "巧言カイド", 30000, 111, RACE_VAMPIRE },
+        { "暗きフリア", 30000, 110, RACE_NIBELUNG },
+        { "質素なドムリ", 30000, 116, RACE_DWARF },
+        { "魔の子ヤァジュッカ", 30000, 111, RACE_IMP },
+        { "薬草師ジェララルドール", 30000, 111, RACE_HIGH_ELF },
+        { "賢者オレラルダン", 30000, 110, RACE_BARBARIAN },
+        { "デモニシストのフゾグロ", 30000, 116, RACE_IMP },
+        { "錬金術師ドゥリアシュ", 30000, 111, RACE_HALF_ORC },
+        { "強者ネリア", 30000, 111, RACE_CYCLOPS },
+        { "辛口リグナス", 30000, 110, RACE_HALF_ORC },
+        { "ティルバ", 30000, 116, RACE_HOBBIT },
+        { "金持ちミリルドリック", 30000, 111, RACE_HUMAN },
 
-               { "科学者マウザー",         10000,  190, 111,  5,  8, RACE_HALF_ELF},
-               { "カオスのウィズル",         10000,  190, 110,  6,  8, RACE_HOBBIT},
-               { "強欲ミダス",           15000,  200, 116,  6,  9, RACE_GNOME},
-               { "錬金術師ジャ=ファー",       15000,  220, 111,  4,  9, RACE_ELF},
-               { "カカルラカカル",           15000,  200, 116,  6,  9, RACE_KLACKON},
-               { "錬金術師ジャル=エス",       15000,  220, 111,  4,  9, RACE_ELF},
+        { "科学者マウザー", 30000, 111, RACE_HALF_ELF },
+        { "カオスのウィズル", 30000, 110, RACE_HOBBIT },
+        { "強欲ミダス", 30000, 116, RACE_GNOME },
+        { "錬金術師ジャ=ファー", 30000, 111, RACE_ELF },
+        { "カカルラカカル", 30000, 116, RACE_KLACKON },
+        { "錬金術師ジャル=エス", 30000, 111, RACE_ELF },
 #else
-               { "Mauser the Chemist",         10000,  190, 111,  5,  8, RACE_HALF_ELF},
-               { "Wizzle the Chaotic",         10000,  190, 110,  6,  8, RACE_HOBBIT},
-               { "Midas the Greedy",           15000,  200, 116,  6,  9, RACE_GNOME},
-               { "Ja-Far the Alchemist",       15000,  220, 111,  4,  9, RACE_ELF},
-               { "Kakalrakakal",           15000,  200, 116,  6,  9, RACE_KLACKON},
-               { "Jal-Eth the Alchemist",       15000,  220, 111,  4,  9, RACE_ELF},
-               { "Fanelath the Cautious",         10000,  190, 111,  5,  8, RACE_DWARF},
-               { "Runcie the Insane",         10000,  190, 110,  6,  8, RACE_HUMAN},
-               { "Grumbleworth",           15000,  200, 116,  6,  9, RACE_GNOME},
-               { "Flitter",       15000,  220, 111,  4,  9, RACE_SPRITE},
-               { "Xarillus",         10000,  190, 111,  5,  8, RACE_HUMAN},
-               { "Egbert the Old",         10000,  190, 110,  6,  8, RACE_DWARF},
-               { "Valindra the Proud",           15000,  200, 116,  6,  9, RACE_HIGH_ELF},
-               { "Taen the Alchemist",       15000,  220, 111,  4,  9, RACE_HUMAN},
-               { "Cayd the Sweet",         10000,  190, 111,  5,  8, RACE_VAMPIRE},
-               { "Fulir the Dark",         10000,  190, 110,  6,  8, RACE_NIBELUNG},
-               { "Domli the Humble",           15000,  200, 116,  6,  9, RACE_DWARF},
-               { "Yaarjukka Demonspawn",       15000,  220, 111,  4,  9, RACE_IMP},
-               { "Gelaraldor the Herbmaster",         10000,  190, 111,  5,  8, RACE_HIGH_ELF},
-               { "Olelaldan the Wise",         10000,  190, 110,  6,  8, RACE_BARBARIAN},
-               { "Fthoglo the Demonicist",           15000,  200, 116,  6,  9, RACE_IMP},
-               { "Dridash the Alchemist",       15000,  220, 111,  4,  9, RACE_HALF_ORC},
-               { "Nelir the Strong",         10000,  190, 111,  5,  8, RACE_CYCLOPS},
-               { "Lignus the Pungent",         10000,  190, 110,  6,  8, RACE_HALF_ORC},
-               { "Tilba",           15000,  200, 116,  6,  9, RACE_HOBBIT},
-               { "Myrildric the Wealthy",       15000,  220, 111,  4,  9, RACE_HUMAN},
+        { "Mauser the Chemist", 30000, 111, RACE_HALF_ELF },
+        { "Wizzle the Chaotic", 30000, 110, RACE_HOBBIT },
+        { "Midas the Greedy", 30000, 116, RACE_GNOME },
+        { "Ja-Far the Alchemist", 30000, 111, RACE_ELF },
+        { "Kakalrakakal", 30000, 116, RACE_KLACKON },
+        { "Jal-Eth the Alchemist", 30000, 111, RACE_ELF },
+        { "Fanelath the Cautious", 30000, 111, RACE_DWARF },
+        { "Runcie the Insane", 30000, 110, RACE_HUMAN },
+        { "Grumbleworth", 30000, 116, RACE_GNOME },
+        { "Flitter", 30000, 111, RACE_SPRITE },
+        { "Xarillus", 30000, 111, RACE_HUMAN },
+        { "Egbert the Old", 30000, 110, RACE_DWARF },
+        { "Valindra the Proud", 30000, 116, RACE_HIGH_ELF },
+        { "Taen the Alchemist", 30000, 111, RACE_HUMAN },
+        { "Cayd the Sweet", 30000, 111, RACE_VAMPIRE },
+        { "Fulir the Dark", 30000, 110, RACE_NIBELUNG },
+        { "Domli the Humble", 30000, 116, RACE_DWARF },
+        { "Yaarjukka Demonspawn", 30000, 111, RACE_IMP },
+        { "Gelaraldor the Herbmaster", 30000, 111, RACE_HIGH_ELF },
+        { "Olelaldan the Wise", 30000, 110, RACE_BARBARIAN },
+        { "Fthoglo the Demonicist", 30000, 116, RACE_IMP },
+        { "Dridash the Alchemist", 30000, 111, RACE_HALF_ORC },
+        { "Nelir the Strong", 30000, 111, RACE_CYCLOPS },
+        { "Lignus the Pungent", 30000, 110, RACE_HALF_ORC },
+        { "Tilba", 30000, 116, RACE_HOBBIT },
+        { "Myrildric the Wealthy", 30000, 111, RACE_HUMAN },
 
-               { "Mauser the Chemist",         10000,  190, 111,  5,  8, RACE_HALF_ELF},
-               { "Wizzle the Chaotic",         10000,  190, 110,  6,  8, RACE_HOBBIT},
-               { "Midas the Greedy",           15000,  200, 116,  6,  9, RACE_GNOME},
-               { "Ja-Far the Alchemist",       15000,  220, 111,  4,  9, RACE_ELF},
-               { "Kakalrakakal",           15000,  200, 116,  6,  9, RACE_KLACKON},
-               { "Jal-Eth the Alchemist",       15000,  220, 111,  4,  9, RACE_ELF},
+        { "Mauser the Chemist", 30000, 111, RACE_HALF_ELF },
+        { "Wizzle the Chaotic", 30000, 110, RACE_HOBBIT },
+        { "Midas the Greedy", 30000, 116, RACE_GNOME },
+        { "Ja-Far the Alchemist", 30000, 111, RACE_ELF },
+        { "Kakalrakakal", 30000, 116, RACE_KLACKON },
+        { "Jal-Eth the Alchemist", 30000, 111, RACE_ELF },
 #endif
-       },
+    },
 
-       {
-               /* Magic Shop - 23 unique names */
-#ifdef JP
-               { "ソーサラーのロ=パン",       20000,  200,  110,   7,   8,  RACE_HALF_ELF},
-               { "偉大なるブガービイ",         20000,  215,  113,   6,  10,  RACE_GNOME},
-               { "イェンダーの魔法使い",     30000,  200,  110,   7,  10,  RACE_HUMAN},
-               { "死霊使いリャク",30000,      175,  110,   5,  11,  RACE_HIGH_ELF},
-               { "魔術師スキドゥニー",        15000,  200, 110,  7,  8, RACE_HALF_ELF},
-               { "幻術師キリア",       30000,  200, 110,  7, 10, RACE_HUMAN},
-               { "死霊術師ニッキ",       30000,  175, 110,  5, 11, RACE_DARK_ELF},
-               { "ソロストラン",        15000,  200, 110,  7,  8, RACE_SPRITE},
-               { "烏賊口アチシェ",         20000,  215, 113,  6, 10, RACE_MIND_FLAYER},
-               { "貴族のカザ",       30000,  200, 110,  7, 10, RACE_HIGH_ELF},
-               { "暗きファジル",       30000,  175, 110,  5, 11, RACE_DARK_ELF},
-               { "偉大なるケルドーン",        15000,  200, 110,  7,  8, RACE_DWARF},
-               { "フィランスロプス",         20000,  215, 113,  6, 10, RACE_HOBBIT},
-               { "魔女のアグナー",       30000,  200, 110,  7, 10, RACE_HUMAN},
-               { "死霊術師ビュリアンス",       30000,  175, 110,  5, 11, RACE_BEASTMAN},
-               { "ハイメイジのヴイラク",        15000,  200, 110,  7,  8, RACE_BEASTMAN},
-               { "知恵者マディッシュ",         20000,  215, 113,  6, 10, RACE_BEASTMAN},
-               { "ファレブリンボール",       30000,  200, 110,  7, 10, RACE_HIGH_ELF},
-               { "陰険フェリル=ガンド",       30000,  175, 110,  5, 11, RACE_DARK_ELF},
-               { "呪術師サレゴード",        15000,  200, 110,  7,  8, RACE_BARBARIAN},
-               { "神秘家クトゥアロス",         20000,  215, 113,  6, 10, RACE_MIND_FLAYER},
-               { "幻術師イベリ",       30000,  200, 110,  7, 10, RACE_SKELETON},
-               { "死霊術師ヘトー",       30000,  175, 110,  5, 11, RACE_YEEK},
-               { "魔術師ロ=パン",        20000,  200, 110,  7,  8, RACE_HALF_ELF},
-               { "偉大なるブガービイ",         20000,  215, 113,  6, 10, RACE_GNOME},
-               { "イェンダーの魔法使い",       30000,  200, 110,  7, 10, RACE_HUMAN},
-               { "死霊術師リャク",       30000,  175, 110,  5, 11, RACE_DARK_ELF},
-               { "魔術師スキドゥニー",        15000,  200, 110,  7,  8, RACE_HALF_ELF},
-               { "幻術師キリア",       30000,  200, 110,  7, 10, RACE_HUMAN},
-               { "死霊術師ニッキ",       30000,  175, 110,  5, 11, RACE_DARK_ELF},
-               { "ソロストラン",        15000,  200, 110,  7,  8, RACE_SPRITE},
-               { "烏賊口アチシェ",         20000,  215, 113,  6, 10, RACE_MIND_FLAYER},
-#else
-               { "Lo Pan the Sorcerer",        20000,  200, 110,  7,  8, RACE_HALF_ELF},
-               { "Buggerby the Great",         20000,  215, 113,  6, 10, RACE_GNOME},
-               { "The Wizard of Yendor",       30000,  200, 110,  7, 10, RACE_HUMAN},
-               { "Rjak the Necromancer",       30000,  175, 110,  5, 11, RACE_DARK_ELF},
-               { "Skidney the Sorcerer",        15000,  200, 110,  7,  8, RACE_HALF_ELF},
-               { "Kyria the Illusionist",       30000,  200, 110,  7, 10, RACE_HUMAN},
-               { "Nikki the Necromancer",       30000,  175, 110,  5, 11, RACE_DARK_ELF},
-               { "Solostoran",        15000,  200, 110,  7,  8, RACE_SPRITE},
-               { "Achshe the Tentacled",         20000,  215, 113,  6, 10, RACE_MIND_FLAYER},
-               { "Kaza the Noble",       30000,  200, 110,  7, 10, RACE_HIGH_ELF},
-               { "Fazzil the Dark",       30000,  175, 110,  5, 11, RACE_DARK_ELF},
-               { "Keldorn the Grand",        15000,  200, 110,  7,  8, RACE_DWARF},
-               { "Philanthropus",         20000,  215, 113,  6, 10, RACE_HOBBIT},
-               { "Agnar the Enchantress",       30000,  200, 110,  7, 10, RACE_HUMAN},
-               { "Buliance the Necromancer",       30000,  175, 110,  5, 11, RACE_BEASTMAN},
-               { "Vuirak the High-Mage",        15000,  200, 110,  7,  8, RACE_BEASTMAN},
-               { "Madish the Smart",         20000,  215, 113,  6, 10, RACE_BEASTMAN},
-               { "Falebrimbor",       30000,  200, 110,  7, 10, RACE_HIGH_ELF},
-               { "Felil-Gand the Subtle",       30000,  175, 110,  5, 11, RACE_DARK_ELF},
-               { "Thalegord the Shaman",        15000,  200, 110,  7,  8, RACE_BARBARIAN},
-               { "Cthoaloth the Mystic",         20000,  215, 113,  6, 10, RACE_MIND_FLAYER},
-               { "Ibeli the Illusionist",       30000,  200, 110,  7, 10, RACE_SKELETON},
-               { "Heto the Necromancer",       30000,  175, 110,  5, 11, RACE_YEEK},
-               { "Lo Pan the Sorcerer",        20000,  200, 110,  7,  8, RACE_HALF_ELF},
-               { "Buggerby the Great",         20000,  215, 113,  6, 10, RACE_GNOME},
-               { "The Wizard of Yendor",       30000,  200, 110,  7, 10, RACE_HUMAN},
-               { "Rjak the Necromancer",       30000,  175, 110,  5, 11, RACE_DARK_ELF},
-               { "Skidney the Sorcerer",        15000,  200, 110,  7,  8, RACE_HALF_ELF},
-               { "Kyria the Illusionist",       30000,  200, 110,  7, 10, RACE_HUMAN},
-               { "Nikki the Necromancer",       30000,  175, 110,  5, 11, RACE_DARK_ELF},
-               { "Solostoran",        15000,  200, 110,  7,  8, RACE_SPRITE},
-               { "Achshe the Tentacled",         20000,  215, 113,  6, 10, RACE_MIND_FLAYER},
-#endif
-       },
-       {
-               /* Black Market - 32 unique names */
+    {
+        /* Magic Shop - 23 unique names */
 #ifdef JP
-               { "ガリー=ギガズ",            20000,  250,  150,  10,   5,  RACE_HALF_TROLL},
-               { "ゴブリンのヒストーア",       20000,  250,  150,  10,   5,  RACE_HALF_ORC},
-               { "フェレンギ人クアーク",           30000,  250,  150,  10,   5,  RACE_HUMAN},
-               { "公正なる(?)トッピ",                     30000,  250,  150,  10,   5,  RACE_ELF},
-               { "死人ヴァッサ",             20000,  250, 150, 10,  5, RACE_ZOMBIE},
-               { "裏切り者カイン",          20000,  250, 150, 10,  5, RACE_VAMPIRE},
-               { "ブボニカス",          30000,  250, 150, 10,  5, RACE_BEASTMAN},
-               { "コープスライト",           30000,  250, 150, 10,  5, RACE_SPECTRE},
-               { "血に飢えしパリッシュ",                 20000,  250, 150, 10,  5, RACE_VAMPIRE},
-               { "ヴァイル",          20000,  250, 150, 10,  5, RACE_SKELETON},
-               { "信頼のプレンティス",          30000,  250, 150, 10,  5, RACE_SKELETON},
-               { "人間殺しのグリエラ",           30000,  250, 150, 10,  5, RACE_IMP},
-               { "エンジェル",                 20000,  250, 150, 10,  5, RACE_VAMPIRE},
-               { "水膨れフロツァム",          20000,  250, 150, 10,  5, RACE_ZOMBIE},
-               { "ニーヴァル",          30000,  250, 150, 10,  5, RACE_VAMPIRE},
-               { "明るいアナスタシア",           30000,  250, 150, 10,  5, RACE_SPECTRE},
-               { "死霊術師チャリティー", 20000,  250, 150, 10,  5, RACE_DARK_ELF},
-               { "ボクサーのプグナシオス",          20000,  250, 150, 10,  5, RACE_HALF_ORC},
-               { "幸運なフットソア",          30000,  250, 150, 10,  5, RACE_BEASTMAN},
-               { "光指のシドリア",           30000,  250, 150, 10,  5, RACE_HUMAN},
-               { "手品師リアソー",                 20000,  250, 150, 10,  5, RACE_HOBBIT},
-               { "やりくり上手のジャナッカ",          20000,  250, 150, 10,  5, RACE_GNOME},
-               { "悪党シーナ",          30000,  250, 150, 10,  5, RACE_GNOME},
-               { "大爪アルニッキ",           30000,  250, 150, 10,  5, RACE_DRACONIAN},
-               { "貧乏チャエアンド",                 20000,  250, 150, 10,  5, RACE_HUMAN},
-               { "山賊アファードーフ",          20000,  250, 150, 10,  5, RACE_BARBARIAN},
-               { "強欲ラザクスル",          30000,  250, 150, 10,  5, RACE_MIND_FLAYER},
-               { "ファラレウィン",           30000,  250, 150, 10,  5, RACE_SPRITE},
-               { "しわしわヴォスール",                 20000,  250, 150, 10,  5, RACE_NIBELUNG},
-               { "ハンサムなアラオード",          20000,  250, 150, 10,  5, RACE_AMBERITE},
-               { "負け犬セラドフリド",          30000,  250, 150, 10,  5, RACE_HUMAN},
-               { "片足のエルーロ",           30000,  250, 150, 10,  5, RACE_HALF_OGRE},
+        { "ソーサラーのロ=パン", 30000, 110, RACE_HALF_ELF },
+        { "偉大なるブガービイ", 30000, 113, RACE_GNOME },
+        { "イェンダーの魔法使い", 30000, 110, RACE_HUMAN },
+        { "死霊使いリャク", 30000, 110, RACE_HIGH_ELF },
+        { "魔術師スキドゥニー", 30000, 110, RACE_HALF_ELF },
+        { "幻術師キリア", 30000, 110, RACE_HUMAN },
+        { "死霊術師ニッキ", 30000, 110, RACE_DARK_ELF },
+        { "ソロストラン", 30000, 110, RACE_SPRITE },
+        { "烏賊口アチシェ", 30000, 113, RACE_MIND_FLAYER },
+        { "貴族のカザ", 30000, 110, RACE_HIGH_ELF },
+        { "暗きファジル", 30000, 110, RACE_DARK_ELF },
+        { "偉大なるケルドーン", 30000, 110, RACE_DWARF },
+        { "フィランスロプス", 30000, 113, RACE_HOBBIT },
+        { "魔女のアグナー", 30000, 110, RACE_HUMAN },
+        { "死霊術師ビュリアンス", 30000, 110, RACE_BEASTMAN },
+        { "ハイメイジのヴイラク", 30000, 110, RACE_BEASTMAN },
+        { "知恵者マディッシュ", 30000, 113, RACE_BEASTMAN },
+        { "ファレブリンボール", 30000, 110, RACE_HIGH_ELF },
+        { "陰険フェリル=ガンド", 30000, 110, RACE_DARK_ELF },
+        { "呪術師サレゴード", 30000, 110, RACE_BARBARIAN },
+        { "神秘家クトゥアロス", 30000, 113, RACE_MIND_FLAYER },
+        { "幻術師イベリ", 30000, 110, RACE_SKELETON },
+        { "死霊術師ヘトー", 30000, 110, RACE_YEEK },
+        { "魔術師ロ=パン", 30000, 110, RACE_HALF_ELF },
+        { "偉大なるブガービイ", 30000, 113, RACE_GNOME },
+        { "イェンダーの魔法使い", 30000, 110, RACE_HUMAN },
+        { "死霊術師リャク", 30000, 110, RACE_DARK_ELF },
+        { "魔術師スキドゥニー", 30000, 110, RACE_HALF_ELF },
+        { "幻術師キリア", 30000, 110, RACE_HUMAN },
+        { "死霊術師ニッキ", 30000, 110, RACE_DARK_ELF },
+        { "ソロストラン", 30000, 110, RACE_SPRITE },
+        { "烏賊口アチシェ", 30000, 113, RACE_MIND_FLAYER },
 #else
-               { "Gary Gygaz",                 20000,  250, 150, 10,  5, RACE_HALF_TROLL},
-               { "Histor the Goblin",          20000,  250, 150, 10,  5, RACE_HALF_ORC},
-               { "Quark the Ferengi",          30000,  250, 150, 10,  5, RACE_DWARF},
-               { "Topi the Fair(?)",           30000,  250, 150, 10,  5, RACE_HUMAN},
-               { "Vhassa the Dead",             20000,  250, 150, 10,  5, RACE_ZOMBIE},
-               { "Kyn the Treacherous",          20000,  250, 150, 10,  5, RACE_VAMPIRE},
-               { "Bubonicus",          30000,  250, 150, 10,  5, RACE_BEASTMAN},
-               { "Corpselight",           30000,  250, 150, 10,  5, RACE_SPECTRE},
-               { "Parrish the Bloodthirsty",                 20000,  250, 150, 10,  5, RACE_VAMPIRE},
-               { "Vile",          20000,  250, 150, 10,  5, RACE_SKELETON},
-               { "Prentice the Trusted",          30000,  250, 150, 10,  5, RACE_SKELETON},
-               { "Griella Humanslayer",           30000,  250, 150, 10,  5, RACE_IMP},
-               { "Angel",                 20000,  250, 150, 10,  5, RACE_VAMPIRE},
-               { "Flotsam the Bloated",          20000,  250, 150, 10,  5, RACE_ZOMBIE},
-               { "Nieval",          30000,  250, 150, 10,  5, RACE_VAMPIRE},
-               { "Anastasia the Luminous",           30000,  250, 150, 10,  5, RACE_SPECTRE},
-               { "Charity the Necromancer", 20000,  250, 150, 10,  5, RACE_DARK_ELF},
-               { "Pugnacious the Pugilist",          20000,  250, 150, 10,  5, RACE_HALF_ORC},
-               { "Footsore the Lucky",          30000,  250, 150, 10,  5, RACE_BEASTMAN},
-               { "Sidria Lighfingered",           30000,  250, 150, 10,  5, RACE_HUMAN},
-               { "Riatho the Juggler",                 20000,  250, 150, 10,  5, RACE_HOBBIT},
-               { "Janaaka the Shifty",          20000,  250, 150, 10,  5, RACE_GNOME},
-               { "Cina the Rogue",          30000,  250, 150, 10,  5, RACE_GNOME},
-               { "Arunikki Greatclaw",           30000,  250, 150, 10,  5, RACE_DRACONIAN},
-               { "Chaeand the Poor",                 20000,  250, 150, 10,  5, RACE_HUMAN},
-               { "Afardorf the Brigand",          20000,  250, 150, 10,  5, RACE_BARBARIAN},
-               { "Lathaxl the Greedy",          30000,  250, 150, 10,  5, RACE_MIND_FLAYER},
-               { "Falarewyn",           30000,  250, 150, 10,  5, RACE_SPRITE},
-               { "Vosur the Wrinkled",                 20000,  250, 150, 10,  5, RACE_NIBELUNG},
-               { "Araord the Handsome",          20000,  250, 150, 10,  5, RACE_AMBERITE},
-               { "Theradfrid the Loser",          30000,  250, 150, 10,  5, RACE_HUMAN},
-               { "One-Legged Eroolo",           30000,  250, 150, 10,  5, RACE_HALF_OGRE},
+        { "Lo Pan the Sorcerer", 30000, 110, RACE_HALF_ELF },
+        { "Buggerby the Great", 30000, 113, RACE_GNOME },
+        { "The Wizard of Yendor", 30000, 110, RACE_HUMAN },
+        { "Rjak the Necromancer", 30000, 110, RACE_DARK_ELF },
+        { "Skidney the Sorcerer", 30000, 110, RACE_HALF_ELF },
+        { "Kyria the Illusionist", 30000, 110, RACE_HUMAN },
+        { "Nikki the Necromancer", 30000, 110, RACE_DARK_ELF },
+        { "Solostoran", 30000, 110, RACE_SPRITE },
+        { "Achshe the Tentacled", 30000, 113, RACE_MIND_FLAYER },
+        { "Kaza the Noble", 30000, 110, RACE_HIGH_ELF },
+        { "Fazzil the Dark", 30000, 110, RACE_DARK_ELF },
+        { "Keldorn the Grand", 30000, 110, RACE_DWARF },
+        { "Philanthropus", 30000, 113, RACE_HOBBIT },
+        { "Agnar the Enchantress", 30000, 110, RACE_HUMAN },
+        { "Buliance the Necromancer", 30000, 110, RACE_BEASTMAN },
+        { "Vuirak the High-Mage", 30000, 110, RACE_BEASTMAN },
+        { "Madish the Smart", 30000, 113, RACE_BEASTMAN },
+        { "Falebrimbor", 30000, 110, RACE_HIGH_ELF },
+        { "Felil-Gand the Subtle", 30000, 110, RACE_DARK_ELF },
+        { "Thalegord the Shaman", 30000, 110, RACE_BARBARIAN },
+        { "Cthoaloth the Mystic", 30000, 113, RACE_MIND_FLAYER },
+        { "Ibeli the Illusionist", 30000, 110, RACE_SKELETON },
+        { "Heto the Necromancer", 30000, 110, RACE_YEEK },
+        { "Lo Pan the Sorcerer", 30000, 110, RACE_HALF_ELF },
+        { "Buggerby the Great", 30000, 113, RACE_GNOME },
+        { "The Wizard of Yendor", 30000, 110, RACE_HUMAN },
+        { "Rjak the Necromancer", 30000, 110, RACE_DARK_ELF },
+        { "Skidney the Sorcerer", 30000, 110, RACE_HALF_ELF },
+        { "Kyria the Illusionist", 30000, 110, RACE_HUMAN },
+        { "Nikki the Necromancer", 30000, 110, RACE_DARK_ELF },
+        { "Solostoran", 30000, 110, RACE_SPRITE },
+        { "Achshe the Tentacled", 30000, 113, RACE_MIND_FLAYER },
 #endif
-       },
-       {
-               /* Home */
+    },
+    {
+        /* Black Market - 32 unique names */
 #ifdef JP
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
-               { "我が家",                          0,      100, 100,  0, 99, 99},
+        { "ガリー=ギガズ", 60000, 150, RACE_HALF_TROLL },
+        { "ゴブリンのヒストーア", 60000, 150, RACE_HALF_ORC },
+        { "フェレンギ人クアーク", 60000, 150, RACE_HUMAN },
+        { "公正なる(?)トッピ", 60000, 150, RACE_ELF },
+        { "死人ヴァッサ", 60000, 150, RACE_ZOMBIE },
+        { "裏切り者カイン", 60000, 150, RACE_VAMPIRE },
+        { "ブボニカス", 60000, 150, RACE_BEASTMAN },
+        { "コープスライト", 60000, 150, RACE_SPECTRE },
+        { "血に飢えしパリッシュ", 60000, 150, RACE_VAMPIRE },
+        { "ヴァイル", 60000, 150, RACE_SKELETON },
+        { "信頼のプレンティス", 60000, 150, RACE_SKELETON },
+        { "人間殺しのグリエラ", 60000, 150, RACE_IMP },
+        { "エンジェル", 60000, 150, RACE_VAMPIRE },
+        { "水膨れフロツァム", 60000, 150, RACE_ZOMBIE },
+        { "ニーヴァル", 60000, 150, RACE_VAMPIRE },
+        { "明るいアナスタシア", 60000, 150, RACE_SPECTRE },
+        { "死霊術師チャリティー", 60000, 150, RACE_DARK_ELF },
+        { "ボクサーのプグナシオス", 60000, 150, RACE_HALF_ORC },
+        { "幸運なフットソア", 60000, 150, RACE_BEASTMAN },
+        { "光指のシドリア", 60000, 150, RACE_HUMAN },
+        { "手品師リアソー", 60000, 150, RACE_HOBBIT },
+        { "やりくり上手のジャナッカ", 60000, 150, RACE_GNOME },
+        { "悪党シーナ", 60000, 150, RACE_GNOME },
+        { "大爪アルニッキ", 60000, 150, RACE_DRACONIAN },
+        { "貧乏チャエアンド", 60000, 150, RACE_HUMAN },
+        { "山賊アファードーフ", 60000, 150, RACE_BARBARIAN },
+        { "強欲ラザクスル", 60000, 150, RACE_MIND_FLAYER },
+        { "ファラレウィン", 60000, 150, RACE_SPRITE },
+        { "しわしわヴォスール", 60000, 150, RACE_NIBELUNG },
+        { "ハンサムなアラオード", 60000, 150, RACE_AMBERITE },
+        { "負け犬セラドフリド", 60000, 150, RACE_HUMAN },
+        { "片足のエルーロ", 60000, 150, RACE_HALF_OGRE },
 #else
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
-               { "Your home",                          0,      100, 100,  0, 99, 99},
+        { "Gary Gygaz", 60000, 150, RACE_HALF_TROLL },
+        { "Histor the Goblin", 60000, 150, RACE_HALF_ORC },
+        { "Quark the Ferengi", 60000, 150, RACE_DWARF },
+        { "Topi the Fair(?)", 60000, 150, RACE_HUMAN },
+        { "Vhassa the Dead", 60000, 150, RACE_ZOMBIE },
+        { "Kyn the Treacherous", 60000, 150, RACE_VAMPIRE },
+        { "Bubonicus", 60000, 150, RACE_BEASTMAN },
+        { "Corpselight", 60000, 150, RACE_SPECTRE },
+        { "Parrish the Bloodthirsty", 60000, 150, RACE_VAMPIRE },
+        { "Vile", 60000, 150, RACE_SKELETON },
+        { "Prentice the Trusted", 60000, 150, RACE_SKELETON },
+        { "Griella Humanslayer", 60000, 150, RACE_IMP },
+        { "Angel", 60000, 150, RACE_VAMPIRE },
+        { "Flotsam the Bloated", 60000, 150, RACE_ZOMBIE },
+        { "Nieval", 60000, 150, RACE_VAMPIRE },
+        { "Anastasia the Luminous", 60000, 150, RACE_SPECTRE },
+        { "Charity the Necromancer", 60000, 150, RACE_DARK_ELF },
+        { "Pugnacious the Pugilist", 60000, 150, RACE_HALF_ORC },
+        { "Footsore the Lucky", 60000, 150, RACE_BEASTMAN },
+        { "Sidria Lighfingered", 60000, 150, RACE_HUMAN },
+        { "Riatho the Juggler", 60000, 150, RACE_HOBBIT },
+        { "Janaaka the Shifty", 60000, 150, RACE_GNOME },
+        { "Cina the Rogue", 60000, 150, RACE_GNOME },
+        { "Arunikki Greatclaw", 60000, 150, RACE_DRACONIAN },
+        { "Chaeand the Poor", 60000, 150, RACE_HUMAN },
+        { "Afardorf the Brigand", 60000, 150, RACE_BARBARIAN },
+        { "Lathaxl the Greedy", 60000, 150, RACE_MIND_FLAYER },
+        { "Falarewyn", 60000, 150, RACE_SPRITE },
+        { "Vosur the Wrinkled", 60000, 150, RACE_NIBELUNG },
+        { "Araord the Handsome", 60000, 150, RACE_AMBERITE },
+        { "Theradfrid the Loser", 60000, 150, RACE_HUMAN },
+        { "One-Legged Eroolo", 60000, 150, RACE_HALF_OGRE },
 #endif
+    },
+    {
+        /* Home */
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+        { _("我が家", "Your home"), 0, 100, 99 },
+    },
 
-       },
-
-       {
-               /* Bookstore - 21 unique names */
+    {
+        /* Bookstore - 21 unique names */
 #ifdef JP
-               { "強欲ドラフ", 10000, 175, 108, 4, 12, RACE_HUMAN},
-               { "賢者オドナー", 15000, 120, 105, 6, 16, RACE_HIGH_ELF},
-               { "中立のガンダー", 25000, 120, 110, 7, 19, RACE_DARK_ELF},
-               { "忍耐の人ロ=シャ", 30000, 140, 105, 6, 12, RACE_ELF},
-               { "ランドルフ・カーター", 15000, 175, 108, 4, 12, RACE_HUMAN},
-               { "隼のサライ", 15000, 175, 108, 4, 12, RACE_HUMAN},
-               { "千里眼ボドリル", 20000, 120, 105, 6, 16, RACE_HIGH_ELF},
-               { "沈黙のヴェオロイン", 25000, 120, 110, 7, 19, RACE_ZOMBIE},
-               { "学者のヴァンシラス", 30000, 140, 105, 6, 12, RACE_MIND_FLAYER},
-               { "物書きオセイン", 15000, 175, 108, 4, 12, RACE_SKELETON},
-               { "本の虫オルヴァー", 20000, 120, 105, 6, 16, RACE_VAMPIRE},
-               { "浅井墓男", 25000, 120, 110, 7, 19, RACE_ZOMBIE},
-               { "デスマスク", 30000, 140, 105, 6, 12, RACE_ZOMBIE},
-               { "学者のアスーヌ", 15000, 175, 108, 4, 12, RACE_MIND_FLAYER},
-               { "死人のプリランド", 20000, 120, 105, 6, 16, RACE_ZOMBIE},
-               { "鉄のロナール", 25000, 120, 110, 7, 19, RACE_GOLEM},
+        { "強欲ドラフ", 30000, 108, RACE_HUMAN },
+        { "賢者オドナー", 30000, 105, RACE_HIGH_ELF },
+        { "中立のガンダー", 30000, 110, RACE_DARK_ELF },
+        { "忍耐の人ロ=シャ", 30000, 105, RACE_ELF },
+        { "ランドルフ・カーター", 30000, 108, RACE_HUMAN },
+        { "隼のサライ", 30000, 108, RACE_HUMAN },
+        { "千里眼ボドリル", 30000, 105, RACE_HIGH_ELF },
+        { "沈黙のヴェオロイン", 30000, 110, RACE_ZOMBIE },
+        { "学者のヴァンシラス", 30000, 105, RACE_MIND_FLAYER },
+        { "物書きオセイン", 30000, 108, RACE_SKELETON },
+        { "本の虫オルヴァー", 30000, 105, RACE_VAMPIRE },
+        { "浅井墓男", 30000, 110, RACE_ZOMBIE },
+        { "デスマスク", 30000, 105, RACE_ZOMBIE },
+        { "学者のアスーヌ", 30000, 108, RACE_MIND_FLAYER },
+        { "死人のプリランド", 30000, 105, RACE_ZOMBIE },
+        { "鉄のロナール", 30000, 110, RACE_GOLEM },
 #else
-               { "Dolaf the Greedy", 10000, 175, 108, 4, 12, RACE_HUMAN},
-               { "Odnar the Sage", 15000, 120, 105, 6, 16, RACE_HIGH_ELF},
-               { "Gandar the Neutral", 25000, 120, 110, 7, 19, RACE_DARK_ELF},
-               { "Ro-sha the Patient", 30000, 140, 105, 6, 12, RACE_ELF},
-               { "Randolph Carter", 15000, 175, 108, 4, 12, RACE_HUMAN},
-               { "Sarai the Swift", 15000, 175, 108, 4, 12, RACE_HUMAN},
-               { "Bodril the Seer", 20000, 120, 105, 6, 16, RACE_HIGH_ELF},
-               { "Veloin the Quiet", 25000, 120, 110, 7, 19, RACE_ZOMBIE},
-               { "Vanthylas the Learned", 30000, 140, 105, 6, 12, RACE_MIND_FLAYER},
-               { "Ossein the Literate", 15000, 175, 108, 4, 12, RACE_SKELETON},
-               { "Olvar Bookworm", 20000, 120, 105, 6, 16, RACE_VAMPIRE},
-               { "Shallowgrave", 25000, 120, 110, 7, 19, RACE_ZOMBIE},
-               { "Death Mask", 30000, 140, 105, 6, 12, RACE_ZOMBIE},
-               { "Asuunu the Learned", 15000, 175, 108, 4, 12, RACE_MIND_FLAYER},
-               { "Prirand the Dead", 20000, 120, 105, 6, 16, RACE_ZOMBIE},
-               { "Ronar the Iron", 25000, 120, 110, 7, 19, RACE_GOLEM},
+        { "Dolaf the Greedy", 30000, 108, RACE_HUMAN },
+        { "Odnar the Sage", 30000, 105, RACE_HIGH_ELF },
+        { "Gandar the Neutral", 30000, 110, RACE_DARK_ELF },
+        { "Ro-sha the Patient", 30000, 105, RACE_ELF },
+        { "Randolph Carter", 30000, 108, RACE_HUMAN },
+        { "Sarai the Swift", 30000, 108, RACE_HUMAN },
+        { "Bodril the Seer", 30000, 105, RACE_HIGH_ELF },
+        { "Veloin the Quiet", 30000, 110, RACE_ZOMBIE },
+        { "Vanthylas the Learned", 30000, 105, RACE_MIND_FLAYER },
+        { "Ossein the Literate", 30000, 108, RACE_SKELETON },
+        { "Olvar Bookworm", 30000, 105, RACE_VAMPIRE },
+        { "Shallowgrave", 30000, 110, RACE_ZOMBIE },
+        { "Death Mask", 30000, 105, RACE_ZOMBIE },
+        { "Asuunu the Learned", 30000, 108, RACE_MIND_FLAYER },
+        { "Prirand the Dead", 30000, 105, RACE_ZOMBIE },
+        { "Ronar the Iron", 30000, 110, RACE_GOLEM },
 #endif
 #ifdef JP
-               { "ガリル=ガミル", 30000, 140, 105, 6, 12, RACE_ELF},
-               { "本食いローバグ", 15000, 175, 108, 4, 12, RACE_KOBOLD},
-               { "キリアリキーク", 20000, 120, 105, 6, 16, RACE_KLACKON},
-               { "静かなるリリン", 25000, 120, 110, 7, 19, RACE_DWARF},
-               { "王者イサング", 30000, 140, 105, 6, 12, RACE_HIGH_ELF},
-               { "強欲ドラフ", 10000, 175, 108, 4, 12, RACE_HUMAN},
-               { "賢者オドナー", 15000, 120, 105, 6, 16, RACE_HIGH_ELF},
-               { "中立のガンダー", 25000, 120, 110, 7, 19, RACE_DARK_ELF},
-               { "忍耐の人ロ=シャ", 30000, 140, 105, 6, 12, RACE_ELF},
-               { "ランドルフ・カーター", 15000, 175, 108, 4, 12, RACE_HUMAN},
-               { "隼サライ", 15000, 175, 108, 4, 12, RACE_HUMAN},
-               { "千里眼ボドリル", 20000, 120, 105, 6, 16, RACE_HIGH_ELF},
-               { "沈黙のヴェオロイン", 25000, 120, 110, 7, 19, RACE_ZOMBIE},
-               { "学者のヴァンシラス", 30000, 140, 105, 6, 12, RACE_MIND_FLAYER},
-               { "物書きオセイン", 15000, 175, 108, 4, 12, RACE_SKELETON},
-               { "本の虫オルヴァー", 20000, 120, 105, 6, 16, RACE_VAMPIRE},
+        { "ガリル=ガミル", 30000, 105, RACE_ELF },
+        { "本食いローバグ", 30000, 108, RACE_KOBOLD },
+        { "キリアリキーク", 30000, 105, RACE_KLACKON },
+        { "静かなるリリン", 30000, 110, RACE_DWARF },
+        { "王者イサング", 30000, 105, RACE_HIGH_ELF },
+        { "強欲ドラフ", 30000, 108, RACE_HUMAN },
+        { "賢者オドナー", 30000, 105, RACE_HIGH_ELF },
+        { "中立のガンダー", 30000, 110, RACE_DARK_ELF },
+        { "忍耐の人ロ=シャ", 30000, 105, RACE_ELF },
+        { "ランドルフ・カーター", 30000, 108, RACE_HUMAN },
+        { "隼サライ", 30000, 108, RACE_HUMAN },
+        { "千里眼ボドリル", 30000, 105, RACE_HIGH_ELF },
+        { "沈黙のヴェオロイン", 30000, 110, RACE_ZOMBIE },
+        { "学者のヴァンシラス", 30000, 105, RACE_MIND_FLAYER },
+        { "物書きオセイン", 30000, 108, RACE_SKELETON },
+        { "本の虫オルヴァー", 30000, 105, RACE_VAMPIRE },
 #else
-               { "Galil-Gamir", 30000, 140, 105, 6, 12, RACE_ELF},
-               { "Rorbag Book-Eater", 15000, 175, 108, 4, 12, RACE_KOBOLD},
-               { "Kiriarikirk", 20000, 120, 105, 6, 16, RACE_KLACKON},
-               { "Rilin the Quiet", 25000, 120, 110, 7, 19, RACE_DWARF},
-               { "Isung the Lord", 30000, 140, 105, 6, 12, RACE_HIGH_ELF},
-               { "Dolaf the Greedy", 10000, 175, 108, 4, 12, RACE_HUMAN},
-               { "Odnar the Sage", 15000, 120, 105, 6, 16, RACE_HIGH_ELF},
-               { "Gandar the Neutral", 25000, 120, 110, 7, 19, RACE_DARK_ELF},
-               { "Ro-sha the Patient", 30000, 140, 105, 6, 12, RACE_ELF},
-               { "Randolph Carter", 15000, 175, 108, 4, 12, RACE_HUMAN},
-               { "Sarai the Swift", 15000, 175, 108, 4, 12, RACE_HUMAN},
-               { "Bodril the Seer", 20000, 120, 105, 6, 16, RACE_HIGH_ELF},
-               { "Veloin the Quiet", 25000, 120, 110, 7, 19, RACE_ZOMBIE},
-               { "Vanthylas the Learned", 30000, 140, 105, 6, 12, RACE_MIND_FLAYER},
-               { "Ossein the Literate", 15000, 175, 108, 4, 12, RACE_SKELETON},
-               { "Olvar Bookworm", 20000, 120, 105, 6, 16, RACE_VAMPIRE},
+        { "Galil-Gamir", 30000, 105, RACE_ELF },
+        { "Rorbag Book-Eater", 30000, 108, RACE_KOBOLD },
+        { "Kiriarikirk", 30000, 105, RACE_KLACKON },
+        { "Rilin the Quiet", 30000, 110, RACE_DWARF },
+        { "Isung the Lord", 30000, 105, RACE_HIGH_ELF },
+        { "Dolaf the Greedy", 30000, 108, RACE_HUMAN },
+        { "Odnar the Sage", 30000, 105, RACE_HIGH_ELF },
+        { "Gandar the Neutral", 30000, 110, RACE_DARK_ELF },
+        { "Ro-sha the Patient", 30000, 105, RACE_ELF },
+        { "Randolph Carter", 30000, 108, RACE_HUMAN },
+        { "Sarai the Swift", 30000, 108, RACE_HUMAN },
+        { "Bodril the Seer", 30000, 105, RACE_HIGH_ELF },
+        { "Veloin the Quiet", 30000, 110, RACE_ZOMBIE },
+        { "Vanthylas the Learned", 30000, 105, RACE_MIND_FLAYER },
+        { "Ossein the Literate", 30000, 108, RACE_SKELETON },
+        { "Olvar Bookworm", 30000, 105, RACE_VAMPIRE },
 #endif
-       },
+    },
 
-       {
-               /* Museum */
-#ifdef JP
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-               { "博物館",                          0,      100, 100,  0, 99, 99},
-#else
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-               { "Museum",                          0,      100, 100,  0, 99, 99},
-#endif
-       },
+    {
+        /* Museum */
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+        { _("博物館", "Museum"), 0, 100, 99 },
+    },
 };
index c437af4..fc25210 100644 (file)
@@ -1,18 +1,19 @@
 #pragma once
 
 #include "system/angband.h"
+#include <array>
 
 #define MAX_STORES      10 /*!< 店舗の種類最大数 / Total number of stores (see "store.c", etc) */
 #define MAX_OWNERS      32 /*!< 各店舗毎の店主定義最大数 / Total number of owners per store (see "store.c", etc) */
 
-typedef struct owner_type {
-       concptr owner_name;     /* Name */
      PRICE max_cost;         /* Purse limit */
-       byte max_inflate;       /* Inflation (max) */
-       byte min_inflate;       /* Inflation (min) */
-       byte haggle_per;        /* Haggle unit */
-       byte insult_max;        /* Insult limit */
-       byte owner_race;        /* Owner race */
-} owner_type;
+/*!
+ * @brief 店主データ構造体
+ */
+struct owner_type {
+       concptr owner_name;     //!< 名前 / Name
+       PRICE max_cost; //!< 買取上限 / Purse limit
+       byte inflate; //!< 価格上乗せ率 / Inflation
+       byte owner_race; //!< 店主種族 / Owner race
+};
 
 extern const owner_type owners[MAX_STORES][MAX_OWNERS];
index 9124f81..fd829cb 100644 (file)
@@ -32,9 +32,8 @@ store_type *st_ptr = NULL;
  * Increase, by a given amount, the number of a certain item
  * in a certain store. This can result in zero items.
  * </pre>
- * @todo numは本来ITEM_NUMBER型にしたい。
  */
-void store_item_increase(INVENTORY_IDX item, int num)
+void store_item_increase(INVENTORY_IDX item, ITEM_NUMBER num)
 {
     object_type *o_ptr;
     o_ptr = &st_ptr->stock[item];
@@ -45,7 +44,7 @@ void store_item_increase(INVENTORY_IDX item, int num)
         cnt = 0;
 
     num = cnt - o_ptr->number;
-    o_ptr->number += (ITEM_NUMBER)num;
+    o_ptr->number += num;
 }
 
 /*!
@@ -95,6 +94,29 @@ void store_delete(void)
 }
 
 /*!
+ * @brief 店舗販売中の杖と魔法棒のpvalのリストを返す
+ * @param j_ptr これから売ろうとしているオブジェクト
+ * @return plavリスト(充填数)
+ * @details
+ * 回数の違う杖と魔法棒がスロットを圧迫するのでスロット数制限をかける
+ */
+static std::vector<PARAMETER_VALUE> store_same_magic_device_pvals(object_type *j_ptr)
+{
+    auto list = std::vector<PARAMETER_VALUE>();
+    for (INVENTORY_IDX i = 0; i < st_ptr->stock_num; i++) {
+        object_type *o_ptr = &st_ptr->stock[i];
+        if (o_ptr == j_ptr)
+            continue;
+        if (o_ptr->k_idx != j_ptr->k_idx)
+            continue;
+        if (o_ptr->tval != TV_STAFF && o_ptr->tval != TV_WAND)
+            continue;
+        list.push_back(o_ptr->pval);
+    }
+    return list;
+}
+
+/*!
  * @brief 店舗の品揃え変化のためにアイテムを追加する /
  * Creates a random item and gives it to a store
  * @param player_ptr プレーヤーへの参照ポインタ
@@ -127,7 +149,7 @@ void store_create(
             k_idx = fix_k_idx;
             level = rand_range(1, STORE_OBJ_LEVEL);
         } else {
-            k_idx = st_ptr->table[randint0(st_ptr->table_num)];
+            k_idx = st_ptr->table[randint0(st_ptr->table.size())];
             level = rand_range(1, STORE_OBJ_LEVEL);
         }
 
@@ -139,6 +161,12 @@ void store_create(
         if (!(*store_will_buy)(player_ptr, q_ptr))
             continue;
 
+        auto pvals = store_same_magic_device_pvals(q_ptr);
+        if (pvals.size() >= 2) {
+            auto pval = pvals.at(randint0(pvals.size()));
+            q_ptr->pval = pval;
+        }
+
         if (q_ptr->tval == TV_LITE) {
             if (q_ptr->sval == SV_LITE_TORCH)
                 q_ptr->xtra4 = FUEL_TORCH / 2;
index c4f67df..b80a8bc 100644 (file)
@@ -1,40 +1,44 @@
 #pragma once
 
 #include "system/angband.h"
+#include <vector>
 
-#define STORE_OBJ_LEVEL 5 /* Magic Level for normal stores */
+#define STORE_OBJ_LEVEL 5 //!< 通常店舗の階層レベル / Magic Level for normal stores
 
-#define STORE_GENERAL   0 /*!< 店舗の種類: 雑貨屋 */
-#define STORE_ARMOURY   1 /*!< 店舗の種類: 防具屋 */
-#define STORE_WEAPON    2 /*!< 店舗の種類: 武器屋 */
-#define STORE_TEMPLE    3 /*!< 店舗の種類: 寺院 */
-#define STORE_ALCHEMIST 4 /*!< 店舗の種類: 錬金術の店 */
-#define STORE_MAGIC     5 /*!< 店舗の種類: 魔道具屋 */
-#define STORE_BLACK     6 /*!< 店舗の種類: ブラック・マーケット */
-#define STORE_HOME      7 /*!< 店舗の種類: 我が家 */
-#define STORE_BOOK      8 /*!< 店舗の種類: 書店 */
-#define STORE_MUSEUM    9 /*!< 店舗の種類: 博物館 */
+enum STORE_TYPE_IDX {
+    STORE_GENERAL   = 0, //!< 店舗の種類: 雑貨屋
+    STORE_ARMOURY   = 1, //!< 店舗の種類: 防具屋
+    STORE_WEAPON    = 2, //!< 店舗の種類: 武器屋
+    STORE_TEMPLE    = 3, //!< 店舗の種類: 寺院
+    STORE_ALCHEMIST = 4, //!< 店舗の種類: 錬金術の店
+    STORE_MAGIC     = 5, //!< 店舗の種類: 魔道具屋
+    STORE_BLACK     = 6, //!< 店舗の種類: ブラック・マーケット
+    STORE_HOME      = 7, //!< 店舗の種類: 我が家
+    STORE_BOOK      = 8, //!< 店舗の種類: 書店
+    STORE_MUSEUM    = 9, //!< 店舗の種類: 博物館
+    STORE_MAX       = 10
+};
 
-typedef struct object_type object_type;
-typedef struct store_type {
-       byte type;                                /* Store type */
-       byte owner;                               /* Owner index */
      byte extra;                               /* Unused for now */
-       s16b insult_cur;                  /* Insult counter */
-       s16b good_buy;                    /* Number of "good" buys */
-       s16b bad_buy;                     /* Number of "bad" buys */
-       s32b store_open;                  /* Closed until this turn */
-       s32b last_visit;                  /* Last visited on this turn */
-    s16b regular_num;         /* Table -- Number of entries */
-    s16b regular_size;        /* Table -- Total Size of Array */
-    KIND_OBJECT_IDX *regular; /* Table -- Legal regular item kinds */
-    s16b table_num;           /* Table -- Number of entries */
-       s16b table_size;                  /* Table -- Total Size of Array */
-    KIND_OBJECT_IDX *table;   /* Table -- Legal item kinds */
-       s16b stock_num;                   /* Stock -- Number of entries */
-       s16b stock_size;                  /* Stock -- Total Size of Array */
-       object_type *stock;               /* Stock -- Actual stock items */
-} store_type;
+using store_k_idx = std::vector<KIND_OBJECT_IDX>;
+
+/*!
+ * @brief 店舗の情報構造体
+ */
+struct store_type {
+    byte type{};           //!< Store type
+    byte owner{};          //!< Owner index
+    byte extra{};          //!< Unused for now
+    s16b insult_cur{};     //!< Insult counter
+    s16b good_buy{};       //!< Number of "good" buys (3.0.0で廃止)
+    s16b bad_buy{};        //!< Number of "bad" buys (3.0.0で廃止)
+    s32b store_open{};     //!< Closed until this turn
+    s32b last_visit{};     //!< Last visited on this turn
+    store_k_idx regular{}; //!< Table -- Legal regular item kinds
+    store_k_idx table{};   //!< Table -- Legal item kinds
+    s16b stock_num{};      //!< Stock -- Number of entries
+    s16b stock_size{};     //!< Stock -- Total Size of Array
+    object_type *stock{};  //!< Stock -- Actual stock items
+};
 
 extern int cur_store_num;
 extern store_type *st_ptr;
@@ -44,7 +48,7 @@ typedef bool (*store_will_buy_pf)(player_type *, object_type *);
 typedef void (*mass_produce_pf)(player_type *, object_type *);
 void store_delete(void);
 void store_create(player_type *player_ptr, KIND_OBJECT_IDX k_idx, black_market_crap_pf black_market_crap, store_will_buy_pf store_will_buy, mass_produce_pf mass_produce);
-void store_item_increase(INVENTORY_IDX item, int num);
+void store_item_increase(INVENTORY_IDX item, ITEM_NUMBER num);
 void store_item_optimize(INVENTORY_IDX item);
 int store_carry(player_type *player_ptr, object_type *o_ptr);
 bool store_object_similar(object_type *o_ptr, object_type *j_ptr);
index 1d249e6..6cc7b2e 100644 (file)
@@ -47,7 +47,24 @@ int cur_store_feat;
 /* Enable "increments" */
 bool allow_inc = FALSE;
 
-/*
+/*!
+ * @brief 店舗の最大スロット数を返す
+ * @param store_idx 店舗ID
+ * @return 店舗の最大スロット数
+ */
+s16b store_get_stock_max(STORE_TYPE_IDX store_idx, bool powerup)
+{
+    switch (store_idx) {
+    case STORE_HOME:
+        return powerup ? STORE_INVEN_MAX * 10 : STORE_INVEN_MAX;
+    case STORE_MUSEUM:
+        return STORE_INVEN_MAX * 50;
+    default:
+        return STORE_INVEN_MAX * 3 / 2;
+    }
+}
+
+/*!
  * @brief アイテムが格納可能な数より多いかをチェックする
  * @param なし
  * @return 
@@ -295,27 +312,30 @@ void store_maintenance(player_type *player_ptr, int town_num, int store_num, int
     }
 
     INVENTORY_IDX j = st_ptr->stock_num;
-    int turn_over = 0;
-    for (int i = 0; i < chance; i++)
-        turn_over = MAX(turn_over, randint1(STORE_TURNOVER));
+    int remain = STORE_TURNOVER + MAX(0, j - STORE_MAX_KEEP);
+    int turn_over = 1;
+    for (int i = 0; i < chance; i++) {
+        auto n = randint0(remain);
+        turn_over += n;
+        remain -= n;
+    }
 
     j = j - turn_over;
     if (j > STORE_MAX_KEEP)
         j = STORE_MAX_KEEP;
-
     if (j < STORE_MIN_KEEP)
         j = STORE_MIN_KEEP;
 
-    if (j < 0)
-        j = 0;
-
     while (st_ptr->stock_num > j)
         store_delete();
 
-    int diff = STORE_MAX_KEEP - st_ptr->stock_num;
-    turn_over = 0;
-    for (int i = 0; i < chance; i++)
-        turn_over = MAX(turn_over, randint1(diff));
+    remain = STORE_MAX_KEEP - st_ptr->stock_num;
+    turn_over = 1;
+    for (int i = 0; i < chance; i++) {
+        auto n = randint0(remain);
+        turn_over += n;
+        remain -= n;
+    }
 
     j = st_ptr->stock_num + turn_over;
     if (j > STORE_MAX_KEEP)
@@ -325,7 +345,7 @@ void store_maintenance(player_type *player_ptr, int town_num, int store_num, int
     if (j >= st_ptr->stock_size)
         j = st_ptr->stock_size - 1;
 
-    for (int k = 0; k < st_ptr->regular_num; k++) {
+    for (size_t k = 0; k < st_ptr->regular.size(); k++) {
         store_create(player_ptr, st_ptr->regular[k], black_market_crap, store_will_buy, mass_produce);
         if (st_ptr->stock_num >= STORE_MAX_KEEP)
             break;
index 46d4b5d..51292b4 100644 (file)
@@ -2,12 +2,13 @@
 
 #include "system/angband.h"
 #include "store/store-owners.h"
+#include "store/store-util.h"
 
  /* Store constants */
 #define STORE_INVEN_MAX 24              /* Max number of discrete objs in inven */
-#define STORE_TURNOVER                /* Normal shop turnover, per day */
+#define STORE_TURNOVER  12              /* Normal shop turnover, per day */
 #define STORE_MIN_KEEP  6               /* Min slots to "always" keep full */
-#define STORE_MAX_KEEP  18              /* Max slots to "always" keep full */
+#define STORE_MAX_KEEP  21              /* Max slots to "always" keep full */
 #define STORE_SHUFFLE   21              /* 1/Chance (per day) of an owner changing */
 #define STORE_TICKS     1000            /* Number of ticks between turnovers */
 
@@ -21,6 +22,7 @@ extern s16b inner_town_num;
 extern int cur_store_feat;
 extern bool allow_inc;
 
+s16b store_get_stock_max(STORE_TYPE_IDX store_idx, bool powerup = true);
 void store_shuffle(player_type *player_ptr, int which);
 void store_maintenance(player_type *player_ptr, int town_num, int store_num, int chance);
 void store_init(int town_num, int store_num);
index 01082ae..fcf75c6 100644 (file)
 #define H_VER_MAJOR  3 //!< ゲームのバージョン定義(メジャー番号)
 #define H_VER_MINOR  0 //!< ゲームのバージョン定義(マイナー番号)
 #define H_VER_PATCH  0 //!< ゲームのバージョン定義(パッチ番号)
-#define H_VER_EXTRA 16 //!< ゲームのバージョン定義(エクストラ番号)
+#define H_VER_EXTRA 17 //!< ゲームのバージョン定義(エクストラ番号)
 
 /*!
  * @brief セーブファイルのバージョン(3.0.0から導入)
  */
-constexpr u32b SAVEFILE_VERSION = 2;
+constexpr u32b SAVEFILE_VERSION = 3;
 
 /*!
  * @brief バージョンが開発版が安定版かを返す(廃止予定)
index 48eb462..93d9cdf 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * The artifact arrays
  */
-artifact_type *a_info;
+std::vector<artifact_type> a_info;
 
 /*
  * Maximum number of artifacts in a_info.txt
index 99e120e..6039619 100644 (file)
@@ -1,10 +1,13 @@
 #pragma once
 
 #include "system/angband.h"
+
 #include "object-enchant/trg-types.h"
-#include "util/flag-group.h"
 #include "system/object-type-definition.h"
+#include "util/flag-group.h"
+
 #include <string>
+#include <vector>
 
 /*!
  * @struct artifact_type
@@ -38,5 +41,5 @@ typedef struct artifact_type {
        byte act_idx{};         /*! 発動能力ID / Activative ability index */
 } artifact_type;
 
-extern artifact_type *a_info;
+extern std::vector<artifact_type> a_info;
 extern ARTIFACT_IDX max_a_idx;
index bc30f38..5d8086d 100644 (file)
@@ -2,6 +2,8 @@
 
 #include "monster-attack/monster-attack-effect.h"
 #include "monster-attack/monster-attack-types.h"
+#include "monster-race/race-ability-flags.h"
+#include "util/flag-group.h"
 #include "system/angband.h"
 #include <string>
 
@@ -61,15 +63,11 @@ typedef struct monster_race {
     BIT_FLAGS flags1{}; /* Flags 1 (general) */
     BIT_FLAGS flags2{}; /* Flags 2 (abilities) */
     BIT_FLAGS flags3{}; /* Flags 3 (race/resist) */
-    BIT_FLAGS flags4{}; /* Flags 4 (inate/breath) */
     BIT_FLAGS flags7{}; /* Flags 7 (movement related abilities) */
     BIT_FLAGS flags8{}; /* Flags 8 (wilderness info) */
     BIT_FLAGS flags9{}; /* Flags 9 (drops info) */
     BIT_FLAGS flagsr{}; /* Flags R (resistances info) */
-    BIT_FLAGS a_ability_flags1{}; /* Activate Ability Flags 5 (normal spells) */
-    BIT_FLAGS a_ability_flags2{}; /* Activate Ability Flags 6 (special spells) */
-    BIT_FLAGS a_ability_flags3{}; /* Activate Ability Flags 7 (implementing) */
-    BIT_FLAGS a_ability_flags4{}; /* Activate Ability Flags 8 (implementing) */
+    FlagGroup<RF_ABILITY> ability_flags; /* Ability Flags */
     monster_blow blow[MAX_NUM_BLOWS]{}; /* Up to four blows per round */
     MONRACE_IDX reinforce_id[6]{};
     DICE_NUMBER reinforce_dd[6]{};
@@ -106,8 +104,6 @@ typedef struct monster_race {
     u32b r_flags1{}; /* Observed racial flags */
     u32b r_flags2{}; /* Observed racial flags */
     u32b r_flags3{}; /* Observed racial flags */
-    u32b r_flags4{}; /* Observed racial flags */
-    u32b r_flags5{}; /* Observed racial flags */
-    u32b r_flags6{}; /* Observed racial flags */
     u32b r_flagsr{}; /* Observed racial resistance flags */
+    FlagGroup<RF_ABILITY> r_ability_flags; /* Observed racial ability flags */
 } monster_race;
index e6214d0..8f5ada4 100644 (file)
@@ -620,6 +620,17 @@ uint vstrnfmt(char *buf, uint max, concptr fmt, va_list vp)
                 break;
 
             /* Save the character */
+#ifdef JP
+            if (iskanji(tmp[q])) {
+                if (tmp[q + 1]) {
+                    buf[n++] = tmp[q++];
+                } else {
+                    // 最後の文字が2バイト文字の前半で終わる場合は空白で置き換えて終了する
+                    buf[n++] = ' ';
+                    break;
+                }
+            }
+#endif
             buf[n++] = tmp[q];
         }
     }
index 0897edd..5c325aa 100644 (file)
@@ -129,12 +129,13 @@ typedef struct term_type {
 #define TERM_XTRA_ALIVE 11 /* Change the "hard" level (optional) */
 #define TERM_XTRA_LEVEL 12 /* Change the "soft" level (optional) */
 #define TERM_XTRA_DELAY 13 /* Delay some milliseconds (optional) */
-#define TERM_XTRA_MUSIC_BASIC 14 /* Play a music(basic)   (optional) */
+#define TERM_XTRA_MUSIC_BASIC 14 /* Play a music(basic) (optional) */
 #define TERM_XTRA_MUSIC_DUNGEON 15 /* Play a music(dungeon) (optional) */
-#define TERM_XTRA_MUSIC_QUEST 16 /* Play a music(quest)   (optional) */
-#define TERM_XTRA_MUSIC_TOWN 17 /* Play a music(floor)   (optional) */
-#define TERM_XTRA_MUSIC_MUTE 18
-#define TERM_XTRA_SCENE 19 /* React to scene changes (optional) */
+#define TERM_XTRA_MUSIC_QUEST 16 /* Play a music(quest) (optional) */
+#define TERM_XTRA_MUSIC_TOWN 17 /* Play a music(floor) (optional) */
+#define TERM_XTRA_MUSIC_MONSTER 18 /* Play a music(monster) (optional) */
+#define TERM_XTRA_MUSIC_MUTE 19
+#define TERM_XTRA_SCENE 20 /* React to scene changes (optional) */
 
 /**** Available Variables ****/
 extern term_type *Term;
index 854910a..d7bd29a 100644 (file)
@@ -377,6 +377,66 @@ public:
     }
 
     /**
+     * @brief フラグ集合 *this と rhs が等値かどうかを調べる
+     *
+     * @param rhs 比較するフラグ集合
+     * @return bool すべてのフラグの状態が等しければtrue、そうでなければfalse
+     */
+    bool operator==(const FlagGroup<FlagType> &rhs) const noexcept
+    {
+        return bs_ == rhs.bs_;
+    }
+
+    /**
+     * @brief フラグ集合 *this と rhs が非等値かどうかを調べる
+     *
+     * @param rhs 比較するフラグ集合
+     * @return bool いずれかのフラグの状態が等しくなければtrue、そうでなければfalse
+     */
+    bool operator!=(const FlagGroup<FlagType> &rhs) const noexcept
+    {
+        return bs_ != rhs.bs_;
+    }
+
+    /**
+     * @brief フラグ集合 *this と rhs の論理積(AND)の複合演算を行う
+     *
+     * *this に対して、*this と rhs で共通してONのフラグをONのままにし、それ以外のフラグをOFFにする
+     *
+     * @param rhs 複合演算を行うフラグ集合
+     * @return FlagGroup<FlagType>& *thisを返す
+     */
+    FlagGroup<FlagType> &operator&=(const FlagGroup<FlagType> &rhs) noexcept
+    {
+        bs_ &= rhs.bs_;
+        return *this;
+    }
+
+    /**
+     * @brief フラグ集合 *this と rhs の論理和(OR)の複合演算を行う
+     *
+     * *this に対して、*this と rhs でどちらか一方でもONのフラグをONにし、それ以外のフラグをOFFにする
+     *
+     * @param rhs 複合演算を行うフラグ集合
+     * @return FlagGroup<FlagType>& *thisを返す
+     */
+    FlagGroup<FlagType> &operator|=(const FlagGroup<FlagType> &rhs) noexcept
+    {
+        bs_ |= rhs.bs_;
+        return *this;
+    }
+
+    template <typename OutputIter>
+    static void get_flags(const FlagGroup<FlagType>& flag_group, OutputIter start)
+    {
+        for (size_t i = 0; i < flag_group.size(); i++) {
+            if (flag_group.bs_.test(i)) {
+                *start++ = static_cast<FlagType>(i);
+            }
+        }
+    }
+
+    /**
      * @brief セーブファイルからフラグ集合を読み出す
      *
      * @param fg 読み出したフラグ集合を格納するFlagGroupインスタンスの参照
@@ -500,3 +560,35 @@ private:
     /** フラグ集合を保持するstd::bitsetのインスタンス */
     std::bitset<FLAG_TYPE_MAX> bs_;
 };
+
+/**
+ * @brief フラグ集合 lhs と rhs に対して論理積(AND)を取ったフラグ集合を生成する
+ *
+ * lhs と rhs で共通してONのフラグがON、それ以外のフラグがOFFのフラグ集合を生成する
+ *
+ * @tparam FlagType 扱うフラグ集合を定義したenum class型
+ * @param lhs フラグ集合1
+ * @param rhs フラグ集合2
+ * @return FlagGroup<FlagType> lhs と rhs の論理積を取ったフラグ集合
+ */
+template <typename FlagType>
+FlagGroup<FlagType> operator&(const FlagGroup<FlagType> &lhs, const FlagGroup<FlagType> &rhs) noexcept
+{
+    return FlagGroup<FlagType>(lhs) &= rhs;
+}
+
+/**
+ * @brief フラグ集合 lhs と rhs に対して論理和(OR)を取ったフラグ集合を生成する
+ *
+ * lhs と rhs でどちらか一方でもONのフラグがON、それ以外のフラグがOFFのフラグ集合を生成する
+ *
+ * @tparam FlagType 扱うフラグ集合を定義したenum class型
+ * @param lhs フラグ集合1
+ * @param rhs フラグ集合2
+ * @return FlagGroup<FlagType> lhs と rhs の論理積を取ったフラグ集合
+ */
+template <typename FlagType>
+FlagGroup<FlagType> operator|(const FlagGroup<FlagType> &lhs, const FlagGroup<FlagType> &rhs) noexcept
+{
+    return FlagGroup<FlagType>(lhs) |= rhs;
+}
index 20c2bae..e6477d9 100644 (file)
@@ -537,3 +537,132 @@ int strrncmp(const char *s1, const char *s2, int len)
 
     return (0);
 }
+
+/**
+ * @brief 文字列の両端の空白を削除する
+ *
+ * 文字列 str の両端にある空白(スペースおよびタブ)を削除し、
+ * 削除した文字列を std::string 型のオブジェクトとして返す。
+ * 文字列全体が空白の場合は空文字列を返す。
+ *
+ * @param str 操作の対象とする文字列
+ * @return std::string strの両端の空白を削除した文字列
+ */
+std::string str_trim(std::string_view str)
+{
+    const auto start_pos = str.find_first_not_of(" \t");
+    const auto end_pos = str.find_last_not_of(" \t");
+
+    if (start_pos == std::string_view::npos || end_pos == std::string_view::npos) {
+        return std::string();
+    }
+
+    return std::string(str.substr(start_pos, end_pos - start_pos + 1));
+}
+
+/**
+ * @brief 文字列の右端の空白を削除する
+ *
+ * 文字列 str の右端にある空白(スペースおよびタブ)を削除し、
+ * 削除した文字列を std::string 型のオブジェクトとして返す。
+ * 文字列全体が空白の場合は空文字列を返す。
+ *
+ * @param str 操作の対象とする文字列
+ * @return std::string strの右端の空白を削除した文字列
+ */
+std::string str_rtrim(std::string_view str)
+{
+    const auto end_pos = str.find_last_not_of(" \t");
+
+    if (end_pos == std::string_view::npos) {
+        return std::string();
+    }
+
+    return std::string(str.substr(0, end_pos + 1));
+}
+
+/**
+ * @brief 文字列の左端の空白を削除する
+ *
+ * 文字列 str の左端にある空白(スペースおよびタブ)を削除し、
+ * 削除した文字列を std::string 型のオブジェクトとして返す。
+ * 文字列全体が空白の場合は空文字列を返す。
+ *
+ * @param str 操作の対象とする文字列
+ * @return std::string strの左端の空白を削除した文字列
+ */
+std::string str_ltrim(std::string_view str)
+{
+    const auto start_pos = str.find_first_not_of(" \t");
+
+    if (start_pos == std::string_view::npos) {
+        return std::string();
+    }
+
+    return std::string(str.substr(start_pos));
+}
+
+/**
+ * @brief 文字列を指定した文字で分割する
+ *
+ * 文字列 str を delim で指定した文字で分割し、分割した文字列を要素とする配列を
+ * std::vector<std::string> 型のオブジェクトとして返す。
+ *
+ * @param str 操作の対象とする文字列
+ * @param delim 文字列を分割する文字
+ * @param trim trueの場合、分割した文字列の両端の空白を削除する
+ * @return std::vector<std::string> 分割した文字列を要素とする配列
+ */
+std::vector<std::string> str_split(std::string_view str, char delim, bool trim)
+{
+    std::vector<std::string> result;
+
+    auto make_str = [trim](std::string_view sv) { return trim ? str_trim(sv) : std::string(sv); };
+
+    while (true) {
+        bool found = false;
+        for (size_t i = 0; i < str.size(); ++i) {
+            if (str[i] == delim) {
+                result.push_back(make_str(str.substr(0, i)));
+                str.remove_prefix(i + 1);
+                found = true;
+                break;
+            }
+#ifdef JP
+            if (iskanji(str[i]))
+                ++i;
+#endif
+        }
+        if (!found) {
+            result.push_back(make_str(str));
+            return result;
+        }
+    }
+}
+
+/**
+ * @brief 文字列から指定した文字を取り除く
+ *
+ * 文字列 str から文字列 erase_chars に含まれる文字をすべて削除し、
+ * 削除した文字列を std::string 型のオブジェクトとして返す。
+ *
+ * @param str 操作の対象とする文字列
+ * @param erase_chars 削除する文字を指定する文字列
+ * @return std::string 指定した文字をすべて削除した文字列
+ */
+std::string str_erase(std::string str, std::string_view erase_chars)
+{
+    for (auto it = str.begin(); it != str.end();) {
+        if (erase_chars.find(*it) != std::string_view::npos) {
+            it = str.erase(it);
+            continue;
+        }
+#ifdef JP
+        if (iskanji(*it))
+            ++it;
+#endif
+        ++it;
+    }
+
+    return str;
+}
index 74bf815..3b77a7c 100644 (file)
@@ -2,6 +2,10 @@
 
 #include "system/angband.h"
 
+#include <string>
+#include <string_view>
+#include <vector>
+
 #define MAX_MACRO_MOD 12
 #define MAX_MACRO_TRIG 200 /*!< 登録を許すマクロ(トリガー)の最大数 */
 
@@ -26,3 +30,8 @@ char *angband_strchr(concptr ptr, char ch);
 char *ltrim(char *p);
 char *rtrim(char *p);
 int strrncmp(const char *s1, const char *s2, int len);
+std::string str_trim(std::string_view str);
+std::string str_rtrim(std::string_view str);
+std::string str_ltrim(std::string_view str);
+std::vector<std::string> str_split(std::string_view str, char delim, bool trim = false);
+std::string str_erase(std::string str, std::string_view erase_chars);
index 7b92e6c..848b1c7 100644 (file)
@@ -13,7 +13,6 @@
 #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-flags7.h"
 #include "monster-race/race-indice-types.h"
 #include "mspell/mspell-type.h"
@@ -563,13 +562,13 @@ void display_monster_collective(lore_type *lore_ptr)
  */
 void display_monster_launching(player_type *player_ptr, lore_type *lore_ptr)
 {
-    if (lore_ptr->flags4 & RF4_ROCKET) {
+    if (lore_ptr->ability_flags.has(RF_ABILITY::ROCKET)) {
         set_damage(player_ptr, lore_ptr, (MS_ROCKET), _("ロケット%sを発射する", "shoot a rocket%s"));
         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
         lore_ptr->color[lore_ptr->vn++] = TERM_UMBER;
     }
 
-    if ((lore_ptr->flags4 & RF4_SHOOT) == 0)
+    if (lore_ptr->ability_flags.has_not(RF_ABILITY::SHOOT))
         return;
 
     int p = -1; /* Position of SHOOT */
index 7e26a33..800fe08 100644 (file)
@@ -80,10 +80,25 @@ static void image_random(TERM_COLOR *ap, SYMBOL_CODE *cp)
     }
 }
 
+/*!
+ * @brief マップに表示されるべき地形(壁)かどうかを判定する
+ * @param floor_ptr 階の情報への参照ポインタ
+ * @param f_ptr 地形の情報への参照ポインタ
+ * @param y グリッドy座標
+ * @param x グリッドx座標
+ * @return 表示されるべきならtrue、そうでないならfalse
+ * @details
+ * 周り全てが壁に囲まれている壁についてはオプション状態による。
+ * 1か所でも空きがあるか、壁ではない地形、金を含む地形、永久岩は表示。
+ */
 static bool is_revealed_wall(floor_type *floor_ptr, feature_type *f_ptr, POSITION y, POSITION x)
 {
-    if (view_hidden_walls)
-        return TRUE;
+    if (view_hidden_walls) {
+        if (view_unsafe_walls)
+            return TRUE;
+        if (none_bits(floor_ptr->grid_array[y][x].info, CAVE_UNSAFE))
+            return TRUE;
+    }
 
     if (!has_flag(f_ptr->flags, FF_WALL) || has_flag(f_ptr->flags, FF_HAS_GOLD))
         return TRUE;
index 6a75a90..66de0dc 100644 (file)
@@ -25,8 +25,8 @@
 #include "player/player-status-table.h"
 #include "realm/realm-names-table.h"
 #include "status-first-page.h"
-#include "system/system-variables.h" // 暫定。後で消す
 #include "system/floor-type-definition.h"
+#include "system/system-variables.h" // 暫定。後で消す
 #include "term/screen-processor.h"
 #include "term/term-color-types.h"
 #include "util/buffer-shaper.h"
@@ -36,6 +36,7 @@
 #include "view/display-player-stat-info.h"
 #include "view/display-util.h"
 #include "world/world.h"
+#include <string>
 
 /*!
  * @brief
  */
 static bool display_player_info(player_type *creature_ptr, int mode)
 {
-       if (mode == 2)
-       {
-               display_player_misc_info(creature_ptr);
-               display_player_stat_info(creature_ptr);
-               display_player_flag_info_1(creature_ptr, display_player_equippy);
-               return TRUE;
-       }
-
-       if (mode == 3)
-       {
-               display_player_flag_info_2(creature_ptr, display_player_equippy);
-               return TRUE;
-       }
-
-       if (mode == 4)
-       {
-               do_cmd_knowledge_mutations(creature_ptr);
-               return TRUE;
-       }
-
-       return FALSE;
+    if (mode == 2) {
+        display_player_misc_info(creature_ptr);
+        display_player_stat_info(creature_ptr);
+        display_player_flag_info_1(creature_ptr, display_player_equippy);
+        return TRUE;
+    }
+
+    if (mode == 3) {
+        display_player_flag_info_2(creature_ptr, display_player_equippy);
+        return TRUE;
+    }
+
+    if (mode == 4) {
+        do_cmd_knowledge_mutations(creature_ptr);
+        return TRUE;
+    }
+
+    return FALSE;
 }
 
-
 /*!
  * @brief 名前、性別、種族、職業を表示する
  * @param creature_ptr プレーヤーへの参照ポインタ
  */
 static void display_player_basic_info(player_type *creature_ptr)
 {
-       char tmp[64];
+    char tmp[64];
 #ifdef JP
-       sprintf(tmp, "%s%s%s", ap_ptr->title, ap_ptr->no == 1 ? "の" : "", creature_ptr->name);
+    sprintf(tmp, "%s%s%s", ap_ptr->title, ap_ptr->no == 1 ? "の" : "", creature_ptr->name);
 #else
-       sprintf(tmp, "%s %s", ap_ptr->title, creature_ptr->name);
+    sprintf(tmp, "%s %s", ap_ptr->title, creature_ptr->name);
 #endif
 
-       display_player_one_line(ENTRY_NAME, tmp, TERM_L_BLUE);
-       display_player_one_line(ENTRY_SEX, sp_ptr->title, TERM_L_BLUE);
-       display_player_one_line(ENTRY_RACE, (creature_ptr->mimic_form ? mimic_info[creature_ptr->mimic_form].title : rp_ptr->title), TERM_L_BLUE);
-       display_player_one_line(ENTRY_CLASS, cp_ptr->title, TERM_L_BLUE);
+    display_player_one_line(ENTRY_NAME, tmp, TERM_L_BLUE);
+    display_player_one_line(ENTRY_SEX, sp_ptr->title, TERM_L_BLUE);
+    display_player_one_line(ENTRY_RACE, (creature_ptr->mimic_form ? mimic_info[creature_ptr->mimic_form].title : rp_ptr->title), TERM_L_BLUE);
+    display_player_one_line(ENTRY_CLASS, cp_ptr->title, TERM_L_BLUE);
 }
 
-
 /*!
  * @brief 魔法領域を表示する
  * @param creature_ptr プレーヤーへの参照ポインタ
@@ -96,21 +92,20 @@ static void display_player_basic_info(player_type *creature_ptr)
  */
 static void display_magic_realms(player_type *creature_ptr)
 {
-    if (creature_ptr->realm1 == 0)
+    if (creature_ptr->realm1 == REALM_NONE && creature_ptr->element == REALM_NONE)
         return;
 
     char tmp[64];
     if (creature_ptr->pclass == CLASS_ELEMENTALIST)
-            sprintf(tmp, "%s", get_element_title(creature_ptr->realm1));
-       else if (creature_ptr->realm2)
-               sprintf(tmp, "%s, %s", realm_names[creature_ptr->realm1], realm_names[creature_ptr->realm2]);
-       else
-               strcpy(tmp, realm_names[creature_ptr->realm1]);
+        sprintf(tmp, "%s", get_element_title(creature_ptr->element));
+    else if (creature_ptr->realm2)
+        sprintf(tmp, "%s, %s", realm_names[creature_ptr->realm1], realm_names[creature_ptr->realm2]);
+    else
+        strcpy(tmp, realm_names[creature_ptr->realm1]);
 
-       display_player_one_line(ENTRY_REALM, tmp, TERM_L_BLUE);
+    display_player_one_line(ENTRY_REALM, tmp, TERM_L_BLUE);
 }
 
-
 /*!
  * @ brief 年齢、身長、体重、社会的地位を表示する
  * @param creature_ptr プレーヤーへの参照ポインタ
@@ -121,52 +116,47 @@ static void display_magic_realms(player_type *creature_ptr)
 static void display_phisique(player_type *creature_ptr)
 {
 #ifdef JP
-       display_player_one_line(ENTRY_AGE, format("%d才", (int)creature_ptr->age), TERM_L_BLUE);
-       display_player_one_line(ENTRY_HEIGHT, format("%dcm", (int)((creature_ptr->ht * 254) / 100)), TERM_L_BLUE);
-       display_player_one_line(ENTRY_WEIGHT, format("%dkg", (int)((creature_ptr->wt * 4536) / 10000)), TERM_L_BLUE);
-       display_player_one_line(ENTRY_SOCIAL, format("%d  ", (int)creature_ptr->sc), TERM_L_BLUE);
+    display_player_one_line(ENTRY_AGE, format("%d才", (int)creature_ptr->age), TERM_L_BLUE);
+    display_player_one_line(ENTRY_HEIGHT, format("%dcm", (int)((creature_ptr->ht * 254) / 100)), TERM_L_BLUE);
+    display_player_one_line(ENTRY_WEIGHT, format("%dkg", (int)((creature_ptr->wt * 4536) / 10000)), TERM_L_BLUE);
+    display_player_one_line(ENTRY_SOCIAL, format("%d  ", (int)creature_ptr->sc), TERM_L_BLUE);
 #else
-       display_player_one_line(ENTRY_AGE, format("%d", (int)creature_ptr->age), TERM_L_BLUE);
-       display_player_one_line(ENTRY_HEIGHT, format("%d", (int)creature_ptr->ht), TERM_L_BLUE);
-       display_player_one_line(ENTRY_WEIGHT, format("%d", (int)creature_ptr->wt), TERM_L_BLUE);
-       display_player_one_line(ENTRY_SOCIAL, format("%d", (int)creature_ptr->sc), TERM_L_BLUE);
+    display_player_one_line(ENTRY_AGE, format("%d", (int)creature_ptr->age), TERM_L_BLUE);
+    display_player_one_line(ENTRY_HEIGHT, format("%d", (int)creature_ptr->ht), TERM_L_BLUE);
+    display_player_one_line(ENTRY_WEIGHT, format("%d", (int)creature_ptr->wt), TERM_L_BLUE);
+    display_player_one_line(ENTRY_SOCIAL, format("%d", (int)creature_ptr->sc), TERM_L_BLUE);
 #endif
-       display_player_one_line(ENTRY_ALIGN, format("%s", your_alignment(creature_ptr)), TERM_L_BLUE);
+    std::string alg = your_alignment(creature_ptr);
+    display_player_one_line(ENTRY_ALIGN, format("%s", alg.c_str()), TERM_L_BLUE);
 }
 
-
 /*!
  * @brief 能力値を (減少していたら色を変えて)表示する
  * @param creature_ptr プレーヤーへの参照ポインタ
  */
 static void display_player_stats(player_type *creature_ptr)
 {
-       char buf[80];
-       for (int i = 0; i < A_MAX; i++)
-       {
-               if (creature_ptr->stat_cur[i] < creature_ptr->stat_max[i])
-               {
-                       put_str(stat_names_reduced[i], 3 + i, 53);
-                       int value = creature_ptr->stat_use[i];
-                       cnv_stat(value, buf);
-                       c_put_str(TERM_YELLOW, buf, 3 + i, 60);
-                       value = creature_ptr->stat_top[i];
-                       cnv_stat(value, buf);
-                       c_put_str(TERM_L_GREEN, buf, 3 + i, 67);
-               }
-               else
-               {
-                       put_str(stat_names[i], 3 + i, 53);
-                       cnv_stat(creature_ptr->stat_use[i], buf);
-                       c_put_str(TERM_L_GREEN, buf, 3 + i, 60);
-               }
-
-               if (creature_ptr->stat_max[i] == creature_ptr->stat_max_max[i])
-                       c_put_str(TERM_WHITE, "!", 3 + i, _(58, 58 - 2));
-       }
+    char buf[80];
+    for (int i = 0; i < A_MAX; i++) {
+        if (creature_ptr->stat_cur[i] < creature_ptr->stat_max[i]) {
+            put_str(stat_names_reduced[i], 3 + i, 53);
+            int value = creature_ptr->stat_use[i];
+            cnv_stat(value, buf);
+            c_put_str(TERM_YELLOW, buf, 3 + i, 60);
+            value = creature_ptr->stat_top[i];
+            cnv_stat(value, buf);
+            c_put_str(TERM_L_GREEN, buf, 3 + i, 67);
+        } else {
+            put_str(stat_names[i], 3 + i, 53);
+            cnv_stat(creature_ptr->stat_use[i], buf);
+            c_put_str(TERM_L_GREEN, buf, 3 + i, 60);
+        }
+
+        if (creature_ptr->stat_max[i] == creature_ptr->stat_max_max[i])
+            c_put_str(TERM_WHITE, "!", 3 + i, _(58, 58 - 2));
+    }
 }
 
-
 /*!
  * @brief ゲームオーバーの原因を探る (生きていたら何もしない)
  * @param creature_ptr プレーヤーへの参照ポインタ
@@ -175,51 +165,48 @@ static void display_player_stats(player_type *creature_ptr)
  */
 static bool search_death_cause(player_type *creature_ptr, char *statmsg)
 {
-       floor_type *floor_ptr = creature_ptr->current_floor_ptr;
-       if (!creature_ptr->is_dead) return FALSE;
-
-       if (current_world_ptr->total_winner)
-       {
-               sprintf(statmsg, _("…あなたは勝利の後%sした。", "...You %s after winning."),
-                       streq(creature_ptr->died_from, "Seppuku") ? _("切腹", "committed seppuku") : _("引退", "retired from the adventure"));
-
-               return TRUE;
-       }
-       
-       if (!floor_ptr->dun_level)
-       {
+    floor_type *floor_ptr = creature_ptr->current_floor_ptr;
+    if (!creature_ptr->is_dead)
+        return FALSE;
+
+    if (current_world_ptr->total_winner) {
+        sprintf(statmsg, _("…あなたは勝利の後%sした。", "...You %s after winning."),
+            streq(creature_ptr->died_from, "Seppuku") ? _("切腹", "committed seppuku") : _("引退", "retired from the adventure"));
+
+        return TRUE;
+    }
+
+    if (!floor_ptr->dun_level) {
 #ifdef JP
-               sprintf(statmsg, "…あなたは%sで%sに殺された。", map_name(creature_ptr), creature_ptr->died_from);
+        sprintf(statmsg, "…あなたは%sで%sに殺された。", map_name(creature_ptr), creature_ptr->died_from);
 #else
-               sprintf(statmsg, "...You were killed by %s in %s.", creature_ptr->died_from, map_name(creature_ptr));
+        sprintf(statmsg, "...You were killed by %s in %s.", creature_ptr->died_from, map_name(creature_ptr));
 #endif
-               return TRUE;
-       }
-       
-       if (floor_ptr->inside_quest && is_fixed_quest_idx(floor_ptr->inside_quest))
-       {
-               /* Get the quest text */
-               /* Bewere that INIT_ASSIGN resets the cur_num. */
-               init_flags = INIT_NAME_ONLY;
-               parse_fixed_map(creature_ptr, "q_info.txt", 0, 0, 0, 0);
+        return TRUE;
+    }
+
+    if (floor_ptr->inside_quest && is_fixed_quest_idx(floor_ptr->inside_quest)) {
+        /* Get the quest text */
+        /* Bewere that INIT_ASSIGN resets the cur_num. */
+        init_flags = INIT_NAME_ONLY;
+        parse_fixed_map(creature_ptr, "q_info.txt", 0, 0, 0, 0);
 #ifdef JP
-               sprintf(statmsg, "…あなたは、クエスト「%s」で%sに殺された。", quest[floor_ptr->inside_quest].name, creature_ptr->died_from);
+        sprintf(statmsg, "…あなたは、クエスト「%s」で%sに殺された。", quest[floor_ptr->inside_quest].name, creature_ptr->died_from);
 #else
-               sprintf(statmsg, "...You were killed by %s in the quest '%s'.", creature_ptr->died_from, quest[floor_ptr->inside_quest].name);
+        sprintf(statmsg, "...You were killed by %s in the quest '%s'.", creature_ptr->died_from, quest[floor_ptr->inside_quest].name);
 #endif
-               return TRUE;
-       }
+        return TRUE;
+    }
 
 #ifdef JP
-       sprintf(statmsg, "…あなたは、%sの%d階で%sに殺された。", map_name(creature_ptr), (int)floor_ptr->dun_level, creature_ptr->died_from);
+    sprintf(statmsg, "…あなたは、%sの%d階で%sに殺された。", map_name(creature_ptr), (int)floor_ptr->dun_level, creature_ptr->died_from);
 #else
-       sprintf(statmsg, "...You were killed by %s on level %d of %s.", creature_ptr->died_from, floor_ptr->dun_level, map_name(creature_ptr));
+    sprintf(statmsg, "...You were killed by %s on level %d of %s.", creature_ptr->died_from, floor_ptr->dun_level, map_name(creature_ptr));
 #endif
 
-       return TRUE;
+    return TRUE;
 }
 
-
 /*!
  * @brief クエストフロアで生きている場合、クエスト名をバッファに詰める
  * @param creature_ptr プレーヤーへの参照ポインタ
@@ -228,21 +215,20 @@ static bool search_death_cause(player_type *creature_ptr, char *statmsg)
  */
 static bool decide_death_in_quest(player_type *creature_ptr, char *statmsg)
 {
-       floor_type *floor_ptr = creature_ptr->current_floor_ptr;
-       if (!floor_ptr->inside_quest || !is_fixed_quest_idx(floor_ptr->inside_quest))
-               return FALSE;
-
-       for (int i = 0; i < 10; i++)
-               quest_text[i][0] = '\0';
-
-       quest_text_line = 0;
-       init_flags = INIT_NAME_ONLY;
-       parse_fixed_map(creature_ptr, "q_info.txt", 0, 0, 0, 0);
-       sprintf(statmsg, _("…あなたは現在、 クエスト「%s」を遂行中だ。", "...Now, you are in the quest '%s'."), quest[floor_ptr->inside_quest].name);
-       return TRUE;
+    floor_type *floor_ptr = creature_ptr->current_floor_ptr;
+    if (!floor_ptr->inside_quest || !is_fixed_quest_idx(floor_ptr->inside_quest))
+        return FALSE;
+
+    for (int i = 0; i < 10; i++)
+        quest_text[i][0] = '\0';
+
+    quest_text_line = 0;
+    init_flags = INIT_NAME_ONLY;
+    parse_fixed_map(creature_ptr, "q_info.txt", 0, 0, 0, 0);
+    sprintf(statmsg, _("…あなたは現在、 クエスト「%s」を遂行中だ。", "...Now, you are in the quest '%s'."), quest[floor_ptr->inside_quest].name);
+    return TRUE;
 }
 
-
 /*!
  * @brief 現在いるフロアを、または死んでいたらどこでどう死んだかをバッファに詰める
  * @param creature_ptr プレーヤーへの参照ポインタ
@@ -251,26 +237,27 @@ static bool decide_death_in_quest(player_type *creature_ptr, char *statmsg)
  */
 static void decide_current_floor(player_type *creature_ptr, char *statmsg)
 {
-       if (search_death_cause(creature_ptr, statmsg)) return;
-       if (!current_world_ptr->character_dungeon) return;
-
-       floor_type *floor_ptr = creature_ptr->current_floor_ptr;
-       if (floor_ptr->dun_level == 0)
-       {
-               sprintf(statmsg, _("…あなたは現在、 %s にいる。", "...Now, you are in %s."), map_name(creature_ptr));
-               return;
-       }
-       
-       if (decide_death_in_quest(creature_ptr, statmsg)) return;
+    if (search_death_cause(creature_ptr, statmsg))
+        return;
+    if (!current_world_ptr->character_dungeon)
+        return;
+
+    floor_type *floor_ptr = creature_ptr->current_floor_ptr;
+    if (floor_ptr->dun_level == 0) {
+        sprintf(statmsg, _("…あなたは現在、 %s にいる。", "...Now, you are in %s."), map_name(creature_ptr));
+        return;
+    }
+
+    if (decide_death_in_quest(creature_ptr, statmsg))
+        return;
 
 #ifdef JP
-       sprintf(statmsg, "…あなたは現在、 %s の %d 階で探索している。", map_name(creature_ptr), (int)floor_ptr->dun_level);
+    sprintf(statmsg, "…あなたは現在、 %s の %d 階で探索している。", map_name(creature_ptr), (int)floor_ptr->dun_level);
 #else
-       sprintf(statmsg, "...Now, you are exploring level %d of %s.", (int)floor_ptr->dun_level, map_name(creature_ptr));
+    sprintf(statmsg, "...Now, you are exploring level %d of %s.", (int)floor_ptr->dun_level, map_name(creature_ptr));
 #endif
 }
 
-
 /*!
  * @brief 今いる、または死亡した場所を表示する
  * @param statmsg メッセージバッファ
@@ -278,20 +265,19 @@ static void decide_current_floor(player_type *creature_ptr, char *statmsg)
  */
 static void display_current_floor(char *statmsg)
 {
-       char temp[128];
-       shape_buffer(statmsg, 60, temp, sizeof(temp));
-       char  *t;
-       t = temp;
-       for (int i = 0; i < 2; i++)
-       {
-               if (t[0] == 0) return;
-
-               put_str(t, i + 5 + 12, 10);
-               t += strlen(t) + 1;
-       }
+    char temp[128];
+    shape_buffer(statmsg, 60, temp, sizeof(temp));
+    char *t;
+    t = temp;
+    for (int i = 0; i < 2; i++) {
+        if (t[0] == 0)
+            return;
+
+        put_str(t, i + 5 + 12, 10);
+        t += strlen(t) + 1;
+    }
 }
 
-
 /*!
  * @brief プレイヤーのステータス表示メイン処理
  * Display the character on the screen (various modes)
@@ -310,43 +296,43 @@ static void display_current_floor(char *statmsg)
  */
 void display_player(player_type *creature_ptr, int mode)
 {
-       if (creature_ptr->muta.any() && display_mutations)
-               mode = (mode % 5);
-       else
-               mode = (mode % 4);
+    if (creature_ptr->muta.any() && display_mutations)
+        mode = (mode % 5);
+    else
+        mode = (mode % 4);
 
-       clear_from(0);
-       if (display_player_info(creature_ptr, mode)) return;
+    clear_from(0);
+    if (display_player_info(creature_ptr, mode))
+        return;
 
-       display_player_basic_info(creature_ptr);
-       display_magic_realms(creature_ptr);
+    display_player_basic_info(creature_ptr);
+    display_magic_realms(creature_ptr);
 
-       if ((creature_ptr->pclass == CLASS_CHAOS_WARRIOR) || (creature_ptr->muta.has(MUTA::CHAOS_GIFT)))
-               display_player_one_line(ENTRY_PATRON, chaos_patrons[creature_ptr->chaos_patron], TERM_L_BLUE);
+    if ((creature_ptr->pclass == CLASS_CHAOS_WARRIOR) || (creature_ptr->muta.has(MUTA::CHAOS_GIFT)))
+        display_player_one_line(ENTRY_PATRON, chaos_patrons[creature_ptr->chaos_patron], TERM_L_BLUE);
 
-       display_phisique(creature_ptr);
-       display_player_stats(creature_ptr);
+    display_phisique(creature_ptr);
+    display_player_stats(creature_ptr);
 
-       if (mode == 0)
-       {
-               display_player_middle(creature_ptr);
-               display_player_various(creature_ptr);
-               return;
-       }
+    if (mode == 0) {
+        display_player_middle(creature_ptr);
+        display_player_various(creature_ptr);
+        return;
+    }
 
-       char statmsg[1000];
-       put_str(_("(キャラクターの生い立ち)", "(Character Background)"), 11, 25);
-       for (int i = 0; i < 4; i++)
-               put_str(creature_ptr->history[i], i + 12, 10);
+    char statmsg[1000];
+    put_str(_("(キャラクターの生い立ち)", "(Character Background)"), 11, 25);
+    for (int i = 0; i < 4; i++)
+        put_str(creature_ptr->history[i], i + 12, 10);
 
-       *statmsg = '\0';
-       decide_current_floor(creature_ptr, statmsg);
-       if (!*statmsg) return;
+    *statmsg = '\0';
+    decide_current_floor(creature_ptr, statmsg);
+    if (!*statmsg)
+        return;
 
-       display_current_floor(statmsg);
+    display_current_floor(statmsg);
 }
 
-
 /*!
  * @brief プレイヤーの装備一覧をシンボルで並べる
  * Equippy chars
@@ -359,21 +345,19 @@ void display_player(player_type *creature_ptr, int mode)
  */
 void display_player_equippy(player_type *creature_ptr, TERM_LEN y, TERM_LEN x, BIT_FLAGS16 mode)
 {
-       int max_i = (mode & DP_WP) ? INVEN_SUB_HAND + 1 : INVEN_TOTAL;
-       for (int i = INVEN_MAIN_HAND; i < max_i; i++)
-       {
-               object_type *o_ptr;
-               o_ptr = &creature_ptr->inventory_list[i];
-
-               TERM_COLOR a = object_attr(o_ptr);
-               SYMBOL_CODE c = object_char(o_ptr);
-
-               if (!equippy_chars || !o_ptr->k_idx)
-               {
-                       c = ' ';
-                       a = TERM_DARK;
-               }
-
-               term_putch(x + i - INVEN_MAIN_HAND, y, a, c);
-       }
+    int max_i = (mode & DP_WP) ? INVEN_SUB_HAND + 1 : INVEN_TOTAL;
+    for (int i = INVEN_MAIN_HAND; i < max_i; i++) {
+        object_type *o_ptr;
+        o_ptr = &creature_ptr->inventory_list[i];
+
+        TERM_COLOR a = object_attr(o_ptr);
+        SYMBOL_CODE c = object_char(o_ptr);
+
+        if (!equippy_chars || !o_ptr->k_idx) {
+            c = ' ';
+            a = TERM_DARK;
+        }
+
+        term_putch(x + i - INVEN_MAIN_HAND, y, a, c);
+    }
 }
index 55266b4..4b85111 100644 (file)
@@ -5,6 +5,7 @@
 #include "player/player-race.h"
 #include "player/player-status-table.h"
 #include "term/screen-processor.h"
+#include <string>
 
 void display_life_rating(player_type *creature_ptr, self_info_type *self_ptr)
 {
@@ -32,7 +33,8 @@ void display_max_base_status(player_type *creature_ptr, self_info_type *self_ptr
 void display_virtue(player_type *creature_ptr, self_info_type *self_ptr)
 {
     self_ptr->info[self_ptr->line++] = "";
-    sprintf(self_ptr->plev_buf, _("現在の属性 : %s(%ld)", "Your alignment : %s(%ld)"), your_alignment(creature_ptr), (long int)creature_ptr->align);
+    std::string alg = your_alignment(creature_ptr, true);
+    sprintf(self_ptr->plev_buf, _("現在の属性 : %s", "Your alignment : %s"), alg.c_str());
     strcpy(self_ptr->buf[1], self_ptr->plev_buf);
     self_ptr->info[self_ptr->line++] = self_ptr->buf[1];
     for (int v_nr = 0; v_nr < 8; v_nr++) {
index 64aa81b..5447d89 100644 (file)
@@ -98,23 +98,16 @@ void display_entry(player_type *player_ptr, int pos)
 
     s32b x;
     if (o_ptr->ident & IDENT_FIXED) {
-        x = price_item(player_ptr, o_ptr, ot_ptr->min_inflate, FALSE);
+        x = price_item(player_ptr, o_ptr, ot_ptr->inflate, FALSE);
         (void)sprintf(out_val, _("%9ld固", "%9ld F"), (long)x);
         put_str(out_val, i + 6, 68);
         return;
     }
 
-    if (!manual_haggle) {
-        x = price_item(player_ptr, o_ptr, ot_ptr->min_inflate, FALSE);
-        if (!noneedtobargain(x))
-            x += x / 10;
+    x = price_item(player_ptr, o_ptr, ot_ptr->inflate, FALSE);
+    if (x >= LOW_PRICE_THRESHOLD)
+        x += x / 10;
 
-        (void)sprintf(out_val, "%9ld  ", (long)x);
-        put_str(out_val, i + 6, 68);
-        return;
-    }
-
-    x = price_item(player_ptr, o_ptr, ot_ptr->max_inflate, FALSE);
     (void)sprintf(out_val, "%9ld  ", (long)x);
     put_str(out_val, i + 6, 68);
 }
index b569c1d..38562be 100644 (file)
@@ -98,8 +98,6 @@ void display_koff(player_type *owner_ptr, KIND_OBJECT_IDX k_idx)
     use_realm = tval2realm(q_ptr->tval);
 
     if (owner_ptr->realm1 || owner_ptr->realm2) {
-        if (owner_ptr->pclass == CLASS_ELEMENTALIST)
-            return;
         if ((use_realm != owner_ptr->realm1) && (use_realm != owner_ptr->realm2))
             return;
     } else {
index 7b9e959..8e76c01 100644 (file)
@@ -10,6 +10,7 @@
 #include "inventory/inventory-describer.h"
 #include "inventory/inventory-slot-types.h"
 #include "inventory/inventory-util.h"
+#include "main/sound-of-music.h"
 #include "monster-race/monster-race.h"
 #include "monster-race/race-flags1.h"
 #include "monster/monster-flag-types.h"
@@ -39,6 +40,7 @@
 #include "world/world.h"
 #include <string>
 #include <sstream>
+#include <mutex>
 
 /*!
  * @brief サブウィンドウに所持品一覧を表示する / Hack -- display inventory in sub-windows
@@ -182,6 +184,7 @@ void print_monster_list(floor_type *floor_ptr, const std::vector<MONSTER_IDX> &m
 void fix_monster_list(player_type *player_ptr)
 {
     static std::vector<MONSTER_IDX> monster_list;
+    std::once_flag once;
 
     for (int j = 0; j < 8; j++) {
         term_type *old = Term;
@@ -195,11 +198,16 @@ void fix_monster_list(player_type *player_ptr)
         term_activate(angband_term[j]);
         int w, h;
         term_get_size(&w, &h);
-        target_sensing_monsters_prepare(player_ptr, monster_list);
+        std::call_once(once, target_sensing_monsters_prepare, player_ptr, monster_list);
         print_monster_list(player_ptr->current_floor_ptr, monster_list, 0, 0, h);
         term_fresh();
         term_activate(old);
     }
+
+    if (use_music && has_monster_music) {
+        std::call_once(once, target_sensing_monsters_prepare, player_ptr, monster_list);
+        select_monster_music(player_ptr, monster_list);
+    }
 }
 
 /*!
index 31c6978..045b85b 100644 (file)
@@ -840,33 +840,39 @@ WishResult do_cmd_wishing(player_type *caster_ptr, int prob, bool allow_art, boo
         WishResult res = WishResult::NOTHING;
         if (allow_ego && (wish_ego || e_ids.size() > 0)) {
             if (must || ok_ego) {
-                int max_roll = 1000;
-                int i = 0;
-                for (i = 0; i < max_roll; i++) {
+                if (e_ids.size() > 0) {
                     object_prep(caster_ptr, o_ptr, k_idx);
-                    (void)apply_magic(caster_ptr, o_ptr, k_ptr->level, (AM_GREAT | AM_NO_FIXED_ART));
-
-                    if (o_ptr->name1 || o_ptr->art_name)
-                        continue;
+                    o_ptr->name2 = e_ids[0];
+                    apply_ego(caster_ptr, o_ptr, caster_ptr->current_floor_ptr->base_level);
+                } else {
+                    int max_roll = 1000;
+                    int i = 0;
+                    for (i = 0; i < max_roll; i++) {
+                        object_prep(caster_ptr, o_ptr, k_idx);
+                        (void)apply_magic(caster_ptr, o_ptr, k_ptr->level, (AM_GREAT | AM_NO_FIXED_ART));
+
+                        if (o_ptr->name1 || o_ptr->art_name)
+                            continue;
+
+                        if (wish_ego)
+                            break;
 
-                    if (wish_ego)
-                        break;
+                        EGO_IDX e_idx = 0;
+                        for (auto e : e_ids) {
+                            if (o_ptr->name2 == e) {
+                                e_idx = e;
+                                break;
+                            }
+                        }
 
-                    EGO_IDX e_idx = 0;
-                    for (auto e : e_ids) {
-                        if (o_ptr->name2 == e) {
-                            e_idx = e;
+                        if (e_idx != 0)
                             break;
-                        }
                     }
 
-                    if (e_idx != 0)
-                        break;
-                }
-
-                if (i == max_roll) {
-                    msg_print(_("失敗!もう一度願ってみてください。", "Failed! Try again."));
-                    return WishResult::FAIL;
+                    if (i == max_roll) {
+                        msg_print(_("失敗!もう一度願ってみてください。", "Failed! Try again."));
+                        return WishResult::FAIL;
+                    }
                 }
             } else {
                 wishing_puff_of_smoke();
index cfc7a59..6286752 100644 (file)
@@ -665,14 +665,13 @@ void cheat_death(player_type *creature_ptr)
     msg_print(_("ウィザードモードに念を送り、死を欺いた。", "You invoke wizard mode and cheat death."));
     msg_print(NULL);
 
+    creature_ptr->is_dead = FALSE;
     (void)life_stream(creature_ptr, FALSE, FALSE);
     (void)restore_mana(creature_ptr, TRUE);
-
     (void)recall_player(creature_ptr, 0);
     reserve_alter_reality(creature_ptr, 0);
 
     (void)strcpy(creature_ptr->died_from, _("死の欺き", "Cheating death"));
-    creature_ptr->is_dead = FALSE;
     (void)set_food(creature_ptr, PY_FOOD_MAX - 1);
 
     floor_type *floor_ptr = creature_ptr->current_floor_ptr;
index b5f0c39..ca8bc33 100644 (file)
@@ -14,6 +14,7 @@
 #include "monster-floor/monster-generator.h"
 #include "monster-floor/monster-summon.h"
 #include "monster-floor/place-monster-types.h"
+#include "monster-race/race-ability-flags.h"
 #include "mutation/mutation-processor.h"
 #include "spell-kind/spells-launcher.h"
 #include "spell-kind/spells-teleport.h"
@@ -27,6 +28,8 @@
 #include "target/target-getter.h"
 #include "view/display-messages.h"
 
+#include <vector>
+
 debug_spell_command debug_spell_commands_list[SPELL_MAX] = {
     { 2, "vanish dungeon", { .spell2 = { vanish_dungeon } } },
     { 3, "true healing", { .spell3 = { true_healing } } },
@@ -123,24 +126,14 @@ void wiz_teleport_back(player_type *caster_ptr)
  */
 void wiz_learn_blue_magic_all(player_type *caster_ptr)
 {
-    BIT_FLAGS f4 = 0L, f5 = 0L, f6 = 0L;
+    FlagGroup<RF_ABILITY> ability_flags;
     for (int j = 1; j < A_MAX; j++) {
-        set_rf_masks(&f4, &f5, &f6, static_cast<blue_magic_type>(j));
-
-        int i;
-        for (i = 0; i < 32; i++) {
-            if ((0x00000001U << i) & f4)
-                caster_ptr->magic_num2[i] = 1;
-        }
-
-        for (; i < 64; i++) {
-            if ((0x00000001U << (i - 32)) & f5)
-                caster_ptr->magic_num2[i] = 1;
-        }
+        set_rf_masks(ability_flags, static_cast<blue_magic_type>(j));
 
-        for (; i < 96; i++) {
-            if ((0x00000001U << (i - 64)) & f6)
-                caster_ptr->magic_num2[i] = 1;
+        std::vector<RF_ABILITY> spells;
+        FlagGroup<RF_ABILITY>::get_flags(ability_flags, std::back_inserter(spells));
+        for (auto spell : spells) {
+            caster_ptr->magic_num2[static_cast<int>(spell)] = 1;
         }
     }
 }