OSDN Git Service

[Refactor] #37353 max_f_idx を feature.c/h へ移動.
[hengband/hengband.git] / src / spells-summon.c
1 #include "angband.h"
2 #include "util.h"
3
4 #include "spells.h"
5 #include "spells-summon.h"
6 #include "monster-status.h"
7 #include "floor.h"
8
9 /*!
10 * @brief トランプ魔法独自の召喚処理を行う / Handle summoning and failure of trump spells
11 * @param num summon_specific()関数を呼び出す回数
12 * @param pet ペット化として召喚されるか否か
13 * @param y 召喚位置のy座標
14 * @param x 召喚位置のx座標
15 * @param lev 召喚レベル
16 * @param type 召喚条件ID
17 * @param mode モンスター生成条件フラグ
18 * @return モンスターが(敵対も含めて)召還されたならばTRUEを返す。
19 */
20 bool trump_summoning(int num, bool pet, POSITION y, POSITION x, DEPTH lev, int type, BIT_FLAGS mode)
21 {
22         PLAYER_LEVEL plev = p_ptr->lev;
23
24         MONSTER_IDX who;
25         int i;
26         bool success = FALSE;
27
28         /* Default level */
29         if (!lev) lev = plev * 2 / 3 + randint1(plev / 2);
30
31         if (pet)
32         {
33                 /* Become pet */
34                 mode |= PM_FORCE_PET;
35
36                 /* Only sometimes allow unique monster */
37                 if (mode & PM_ALLOW_UNIQUE)
38                 {
39                         /* Forbid often */
40                         if (randint1(50 + plev) >= plev / 10)
41                                 mode &= ~PM_ALLOW_UNIQUE;
42                 }
43
44                 /* Player is who summons */
45                 who = -1;
46         }
47         else
48         {
49                 /* Prevent taming, allow unique monster */
50                 mode |= PM_NO_PET;
51
52                 /* Behave as if they appear by themselfs */
53                 who = 0;
54         }
55
56         for (i = 0; i < num; i++)
57         {
58                 if (summon_specific(who, y, x, lev, type, mode))
59                         success = TRUE;
60         }
61
62         if (!success)
63         {
64                 msg_print(_("誰もあなたのカードの呼び声に答えない。", "Nobody answers to your Trump call."));
65         }
66
67         return success;
68 }
69
70
71 bool cast_summon_demon(int power)
72 {
73         u32b flg = 0L;
74         bool pet = !one_in_(3);
75
76         if (pet) flg |= PM_FORCE_PET;
77         else flg |= PM_NO_PET;
78         if (!(pet && (p_ptr->lev < 50))) flg |= PM_ALLOW_GROUP;
79
80         if (summon_specific((pet ? -1 : 0), p_ptr->y, p_ptr->x, power, SUMMON_DEMON, flg))
81         {
82                 msg_print(_("硫黄の悪臭が充満した。", "The area fills with a stench of sulphur and brimstone."));
83                 if (pet)
84                 {
85                         msg_print(_("「ご用でございますか、ご主人様」", "'What is thy bidding... Master?'"));
86                 }
87                 else
88                 {
89                         msg_print(_("「卑しき者よ、我は汝の下僕にあらず! お前の魂を頂くぞ!」",
90                                 "'NON SERVIAM! Wretch! I shall feast on thy mortal soul!'"));
91                 }
92         }
93         return TRUE;
94 }
95
96 bool cast_summon_undead(player_type *creature_ptr, int power)
97 {
98         bool pet = one_in_(3);
99         int type;
100         BIT_FLAGS mode = 0L;
101
102         type = (creature_ptr->lev > 47 ? SUMMON_HI_UNDEAD : SUMMON_UNDEAD);
103
104         if (!pet || ((creature_ptr->lev > 24) && one_in_(3))) mode |= PM_ALLOW_GROUP;
105         if (pet) mode |= PM_FORCE_PET;
106         else mode |= (PM_ALLOW_UNIQUE | PM_NO_PET);
107
108         if (summon_specific((pet ? -1 : 0), creature_ptr->y, creature_ptr->x, power, type, mode))
109         {
110                 msg_print(_("冷たい風があなたの周りに吹き始めた。それは腐敗臭を運んでいる...",
111                         "Cold winds begin to blow around you, carrying with them the stench of decay..."));
112                 if (pet)
113                         msg_print(_("古えの死せる者共があなたに仕えるため土から甦った!",
114                                 "Ancient, long-dead forms arise from the ground to serve you!"));
115                 else
116                         msg_print(_("死者が甦った。眠りを妨げるあなたを罰するために!",
117                                 "'The dead arise... to punish you for disturbing them!'"));
118         }
119         return TRUE;
120 }
121
122
123 bool cast_summon_hound(player_type *creature_ptr, int power)
124 {
125         BIT_FLAGS mode = PM_ALLOW_GROUP;
126         bool pet = !one_in_(5);
127         if (pet) mode |= PM_FORCE_PET;
128         else mode |= PM_NO_PET;
129
130         if (summon_specific((pet ? -1 : 0), creature_ptr->y, creature_ptr->x, power, SUMMON_HOUND, mode))
131         {
132                 if (pet)
133                         msg_print(_("ハウンドがあなたの下僕として出現した。", "A group of hounds appear as your servant."));
134                 else
135                         msg_print(_("ハウンドはあなたに牙を向けている!", "A group of hounds appear as your enemy!"));
136         }
137         return TRUE;
138 }
139
140 bool cast_summon_elemental(player_type *creature_ptr, int power)
141 {
142         bool pet = one_in_(3);
143         BIT_FLAGS mode = 0L;
144
145         if (!(pet && (creature_ptr->lev < 50))) mode |= PM_ALLOW_GROUP;
146         if (pet) mode |= PM_FORCE_PET;
147         else mode |= PM_NO_PET;
148
149         if (summon_specific((pet ? -1 : 0), creature_ptr->y, creature_ptr->x, power, SUMMON_ELEMENTAL, mode))
150         {
151                 msg_print(_("エレメンタルが現れた...", "An elemental materializes..."));
152                 if (pet)
153                         msg_print(_("あなたに服従しているようだ。", "It seems obedient to you."));
154                 else
155                         msg_print(_("それをコントロールできなかった!", "You fail to control it!"));
156         }
157
158         return TRUE;
159 }
160
161
162 bool cast_summon_octopus(player_type *creature_ptr)
163 {
164         BIT_FLAGS mode = PM_ALLOW_GROUP;
165         bool pet = !one_in_(5);
166         if (pet) mode |= PM_FORCE_PET;
167
168         if (summon_named_creature(0, creature_ptr->y, creature_ptr->x, MON_JIZOTAKO, mode))
169         {
170                 if (pet)
171                         msg_print(_("蛸があなたの下僕として出現した。", "A group of octopuses appear as your servant."));
172                 else
173                         msg_print(_("蛸はあなたを睨んでいる!", "A group of octopuses appear as your enemy!"));
174         }
175
176         return TRUE;
177 }
178
179 /*!
180 * @brief 悪魔領域のグレーターデーモン召喚に利用可能な死体かどうかを返す。 / An "item_tester_hook" for offer
181 * @param o_ptr オブジェクト構造体の参照ポインタ
182 * @return 生贄に使用可能な死体ならばTRUEを返す。
183 */
184 bool item_tester_offer(object_type *o_ptr)
185 {
186         /* Flasks of oil are okay */
187         if (o_ptr->tval != TV_CORPSE) return (FALSE);
188         if (o_ptr->sval != SV_CORPSE) return (FALSE);
189
190         if (my_strchr("pht", r_info[o_ptr->pval].d_char)) return (TRUE);
191
192         /* Assume not okay */
193         return (FALSE);
194 }
195
196 /*!
197 * @brief 悪魔領域のグレーターデーモン召喚を処理する / Daemon spell Summon Greater Demon
198 * @return 処理を実行したならばTRUEを返す。
199 */
200 bool cast_summon_greater_demon(void)
201 {
202         PLAYER_LEVEL plev = p_ptr->lev;
203         OBJECT_IDX item;
204         concptr q, s;
205         int summon_lev;
206         object_type *o_ptr;
207
208         item_tester_hook = item_tester_offer;
209         q = _("どの死体を捧げますか? ", "Sacrifice which corpse? ");
210         s = _("捧げられる死体を持っていない。", "You have nothing to scrifice.");
211         o_ptr = choose_object(&item, q, s, (USE_INVEN | USE_FLOOR));
212         if (!o_ptr) return FALSE;
213
214         summon_lev = plev * 2 / 3 + r_info[o_ptr->pval].level;
215
216         if (summon_specific(-1, p_ptr->y, p_ptr->x, summon_lev, SUMMON_HI_DEMON, (PM_ALLOW_GROUP | PM_FORCE_PET)))
217         {
218                 msg_print(_("硫黄の悪臭が充満した。", "The area fills with a stench of sulphur and brimstone."));
219                 msg_print(_("「ご用でございますか、ご主人様」", "'What is thy bidding... Master?'"));
220
221                 /* Decrease the item (from the pack) */
222                 if (item >= 0)
223                 {
224                         inven_item_increase(item, -1);
225                         inven_item_describe(item);
226                         inven_item_optimize(item);
227                 }
228
229                 /* Decrease the item (from the floor) */
230                 else
231                 {
232                         floor_item_increase(0 - item, -1);
233                         floor_item_describe(0 - item);
234                         floor_item_optimize(0 - item);
235                 }
236         }
237         else
238         {
239                 msg_print(_("悪魔は現れなかった。", "No Greater Demon arrive."));
240         }
241
242         return TRUE;
243 }
244
245 /*!
246  * @brief 同族召喚(援軍)処理
247  * @param level 召喚基準レベル
248  * @param y 召喚先Y座標
249  * @param x 召喚先X座標
250  * @param mode 召喚オプション
251  * @return ターンを消費した場合TRUEを返す
252  */
253 bool summon_kin_player(DEPTH level, POSITION y, POSITION x, BIT_FLAGS mode)
254 {
255         bool pet = (bool)(mode & PM_FORCE_PET);
256         if (!pet) mode |= PM_NO_PET;
257         return summon_specific((pet ? -1 : 0), y, x, level, SUMMON_KIN, mode);
258 }
259
260 /*!
261  * @brief サイバーデーモンの召喚
262  * @param who 召喚主のモンスターID(0ならばプレイヤー)
263  * @param y 召喚位置Y座標
264  * @param x 召喚位置X座標
265  * @return 作用が実際にあった場合TRUEを返す
266  */
267 int summon_cyber(MONSTER_IDX who, POSITION y, POSITION x)
268 {
269         int i;
270         int max_cyber = (easy_band ? 1 : (current_floor_ptr->dun_level / 50) + randint1(2));
271         int count = 0;
272         BIT_FLAGS mode = PM_ALLOW_GROUP;
273
274         /* Summoned by a monster */
275         if (who > 0)
276         {
277                 monster_type *m_ptr = &current_floor_ptr->m_list[who];
278                 if (is_pet(m_ptr)) mode |= PM_FORCE_PET;
279         }
280
281         if (max_cyber > 4) max_cyber = 4;
282
283         for (i = 0; i < max_cyber; i++)
284         {
285                 count += summon_specific(who, y, x, 100, SUMMON_CYBER, mode);
286         }
287
288         return count;
289 }
290
291
292 void mitokohmon(void)
293 {
294         int count = 0, i;
295         monster_type *m_ptr;
296         concptr kakusan = "";
297
298         if (summon_named_creature(0, p_ptr->y, p_ptr->x, MON_SUKE, PM_FORCE_PET))
299         {
300                 msg_print(_("『助さん』が現れた。", "Suke-san apperars."));
301                 kakusan = "Suke-san";
302                 count++;
303         }
304         if (summon_named_creature(0, p_ptr->y, p_ptr->x, MON_KAKU, PM_FORCE_PET))
305         {
306                 msg_print(_("『格さん』が現れた。", "Kaku-san appears."));
307                 kakusan = "Kaku-san";
308                 count++;
309         }
310         if (!count)
311         {
312                 for (i = current_floor_ptr->m_max - 1; i > 0; i--)
313                 {
314                         m_ptr = &current_floor_ptr->m_list[i];
315                         if (!monster_is_valid(m_ptr)) continue;
316                         if (!((m_ptr->r_idx == MON_SUKE) || (m_ptr->r_idx == MON_KAKU))) continue;
317                         if (!los(m_ptr->fy, m_ptr->fx, p_ptr->y, p_ptr->x)) continue;
318                         if (!projectable(m_ptr->fy, m_ptr->fx, p_ptr->y, p_ptr->x)) continue;
319                         count++;
320                         break;
321                 }
322         }
323
324         if (count)
325         {
326                 msg_format(_("「者ども、ひかえおろう!!!このお方をどなたとこころえる。」",
327                         "%^s says 'WHO do you think this person is! Bow your head, down your knees!'"), kakusan);
328                 sukekaku = TRUE;
329                 stun_monsters(120);
330                 confuse_monsters(120);
331                 turn_monsters(120);
332                 stasis_monsters(120);
333                 sukekaku = FALSE;
334         }
335         else
336         {
337                 msg_print(_("しかし、何も起きなかった。", "Nothing happen."));
338         }
339 }