2 * @brief 魔法効果の実装/ Spell code (part 3)
6 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
7 * This software may be copied and distributed for educational, research,
8 * and not for profit purposes provided that this copyright and statement
9 * are included in all such copies. Other copyrights may also apply.
13 #include "spell/spells3.h"
14 #include "autopick/autopick.h"
15 #include "cmd-action/cmd-attack.h"
16 #include "cmd-action/cmd-spell.h"
17 #include "cmd-building/cmd-building.h"
18 #include "cmd-io/cmd-dump.h"
19 #include "core/asking-player.h"
20 #include "core/speed-table.h"
21 #include "core/stuff-handler.h"
22 #include "dungeon/dungeon.h"
23 #include "dungeon/quest.h"
24 #include "effect/effect-characteristics.h"
25 #include "effect/spells-effect-util.h"
26 #include "floor/floor-object.h"
27 #include "floor/floor-save.h"
28 #include "floor/floor-town.h"
29 #include "floor/wild.h"
30 #include "game-option/auto-destruction-options.h"
31 #include "game-option/birth-options.h"
32 #include "game-option/disturbance-options.h"
33 #include "game-option/input-options.h"
34 #include "game-option/play-record-options.h"
35 #include "grid/grid.h"
36 #include "inventory/inventory-object.h"
37 #include "inventory/player-inventory.h"
38 #include "io/input-key-acceptor.h"
39 #include "io/input-key-requester.h"
40 #include "io/targeting.h"
41 #include "io/write-diary.h"
42 #include "lore/lore-calculator.h"
43 #include "market/building-util.h"
44 #include "mind/mind-force-trainer.h"
45 #include "mind/mind-sniper.h"
46 #include "mind/mind.h"
47 #include "monster-floor/monster-generator.h"
48 #include "monster-floor/monster-remover.h"
49 #include "monster-floor/monster-summon.h"
50 #include "monster-floor/place-monster-types.h"
51 #include "monster-race/monster-race.h"
52 #include "monster-race/race-flags1.h"
53 #include "monster-race/race-flags7.h"
54 #include "monster/monster-describer.h"
55 #include "monster/monster-flag-types.h"
56 #include "monster/monster-info.h"
57 #include "monster/monster-list.h"
58 #include "monster/monster-processor.h"
59 #include "monster/monster-status.h"
60 #include "monster/monster-update.h"
61 #include "monster/monster-util.h"
62 #include "object-enchant/artifact.h"
63 #include "object-enchant/item-feeling.h"
64 #include "object-enchant/object-boost.h"
65 #include "object-enchant/object-ego.h"
66 #include "object-enchant/special-object-flags.h"
67 #include "object-enchant/tr-types.h"
68 #include "object-enchant/trc-types.h"
69 #include "object-hook/hook-enchant.h"
70 #include "object-hook/hook-expendable.h"
71 #include "object-hook/hook-perception.h"
72 #include "object-hook/hook-magic.h"
73 #include "object-hook/hook-weapon.h"
74 #include "object/item-use-flags.h"
75 #include "object/object-flavor.h"
76 #include "object/object-generator.h"
77 #include "object/object-hook.h"
78 #include "object/object-info.h"
79 #include "object/object-kind.h"
80 #include "object/object-mark-types.h"
81 #include "object/object-value.h"
82 #include "perception/identification.h"
83 #include "perception/object-perception.h"
84 #include "player/avatar.h"
85 #include "player/bad-status-setter.h"
86 #include "player/player-class.h"
87 #include "player/player-damage.h"
88 #include "player/player-effects.h"
89 #include "player/player-move.h"
90 #include "player/player-personalities-types.h"
91 #include "player/player-skill.h"
92 #include "player/player-status.h"
93 #include "realm/realm-names-table.h"
94 #include "spell-kind/earthquake.h"
95 #include "spell-kind/spells-floor.h"
96 #include "spell-kind/spells-launcher.h"
97 #include "spell-kind/spells-sight.h"
98 #include "spell-kind/spells-teleport.h"
99 #include "spell/process-effect.h"
100 #include "spell/spell-types.h"
101 #include "spell/spells-execution.h"
102 #include "spell/spells-summon.h"
103 #include "spell/technic-info-table.h"
104 #include "term/screen-processor.h"
105 #include "term/term-color-types.h"
106 #include "util/bit-flags-calculator.h"
107 #include "util/int-char-converter.h"
108 #include "view/display-messages.h"
109 #include "world/world.h"
112 * @brief プレイヤーの装備劣化処理 /
113 * Apply disenchantment to the player's stuff
114 * @param target_ptr プレーヤーへの参照ポインタ
115 * @param mode 最下位ビットが1ならば劣化処理が若干低減される
116 * @return 劣化処理に関するメッセージが発せられた場合はTRUEを返す /
117 * Return "TRUE" if the player notices anything
119 bool apply_disenchant(player_type *target_ptr, BIT_FLAGS mode)
122 switch (randint1(8)) {
150 o_ptr = &target_ptr->inventory_list[t];
154 if (!object_is_weapon_armour_ammo(target_ptr, o_ptr))
157 if ((o_ptr->to_h <= 0) && (o_ptr->to_d <= 0) && (o_ptr->to_a <= 0) && (o_ptr->pval <= 1)) {
161 GAME_TEXT o_name[MAX_NLEN];
162 object_desc(target_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
163 if (object_is_artifact(o_ptr) && (randint0(100) < 71)) {
165 msg_format("%s(%c)は劣化を跳ね返した!", o_name, index_to_label(t));
167 msg_format("Your %s (%c) resist%s disenchantment!", o_name, index_to_label(t), ((o_ptr->number != 1) ? "" : "s"));
172 int to_h = o_ptr->to_h;
173 int to_d = o_ptr->to_d;
174 int to_a = o_ptr->to_a;
175 int pval = o_ptr->pval;
179 if ((o_ptr->to_h > 5) && (randint0(100) < 20))
184 if ((o_ptr->to_d > 5) && (randint0(100) < 20))
189 if ((o_ptr->to_a > 5) && (randint0(100) < 20))
192 if ((o_ptr->pval > 1) && one_in_(13) && !(mode & 0x01))
195 bool is_actually_disenchanted = to_h != o_ptr->to_h;
196 is_actually_disenchanted |= to_d != o_ptr->to_d;
197 is_actually_disenchanted |= to_a != o_ptr->to_a;
198 is_actually_disenchanted |= pval != o_ptr->pval;
199 if (!is_actually_disenchanted)
203 msg_format("%s(%c)は劣化してしまった!", o_name, index_to_label(t));
205 msg_format("Your %s (%c) %s disenchanted!", o_name, index_to_label(t), ((o_ptr->number != 1) ? "were" : "was"));
207 chg_virtue(target_ptr, V_HARMONY, 1);
208 chg_virtue(target_ptr, V_ENCHANT, -2);
209 target_ptr->update |= (PU_BONUS);
210 target_ptr->window |= (PW_EQUIP | PW_PLAYER);
212 calc_android_exp(target_ptr);
217 * @brief アイテム引き寄せ処理 /
218 * Fetch an item (teleport it right underneath the caster)
219 * @param caster_ptr プレーヤーへの参照ポインタ
222 * @param require_los 射線の通りを要求するならばTRUE
225 void fetch(player_type *caster_ptr, DIRECTION dir, WEIGHT wgt, bool require_los)
229 GAME_TEXT o_name[MAX_NLEN];
231 if (caster_ptr->current_floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].o_idx) {
232 msg_print(_("自分の足の下にある物は取れません。", "You can't fetch when you're already standing on something."));
237 if (dir == 5 && target_okay(caster_ptr)) {
241 if (distance(caster_ptr->y, caster_ptr->x, ty, tx) > get_max_range(caster_ptr)) {
242 msg_print(_("そんなに遠くにある物は取れません!", "You can't fetch something that far away!"));
246 g_ptr = &caster_ptr->current_floor_ptr->grid_array[ty][tx];
248 msg_print(_("そこには何もありません。", "There is no object at this place."));
252 if (g_ptr->info & CAVE_ICKY) {
253 msg_print(_("アイテムがコントロールを外れて落ちた。", "The item slips from your control."));
258 if (!player_has_los_bold(caster_ptr, ty, tx)) {
259 msg_print(_("そこはあなたの視界に入っていません。", "You have no direct line of sight to that location."));
261 } else if (!projectable(caster_ptr, caster_ptr->y, caster_ptr->x, ty, tx)) {
262 msg_print(_("そこは壁の向こうです。", "You have no direct line of sight to that location."));
269 bool is_first_loop = TRUE;
270 g_ptr = &caster_ptr->current_floor_ptr->grid_array[ty][tx];
271 while (is_first_loop || !g_ptr->o_idx) {
272 is_first_loop = FALSE;
275 g_ptr = &caster_ptr->current_floor_ptr->grid_array[ty][tx];
277 if ((distance(caster_ptr->y, caster_ptr->x, ty, tx) > get_max_range(caster_ptr))
278 || !cave_have_flag_bold(caster_ptr->current_floor_ptr, ty, tx, FF_PROJECT))
283 o_ptr = &caster_ptr->current_floor_ptr->o_list[g_ptr->o_idx];
284 if (o_ptr->weight > wgt) {
285 msg_print(_("そのアイテムは重過ぎます。", "The object is too heavy."));
289 OBJECT_IDX i = g_ptr->o_idx;
290 g_ptr->o_idx = o_ptr->next_o_idx;
291 caster_ptr->current_floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].o_idx = i; /* 'move' it */
293 o_ptr->next_o_idx = 0;
294 o_ptr->iy = caster_ptr->y;
295 o_ptr->ix = caster_ptr->x;
297 object_desc(caster_ptr, o_name, o_ptr, OD_NAME_ONLY);
298 msg_format(_("%^sがあなたの足元に飛んできた。", "%^s flies through the air to your feet."), o_name);
300 note_spot(caster_ptr, caster_ptr->y, caster_ptr->x);
301 caster_ptr->redraw |= PR_MAP;
306 * @param caster_ptr プレーヤーへの参照ポインタ
309 void reserve_alter_reality(player_type *caster_ptr)
311 if (caster_ptr->current_floor_ptr->inside_arena || ironman_downward) {
312 msg_print(_("何も起こらなかった。", "Nothing happens."));
316 if (caster_ptr->alter_reality) {
317 caster_ptr->alter_reality = 0;
318 msg_print(_("景色が元に戻った...", "The view around you returns to normal..."));
319 caster_ptr->redraw |= PR_STATUS;
323 TIME_EFFECT turns = randint0(21) + 15;
324 caster_ptr->alter_reality = turns;
325 msg_print(_("回りの景色が変わり始めた...", "The view around you begins to change..."));
326 caster_ptr->redraw |= PR_STATUS;
330 * @brief アイテムの価値に応じた錬金術処理 /
331 * Turns an object into gold, gain some of its value in a shop
332 * @param caster_ptr プレーヤーへの参照ポインタ
333 * @return 処理が実際に行われたらTRUEを返す
335 bool alchemy(player_type *caster_ptr)
341 concptr q = _("どのアイテムを金に変えますか?", "Turn which item to gold? ");
342 concptr s = _("金に変えられる物がありません。", "You have nothing to turn to gold.");
345 o_ptr = choose_object(caster_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), 0);
350 if (o_ptr->number > 1) {
351 amt = get_quantity(NULL, o_ptr->number);
356 ITEM_NUMBER old_number = o_ptr->number;
358 GAME_TEXT o_name[MAX_NLEN];
359 object_desc(caster_ptr, o_name, o_ptr, 0);
360 o_ptr->number = old_number;
363 if (confirm_destroy || (object_value(caster_ptr, o_ptr) > 0)) {
364 char out_val[MAX_NLEN + 40];
365 sprintf(out_val, _("本当に%sを金に変えますか?", "Really turn %s to gold? "), o_name);
366 if (!get_check(out_val))
371 if (!can_player_destroy_object(caster_ptr, o_ptr)) {
372 msg_format(_("%sを金に変えることに失敗した。", "You fail to turn %s to gold!"), o_name);
376 PRICE price = object_value_real(caster_ptr, o_ptr);
378 msg_format(_("%sをニセの金に変えた。", "You turn %s to fool's gold."), o_name);
379 vary_item(caster_ptr, item, -amt);
390 msg_format(_("%sを$%d の金に変えた。", "You turn %s to %ld coins worth of gold."), o_name, price);
392 caster_ptr->au += price;
393 caster_ptr->redraw |= PR_GOLD;
394 caster_ptr->window |= PW_PLAYER;
395 vary_item(caster_ptr, item, -amt);
400 * @brief アーティファクト生成の巻物処理 /
401 * @param caster_ptr プレーヤーへの参照ポインタ
402 * @return 生成が実際に試みられたらTRUEを返す
404 bool artifact_scroll(player_type *caster_ptr)
406 item_tester_hook = item_tester_hook_nameless_weapon_armour;
408 concptr q = _("どのアイテムを強化しますか? ", "Enchant which item? ");
409 concptr s = _("強化できるアイテムがない。", "You have nothing to enchant.");
412 o_ptr = choose_object(caster_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0);
416 GAME_TEXT o_name[MAX_NLEN];
417 object_desc(caster_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
419 msg_format("%s は眩い光を発した!", o_name);
421 msg_format("%s %s radiate%s a blinding light!", ((item >= 0) ? "Your" : "The"), o_name, ((o_ptr->number > 1) ? "" : "s"));
425 if (object_is_artifact(o_ptr)) {
427 msg_format("%sは既に伝説のアイテムです!", o_name);
429 msg_format("The %s %s already %s!", o_name, ((o_ptr->number > 1) ? "are" : "is"), ((o_ptr->number > 1) ? "artifacts" : "an artifact"));
432 } else if (object_is_ego(o_ptr)) {
434 msg_format("%sは既に名のあるアイテムです!", o_name);
436 msg_format("The %s %s already %s!", o_name, ((o_ptr->number > 1) ? "are" : "is"), ((o_ptr->number > 1) ? "ego items" : "an ego item"));
439 } else if (o_ptr->xtra3) {
441 msg_format("%sは既に強化されています!", o_name);
443 msg_format("The %s %s already %s!", o_name, ((o_ptr->number > 1) ? "are" : "is"), ((o_ptr->number > 1) ? "customized items" : "a customized item"));
446 if (o_ptr->number > 1) {
447 msg_print(_("複数のアイテムに魔法をかけるだけのエネルギーはありません!", "Not enough energy to enchant more than one object!"));
449 msg_format("%d 個の%sが壊れた!", (o_ptr->number) - 1, o_name);
451 msg_format("%d of your %s %s destroyed!", (o_ptr->number) - 1, o_name, (o_ptr->number > 2 ? "were" : "was"));
455 inven_item_increase(caster_ptr, item, 1 - (o_ptr->number));
457 floor_item_increase(caster_ptr->current_floor_ptr, 0 - item, 1 - (o_ptr->number));
461 okay = become_random_artifact(caster_ptr, o_ptr, TRUE);
467 msg_print(_("強化に失敗した。", "The enchantment failed."));
469 chg_virtue(caster_ptr, V_ENCHANT, -1);
470 calc_android_exp(caster_ptr);
474 if (record_rand_art) {
475 object_desc(caster_ptr, o_name, o_ptr, OD_NAME_ONLY);
476 exe_write_diary(caster_ptr, DIARY_ART_SCROLL, 0, o_name);
479 chg_virtue(caster_ptr, V_ENCHANT, 1);
480 calc_android_exp(caster_ptr);
485 * @brief アイテム凡庸化のメインルーチン処理 /
486 * Identify an object in the inventory (or on the floor)
487 * @param owner_ptr プレーヤーへの参照ポインタ
488 * @param only_equip 装備品のみを対象とするならばTRUEを返す
489 * @return 実際に凡庸化をを行ったならばTRUEを返す
492 * Mundanify an object in the inventory (or on the floor)
493 * This routine does *not* automatically combine objects.
494 * Returns TRUE if something was mundanified, else FALSE.
497 bool mundane_spell(player_type *owner_ptr, bool only_equip)
500 item_tester_hook = object_is_weapon_armour_ammo;
504 concptr q = _("どれを使いますか?", "Use which item? ");
505 concptr s = _("使えるものがありません。", "You have nothing you can use.");
507 o_ptr = choose_object(owner_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0);
511 msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!"));
512 POSITION iy = o_ptr->iy;
513 POSITION ix = o_ptr->ix;
514 OBJECT_IDX next_o_idx = o_ptr->next_o_idx;
515 byte marked = o_ptr->marked;
516 WEIGHT weight = o_ptr->number * o_ptr->weight;
517 u16b inscription = o_ptr->inscription;
519 object_prep(owner_ptr, o_ptr, o_ptr->k_idx);
523 o_ptr->next_o_idx = next_o_idx;
524 o_ptr->marked = marked;
525 o_ptr->inscription = inscription;
527 owner_ptr->total_weight += (o_ptr->weight - weight);
529 calc_android_exp(owner_ptr);
535 * Recharge a wand/staff/rod from the pack or on the floor.
536 * This function has been rewritten in Oangband and ZAngband.
537 * @param caster_ptr プレーヤーへの参照ポインタ
539 * @return ターン消費を要する処理まで進んだらTRUEを返す
541 * Sorcery/Arcane -- Recharge --> recharge(plev * 4)
542 * Chaos -- Arcane Binding --> recharge(90)
544 * Scroll of recharging --> recharge(130)
545 * Artifact activation/Thingol --> recharge(130)
547 * It is harder to recharge high level, and highly charged wands,
548 * staffs, and rods. The more wands in a stack, the more easily and
549 * strongly they recharge. Staffs, however, each get fewer charges if
552 * Beware of "sliding index errors".
554 bool recharge(player_type *caster_ptr, int power)
556 item_tester_hook = item_tester_hook_recharge;
557 concptr q = _("どのアイテムに魔力を充填しますか? ", "Recharge which item? ");
558 concptr s = _("魔力を充填すべきアイテムがない。", "You have nothing to recharge.");
562 o_ptr = choose_object(caster_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), 0);
567 k_ptr = &k_info[o_ptr->k_idx];
568 DEPTH lev = k_info[o_ptr->k_idx].level;
570 TIME_EFFECT recharge_amount;
571 int recharge_strength;
572 bool is_recharge_successful = TRUE;
573 if (o_ptr->tval == TV_ROD) {
574 recharge_strength = ((power > lev / 2) ? (power - lev / 2) : 0) / 5;
575 if (one_in_(recharge_strength)) {
576 is_recharge_successful = FALSE;
578 recharge_amount = (power * damroll(3, 2));
579 if (o_ptr->timeout > recharge_amount)
580 o_ptr->timeout -= recharge_amount;
585 if ((o_ptr->tval == TV_WAND) && (o_ptr->number > 1))
586 recharge_strength = (100 + power - lev - (8 * o_ptr->pval / o_ptr->number)) / 15;
588 recharge_strength = (100 + power - lev - (8 * o_ptr->pval)) / 15;
590 if (recharge_strength < 0)
591 recharge_strength = 0;
593 if (one_in_(recharge_strength)) {
594 is_recharge_successful = FALSE;
596 recharge_amount = randint1(1 + k_ptr->pval / 2);
597 if ((o_ptr->tval == TV_WAND) && (o_ptr->number > 1)) {
598 recharge_amount += (randint1(recharge_amount * (o_ptr->number - 1))) / 2;
599 if (recharge_amount < 1)
601 if (recharge_amount > 12)
602 recharge_amount = 12;
605 if ((o_ptr->tval == TV_STAFF) && (o_ptr->number > 1)) {
606 recharge_amount /= (TIME_EFFECT)o_ptr->number;
607 if (recharge_amount < 1)
611 o_ptr->pval += recharge_amount;
612 o_ptr->ident &= ~(IDENT_KNOWN);
613 o_ptr->ident &= ~(IDENT_EMPTY);
617 if (!is_recharge_successful) {
618 return update_player(caster_ptr);
622 GAME_TEXT o_name[MAX_NLEN];
623 if (object_is_fixed_artifact(o_ptr)) {
624 object_desc(caster_ptr, o_name, o_ptr, OD_NAME_ONLY);
625 msg_format(_("魔力が逆流した!%sは完全に魔力を失った。", "The recharging backfires - %s is completely drained!"), o_name);
626 if ((o_ptr->tval == TV_ROD) && (o_ptr->timeout < 10000))
627 o_ptr->timeout = (o_ptr->timeout + 100) * 2;
628 else if ((o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_STAFF))
630 return update_player(caster_ptr);
633 object_desc(caster_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
635 if (IS_WIZARD_CLASS(caster_ptr) || caster_ptr->pclass == CLASS_MAGIC_EATER || caster_ptr->pclass == CLASS_BLUE_MAGE) {
636 /* 10% chance to blow up one rod, otherwise draining. */
637 if (o_ptr->tval == TV_ROD) {
643 /* 75% chance to blow up one wand, otherwise draining. */
644 else if (o_ptr->tval == TV_WAND) {
650 /* 50% chance to blow up one staff, otherwise no effect. */
651 else if (o_ptr->tval == TV_STAFF) {
658 /* 33% chance to blow up one rod, otherwise draining. */
659 if (o_ptr->tval == TV_ROD) {
665 /* 20% chance of the entire stack, else destroy one wand. */
666 else if (o_ptr->tval == TV_WAND) {
672 /* Blow up one staff. */
673 else if (o_ptr->tval == TV_STAFF) {
678 if (fail_type == 1) {
679 if (o_ptr->tval == TV_ROD) {
680 msg_print(_("魔力が逆噴射して、ロッドからさらに魔力を吸い取ってしまった!", "The recharge backfires, draining the rod further!"));
682 if (o_ptr->timeout < 10000)
683 o_ptr->timeout = (o_ptr->timeout + 100) * 2;
684 } else if (o_ptr->tval == TV_WAND) {
685 msg_format(_("%sは破損を免れたが、魔力が全て失われた。", "You save your %s from destruction, but all charges are lost."), o_name);
690 if (fail_type == 2) {
691 if (o_ptr->number > 1)
692 msg_format(_("乱暴な魔法のために%sが一本壊れた!", "Wild magic consumes one of your %s!"), o_name);
694 msg_format(_("乱暴な魔法のために%sが壊れた!", "Wild magic consumes your %s!"), o_name);
696 if (o_ptr->tval == TV_ROD)
697 o_ptr->timeout = (o_ptr->number - 1) * k_ptr->pval;
698 if (o_ptr->tval == TV_WAND)
701 vary_item(caster_ptr, item, -1);
704 if (fail_type == 3) {
705 if (o_ptr->number > 1)
706 msg_format(_("乱暴な魔法のために%sが全て壊れた!", "Wild magic consumes all your %s!"), o_name);
708 msg_format(_("乱暴な魔法のために%sが壊れた!", "Wild magic consumes your %s!"), o_name);
710 vary_item(caster_ptr, item, -999);
713 return update_player(caster_ptr);
717 * @brief クリーチャー全既知呪文を表示する /
718 * Hack -- Display all known spells in a window
719 * @param caster_ptr 術者の参照ポインタ
722 * Need to analyze size of the window.
723 * Need more color coding.
725 void display_spell_list(player_type *caster_ptr)
729 const magic_type *s_ptr;
730 GAME_TEXT name[MAX_NLEN];
735 if (caster_ptr->pclass == CLASS_SORCERER)
737 if (caster_ptr->pclass == CLASS_RED_MAGE)
739 if (caster_ptr->pclass == CLASS_SNIPER) {
740 display_snipe_list(caster_ptr);
744 if ((caster_ptr->pclass == CLASS_MINDCRAFTER) || (caster_ptr->pclass == CLASS_BERSERKER) || (caster_ptr->pclass == CLASS_NINJA)
745 || (caster_ptr->pclass == CLASS_MIRROR_MASTER) || (caster_ptr->pclass == CLASS_FORCETRAINER)) {
746 PERCENTAGE minfail = 0;
747 PLAYER_LEVEL plev = caster_ptr->lev;
748 PERCENTAGE chance = 0;
759 put_str(_("名前", "Name"), y, x + 5);
760 put_str(_("Lv MP 失率 効果", "Lv Mana Fail Info"), y, x + 35);
762 switch (caster_ptr->pclass) {
763 case CLASS_MINDCRAFTER:
764 use_mind = MIND_MINDCRAFTER;
766 case CLASS_FORCETRAINER:
769 case CLASS_BERSERKER:
770 use_mind = MIND_BERSERKER;
773 case CLASS_MIRROR_MASTER:
774 use_mind = MIND_MIRROR_MASTER;
777 use_mind = MIND_NINJUTSU;
785 for (int i = 0; i < MAX_MIND_POWERS; i++) {
787 spell = mind_powers[use_mind].info[i];
788 if (spell.min_lev > plev)
792 chance -= 3 * (caster_ptr->lev - spell.min_lev);
793 chance -= 3 * (adj_mag_stat[caster_ptr->stat_ind[mp_ptr->spell_stat]] - 1);
795 if (spell.mana_cost > caster_ptr->csp) {
796 chance += 5 * (spell.mana_cost - caster_ptr->csp);
800 if (spell.mana_cost > caster_ptr->chp) {
806 minfail = adj_mag_fail[caster_ptr->stat_ind[mp_ptr->spell_stat]];
807 if (chance < minfail)
810 if (caster_ptr->stun > 50)
812 else if (caster_ptr->stun)
818 mindcraft_info(caster_ptr, comment, use_mind, i);
819 sprintf(psi_desc, " %c) %-30s%2d %4d %3d%%%s", I2A(i), spell.name, spell.min_lev, spell.mana_cost, chance, comment);
821 Term_putstr(x, y + i + 1, -1, a, psi_desc);
827 if (REALM_NONE == caster_ptr->realm1)
830 for (int j = 0; j < ((caster_ptr->realm2 > REALM_NONE) ? 2 : 1); j++) {
832 y = (j < 3) ? 0 : (m[j - 3] + 2);
835 for (int i = 0; i < 32; i++) {
838 if (!is_magic((j < 1) ? caster_ptr->realm1 : caster_ptr->realm2)) {
839 s_ptr = &technic_info[((j < 1) ? caster_ptr->realm1 : caster_ptr->realm2) - MIN_TECHNIC][i % 32];
841 s_ptr = &mp_ptr->info[((j < 1) ? caster_ptr->realm1 : caster_ptr->realm2) - 1][i % 32];
844 strcpy(name, exe_spell(caster_ptr, (j < 1) ? caster_ptr->realm1 : caster_ptr->realm2, i % 32, SPELL_NAME));
846 if (s_ptr->slevel >= 99) {
847 strcpy(name, _("(判読不能)", "(illegible)"));
849 } else if ((j < 1) ? ((caster_ptr->spell_forgotten1 & (1L << i))) : ((caster_ptr->spell_forgotten2 & (1L << (i % 32))))) {
851 } else if (!((j < 1) ? (caster_ptr->spell_learned1 & (1L << i)) : (caster_ptr->spell_learned2 & (1L << (i % 32))))) {
853 } else if (!((j < 1) ? (caster_ptr->spell_worked1 & (1L << i)) : (caster_ptr->spell_worked2 & (1L << (i % 32))))) {
857 sprintf(out_val, "%c/%c) %-20.20s", I2A(n / 8), I2A(n % 8), name);
860 Term_putstr(x, m[j], -1, a, out_val);
867 * @brief 変身処理向けにモンスターの近隣レベル帯モンスターを返す /
868 * Helper function -- return a "nearby" race for polymorphing
869 * @param floor_ptr 配置するフロアの参照ポインタ
870 * @param r_idx 基準となるモンスター種族ID
871 * @return 変更先のモンスター種族ID
873 * Note that this function is one of the more "dangerous" ones...
875 static MONRACE_IDX poly_r_idx(player_type *caster_ptr, MONRACE_IDX r_idx)
877 monster_race *r_ptr = &r_info[r_idx];
878 if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags1 & RF1_QUESTOR))
881 DEPTH lev1 = r_ptr->level - ((randint1(20) / randint1(9)) + 1);
882 DEPTH lev2 = r_ptr->level + ((randint1(20) / randint1(9)) + 1);
884 for (int i = 0; i < 1000; i++) {
885 r = get_mon_num(caster_ptr, (caster_ptr->current_floor_ptr->dun_level + r_ptr->level) / 2 + 5, 0);
890 if (r_ptr->flags1 & RF1_UNIQUE)
892 if ((r_ptr->level < lev1) || (r_ptr->level > lev2))
903 * @brief 指定座標にいるモンスターを変身させる /
904 * Helper function -- return a "nearby" race for polymorphing
905 * @param caster_ptr プレーヤーへの参照ポインタ
908 * @return 実際に変身したらTRUEを返す
910 bool polymorph_monster(player_type *caster_ptr, POSITION y, POSITION x)
912 floor_type *floor_ptr = caster_ptr->current_floor_ptr;
913 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
914 monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
915 MONRACE_IDX new_r_idx;
916 MONRACE_IDX old_r_idx = m_ptr->r_idx;
917 bool targeted = (target_who == g_ptr->m_idx) ? TRUE : FALSE;
918 bool health_tracked = (caster_ptr->health_who == g_ptr->m_idx) ? TRUE : FALSE;
920 if (floor_ptr->inside_arena || caster_ptr->phase_out)
922 if ((caster_ptr->riding == g_ptr->m_idx) || (m_ptr->mflag2 & MFLAG2_KAGE))
925 monster_type back_m = *m_ptr;
926 new_r_idx = poly_r_idx(caster_ptr, old_r_idx);
927 if (new_r_idx == old_r_idx)
930 bool preserve_hold_objects = back_m.hold_o_idx ? TRUE : FALSE;
931 OBJECT_IDX this_o_idx, next_o_idx = 0;
934 if (is_friendly(m_ptr))
935 mode |= PM_FORCE_FRIENDLY;
937 mode |= PM_FORCE_PET;
938 if (m_ptr->mflag2 & MFLAG2_NOPET)
941 m_ptr->hold_o_idx = 0;
942 delete_monster_idx(caster_ptr, g_ptr->m_idx);
943 bool polymorphed = FALSE;
944 if (place_monster_aux(caster_ptr, 0, y, x, new_r_idx, mode)) {
945 floor_ptr->m_list[hack_m_idx_ii].nickname = back_m.nickname;
946 floor_ptr->m_list[hack_m_idx_ii].parent_m_idx = back_m.parent_m_idx;
947 floor_ptr->m_list[hack_m_idx_ii].hold_o_idx = back_m.hold_o_idx;
950 if (place_monster_aux(caster_ptr, 0, y, x, old_r_idx, (mode | PM_NO_KAGE | PM_IGNORE_TERRAIN))) {
951 floor_ptr->m_list[hack_m_idx_ii] = back_m;
952 mproc_init(floor_ptr);
954 preserve_hold_objects = FALSE;
957 if (preserve_hold_objects) {
958 for (this_o_idx = back_m.hold_o_idx; this_o_idx; this_o_idx = next_o_idx) {
959 object_type *o_ptr = &floor_ptr->o_list[this_o_idx];
960 next_o_idx = o_ptr->next_o_idx;
961 o_ptr->held_m_idx = hack_m_idx_ii;
963 } else if (back_m.hold_o_idx) {
964 for (this_o_idx = back_m.hold_o_idx; this_o_idx; this_o_idx = next_o_idx) {
965 next_o_idx = floor_ptr->o_list[this_o_idx].next_o_idx;
966 delete_object_idx(caster_ptr, this_o_idx);
971 target_who = hack_m_idx_ii;
973 health_track(caster_ptr, hack_m_idx_ii);
978 * @brief 皆殺し(全方向攻撃)処理
979 * @param caster_ptr プレーヤーへの参照ポインタ
982 void massacre(player_type *caster_ptr)
986 for (DIRECTION dir = 0; dir < 8; dir++) {
987 POSITION y = caster_ptr->y + ddy_ddd[dir];
988 POSITION x = caster_ptr->x + ddx_ddd[dir];
989 g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
990 m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
991 if (g_ptr->m_idx && (m_ptr->ml || cave_have_flag_bold(caster_ptr->current_floor_ptr, y, x, FF_PROJECT)))
992 do_cmd_attack(caster_ptr, y, x, 0);
998 * @param caster_ptr プレーヤーへの参照ポインタ
999 * @return コマンドの入力方向に地形があればTRUE
1001 bool eat_rock(player_type *caster_ptr)
1004 if (!get_direction(caster_ptr, &dir, FALSE, FALSE))
1006 POSITION y = caster_ptr->y + ddy[dir];
1007 POSITION x = caster_ptr->x + ddx[dir];
1009 g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
1010 feature_type *f_ptr, *mimic_f_ptr;
1011 f_ptr = &f_info[g_ptr->feat];
1012 mimic_f_ptr = &f_info[get_feat_mimic(g_ptr)];
1014 stop_mouth(caster_ptr);
1015 if (!have_flag(mimic_f_ptr->flags, FF_HURT_ROCK)) {
1016 msg_print(_("この地形は食べられない。", "You cannot eat this feature."));
1017 } else if (have_flag(f_ptr->flags, FF_PERMANENT)) {
1018 msg_format(_("いてっ!この%sはあなたの歯より硬い!", "Ouch! This %s is harder than your teeth!"), f_name + mimic_f_ptr->name);
1019 } else if (g_ptr->m_idx) {
1020 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
1021 msg_print(_("何かが邪魔しています!", "There's something in the way!"));
1023 if (!m_ptr->ml || !is_pet(m_ptr))
1024 do_cmd_attack(caster_ptr, y, x, 0);
1025 } else if (have_flag(f_ptr->flags, FF_TREE)) {
1026 msg_print(_("木の味は好きじゃない!", "You don't like the woody taste!"));
1027 } else if (have_flag(f_ptr->flags, FF_GLASS)) {
1028 msg_print(_("ガラスの味は好きじゃない!", "You don't like the glassy taste!"));
1029 } else if (have_flag(f_ptr->flags, FF_DOOR) || have_flag(f_ptr->flags, FF_CAN_DIG)) {
1030 (void)set_food(caster_ptr, caster_ptr->food + 3000);
1031 } else if (have_flag(f_ptr->flags, FF_MAY_HAVE_GOLD) || have_flag(f_ptr->flags, FF_HAS_GOLD)) {
1032 (void)set_food(caster_ptr, caster_ptr->food + 5000);
1034 msg_format(_("この%sはとてもおいしい!", "This %s is very filling!"), f_name + mimic_f_ptr->name);
1035 (void)set_food(caster_ptr, caster_ptr->food + 10000);
1038 cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK);
1039 (void)move_player_effect(caster_ptr, y, x, MPE_DONT_PICKUP);
1043 bool shock_power(player_type *caster_ptr)
1045 int boost = get_current_ki(caster_ptr);
1046 if (heavy_armor(caster_ptr))
1051 if (!get_aim_dir(caster_ptr, &dir))
1054 POSITION y = caster_ptr->y + ddy[dir];
1055 POSITION x = caster_ptr->x + ddx[dir];
1056 PLAYER_LEVEL plev = caster_ptr->lev;
1057 HIT_POINT dam = damroll(8 + ((plev - 5) / 4) + boost / 12, 8);
1058 fire_beam(caster_ptr, GF_MISSILE, dir, dam);
1059 if (!caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
1062 POSITION ty = y, tx = x;
1063 POSITION oy = y, ox = x;
1064 MONSTER_IDX m_idx = caster_ptr->current_floor_ptr->grid_array[y][x].m_idx;
1065 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
1066 monster_race *r_ptr = &r_info[m_ptr->r_idx];
1067 GAME_TEXT m_name[MAX_NLEN];
1068 monster_desc(caster_ptr, m_name, m_ptr, 0);
1070 if (randint1(r_ptr->level * 3 / 2) > randint0(dam / 2) + dam / 2) {
1071 msg_format(_("%sは飛ばされなかった。", "%^s was not blown away."), m_name);
1075 for (int i = 0; i < 5; i++) {
1078 if (is_cave_empty_bold(caster_ptr, y, x)) {
1086 bool is_shock_successful = ty != oy;
1087 is_shock_successful |= tx != ox;
1088 if (is_shock_successful)
1091 msg_format(_("%sを吹き飛ばした!", "You blow %s away!"), m_name);
1092 caster_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = 0;
1093 caster_ptr->current_floor_ptr->grid_array[ty][tx].m_idx = m_idx;
1097 update_monster(caster_ptr, m_idx, TRUE);
1098 lite_spot(caster_ptr, oy, ox);
1099 lite_spot(caster_ptr, ty, tx);
1101 if (r_ptr->flags7 & (RF7_LITE_MASK | RF7_DARK_MASK))
1102 caster_ptr->update |= (PU_MON_LITE);
1106 bool fetch_monster(player_type *caster_ptr)
1108 monster_type *m_ptr;
1110 GAME_TEXT m_name[MAX_NLEN];
1116 if (!target_set(caster_ptr, TARGET_KILL))
1118 m_idx = caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx;
1121 if (m_idx == caster_ptr->riding)
1123 if (!player_has_los_bold(caster_ptr, target_row, target_col))
1125 if (!projectable(caster_ptr, caster_ptr->y, caster_ptr->x, target_row, target_col))
1127 m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
1128 monster_desc(caster_ptr, m_name, m_ptr, 0);
1129 msg_format(_("%sを引き戻した。", "You pull back %s."), m_name);
1130 path_n = project_path(caster_ptr, path_g, get_max_range(caster_ptr), target_row, target_col, caster_ptr->y, caster_ptr->x, 0);
1131 ty = target_row, tx = target_col;
1132 for (i = 1; i < path_n; i++) {
1133 POSITION ny = GRID_Y(path_g[i]);
1134 POSITION nx = GRID_X(path_g[i]);
1135 grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[ny][nx];
1137 if (in_bounds(caster_ptr->current_floor_ptr, ny, nx) && is_cave_empty_bold(caster_ptr, ny, nx) && !(g_ptr->info & CAVE_OBJECT)
1138 && !pattern_tile(caster_ptr->current_floor_ptr, ny, nx)) {
1144 caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx = 0;
1145 caster_ptr->current_floor_ptr->grid_array[ty][tx].m_idx = m_idx;
1148 (void)set_monster_csleep(caster_ptr, m_idx, 0);
1149 update_monster(caster_ptr, m_idx, TRUE);
1150 lite_spot(caster_ptr, target_row, target_col);
1151 lite_spot(caster_ptr, ty, tx);
1152 if (r_info[m_ptr->r_idx].flags7 & (RF7_LITE_MASK | RF7_DARK_MASK))
1153 caster_ptr->update |= (PU_MON_LITE);
1156 if (!caster_ptr->image)
1157 monster_race_track(caster_ptr, m_ptr->ap_r_idx);
1159 health_track(caster_ptr, m_idx);
1165 bool booze(player_type *creature_ptr)
1168 if (creature_ptr->pclass != CLASS_MONK)
1169 chg_virtue(creature_ptr, V_HARMONY, -1);
1170 else if (!creature_ptr->resist_conf)
1171 creature_ptr->special_attack |= ATTACK_SUIKEN;
1172 if (!creature_ptr->resist_conf && set_confused(creature_ptr, randint0(20) + 15)) {
1176 if (creature_ptr->resist_chaos) {
1180 if (one_in_(2) && set_image(creature_ptr, creature_ptr->image + randint0(150) + 150)) {
1184 if (one_in_(13) && (creature_ptr->pclass != CLASS_MONK)) {
1187 lose_all_info(creature_ptr);
1189 wiz_dark(creature_ptr);
1190 (void)teleport_player_aux(creature_ptr, 100, FALSE, TELEPORT_NONMAGICAL | TELEPORT_PASSIVE);
1191 wiz_dark(creature_ptr);
1192 msg_print(_("知らない場所で目が醒めた。頭痛がする。", "You wake up somewhere with a sore head..."));
1193 msg_print(_("何も思い出せない。どうやってここへ来たのかも分からない!", "You can't remember a thing or how you got here!"));
1199 bool detonation(player_type *creature_ptr)
1201 msg_print(_("体の中で激しい爆発が起きた!", "Massive explosions rupture your body!"));
1202 take_hit(creature_ptr, DAMAGE_NOESCAPE, damroll(50, 20), _("爆発の薬", "a potion of Detonation"), -1);
1203 (void)set_stun(creature_ptr, creature_ptr->stun + 75);
1204 (void)set_cut(creature_ptr, creature_ptr->cut + 5000);
1208 void blood_curse_to_enemy(player_type *caster_ptr, MONSTER_IDX m_idx)
1210 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
1211 grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[m_ptr->fy][m_ptr->fx];
1212 BIT_FLAGS curse_flg = (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP);
1214 bool is_first_loop = TRUE;
1215 while (is_first_loop || one_in_(5)) {
1216 is_first_loop = FALSE;
1217 switch (randint1(28)) {
1221 msg_print(_("地面が揺れた...", "The ground trembles..."));
1222 earthquake(caster_ptr, m_ptr->fy, m_ptr->fx, 4 + randint0(4), 0);
1232 int extra_dam = damroll(10, 10);
1233 msg_print(_("純粋な魔力の次元への扉が開いた!", "A portal opens to a plane of raw mana!"));
1235 project(caster_ptr, 0, 8, m_ptr->fy, m_ptr->fx, extra_dam, GF_MANA, curse_flg, -1);
1243 msg_print(_("空間が歪んだ!", "Space warps about you!"));
1246 teleport_away(caster_ptr, g_ptr->m_idx, damroll(10, 10), TELEPORT_PASSIVE);
1248 count += activate_hi_summon(caster_ptr, m_ptr->fy, m_ptr->fx, TRUE);
1256 msg_print(_("エネルギーのうねりを感じた!", "You feel a surge of energy!"));
1257 project(caster_ptr, 0, 7, m_ptr->fy, m_ptr->fx, 50, GF_DISINTEGRATE, curse_flg, -1);
1266 aggravate_monsters(caster_ptr, 0);
1272 count += activate_hi_summon(caster_ptr, m_ptr->fy, m_ptr->fx, TRUE);
1280 bool pet = !one_in_(3);
1281 BIT_FLAGS mode = PM_ALLOW_GROUP;
1284 mode |= PM_FORCE_PET;
1286 mode |= (PM_NO_PET | PM_FORCE_FRIENDLY);
1288 count += summon_specific(caster_ptr, (pet ? -1 : 0), caster_ptr->y, caster_ptr->x,
1289 (pet ? caster_ptr->lev * 2 / 3 + randint1(caster_ptr->lev / 2) : caster_ptr->current_floor_ptr->dun_level), 0, mode);
1297 if (caster_ptr->hold_exp && (randint0(100) < 75))
1299 msg_print(_("経験値が体から吸い取られた気がする!", "You feel your experience draining away..."));
1301 if (caster_ptr->hold_exp)
1302 lose_exp(caster_ptr, caster_ptr->exp / 160);
1304 lose_exp(caster_ptr, caster_ptr->exp / 16);
1312 for (int i = 0; i < A_MAX; i++) {
1313 bool is_first_dec_stat = TRUE;
1314 while (is_first_dec_stat || one_in_(2)) {
1315 (void)do_dec_stat(caster_ptr, i);
1319 (void)do_dec_stat(caster_ptr, randint0(6));
1329 * @brief クリムゾンを発射する / Fire Crimson, evoluting gun.
1330 @ @param shooter_ptr 射撃を行うクリーチャー参照
1331 * @return キャンセルした場合 false.
1333 * Need to analyze size of the window.
1334 * Need more color coding.
1336 bool fire_crimson(player_type *shooter_ptr)
1339 if (!get_aim_dir(shooter_ptr, &dir))
1342 POSITION tx = shooter_ptr->x + 99 * ddx[dir];
1343 POSITION ty = shooter_ptr->y + 99 * ddy[dir];
1344 if ((dir == 5) && target_okay(shooter_ptr)) {
1350 if (shooter_ptr->pclass == CLASS_ARCHER) {
1351 if (shooter_ptr->lev >= 10)
1353 if (shooter_ptr->lev >= 30)
1355 if (shooter_ptr->lev >= 45)
1359 BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
1360 for (int i = 0; i < num; i++)
1361 project(shooter_ptr, 0, shooter_ptr->lev / 20 + 1, ty, tx, shooter_ptr->lev * shooter_ptr->lev * 6 / 50, GF_ROCKET, flg, -1);
1367 * @brief 町間のテレポートを行うメインルーチン
1368 * @param caster_ptr プレーヤーへの参照ポインタ
1369 * @return テレポート処理を決定したか否か
1371 bool tele_town(player_type *caster_ptr)
1373 if (caster_ptr->current_floor_ptr->dun_level) {
1374 msg_print(_("この魔法は地上でしか使えない!", "This spell can only be used on the surface!"));
1378 if (caster_ptr->current_floor_ptr->inside_arena || caster_ptr->phase_out) {
1379 msg_print(_("この魔法は外でしか使えない!", "This spell can only be used outside!"));
1388 for (i = 1; i < max_towns; i++) {
1391 if ((i == NO_TOWN) || (i == SECRET_TOWN) || (i == caster_ptr->town_num) || !(caster_ptr->visit & (1L << (i - 1))))
1394 sprintf(buf, "%c) %-20s", I2A(i - 1), town_info[i].name);
1400 msg_print(_("まだ行けるところがない。", "You have not yet visited any town."));
1406 prt(_("どこに行きますか:", "Where do you want to go: "), 0, 0);
1415 else if ((i < 'a') || (i > ('a' + max_towns - 2)))
1417 else if (((i - 'a' + 1) == caster_ptr->town_num) || ((i - 'a' + 1) == NO_TOWN) || ((i - 'a' + 1) == SECRET_TOWN)
1418 || !(caster_ptr->visit & (1L << (i - 'a'))))
1423 for (POSITION y = 0; y < current_world_ptr->max_wild_y; y++) {
1424 for (POSITION x = 0; x < current_world_ptr->max_wild_x; x++) {
1425 if (wilderness[y][x].town == (i - 'a' + 1)) {
1426 caster_ptr->wilderness_y = y;
1427 caster_ptr->wilderness_x = x;
1432 caster_ptr->leaving = TRUE;
1433 caster_ptr->leave_bldg = TRUE;
1434 caster_ptr->teleport_town = TRUE;