OSDN Git Service

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