OSDN Git Service

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