OSDN Git Service

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