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 "inventory/inventory-slot-types.h"
39 #include "io/input-key-acceptor.h"
40 #include "io/input-key-requester.h"
41 #include "io/targeting.h"
42 #include "io/write-diary.h"
43 #include "lore/lore-calculator.h"
44 #include "market/building-util.h"
45 #include "mind/mind-force-trainer.h"
46 #include "mind/mind-sniper.h"
47 #include "mind/mind.h"
48 #include "mind/racial-android.h"
49 #include "monster-floor/monster-generator.h"
50 #include "monster-floor/monster-remover.h"
51 #include "monster-floor/monster-summon.h"
52 #include "monster-floor/place-monster-types.h"
53 #include "monster-race/monster-race.h"
54 #include "monster-race/race-flags1.h"
55 #include "monster-race/race-flags7.h"
56 #include "monster/monster-describer.h"
57 #include "monster/monster-flag-types.h"
58 #include "monster/monster-info.h"
59 #include "monster/monster-list.h"
60 #include "monster/monster-processor.h"
61 #include "monster/monster-status.h"
62 #include "monster/monster-update.h"
63 #include "monster/monster-util.h"
64 #include "object-enchant/artifact.h"
65 #include "object-enchant/item-feeling.h"
66 #include "object-enchant/object-boost.h"
67 #include "object-enchant/object-ego.h"
68 #include "object-enchant/special-object-flags.h"
69 #include "object-enchant/tr-types.h"
70 #include "object-enchant/trc-types.h"
71 #include "object-hook/hook-enchant.h"
72 #include "object-hook/hook-expendable.h"
73 #include "object-hook/hook-magic.h"
74 #include "object-hook/hook-perception.h"
75 #include "object-hook/hook-weapon.h"
76 #include "object/item-tester-hooker.h"
77 #include "object/item-use-flags.h"
78 #include "object/object-flavor.h"
79 #include "object/object-generator.h"
80 #include "object/object-info.h"
81 #include "object/object-kind.h"
82 #include "object/object-mark-types.h"
83 #include "object/object-value.h"
84 #include "perception/identification.h"
85 #include "perception/object-perception.h"
86 #include "player/avatar.h"
87 #include "player/digestion-processor.h"
88 #include "player/player-class.h"
89 #include "player/player-damage.h"
90 #include "player/player-move.h"
91 #include "player/player-personalities-types.h"
92 #include "player/player-skill.h"
93 #include "player/player-status.h"
94 #include "realm/realm-names-table.h"
95 #include "spell-kind/earthquake.h"
96 #include "spell-kind/spells-floor.h"
97 #include "spell-kind/spells-launcher.h"
98 #include "spell-kind/spells-sight.h"
99 #include "spell-kind/spells-teleport.h"
100 #include "spell/process-effect.h"
101 #include "spell/spell-types.h"
102 #include "spell/spells-execution.h"
103 #include "spell/spells-summon.h"
104 #include "spell/technic-info-table.h"
105 #include "status/bad-status-setter.h"
106 #include "status/base-status.h"
107 #include "status/experience.h"
108 #include "term/screen-processor.h"
109 #include "term/term-color-types.h"
110 #include "util/bit-flags-calculator.h"
111 #include "util/int-char-converter.h"
112 #include "view/display-messages.h"
113 #include "world/world.h"
116 * @brief プレイヤーの装備劣化処理 /
117 * Apply disenchantment to the player's stuff
118 * @param target_ptr プレーヤーへの参照ポインタ
119 * @param mode 最下位ビットが1ならば劣化処理が若干低減される
120 * @return 劣化処理に関するメッセージが発せられた場合はTRUEを返す /
121 * Return "TRUE" if the player notices anything
123 bool apply_disenchant(player_type *target_ptr, BIT_FLAGS mode)
126 switch (randint1(8)) {
154 o_ptr = &target_ptr->inventory_list[t];
158 if (!object_is_weapon_armour_ammo(target_ptr, o_ptr))
161 if ((o_ptr->to_h <= 0) && (o_ptr->to_d <= 0) && (o_ptr->to_a <= 0) && (o_ptr->pval <= 1)) {
165 GAME_TEXT o_name[MAX_NLEN];
166 object_desc(target_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
167 if (object_is_artifact(o_ptr) && (randint0(100) < 71)) {
169 msg_format("%s(%c)は劣化を跳ね返した!", o_name, index_to_label(t));
171 msg_format("Your %s (%c) resist%s disenchantment!", o_name, index_to_label(t), ((o_ptr->number != 1) ? "" : "s"));
176 int to_h = o_ptr->to_h;
177 int to_d = o_ptr->to_d;
178 int to_a = o_ptr->to_a;
179 int pval = o_ptr->pval;
183 if ((o_ptr->to_h > 5) && (randint0(100) < 20))
188 if ((o_ptr->to_d > 5) && (randint0(100) < 20))
193 if ((o_ptr->to_a > 5) && (randint0(100) < 20))
196 if ((o_ptr->pval > 1) && one_in_(13) && !(mode & 0x01))
199 bool is_actually_disenchanted = to_h != o_ptr->to_h;
200 is_actually_disenchanted |= to_d != o_ptr->to_d;
201 is_actually_disenchanted |= to_a != o_ptr->to_a;
202 is_actually_disenchanted |= pval != o_ptr->pval;
203 if (!is_actually_disenchanted)
207 msg_format("%s(%c)は劣化してしまった!", o_name, index_to_label(t));
209 msg_format("Your %s (%c) %s disenchanted!", o_name, index_to_label(t), ((o_ptr->number != 1) ? "were" : "was"));
211 chg_virtue(target_ptr, V_HARMONY, 1);
212 chg_virtue(target_ptr, V_ENCHANT, -2);
213 target_ptr->update |= (PU_BONUS);
214 target_ptr->window |= (PW_EQUIP | PW_PLAYER);
216 calc_android_exp(target_ptr);
222 * @param caster_ptr プレーヤーへの参照ポインタ
225 void reserve_alter_reality(player_type *caster_ptr)
227 if (caster_ptr->current_floor_ptr->inside_arena || ironman_downward) {
228 msg_print(_("何も起こらなかった。", "Nothing happens."));
232 if (caster_ptr->alter_reality) {
233 caster_ptr->alter_reality = 0;
234 msg_print(_("景色が元に戻った...", "The view around you returns to normal..."));
235 caster_ptr->redraw |= PR_STATUS;
239 TIME_EFFECT turns = randint0(21) + 15;
240 caster_ptr->alter_reality = turns;
241 msg_print(_("回りの景色が変わり始めた...", "The view around you begins to change..."));
242 caster_ptr->redraw |= PR_STATUS;
246 * @brief アイテムの価値に応じた錬金術処理 /
247 * Turns an object into gold, gain some of its value in a shop
248 * @param caster_ptr プレーヤーへの参照ポインタ
249 * @return 処理が実際に行われたらTRUEを返す
251 bool alchemy(player_type *caster_ptr)
257 concptr q = _("どのアイテムを金に変えますか?", "Turn which item to gold? ");
258 concptr s = _("金に変えられる物がありません。", "You have nothing to turn to gold.");
261 o_ptr = choose_object(caster_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), 0);
266 if (o_ptr->number > 1) {
267 amt = get_quantity(NULL, o_ptr->number);
272 ITEM_NUMBER old_number = o_ptr->number;
274 GAME_TEXT o_name[MAX_NLEN];
275 object_desc(caster_ptr, o_name, o_ptr, 0);
276 o_ptr->number = old_number;
279 if (confirm_destroy || (object_value(caster_ptr, o_ptr) > 0)) {
280 char out_val[MAX_NLEN + 40];
281 sprintf(out_val, _("本当に%sを金に変えますか?", "Really turn %s to gold? "), o_name);
282 if (!get_check(out_val))
287 if (!can_player_destroy_object(caster_ptr, o_ptr)) {
288 msg_format(_("%sを金に変えることに失敗した。", "You fail to turn %s to gold!"), o_name);
292 PRICE price = object_value_real(caster_ptr, o_ptr);
294 msg_format(_("%sをニセの金に変えた。", "You turn %s to fool's gold."), o_name);
295 vary_item(caster_ptr, item, -amt);
306 msg_format(_("%sを$%d の金に変えた。", "You turn %s to %ld coins worth of gold."), o_name, price);
308 caster_ptr->au += price;
309 caster_ptr->redraw |= PR_GOLD;
310 caster_ptr->window |= PW_PLAYER;
311 vary_item(caster_ptr, item, -amt);
316 * @brief アーティファクト生成の巻物処理 /
317 * @param caster_ptr プレーヤーへの参照ポインタ
318 * @return 生成が実際に試みられたらTRUEを返す
320 bool artifact_scroll(player_type *caster_ptr)
322 item_tester_hook = item_tester_hook_nameless_weapon_armour;
324 concptr q = _("どのアイテムを強化しますか? ", "Enchant which item? ");
325 concptr s = _("強化できるアイテムがない。", "You have nothing to enchant.");
328 o_ptr = choose_object(caster_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0);
332 GAME_TEXT o_name[MAX_NLEN];
333 object_desc(caster_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
335 msg_format("%s は眩い光を発した!", o_name);
337 msg_format("%s %s radiate%s a blinding light!", ((item >= 0) ? "Your" : "The"), o_name, ((o_ptr->number > 1) ? "" : "s"));
341 if (object_is_artifact(o_ptr)) {
343 msg_format("%sは既に伝説のアイテムです!", o_name);
345 msg_format("The %s %s already %s!", o_name, ((o_ptr->number > 1) ? "are" : "is"), ((o_ptr->number > 1) ? "artifacts" : "an artifact"));
348 } else if (object_is_ego(o_ptr)) {
350 msg_format("%sは既に名のあるアイテムです!", o_name);
352 msg_format("The %s %s already %s!", o_name, ((o_ptr->number > 1) ? "are" : "is"), ((o_ptr->number > 1) ? "ego items" : "an ego item"));
355 } else if (o_ptr->xtra3) {
357 msg_format("%sは既に強化されています!", o_name);
359 msg_format("The %s %s already %s!", o_name, ((o_ptr->number > 1) ? "are" : "is"), ((o_ptr->number > 1) ? "customized items" : "a customized item"));
362 if (o_ptr->number > 1) {
363 msg_print(_("複数のアイテムに魔法をかけるだけのエネルギーはありません!", "Not enough energy to enchant more than one object!"));
365 msg_format("%d 個の%sが壊れた!", (o_ptr->number) - 1, o_name);
367 msg_format("%d of your %s %s destroyed!", (o_ptr->number) - 1, o_name, (o_ptr->number > 2 ? "were" : "was"));
371 inven_item_increase(caster_ptr, item, 1 - (o_ptr->number));
373 floor_item_increase(caster_ptr->current_floor_ptr, 0 - item, 1 - (o_ptr->number));
377 okay = become_random_artifact(caster_ptr, o_ptr, TRUE);
383 msg_print(_("強化に失敗した。", "The enchantment failed."));
385 chg_virtue(caster_ptr, V_ENCHANT, -1);
386 calc_android_exp(caster_ptr);
390 if (record_rand_art) {
391 object_desc(caster_ptr, o_name, o_ptr, OD_NAME_ONLY);
392 exe_write_diary(caster_ptr, DIARY_ART_SCROLL, 0, o_name);
395 chg_virtue(caster_ptr, V_ENCHANT, 1);
396 calc_android_exp(caster_ptr);
401 * @brief アイテム凡庸化のメインルーチン処理 /
402 * Identify an object in the inventory (or on the floor)
403 * @param owner_ptr プレーヤーへの参照ポインタ
404 * @param only_equip 装備品のみを対象とするならばTRUEを返す
405 * @return 実際に凡庸化をを行ったならばTRUEを返す
408 * Mundanify an object in the inventory (or on the floor)
409 * This routine does *not* automatically combine objects.
410 * Returns TRUE if something was mundanified, else FALSE.
413 bool mundane_spell(player_type *owner_ptr, bool only_equip)
416 item_tester_hook = object_is_weapon_armour_ammo;
420 concptr q = _("どれを使いますか?", "Use which item? ");
421 concptr s = _("使えるものがありません。", "You have nothing you can use.");
423 o_ptr = choose_object(owner_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0);
427 msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!"));
428 POSITION iy = o_ptr->iy;
429 POSITION ix = o_ptr->ix;
430 OBJECT_IDX next_o_idx = o_ptr->next_o_idx;
431 byte marked = o_ptr->marked;
432 WEIGHT weight = o_ptr->number * o_ptr->weight;
433 u16b inscription = o_ptr->inscription;
435 object_prep(owner_ptr, o_ptr, o_ptr->k_idx);
439 o_ptr->next_o_idx = next_o_idx;
440 o_ptr->marked = marked;
441 o_ptr->inscription = inscription;
443 owner_ptr->total_weight += (o_ptr->weight - weight);
445 calc_android_exp(owner_ptr);
451 * Recharge a wand/staff/rod from the pack or on the floor.
452 * This function has been rewritten in Oangband and ZAngband.
453 * @param caster_ptr プレーヤーへの参照ポインタ
455 * @return ターン消費を要する処理まで進んだらTRUEを返す
457 * Sorcery/Arcane -- Recharge --> recharge(plev * 4)
458 * Chaos -- Arcane Binding --> recharge(90)
460 * Scroll of recharging --> recharge(130)
461 * Artifact activation/Thingol --> recharge(130)
463 * It is harder to recharge high level, and highly charged wands,
464 * staffs, and rods. The more wands in a stack, the more easily and
465 * strongly they recharge. Staffs, however, each get fewer charges if
468 * Beware of "sliding index errors".
470 bool recharge(player_type *caster_ptr, int power)
472 item_tester_hook = item_tester_hook_recharge;
473 concptr q = _("どのアイテムに魔力を充填しますか? ", "Recharge which item? ");
474 concptr s = _("魔力を充填すべきアイテムがない。", "You have nothing to recharge.");
478 o_ptr = choose_object(caster_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), 0);
483 k_ptr = &k_info[o_ptr->k_idx];
484 DEPTH lev = k_info[o_ptr->k_idx].level;
486 TIME_EFFECT recharge_amount;
487 int recharge_strength;
488 bool is_recharge_successful = TRUE;
489 if (o_ptr->tval == TV_ROD) {
490 recharge_strength = ((power > lev / 2) ? (power - lev / 2) : 0) / 5;
491 if (one_in_(recharge_strength)) {
492 is_recharge_successful = FALSE;
494 recharge_amount = (power * damroll(3, 2));
495 if (o_ptr->timeout > recharge_amount)
496 o_ptr->timeout -= recharge_amount;
501 if ((o_ptr->tval == TV_WAND) && (o_ptr->number > 1))
502 recharge_strength = (100 + power - lev - (8 * o_ptr->pval / o_ptr->number)) / 15;
504 recharge_strength = (100 + power - lev - (8 * o_ptr->pval)) / 15;
506 if (recharge_strength < 0)
507 recharge_strength = 0;
509 if (one_in_(recharge_strength)) {
510 is_recharge_successful = FALSE;
512 recharge_amount = randint1(1 + k_ptr->pval / 2);
513 if ((o_ptr->tval == TV_WAND) && (o_ptr->number > 1)) {
514 recharge_amount += (randint1(recharge_amount * (o_ptr->number - 1))) / 2;
515 if (recharge_amount < 1)
517 if (recharge_amount > 12)
518 recharge_amount = 12;
521 if ((o_ptr->tval == TV_STAFF) && (o_ptr->number > 1)) {
522 recharge_amount /= (TIME_EFFECT)o_ptr->number;
523 if (recharge_amount < 1)
527 o_ptr->pval += recharge_amount;
528 o_ptr->ident &= ~(IDENT_KNOWN);
529 o_ptr->ident &= ~(IDENT_EMPTY);
533 if (!is_recharge_successful) {
534 return update_player(caster_ptr);
538 GAME_TEXT o_name[MAX_NLEN];
539 if (object_is_fixed_artifact(o_ptr)) {
540 object_desc(caster_ptr, o_name, o_ptr, OD_NAME_ONLY);
541 msg_format(_("魔力が逆流した!%sは完全に魔力を失った。", "The recharging backfires - %s is completely drained!"), o_name);
542 if ((o_ptr->tval == TV_ROD) && (o_ptr->timeout < 10000))
543 o_ptr->timeout = (o_ptr->timeout + 100) * 2;
544 else if ((o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_STAFF))
546 return update_player(caster_ptr);
549 object_desc(caster_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
551 if (IS_WIZARD_CLASS(caster_ptr) || caster_ptr->pclass == CLASS_MAGIC_EATER || caster_ptr->pclass == CLASS_BLUE_MAGE) {
552 /* 10% chance to blow up one rod, otherwise draining. */
553 if (o_ptr->tval == TV_ROD) {
559 /* 75% chance to blow up one wand, otherwise draining. */
560 else if (o_ptr->tval == TV_WAND) {
566 /* 50% chance to blow up one staff, otherwise no effect. */
567 else if (o_ptr->tval == TV_STAFF) {
574 /* 33% chance to blow up one rod, otherwise draining. */
575 if (o_ptr->tval == TV_ROD) {
581 /* 20% chance of the entire stack, else destroy one wand. */
582 else if (o_ptr->tval == TV_WAND) {
588 /* Blow up one staff. */
589 else if (o_ptr->tval == TV_STAFF) {
594 if (fail_type == 1) {
595 if (o_ptr->tval == TV_ROD) {
596 msg_print(_("魔力が逆噴射して、ロッドからさらに魔力を吸い取ってしまった!", "The recharge backfires, draining the rod further!"));
598 if (o_ptr->timeout < 10000)
599 o_ptr->timeout = (o_ptr->timeout + 100) * 2;
600 } else if (o_ptr->tval == TV_WAND) {
601 msg_format(_("%sは破損を免れたが、魔力が全て失われた。", "You save your %s from destruction, but all charges are lost."), o_name);
606 if (fail_type == 2) {
607 if (o_ptr->number > 1)
608 msg_format(_("乱暴な魔法のために%sが一本壊れた!", "Wild magic consumes one of your %s!"), o_name);
610 msg_format(_("乱暴な魔法のために%sが壊れた!", "Wild magic consumes your %s!"), o_name);
612 if (o_ptr->tval == TV_ROD)
613 o_ptr->timeout = (o_ptr->number - 1) * k_ptr->pval;
614 if (o_ptr->tval == TV_WAND)
617 vary_item(caster_ptr, item, -1);
620 if (fail_type == 3) {
621 if (o_ptr->number > 1)
622 msg_format(_("乱暴な魔法のために%sが全て壊れた!", "Wild magic consumes all your %s!"), o_name);
624 msg_format(_("乱暴な魔法のために%sが壊れた!", "Wild magic consumes your %s!"), o_name);
626 vary_item(caster_ptr, item, -999);
629 return update_player(caster_ptr);
633 * @brief クリーチャー全既知呪文を表示する /
634 * Hack -- Display all known spells in a window
635 * @param caster_ptr 術者の参照ポインタ
638 * Need to analyze size of the window.
639 * Need more color coding.
641 void display_spell_list(player_type *caster_ptr)
645 const magic_type *s_ptr;
646 GAME_TEXT name[MAX_NLEN];
651 if (caster_ptr->pclass == CLASS_SORCERER)
653 if (caster_ptr->pclass == CLASS_RED_MAGE)
655 if (caster_ptr->pclass == CLASS_SNIPER) {
656 display_snipe_list(caster_ptr);
660 if ((caster_ptr->pclass == CLASS_MINDCRAFTER) || (caster_ptr->pclass == CLASS_BERSERKER) || (caster_ptr->pclass == CLASS_NINJA)
661 || (caster_ptr->pclass == CLASS_MIRROR_MASTER) || (caster_ptr->pclass == CLASS_FORCETRAINER)) {
662 PERCENTAGE minfail = 0;
663 PLAYER_LEVEL plev = caster_ptr->lev;
664 PERCENTAGE chance = 0;
675 put_str(_("名前", "Name"), y, x + 5);
676 put_str(_("Lv MP 失率 効果", "Lv Mana Fail Info"), y, x + 35);
678 switch (caster_ptr->pclass) {
679 case CLASS_MINDCRAFTER:
680 use_mind = MIND_MINDCRAFTER;
682 case CLASS_FORCETRAINER:
685 case CLASS_BERSERKER:
686 use_mind = MIND_BERSERKER;
689 case CLASS_MIRROR_MASTER:
690 use_mind = MIND_MIRROR_MASTER;
693 use_mind = MIND_NINJUTSU;
701 for (int i = 0; i < MAX_MIND_POWERS; i++) {
703 spell = mind_powers[use_mind].info[i];
704 if (spell.min_lev > plev)
708 chance -= 3 * (caster_ptr->lev - spell.min_lev);
709 chance -= 3 * (adj_mag_stat[caster_ptr->stat_ind[mp_ptr->spell_stat]] - 1);
711 if (spell.mana_cost > caster_ptr->csp) {
712 chance += 5 * (spell.mana_cost - caster_ptr->csp);
716 if (spell.mana_cost > caster_ptr->chp) {
722 minfail = adj_mag_fail[caster_ptr->stat_ind[mp_ptr->spell_stat]];
723 if (chance < minfail)
726 if (caster_ptr->stun > 50)
728 else if (caster_ptr->stun)
734 mindcraft_info(caster_ptr, comment, use_mind, i);
735 sprintf(psi_desc, " %c) %-30s%2d %4d %3d%%%s", I2A(i), spell.name, spell.min_lev, spell.mana_cost, chance, comment);
737 Term_putstr(x, y + i + 1, -1, a, psi_desc);
743 if (REALM_NONE == caster_ptr->realm1)
746 for (int j = 0; j < ((caster_ptr->realm2 > REALM_NONE) ? 2 : 1); j++) {
748 y = (j < 3) ? 0 : (m[j - 3] + 2);
751 for (int i = 0; i < 32; i++) {
754 if (!is_magic((j < 1) ? caster_ptr->realm1 : caster_ptr->realm2)) {
755 s_ptr = &technic_info[((j < 1) ? caster_ptr->realm1 : caster_ptr->realm2) - MIN_TECHNIC][i % 32];
757 s_ptr = &mp_ptr->info[((j < 1) ? caster_ptr->realm1 : caster_ptr->realm2) - 1][i % 32];
760 strcpy(name, exe_spell(caster_ptr, (j < 1) ? caster_ptr->realm1 : caster_ptr->realm2, i % 32, SPELL_NAME));
762 if (s_ptr->slevel >= 99) {
763 strcpy(name, _("(判読不能)", "(illegible)"));
765 } else if ((j < 1) ? ((caster_ptr->spell_forgotten1 & (1L << i))) : ((caster_ptr->spell_forgotten2 & (1L << (i % 32))))) {
767 } else if (!((j < 1) ? (caster_ptr->spell_learned1 & (1L << i)) : (caster_ptr->spell_learned2 & (1L << (i % 32))))) {
769 } else if (!((j < 1) ? (caster_ptr->spell_worked1 & (1L << i)) : (caster_ptr->spell_worked2 & (1L << (i % 32))))) {
773 sprintf(out_val, "%c/%c) %-20.20s", I2A(n / 8), I2A(n % 8), name);
776 Term_putstr(x, m[j], -1, a, out_val);
783 * @brief 変身処理向けにモンスターの近隣レベル帯モンスターを返す /
784 * Helper function -- return a "nearby" race for polymorphing
785 * @param floor_ptr 配置するフロアの参照ポインタ
786 * @param r_idx 基準となるモンスター種族ID
787 * @return 変更先のモンスター種族ID
789 * Note that this function is one of the more "dangerous" ones...
791 static MONRACE_IDX poly_r_idx(player_type *caster_ptr, MONRACE_IDX r_idx)
793 monster_race *r_ptr = &r_info[r_idx];
794 if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags1 & RF1_QUESTOR))
797 DEPTH lev1 = r_ptr->level - ((randint1(20) / randint1(9)) + 1);
798 DEPTH lev2 = r_ptr->level + ((randint1(20) / randint1(9)) + 1);
800 for (int i = 0; i < 1000; i++) {
801 r = get_mon_num(caster_ptr, (caster_ptr->current_floor_ptr->dun_level + r_ptr->level) / 2 + 5, 0);
806 if (r_ptr->flags1 & RF1_UNIQUE)
808 if ((r_ptr->level < lev1) || (r_ptr->level > lev2))
819 * @brief 指定座標にいるモンスターを変身させる /
820 * Helper function -- return a "nearby" race for polymorphing
821 * @param caster_ptr プレーヤーへの参照ポインタ
824 * @return 実際に変身したらTRUEを返す
826 bool polymorph_monster(player_type *caster_ptr, POSITION y, POSITION x)
828 floor_type *floor_ptr = caster_ptr->current_floor_ptr;
829 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
830 monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
831 MONRACE_IDX new_r_idx;
832 MONRACE_IDX old_r_idx = m_ptr->r_idx;
833 bool targeted = (target_who == g_ptr->m_idx) ? TRUE : FALSE;
834 bool health_tracked = (caster_ptr->health_who == g_ptr->m_idx) ? TRUE : FALSE;
836 if (floor_ptr->inside_arena || caster_ptr->phase_out)
838 if ((caster_ptr->riding == g_ptr->m_idx) || (m_ptr->mflag2 & MFLAG2_KAGE))
841 monster_type back_m = *m_ptr;
842 new_r_idx = poly_r_idx(caster_ptr, old_r_idx);
843 if (new_r_idx == old_r_idx)
846 bool preserve_hold_objects = back_m.hold_o_idx ? TRUE : FALSE;
847 OBJECT_IDX this_o_idx, next_o_idx = 0;
850 if (is_friendly(m_ptr))
851 mode |= PM_FORCE_FRIENDLY;
853 mode |= PM_FORCE_PET;
854 if (m_ptr->mflag2 & MFLAG2_NOPET)
857 m_ptr->hold_o_idx = 0;
858 delete_monster_idx(caster_ptr, g_ptr->m_idx);
859 bool polymorphed = FALSE;
860 if (place_monster_aux(caster_ptr, 0, y, x, new_r_idx, mode)) {
861 floor_ptr->m_list[hack_m_idx_ii].nickname = back_m.nickname;
862 floor_ptr->m_list[hack_m_idx_ii].parent_m_idx = back_m.parent_m_idx;
863 floor_ptr->m_list[hack_m_idx_ii].hold_o_idx = back_m.hold_o_idx;
866 if (place_monster_aux(caster_ptr, 0, y, x, old_r_idx, (mode | PM_NO_KAGE | PM_IGNORE_TERRAIN))) {
867 floor_ptr->m_list[hack_m_idx_ii] = back_m;
868 mproc_init(floor_ptr);
870 preserve_hold_objects = FALSE;
873 if (preserve_hold_objects) {
874 for (this_o_idx = back_m.hold_o_idx; this_o_idx; this_o_idx = next_o_idx) {
875 object_type *o_ptr = &floor_ptr->o_list[this_o_idx];
876 next_o_idx = o_ptr->next_o_idx;
877 o_ptr->held_m_idx = hack_m_idx_ii;
879 } else if (back_m.hold_o_idx) {
880 for (this_o_idx = back_m.hold_o_idx; this_o_idx; this_o_idx = next_o_idx) {
881 next_o_idx = floor_ptr->o_list[this_o_idx].next_o_idx;
882 delete_object_idx(caster_ptr, this_o_idx);
887 target_who = hack_m_idx_ii;
889 health_track(caster_ptr, hack_m_idx_ii);
894 * @brief 皆殺し(全方向攻撃)処理
895 * @param caster_ptr プレーヤーへの参照ポインタ
898 void massacre(player_type *caster_ptr)
902 for (DIRECTION dir = 0; dir < 8; dir++) {
903 POSITION y = caster_ptr->y + ddy_ddd[dir];
904 POSITION x = caster_ptr->x + ddx_ddd[dir];
905 g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
906 m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
907 if (g_ptr->m_idx && (m_ptr->ml || cave_have_flag_bold(caster_ptr->current_floor_ptr, y, x, FF_PROJECT)))
908 do_cmd_attack(caster_ptr, y, x, 0);
914 * @param caster_ptr プレーヤーへの参照ポインタ
915 * @return コマンドの入力方向に地形があればTRUE
917 bool eat_rock(player_type *caster_ptr)
920 if (!get_direction(caster_ptr, &dir, FALSE, FALSE))
922 POSITION y = caster_ptr->y + ddy[dir];
923 POSITION x = caster_ptr->x + ddx[dir];
925 g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
926 feature_type *f_ptr, *mimic_f_ptr;
927 f_ptr = &f_info[g_ptr->feat];
928 mimic_f_ptr = &f_info[get_feat_mimic(g_ptr)];
930 stop_mouth(caster_ptr);
931 if (!have_flag(mimic_f_ptr->flags, FF_HURT_ROCK)) {
932 msg_print(_("この地形は食べられない。", "You cannot eat this feature."));
933 } else if (have_flag(f_ptr->flags, FF_PERMANENT)) {
934 msg_format(_("いてっ!この%sはあなたの歯より硬い!", "Ouch! This %s is harder than your teeth!"), f_name + mimic_f_ptr->name);
935 } else if (g_ptr->m_idx) {
936 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
937 msg_print(_("何かが邪魔しています!", "There's something in the way!"));
939 if (!m_ptr->ml || !is_pet(m_ptr))
940 do_cmd_attack(caster_ptr, y, x, 0);
941 } else if (have_flag(f_ptr->flags, FF_TREE)) {
942 msg_print(_("木の味は好きじゃない!", "You don't like the woody taste!"));
943 } else if (have_flag(f_ptr->flags, FF_GLASS)) {
944 msg_print(_("ガラスの味は好きじゃない!", "You don't like the glassy taste!"));
945 } else if (have_flag(f_ptr->flags, FF_DOOR) || have_flag(f_ptr->flags, FF_CAN_DIG)) {
946 (void)set_food(caster_ptr, caster_ptr->food + 3000);
947 } else if (have_flag(f_ptr->flags, FF_MAY_HAVE_GOLD) || have_flag(f_ptr->flags, FF_HAS_GOLD)) {
948 (void)set_food(caster_ptr, caster_ptr->food + 5000);
950 msg_format(_("この%sはとてもおいしい!", "This %s is very filling!"), f_name + mimic_f_ptr->name);
951 (void)set_food(caster_ptr, caster_ptr->food + 10000);
954 cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK);
955 (void)move_player_effect(caster_ptr, y, x, MPE_DONT_PICKUP);
959 bool shock_power(player_type *caster_ptr)
961 int boost = get_current_ki(caster_ptr);
962 if (heavy_armor(caster_ptr))
967 if (!get_aim_dir(caster_ptr, &dir))
970 POSITION y = caster_ptr->y + ddy[dir];
971 POSITION x = caster_ptr->x + ddx[dir];
972 PLAYER_LEVEL plev = caster_ptr->lev;
973 HIT_POINT dam = damroll(8 + ((plev - 5) / 4) + boost / 12, 8);
974 fire_beam(caster_ptr, GF_MISSILE, dir, dam);
975 if (!caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
978 POSITION ty = y, tx = x;
979 POSITION oy = y, ox = x;
980 MONSTER_IDX m_idx = caster_ptr->current_floor_ptr->grid_array[y][x].m_idx;
981 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
982 monster_race *r_ptr = &r_info[m_ptr->r_idx];
983 GAME_TEXT m_name[MAX_NLEN];
984 monster_desc(caster_ptr, m_name, m_ptr, 0);
986 if (randint1(r_ptr->level * 3 / 2) > randint0(dam / 2) + dam / 2) {
987 msg_format(_("%sは飛ばされなかった。", "%^s was not blown away."), m_name);
991 for (int i = 0; i < 5; i++) {
994 if (is_cave_empty_bold(caster_ptr, y, x)) {
1002 bool is_shock_successful = ty != oy;
1003 is_shock_successful |= tx != ox;
1004 if (is_shock_successful)
1007 msg_format(_("%sを吹き飛ばした!", "You blow %s away!"), m_name);
1008 caster_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = 0;
1009 caster_ptr->current_floor_ptr->grid_array[ty][tx].m_idx = m_idx;
1013 update_monster(caster_ptr, m_idx, TRUE);
1014 lite_spot(caster_ptr, oy, ox);
1015 lite_spot(caster_ptr, ty, tx);
1017 if (r_ptr->flags7 & (RF7_LITE_MASK | RF7_DARK_MASK))
1018 caster_ptr->update |= (PU_MON_LITE);
1022 bool booze(player_type *creature_ptr)
1025 if (creature_ptr->pclass != CLASS_MONK)
1026 chg_virtue(creature_ptr, V_HARMONY, -1);
1027 else if (!creature_ptr->resist_conf)
1028 creature_ptr->special_attack |= ATTACK_SUIKEN;
1029 if (!creature_ptr->resist_conf && set_confused(creature_ptr, randint0(20) + 15)) {
1033 if (creature_ptr->resist_chaos) {
1037 if (one_in_(2) && set_image(creature_ptr, creature_ptr->image + randint0(150) + 150)) {
1041 if (one_in_(13) && (creature_ptr->pclass != CLASS_MONK)) {
1044 lose_all_info(creature_ptr);
1046 wiz_dark(creature_ptr);
1047 (void)teleport_player_aux(creature_ptr, 100, FALSE, TELEPORT_NONMAGICAL | TELEPORT_PASSIVE);
1048 wiz_dark(creature_ptr);
1049 msg_print(_("知らない場所で目が醒めた。頭痛がする。", "You wake up somewhere with a sore head..."));
1050 msg_print(_("何も思い出せない。どうやってここへ来たのかも分からない!", "You can't remember a thing or how you got here!"));
1057 * @brief 爆発の薬の効果処理 / Fumble ramble
1058 * @param creature_ptr プレーヤーへの参照ポインタ
1061 bool detonation(player_type *creature_ptr)
1063 msg_print(_("体の中で激しい爆発が起きた!", "Massive explosions rupture your body!"));
1064 take_hit(creature_ptr, DAMAGE_NOESCAPE, damroll(50, 20), _("爆発の薬", "a potion of Detonation"), -1);
1065 (void)set_stun(creature_ptr, creature_ptr->stun + 75);
1066 (void)set_cut(creature_ptr, creature_ptr->cut + 5000);
1070 void blood_curse_to_enemy(player_type *caster_ptr, MONSTER_IDX m_idx)
1072 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
1073 grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[m_ptr->fy][m_ptr->fx];
1074 BIT_FLAGS curse_flg = (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP);
1076 bool is_first_loop = TRUE;
1077 while (is_first_loop || one_in_(5)) {
1078 is_first_loop = FALSE;
1079 switch (randint1(28)) {
1083 msg_print(_("地面が揺れた...", "The ground trembles..."));
1084 earthquake(caster_ptr, m_ptr->fy, m_ptr->fx, 4 + randint0(4), 0);
1094 int extra_dam = damroll(10, 10);
1095 msg_print(_("純粋な魔力の次元への扉が開いた!", "A portal opens to a plane of raw mana!"));
1097 project(caster_ptr, 0, 8, m_ptr->fy, m_ptr->fx, extra_dam, GF_MANA, curse_flg, -1);
1105 msg_print(_("空間が歪んだ!", "Space warps about you!"));
1108 teleport_away(caster_ptr, g_ptr->m_idx, damroll(10, 10), TELEPORT_PASSIVE);
1110 count += activate_hi_summon(caster_ptr, m_ptr->fy, m_ptr->fx, TRUE);
1118 msg_print(_("エネルギーのうねりを感じた!", "You feel a surge of energy!"));
1119 project(caster_ptr, 0, 7, m_ptr->fy, m_ptr->fx, 50, GF_DISINTEGRATE, curse_flg, -1);
1128 aggravate_monsters(caster_ptr, 0);
1134 count += activate_hi_summon(caster_ptr, m_ptr->fy, m_ptr->fx, TRUE);
1142 bool pet = !one_in_(3);
1143 BIT_FLAGS mode = PM_ALLOW_GROUP;
1146 mode |= PM_FORCE_PET;
1148 mode |= (PM_NO_PET | PM_FORCE_FRIENDLY);
1150 count += summon_specific(caster_ptr, (pet ? -1 : 0), caster_ptr->y, caster_ptr->x,
1151 (pet ? caster_ptr->lev * 2 / 3 + randint1(caster_ptr->lev / 2) : caster_ptr->current_floor_ptr->dun_level), 0, mode);
1159 if (caster_ptr->hold_exp && (randint0(100) < 75))
1161 msg_print(_("経験値が体から吸い取られた気がする!", "You feel your experience draining away..."));
1163 if (caster_ptr->hold_exp)
1164 lose_exp(caster_ptr, caster_ptr->exp / 160);
1166 lose_exp(caster_ptr, caster_ptr->exp / 16);
1174 for (int i = 0; i < A_MAX; i++) {
1175 bool is_first_dec_stat = TRUE;
1176 while (is_first_dec_stat || one_in_(2)) {
1177 (void)do_dec_stat(caster_ptr, i);
1181 (void)do_dec_stat(caster_ptr, randint0(6));
1191 * @brief クリムゾンを発射する / Fire Crimson, evoluting gun.
1192 @ @param shooter_ptr 射撃を行うクリーチャー参照
1193 * @return キャンセルした場合 false.
1195 * Need to analyze size of the window.
1196 * Need more color coding.
1198 bool fire_crimson(player_type *shooter_ptr)
1201 if (!get_aim_dir(shooter_ptr, &dir))
1204 POSITION tx = shooter_ptr->x + 99 * ddx[dir];
1205 POSITION ty = shooter_ptr->y + 99 * ddy[dir];
1206 if ((dir == 5) && target_okay(shooter_ptr)) {
1212 if (shooter_ptr->pclass == CLASS_ARCHER) {
1213 if (shooter_ptr->lev >= 10)
1215 if (shooter_ptr->lev >= 30)
1217 if (shooter_ptr->lev >= 45)
1221 BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
1222 for (int i = 0; i < num; i++)
1223 project(shooter_ptr, 0, shooter_ptr->lev / 20 + 1, ty, tx, shooter_ptr->lev * shooter_ptr->lev * 6 / 50, GF_ROCKET, flg, -1);
1229 * @brief 町間のテレポートを行うメインルーチン
1230 * @param caster_ptr プレーヤーへの参照ポインタ
1231 * @return テレポート処理を決定したか否か
1233 bool tele_town(player_type *caster_ptr)
1235 if (caster_ptr->current_floor_ptr->dun_level) {
1236 msg_print(_("この魔法は地上でしか使えない!", "This spell can only be used on the surface!"));
1240 if (caster_ptr->current_floor_ptr->inside_arena || caster_ptr->phase_out) {
1241 msg_print(_("この魔法は外でしか使えない!", "This spell can only be used outside!"));
1250 for (i = 1; i < max_towns; i++) {
1253 if ((i == NO_TOWN) || (i == SECRET_TOWN) || (i == caster_ptr->town_num) || !(caster_ptr->visit & (1L << (i - 1))))
1256 sprintf(buf, "%c) %-20s", I2A(i - 1), town_info[i].name);
1262 msg_print(_("まだ行けるところがない。", "You have not yet visited any town."));
1268 prt(_("どこに行きますか:", "Where do you want to go: "), 0, 0);
1277 else if ((i < 'a') || (i > ('a' + max_towns - 2)))
1279 else if (((i - 'a' + 1) == caster_ptr->town_num) || ((i - 'a' + 1) == NO_TOWN) || ((i - 'a' + 1) == SECRET_TOWN)
1280 || !(caster_ptr->visit & (1L << (i - 'a'))))
1285 for (POSITION y = 0; y < current_world_ptr->max_wild_y; y++) {
1286 for (POSITION x = 0; x < current_world_ptr->max_wild_x; x++) {
1287 if (wilderness[y][x].town == (i - 'a' + 1)) {
1288 caster_ptr->wilderness_y = y;
1289 caster_ptr->wilderness_x = x;
1294 caster_ptr->leaving = TRUE;
1295 caster_ptr->leave_bldg = TRUE;
1296 caster_ptr->teleport_town = TRUE;