OSDN Git Service

[Refactor] #40014 Separated monster-describer.c/h from monster2.c/h
[hengband/hengband.git] / src / spell / process-effect.c
1 #include "spell/process-effect.h"
2 #include "core/stuff-handler.h"
3 #include "effect/effect-characteristics.h"
4 #include "effect/effect-feature.h"
5 #include "effect/effect-item.h"
6 #include "effect/effect-monster.h"
7 #include "effect/effect-player.h"
8 #include "effect/spells-effect-util.h"
9 #include "floor/floor.h"
10 #include "main/sound-definitions-table.h"
11 #include "monster-race/race-flags2.h"
12 #include "monster-race/race-indice-types.h"
13 #include "monster/monster-describer.h"
14 #include "monster/monster-description-types.h"
15 #include "monster/monster-info.h"
16 #include "pet/pet-fall-off.h"
17 #include "spell/spells-type.h"
18 #include "spell/range-calc.h"
19 #include "term/gameterm.h"
20 #include "view/display-main-window.h" // 暫定、後で消すかも.
21
22 /*!
23  * @brief 配置した鏡リストの次を取得する /
24  * Get another mirror. for SEEKER
25  * @param next_y 次の鏡のy座標を返す参照ポインタ
26  * @param next_x 次の鏡のx座標を返す参照ポインタ
27  * @param cury 現在の鏡のy座標
28  * @param curx 現在の鏡のx座標
29  */
30 static void next_mirror(player_type *creature_ptr, POSITION *next_y, POSITION *next_x, POSITION cury, POSITION curx)
31 {
32     POSITION mirror_x[10], mirror_y[10]; /* 鏡はもっと少ない */
33     int mirror_num = 0; /* 鏡の数 */
34     for (POSITION x = 0; x < creature_ptr->current_floor_ptr->width; x++) {
35         for (POSITION y = 0; y < creature_ptr->current_floor_ptr->height; y++) {
36             if (is_mirror_grid(&creature_ptr->current_floor_ptr->grid_array[y][x])) {
37                 mirror_y[mirror_num] = y;
38                 mirror_x[mirror_num] = x;
39                 mirror_num++;
40             }
41         }
42     }
43
44     if (mirror_num) {
45         int num = randint0(mirror_num);
46         *next_y = mirror_y[num];
47         *next_x = mirror_x[num];
48         return;
49     }
50
51     *next_y = cury + randint0(5) - 2;
52     *next_x = curx + randint0(5) - 2;
53 }
54
55 /*!
56  * todo 似たような処理が山ほど並んでいる、何とかならないものか
57  * todo 引数にそのまま再代入していてカオスすぎる。直すのは簡単ではない
58  * @brief 汎用的なビーム/ボルト/ボール系処理のルーチン Generic
59  * "beam"/"bolt"/"ball" projection routine.
60  * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source"
61  * monster (zero for "player")
62  * @param rad 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion
63  * (0 = beam/bolt, 1 to 9 = ball)
64  * @param y 目標Y座標 / Target y location (or location to travel "towards")
65  * @param x 目標X座標 / Target x location (or location to travel "towards")
66  * @param dam 基本威力 / Base damage roll to apply to affected monsters (or
67  * player)
68  * @param typ 効果属性 / Type of damage to apply to monsters (and objects)
69  * @param flag 効果フラグ / Extra bit flags (see PROJECT_xxxx)
70  * @param monspell 効果元のモンスター魔法ID
71  * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the
72  * projection were observed, else FALSE
73  */
74 bool project(player_type *caster_ptr, MONSTER_IDX who, POSITION rad, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ, BIT_FLAGS flag, int monspell)
75 {
76     int dist;
77     POSITION y1, x1;
78     POSITION y2, x2;
79
80     /* For reflecting monsters */
81     POSITION y_saver;
82     POSITION x_saver;
83     int msec = delay_factor * delay_factor * delay_factor;
84     bool notice = FALSE;
85     bool visual = FALSE;
86     bool drawn = FALSE;
87     bool breath = FALSE;
88     bool blind = caster_ptr->blind != 0;
89     bool old_hide = FALSE;
90     int path_n = 0;
91     u16b path_g[512];
92     int grids = 0;
93     POSITION gx[1024];
94     POSITION gy[1024];
95     POSITION gm[32];
96     POSITION gm_rad = rad;
97     bool jump = FALSE;
98     GAME_TEXT who_name[MAX_NLEN];
99     bool see_s_msg = TRUE;
100     who_name[0] = '\0';
101     rakubadam_p = 0;
102     rakubadam_m = 0;
103     monster_target_y = caster_ptr->y;
104     monster_target_x = caster_ptr->x;
105
106     if (flag & (PROJECT_JUMP)) {
107         x1 = x;
108         y1 = y;
109         flag &= ~(PROJECT_JUMP);
110         jump = TRUE;
111     } else if (who <= 0) {
112         x1 = caster_ptr->x;
113         y1 = caster_ptr->y;
114     } else if (who > 0) {
115         x1 = caster_ptr->current_floor_ptr->m_list[who].fx;
116         y1 = caster_ptr->current_floor_ptr->m_list[who].fy;
117         monster_desc(caster_ptr, who_name, &caster_ptr->current_floor_ptr->m_list[who], MD_WRONGDOER_NAME);
118     } else {
119         x1 = x;
120         y1 = y;
121     }
122
123     y_saver = y1;
124     x_saver = x1;
125     y2 = y;
126     x2 = x;
127
128     if (flag & (PROJECT_THRU)) {
129         if ((x1 == x2) && (y1 == y2)) {
130             flag &= ~(PROJECT_THRU);
131         }
132     }
133
134     if (rad < 0) {
135         rad = 0 - rad;
136         breath = TRUE;
137         if (flag & PROJECT_HIDE)
138             old_hide = TRUE;
139         flag |= PROJECT_HIDE;
140     }
141
142     for (dist = 0; dist < 32; dist++)
143         gm[dist] = 0;
144
145     y = y1;
146     x = x1;
147     dist = 0;
148     if (flag & (PROJECT_BEAM)) {
149         gy[grids] = y;
150         gx[grids] = x;
151         grids++;
152     }
153
154     switch (typ) {
155     case GF_LITE:
156     case GF_LITE_WEAK:
157         if (breath || (flag & PROJECT_BEAM))
158             flag |= (PROJECT_LOS);
159         break;
160     case GF_DISINTEGRATE:
161         flag |= (PROJECT_GRID);
162         if (breath || (flag & PROJECT_BEAM))
163             flag |= (PROJECT_DISI);
164         break;
165     }
166
167     /* Calculate the projection path */
168     path_n = project_path(caster_ptr, path_g, (project_length ? project_length : MAX_RANGE), y1, x1, y2, x2, flag);
169     handle_stuff(caster_ptr);
170
171     if (typ == GF_SEEKER) {
172         int j;
173         int last_i = 0;
174         project_m_n = 0;
175         project_m_x = 0;
176         project_m_y = 0;
177         for (int i = 0; i < path_n; ++i) {
178             POSITION oy = y;
179             POSITION ox = x;
180             POSITION ny = GRID_Y(path_g[i]);
181             POSITION nx = GRID_X(path_g[i]);
182             y = ny;
183             x = nx;
184             gy[grids] = y;
185             gx[grids] = x;
186             grids++;
187
188             if (!blind && !(flag & (PROJECT_HIDE))) {
189                 if (panel_contains(y, x) && player_has_los_bold(caster_ptr, y, x)) {
190                     u16b p = bolt_pict(oy, ox, y, x, typ);
191                     TERM_COLOR a = PICT_A(p);
192                     SYMBOL_CODE c = PICT_C(p);
193                     print_rel(caster_ptr, c, a, y, x);
194                     move_cursor_relative(y, x);
195                     Term_fresh();
196                     Term_xtra(TERM_XTRA_DELAY, msec);
197                     lite_spot(caster_ptr, y, x);
198                     Term_fresh();
199                     if (flag & (PROJECT_BEAM)) {
200                         p = bolt_pict(y, x, y, x, typ);
201                         a = PICT_A(p);
202                         c = PICT_C(p);
203                         print_rel(caster_ptr, c, a, y, x);
204                     }
205
206                     visual = TRUE;
207                 } else if (visual) {
208                     Term_xtra(TERM_XTRA_DELAY, msec);
209                 }
210             }
211
212             if (affect_item(caster_ptr, 0, 0, y, x, dam, GF_SEEKER))
213                 notice = TRUE;
214             if (!is_mirror_grid(&caster_ptr->current_floor_ptr->grid_array[y][x]))
215                 continue;
216
217             monster_target_y = y;
218             monster_target_x = x;
219             remove_mirror(caster_ptr, y, x);
220             next_mirror(caster_ptr, &oy, &ox, y, x);
221             path_n = i + project_path(caster_ptr, &(path_g[i + 1]), (project_length ? project_length : MAX_RANGE), y, x, oy, ox, flag);
222             for (j = last_i; j <= i; j++) {
223                 y = GRID_Y(path_g[j]);
224                 x = GRID_X(path_g[j]);
225                 if (affect_monster(caster_ptr, 0, 0, y, x, dam, GF_SEEKER, flag, TRUE))
226                     notice = TRUE;
227                 if (!who && (project_m_n == 1) && !jump && (caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx > 0)) {
228                     monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx];
229                     if (m_ptr->ml) {
230                         if (!caster_ptr->image)
231                             monster_race_track(caster_ptr, m_ptr->ap_r_idx);
232                         health_track(caster_ptr, caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx);
233                     }
234                 }
235
236                 (void)affect_feature(caster_ptr, 0, 0, y, x, dam, GF_SEEKER);
237             }
238
239             last_i = i;
240         }
241
242         for (int i = last_i; i < path_n; i++) {
243             POSITION py, px;
244             py = GRID_Y(path_g[i]);
245             px = GRID_X(path_g[i]);
246             if (affect_monster(caster_ptr, 0, 0, py, px, dam, GF_SEEKER, flag, TRUE))
247                 notice = TRUE;
248             if (!who && (project_m_n == 1) && !jump) {
249                 if (caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx > 0) {
250                     monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx];
251
252                     if (m_ptr->ml) {
253                         if (!caster_ptr->image)
254                             monster_race_track(caster_ptr, m_ptr->ap_r_idx);
255                         health_track(caster_ptr, caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx);
256                     }
257                 }
258             }
259
260             (void)affect_feature(caster_ptr, 0, 0, py, px, dam, GF_SEEKER);
261         }
262
263         return notice;
264     } else if (typ == GF_SUPER_RAY) {
265         int j;
266         int second_step = 0;
267         project_m_n = 0;
268         project_m_x = 0;
269         project_m_y = 0;
270         for (int i = 0; i < path_n; ++i) {
271             POSITION oy = y;
272             POSITION ox = x;
273             POSITION ny = GRID_Y(path_g[i]);
274             POSITION nx = GRID_X(path_g[i]);
275             y = ny;
276             x = nx;
277             gy[grids] = y;
278             gx[grids] = x;
279             grids++;
280             {
281                 if (panel_contains(y, x) && player_has_los_bold(caster_ptr, y, x)) {
282                     u16b p;
283                     TERM_COLOR a;
284                     SYMBOL_CODE c;
285                     p = bolt_pict(oy, ox, y, x, typ);
286                     a = PICT_A(p);
287                     c = PICT_C(p);
288                     print_rel(caster_ptr, c, a, y, x);
289                     move_cursor_relative(y, x);
290                     Term_fresh();
291                     Term_xtra(TERM_XTRA_DELAY, msec);
292                     lite_spot(caster_ptr, y, x);
293                     Term_fresh();
294                     if (flag & (PROJECT_BEAM)) {
295                         p = bolt_pict(y, x, y, x, typ);
296                         a = PICT_A(p);
297                         c = PICT_C(p);
298                         print_rel(caster_ptr, c, a, y, x);
299                     }
300
301                     visual = TRUE;
302                 } else if (visual) {
303                     Term_xtra(TERM_XTRA_DELAY, msec);
304                 }
305             }
306
307             if (affect_item(caster_ptr, 0, 0, y, x, dam, GF_SUPER_RAY))
308                 notice = TRUE;
309             if (!cave_have_flag_bold(caster_ptr->current_floor_ptr, y, x, FF_PROJECT)) {
310                 if (second_step)
311                     continue;
312                 break;
313             }
314
315             if (is_mirror_grid(&caster_ptr->current_floor_ptr->grid_array[y][x]) && !second_step) {
316                 monster_target_y = y;
317                 monster_target_x = x;
318                 remove_mirror(caster_ptr, y, x);
319                 for (j = 0; j <= i; j++) {
320                     y = GRID_Y(path_g[j]);
321                     x = GRID_X(path_g[j]);
322                     (void)affect_feature(caster_ptr, 0, 0, y, x, dam, GF_SUPER_RAY);
323                 }
324
325                 path_n = i;
326                 second_step = i + 1;
327                 path_n += project_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : MAX_RANGE), y, x, y - 1, x - 1, flag);
328                 path_n += project_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : MAX_RANGE), y, x, y - 1, x, flag);
329                 path_n += project_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : MAX_RANGE), y, x, y - 1, x + 1, flag);
330                 path_n += project_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : MAX_RANGE), y, x, y, x - 1, flag);
331                 path_n += project_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : MAX_RANGE), y, x, y, x + 1, flag);
332                 path_n += project_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : MAX_RANGE), y, x, y + 1, x - 1, flag);
333                 path_n += project_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : MAX_RANGE), y, x, y + 1, x, flag);
334                 path_n += project_path(caster_ptr, &(path_g[path_n + 1]), (project_length ? project_length : MAX_RANGE), y, x, y + 1, x + 1, flag);
335             }
336         }
337
338         for (int i = 0; i < path_n; i++) {
339             POSITION py = GRID_Y(path_g[i]);
340             POSITION px = GRID_X(path_g[i]);
341             (void)affect_monster(caster_ptr, 0, 0, py, px, dam, GF_SUPER_RAY, flag, TRUE);
342             if (!who && (project_m_n == 1) && !jump) {
343                 if (caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx > 0) {
344                     monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx];
345
346                     if (m_ptr->ml) {
347                         if (!caster_ptr->image)
348                             monster_race_track(caster_ptr, m_ptr->ap_r_idx);
349                         health_track(caster_ptr, caster_ptr->current_floor_ptr->grid_array[project_m_y][project_m_x].m_idx);
350                     }
351                 }
352             }
353
354             (void)affect_feature(caster_ptr, 0, 0, py, px, dam, GF_SUPER_RAY);
355         }
356
357         return notice;
358     }
359
360     int k;
361     for (k = 0; k < path_n; ++k) {
362         POSITION oy = y;
363         POSITION ox = x;
364         POSITION ny = GRID_Y(path_g[k]);
365         POSITION nx = GRID_X(path_g[k]);
366         if (flag & PROJECT_DISI) {
367             if (cave_stop_disintegration(caster_ptr->current_floor_ptr, ny, nx) && (rad > 0))
368                 break;
369         } else if (flag & PROJECT_LOS) {
370             if (!cave_los_bold(caster_ptr->current_floor_ptr, ny, nx) && (rad > 0))
371                 break;
372         } else {
373             if (!cave_have_flag_bold(caster_ptr->current_floor_ptr, ny, nx, FF_PROJECT) && (rad > 0))
374                 break;
375         }
376
377         y = ny;
378         x = nx;
379         if (flag & (PROJECT_BEAM)) {
380             gy[grids] = y;
381             gx[grids] = x;
382             grids++;
383         }
384
385         if (!blind && !(flag & (PROJECT_HIDE | PROJECT_FAST))) {
386             if (panel_contains(y, x) && player_has_los_bold(caster_ptr, y, x)) {
387                 u16b p;
388                 TERM_COLOR a;
389                 SYMBOL_CODE c;
390                 p = bolt_pict(oy, ox, y, x, typ);
391                 a = PICT_A(p);
392                 c = PICT_C(p);
393                 print_rel(caster_ptr, c, a, y, x);
394                 move_cursor_relative(y, x);
395                 Term_fresh();
396                 Term_xtra(TERM_XTRA_DELAY, msec);
397                 lite_spot(caster_ptr, y, x);
398                 Term_fresh();
399                 if (flag & (PROJECT_BEAM)) {
400                     p = bolt_pict(y, x, y, x, typ);
401                     a = PICT_A(p);
402                     c = PICT_C(p);
403                     print_rel(caster_ptr, c, a, y, x);
404                 }
405
406                 visual = TRUE;
407             } else if (visual) {
408                 Term_xtra(TERM_XTRA_DELAY, msec);
409             }
410         }
411     }
412
413     path_n = k;
414     POSITION by = y;
415     POSITION bx = x;
416     if (breath && !path_n) {
417         breath = FALSE;
418         gm_rad = rad;
419         if (!old_hide) {
420             flag &= ~(PROJECT_HIDE);
421         }
422     }
423
424     gm[0] = 0;
425     gm[1] = grids;
426     dist = path_n;
427     int dist_hack = dist;
428     project_length = 0;
429
430     /* If we found a "target", explode there */
431     if (dist <= MAX_RANGE) {
432         if ((flag & (PROJECT_BEAM)) && (grids > 0))
433             grids--;
434
435         /*
436          * Create a conical breath attack
437          *
438          *       ***
439          *   ********
440          * D********@**
441          *   ********
442          *       ***
443          */
444         if (breath) {
445             flag &= ~(PROJECT_HIDE);
446             breath_shape(caster_ptr, path_g, dist, &grids, gx, gy, gm, &gm_rad, rad, y1, x1, by, bx, typ);
447         } else {
448             for (dist = 0; dist <= rad; dist++) {
449                 for (y = by - dist; y <= by + dist; y++) {
450                     for (x = bx - dist; x <= bx + dist; x++) {
451                         if (!in_bounds2(caster_ptr->current_floor_ptr, y, x))
452                             continue;
453                         if (distance(by, bx, y, x) != dist)
454                             continue;
455
456                         switch (typ) {
457                         case GF_LITE:
458                         case GF_LITE_WEAK:
459                             if (!los(caster_ptr, by, bx, y, x))
460                                 continue;
461                             break;
462                         case GF_DISINTEGRATE:
463                             if (!in_disintegration_range(caster_ptr->current_floor_ptr, by, bx, y, x))
464                                 continue;
465                             break;
466                         default:
467                             if (!projectable(caster_ptr, by, bx, y, x))
468                                 continue;
469                             break;
470                         }
471
472                         gy[grids] = y;
473                         gx[grids] = x;
474                         grids++;
475                     }
476                 }
477
478                 gm[dist + 1] = grids;
479             }
480         }
481     }
482
483     if (!grids)
484         return FALSE;
485
486     if (!blind && !(flag & (PROJECT_HIDE))) {
487         for (int t = 0; t <= gm_rad; t++) {
488             for (int i = gm[t]; i < gm[t + 1]; i++) {
489                 y = gy[i];
490                 x = gx[i];
491                 if (panel_contains(y, x) && player_has_los_bold(caster_ptr, y, x)) {
492                     u16b p;
493                     TERM_COLOR a;
494                     SYMBOL_CODE c;
495                     drawn = TRUE;
496                     p = bolt_pict(y, x, y, x, typ);
497                     a = PICT_A(p);
498                     c = PICT_C(p);
499                     print_rel(caster_ptr, c, a, y, x);
500                 }
501             }
502
503             move_cursor_relative(by, bx);
504             Term_fresh();
505             if (visual || drawn) {
506                 Term_xtra(TERM_XTRA_DELAY, msec);
507             }
508         }
509
510         if (drawn) {
511             for (int i = 0; i < grids; i++) {
512                 y = gy[i];
513                 x = gx[i];
514                 if (panel_contains(y, x) && player_has_los_bold(caster_ptr, y, x)) {
515                     lite_spot(caster_ptr, y, x);
516                 }
517             }
518
519             move_cursor_relative(by, bx);
520             Term_fresh();
521         }
522     }
523
524     update_creature(caster_ptr);
525
526     if (flag & PROJECT_KILL) {
527         see_s_msg = (who > 0) ? is_seen(&caster_ptr->current_floor_ptr->m_list[who])
528                               : (!who ? TRUE : (player_can_see_bold(caster_ptr, y1, x1) && projectable(caster_ptr, caster_ptr->y, caster_ptr->x, y1, x1)));
529     }
530
531     if (flag & (PROJECT_GRID)) {
532         dist = 0;
533         for (int i = 0; i < grids; i++) {
534             if (gm[dist + 1] == i)
535                 dist++;
536             y = gy[i];
537             x = gx[i];
538             if (breath) {
539                 int d = dist_to_line(y, x, y1, x1, by, bx);
540                 if (affect_feature(caster_ptr, who, d, y, x, dam, typ))
541                     notice = TRUE;
542             } else {
543                 if (affect_feature(caster_ptr, who, dist, y, x, dam, typ))
544                     notice = TRUE;
545             }
546         }
547     }
548
549     update_creature(caster_ptr);
550     if (flag & (PROJECT_ITEM)) {
551         dist = 0;
552         for (int i = 0; i < grids; i++) {
553             if (gm[dist + 1] == i)
554                 dist++;
555
556             y = gy[i];
557             x = gx[i];
558             if (breath) {
559                 int d = dist_to_line(y, x, y1, x1, by, bx);
560                 if (affect_item(caster_ptr, who, d, y, x, dam, typ))
561                     notice = TRUE;
562             } else {
563                 if (affect_item(caster_ptr, who, dist, y, x, dam, typ))
564                     notice = TRUE;
565             }
566         }
567     }
568
569     if (flag & (PROJECT_KILL)) {
570         project_m_n = 0;
571         project_m_x = 0;
572         project_m_y = 0;
573         dist = 0;
574         for (int i = 0; i < grids; i++) {
575             int effective_dist;
576             if (gm[dist + 1] == i)
577                 dist++;
578
579             y = gy[i];
580             x = gx[i];
581             if (grids <= 1) {
582                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[caster_ptr->current_floor_ptr->grid_array[y][x].m_idx];
583                 monster_race *ref_ptr = &r_info[m_ptr->r_idx];
584                 if ((flag & PROJECT_REFLECTABLE) && caster_ptr->current_floor_ptr->grid_array[y][x].m_idx && (ref_ptr->flags2 & RF2_REFLECTING)
585                     && ((caster_ptr->current_floor_ptr->grid_array[y][x].m_idx != caster_ptr->riding) || !(flag & PROJECT_PLAYER)) && (!who || dist_hack > 1)
586                     && !one_in_(10)) {
587                     POSITION t_y, t_x;
588                     int max_attempts = 10;
589                     do {
590                         t_y = y_saver - 1 + randint1(3);
591                         t_x = x_saver - 1 + randint1(3);
592                         max_attempts--;
593                     } while (max_attempts && in_bounds2u(caster_ptr->current_floor_ptr, t_y, t_x) && !projectable(caster_ptr, y, x, t_y, t_x));
594
595                     if (max_attempts < 1) {
596                         t_y = y_saver;
597                         t_x = x_saver;
598                     }
599
600                     sound(SOUND_REFLECT);
601                     if (is_seen(m_ptr)) {
602                         if ((m_ptr->r_idx == MON_KENSHIROU) || (m_ptr->r_idx == MON_RAOU))
603                             msg_print(_("「北斗神拳奥義・二指真空把!」", "The attack bounces!"));
604                         else if (m_ptr->r_idx == MON_DIO)
605                             msg_print(_("ディオ・ブランドーは指一本で攻撃を弾き返した!", "The attack bounces!"));
606                         else
607                             msg_print(_("攻撃は跳ね返った!", "The attack bounces!"));
608                     }
609
610                     if (is_original_ap_and_seen(caster_ptr, m_ptr))
611                         ref_ptr->r_flags2 |= RF2_REFLECTING;
612
613                     if (player_bold(caster_ptr, y, x) || one_in_(2))
614                         flag &= ~(PROJECT_PLAYER);
615                     else
616                         flag |= PROJECT_PLAYER;
617
618                     project(caster_ptr, caster_ptr->current_floor_ptr->grid_array[y][x].m_idx, 0, t_y, t_x, dam, typ, flag, monspell);
619                     continue;
620                 }
621             }
622
623             /* Find the closest point in the blast */
624             if (breath) {
625                 effective_dist = dist_to_line(y, x, y1, x1, by, bx);
626             } else {
627                 effective_dist = dist;
628             }
629
630             if (caster_ptr->riding && player_bold(caster_ptr, y, x)) {
631                 if (flag & PROJECT_PLAYER) {
632                     if (flag & (PROJECT_BEAM | PROJECT_REFLECTABLE | PROJECT_AIMED)) {
633                         /*
634                          * A beam or bolt is well aimed
635                          * at the PLAYER!
636                          * So don't affects the mount.
637                          */
638                         continue;
639                     } else {
640                         /*
641                          * The spell is not well aimed,
642                          * So partly affect the mount too.
643                          */
644                         effective_dist++;
645                     }
646                 }
647
648                 /*
649                  * This grid is the original target.
650                  * Or aimed on your horse.
651                  */
652                 else if (((y == y2) && (x == x2)) || (flag & PROJECT_AIMED)) {
653                     /* Hit the mount with full damage */
654                 }
655
656                 /*
657                  * Otherwise this grid is not the
658                  * original target, it means that line
659                  * of fire is obstructed by this
660                  * monster.
661                  */
662                 /*
663                  * A beam or bolt will hit either
664                  * player or mount.  Choose randomly.
665                  */
666                 else if (flag & (PROJECT_BEAM | PROJECT_REFLECTABLE)) {
667                     if (one_in_(2)) {
668                         /* Hit the mount with full damage */
669                     } else {
670                         flag |= PROJECT_PLAYER;
671                         continue;
672                     }
673                 }
674
675                 /*
676                  * The spell is not well aimed, so
677                  * partly affect both player and
678                  * mount.
679                  */
680                 else {
681                     effective_dist++;
682                 }
683             }
684
685             if (affect_monster(caster_ptr, who, effective_dist, y, x, dam, typ, flag, see_s_msg))
686                 notice = TRUE;
687         }
688
689         /* Player affected one monster (without "jumping") */
690         if (!who && (project_m_n == 1) && !jump) {
691             x = project_m_x;
692             y = project_m_y;
693             if (caster_ptr->current_floor_ptr->grid_array[y][x].m_idx > 0) {
694                 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[caster_ptr->current_floor_ptr->grid_array[y][x].m_idx];
695
696                 if (m_ptr->ml) {
697                     if (!caster_ptr->image)
698                         monster_race_track(caster_ptr, m_ptr->ap_r_idx);
699                     health_track(caster_ptr, caster_ptr->current_floor_ptr->grid_array[y][x].m_idx);
700                 }
701             }
702         }
703     }
704
705     if (flag & (PROJECT_KILL)) {
706         dist = 0;
707         for (int i = 0; i < grids; i++) {
708             int effective_dist;
709             if (gm[dist + 1] == i)
710                 dist++;
711
712             y = gy[i];
713             x = gx[i];
714             if (!player_bold(caster_ptr, y, x))
715                 continue;
716
717             /* Find the closest point in the blast */
718             if (breath) {
719                 effective_dist = dist_to_line(y, x, y1, x1, by, bx);
720             } else {
721                 effective_dist = dist;
722             }
723
724             if (caster_ptr->riding) {
725                 if (flag & PROJECT_PLAYER) {
726                     /* Hit the player with full damage */
727                 }
728
729                 /*
730                  * Hack -- When this grid was not the
731                  * original target, a beam or bolt
732                  * would hit either player or mount,
733                  * and should be choosen randomly.
734                  *
735                  * But already choosen to hit the
736                  * mount at this point.
737                  *
738                  * Or aimed on your horse.
739                  */
740                 else if (flag & (PROJECT_BEAM | PROJECT_REFLECTABLE | PROJECT_AIMED)) {
741                     /*
742                      * A beam or bolt is well aimed
743                      * at the mount!
744                      * So don't affects the player.
745                      */
746                     continue;
747                 } else {
748                     /*
749                      * The spell is not well aimed,
750                      * So partly affect the player too.
751                      */
752                     effective_dist++;
753                 }
754             }
755
756             if (affect_player(who, caster_ptr, who_name, effective_dist, y, x, dam, typ, flag, monspell, project))
757                 notice = TRUE;
758         }
759     }
760
761     if (caster_ptr->riding) {
762         GAME_TEXT m_name[MAX_NLEN];
763         monster_desc(caster_ptr, m_name, &caster_ptr->current_floor_ptr->m_list[caster_ptr->riding], 0);
764         if (rakubadam_m > 0) {
765             if (process_fall_off_horse(caster_ptr, rakubadam_m, FALSE)) {
766                 msg_format(_("%^sに振り落とされた!", "%^s has thrown you off!"), m_name);
767             }
768         }
769
770         if (caster_ptr->riding && rakubadam_p > 0) {
771             if (process_fall_off_horse(caster_ptr, rakubadam_p, FALSE)) {
772                 msg_format(_("%^sから落ちてしまった!", "You have fallen from %s."), m_name);
773             }
774         }
775     }
776
777     return (notice);
778 }