<ClCompile Include="..\..\src\spell\spells-describer.c" />\r
<ClCompile Include="..\..\src\spell\spells-detection.c" />\r
<ClCompile Include="..\..\src\spell\spells-hex.c" />\r
+ <ClCompile Include="..\..\src\spell\spells-teleport.c" />\r
<ClCompile Include="..\..\src\system\system-variables.c" />\r
<ClCompile Include="..\..\src\core\show-file.c" />\r
<ClCompile Include="..\..\src\monster\creature.c" />\r
<ClInclude Include="..\..\src\realm\realm-song-numbers.h" />\r
<ClInclude Include="..\..\src\spell\spells-describer.h" />\r
<ClInclude Include="..\..\src\spell\spells-hex.h" />\r
+ <ClInclude Include="..\..\src\spell\spells-teleport.h" />\r
<ClInclude Include="..\..\src\sv-definition\sv-amulet-types.h" />\r
<ClInclude Include="..\..\src\sv-definition\sv-armor-types.h" />\r
<ClInclude Include="..\..\src\sv-definition\sv-bow-types.h" />\r
<ClCompile Include="..\..\src\mind\racial-ninja.c">
<Filter>mind</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\spell\spells-teleport.c">
+ <Filter>spell</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\cmd\cmd-basic.h">
<ClInclude Include="..\..\src\mind\racial-ninja.h">
<Filter>mind</Filter>
</ClInclude>
+ <ClInclude Include="..\..\src\spell\spells-teleport.h">
+ <Filter>spell</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\wall.bmp" />
spell/spells-hex.c spell/spells-hex.h \
spell/spells-object.c spell/spells-object.h \
spell/spells-status.c spell/spells-status.h \
+ spell/spells-teleport.c spell/spells-teleport.h \
spell/spells-summon.c spell/spells-summon.h \
spell/spells-world.c spell/spells-world.h \
spell/spells-detection.c spell/spells-detection.h \
* 2014 Deskull rearranged comment for Doxygen.\n
*/
-#include "system/angband.h"
+#include "cmd-action/cmd-spell.h"
+#include "cmd/cmd-basic.h"
#include "core/stuff-handler.h"
-#include "util/util.h"
-#include "main/sound-definitions-table.h"
-
#include "floor/floor.h"
#include "grid/grid.h"
-#include "spell/spells-summon.h"
-#include "spell/spells-status.h"
+#include "io/targeting.h"
+#include "main/sound-definitions-table.h"
+#include "monster/monster-process.h"
#include "monster/monster-status.h"
#include "mspell/monster-spell.h"
-#include "monster/monster-process.h"
-#include "cmd-action/cmd-spell.h"
-#include "player/player-status.h"
+#include "mspell/mspell-type.h"
#include "player/player-effects.h"
-#include "cmd/cmd-basic.h"
-#include "io/targeting.h"
-#include "view/display-main-window.h"
+#include "player/player-status.h"
+#include "spell/spells-status.h"
+#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
-#include "spell/spells3.h"
-#include "mspell/mspell-type.h"
+#include "util/util.h"
+#include "view/display-main-window.h"
static int damage;
#pragma once
-/* mane.c */
-extern bool do_cmd_mane(player_type *creature_ptr, bool baigaesi);
+#include "system/angband.h"
+
+bool do_cmd_mane(player_type *creature_ptr, bool baigaesi);
#include "player/player-personalities-table.h"
#include "player/player-status.h"
#include "spell/spells-status.h"
+#include "spell/spells-teleport.h"
#include "spell/spells3.h"
#include "util/util.h"
#include "world/world.h"
#include "spell/spells-object.h"
#include "spell/spells-status.h"
#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
#include "spell/spells-object.h"
#include "spell/spells-status.h"
#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
#include "spell/spells-floor.h"
#include "spell/spells-status.h"
#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
#include "util/util.h"
#include "spell/spells-detection.h"
#include "spell/spells-floor.h"
#include "spell/spells-status.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
#include "player/player-effects.h"
#include "player/player-status.h"
#include "spell/spells-status.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
-#include "spell/spells3.h"
#include "util/util.h"
#include "view/display-main-window.h"
#include "view/object-describer.h"
#include "cmd-io/cmd-dump.h"
#include "cmd-io/cmd-save.h"
#include "combat/attack-power-table.h"
+#include "combat/shoot.h"
#include "combat/slaying.h"
#include "combat/snipe.h"
#include "core/output-updater.h"
#include "player/player-move.h"
#include "player/player-personalities-table.h"
#include "player/player-status.h"
-#include "shoot.h"
#include "spell/spells-hex.h"
-#include "spell/spells3.h"
+#include "spell/spells-teleport.h"
#include "system/system-variables.h"
#include "term/gameterm.h"
#include "view/display-main-window.h"
#include "object/object-mark-types.h"
#include "realm/realm-hex-numbers.h"
#include "spell/spells-hex.h"
+#include "spell/spells-teleport.h"
#include "spell/spells3.h"
/*!
#include "realm/realm-hex-numbers.h"
#include "spell/process-effect.h"
#include "spell/spells-hex.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
-#include "spell/spells3.h"
static void aura_fire_by_monster_attack(player_type *target_ptr, monap_type *monap_ptr)
{
#include "player/player-move.h"
#include "spell/process-effect.h"
#include "spell/spells-hex.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
-#include "spell/spells3.h"
/* todo モンスター共通なので、monster-attack-player.cでも使うはず */
const int MAX_BLOW = 4;
#include "realm/realm-hex-numbers.h"
#include "spell/process-effect.h"
#include "spell/spells-hex.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
-#include "spell/spells2.h"
-#include "spell/spells3.h"
static bool check_no_blow(player_type *target_ptr, monap_type *monap_ptr)
{
* @author Hourier
*/
-#include "system/angband.h"
#include "effect/effect-monster.h"
-#include "spells-effect-util.h"
-#include "io/write-diary.h"
-#include "main/sound-definitions-table.h"
-#include "player/player-move.h"
#include "core/stuff-handler.h"
-#include "effect/effect-monster-util.h"
+#include "effect/effect-characteristics.h"
#include "effect/effect-monster-switcher.h"
#include "floor/floor-object.h"
-#include "object/object-kind-hook.h"
+#include "io/write-diary.h"
+#include "main/sound-definitions-table.h"
#include "monster/monster-status.h"
+#include "object-enchant/special-object-flags.h"
+#include "object/object-generator.h"
+#include "object/object-kind-hook.h"
#include "player/avatar.h"
+#include "player/player-move.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
-#include "effect/effect-characteristics.h"
#include "spell/spells3.h"
-#include "object/object-generator.h"
-#include "object-enchant/special-object-flags.h"
+#include "spells-effect-util.h"
#include "sv-definition/sv-other-types.h"
/*!
#pragma once
+#include "system/angband.h"
+#include "effect/effect-monster-util.h"
+
bool affect_monster(player_type *caster_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ, BIT_FLAGS flag, bool see_s_msg);
-#include "system/angband.h"
-#include "effect/effect-player-util.h"
-#include "effect/effect-player-resist-hurt.h"
-#include "player/player-damage.h"
+#include "effect/effect-player-resist-hurt.h"
#include "inventory/inventory-damage.h"
#include "mind/racial-mirror-master.h"
-#include "world/world.h"
-#include "object/object-broken.h"
+#include "mspell/monster-spell.h"
+#include "mutation/mutation.h"
#include "object-enchant/artifact.h"
+#include "object/object-broken.h"
+#include "player/player-damage.h"
#include "player/player-effects.h"
-#include "mutation/mutation.h"
-#include "mspell/monster-spell.h"
+#include "player/player-races-table.h"
#include "spell/spells-status.h"
+#include "spell/spells-teleport.h"
#include "spell/spells3.h"
-#include "player/player-races-table.h"
+#include "world/world.h"
// 毒を除く4元素.
void effect_player_elements(player_type *target_ptr, effect_player_type *ep_ptr,
#pragma once
+#include "system/angband.h"
+#include "effect/effect-player-util.h"
+
void effect_player_elements(player_type *target_ptr, effect_player_type *ep_ptr, concptr attack_message, HIT_POINT (*damage_func)(player_type *, HIT_POINT, concptr, int, bool));
void effect_player_poison(player_type *target_ptr, effect_player_type *ep_ptr);
void effect_player_nuke(player_type *target_ptr, effect_player_type *ep_ptr);
#include "player/player-races-table.h"
#include "realm/realm-song-numbers.h"
#include "spell/spells-status.h"
-#include "spell/spells3.h"
+#include "spell/spells-teleport.h"
/*!
* @brief パターン終点到達時のテレポート処理を行う
#include "system/angband.h"
#include "util/util.h"
#include "main/sound-definitions-table.h"
-
#include "io/write-diary.h"
#include "cmd-io/cmd-dump.h"
#include "cmd-io/cmd-save.h"
#include "dungeon/dungeon.h"
#include "world/world.h"
#include "spell/process-effect.h"
+#include "spell/spells-teleport.h"
#include "spell/spells2.h"
-#include "spell/spells3.h"
#include "mind/racial-mirror-master.h"
static s16b normal_traps[MAX_NORMAL_TRAPS];
#include "player/player-move.h"
#include "player/player-races-table.h"
#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells2.h"
-#include "spell/spells3.h"
#define TRC_P_FLAG_MASK \
(TRC_TELEPORT_SELF | TRC_CHAINSWORD | TRC_TY_CURSE | TRC_DRAIN_EXP | TRC_ADD_L_CURSE | TRC_ADD_H_CURSE | TRC_CALL_ANIMAL | TRC_CALL_DEMON \
#include "spell/spells-floor.h"
#include "spell/spells-status.h"
#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
#include "effect/spells-effect-util.h"
#include "object/object-generator.h"
#include "object/object-kind-hook.h"
-#include "spell/spells3.h"
+#include "spell/spells-teleport.h"
/*!
* @brief 変わり身処理
#include "spell/spells-hex.h"
#include "spell/spells-object.h"
#include "spell/spells-status.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
-#include "system/angband.h"
+#include "quantum-effect.h"
#include "floor/floor.h"
-#include "quantum-effect.h"
-#include "mspell/monster-spell.h"
-#include "spell/spells3.h"
#include "mspell/assign-monster-spell.h"
+#include "mspell/monster-spell.h"
+#include "spell/spells-teleport.h"
/*!
* @brief ユニークでない量子生物を消滅させる
#pragma once
+#include "system/angband.h"
+
bool process_quantum_effect(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m);
* @author Habu
*/
-#include "system/angband.h"
-#include "mspell/mspell-util.h"
-#include "mspell/mspell-type.h"
#include "mspell/assign-monster-spell.h"
#include "mspell/monster-spell.h"
-#include "spell/spells-type.h"
-#include "mspell/mspell-summon.h"
-#include "mspell/mspell-curse.h"
-#include "mspell/mspell-breath.h"
#include "mspell/mspell-ball.h"
#include "mspell/mspell-bolt.h"
+#include "mspell/mspell-breath.h"
+#include "mspell/mspell-curse.h"
#include "mspell/mspell-floor.h"
-#include "mspell/mspell-status.h"
-#include "mspell/mspell-special.h"
#include "mspell/mspell-particularity.h"
+#include "mspell/mspell-special.h"
+#include "mspell/mspell-status.h"
+#include "mspell/mspell-summon.h"
+#include "mspell/mspell-type.h"
+#include "mspell/mspell-util.h"
+#include "spell/spells-type.h"
/*!
* @brief モンスターからプレイヤーへの呪文の振り分け関数。 /
#pragma once
-HIT_POINT monspell_to_player(player_type* target_ptr, monster_spell_type ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx);
-HIT_POINT monspell_to_monster(player_type* target_ptr, monster_spell_type ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, bool is_special_spell);
+#include "system/angband.h"
+
+HIT_POINT monspell_to_player(player_type *target_ptr, SPELL_IDX ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx);
+HIT_POINT 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);
#include "player/player-personalities-table.h"
#include "spell/process-effect.h"
#include "spell/spells-hex.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
-#include "spell/spells3.h"
/*!
* @brief RF4_SHRIEKの処理。叫び。 /
* @author Hourier
*/
-#include "system/angband.h"
#include "mspell/mspell-special.h"
-#include "player/player-damage.h"
-#include "mspell/monster-spell.h"
-#include "main/sound-definitions-table.h"
-#include "spell/spells-type.h"
+#include "combat/melee-postprocess.h"
#include "effect/effect-characteristics.h"
-#include "player/player-move.h"
+#include "main/sound-definitions-table.h"
+#include "mspell/monster-spell.h"
#include "mspell/mspell-util.h"
-#include "spell/spells3.h"
-#include "spell/process-effect.h"
+#include "player/player-damage.h"
#include "player/player-effects.h"
-#include "combat/melee-postprocess.h"
+#include "player/player-move.h"
+#include "spell/process-effect.h"
+#include "spell/spells-teleport.h"
+#include "spell/spells-type.h"
/*!
* @brief バーノール・ルパートのRF6_SPECIALの処理。分裂・合体。 /
#pragma once
+#include "system/angband.h"
+
HIT_POINT spell_RF6_SPECIAL(player_type* target_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE);
#include "spell/process-effect.h"
#include "spell/range-calc.h"
#include "spell/spells-hex.h"
-#include "spell/spells3.h"
+#include "spell/spells-teleport.h"
#include "mspell/mspell-learn-checker.h"
#include "mspell/assign-monster-spell.h"
#include "monster/monster.h"
#include "monster/monster-status.h"
#include "mspell/monster-spell.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/range-calc.h"
#include "dungeon/dungeon.h"
#include "world/world.h"
#include "view/display-main-window.h"
-#include "spell/spells3.h"
#include "mspell/assign-monster-spell.h"
#include "spell/spells-hex.h"
#include "player/player-effects.h"
#include "io/targeting.h"
#include "view/display-main-window.h"
+#include "spell/spells-teleport.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
#include "mspell/mspell-type.h"
-#include "system/angband.h"
-#include "mutation/mutation-processor.h"
-#include "spell/spells-type.h"
-#include "spell/spells-summon.h"
-#include "store/store-util.h"
-#include "store/store-owners.h"
+#include "mutation/mutation-processor.h"
+#include "io/targeting.h"
+#include "monster/monster-status.h"
+#include "mutation/mutation.h"
+#include "object/lite-processor.h"
+#include "object/object-hook.h"
#include "player/player-damage.h"
-#include "player/player-move.h"
#include "player/player-effects.h"
+#include "player/player-move.h"
+#include "spell/spells-floor.h"
+#include "spell/spells-hex.h"
+#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
+#include "spell/spells-type.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
-#include "spell/spells-floor.h"
-#include "io/targeting.h"
+#include "store/store-owners.h"
+#include "store/store-util.h"
#include "store/store.h"
-#include "object/object-hook.h"
-#include "mutation/mutation.h"
-#include "monster/monster-status.h"
-#include "object/lite-processor.h"
-#include "spell/spells-hex.h"
/*!
* @brief 10ゲームターンが進行するごとに突然変異の発動判定を行う処理
#pragma once
+#include "system/angband.h"
+
void process_world_aux_mutation(player_type* creature_ptr);
* 2014 Deskull rearranged comment for Doxygen.\n
*/
-#include "system/angband.h"
-#include "core/stuff-handler.h"
+#include "mutation/mutation.h"
+#include "cmd-io/cmd-dump.h"
+#include "cmd/cmd-basic.h"
#include "core/show-file.h"
-#include "util/util.h"
-
+#include "core/stuff-handler.h"
+#include "effect/spells-effect-util.h"
+#include "floor/floor.h"
+#include "io/files-util.h"
+#include "io/targeting.h"
#include "io/write-diary.h"
-#include "cmd-io/cmd-dump.h"
-#include "mutation/mutation.h"
-
-#include "player/selfinfo.h"
-#include "spell/spells-summon.h"
+#include "object-enchant/item-feeling.h"
+#include "object/object-hook.h"
#include "player/avatar.h"
-#include "player/player-status.h"
-#include "player/player-effects.h"
-#include "player/player-personalities-table.h"
#include "player/player-class.h"
#include "player/player-damage.h"
-#include "spell/spells-status.h"
-#include "spell/spells-floor.h"
-#include "object-enchant/item-feeling.h"
-#include "object/object-hook.h"
-#include "cmd/cmd-basic.h"
-#include "io/files-util.h"
-#include "floor/floor.h"
-#include "io/targeting.h"
+#include "player/player-effects.h"
+#include "player/player-personalities-table.h"
#include "player/player-races-table.h"
-#include "effect/spells-effect-util.h"
+#include "player/player-status.h"
+#include "player/selfinfo.h"
+#include "spell/spells-detection.h"
+#include "spell/spells-floor.h"
+#include "spell/spells-status.h"
+#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
-#include "spell/spells-detection.h"
+#include "util/util.h"
/*!
* @brief プレイヤーに突然変異を与える
-/* mutation.c */
-extern bool gain_mutation(player_type *creature_ptr, MUTATION_IDX choose_mut);
-extern bool lose_mutation(player_type *creature_ptr, MUTATION_IDX choose_mut);
-extern void lose_all_mutations(player_type *creature_ptr);
-extern int calc_mutant_regenerate_mod(player_type *creature_ptr);
-extern bool exe_mutation_power(player_type *creature_ptr, int power);
-extern void become_living_trump(player_type *creature_ptr);
+#pragma once
+
+#include "system/angband.h"
+
+bool gain_mutation(player_type *creature_ptr, MUTATION_IDX choose_mut);
+bool lose_mutation(player_type *creature_ptr, MUTATION_IDX choose_mut);
+void lose_all_mutations(player_type *creature_ptr);
+int calc_mutant_regenerate_mod(player_type *creature_ptr);
+bool exe_mutation_power(player_type *creature_ptr, int power);
+void become_living_trump(player_type *creature_ptr);
-#include "system/angband.h"
-#include "util/util.h"
-
+#include "realm/realm-arcane.h"
#include "cmd-action/cmd-spell.h"
+#include "io/targeting.h"
#include "player/avatar.h"
-
-#include "spell/spells2.h"
-#include "spell/spells3.h"
+#include "player/player-effects.h"
+#include "player/player-status.h"
+#include "spell/spells-detection.h"
+#include "spell/spells-diceroll.h"
#include "spell/spells-floor.h"
#include "spell/spells-object.h"
-#include "spell/spells-summon.h"
#include "spell/spells-status.h"
-#include "spell/spells-diceroll.h"
-#include "player/player-status.h"
-#include "player/player-effects.h"
-#include "io/targeting.h"
-#include "realm/realm-arcane.h"
+#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
-#include "spell/spells-detection.h"
+#include "spell/spells2.h"
+#include "spell/spells3.h"
+#include "util/util.h"
/*!
* @brief 秘術領域魔法の各処理を行う
#pragma once
+#include "system/angband.h"
#include "spell/spells-util.h"
concptr do_arcane_spell(player_type *caster_ptr, SPELL_IDX spell, spell_type mode);
-#include "system/angband.h"
-#include "util/util.h"
-
+#include "realm/realm-chaos.h"
#include "cmd-action/cmd-spell.h"
+#include "effect/effect-characteristics.h"
+#include "io/targeting.h"
#include "player/player-class.h"
#include "player/player-effects.h"
-#include "spell/spells-summon.h"
-#include "spell/spells-status.h"
+#include "spell/process-effect.h"
+#include "spell/spells-diceroll.h"
#include "spell/spells-floor.h"
#include "spell/spells-object.h"
-#include "spell/spells-diceroll.h"
-#include "io/targeting.h"
-#include "view/display-main-window.h"
-#include "realm/realm-chaos.h"
+#include "spell/spells-status.h"
+#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
-#include "spell/process-effect.h"
-#include "effect/effect-characteristics.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
+#include "util/util.h"
+#include "view/display-main-window.h"
/*!
* @brief カオス領域魔法の各処理を行う
#pragma once
+#include "system/angband.h"
#include "spell/spells-util.h"
concptr do_chaos_spell(player_type *caster_ptr, SPELL_IDX spell, spell_type mode);
-#include "system/angband.h"
-#include "util/util.h"
-
-#include "world/world.h"
+#include "realm/realm-crusade.h"
#include "cmd-action/cmd-spell.h"
#include "effect/effect-characteristics.h"
-#include "spell/spells-type.h"
-#include "spell/spells-object.h"
-#include "spell/spells-summon.h"
-#include "spell/spells-status.h"
-#include "spell/spells-floor.h"
-#include "spell/spells-diceroll.h"
+#include "floor/floor.h"
+#include "io/targeting.h"
#include "player/player-class.h"
#include "player/player-effects.h"
-#include "io/targeting.h"
-#include "realm/realm-crusade.h"
-#include "floor/floor.h"
#include "spell/process-effect.h"
+#include "spell/spells-detection.h"
+#include "spell/spells-diceroll.h"
+#include "spell/spells-floor.h"
+#include "spell/spells-object.h"
+#include "spell/spells-status.h"
+#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
+#include "spell/spells-type.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
-#include "spell/spells-detection.h"
+#include "util/util.h"
+#include "world/world.h"
/*!
* @brief 破邪領域魔法の各処理を行う
#pragma once
+#include "system/angband.h"
#include "spell/spells-util.h"
concptr do_crusade_spell(player_type *caster_ptr, SPELL_IDX spell, spell_type mode);
#include "realm/realm-hex-numbers.h"
#include "spell/process-effect.h"
#include "spell/spells-execution.h"
-#include "spell/spells-status.h"
#include "spell/spells-hex.h"
+#include "spell/spells-status.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
-#include "cmd-action/cmd-attack.h"
+#include "realm/realm-hissatsu.h"
+#include "cmd-action/cmd-attack.h"
#include "cmd-action/cmd-spell.h"
#include "cmd/cmd-basic.h"
#include "combat/combat-options-type.h"
#include "spell/process-effect.h"
#include "spell/spells-detection.h"
#include "spell/spells-floor.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells-util.h"
#include "spell/spells2.h"
-#include "system/angband.h"
-#include "util/util.h"
-
+#include "realm/realm-sorcery.h"
#include "cmd-action/cmd-spell.h"
-#include "player/selfinfo.h"
+#include "io/targeting.h"
#include "player/avatar.h"
-
-#include "spell/spells-type.h"
-#include "spell/spells-status.h"
-#include "spell/spells-floor.h"
#include "player/player-effects.h"
-#include "io/targeting.h"
-#include "realm/realm-sorcery.h"
+#include "player/selfinfo.h"
+#include "spell/spells-detection.h"
+#include "spell/spells-floor.h"
+#include "spell/spells-status.h"
+#include "spell/spells-teleport.h"
+#include "spell/spells-type.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
-#include "spell/spells-detection.h"
+#include "util/util.h"
/*!
* @brief 仙術領域魔法の各処理を行う
#pragma once
+#include "system/angband.h"
#include "spell/spells-util.h"
concptr do_sorcery_spell(player_type *caster_ptr, SPELL_IDX spell, spell_type mode);
-#include "system/angband.h"
-#include "util/util.h"
-
+#include "realm/realm-trump.h"
#include "cmd-action/cmd-spell.h"
+#include "effect/spells-effect-util.h"
+#include "io/targeting.h"
#include "mutation/mutation.h"
-#include "spell/spells-summon.h"
-#include "spell/spells-status.h"
-#include "spell/spells-object.h"
-#include "player/player-effects.h"
#include "player/player-class.h"
-#include "io/targeting.h"
-#include "effect/spells-effect-util.h"
-#include "realm/realm-trump.h"
+#include "player/player-effects.h"
+#include "spell/spells-detection.h"
+#include "spell/spells-object.h"
+#include "spell/spells-status.h"
+#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
#include "spell/spells3.h"
-#include "spell/spells-detection.h"
+#include "util/util.h"
/*!
* @brief トランプ領域魔法の各処理を行う
#pragma once
+#include "system/angband.h"
#include "spell/spells-util.h"
concptr do_trump_spell(player_type *caster_ptr, SPELL_IDX spell, spell_type mode);
#include "player/player-damage.h"
#include "player/player-effects.h"
#include "player/player-move.h"
-#include "spell/spells3.h"
+#include "spell/spells-teleport.h"
#include "util/util.h"
#include "view/display-main-window.h"
#include "player/player-class.h"
#include "player/player-effects.h"
#include "player/player-status.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/spells2.h"
-#include "spell/spells3.h"
#include "util/util.h"
#include "view/display-main-window.h"
--- /dev/null
+/*!
+ * todo 少し長いかも
+ * @brief テレポート魔法全般
+ * @date 2020/06/04
+ * @author Hourier
+ */
+
+#include "spell/spells-teleport.h"
+#include "cmd-io/cmd-save.h"
+#include "dungeon/dungeon.h"
+#include "dungeon/quest.h"
+#include "effect/effect-characteristics.h"
+#include "io/targeting.h"
+#include "io/write-diary.h"
+#include "main/sound-definitions-table.h"
+#include "monster/creature.h"
+#include "monster/monster-status.h"
+#include "object-enchant/artifact.h"
+#include "object/object-hook.h"
+#include "player/avatar.h"
+#include "player/player-move.h"
+#include "spell/spells-type.h"
+#include "spell/spells2.h" // 相互参照している.
+#include "world/world.h"
+
+/*!
+ * @brief モンスターとの位置交換処理 / Switch position with a monster.
+ * @param caster_ptr プレーヤーへの参照ポインタ
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @return 作用が実際にあった場合TRUEを返す
+ */
+bool teleport_swap(player_type *caster_ptr, DIRECTION dir)
+{
+ POSITION tx, ty;
+ if ((dir == 5) && target_okay(caster_ptr)) {
+ tx = target_col;
+ ty = target_row;
+ } else {
+ tx = caster_ptr->x + ddx[dir];
+ ty = caster_ptr->y + ddy[dir];
+ }
+
+ if (caster_ptr->anti_tele) {
+ msg_print(_("不思議な力がテレポートを防いだ!", "A mysterious force prevents you from teleporting!"));
+ return FALSE;
+ }
+
+ grid_type *g_ptr;
+ g_ptr = &caster_ptr->current_floor_ptr->grid_array[ty][tx];
+ if (!g_ptr->m_idx || (g_ptr->m_idx == caster_ptr->riding)) {
+ msg_print(_("それとは場所を交換できません。", "You can't trade places with that!"));
+ return FALSE;
+ }
+
+ if ((g_ptr->info & CAVE_ICKY) || (distance(ty, tx, caster_ptr->y, caster_ptr->x) > caster_ptr->lev * 3 / 2 + 10)) {
+ msg_print(_("失敗した。", "Failed to swap."));
+ return FALSE;
+ }
+
+ monster_type *m_ptr;
+ monster_race *r_ptr;
+ m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
+ r_ptr = &r_info[m_ptr->r_idx];
+
+ (void)set_monster_csleep(caster_ptr, g_ptr->m_idx, 0);
+
+ if (r_ptr->flagsr & RFR_RES_TELE) {
+ msg_print(_("テレポートを邪魔された!", "Your teleportation is blocked!"));
+ if (is_original_ap_and_seen(caster_ptr, m_ptr))
+ r_ptr->r_flagsr |= RFR_RES_TELE;
+ return FALSE;
+ }
+
+ sound(SOUND_TELEPORT);
+ (void)move_player_effect(caster_ptr, ty, tx, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP);
+ return TRUE;
+}
+
+/*!
+ * @brief モンスター用テレポート処理
+ * @param caster_ptr プレーヤーへの参照ポインタ
+ * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
+ * @param distance 移動距離
+ * @return 作用が実際にあった場合TRUEを返す
+ */
+bool teleport_monster(player_type *caster_ptr, DIRECTION dir, int distance)
+{
+ BIT_FLAGS flg = PROJECT_BEAM | PROJECT_KILL;
+ return (project_hook(caster_ptr, GF_AWAY_ALL, dir, distance, flg));
+}
+
+/*!
+ * @brief モンスターのテレポートアウェイ処理 /
+ * Teleport a monster, normally up to "dis" grids away.
+ * @param caster_ptr プレーヤーへの参照ポインタ
+ * @param m_idx モンスターID
+ * @param dis テレポート距離
+ * @param mode オプション
+ * @return テレポートが実際に行われたらtrue
+ * @details
+ * Attempt to move the monster at least "dis/2" grids away.
+ * But allow variation to prevent infinite loops.
+ */
+bool teleport_away(player_type *caster_ptr, MONSTER_IDX m_idx, POSITION dis, teleport_flags mode)
+{
+ monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
+ if (!monster_is_valid(m_ptr))
+ return FALSE;
+
+ if ((mode & TELEPORT_DEC_VALOUR) && (((caster_ptr->chp * 10) / caster_ptr->mhp) > 5) && (4 + randint1(5) < ((caster_ptr->chp * 10) / caster_ptr->mhp))) {
+ chg_virtue(caster_ptr, V_VALOUR, -1);
+ }
+
+ POSITION oy = m_ptr->fy;
+ POSITION ox = m_ptr->fx;
+ POSITION min = dis / 2;
+ int tries = 0;
+ POSITION ny = 0, nx = 0;
+ bool look = TRUE;
+ while (look) {
+ tries++;
+ if (dis > 200)
+ dis = 200;
+
+ for (int i = 0; i < 500; i++) {
+ while (TRUE) {
+ ny = rand_spread(oy, dis);
+ nx = rand_spread(ox, dis);
+ POSITION d = distance(oy, ox, ny, nx);
+ if ((d >= min) && (d <= dis))
+ break;
+ }
+
+ if (!in_bounds(caster_ptr->current_floor_ptr, ny, nx))
+ continue;
+ if (!cave_monster_teleportable_bold(caster_ptr, m_idx, ny, nx, mode))
+ continue;
+ if (!(caster_ptr->current_floor_ptr->inside_quest || caster_ptr->current_floor_ptr->inside_arena))
+ if (caster_ptr->current_floor_ptr->grid_array[ny][nx].info & CAVE_ICKY)
+ continue;
+
+ look = FALSE;
+ break;
+ }
+
+ dis = dis * 2;
+ min = min / 2;
+ const int MAX_TELEPORT_TRIES = 100;
+ if (tries > MAX_TELEPORT_TRIES)
+ return FALSE;
+ }
+
+ sound(SOUND_TPOTHER);
+ caster_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = 0;
+ caster_ptr->current_floor_ptr->grid_array[ny][nx].m_idx = m_idx;
+
+ m_ptr->fy = ny;
+ m_ptr->fx = nx;
+
+ reset_target(m_ptr);
+ update_monster(caster_ptr, m_idx, TRUE);
+ lite_spot(caster_ptr, oy, ox);
+ lite_spot(caster_ptr, ny, nx);
+
+ if (r_info[m_ptr->r_idx].flags7 & (RF7_LITE_MASK | RF7_DARK_MASK))
+ caster_ptr->update |= (PU_MON_LITE);
+
+ return TRUE;
+}
+
+/*!
+ * @brief モンスターを指定された座標付近にテレポートする /
+ * Teleport monster next to a grid near the given location
+ * @param caster_ptr プレーヤーへの参照ポインタ
+ * @param m_idx モンスターID
+ * @param ty 目安Y座標
+ * @param tx 目安X座標
+ * @param power テレポート成功確率
+ * @param mode オプション
+ * @return なし
+ */
+void teleport_monster_to(player_type *caster_ptr, MONSTER_IDX m_idx, POSITION ty, POSITION tx, int power, teleport_flags mode)
+{
+ monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
+ if (!m_ptr->r_idx)
+ return;
+ if (randint1(100) > power)
+ return;
+
+ POSITION ny = m_ptr->fy;
+ POSITION nx = m_ptr->fx;
+ POSITION oy = m_ptr->fy;
+ POSITION ox = m_ptr->fx;
+
+ POSITION dis = 2;
+ int min = dis / 2;
+ int attempts = 500;
+ bool look = TRUE;
+ while (look && --attempts) {
+ if (dis > 200)
+ dis = 200;
+
+ for (int i = 0; i < 500; i++) {
+ while (TRUE) {
+ ny = rand_spread(ty, dis);
+ nx = rand_spread(tx, dis);
+ int d = distance(ty, tx, ny, nx);
+ if ((d >= min) && (d <= dis))
+ break;
+ }
+
+ if (!in_bounds(caster_ptr->current_floor_ptr, ny, nx))
+ continue;
+ if (!cave_monster_teleportable_bold(caster_ptr, m_idx, ny, nx, mode))
+ continue;
+
+ look = FALSE;
+ break;
+ }
+
+ dis = dis * 2;
+ min = min / 2;
+ }
+
+ if (attempts < 1)
+ return;
+
+ sound(SOUND_TPOTHER);
+ caster_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = 0;
+ caster_ptr->current_floor_ptr->grid_array[ny][nx].m_idx = m_idx;
+
+ m_ptr->fy = ny;
+ m_ptr->fx = nx;
+
+ update_monster(caster_ptr, m_idx, TRUE);
+ lite_spot(caster_ptr, oy, ox);
+ lite_spot(caster_ptr, ny, nx);
+
+ if (r_info[m_ptr->r_idx].flags7 & (RF7_LITE_MASK | RF7_DARK_MASK))
+ caster_ptr->update |= (PU_MON_LITE);
+}
+
+/*!
+ * @brief プレイヤーのテレポート先選定と移動処理 /
+ * Teleport the player to a location up to "dis" grids away.
+ * @param creature_ptr プレーヤーへの参照ポインタ
+ * @param dis 基本移動距離
+ * @param is_quantum_effect 量子的効果 (反テレポ無効)によるテレポートアウェイならばTRUE
+ * @param mode オプション
+ * @return 実際にテレポート処理が行われたらtrue
+ * @details
+ * <pre>
+ * If no such spaces are readily available, the distance may increase.
+ * Try very hard to move the player at least a quarter that distance.
+ *
+ * There was a nasty tendency for a long time; which was causing the
+ * player to "bounce" between two or three different spots because
+ * these are the only spots that are "far enough" way to satisfy the
+ * algorithm.
+ *
+ * But this tendency is now removed; in the new algorithm, a list of
+ * candidates is selected first, which includes at least 50% of all
+ * floor grids within the distance, and any single grid in this list
+ * of candidates has equal possibility to be choosen as a destination.
+ * </pre>
+ */
+bool teleport_player_aux(player_type *creature_ptr, POSITION dis, bool is_quantum_effect, teleport_flags mode)
+{
+ if (creature_ptr->wild_mode)
+ return FALSE;
+ if (!is_quantum_effect && creature_ptr->anti_tele && !(mode & TELEPORT_NONMAGICAL)) {
+ msg_print(_("不思議な力がテレポートを防いだ!", "A mysterious force prevents you from teleporting!"));
+ return FALSE;
+ }
+
+ int candidates_at[MAX_TELEPORT_DISTANCE + 1];
+ for (int i = 0; i <= MAX_TELEPORT_DISTANCE; i++)
+ candidates_at[i] = 0;
+
+ if (dis > MAX_TELEPORT_DISTANCE)
+ dis = MAX_TELEPORT_DISTANCE;
+
+ int left = MAX(1, creature_ptr->x - dis);
+ int right = MIN(creature_ptr->current_floor_ptr->width - 2, creature_ptr->x + dis);
+ int top = MAX(1, creature_ptr->y - dis);
+ int bottom = MIN(creature_ptr->current_floor_ptr->height - 2, creature_ptr->y + dis);
+ int total_candidates = 0;
+ for (POSITION y = top; y <= bottom; y++) {
+ for (POSITION x = left; x <= right; x++) {
+ if (!cave_player_teleportable_bold(creature_ptr, y, x, mode))
+ continue;
+
+ int d = distance(creature_ptr->y, creature_ptr->x, y, x);
+ if (d > dis)
+ continue;
+
+ total_candidates++;
+ candidates_at[d]++;
+ }
+ }
+
+ if (0 == total_candidates)
+ return FALSE;
+
+ int cur_candidates;
+ int min = dis;
+ for (cur_candidates = 0; min >= 0; min--) {
+ cur_candidates += candidates_at[min];
+ if (cur_candidates && (cur_candidates >= total_candidates / 2))
+ break;
+ }
+
+ int pick = randint1(cur_candidates);
+
+ /* Search again the choosen location */
+ POSITION yy, xx = 0;
+ for (yy = top; yy <= bottom; yy++) {
+ for (xx = left; xx <= right; xx++) {
+ if (!cave_player_teleportable_bold(creature_ptr, yy, xx, mode))
+ continue;
+
+ int d = distance(creature_ptr->y, creature_ptr->x, yy, xx);
+ if (d > dis)
+ continue;
+ if (d < min)
+ continue;
+
+ pick--;
+ if (!pick)
+ break;
+ }
+
+ if (!pick)
+ break;
+ }
+
+ if (player_bold(creature_ptr, yy, xx))
+ return FALSE;
+
+ sound(SOUND_TELEPORT);
+#ifdef JP
+ if (IS_ECHIZEN(creature_ptr))
+ msg_format("『こっちだぁ、%s』", creature_ptr->name);
+#endif
+ (void)move_player_effect(creature_ptr, yy, xx, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP);
+ return TRUE;
+}
+
+/*!
+ * @brief プレイヤーのテレポート処理メインルーチン
+ * @param creature_ptr プレーヤーへの参照ポインタ
+ * @param dis 基本移動距離
+ * @param mode オプション
+ * @return なし
+ */
+void teleport_player(player_type *creature_ptr, POSITION dis, BIT_FLAGS mode)
+{
+ if (!teleport_player_aux(creature_ptr, dis, FALSE, mode))
+ return;
+
+ /* Monsters with teleport ability may follow the player */
+ POSITION oy = creature_ptr->y;
+ POSITION ox = creature_ptr->x;
+ for (POSITION xx = -1; xx < 2; xx++) {
+ for (POSITION yy = -1; yy < 2; yy++) {
+ MONSTER_IDX tmp_m_idx = creature_ptr->current_floor_ptr->grid_array[oy + yy][ox + xx].m_idx;
+ if (tmp_m_idx && (creature_ptr->riding != tmp_m_idx)) {
+ continue;
+ }
+
+ 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;
+ is_resistible &= (r_ptr->flagsr & RFR_RES_TELE) == 0;
+ is_resistible &= MON_CSLEEP(m_ptr) == 0;
+ if (is_resistible) {
+ teleport_monster_to(creature_ptr, tmp_m_idx, creature_ptr->y, creature_ptr->x, r_ptr->level, TELEPORT_SPONTANEOUS);
+ }
+ }
+ }
+}
+
+/*!
+ * @brief プレイヤーのテレポートアウェイ処理 /
+ * @param m_idx アウェイを試みたモンスターID
+ * @param target_ptr プレーヤーへの参照ポインタ
+ * @param dis テレポート距離
+ * @param is_quantum_effect 量子的効果によるテレポートアウェイならばTRUE
+ * @return なし
+ */
+void teleport_player_away(MONSTER_IDX m_idx, player_type *target_ptr, POSITION dis, bool is_quantum_effect)
+{
+ if (!teleport_player_aux(target_ptr, dis, TELEPORT_PASSIVE, is_quantum_effect))
+ return;
+
+ /* Monsters with teleport ability may follow the player */
+ POSITION oy = target_ptr->y;
+ POSITION ox = target_ptr->x;
+ for (POSITION xx = -1; xx < 2; xx++) {
+ for (POSITION yy = -1; yy < 2; yy++) {
+ MONSTER_IDX tmp_m_idx = target_ptr->current_floor_ptr->grid_array[oy + yy][ox + xx].m_idx;
+ bool is_teleportable = tmp_m_idx > 0;
+ is_teleportable &= target_ptr->riding != tmp_m_idx;
+ is_teleportable &= m_idx != tmp_m_idx;
+ if (!is_teleportable) {
+ continue;
+ }
+
+ 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;
+ is_resistible &= (r_ptr->flagsr & RFR_RES_TELE) == 0;
+ is_resistible &= MON_CSLEEP(m_ptr) == 0;
+ if (is_resistible) {
+ teleport_monster_to(target_ptr, tmp_m_idx, target_ptr->y, target_ptr->x, r_ptr->level, TELEPORT_SPONTANEOUS);
+ }
+ }
+ }
+}
+
+/*!
+ * @brief プレイヤーを指定位置近辺にテレポートさせる
+ * Teleport player to a grid near the given location
+ * @param creature_ptr プレーヤーへの参照ポインタ
+ * @param ny 目標Y座標
+ * @param nx 目標X座標
+ * @param mode オプションフラグ
+ * @return なし
+ * @details
+ * <pre>
+ * This function is slightly obsessive about correctness.
+ * This function allows teleporting into vaults (!)
+ * </pre>
+ */
+void teleport_player_to(player_type *creature_ptr, POSITION ny, POSITION nx, teleport_flags mode)
+{
+ if (creature_ptr->anti_tele && !(mode & TELEPORT_NONMAGICAL)) {
+ msg_print(_("不思議な力がテレポートを防いだ!", "A mysterious force prevents you from teleporting!"));
+ return;
+ }
+
+ /* Find a usable location */
+ POSITION y, x;
+ POSITION dis = 0, ctr = 0;
+ while (TRUE) {
+ while (TRUE) {
+ y = (POSITION)rand_spread(ny, dis);
+ x = (POSITION)rand_spread(nx, dis);
+ if (in_bounds(creature_ptr->current_floor_ptr, y, x))
+ break;
+ }
+
+ bool is_anywhere = current_world_ptr->wizard;
+ is_anywhere &= (mode & TELEPORT_PASSIVE) == 0;
+ is_anywhere
+ &= (creature_ptr->current_floor_ptr->grid_array[y][x].m_idx > 0) || creature_ptr->current_floor_ptr->grid_array[y][x].m_idx == creature_ptr->riding;
+ if (is_anywhere)
+ break;
+
+ if (cave_player_teleportable_bold(creature_ptr, y, x, mode))
+ break;
+
+ if (++ctr > (4 * dis * dis + 4 * dis + 1)) {
+ ctr = 0;
+ dis++;
+ }
+ }
+
+ sound(SOUND_TELEPORT);
+ (void)move_player_effect(creature_ptr, y, x, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP);
+}
+
+void teleport_away_followable(player_type *tracer_ptr, MONSTER_IDX m_idx)
+{
+ monster_type *m_ptr = &tracer_ptr->current_floor_ptr->m_list[m_idx];
+ POSITION oldfy = m_ptr->fy;
+ POSITION oldfx = m_ptr->fx;
+ bool old_ml = m_ptr->ml;
+ POSITION old_cdis = m_ptr->cdis;
+
+ teleport_away(tracer_ptr, m_idx, MAX_SIGHT * 2 + 5, TELEPORT_SPONTANEOUS);
+
+ bool is_followable = old_ml;
+ is_followable &= old_cdis <= MAX_SIGHT;
+ is_followable &= current_world_ptr->timewalk_m_idx == 0;
+ is_followable &= !tracer_ptr->phase_out;
+ is_followable &= los(tracer_ptr, tracer_ptr->y, tracer_ptr->x, oldfy, oldfx);
+ if (!is_followable)
+ return;
+
+ bool follow = FALSE;
+ if ((tracer_ptr->muta1 & MUT1_VTELEPORT) || (tracer_ptr->pclass == CLASS_IMITATOR))
+ follow = TRUE;
+ else {
+ BIT_FLAGS flgs[TR_FLAG_SIZE];
+ object_type *o_ptr;
+ INVENTORY_IDX i;
+
+ for (i = INVEN_RARM; i < INVEN_TOTAL; i++) {
+ o_ptr = &tracer_ptr->inventory_list[i];
+ if (o_ptr->k_idx && !object_is_cursed(o_ptr)) {
+ object_flags(o_ptr, flgs);
+ if (have_flag(flgs, TR_TELEPORT)) {
+ follow = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!follow)
+ return;
+ if (!get_check_strict(_("ついていきますか?", "Do you follow it? "), CHECK_OKAY_CANCEL))
+ return;
+
+ if (one_in_(3)) {
+ teleport_player(tracer_ptr, 200, TELEPORT_PASSIVE);
+ msg_print(_("失敗!", "Failed!"));
+ } else {
+ teleport_player_to(tracer_ptr, m_ptr->fy, m_ptr->fx, TELEPORT_SPONTANEOUS);
+ }
+
+ tracer_ptr->energy_need += ENERGY_NEED();
+}
+
+bool teleport_level_other(player_type *caster_ptr)
+{
+ if (!target_set(caster_ptr, TARGET_KILL))
+ return FALSE;
+ MONSTER_IDX target_m_idx = caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx;
+ if (!target_m_idx)
+ return TRUE;
+ if (!player_has_los_bold(caster_ptr, target_row, target_col))
+ return TRUE;
+ if (!projectable(caster_ptr, caster_ptr->y, caster_ptr->x, target_row, target_col))
+ return TRUE;
+
+ monster_type *m_ptr;
+ monster_race *r_ptr;
+ m_ptr = &caster_ptr->current_floor_ptr->m_list[target_m_idx];
+ r_ptr = &r_info[m_ptr->r_idx];
+ GAME_TEXT m_name[MAX_NLEN];
+ monster_desc(caster_ptr, m_name, m_ptr, 0);
+ msg_format(_("%^sの足を指さした。", "You gesture at %^s's feet."), m_name);
+
+ if ((r_ptr->flagsr & (RFR_EFF_RES_NEXU_MASK | RFR_RES_TELE)) || (r_ptr->flags1 & RF1_QUESTOR)
+ || (r_ptr->level + randint1(50) > caster_ptr->lev + randint1(60))) {
+ msg_format(_("しかし効果がなかった!", "%^s is unaffected!"), m_name);
+ } else {
+ teleport_level(caster_ptr, target_m_idx);
+ }
+
+ return TRUE;
+}
+
+/*!
+ * todo cmd-save.h への依存あり。コールバックで何とかしたい
+ * @brief プレイヤー及びモンスターをレベルテレポートさせる /
+ * Teleport the player one level up or down (random when legal)
+ * @param creature_ptr プレーヤーへの参照ポインタ
+ * @param m_idx テレポートの対象となるモンスターID(0ならばプレイヤー) / If m_idx <= 0, target is player.
+ * @return なし
+ */
+void teleport_level(player_type *creature_ptr, MONSTER_IDX m_idx)
+{
+ GAME_TEXT m_name[160];
+ bool see_m = TRUE;
+ if (m_idx <= 0) {
+ strcpy(m_name, _("あなた", "you"));
+ } else {
+ monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx];
+ monster_desc(creature_ptr, m_name, m_ptr, 0);
+ see_m = is_seen(m_ptr);
+ }
+
+ if (is_teleport_level_ineffective(creature_ptr, m_idx)) {
+ if (see_m)
+ msg_print(_("効果がなかった。", "There is no effect."));
+ return;
+ }
+
+ if ((m_idx <= 0) && creature_ptr->anti_tele) {
+ msg_print(_("不思議な力がテレポートを防いだ!", "A mysterious force prevents you from teleporting!"));
+ return;
+ }
+
+ bool go_up;
+ if (randint0(100) < 50)
+ go_up = TRUE;
+ else
+ go_up = FALSE;
+
+ if ((m_idx <= 0) && current_world_ptr->wizard) {
+ if (get_check("Force to go up? "))
+ go_up = TRUE;
+ else if (get_check("Force to go down? "))
+ go_up = FALSE;
+ }
+
+ if ((ironman_downward && (m_idx <= 0)) || (creature_ptr->current_floor_ptr->dun_level <= d_info[creature_ptr->dungeon_idx].mindepth)) {
+#ifdef JP
+ if (see_m)
+ msg_format("%^sは床を突き破って沈んでいく。", m_name);
+#else
+ if (see_m)
+ msg_format("%^s sink%s through the floor.", m_name, (m_idx <= 0) ? "" : "s");
+#endif
+ if (m_idx <= 0) {
+ if (!creature_ptr->current_floor_ptr->dun_level) {
+ creature_ptr->dungeon_idx = ironman_downward ? DUNGEON_ANGBAND : creature_ptr->recall_dungeon;
+ creature_ptr->oldpy = creature_ptr->y;
+ creature_ptr->oldpx = creature_ptr->x;
+ }
+
+ if (record_stair)
+ exe_write_diary(creature_ptr, DIARY_TELEPORT_LEVEL, 1, NULL);
+
+ if (autosave_l)
+ do_cmd_save_game(creature_ptr, TRUE);
+
+ if (!creature_ptr->current_floor_ptr->dun_level) {
+ creature_ptr->current_floor_ptr->dun_level = d_info[creature_ptr->dungeon_idx].mindepth;
+ prepare_change_floor_mode(creature_ptr, CFM_RAND_PLACE);
+ } else {
+ prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_DOWN | CFM_RAND_PLACE | CFM_RAND_CONNECT);
+ }
+
+ creature_ptr->leaving = TRUE;
+ }
+ } else if (quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level)
+ || (creature_ptr->current_floor_ptr->dun_level >= d_info[creature_ptr->dungeon_idx].maxdepth)) {
+#ifdef JP
+ if (see_m)
+ msg_format("%^sは天井を突き破って宙へ浮いていく。", m_name);
+#else
+ if (see_m)
+ msg_format("%^s rise%s up through the ceiling.", m_name, (m_idx <= 0) ? "" : "s");
+#endif
+
+ if (m_idx <= 0) {
+ if (record_stair)
+ exe_write_diary(creature_ptr, DIARY_TELEPORT_LEVEL, -1, NULL);
+
+ if (autosave_l)
+ do_cmd_save_game(creature_ptr, TRUE);
+
+ prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_UP | CFM_RAND_PLACE | CFM_RAND_CONNECT);
+
+ leave_quest_check(creature_ptr);
+ creature_ptr->current_floor_ptr->inside_quest = 0;
+ creature_ptr->leaving = TRUE;
+ }
+ } else if (go_up) {
+#ifdef JP
+ if (see_m)
+ msg_format("%^sは天井を突き破って宙へ浮いていく。", m_name);
+#else
+ if (see_m)
+ msg_format("%^s rise%s up through the ceiling.", m_name, (m_idx <= 0) ? "" : "s");
+#endif
+
+ if (m_idx <= 0) {
+ if (record_stair)
+ exe_write_diary(creature_ptr, DIARY_TELEPORT_LEVEL, -1, NULL);
+
+ if (autosave_l)
+ do_cmd_save_game(creature_ptr, TRUE);
+
+ prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_UP | CFM_RAND_PLACE | CFM_RAND_CONNECT);
+ creature_ptr->leaving = TRUE;
+ }
+ } else {
+#ifdef JP
+ if (see_m)
+ msg_format("%^sは床を突き破って沈んでいく。", m_name);
+#else
+ if (see_m)
+ msg_format("%^s sink%s through the floor.", m_name, (m_idx <= 0) ? "" : "s");
+#endif
+
+ if (m_idx <= 0) {
+ if (record_stair)
+ exe_write_diary(creature_ptr, DIARY_TELEPORT_LEVEL, 1, NULL);
+ if (autosave_l)
+ do_cmd_save_game(creature_ptr, TRUE);
+
+ prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_DOWN | CFM_RAND_PLACE | CFM_RAND_CONNECT);
+ creature_ptr->leaving = TRUE;
+ }
+ }
+
+ if (m_idx <= 0) {
+ sound(SOUND_TPLEVEL);
+ return;
+ }
+
+ monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx];
+ check_quest_completion(creature_ptr, m_ptr);
+ if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname) {
+ char m2_name[MAX_NLEN];
+
+ monster_desc(creature_ptr, m2_name, m_ptr, MD_INDEF_VISIBLE);
+ exe_write_diary(creature_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_TELE_LEVEL, m2_name);
+ }
+
+ delete_monster_idx(creature_ptr, m_idx);
+ sound(SOUND_TPLEVEL);
+}
+
+/*!
+ * todo 変数名が実態と合っているかどうかは要確認
+ * テレポート・レベルが効かないモンスターであるかどうかを判定する
+ * @param caster_ptr プレーヤーへの参照ポインタ
+ * @param idx テレポート・レベル対象のモンスター
+ */
+bool is_teleport_level_ineffective(player_type *caster_ptr, MONSTER_IDX idx)
+{
+ floor_type *floor_ptr = caster_ptr->current_floor_ptr;
+ bool is_special_floor
+ = floor_ptr->inside_arena || caster_ptr->phase_out || (floor_ptr->inside_quest && !random_quest_number(caster_ptr, floor_ptr->dun_level));
+ bool is_invalid_floor = idx <= 0;
+ is_invalid_floor &= quest_number(caster_ptr, floor_ptr->dun_level) || (floor_ptr->dun_level >= d_info[caster_ptr->dungeon_idx].maxdepth);
+ is_invalid_floor &= caster_ptr->current_floor_ptr->dun_level >= 1;
+ is_invalid_floor &= ironman_downward;
+ return is_special_floor || is_invalid_floor;
+}
--- /dev/null
+#pragma once
+
+#include "system/angband.h"
+
+bool teleport_monster(player_type *caster_ptr, DIRECTION dir, int distance);
+bool teleport_swap(player_type *caster_ptr, DIRECTION dir);
+
+bool teleport_away(player_type *caster_ptr, MONSTER_IDX m_idx, POSITION dis, teleport_flags mode);
+void teleport_monster_to(player_type *caster_ptr, MONSTER_IDX m_idx, POSITION ty, POSITION tx, int power, teleport_flags mode);
+bool teleport_player_aux(player_type *creature_ptr, POSITION dis, bool is_quantum_effect, teleport_flags mode);
+void teleport_player(player_type *creature_ptr, POSITION dis, BIT_FLAGS mode);
+void teleport_player_away(MONSTER_IDX m_idx, player_type *target_ptr, POSITION dis, bool is_quantum_effect);
+void teleport_player_to(player_type *creature_ptr, POSITION ny, POSITION nx, teleport_flags mode);
+void teleport_away_followable(player_type *creature_ptr, MONSTER_IDX m_idx);
+bool teleport_level_other(player_type *caster_ptr);
+void teleport_level(player_type *creature_ptr, MONSTER_IDX m_idx);
+bool tele_town(player_type *caster_ptr);
+bool is_teleport_level_ineffective(player_type *caster_ptr, MONSTER_IDX idx);
#include "monster/monster-race.h"
#include "monster/monster-status.h"
#include "mutation/mutation.h"
-#include "object-enchant/artifact.h"
#include "object-enchant/item-feeling.h"
#include "object/item-use-flags.h"
#include "perception/object-perception.h"
#include "player/player-class.h"
#include "player/player-damage.h"
#include "player/player-effects.h"
-#include "player/player-move.h"
#include "player/player-skill.h"
#include "player/player-status.h"
#include "spell/process-effect.h"
#include "spell/spells-floor.h"
#include "spell/spells-status.h"
#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-type.h"
#include "spell/range-calc.h"
#include "spell/spells3.h"
/*!
- * @brief モンスターとの位置交換処理 / Switch position with a monster.
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
- * @return 作用が実際にあった場合TRUEを返す
- */
-bool teleport_swap(player_type *caster_ptr, DIRECTION dir)
-{
- POSITION tx, ty;
- if ((dir == 5) && target_okay(caster_ptr))
- {
- tx = target_col;
- ty = target_row;
- }
- else
- {
- tx = caster_ptr->x + ddx[dir];
- ty = caster_ptr->y + ddy[dir];
- }
-
- if (caster_ptr->anti_tele)
- {
- msg_print(_("不思議な力がテレポートを防いだ!", "A mysterious force prevents you from teleporting!"));
- return FALSE;
- }
-
- grid_type* g_ptr;
- g_ptr = &caster_ptr->current_floor_ptr->grid_array[ty][tx];
- if (!g_ptr->m_idx || (g_ptr->m_idx == caster_ptr->riding))
- {
- msg_print(_("それとは場所を交換できません。", "You can't trade places with that!"));
- return FALSE;
- }
-
- if ((g_ptr->info & CAVE_ICKY) || (distance(ty, tx, caster_ptr->y, caster_ptr->x) > caster_ptr->lev * 3 / 2 + 10))
- {
- msg_print(_("失敗した。", "Failed to swap."));
- return FALSE;
- }
-
- monster_type* m_ptr;
- monster_race* r_ptr;
- m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
- r_ptr = &r_info[m_ptr->r_idx];
-
- (void)set_monster_csleep(caster_ptr, g_ptr->m_idx, 0);
-
- if (r_ptr->flagsr & RFR_RES_TELE)
- {
- msg_print(_("テレポートを邪魔された!", "Your teleportation is blocked!"));
- if (is_original_ap_and_seen(caster_ptr, m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE;
- return FALSE;
- }
-
- sound(SOUND_TELEPORT);
- (void)move_player_effect(caster_ptr, ty, tx, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP);
- return TRUE;
-}
-
-
-/*!
* @brief 指定方向に飛び道具を飛ばす(フラグ任意指定) / Hack -- apply a "project()" in a direction (or at the target)
* @param caster_ptr プレーヤーへの参照ポインタ
* @param typ 効果属性
/*!
- * @brief モンスター用テレポート処理
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
- * @param distance 移動距離
- * @return 作用が実際にあった場合TRUEを返す
- */
-bool teleport_monster(player_type *caster_ptr, DIRECTION dir, int distance)
-{
- BIT_FLAGS flg = PROJECT_BEAM | PROJECT_KILL;
- return (project_hook(caster_ptr, GF_AWAY_ALL, dir, distance, flg));
-}
-
-
-/*!
* @brief ドア生成処理(プレイヤー中心に周囲1マス) / Hooks -- affect adjacent grids (radius 1 ball attack)
* @param caster_ptr プレーヤーへの参照ポインタ
* @return 作用が実際にあった場合TRUEを返す
bool destroy_door(player_type* caster_ptr, DIRECTION dir);
bool disarm_trap(player_type* caster_ptr, DIRECTION dir);
bool wizard_lock(player_type* caster_ptr, DIRECTION dir);
-bool teleport_monster(player_type* caster_ptr, DIRECTION dir, int distance);
bool door_creation(player_type* caster_ptr, POSITION y, POSITION x);
bool trap_creation(player_type* caster_ptr, POSITION y, POSITION x);
bool tree_creation(player_type* caster_ptr, POSITION y, POSITION x);
bool control_one_demon(player_type* caster_ptr, DIRECTION dir, PLAYER_LEVEL plev);
bool charm_animal(player_type* caster_ptr, DIRECTION dir, PLAYER_LEVEL plev);
bool mindblast_monsters(player_type* caster_ptr, HIT_POINT dam);
-bool teleport_swap(player_type* caster_ptr, DIRECTION dir);
bool project_hook(player_type* caster_ptr, EFFECT_ID typ, DIRECTION dir, HIT_POINT dam, BIT_FLAGS flg);
bool project_all_los(player_type* caster_ptr, EFFECT_ID typ, HIT_POINT dam);
bool eat_magic(player_type* caster_ptr, int power);
#include "cmd-action/cmd-attack.h"
#include "cmd-action/cmd-spell.h"
#include "cmd-io/cmd-dump.h"
-#include "cmd-io/cmd-save.h"
#include "cmd-building/cmd-building.h"
#include "combat/snipe.h"
#include "core/stuff-handler.h"
#include "io/files-util.h"
#include "io/targeting.h"
#include "io/write-diary.h"
-#include "main/sound-definitions-table.h"
#include "market/building-util.h"
#include "mind/mind.h"
#include "mind/racial-force-trainer.h"
#include "spell/spells-execution.h"
#include "spell/spells-floor.h"
#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells2.h"
#include "spell/technic-info-table.h"
#include "term/gameterm.h"
#include "view/display-main-window.h"
#include "world/world.h"
-/*! テレポート先探索の試行数 / Maximum number of tries for teleporting */
-#define MAX_TRIES 100
-
// todo コピペ感が強くなったので関数化
static bool update_player(player_type *caster_ptr);
static bool redraw_player(player_type *caster_ptr);
/*!
- * @brief モンスターのテレポートアウェイ処理 /
- * Teleport a monster, normally up to "dis" grids away.
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param m_idx モンスターID
- * @param dis テレポート距離
- * @param mode オプション
- * @return テレポートが実際に行われたらtrue
- * @details
- * Attempt to move the monster at least "dis/2" grids away.
- * But allow variation to prevent infinite loops.
- */
-bool teleport_away(player_type *caster_ptr, MONSTER_IDX m_idx, POSITION dis, teleport_flags mode)
-{
- monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
- if (!monster_is_valid(m_ptr)) return FALSE;
-
- if ((mode & TELEPORT_DEC_VALOUR) &&
- (((caster_ptr->chp * 10) / caster_ptr->mhp) > 5) &&
- (4+randint1(5) < ((caster_ptr->chp * 10) / caster_ptr->mhp)))
- {
- chg_virtue(caster_ptr, V_VALOUR, -1);
- }
-
- POSITION oy = m_ptr->fy;
- POSITION ox = m_ptr->fx;
- POSITION min = dis / 2;
- int tries = 0;
- POSITION ny = 0, nx = 0;
- bool look = TRUE;
- while (look)
- {
- tries++;
- if (dis > 200) dis = 200;
-
- for (int i = 0; i < 500; i++)
- {
- while (TRUE)
- {
- ny = rand_spread(oy, dis);
- nx = rand_spread(ox, dis);
- POSITION d = distance(oy, ox, ny, nx);
- if ((d >= min) && (d <= dis)) break;
- }
-
- if (!in_bounds(caster_ptr->current_floor_ptr, ny, nx)) continue;
- if (!cave_monster_teleportable_bold(caster_ptr, m_idx, ny, nx, mode)) continue;
- if (!(caster_ptr->current_floor_ptr->inside_quest || caster_ptr->current_floor_ptr->inside_arena))
- if (caster_ptr->current_floor_ptr->grid_array[ny][nx].info & CAVE_ICKY) continue;
-
- look = FALSE;
- break;
- }
-
- dis = dis * 2;
- min = min / 2;
- if (tries > MAX_TRIES) return FALSE;
- }
-
- sound(SOUND_TPOTHER);
- caster_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = 0;
- caster_ptr->current_floor_ptr->grid_array[ny][nx].m_idx = m_idx;
-
- m_ptr->fy = ny;
- m_ptr->fx = nx;
-
- reset_target(m_ptr);
- update_monster(caster_ptr, m_idx, TRUE);
- lite_spot(caster_ptr, oy, ox);
- lite_spot(caster_ptr, ny, nx);
-
- if (r_info[m_ptr->r_idx].flags7 & (RF7_LITE_MASK | RF7_DARK_MASK))
- caster_ptr->update |= (PU_MON_LITE);
-
- return TRUE;
-}
-
-
-/*!
- * @brief モンスターを指定された座標付近にテレポートする /
- * Teleport monster next to a grid near the given location
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param m_idx モンスターID
- * @param ty 目安Y座標
- * @param tx 目安X座標
- * @param power テレポート成功確率
- * @param mode オプション
- * @return なし
- */
-void teleport_monster_to(player_type *caster_ptr, MONSTER_IDX m_idx, POSITION ty, POSITION tx, int power, teleport_flags mode)
-{
- monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
- if(!m_ptr->r_idx) return;
- if(randint1(100) > power) return;
-
- POSITION ny = m_ptr->fy;
- POSITION nx = m_ptr->fx;
- POSITION oy = m_ptr->fy;
- POSITION ox = m_ptr->fx;
-
- POSITION dis = 2;
- int min = dis / 2;
- int attempts = 500;
- bool look = TRUE;
- while (look && --attempts)
- {
- if (dis > 200) dis = 200;
-
- for (int i = 0; i < 500; i++)
- {
- while (TRUE)
- {
- ny = rand_spread(ty, dis);
- nx = rand_spread(tx, dis);
- int d = distance(ty, tx, ny, nx);
- if ((d >= min) && (d <= dis)) break;
- }
-
- if (!in_bounds(caster_ptr->current_floor_ptr, ny, nx)) continue;
- if (!cave_monster_teleportable_bold(caster_ptr, m_idx, ny, nx, mode)) continue;
-
- look = FALSE;
- break;
- }
-
- dis = dis * 2;
- min = min / 2;
- }
-
- if (attempts < 1) return;
-
- sound(SOUND_TPOTHER);
- caster_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = 0;
- caster_ptr->current_floor_ptr->grid_array[ny][nx].m_idx = m_idx;
-
- m_ptr->fy = ny;
- m_ptr->fx = nx;
-
- update_monster(caster_ptr, m_idx, TRUE);
- lite_spot(caster_ptr, oy, ox);
- lite_spot(caster_ptr, ny, nx);
-
- if (r_info[m_ptr->r_idx].flags7 & (RF7_LITE_MASK | RF7_DARK_MASK))
- caster_ptr->update |= (PU_MON_LITE);
-}
-
-
-/*!
- * @brief プレイヤーのテレポート先選定と移動処理 /
- * Teleport the player to a location up to "dis" grids away.
- * @param creature_ptr プレーヤーへの参照ポインタ
- * @param dis 基本移動距離
- * @param is_quantum_effect 量子的効果 (反テレポ無効)によるテレポートアウェイならばTRUE
- * @param mode オプション
- * @return 実際にテレポート処理が行われたらtrue
- * @details
- * <pre>
- * If no such spaces are readily available, the distance may increase.
- * Try very hard to move the player at least a quarter that distance.
- *
- * There was a nasty tendency for a long time; which was causing the
- * player to "bounce" between two or three different spots because
- * these are the only spots that are "far enough" way to satisfy the
- * algorithm.
- *
- * But this tendency is now removed; in the new algorithm, a list of
- * candidates is selected first, which includes at least 50% of all
- * floor grids within the distance, and any single grid in this list
- * of candidates has equal possibility to be choosen as a destination.
- * </pre>
- */
-bool teleport_player_aux(player_type *creature_ptr, POSITION dis, bool is_quantum_effect, teleport_flags mode)
-{
- if (creature_ptr->wild_mode) return FALSE;
- if (!is_quantum_effect && creature_ptr->anti_tele && !(mode & TELEPORT_NONMAGICAL))
- {
- msg_print(_("不思議な力がテレポートを防いだ!", "A mysterious force prevents you from teleporting!"));
- return FALSE;
- }
-
- int candidates_at[MAX_TELEPORT_DISTANCE + 1];
- for (int i = 0; i <= MAX_TELEPORT_DISTANCE; i++)
- candidates_at[i] = 0;
-
- if (dis > MAX_TELEPORT_DISTANCE) dis = MAX_TELEPORT_DISTANCE;
-
- int left = MAX(1, creature_ptr->x - dis);
- int right = MIN(creature_ptr->current_floor_ptr->width - 2, creature_ptr->x + dis);
- int top = MAX(1, creature_ptr->y - dis);
- int bottom = MIN(creature_ptr->current_floor_ptr->height - 2, creature_ptr->y + dis);
- int total_candidates = 0;
- for (POSITION y = top; y <= bottom; y++)
- {
- for (POSITION x = left; x <= right; x++)
- {
- if (!cave_player_teleportable_bold(creature_ptr, y, x, mode)) continue;
-
- int d = distance(creature_ptr->y, creature_ptr->x, y, x);
- if (d > dis) continue;
-
- total_candidates++;
- candidates_at[d]++;
- }
- }
-
- if (0 == total_candidates) return FALSE;
-
- int cur_candidates;
- int min = dis;
- for (cur_candidates = 0; min >= 0; min--)
- {
- cur_candidates += candidates_at[min];
- if (cur_candidates && (cur_candidates >= total_candidates / 2)) break;
- }
-
- int pick = randint1(cur_candidates);
-
- /* Search again the choosen location */
- POSITION yy, xx = 0;
- for (yy = top; yy <= bottom; yy++)
- {
- for (xx = left; xx <= right; xx++)
- {
- if (!cave_player_teleportable_bold(creature_ptr, yy, xx, mode)) continue;
-
- int d = distance(creature_ptr->y, creature_ptr->x, yy, xx);
- if (d > dis) continue;
- if (d < min) continue;
-
- pick--;
- if (!pick) break;
- }
-
- if (!pick) break;
- }
-
- if (player_bold(creature_ptr, yy, xx)) return FALSE;
-
- sound(SOUND_TELEPORT);
-#ifdef JP
- if (IS_ECHIZEN(creature_ptr))
- msg_format("『こっちだぁ、%s』", creature_ptr->name);
-#endif
- (void)move_player_effect(creature_ptr, yy, xx, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP);
- return TRUE;
-}
-
-
-/*!
- * @brief プレイヤーのテレポート処理メインルーチン
- * @param creature_ptr プレーヤーへの参照ポインタ
- * @param dis 基本移動距離
- * @param mode オプション
- * @return なし
- */
-void teleport_player(player_type *creature_ptr, POSITION dis, BIT_FLAGS mode)
-{
- if (!teleport_player_aux(creature_ptr, dis, FALSE, mode)) return;
-
- /* Monsters with teleport ability may follow the player */
- POSITION oy = creature_ptr->y;
- POSITION ox = creature_ptr->x;
- for (POSITION xx = -1; xx < 2; xx++)
- {
- for (POSITION yy = -1; yy < 2; yy++)
- {
- MONSTER_IDX tmp_m_idx = creature_ptr->current_floor_ptr->grid_array[oy+yy][ox+xx].m_idx;
- if (tmp_m_idx && (creature_ptr->riding != tmp_m_idx))
- {
- continue;
- }
-
- 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;
- is_resistible &= (r_ptr->flagsr & RFR_RES_TELE) == 0;
- is_resistible &= MON_CSLEEP(m_ptr) == 0;
- if (is_resistible)
- {
- teleport_monster_to(creature_ptr, tmp_m_idx, creature_ptr->y, creature_ptr->x, r_ptr->level, TELEPORT_SPONTANEOUS);
- }
- }
- }
-}
-
-
-/*!
- * @brief プレイヤーのテレポートアウェイ処理 /
- * @param m_idx アウェイを試みたモンスターID
- * @param target_ptr プレーヤーへの参照ポインタ
- * @param dis テレポート距離
- * @param is_quantum_effect 量子的効果によるテレポートアウェイならばTRUE
- * @return なし
- */
-void teleport_player_away(MONSTER_IDX m_idx, player_type *target_ptr, POSITION dis, bool is_quantum_effect)
-{
- if (!teleport_player_aux(target_ptr, dis, TELEPORT_PASSIVE, is_quantum_effect)) return;
-
- /* Monsters with teleport ability may follow the player */
- POSITION oy = target_ptr->y;
- POSITION ox = target_ptr->x;
- for (POSITION xx = -1; xx < 2; xx++)
- {
- for (POSITION yy = -1; yy < 2; yy++)
- {
- MONSTER_IDX tmp_m_idx = target_ptr->current_floor_ptr->grid_array[oy+yy][ox+xx].m_idx;
- bool is_teleportable = tmp_m_idx > 0;
- is_teleportable &= target_ptr->riding != tmp_m_idx;
- is_teleportable &= m_idx != tmp_m_idx;
- if (!is_teleportable)
- {
- continue;
- }
-
- 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;
- is_resistible &= (r_ptr->flagsr & RFR_RES_TELE) == 0;
- is_resistible &= MON_CSLEEP(m_ptr) == 0;
- if (is_resistible)
- {
- teleport_monster_to(target_ptr, tmp_m_idx, target_ptr->y, target_ptr->x, r_ptr->level, TELEPORT_SPONTANEOUS);
- }
- }
- }
-}
-
-
-/*!
- * @brief プレイヤーを指定位置近辺にテレポートさせる
- * Teleport player to a grid near the given location
- * @param creature_ptr プレーヤーへの参照ポインタ
- * @param ny 目標Y座標
- * @param nx 目標X座標
- * @param mode オプションフラグ
- * @return なし
- * @details
- * <pre>
- * This function is slightly obsessive about correctness.
- * This function allows teleporting into vaults (!)
- * </pre>
- */
-void teleport_player_to(player_type *creature_ptr, POSITION ny, POSITION nx, teleport_flags mode)
-{
- if (creature_ptr->anti_tele && !(mode & TELEPORT_NONMAGICAL))
- {
- msg_print(_("不思議な力がテレポートを防いだ!", "A mysterious force prevents you from teleporting!"));
- return;
- }
-
- /* Find a usable location */
- POSITION y, x;
- POSITION dis = 0, ctr = 0;
- while (TRUE)
- {
- while (TRUE)
- {
- y = (POSITION)rand_spread(ny, dis);
- x = (POSITION)rand_spread(nx, dis);
- if (in_bounds(creature_ptr->current_floor_ptr, y, x)) break;
- }
-
- bool is_anywhere = current_world_ptr->wizard;
- is_anywhere &= (mode & TELEPORT_PASSIVE) == 0;
- is_anywhere &= (creature_ptr->current_floor_ptr->grid_array[y][x].m_idx > 0) ||
- creature_ptr->current_floor_ptr->grid_array[y][x].m_idx == creature_ptr->riding;
- if (is_anywhere) break;
-
- if (cave_player_teleportable_bold(creature_ptr, y, x, mode)) break;
-
- if (++ctr > (4 * dis * dis + 4 * dis + 1))
- {
- ctr = 0;
- dis++;
- }
- }
-
- sound(SOUND_TELEPORT);
- (void)move_player_effect(creature_ptr, y, x, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP);
-}
-
-
-void teleport_away_followable(player_type *tracer_ptr, MONSTER_IDX m_idx)
-{
- monster_type *m_ptr = &tracer_ptr->current_floor_ptr->m_list[m_idx];
- POSITION oldfy = m_ptr->fy;
- POSITION oldfx = m_ptr->fx;
- bool old_ml = m_ptr->ml;
- POSITION old_cdis = m_ptr->cdis;
-
- teleport_away(tracer_ptr, m_idx, MAX_SIGHT * 2 + 5, TELEPORT_SPONTANEOUS);
-
- bool is_followable = old_ml;
- is_followable &= old_cdis <= MAX_SIGHT;
- is_followable &= current_world_ptr->timewalk_m_idx == 0;
- is_followable &= !tracer_ptr->phase_out;
- is_followable &= los(tracer_ptr, tracer_ptr->y, tracer_ptr->x, oldfy, oldfx);
- if (!is_followable) return;
-
- bool follow = FALSE;
- if ((tracer_ptr->muta1 & MUT1_VTELEPORT) || (tracer_ptr->pclass == CLASS_IMITATOR)) follow = TRUE;
- else
- {
- BIT_FLAGS flgs[TR_FLAG_SIZE];
- object_type *o_ptr;
- INVENTORY_IDX i;
-
- for (i = INVEN_RARM; i < INVEN_TOTAL; i++)
- {
- o_ptr = &tracer_ptr->inventory_list[i];
- if (o_ptr->k_idx && !object_is_cursed(o_ptr))
- {
- object_flags(o_ptr, flgs);
- if (have_flag(flgs, TR_TELEPORT))
- {
- follow = TRUE;
- break;
- }
- }
- }
- }
-
- if (!follow) return;
- if (!get_check_strict(_("ついていきますか?", "Do you follow it? "), CHECK_OKAY_CANCEL))
- return;
-
- if (one_in_(3))
- {
- teleport_player(tracer_ptr, 200, TELEPORT_PASSIVE);
- msg_print(_("失敗!", "Failed!"));
- }
- else
- {
- teleport_player_to(tracer_ptr, m_ptr->fy, m_ptr->fx, TELEPORT_SPONTANEOUS);
- }
-
- tracer_ptr->energy_need += ENERGY_NEED();
-}
-
-
-bool teleport_level_other(player_type *caster_ptr)
-{
- if (!target_set(caster_ptr, TARGET_KILL)) return FALSE;
- MONSTER_IDX target_m_idx = caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx;
- if (!target_m_idx) return TRUE;
- if (!player_has_los_bold(caster_ptr, target_row, target_col)) return TRUE;
- if (!projectable(caster_ptr, caster_ptr->y, caster_ptr->x, target_row, target_col)) return TRUE;
-
- monster_type *m_ptr;
- monster_race *r_ptr;
- m_ptr = &caster_ptr->current_floor_ptr->m_list[target_m_idx];
- r_ptr = &r_info[m_ptr->r_idx];
- GAME_TEXT m_name[MAX_NLEN];
- monster_desc(caster_ptr, m_name, m_ptr, 0);
- msg_format(_("%^sの足を指さした。", "You gesture at %^s's feet."), m_name);
-
- if ((r_ptr->flagsr & (RFR_EFF_RES_NEXU_MASK | RFR_RES_TELE)) ||
- (r_ptr->flags1 & RF1_QUESTOR) || (r_ptr->level + randint1(50) > caster_ptr->lev + randint1(60)))
- {
- msg_format(_("しかし効果がなかった!", "%^s is unaffected!"), m_name);
- }
- else
- {
- teleport_level(caster_ptr, target_m_idx);
- }
-
- return TRUE;
-}
-
-
-/*!
- * todo cmd-save.h への依存あり。コールバックで何とかしたい
- * @brief プレイヤー及びモンスターをレベルテレポートさせる /
- * Teleport the player one level up or down (random when legal)
- * @param creature_ptr プレーヤーへの参照ポインタ
- * @param m_idx テレポートの対象となるモンスターID(0ならばプレイヤー) / If m_idx <= 0, target is player.
- * @return なし
- */
-void teleport_level(player_type *creature_ptr, MONSTER_IDX m_idx)
-{
- GAME_TEXT m_name[160];
- bool see_m = TRUE;
- if (m_idx <= 0)
- {
- strcpy(m_name, _("あなた", "you"));
- }
- else
- {
- monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx];
- monster_desc(creature_ptr, m_name, m_ptr, 0);
- see_m = is_seen(m_ptr);
- }
-
- if (is_teleport_level_ineffective(creature_ptr, m_idx))
- {
- if (see_m) msg_print(_("効果がなかった。", "There is no effect."));
- return;
- }
-
- if ((m_idx <= 0) && creature_ptr->anti_tele)
- {
- msg_print(_("不思議な力がテレポートを防いだ!", "A mysterious force prevents you from teleporting!"));
- return;
- }
-
- bool go_up;
- if (randint0(100) < 50) go_up = TRUE;
- else go_up = FALSE;
-
- if ((m_idx <= 0) && current_world_ptr->wizard)
- {
- if (get_check("Force to go up? ")) go_up = TRUE;
- else if (get_check("Force to go down? ")) go_up = FALSE;
- }
-
- if ((ironman_downward && (m_idx <= 0)) || (creature_ptr->current_floor_ptr->dun_level <= d_info[creature_ptr->dungeon_idx].mindepth))
- {
-#ifdef JP
- if (see_m) msg_format("%^sは床を突き破って沈んでいく。", m_name);
-#else
- if (see_m) msg_format("%^s sink%s through the floor.", m_name, (m_idx <= 0) ? "" : "s");
-#endif
- if (m_idx <= 0)
- {
- if (!creature_ptr->current_floor_ptr->dun_level)
- {
- creature_ptr->dungeon_idx = ironman_downward ? DUNGEON_ANGBAND : creature_ptr->recall_dungeon;
- creature_ptr->oldpy = creature_ptr->y;
- creature_ptr->oldpx = creature_ptr->x;
- }
-
- if (record_stair) exe_write_diary(creature_ptr, DIARY_TELEPORT_LEVEL, 1, NULL);
-
- if (autosave_l) do_cmd_save_game(creature_ptr, TRUE);
-
- if (!creature_ptr->current_floor_ptr->dun_level)
- {
- creature_ptr->current_floor_ptr->dun_level = d_info[creature_ptr->dungeon_idx].mindepth;
- prepare_change_floor_mode(creature_ptr, CFM_RAND_PLACE);
- }
- else
- {
- prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_DOWN | CFM_RAND_PLACE | CFM_RAND_CONNECT);
- }
-
- creature_ptr->leaving = TRUE;
- }
- }
- else if (quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level) || (creature_ptr->current_floor_ptr->dun_level >= d_info[creature_ptr->dungeon_idx].maxdepth))
- {
-#ifdef JP
- if (see_m) msg_format("%^sは天井を突き破って宙へ浮いていく。", m_name);
-#else
- if (see_m) msg_format("%^s rise%s up through the ceiling.", m_name, (m_idx <= 0) ? "" : "s");
-#endif
-
- if (m_idx <= 0)
- {
- if (record_stair) exe_write_diary(creature_ptr, DIARY_TELEPORT_LEVEL, -1, NULL);
-
- if (autosave_l) do_cmd_save_game(creature_ptr, TRUE);
-
- prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_UP | CFM_RAND_PLACE | CFM_RAND_CONNECT);
-
- leave_quest_check(creature_ptr);
- creature_ptr->current_floor_ptr->inside_quest = 0;
- creature_ptr->leaving = TRUE;
- }
- }
- else if (go_up)
- {
-#ifdef JP
- if (see_m) msg_format("%^sは天井を突き破って宙へ浮いていく。", m_name);
-#else
- if (see_m) msg_format("%^s rise%s up through the ceiling.", m_name, (m_idx <= 0) ? "" : "s");
-#endif
-
- if (m_idx <= 0)
- {
- if (record_stair) exe_write_diary(creature_ptr, DIARY_TELEPORT_LEVEL, -1, NULL);
-
- if (autosave_l) do_cmd_save_game(creature_ptr, TRUE);
-
- prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_UP | CFM_RAND_PLACE | CFM_RAND_CONNECT);
- creature_ptr->leaving = TRUE;
- }
- }
- else
- {
-#ifdef JP
- if (see_m) msg_format("%^sは床を突き破って沈んでいく。", m_name);
-#else
- if (see_m) msg_format("%^s sink%s through the floor.", m_name, (m_idx <= 0) ? "" : "s");
-#endif
-
- if (m_idx <= 0)
- {
- if (record_stair) exe_write_diary(creature_ptr, DIARY_TELEPORT_LEVEL, 1, NULL);
- if (autosave_l) do_cmd_save_game(creature_ptr, TRUE);
-
- prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_DOWN | CFM_RAND_PLACE | CFM_RAND_CONNECT);
- creature_ptr->leaving = TRUE;
- }
- }
-
- if (m_idx <= 0)
- {
- sound(SOUND_TPLEVEL);
- return;
- }
-
- monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx];
- check_quest_completion(creature_ptr, m_ptr);
- if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname)
- {
- char m2_name[MAX_NLEN];
-
- monster_desc(creature_ptr, m2_name, m_ptr, MD_INDEF_VISIBLE);
- exe_write_diary(creature_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_TELE_LEVEL, m2_name);
- }
-
- delete_monster_idx(creature_ptr, m_idx);
- sound(SOUND_TPLEVEL);
-}
-
-
-/*!
* @brief プレイヤーの帰還発動及び中止処理 /
* Recall the player to town or dungeon
* @param creature_ptr プレーヤーへの参照ポインタ
}
-/*!
-* todo 変数名が実態と合っているかどうかは要確認
-* テレポート・レベルが効かないモンスターであるかどうかを判定する
-* @param caster_ptr プレーヤーへの参照ポインタ
-* @param idx テレポート・レベル対象のモンスター
-*/
-bool is_teleport_level_ineffective(player_type *caster_ptr, MONSTER_IDX idx)
-{
- floor_type *floor_ptr = caster_ptr->current_floor_ptr;
- bool is_special_floor = floor_ptr->inside_arena || caster_ptr->phase_out ||
- (floor_ptr->inside_quest && !random_quest_number(caster_ptr, floor_ptr->dun_level));
- bool is_invalid_floor = idx <= 0;
- is_invalid_floor &= quest_number(caster_ptr, floor_ptr->dun_level) || (floor_ptr->dun_level >= d_info[caster_ptr->dungeon_idx].maxdepth);
- is_invalid_floor &= caster_ptr->current_floor_ptr->dun_level >= 1;
- is_invalid_floor &= ironman_downward;
- return is_special_floor || is_invalid_floor;
-}
-
-
static bool update_player(player_type *caster_ptr)
{
caster_ptr->update |= PU_COMBINE | PU_REORDER;
#include "system/angband.h"
#include "spell/spells-util.h"
-bool teleport_away(player_type* caster_ptr, MONSTER_IDX m_idx, POSITION dis, teleport_flags mode);
-void teleport_monster_to(player_type* caster_ptr, MONSTER_IDX m_idx, POSITION ty, POSITION tx, int power, teleport_flags mode);
-bool teleport_player_aux(player_type* creature_ptr, POSITION dis, bool is_quantum_effect, teleport_flags mode);
-void teleport_player(player_type* creature_ptr, POSITION dis, BIT_FLAGS mode);
-void teleport_player_away(MONSTER_IDX m_idx, player_type* target_ptr, POSITION dis, bool is_quantum_effect);
-void teleport_player_to(player_type* creature_ptr, POSITION ny, POSITION nx, teleport_flags mode);
-void teleport_away_followable(player_type* creature_ptr, MONSTER_IDX m_idx);
-bool teleport_level_other(player_type* caster_ptr);
-void teleport_level(player_type* creature_ptr, MONSTER_IDX m_idx);
bool recall_player(player_type* creature_ptr, TIME_EFFECT turns);
bool free_level_recall(player_type* creature_ptr);
bool reset_recall(player_type* caster_ptr);
bool detonation(player_type* creature_ptr);
void blood_curse_to_enemy(player_type* caster_ptr, MONSTER_IDX m_idx);
bool fire_crimson(player_type* shooter_ptr);
-bool tele_town(player_type* caster_ptr);
-bool is_teleport_level_ineffective(player_type* caster_ptr, MONSTER_IDX idx);
#include "spell/spells-object.h"
#include "spell/spells-status.h"
#include "spell/spells-summon.h"
+#include "spell/spells-teleport.h"
#include "spell/spells-util.h"
#include "spell/spells-world.h"
#include "spell/spells2.h"