OSDN Git Service

[Refactor] #37353 GF_* と gf_color を整理。
[hengband/hengband.git] / src / realm-arcane.c
1 #include "angband.h"
2 #include "cmd-spell.h"
3 #include "avatar.h"
4
5 #include "spells.h"
6 #include "spells-floor.h"
7 #include "spells-object.h"
8 #include "spells-summon.h"
9 #include "spells-status.h"
10 #include "player-status.h"
11
12 /*!
13 * @brief 秘術領域魔法の各処理を行う
14 * @param spell 魔法ID
15 * @param mode 処理内容 (SPELL_NAME / SPELL_DESC / SPELL_INFO / SPELL_CAST)
16 * @return SPELL_NAME / SPELL_DESC / SPELL_INFO 時には文字列ポインタを返す。SPELL_CAST時はNULL文字列を返す。
17 */
18 concptr do_arcane_spell(SPELL_IDX spell, BIT_FLAGS mode)
19 {
20         bool name = (mode == SPELL_NAME) ? TRUE : FALSE;
21         bool desc = (mode == SPELL_DESC) ? TRUE : FALSE;
22         bool info = (mode == SPELL_INFO) ? TRUE : FALSE;
23         bool cast = (mode == SPELL_CAST) ? TRUE : FALSE;
24
25         DIRECTION dir;
26         PLAYER_LEVEL plev = p_ptr->lev;
27
28         switch (spell)
29         {
30         case 0:
31                 if (name) return _("電撃", "Zap");
32                 if (desc) return _("電撃のボルトもしくはビームを放つ。", "Fires a bolt or beam of lightning.");
33
34                 {
35                         DICE_NUMBER dice = 3 + (plev - 1) / 5;
36                         DICE_SID sides = 3;
37
38                         if (info) return info_damage(dice, sides, 0);
39
40                         if (cast)
41                         {
42                                 if (!get_aim_dir(&dir)) return NULL;
43
44                                 fire_bolt_or_beam(beam_chance() - 10, GF_ELEC, dir, damroll(dice, sides));
45                         }
46                 }
47                 break;
48
49         case 1:
50                 if (name) return _("魔法の施錠", "Wizard Lock");
51                 if (desc) return _("扉に鍵をかける。", "Locks a door.");
52
53                 {
54                         if (cast)
55                         {
56                                 if (!get_aim_dir(&dir)) return NULL;
57
58                                 wizard_lock(dir);
59                         }
60                 }
61                 break;
62
63         case 2:
64                 if (name) return _("透明体感知", "Detect Invisibility");
65                 if (desc) return _("近くの透明なモンスターを感知する。", "Detects all invisible monsters in your vicinity.");
66
67                 {
68                         POSITION rad = DETECT_RAD_DEFAULT;
69
70                         if (info) return info_radius(rad);
71
72                         if (cast)
73                         {
74                                 detect_monsters_invis(rad);
75                         }
76                 }
77                 break;
78
79         case 3:
80                 if (name) return _("モンスター感知", "Detect Monsters");
81                 if (desc) return _("近くの全ての見えるモンスターを感知する。", "Detects all monsters in your vicinity unless invisible.");
82
83                 {
84                         POSITION rad = DETECT_RAD_DEFAULT;
85
86                         if (info) return info_radius(rad);
87
88                         if (cast)
89                         {
90                                 detect_monsters_normal(rad);
91                         }
92                 }
93                 break;
94
95         case 4:
96                 if (name) return _("ショート・テレポート", "Blink");
97                 if (desc) return _("近距離のテレポートをする。", "Teleport short distance.");
98
99                 {
100                         POSITION range = 10;
101
102                         if (info) return info_range(range);
103
104                         if (cast)
105                         {
106                                 teleport_player(range, 0L);
107                         }
108                 }
109                 break;
110
111         case 5:
112                 if (name) return _("ライト・エリア", "Light Area");
113                 if (desc) return _("光源が照らしている範囲か部屋全体を永久に明るくする。", "Lights up nearby area and the inside of a room permanently.");
114
115                 {
116                         DICE_NUMBER dice = 2;
117                         DICE_SID sides = plev / 2;
118                         POSITION rad = plev / 10 + 1;
119
120                         if (info) return info_damage(dice, sides, 0);
121
122                         if (cast)
123                         {
124                                 lite_area(damroll(dice, sides), rad);
125                         }
126                 }
127                 break;
128
129         case 6:
130                 if (name) return _("罠と扉 破壊", "Trap & Door Destruction");
131                 if (desc) return _("一直線上の全ての罠と扉を破壊する。", "Fires a beam which destroy traps and doors.");
132
133                 {
134                         if (cast)
135                         {
136                                 if (!get_aim_dir(&dir)) return NULL;
137
138                                 destroy_door(dir);
139                         }
140                 }
141                 break;
142
143         case 7:
144                 if (name) return _("軽傷の治癒", "Cure Light Wounds");
145                 if (desc) return _("怪我と体力を少し回復させる。", "Heals cut and HP a little.");
146
147                 {
148                         DICE_NUMBER dice = 2;
149                         DICE_SID sides = 8;
150
151                         if (info) return info_heal(dice, sides, 0);
152                         if (cast) (void)cure_light_wounds(dice, sides);
153                 }
154                 break;
155
156         case 8:
157                 if (name) return _("罠と扉 感知", "Detect Doors & Traps");
158                 if (desc) return _("近くの全ての罠と扉と階段を感知する。", "Detects traps, doors, and stairs in your vicinity.");
159
160                 {
161                         POSITION rad = DETECT_RAD_DEFAULT;
162
163                         if (info) return info_radius(rad);
164
165                         if (cast)
166                         {
167                                 detect_traps(rad, TRUE);
168                                 detect_doors(rad);
169                                 detect_stairs(rad);
170                         }
171                 }
172                 break;
173
174         case 9:
175                 if (name) return _("燃素", "Phlogiston");
176                 if (desc) return _("光源に燃料を補給する。", "Adds more turns of light to a lantern or torch.");
177
178                 {
179                         if (cast)
180                         {
181                                 phlogiston();
182                         }
183                 }
184                 break;
185
186         case 10:
187                 if (name) return _("財宝感知", "Detect Treasure");
188                 if (desc) return _("近くの財宝を感知する。", "Detects all treasures in your vicinity.");
189
190                 {
191                         POSITION rad = DETECT_RAD_DEFAULT;
192
193                         if (info) return info_radius(rad);
194
195                         if (cast)
196                         {
197                                 detect_treasure(rad);
198                                 detect_objects_gold(rad);
199                         }
200                 }
201                 break;
202
203         case 11:
204                 if (name) return _("魔法 感知", "Detect Enchantment");
205                 if (desc) return _("近くの魔法がかかったアイテムを感知する。", "Detects all magical items in your vicinity.");
206
207                 {
208                         POSITION rad = DETECT_RAD_DEFAULT;
209
210                         if (info) return info_radius(rad);
211
212                         if (cast)
213                         {
214                                 detect_objects_magic(rad);
215                         }
216                 }
217                 break;
218
219         case 12:
220                 if (name) return _("アイテム感知", "Detect Objects");
221                 if (desc) return _("近くの全てのアイテムを感知する。", "Detects all items in your vicinity.");
222
223                 {
224                         POSITION rad = DETECT_RAD_DEFAULT;
225
226                         if (info) return info_radius(rad);
227
228                         if (cast)
229                         {
230                                 detect_objects_normal(rad);
231                         }
232                 }
233                 break;
234
235         case 13:
236                 if (name) return _("解毒", "Cure Poison");
237                 if (desc) return _("毒を体内から完全に取り除く。", "Cures poison status.");
238
239                 {
240                         if (cast)
241                         {
242                                 set_poisoned(0);
243                         }
244                 }
245                 break;
246
247         case 14:
248                 if (name) return _("耐冷", "Resist Cold");
249                 if (desc) return _("一定時間、冷気への耐性を得る。装備による耐性に累積する。", "Gives resistance to cold. This resistance can be added to which from equipment for more powerful resistance.");
250
251                 {
252                         int base = 20;
253
254                         if (info) return info_duration(base, base);
255
256                         if (cast)
257                         {
258                                 set_oppose_cold(randint1(base) + base, FALSE);
259                         }
260                 }
261                 break;
262
263         case 15:
264                 if (name) return _("耐火", "Resist Fire");
265                 if (desc) return _("一定時間、炎への耐性を得る。装備による耐性に累積する。",
266                         "Gives resistance to fire. This resistance can be added to which from equipment for more powerful resistance.");
267
268                 {
269                         int base = 20;
270
271                         if (info) return info_duration(base, base);
272
273                         if (cast)
274                         {
275                                 set_oppose_fire(randint1(base) + base, FALSE);
276                         }
277                 }
278                 break;
279
280         case 16:
281                 if (name) return _("耐電", "Resist Lightning");
282                 if (desc) return _("一定時間、電撃への耐性を得る。装備による耐性に累積する。",
283                         "Gives resistance to electricity. This resistance can be added to which from equipment for more powerful resistance.");
284
285                 {
286                         int base = 20;
287
288                         if (info) return info_duration(base, base);
289
290                         if (cast)
291                         {
292                                 set_oppose_elec(randint1(base) + base, FALSE);
293                         }
294                 }
295                 break;
296
297         case 17:
298                 if (name) return _("耐酸", "Resist Acid");
299                 if (desc) return _("一定時間、酸への耐性を得る。装備による耐性に累積する。",
300                         "Gives resistance to acid. This resistance can be added to which from equipment for more powerful resistance.");
301
302                 {
303                         int base = 20;
304
305                         if (info) return info_duration(base, base);
306
307                         if (cast)
308                         {
309                                 set_oppose_acid(randint1(base) + base, FALSE);
310                         }
311                 }
312                 break;
313
314         case 18:
315                 if (name) return _("重傷の治癒", "Cure Medium Wounds");
316                 if (desc) return _("怪我と体力を中程度回復させる。", "Heals cut and HP more.");
317
318                 {
319                         DICE_NUMBER dice = 4;
320                         DICE_SID sides = 8;
321
322                         if (info) return info_heal(dice, sides, 0);
323                         if (cast) (void)cure_serious_wounds(4, 8);
324                 }
325                 break;
326
327         case 19:
328                 if (name) return _("テレポート", "Teleport");
329                 if (desc) return _("遠距離のテレポートをする。", "Teleport long distance.");
330
331                 {
332                         POSITION range = plev * 5;
333
334                         if (info) return info_range(range);
335
336                         if (cast)
337                         {
338                                 teleport_player(range, 0L);
339                         }
340                 }
341                 break;
342
343         case 20:
344                 if (name) return _("鑑定", "Identify");
345                 if (desc) return _("アイテムを識別する。", "Identifies an item.");
346
347                 {
348                         if (cast)
349                         {
350                                 if (!ident_spell(FALSE)) return NULL;
351                         }
352                 }
353                 break;
354
355         case 21:
356                 if (name) return _("岩石溶解", "Stone to Mud");
357                 if (desc) return _("壁を溶かして床にする。", "Turns one rock square to mud.");
358
359                 {
360                         DICE_NUMBER dice = 1;
361                         DICE_SID sides = 30;
362                         int base = 20;
363
364                         if (info) return info_damage(dice, sides, base);
365
366                         if (cast)
367                         {
368                                 if (!get_aim_dir(&dir)) return NULL;
369
370                                 wall_to_mud(dir, 20 + randint1(30));
371                         }
372                 }
373                 break;
374
375         case 22:
376                 if (name) return _("閃光", "Ray of Light");
377                 if (desc) return _("光線を放つ。光りを嫌うモンスターに効果がある。", "Fires a beam of light which damages to light-sensitive monsters.");
378
379                 {
380                         DICE_NUMBER dice = 6;
381                         DICE_SID sides = 8;
382
383                         if (info) return info_damage(dice, sides, 0);
384
385                         if (cast)
386                         {
387                                 if (!get_aim_dir(&dir)) return NULL;
388
389                                 msg_print(_("光線が放たれた。", "A line of light appears."));
390                                 lite_line(dir, damroll(6, 8));
391                         }
392                 }
393                 break;
394
395         case 23:
396                 if (name) return _("空腹充足", "Satisfy Hunger");
397                 if (desc) return _("満腹にする。", "Satisfies hunger.");
398
399                 {
400                         if (cast)
401                         {
402                                 set_food(PY_FOOD_MAX - 1);
403                         }
404                 }
405                 break;
406
407         case 24:
408                 if (name) return _("透明視認", "See Invisible");
409                 if (desc) return _("一定時間、透明なものが見えるようになる。", "Gives see invisible for a while.");
410
411                 {
412                         int base = 24;
413
414                         if (info) return info_duration(base, base);
415
416                         if (cast)
417                         {
418                                 set_tim_invis(randint1(base) + base, FALSE);
419                         }
420                 }
421                 break;
422
423         case 25:
424                 if (name) return _("エレメンタル召喚", "Conjure Elemental");
425                 if (desc) return _("1体のエレメンタルを召喚する。", "Summons an elemental.");
426                 {
427                         if (cast)
428                         {
429                                 if (!summon_specific(-1, p_ptr->y, p_ptr->x, plev, SUMMON_ELEMENTAL, (PM_ALLOW_GROUP | PM_FORCE_PET), '\0'))
430                                 {
431                                         msg_print(_("エレメンタルは現れなかった。", "No Elementals arrive."));
432                                 }
433                         }
434                 }
435                 break;
436
437         case 26:
438                 if (name) return _("テレポート・レベル", "Teleport Level");
439                 if (desc) return _("瞬時に上か下の階にテレポートする。", "Teleport to up or down stairs in a moment.");
440
441                 {
442                         if (cast)
443                         {
444                                 if (!get_check(_("本当に他の階にテレポートしますか?", "Are you sure? (Teleport Level)"))) return NULL;
445                                 teleport_level(0);
446                         }
447                 }
448                 break;
449
450         case 27:
451                 if (name) return _("テレポート・モンスター", "Teleport Away");
452                 if (desc) return _("モンスターをテレポートさせるビームを放つ。抵抗されると無効。", "Teleports all monsters on the line away unless resisted.");
453
454                 {
455                         int power = plev;
456
457                         if (info) return info_power(power);
458
459                         if (cast)
460                         {
461                                 if (!get_aim_dir(&dir)) return NULL;
462
463                                 fire_beam(GF_AWAY_ALL, dir, power);
464                         }
465                 }
466                 break;
467
468         case 28:
469                 if (name) return _("元素の球", "Elemental Ball");
470                 if (desc) return _("炎、電撃、冷気、酸のどれかの球を放つ。", "Fires a ball of some elements.");
471
472                 {
473                         HIT_POINT dam = 75 + plev;
474                         POSITION rad = 2;
475
476                         if (info) return info_damage(0, 0, dam);
477
478                         if (cast)
479                         {
480                                 int type;
481
482                                 if (!get_aim_dir(&dir)) return NULL;
483
484                                 switch (randint1(4))
485                                 {
486                                 case 1:  type = GF_FIRE; break;
487                                 case 2:  type = GF_ELEC; break;
488                                 case 3:  type = GF_COLD; break;
489                                 default: type = GF_ACID; break;
490                                 }
491
492                                 fire_ball(type, dir, dam, rad);
493                         }
494                 }
495                 break;
496
497         case 29:
498                 if (name) return _("全感知", "Detection");
499                 if (desc) return _("近くの全てのモンスター、罠、扉、階段、財宝、そしてアイテムを感知する。",
500                         "Detects all monsters, traps, doors, stairs, treasures and items in your vicinity.");
501
502                 {
503                         POSITION rad = DETECT_RAD_DEFAULT;
504
505                         if (info) return info_radius(rad);
506
507                         if (cast)
508                         {
509                                 detect_all(rad);
510                         }
511                 }
512                 break;
513
514         case 30:
515                 if (name) return _("帰還の呪文", "Word of Recall");
516                 if (desc) return _("地上にいるときはダンジョンの最深階へ、ダンジョンにいるときは地上へと移動する。",
517                         "Recalls player from dungeon to town, or from town to the deepest level of dungeon.");
518
519                 {
520                         int base = 15;
521                         DICE_SID sides = 20;
522
523                         if (info) return info_delay(base, sides);
524
525                         if (cast)
526                         {
527                                 if (!recall_player(p_ptr, randint0(21) + 15)) return NULL;
528                         }
529                 }
530                 break;
531
532         case 31:
533                 if (name) return _("千里眼", "Clairvoyance");
534                 if (desc) return _("その階全体を永久に照らし、ダンジョン内すべてのアイテムを感知する。さらに、一定時間テレパシー能力を得る。",
535                         "Maps and lights whole dungeon level. Knows all objects location. And gives telepathy for a while.");
536
537                 {
538                         int base = 25;
539                         DICE_SID sides = 30;
540
541                         if (info) return info_duration(base, sides);
542
543                         if (cast)
544                         {
545                                 chg_virtue(V_KNOWLEDGE, 1);
546                                 chg_virtue(V_ENLIGHTEN, 1);
547
548                                 wiz_lite(FALSE);
549
550                                 if (!p_ptr->telepathy)
551                                 {
552                                         set_tim_esp(randint1(sides) + base, FALSE);
553                                 }
554                         }
555                 }
556                 break;
557         }
558
559         return "";
560 }