OSDN Git Service

[Refactor] #38862 Moved save/load.c/h to io/
[hengband/hengband.git] / src / realm / realm-hissatsu.c
1 #include "system/angband.h"
2 #include "core/stuff-handler.h"
3 #include "util.h"
4
5 #include "cmd-spell.h"
6 #include "cmd-basic.h"
7 #include "dungeon/dungeon.h"
8 #include "effect/effect-characteristics.h"
9 #include "melee.h"
10 #include "monster/monsterrace-hook.h"
11 #include "artifact.h"
12 #include "monster/monster.h"
13 #include "player/player-move.h"
14 #include "player/player-status.h"
15 #include "player/player-effects.h"
16 #include "player/player-damage.h"
17 #include "feature.h"
18 #include "spell/technic-info-table.h"
19 #include "grid.h"
20 #include "targeting.h"
21 #include "view/display-main-window.h"
22 #include "spell/spells-floor.h"
23 #include "world/world.h"
24 #include "effect/spells-effect-util.h"
25 #include "spell/spells-util.h"
26 #include "spell/spells-type.h"
27 #include "spell/process-effect.h"
28 #include "spell/spells2.h"
29 #include "spell/spells3.h"
30
31 /*!
32 * @brief 剣術の各処理を行う
33 * @param caster_ptr プレーヤーへの参照ポインタ
34 * @param spell 剣術ID
35 * @param mode 処理内容 (SPELL_NAME / SPELL_DESC / SPELL_CAST)
36 * @return SPELL_NAME / SPELL_DESC 時には文字列ポインタを返す。SPELL_CAST時はNULL文字列を返す。
37 */
38 concptr do_hissatsu_spell(player_type *caster_ptr, SPELL_IDX spell, spell_type mode)
39 {
40         bool name = (mode == SPELL_NAME) ? TRUE : FALSE;
41         bool desc = (mode == SPELL_DESC) ? TRUE : FALSE;
42         bool cast = (mode == SPELL_CAST) ? TRUE : FALSE;
43
44         DIRECTION dir;
45         PLAYER_LEVEL plev = caster_ptr->lev;
46
47         switch (spell)
48         {
49         case 0:
50                 if (name) return _("飛飯綱", "Tobi-Izuna");
51                 if (desc) return _("2マス離れたところにいるモンスターを攻撃する。", "Attacks a monster two squares away.");
52
53                 if (cast)
54                 {
55                         project_length = 2;
56                         if (!get_aim_dir(caster_ptr, &dir)) return NULL;
57
58                         project_hook(caster_ptr, GF_ATTACK, dir, HISSATSU_2, PROJECT_STOP | PROJECT_KILL);
59                 }
60                 break;
61
62         case 1:
63                 if (name) return _("五月雨斬り", "3-Way Attack");
64                 if (desc) return _("3方向に対して攻撃する。", "Attacks in 3 directions at one time.");
65
66                 if (cast)
67                 {
68                         DIRECTION cdir;
69                         POSITION y, x;
70
71                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
72                         if (dir == 5) return NULL;
73
74                         for (cdir = 0; cdir < 8; cdir++)
75                         {
76                                 if (cdd[cdir] == dir) break;
77                         }
78
79                         if (cdir == 8) return NULL;
80
81                         y = caster_ptr->y + ddy_cdd[cdir];
82                         x = caster_ptr->x + ddx_cdd[cdir];
83                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
84                                 py_attack(caster_ptr, y, x, 0);
85                         else
86                                 msg_print(_("攻撃は空を切った。", "You attack the empty air."));
87
88                         y = caster_ptr->y + ddy_cdd[(cdir + 7) % 8];
89                         x = caster_ptr->x + ddx_cdd[(cdir + 7) % 8];
90                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
91                                 py_attack(caster_ptr, y, x, 0);
92                         else
93                                 msg_print(_("攻撃は空を切った。", "You attack the empty air."));
94
95                         y = caster_ptr->y + ddy_cdd[(cdir + 1) % 8];
96                         x = caster_ptr->x + ddx_cdd[(cdir + 1) % 8];
97                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
98                                 py_attack(caster_ptr, y, x, 0);
99                         else
100                                 msg_print(_("攻撃は空を切った。", "You attack the empty air."));
101                 }
102                 break;
103
104         case 2:
105                 if (name) return _("ブーメラン", "Boomerang");
106                 if (desc) return _("武器を手元に戻ってくるように投げる。戻ってこないこともある。",
107                         "Throws current weapon. It'll return to your hand unless the action failed.");
108
109                 if (cast)
110                 {
111                         if (!do_cmd_throw(caster_ptr, 1, TRUE, -1)) return NULL;
112                 }
113                 break;
114
115         case 3:
116                 if (name) return _("焔霊", "Burning Strike");
117                 if (desc) return _("火炎耐性のないモンスターに大ダメージを与える。", "Attacks a monster with more damage unless it has resistance to fire.");
118
119                 if (cast)
120                 {
121                         POSITION y, x;
122
123                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
124                         if (dir == 5) return NULL;
125
126                         y = caster_ptr->y + ddy[dir];
127                         x = caster_ptr->x + ddx[dir];
128
129                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
130                                 py_attack(caster_ptr, y, x, HISSATSU_FIRE);
131                         else
132                         {
133                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
134                                 return NULL;
135                         }
136                 }
137                 break;
138
139         case 4:
140                 if (name) return _("殺気感知", "Detect Ferocity");
141                 if (desc) return _("近くの思考することができるモンスターを感知する。", "Detects all monsters except the mindless in your vicinity.");
142
143                 if (cast)
144                 {
145                         detect_monsters_mind(caster_ptr, DETECT_RAD_DEFAULT);
146                 }
147                 break;
148
149         case 5:
150                 if (name) return _("みね打ち", "Strike to Stun");
151                 if (desc) return _("相手にダメージを与えないが、朦朧とさせる。", "Attempts to stun a monster next to you.");
152
153                 if (cast)
154                 {
155                         POSITION y, x;
156
157                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
158                         if (dir == 5) return NULL;
159
160                         y = caster_ptr->y + ddy[dir];
161                         x = caster_ptr->x + ddx[dir];
162
163                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
164                                 py_attack(caster_ptr, y, x, HISSATSU_MINEUCHI);
165                         else
166                         {
167                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
168                                 return NULL;
169                         }
170                 }
171                 break;
172
173         case 6:
174                 if (name) return _("カウンター", "Counter");
175                 if (desc) return _("相手に攻撃されたときに反撃する。反撃するたびにMPを消費。",
176                         "Prepares to counterattack. When attacked by a monster, strikes back using SP each time.");
177
178                 if (cast)
179                 {
180                         if (caster_ptr->riding)
181                         {
182                                 msg_print(_("乗馬中には無理だ。", "You cannot do it when riding."));
183                                 return NULL;
184                         }
185                         msg_print(_("相手の攻撃に対して身構えた。", "You prepare to counterattack."));
186                         caster_ptr->counter = TRUE;
187                 }
188                 break;
189
190         case 7:
191                 if (name) return _("払い抜け", "Harainuke");
192                 if (desc) return _("攻撃した後、反対側に抜ける。",
193                         "In one action, attacks a monster with your weapons normally and then moves to the space beyond the monster if that space is not blocked.");
194
195                 if (cast)
196                 {
197                         POSITION y, x;
198
199                         if (caster_ptr->riding)
200                         {
201                                 msg_print(_("乗馬中には無理だ。", "You cannot do it when riding."));
202                                 return NULL;
203                         }
204
205                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
206
207                         if (dir == 5) return NULL;
208                         y = caster_ptr->y + ddy[dir];
209                         x = caster_ptr->x + ddx[dir];
210
211                         if (!caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
212                         {
213                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
214                                 return NULL;
215                         }
216
217                         py_attack(caster_ptr, y, x, 0);
218
219                         if (!player_can_enter(caster_ptr, caster_ptr->current_floor_ptr->grid_array[y][x].feat, 0) || is_trap(caster_ptr, caster_ptr->current_floor_ptr->grid_array[y][x].feat))
220                                 break;
221
222                         y += ddy[dir];
223                         x += ddx[dir];
224
225                         if (player_can_enter(caster_ptr, caster_ptr->current_floor_ptr->grid_array[y][x].feat, 0) && !is_trap(caster_ptr, caster_ptr->current_floor_ptr->grid_array[y][x].feat) && !caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
226                         {
227                                 msg_print(NULL);
228                                 (void)move_player_effect(caster_ptr, y, x, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP);
229                         }
230                 }
231                 break;
232
233         case 8:
234                 if (name) return _("サーペンツタン", "Serpent's Tongue");
235                 if (desc) return _("毒耐性のないモンスターに大ダメージを与える。", "Attacks a monster with more damage unless it has resistance to poison.");
236
237                 if (cast)
238                 {
239                         POSITION y, x;
240
241                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
242                         if (dir == 5) return NULL;
243
244                         y = caster_ptr->y + ddy[dir];
245                         x = caster_ptr->x + ddx[dir];
246
247                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
248                                 py_attack(caster_ptr, y, x, HISSATSU_POISON);
249                         else
250                         {
251                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
252                                 return NULL;
253                         }
254                 }
255                 break;
256
257         case 9:
258                 if (name) return _("斬魔剣弐の太刀", "Zammaken");
259                 if (desc) return _("生命のない邪悪なモンスターに大ダメージを与えるが、他のモンスターには全く効果がない。",
260                         "Attacks an evil unliving monster with great damage. Has no effect on other monsters.");
261
262                 if (cast)
263                 {
264                         POSITION y, x;
265
266                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
267                         if (dir == 5) return NULL;
268
269                         y = caster_ptr->y + ddy[dir];
270                         x = caster_ptr->x + ddx[dir];
271
272                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
273                                 py_attack(caster_ptr, y, x, HISSATSU_ZANMA);
274                         else
275                         {
276                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
277                                 return NULL;
278                         }
279                 }
280                 break;
281
282         case 10:
283                 if (name) return _("裂風剣", "Wind Blast");
284                 if (desc) return _("攻撃した相手を後方へ吹き飛ばす。", "Attacks an adjacent monster and blows it away.");
285
286                 if (cast)
287                 {
288                         POSITION y, x;
289
290                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
291                         if (dir == 5) return NULL;
292
293                         y = caster_ptr->y + ddy[dir];
294                         x = caster_ptr->x + ddx[dir];
295
296                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
297                                 py_attack(caster_ptr, y, x, 0);
298                         else
299                         {
300                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
301                                 return NULL;
302                         }
303                         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_NO_MELEE)
304                         {
305                                 return "";
306                         }
307                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
308                         {
309                                 int i;
310                                 POSITION ty = y, tx = x;
311                                 POSITION oy = y, ox = x;
312                                 MONSTER_IDX m_idx = caster_ptr->current_floor_ptr->grid_array[y][x].m_idx;
313                                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
314                                 GAME_TEXT m_name[MAX_NLEN];
315
316                                 monster_desc(caster_ptr, m_name, m_ptr, 0);
317
318                                 for (i = 0; i < 5; i++)
319                                 {
320                                         y += ddy[dir];
321                                         x += ddx[dir];
322                                         if (is_cave_empty_bold(caster_ptr, y, x))
323                                         {
324                                                 ty = y;
325                                                 tx = x;
326                                         }
327                                         else break;
328                                 }
329                                 if ((ty != oy) || (tx != ox))
330                                 {
331                                         msg_format(_("%sを吹き飛ばした!", "You blow %s away!"), m_name);
332                                         caster_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = 0;
333                                         caster_ptr->current_floor_ptr->grid_array[ty][tx].m_idx = m_idx;
334                                         m_ptr->fy = ty;
335                                         m_ptr->fx = tx;
336
337                                         update_monster(caster_ptr, m_idx, TRUE);
338                                         lite_spot(caster_ptr, oy, ox);
339                                         lite_spot(caster_ptr, ty, tx);
340
341                                         if (r_info[m_ptr->r_idx].flags7 & (RF7_LITE_MASK | RF7_DARK_MASK))
342                                                 caster_ptr->update |= (PU_MON_LITE);
343                                 }
344                         }
345                 }
346                 break;
347
348         case 11:
349                 if (name) return _("刀匠の目利き", "Judge");
350                 if (desc) return _("武器・防具を1つ識別する。レベル45以上で武器・防具の能力を完全に知ることができる。",
351                         "Identifies a weapon or armor. *Identifies* the item at level 45.");
352
353                 if (cast)
354                 {
355                         if (plev > 44)
356                         {
357                                 if (!identify_fully(caster_ptr, TRUE, 0)) return NULL;
358                         }
359                         else
360                         {
361                                 if (!ident_spell(caster_ptr, TRUE, 0)) return NULL;
362                         }
363                 }
364                 break;
365
366         case 12:
367                 if (name) return _("破岩斬", "Rock Smash");
368                 if (desc) return _("岩を壊し、岩石系のモンスターに大ダメージを与える。", "Breaks rock or greatly damages a monster made of rocks.");
369
370                 if (cast)
371                 {
372                         POSITION y, x;
373
374                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
375                         if (dir == 5) return NULL;
376
377                         y = caster_ptr->y + ddy[dir];
378                         x = caster_ptr->x + ddx[dir];
379
380                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
381                                 py_attack(caster_ptr, y, x, HISSATSU_HAGAN);
382
383                         if (!cave_have_flag_bold(caster_ptr->current_floor_ptr, y, x, FF_HURT_ROCK)) break;
384
385                         /* Destroy the feature */
386                         cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK);
387                         caster_ptr->update |= (PU_FLOW);
388                 }
389                 break;
390
391         case 13:
392                 if (name) return _("乱れ雪月花", "Midare-Setsugekka");
393                 if (desc) return _("攻撃回数が増え、冷気耐性のないモンスターに大ダメージを与える。",
394                         "Attacks a monster with an increased number of attacks and more damage unless it has resistance to cold.");
395
396                 if (cast)
397                 {
398                         POSITION y, x;
399
400                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
401                         if (dir == 5) return NULL;
402
403                         y = caster_ptr->y + ddy[dir];
404                         x = caster_ptr->x + ddx[dir];
405
406                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
407                                 py_attack(caster_ptr, y, x, HISSATSU_COLD);
408                         else
409                         {
410                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
411                                 return NULL;
412                         }
413                 }
414                 break;
415
416         case 14:
417                 if (name) return _("急所突き", "Spot Aiming");
418                 if (desc) return _("モンスターを一撃で倒す攻撃を繰り出す。失敗すると1点しかダメージを与えられない。",
419                         "Attempts to kill a monster instantly. If that fails, causes only 1HP of damage.");
420
421                 if (cast)
422                 {
423                         POSITION y, x;
424
425                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
426                         if (dir == 5) return NULL;
427
428                         y = caster_ptr->y + ddy[dir];
429                         x = caster_ptr->x + ddx[dir];
430
431                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
432                                 py_attack(caster_ptr, y, x, HISSATSU_KYUSHO);
433                         else
434                         {
435                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
436                                 return NULL;
437                         }
438                 }
439                 break;
440
441         case 15:
442                 if (name) return _("魔神斬り", "Majingiri");
443                 if (desc) return _("会心の一撃で攻撃する。攻撃がかわされやすい。",
444                         "Attempts to attack with a critical hit, but this attack is easy to evade for a monster.");
445
446                 if (cast)
447                 {
448                         POSITION y, x;
449
450                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
451                         if (dir == 5) return NULL;
452
453                         y = caster_ptr->y + ddy[dir];
454                         x = caster_ptr->x + ddx[dir];
455
456                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
457                                 py_attack(caster_ptr, y, x, HISSATSU_MAJIN);
458                         else
459                         {
460                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
461                                 return NULL;
462                         }
463                 }
464                 break;
465
466         case 16:
467                 if (name) return _("捨て身", "Desperate Attack");
468                 if (desc) return _("強力な攻撃を繰り出す。次のターンまでの間、食らうダメージが増える。",
469                         "Attacks with all of your power, but all damage you take will be doubled for one turn.");
470
471                 if (cast)
472                 {
473                         POSITION y, x;
474
475                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
476                         if (dir == 5) return NULL;
477
478                         y = caster_ptr->y + ddy[dir];
479                         x = caster_ptr->x + ddx[dir];
480
481                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
482                                 py_attack(caster_ptr, y, x, HISSATSU_SUTEMI);
483                         else
484                         {
485                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
486                                 return NULL;
487                         }
488                         caster_ptr->sutemi = TRUE;
489                 }
490                 break;
491
492         case 17:
493                 if (name) return _("雷撃鷲爪斬", "Lightning Eagle");
494                 if (desc) return _("電撃耐性のないモンスターに非常に大きいダメージを与える。",
495                         "Attacks a monster with more damage unless it has resistance to electricity.");
496
497                 if (cast)
498                 {
499                         POSITION y, x;
500
501                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
502                         if (dir == 5) return NULL;
503
504                         y = caster_ptr->y + ddy[dir];
505                         x = caster_ptr->x + ddx[dir];
506
507                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
508                                 py_attack(caster_ptr, y, x, HISSATSU_ELEC);
509                         else
510                         {
511                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
512                                 return NULL;
513                         }
514                 }
515                 break;
516
517         case 18:
518                 if (name) return _("入身", "Rush Attack");
519                 if (desc) return _("素早く相手に近寄り攻撃する。", "Steps close to a monster and attacks at the same time.");
520
521                 if (cast)
522                 {
523                         if (!rush_attack(caster_ptr, NULL)) return NULL;
524                 }
525                 break;
526
527         case 19:
528                 if (name) return _("赤流渦", "Bloody Maelstrom");
529                 if (desc) return _("自分自身も傷を作りつつ、その傷が深いほど大きい威力で全方向の敵を攻撃できる。生きていないモンスターには効果がない。",
530                         "Attacks all adjacent monsters with power corresponding to your cuts. Then increases your cuts. Has no effect on unliving monsters.");
531
532                 if (cast)
533                 {
534                         POSITION y = 0, x = 0;
535
536                         grid_type       *g_ptr;
537                         monster_type    *m_ptr;
538
539                         if (caster_ptr->cut < 300)
540                                 set_cut(caster_ptr,caster_ptr->cut + 300);
541                         else
542                                 set_cut(caster_ptr,caster_ptr->cut * 2);
543
544                         for (dir = 0; dir < 8; dir++)
545                         {
546                                 y = caster_ptr->y + ddy_ddd[dir];
547                                 x = caster_ptr->x + ddx_ddd[dir];
548                                 g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
549                                 m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
550
551                                 /* Hack -- attack monsters */
552                                 if (g_ptr->m_idx && (m_ptr->ml || cave_have_flag_bold(caster_ptr->current_floor_ptr, y, x, FF_PROJECT)))
553                                 {
554                                         if (!monster_living(m_ptr->r_idx))
555                                         {
556                                                 GAME_TEXT m_name[MAX_NLEN];
557
558                                                 monster_desc(caster_ptr, m_name, m_ptr, 0);
559                                                 msg_format(_("%sには効果がない!", "%s is unharmed!"), m_name);
560                                         }
561                                         else py_attack(caster_ptr, y, x, HISSATSU_SEKIRYUKA);
562                                 }
563                         }
564                 }
565                 break;
566
567         case 20:
568                 if (name) return _("激震撃", "Earthquake Blow");
569                 if (desc) return _("地震を起こす。", "Shakes dungeon structure, and results in random swapping of floors and walls.");
570
571                 if (cast)
572                 {
573                         POSITION y, x;
574
575                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
576                         if (dir == 5) return NULL;
577
578                         y = caster_ptr->y + ddy[dir];
579                         x = caster_ptr->x + ddx[dir];
580
581                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
582                                 py_attack(caster_ptr, y, x, HISSATSU_QUAKE);
583                         else
584                                 earthquake(caster_ptr, caster_ptr->y, caster_ptr->x, 10, 0);
585                 }
586                 break;
587
588         case 21:
589                 if (name) return _("地走り", "Crack");
590                 if (desc) return _("衝撃波のビームを放つ。", "Fires a shock wave as a beam.");
591
592                 if (cast)
593                 {
594                         int total_damage = 0, basedam, i;
595                         BIT_FLAGS flgs[TR_FLAG_SIZE];
596                         object_type *o_ptr;
597                         if (!get_aim_dir(caster_ptr, &dir)) return NULL;
598                         msg_print(_("武器を大きく振り下ろした。", "You swing your weapon downward."));
599                         for (i = 0; i < 2; i++)
600                         {
601                                 int damage;
602
603                                 if (!has_melee_weapon(caster_ptr, INVEN_RARM + i)) break;
604                                 o_ptr = &caster_ptr->inventory_list[INVEN_RARM + i];
605                                 basedam = (o_ptr->dd * (o_ptr->ds + 1)) * 50;
606                                 damage = o_ptr->to_d * 100;
607                                 object_flags(o_ptr, flgs);
608                                 if ((o_ptr->name1 == ART_VORPAL_BLADE) || (o_ptr->name1 == ART_CHAINSWORD))
609                                 {
610                                         /* vorpal blade */
611                                         basedam *= 5;
612                                         basedam /= 3;
613                                 }
614                                 else if (have_flag(flgs, TR_VORPAL))
615                                 {
616                                         /* vorpal flag only */
617                                         basedam *= 11;
618                                         basedam /= 9;
619                                 }
620                                 damage += basedam;
621                                 damage *= caster_ptr->num_blow[i];
622                                 total_damage += damage / 200;
623                                 if (i) total_damage = total_damage * 7 / 10;
624                         }
625                         fire_beam(caster_ptr, GF_FORCE, dir, total_damage);
626                 }
627                 break;
628
629         case 22:
630                 if (name) return _("気迫の雄叫び", "War Cry");
631                 if (desc) return _("視界内の全モンスターに対して轟音の攻撃を行う。さらに、近くにいるモンスターを怒らせる。",
632                         "Damages all monsters in sight with sound. Aggravates nearby monsters.");
633
634                 if (cast)
635                 {
636                         msg_print(_("雄叫びをあげた!", "You roar!"));
637                         project_all_los(caster_ptr, GF_SOUND, randint1(plev * 3));
638                         aggravate_monsters(caster_ptr, 0);
639                 }
640                 break;
641
642         case 23:
643                 if (name) return _("無双三段", "Musou-Sandan");
644                 if (desc) return _("強力な3段攻撃を繰り出す。", "Attacks with three powerful strikes.");
645
646                 if (cast)
647                 {
648                         int i;
649
650                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
651                         if (dir == 5) return NULL;
652
653                         for (i = 0; i < 3; i++)
654                         {
655                                 POSITION y, x;
656                                 POSITION ny, nx;
657                                 MONSTER_IDX m_idx;
658                                 grid_type *g_ptr;
659                                 monster_type *m_ptr;
660
661                                 y = caster_ptr->y + ddy[dir];
662                                 x = caster_ptr->x + ddx[dir];
663                                 g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
664
665                                 if (g_ptr->m_idx)
666                                         py_attack(caster_ptr, y, x, HISSATSU_3DAN);
667                                 else
668                                 {
669                                         msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
670                                         return NULL;
671                                 }
672
673                                 if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_NO_MELEE)
674                                 {
675                                         return "";
676                                 }
677
678                                 /* Monster is dead? */
679                                 if (!g_ptr->m_idx) break;
680
681                                 ny = y + ddy[dir];
682                                 nx = x + ddx[dir];
683                                 m_idx = g_ptr->m_idx;
684                                 m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
685
686                                 /* Monster cannot move back? */
687                                 if (!monster_can_enter(caster_ptr, ny, nx, &r_info[m_ptr->r_idx], 0))
688                                 {
689                                         /* -more- */
690                                         if (i < 2) msg_print(NULL);
691                                         continue;
692                                 }
693
694                                 g_ptr->m_idx = 0;
695                                 caster_ptr->current_floor_ptr->grid_array[ny][nx].m_idx = m_idx;
696                                 m_ptr->fy = ny;
697                                 m_ptr->fx = nx;
698
699                                 update_monster(caster_ptr, m_idx, TRUE);
700
701                                 /* Redraw the old spot */
702                                 lite_spot(caster_ptr, y, x);
703
704                                 /* Redraw the new spot */
705                                 lite_spot(caster_ptr, ny, nx);
706
707                                 /* Player can move forward? */
708                                 if (player_can_enter(caster_ptr, g_ptr->feat, 0))
709                                 {
710                                         if (!move_player_effect(caster_ptr, y, x, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP)) break;
711                                 }
712                                 else
713                                 {
714                                         break;
715                                 }
716
717                                 /* -more- */
718                                 if (i < 2) msg_print(NULL);
719                         }
720                 }
721                 break;
722
723         case 24:
724                 if (name) return _("吸血鬼の牙", "Vampire's Fang");
725                 if (desc) return _("攻撃した相手の体力を吸いとり、自分の体力を回復させる。生命を持たないモンスターには通じない。",
726                         "Attacks with vampiric strikes which absorb HP from a monster and heal you. Has no effect on unliving monsters.");
727
728                 if (cast)
729                 {
730                         POSITION y, x;
731
732                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
733                         if (dir == 5) return NULL;
734
735                         y = caster_ptr->y + ddy[dir];
736                         x = caster_ptr->x + ddx[dir];
737
738                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
739                                 py_attack(caster_ptr, y, x, HISSATSU_DRAIN);
740                         else
741                         {
742                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
743                                 return NULL;
744                         }
745                 }
746                 break;
747
748         case 25:
749                 if (name) return _("幻惑", "Moon Dazzling");
750                 if (desc) return _("視界内の起きている全モンスターに朦朧、混乱、眠りを与えようとする。", "Attempts to stun, confuse and put to sleep all waking monsters.");
751
752                 if (cast)
753                 {
754                         msg_print(_("武器を不規則に揺らした...", "You irregularly wave your weapon..."));
755                         project_all_los(caster_ptr, GF_ENGETSU, plev * 4);
756                         project_all_los(caster_ptr, GF_ENGETSU, plev * 4);
757                         project_all_los(caster_ptr, GF_ENGETSU, plev * 4);
758                 }
759                 break;
760
761         case 26:
762                 if (name) return _("百人斬り", "Hundred Slaughter");
763                 if (desc) return _("連続して入身でモンスターを攻撃する。攻撃するたびにMPを消費。MPがなくなるか、モンスターを倒せなかったら百人斬りは終了する。",
764                         "Performs a series of rush attacks. The series continues as long as the attacked monster dies and you have sufficient SP.");
765
766                 if (cast)
767                 {
768                         const int mana_cost_per_monster = 8;
769                         bool is_new = TRUE;
770                         bool mdeath;
771
772                         do
773                         {
774                                 if (!rush_attack(caster_ptr, &mdeath)) break;
775                                 if (is_new)
776                                 {
777                                         /* Reserve needed mana point */
778                                         caster_ptr->csp -= technic_info[REALM_HISSATSU - MIN_TECHNIC][26].smana;
779                                         is_new = FALSE;
780                                 }
781                                 else
782                                         caster_ptr->csp -= mana_cost_per_monster;
783
784                                 if (!mdeath) break;
785                                 command_dir = 0;
786
787                                 caster_ptr->redraw |= PR_MANA;
788                                 handle_stuff(caster_ptr);
789                         } while (caster_ptr->csp > mana_cost_per_monster);
790
791                         if (is_new) return NULL;
792
793                         /* Restore reserved mana */
794                         caster_ptr->csp += technic_info[REALM_HISSATSU - MIN_TECHNIC][26].smana;
795                 }
796                 break;
797
798         case 27:
799                 if (name) return _("天翔龍閃", "Dragonic Flash");
800                 if (desc) return _("視界内の場所を指定して、その場所と自分の間にいる全モンスターを攻撃し、その場所に移動する。",
801                         "Runs toward given location while attacking all monsters on the path.");
802
803                 if (cast)
804                 {
805                         POSITION y, x;
806
807                         if (!tgt_pt(caster_ptr, &x, &y)) return NULL;
808
809                         if (!cave_player_teleportable_bold(caster_ptr, y, x, TELEPORT_SPONTANEOUS) ||
810                                 (distance(y, x, caster_ptr->y, caster_ptr->x) > MAX_SIGHT / 2) ||
811                                 !projectable(caster_ptr, caster_ptr->y, caster_ptr->x, y, x))
812                         {
813                                 msg_print(_("失敗!", "You cannot move to that place!"));
814                                 break;
815                         }
816                         if (caster_ptr->anti_tele)
817                         {
818                                 msg_print(_("不思議な力がテレポートを防いだ!", "A mysterious force prevents you from teleporting!"));
819                                 break;
820                         }
821                         project(caster_ptr, 0, 0, y, x, HISSATSU_ISSEN, GF_ATTACK, PROJECT_BEAM | PROJECT_KILL, -1);
822                         teleport_player_to(caster_ptr, y, x, TELEPORT_SPONTANEOUS);
823                 }
824                 break;
825
826         case 28:
827                 if (name) return _("二重の剣撃", "Twin Slash");
828                 if (desc) return _("1ターンで2度攻撃を行う。", "double attacks at a time.");
829
830                 if (cast)
831                 {
832                         POSITION x, y;
833
834                         if (!get_rep_dir(caster_ptr, &dir, FALSE)) return NULL;
835
836                         y = caster_ptr->y + ddy[dir];
837                         x = caster_ptr->x + ddx[dir];
838
839                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
840                         {
841                                 py_attack(caster_ptr, y, x, 0);
842                                 if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
843                                 {
844                                         handle_stuff(caster_ptr);
845                                         py_attack(caster_ptr, y, x, 0);
846                                 }
847                         }
848                         else
849                         {
850                                 msg_print(_("その方向にはモンスターはいません。", "You don't see any monster in this direction"));
851                                 return NULL;
852                         }
853                 }
854                 break;
855
856         case 29:
857                 if (name) return _("虎伏絶刀勢", "Kofuku-Zettousei");
858                 if (desc) return _("強力な攻撃を行い、近くの場所にも効果が及ぶ。", "Performs a powerful attack which even affects nearby monsters.");
859
860                 if (cast)
861                 {
862                         int total_damage = 0, basedam, i;
863                         POSITION y, x;
864                         BIT_FLAGS flgs[TR_FLAG_SIZE];
865                         object_type *o_ptr;
866
867                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
868                         if (dir == 5) return NULL;
869
870                         y = caster_ptr->y + ddy[dir];
871                         x = caster_ptr->x + ddx[dir];
872
873                         if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_NO_MELEE)
874                         {
875                                 msg_print(_("なぜか攻撃することができない。", "Something prevents you from attacking."));
876                                 return "";
877                         }
878                         msg_print(_("武器を大きく振り下ろした。", "You swing your weapon downward."));
879                         for (i = 0; i < 2; i++)
880                         {
881                                 int damage;
882                                 if (!has_melee_weapon(caster_ptr, INVEN_RARM + i)) break;
883                                 o_ptr = &caster_ptr->inventory_list[INVEN_RARM + i];
884                                 basedam = (o_ptr->dd * (o_ptr->ds + 1)) * 50;
885                                 damage = o_ptr->to_d * 100;
886                                 object_flags(o_ptr, flgs);
887                                 if ((o_ptr->name1 == ART_VORPAL_BLADE) || (o_ptr->name1 == ART_CHAINSWORD))
888                                 {
889                                         /* vorpal blade */
890                                         basedam *= 5;
891                                         basedam /= 3;
892                                 }
893                                 else if (have_flag(flgs, TR_VORPAL))
894                                 {
895                                         /* vorpal flag only */
896                                         basedam *= 11;
897                                         basedam /= 9;
898                                 }
899                                 damage += basedam;
900                                 damage += caster_ptr->to_d[i] * 100;
901                                 damage *= caster_ptr->num_blow[i];
902                                 total_damage += (damage / 100);
903                         }
904                         project(caster_ptr, 0, (cave_have_flag_bold(caster_ptr->current_floor_ptr, y, x, FF_PROJECT) ? 5 : 0), y, x, total_damage * 3 / 2, GF_METEOR, PROJECT_KILL | PROJECT_JUMP | PROJECT_ITEM, -1);
905                 }
906                 break;
907
908         case 30:
909                 if (name) return _("慶雲鬼忍剣", "Keiun-Kininken");
910                 if (desc) return _("自分もダメージをくらうが、相手に非常に大きなダメージを与える。アンデッドには特に効果がある。",
911                         "Attacks a monster with extremely powerful damage, but you also take some damage. Hurts an undead monster greatly.");
912
913                 if (cast)
914                 {
915                         POSITION y, x;
916
917                         if (!get_direction(caster_ptr, &dir, FALSE, FALSE)) return NULL;
918                         if (dir == 5) return NULL;
919
920                         y = caster_ptr->y + ddy[dir];
921                         x = caster_ptr->x + ddx[dir];
922
923                         if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx)
924                                 py_attack(caster_ptr, y, x, HISSATSU_UNDEAD);
925                         else
926                         {
927                                 msg_print(_("その方向にはモンスターはいません。", "There is no monster."));
928                                 return NULL;
929                         }
930                         take_hit(caster_ptr, DAMAGE_NOESCAPE, 100 + randint1(100), _("慶雲鬼忍剣を使った衝撃", "exhaustion on using Keiun-Kininken"), -1);
931                 }
932                 break;
933
934         case 31:
935                 if (name) return _("切腹", "Harakiri");
936                 if (desc) return _("「武士道とは、死ぬことと見つけたり。」", "'Bushido, the way of warriors, is found in death'");
937
938                 if (cast)
939                 {
940                         int i;
941                         if (!get_check(_("本当に自殺しますか?", "Do you really want to commit suicide? "))) return NULL;
942                         /* Special Verification for suicide */
943                         prt(_("確認のため '@' を押して下さい。", "Please verify SUICIDE by typing the '@' sign: "), 0, 0);
944
945                         flush();
946                         i = inkey();
947                         prt("", 0, 0);
948                         if (i != '@') return NULL;
949                         if (current_world_ptr->total_winner)
950                         {
951                                 take_hit(caster_ptr, DAMAGE_FORCE, 9999, "Seppuku", -1);
952                                 current_world_ptr->total_winner = TRUE;
953                         }
954                         else
955                         {
956                                 msg_print(_("武士道とは、死ぬことと見つけたり。", "The meaning of bushido is found in death."));
957                                 take_hit(caster_ptr, DAMAGE_FORCE, 9999, "Seppuku", -1);
958                         }
959                 }
960                 break;
961         }
962
963         return "";
964 }