OSDN Git Service

[Refactor] #40534 Separated flavor-describer.c/h from object-flavor.c/h
[hengband/hengband.git] / src / combat / shoot.c
1 #include "combat/shoot.h"
2 #include "art-definition/art-bow-types.h"
3 #include "core/player-redraw-types.h"
4 #include "core/player-update-types.h"
5 #include "core/stuff-handler.h"
6 #include "effect/effect-characteristics.h"
7 #include "effect/spells-effect-util.h"
8 #include "flavor/flavor-describer.h"
9 #include "flavor/object-flavor-types.h"
10 #include "floor/floor-object.h"
11 #include "game-option/cheat-types.h"
12 #include "game-option/special-options.h"
13 #include "grid/feature.h"
14 #include "grid/grid.h"
15 #include "inventory/inventory-object.h"
16 #include "inventory/inventory-slot-types.h"
17 #include "io/cursor.h"
18 #include "io/screen-util.h"
19 #include "io/targeting.h"
20 #include "main/sound-definitions-table.h"
21 #include "main/sound-of-music.h"
22 #include "mind/mind-sniper.h"
23 #include "mind/snipe-types.h"
24 #include "monster-floor/monster-death.h"
25 #include "monster-floor/monster-move.h"
26 #include "monster-race/monster-race.h"
27 #include "monster-race/race-flags-resistance.h"
28 #include "monster-race/race-flags1.h"
29 #include "monster-race/race-flags2.h"
30 #include "monster-race/race-flags3.h"
31 #include "monster-race/race-flags7.h"
32 #include "monster-race/race-indice-types.h"
33 #include "monster/monster-describer.h"
34 #include "monster/monster-info.h"
35 #include "monster/monster-status.h"
36 #include "monster/monster-update.h"
37 #include "object-enchant/artifact.h"
38 #include "object-enchant/tr-types.h"
39 #include "object-hook/hook-enchant.h"
40 #include "object/object-broken.h"
41 #include "object/object-flags.h"
42 #include "object/object-generator.h"
43 #include "object/object-info.h"
44 #include "object/object-kind.h"
45 #include "object/object-mark-types.h"
46 #include "player/avatar.h"
47 #include "player/player-class.h"
48 #include "player/player-personalities-types.h"
49 #include "player/player-skill.h"
50 #include "player/player-status.h"
51 #include "spell/process-effect.h"
52 #include "spell/spell-types.h"
53 #include "sv-definition/sv-bow-types.h"
54 #include "util/bit-flags-calculator.h"
55 #include "view/display-messages.h"
56 #include "wizard/wizard-messages.h"
57 #include "world/world-object.h"
58
59 /*!
60  * @brief 矢弾を射撃した際のスレイ倍率をかけた結果を返す /
61  * Determines the odds of an object breaking when thrown at a monster
62  * @param o_ptr 矢弾のオブジェクト構造体参照ポインタ
63  * @param tdam 計算途中のダメージ量
64  * @param m_ptr 目標モンスターの構造体参照ポインタ
65  * @return スレイ倍率をかけたダメージ量
66  */
67 static MULTIPLY calc_shot_damage_with_slay(player_type *sniper_ptr, object_type *o_ptr, HIT_POINT tdam, monster_type *m_ptr, SPELL_IDX snipe_type)
68 {
69     MULTIPLY mult = 10;
70
71     monster_race *r_ptr = &r_info[m_ptr->r_idx];
72
73     BIT_FLAGS flgs[TR_FLAG_SIZE];
74     object_flags(sniper_ptr, o_ptr, flgs);
75
76     /* Some "weapons" and "ammo" do extra damage */
77     switch (o_ptr->tval) {
78     case TV_SHOT:
79     case TV_ARROW:
80     case TV_BOLT: {
81         if ((have_flag(flgs, TR_SLAY_ANIMAL)) && (r_ptr->flags3 & RF3_ANIMAL)) {
82             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
83                 r_ptr->r_flags3 |= RF3_ANIMAL;
84             }
85             if (mult < 17)
86                 mult = 17;
87         }
88
89         if ((have_flag(flgs, TR_KILL_ANIMAL)) && (r_ptr->flags3 & RF3_ANIMAL)) {
90             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
91                 r_ptr->r_flags3 |= RF3_ANIMAL;
92             }
93             if (mult < 27)
94                 mult = 27;
95         }
96
97         if ((have_flag(flgs, TR_SLAY_EVIL)) && (r_ptr->flags3 & RF3_EVIL)) {
98             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
99                 r_ptr->r_flags3 |= RF3_EVIL;
100             }
101             if (mult < 15)
102                 mult = 15;
103         }
104
105         if ((have_flag(flgs, TR_KILL_EVIL)) && (r_ptr->flags3 & RF3_EVIL)) {
106             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
107                 r_ptr->r_flags3 |= RF3_EVIL;
108             }
109             if (mult < 25)
110                 mult = 25;
111         }
112
113         if ((have_flag(flgs, TR_SLAY_HUMAN)) && (r_ptr->flags2 & RF2_HUMAN)) {
114             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
115                 r_ptr->r_flags2 |= RF2_HUMAN;
116             }
117             if (mult < 17)
118                 mult = 17;
119         }
120
121         if ((have_flag(flgs, TR_KILL_HUMAN)) && (r_ptr->flags2 & RF2_HUMAN)) {
122             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
123                 r_ptr->r_flags2 |= RF2_HUMAN;
124             }
125             if (mult < 27)
126                 mult = 27;
127         }
128
129         if ((have_flag(flgs, TR_SLAY_UNDEAD)) && (r_ptr->flags3 & RF3_UNDEAD)) {
130             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
131                 r_ptr->r_flags3 |= RF3_UNDEAD;
132             }
133             if (mult < 20)
134                 mult = 20;
135         }
136
137         if ((have_flag(flgs, TR_KILL_UNDEAD)) && (r_ptr->flags3 & RF3_UNDEAD)) {
138             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
139                 r_ptr->r_flags3 |= RF3_UNDEAD;
140             }
141             if (mult < 30)
142                 mult = 30;
143         }
144
145         if ((have_flag(flgs, TR_SLAY_DEMON)) && (r_ptr->flags3 & RF3_DEMON)) {
146             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
147                 r_ptr->r_flags3 |= RF3_DEMON;
148             }
149             if (mult < 20)
150                 mult = 20;
151         }
152
153         if ((have_flag(flgs, TR_KILL_DEMON)) && (r_ptr->flags3 & RF3_DEMON)) {
154             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
155                 r_ptr->r_flags3 |= RF3_DEMON;
156             }
157             if (mult < 30)
158                 mult = 30;
159         }
160
161         if ((have_flag(flgs, TR_SLAY_ORC)) && (r_ptr->flags3 & RF3_ORC)) {
162             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
163                 r_ptr->r_flags3 |= RF3_ORC;
164             }
165             if (mult < 20)
166                 mult = 20;
167         }
168
169         if ((have_flag(flgs, TR_KILL_ORC)) && (r_ptr->flags3 & RF3_ORC)) {
170             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
171                 r_ptr->r_flags3 |= RF3_ORC;
172             }
173             if (mult < 30)
174                 mult = 30;
175         }
176
177         if ((have_flag(flgs, TR_SLAY_TROLL)) && (r_ptr->flags3 & RF3_TROLL)) {
178             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
179                 r_ptr->r_flags3 |= RF3_TROLL;
180             }
181
182             if (mult < 20)
183                 mult = 20;
184         }
185
186         if ((have_flag(flgs, TR_KILL_TROLL)) && (r_ptr->flags3 & RF3_TROLL)) {
187             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
188                 r_ptr->r_flags3 |= RF3_TROLL;
189             }
190             if (mult < 30)
191                 mult = 30;
192         }
193
194         if ((have_flag(flgs, TR_SLAY_GIANT)) && (r_ptr->flags3 & RF3_GIANT)) {
195             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
196                 r_ptr->r_flags3 |= RF3_GIANT;
197             }
198             if (mult < 20)
199                 mult = 20;
200         }
201
202         if ((have_flag(flgs, TR_KILL_GIANT)) && (r_ptr->flags3 & RF3_GIANT)) {
203             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
204                 r_ptr->r_flags3 |= RF3_GIANT;
205             }
206             if (mult < 30)
207                 mult = 30;
208         }
209
210         if ((have_flag(flgs, TR_SLAY_DRAGON)) && (r_ptr->flags3 & RF3_DRAGON)) {
211             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
212                 r_ptr->r_flags3 |= RF3_DRAGON;
213             }
214             if (mult < 20)
215                 mult = 20;
216         }
217
218         if ((have_flag(flgs, TR_KILL_DRAGON)) && (r_ptr->flags3 & RF3_DRAGON)) {
219             if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
220                 r_ptr->r_flags3 |= RF3_DRAGON;
221             }
222             if (mult < 30)
223                 mult = 30;
224             if ((o_ptr->name1 == ART_BARD_ARROW) && (m_ptr->r_idx == MON_SMAUG) && (sniper_ptr->inventory_list[INVEN_BOW].name1 == ART_BARD))
225                 mult *= 5;
226         }
227
228         if (have_flag(flgs, TR_BRAND_ACID)) {
229             /* Notice immunity */
230             if (r_ptr->flagsr & RFR_EFF_IM_ACID_MASK) {
231                 if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
232                     r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_ACID_MASK);
233                 }
234             } else {
235                 if (mult < 17)
236                     mult = 17;
237             }
238         }
239
240         if (have_flag(flgs, TR_BRAND_ELEC)) {
241             /* Notice immunity */
242             if (r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK) {
243                 if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
244                     r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK);
245                 }
246             } else {
247                 if (mult < 17)
248                     mult = 17;
249             }
250         }
251
252         if (have_flag(flgs, TR_BRAND_FIRE)) {
253             /* Notice immunity */
254             if (r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK) {
255                 if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
256                     r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK);
257                 }
258             }
259             /* Otherwise, take the damage */
260             else {
261                 if (r_ptr->flags3 & RF3_HURT_FIRE) {
262                     if (mult < 25)
263                         mult = 25;
264                     if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
265                         r_ptr->r_flags3 |= RF3_HURT_FIRE;
266                     }
267                 } else if (mult < 17)
268                     mult = 17;
269             }
270         }
271
272         if (have_flag(flgs, TR_BRAND_COLD)) {
273             /* Notice immunity */
274             if (r_ptr->flagsr & RFR_EFF_IM_COLD_MASK) {
275                 if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
276                     r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_COLD_MASK);
277                 }
278             }
279             /* Otherwise, take the damage */
280             else {
281                 if (r_ptr->flags3 & RF3_HURT_COLD) {
282                     if (mult < 25)
283                         mult = 25;
284                     if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
285                         r_ptr->r_flags3 |= RF3_HURT_COLD;
286                     }
287                 } else if (mult < 17)
288                     mult = 17;
289             }
290         }
291
292         if (have_flag(flgs, TR_BRAND_POIS)) {
293             /* Notice immunity */
294             if (r_ptr->flagsr & RFR_EFF_IM_POIS_MASK) {
295                 if (is_original_ap_and_seen(sniper_ptr, m_ptr)) {
296                     r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_POIS_MASK);
297                 }
298             }
299             /* Otherwise, take the damage */
300             else {
301                 if (mult < 17)
302                     mult = 17;
303             }
304         }
305
306         if ((have_flag(flgs, TR_FORCE_WEAPON)) && (sniper_ptr->csp > (sniper_ptr->msp / 30))) {
307             sniper_ptr->csp -= (1 + (sniper_ptr->msp / 30));
308             sniper_ptr->redraw |= (PR_MANA);
309             mult = mult * 5 / 2;
310         }
311         break;
312     }
313     }
314
315     /* Sniper */
316     if (snipe_type)
317         mult = calc_snipe_damage_with_slay(sniper_ptr, mult, m_ptr, snipe_type);
318
319     /* Return the total damage */
320     return (tdam * mult / 10);
321 }
322
323 /*!
324  * @brief 射撃処理実行 /
325  * Fire an object from the pack or floor.
326  * @param item 射撃するオブジェクトの所持ID
327  * @param j_ptr 射撃武器のオブジェクト参照ポインタ
328  * @return なし
329  * @details
330  * <pre>
331  * You may only fire items that "match" your missile launcher.
332  * You must use slings + pebbles/shots, bows + arrows, xbows + bolts.
333  * See "calc_bonuses()" for more calculations and such.
334  * Note that "firing" a missile is MUCH better than "throwing" it.
335  * Note: "unseen" monsters are very hard to hit.
336  * Objects are more likely to break if they "attempt" to hit a monster.
337  * Rangers (with Bows) and Anyone (with "Extra Shots") get extra shots.
338  * The "extra shot" code works by decreasing the amount of energy
339  * required to make each shot, spreading the shots out over time.
340  * Note that when firing missiles, the launcher multiplier is applied
341  * after all the bonuses are added in, making multipliers very useful.
342  * Note that Bows of "Extra Might" get extra range and an extra bonus
343  * for the damage multiplier.
344  * Note that Bows of "Extra Shots" give an extra shot.
345  * </pre>
346  */
347 void exe_fire(player_type *shooter_ptr, INVENTORY_IDX item, object_type *j_ptr, SPELL_IDX snipe_type)
348 {
349     DIRECTION dir;
350     int i;
351     POSITION y, x, ny, nx, ty, tx, prev_y, prev_x;
352     int tdam_base, tdis, thits, tmul;
353     int bonus, chance;
354     int cur_dis, visible;
355     PERCENTAGE j;
356
357     object_type forge;
358     object_type *q_ptr;
359
360     object_type *o_ptr;
361
362     bool hit_body = FALSE;
363
364     GAME_TEXT o_name[MAX_NLEN];
365
366     u16b path_g[512]; /* For calcuration of path length */
367
368     int msec = delay_factor * delay_factor * delay_factor;
369
370     /* STICK TO */
371     bool stick_to = FALSE;
372
373     /* Access the item (if in the pack) */
374     if (item >= 0) {
375         o_ptr = &shooter_ptr->inventory_list[item];
376     } else {
377         o_ptr = &shooter_ptr->current_floor_ptr->o_list[0 - item];
378     }
379
380     /* Sniper - Cannot shot a single arrow twice */
381     if ((snipe_type == SP_DOUBLE) && (o_ptr->number < 2))
382         snipe_type = SP_NONE;
383
384     describe_flavor(shooter_ptr, o_name, o_ptr, OD_OMIT_PREFIX);
385
386     /* Use the proper number of shots */
387     thits = shooter_ptr->num_fire;
388
389     /* Use a base distance */
390     tdis = 10;
391
392     /* Base damage from thrown object plus launcher bonus */
393     tdam_base = damroll(o_ptr->dd, o_ptr->ds) + o_ptr->to_d + j_ptr->to_d;
394
395     /* Actually "fire" the object */
396     bonus = (shooter_ptr->to_h_b + o_ptr->to_h + j_ptr->to_h);
397     if ((j_ptr->sval == SV_LIGHT_XBOW) || (j_ptr->sval == SV_HEAVY_XBOW))
398         chance = (shooter_ptr->skill_thb + (shooter_ptr->weapon_exp[0][j_ptr->sval] / 400 + bonus) * BTH_PLUS_ADJ);
399     else
400         chance = (shooter_ptr->skill_thb + ((shooter_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + bonus) * BTH_PLUS_ADJ);
401
402     shooter_ptr->energy_use = bow_energy(j_ptr->sval);
403     tmul = bow_tmul(j_ptr->sval);
404
405     /* Get extra "power" from "extra might" */
406     if (shooter_ptr->xtra_might)
407         tmul++;
408
409     tmul = tmul * (100 + (int)(adj_str_td[shooter_ptr->stat_ind[A_STR]]) - 128);
410
411     /* Boost the damage */
412     tdam_base *= tmul;
413     tdam_base /= 100;
414
415     /* Base range */
416     tdis = 13 + tmul / 80;
417     if ((j_ptr->sval == SV_LIGHT_XBOW) || (j_ptr->sval == SV_HEAVY_XBOW)) {
418         if (shooter_ptr->concent)
419             tdis -= (5 - (shooter_ptr->concent + 1) / 2);
420         else
421             tdis -= 5;
422     }
423
424     project_length = tdis + 1;
425
426     /* Get a direction (or cancel) */
427     if (!get_aim_dir(shooter_ptr, &dir)) {
428         free_turn(shooter_ptr);
429
430         if (snipe_type == SP_AWAY)
431             snipe_type = SP_NONE;
432
433         /* need not to reset project_length (already did)*/
434
435         return;
436     }
437
438     /* Predict the "target" location */
439     tx = shooter_ptr->x + 99 * ddx[dir];
440     ty = shooter_ptr->y + 99 * ddy[dir];
441
442     /* Check for "target request" */
443     if ((dir == 5) && target_okay(shooter_ptr)) {
444         tx = target_col;
445         ty = target_row;
446     }
447
448     /* Get projection path length */
449     tdis = project_path(shooter_ptr, path_g, project_length, shooter_ptr->y, shooter_ptr->x, ty, tx, PROJECT_PATH | PROJECT_THRU) - 1;
450
451     project_length = 0; /* reset to default */
452
453     /* Don't shoot at my feet */
454     if (tx == shooter_ptr->x && ty == shooter_ptr->y) {
455         free_turn(shooter_ptr);
456
457         /* project_length is already reset to 0 */
458
459         return;
460     }
461
462     /* Take a (partial) turn */
463     shooter_ptr->energy_use = (shooter_ptr->energy_use / thits);
464     shooter_ptr->is_fired = TRUE;
465
466     /* Sniper - Difficult to shot twice at 1 turn */
467     if (snipe_type == SP_DOUBLE)
468         shooter_ptr->concent = (shooter_ptr->concent + 1) / 2;
469
470     /* Sniper - Repeat shooting when double shots */
471     for (i = 0; i < ((snipe_type == SP_DOUBLE) ? 2 : 1); i++) {
472
473         /* Start at the player */
474         y = shooter_ptr->y;
475         x = shooter_ptr->x;
476         q_ptr = &forge;
477         object_copy(q_ptr, o_ptr);
478
479         /* Single object */
480         q_ptr->number = 1;
481
482         vary_item(shooter_ptr, item, -1);
483
484         sound(SOUND_SHOOT);
485         handle_stuff(shooter_ptr);
486
487         prev_y = y;
488         prev_x = x;
489
490         /* The shot does not hit yet */
491         hit_body = FALSE;
492
493         /* Travel until stopped */
494         for (cur_dis = 0; cur_dis <= tdis;) {
495             grid_type *g_ptr;
496
497             /* Hack -- Stop at the target */
498             if ((y == ty) && (x == tx))
499                 break;
500
501             /* Calculate the new location (see "project()") */
502             ny = y;
503             nx = x;
504             mmove2(&ny, &nx, shooter_ptr->y, shooter_ptr->x, ty, tx);
505
506             /* Shatter Arrow */
507             if (snipe_type == SP_KILL_WALL) {
508                 g_ptr = &shooter_ptr->current_floor_ptr->grid_array[ny][nx];
509
510                 if (cave_have_flag_grid(g_ptr, FF_HURT_ROCK) && !g_ptr->m_idx) {
511                     if (g_ptr->info & (CAVE_MARK))
512                         msg_print(_("岩が砕け散った。", "Wall rocks were shattered."));
513                     /* Forget the wall */
514                     g_ptr->info &= ~(CAVE_MARK);
515                     shooter_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE);
516
517                     /* Destroy the wall */
518                     cave_alter_feat(shooter_ptr, ny, nx, FF_HURT_ROCK);
519
520                     hit_body = TRUE;
521                     break;
522                 }
523             }
524
525             /* Stopped by walls/doors */
526             if (!cave_have_flag_bold(shooter_ptr->current_floor_ptr, ny, nx, FF_PROJECT) && !shooter_ptr->current_floor_ptr->grid_array[ny][nx].m_idx)
527                 break;
528
529             /* Advance the distance */
530             cur_dis++;
531
532             /* Sniper */
533             if (snipe_type == SP_LITE) {
534                 shooter_ptr->current_floor_ptr->grid_array[ny][nx].info |= (CAVE_GLOW);
535                 note_spot(shooter_ptr, ny, nx);
536                 lite_spot(shooter_ptr, ny, nx);
537             }
538
539             /* The player can see the (on screen) missile */
540             if (panel_contains(ny, nx) && player_can_see_bold(shooter_ptr, ny, nx)) {
541                 SYMBOL_CODE c = object_char(q_ptr);
542                 byte a = object_attr(q_ptr);
543
544                 /* Draw, Hilite, Fresh, Pause, Erase */
545                 print_rel(shooter_ptr, c, a, ny, nx);
546                 move_cursor_relative(ny, nx);
547                 Term_fresh();
548                 Term_xtra(TERM_XTRA_DELAY, msec);
549                 lite_spot(shooter_ptr, ny, nx);
550                 Term_fresh();
551             }
552
553             /* The player cannot see the missile */
554             else {
555                 /* Pause anyway, for consistancy */
556                 Term_xtra(TERM_XTRA_DELAY, msec);
557             }
558
559             /* Sniper */
560             if (snipe_type == SP_KILL_TRAP) {
561                 project(shooter_ptr, 0, 0, ny, nx, 0, GF_KILL_TRAP, (PROJECT_JUMP | PROJECT_HIDE | PROJECT_GRID | PROJECT_ITEM), -1);
562             }
563
564             /* Sniper */
565             if (snipe_type == SP_EVILNESS) {
566                 shooter_ptr->current_floor_ptr->grid_array[ny][nx].info &= ~(CAVE_GLOW | CAVE_MARK);
567                 note_spot(shooter_ptr, ny, nx);
568                 lite_spot(shooter_ptr, ny, nx);
569             }
570
571             prev_y = y;
572             prev_x = x;
573
574             /* Save the new location */
575             x = nx;
576             y = ny;
577
578             /* Monster here, Try to hit it */
579             if (shooter_ptr->current_floor_ptr->grid_array[y][x].m_idx) {
580                 grid_type *c_mon_ptr = &shooter_ptr->current_floor_ptr->grid_array[y][x];
581
582                 monster_type *m_ptr = &shooter_ptr->current_floor_ptr->m_list[c_mon_ptr->m_idx];
583                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
584
585                 /* Check the visibility */
586                 visible = m_ptr->ml;
587
588                 /* Note the collision */
589                 hit_body = TRUE;
590
591                 if (monster_csleep_remaining(m_ptr)) {
592                     if (!(r_ptr->flags3 & RF3_EVIL) || one_in_(5))
593                         chg_virtue(shooter_ptr, V_COMPASSION, -1);
594                     if (!(r_ptr->flags3 & RF3_EVIL) || one_in_(5))
595                         chg_virtue(shooter_ptr, V_HONOUR, -1);
596                 }
597
598                 if ((r_ptr->level + 10) > shooter_ptr->lev) {
599                     int now_exp = shooter_ptr->weapon_exp[0][j_ptr->sval];
600                     if (now_exp < s_info[shooter_ptr->pclass].w_max[0][j_ptr->sval]) {
601                         SUB_EXP amount = 0;
602                         if (now_exp < WEAPON_EXP_BEGINNER)
603                             amount = 80;
604                         else if (now_exp < WEAPON_EXP_SKILLED)
605                             amount = 25;
606                         else if ((now_exp < WEAPON_EXP_EXPERT) && (shooter_ptr->lev > 19))
607                             amount = 10;
608                         else if (shooter_ptr->lev > 34)
609                             amount = 2;
610                         shooter_ptr->weapon_exp[0][j_ptr->sval] += amount;
611                         shooter_ptr->update |= (PU_BONUS);
612                     }
613                 }
614
615                 if (shooter_ptr->riding) {
616                     if ((shooter_ptr->skill_exp[GINOU_RIDING] < s_info[shooter_ptr->pclass].s_max[GINOU_RIDING])
617                         && ((shooter_ptr->skill_exp[GINOU_RIDING] - (RIDING_EXP_BEGINNER * 2)) / 200
618                             < r_info[shooter_ptr->current_floor_ptr->m_list[shooter_ptr->riding].r_idx].level)
619                         && one_in_(2)) {
620                         shooter_ptr->skill_exp[GINOU_RIDING] += 1;
621                         shooter_ptr->update |= (PU_BONUS);
622                     }
623                 }
624
625                 /* Did we hit it (penalize range) */
626                 if (test_hit_fire(shooter_ptr, chance - cur_dis, m_ptr, m_ptr->ml, o_name)) {
627                     bool fear = FALSE;
628                     int tdam = tdam_base;
629
630                     /* Get extra damage from concentration */
631                     if (shooter_ptr->concent)
632                         tdam = boost_concentration_damage(shooter_ptr, tdam);
633
634                     /* Handle unseen monster */
635                     if (!visible) {
636                         /* Invisible monster */
637                         msg_format(_("%sが敵を捕捉した。", "The %s finds a mark."), o_name);
638                     }
639
640                     /* Handle visible monster */
641                     else {
642                         GAME_TEXT m_name[MAX_NLEN];
643
644                         /* Get "the monster" or "it" */
645                         monster_desc(shooter_ptr, m_name, m_ptr, 0);
646
647                         msg_format(_("%sが%sに命中した。", "The %s hits %s."), o_name, m_name);
648
649                         if (m_ptr->ml) {
650                             if (!shooter_ptr->image)
651                                 monster_race_track(shooter_ptr, m_ptr->ap_r_idx);
652                             health_track(shooter_ptr, c_mon_ptr->m_idx);
653                         }
654                     }
655
656                     if (snipe_type == SP_NEEDLE) {
657                         if ((randint1(randint1(r_ptr->level / (3 + shooter_ptr->concent)) + (8 - shooter_ptr->concent)) == 1) && !(r_ptr->flags1 & RF1_UNIQUE)
658                             && !(r_ptr->flags7 & RF7_UNIQUE2)) {
659                             GAME_TEXT m_name[MAX_NLEN];
660
661                             /* Get "the monster" or "it" */
662                             monster_desc(shooter_ptr, m_name, m_ptr, 0);
663
664                             tdam = m_ptr->hp + 1;
665                             msg_format(_("%sの急所に突き刺さった!", "Your shot hit a fatal spot of %s!"), m_name);
666                         } else
667                             tdam = 1;
668                     } else {
669                         /* Apply special damage */
670                         tdam = calc_shot_damage_with_slay(shooter_ptr, q_ptr, tdam, m_ptr, snipe_type);
671                         tdam = critical_shot(shooter_ptr, q_ptr->weight, q_ptr->to_h, j_ptr->to_h, tdam);
672
673                         /* No negative damage */
674                         if (tdam < 0)
675                             tdam = 0;
676
677                         /* Modify the damage */
678                         tdam = mon_damage_mod(shooter_ptr, m_ptr, tdam, FALSE);
679                     }
680
681                     msg_format_wizard(shooter_ptr, CHEAT_MONSTER, _("%dのダメージを与えた。(残りHP %d/%d(%d))", "You do %d damage. (left HP %d/%d(%d))"), tdam,
682                         m_ptr->hp - tdam, m_ptr->maxhp, m_ptr->max_maxhp);
683
684                     /* Sniper */
685                     if (snipe_type == SP_EXPLODE) {
686                         u16b flg = (PROJECT_STOP | PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID);
687
688                         sound(SOUND_EXPLODE); /* No explode sound - use breath fire instead */
689                         project(shooter_ptr, 0, ((shooter_ptr->concent + 1) / 2 + 1), ny, nx, tdam, GF_MISSILE, flg, -1);
690                         break;
691                     }
692
693                     /* Sniper */
694                     if (snipe_type == SP_HOLYNESS) {
695                         shooter_ptr->current_floor_ptr->grid_array[ny][nx].info |= (CAVE_GLOW);
696                         note_spot(shooter_ptr, ny, nx);
697                         lite_spot(shooter_ptr, ny, nx);
698                     }
699
700                     /* Hit the monster, check for death */
701                     if (mon_take_hit(shooter_ptr, c_mon_ptr->m_idx, tdam, &fear, extract_note_dies(real_r_idx(m_ptr)))) {
702                         /* Dead monster */
703                     }
704
705                     /* No death */
706                     else {
707                         /* STICK TO */
708                         if (object_is_fixed_artifact(q_ptr) && (shooter_ptr->pclass != CLASS_SNIPER || shooter_ptr->concent == 0)) {
709                             GAME_TEXT m_name[MAX_NLEN];
710
711                             monster_desc(shooter_ptr, m_name, m_ptr, 0);
712
713                             stick_to = TRUE;
714                             msg_format(_("%sは%sに突き刺さった!", "%^s is stuck in %s!"), o_name, m_name);
715                         }
716
717                         message_pain(shooter_ptr, c_mon_ptr->m_idx, tdam);
718
719                         /* Anger the monster */
720                         if (tdam > 0)
721                             anger_monster(shooter_ptr, m_ptr);
722
723                         if (fear && m_ptr->ml) {
724                             GAME_TEXT m_name[MAX_NLEN];
725                             sound(SOUND_FLEE);
726                             monster_desc(shooter_ptr, m_name, m_ptr, 0);
727                             msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), m_name);
728                         }
729
730                         set_target(m_ptr, shooter_ptr->y, shooter_ptr->x);
731
732                         /* Sniper */
733                         if (snipe_type == SP_RUSH) {
734                             int n = randint1(5) + 3;
735                             MONSTER_IDX m_idx = c_mon_ptr->m_idx;
736
737                             for (; cur_dis <= tdis;) {
738                                 POSITION ox = nx;
739                                 POSITION oy = ny;
740
741                                 if (!n)
742                                     break;
743
744                                 /* Calculate the new location (see "project()") */
745                                 mmove2(&ny, &nx, shooter_ptr->y, shooter_ptr->x, ty, tx);
746
747                                 /* Stopped by wilderness boundary */
748                                 if (!in_bounds2(shooter_ptr->current_floor_ptr, ny, nx))
749                                     break;
750
751                                 /* Stopped by walls/doors */
752                                 if (!player_can_enter(shooter_ptr, shooter_ptr->current_floor_ptr->grid_array[ny][nx].feat, 0))
753                                     break;
754
755                                 /* Stopped by monsters */
756                                 if (!is_cave_empty_bold(shooter_ptr, ny, nx))
757                                     break;
758
759                                 shooter_ptr->current_floor_ptr->grid_array[ny][nx].m_idx = m_idx;
760                                 shooter_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = 0;
761
762                                 m_ptr->fx = nx;
763                                 m_ptr->fy = ny;
764
765                                 update_monster(shooter_ptr, c_mon_ptr->m_idx, TRUE);
766
767                                 lite_spot(shooter_ptr, ny, nx);
768                                 lite_spot(shooter_ptr, oy, ox);
769
770                                 Term_fresh();
771                                 Term_xtra(TERM_XTRA_DELAY, msec);
772
773                                 x = nx;
774                                 y = ny;
775                                 cur_dis++;
776                                 n--;
777                             }
778                         }
779                     }
780                 }
781
782                 /* Sniper */
783                 if (snipe_type == SP_PIERCE) {
784                     if (shooter_ptr->concent < 1)
785                         break;
786                     shooter_ptr->concent--;
787                     continue;
788                 }
789
790                 /* Stop looking */
791                 break;
792             }
793         }
794
795         /* Chance of breakage (during attacks) */
796         j = (hit_body ? breakage_chance(shooter_ptr, q_ptr, shooter_ptr->pclass == CLASS_ARCHER, snipe_type) : 0);
797
798         if (stick_to) {
799             MONSTER_IDX m_idx = shooter_ptr->current_floor_ptr->grid_array[y][x].m_idx;
800             monster_type *m_ptr = &shooter_ptr->current_floor_ptr->m_list[m_idx];
801             OBJECT_IDX o_idx = o_pop(shooter_ptr->current_floor_ptr);
802
803             if (!o_idx) {
804                 msg_format(_("%sはどこかへ行った。", "The %s went somewhere."), o_name);
805                 if (object_is_fixed_artifact(q_ptr)) {
806                     a_info[j_ptr->name1].cur_num = 0;
807                 }
808                 return;
809             }
810
811             o_ptr = &shooter_ptr->current_floor_ptr->o_list[o_idx];
812             object_copy(o_ptr, q_ptr);
813
814             /* Forget mark */
815             o_ptr->marked &= OM_TOUCHED;
816
817             /* Forget location */
818             o_ptr->iy = o_ptr->ix = 0;
819
820             /* Memorize monster */
821             o_ptr->held_m_idx = m_idx;
822
823             /* Build a stack */
824             o_ptr->next_o_idx = m_ptr->hold_o_idx;
825
826             /* Carry object */
827             m_ptr->hold_o_idx = o_idx;
828         } else if (cave_have_flag_bold(shooter_ptr->current_floor_ptr, y, x, FF_PROJECT)) {
829             /* Drop (or break) near that location */
830             (void)drop_near(shooter_ptr, q_ptr, j, y, x);
831         } else {
832             /* Drop (or break) near that location */
833             (void)drop_near(shooter_ptr, q_ptr, j, prev_y, prev_x);
834         }
835
836         /* Sniper - Repeat shooting when double shots */
837     }
838
839     /* Sniper - Loose his/her concentration after any shot */
840     if (shooter_ptr->concent)
841         reset_concentration(shooter_ptr, FALSE);
842 }
843
844 /*!
845  * @brief プレイヤーからモンスターへの射撃命中判定 /
846  * Determine if the player "hits" a monster (normal combat).
847  * @param chance 基本命中値
848  * @param m_ptr モンスターの構造体参照ポインタ
849  * @param vis 目標を視界に捕らえているならばTRUEを指定
850  * @param o_name メッセージ表示時のモンスター名
851  * @return 命中と判定された場合TRUEを返す
852  * @note Always miss 5%, always hit 5%, otherwise random.
853  */
854 bool test_hit_fire(player_type *shooter_ptr, int chance, monster_type *m_ptr, int vis, char *o_name)
855 {
856     int k;
857     ARMOUR_CLASS ac;
858     monster_race *r_ptr = &r_info[m_ptr->r_idx];
859
860     /* Percentile dice */
861     k = randint1(100);
862
863     /* Snipers with high-concentration reduce instant miss percentage.*/
864     k += shooter_ptr->concent;
865
866     /* Hack -- Instant miss or hit */
867     if (k <= 5)
868         return FALSE;
869     if (k > 95)
870         return TRUE;
871
872     if (shooter_ptr->pseikaku == PERSONALITY_LAZY)
873         if (one_in_(20))
874             return FALSE;
875
876     /* Never hit */
877     if (chance <= 0)
878         return FALSE;
879
880     ac = r_ptr->ac;
881     if (shooter_ptr->concent) {
882         ac *= (8 - shooter_ptr->concent);
883         ac /= 8;
884     }
885
886     if (m_ptr->r_idx == MON_GOEMON && !monster_csleep_remaining(m_ptr))
887         ac *= 3;
888
889     /* Invisible monsters are harder to hit */
890     if (!vis)
891         chance = (chance + 1) / 2;
892
893     /* Power competes against armor */
894     if (randint0(chance) < (ac * 3 / 4)) {
895         if (m_ptr->r_idx == MON_GOEMON && !monster_csleep_remaining(m_ptr)) {
896             GAME_TEXT m_name[MAX_NLEN];
897             monster_desc(shooter_ptr, m_name, m_ptr, 0);
898             msg_format(_("%sは%sを斬り捨てた!", "%s cuts down %s!"), m_name, o_name);
899         }
900         return FALSE;
901     }
902
903     /* Assume hit */
904     return TRUE;
905 }
906
907 /*!
908  * @brief プレイヤーからモンスターへの射撃クリティカル判定 /
909  * Critical hits (from objects thrown by player) Factor in item weight, total plusses, and player level.
910  * @param weight 矢弾の重量
911  * @param plus_ammo 矢弾の命中修正
912  * @param plus_bow 弓の命中修正
913  * @param dam 現在算出中のダメージ値
914  * @return クリティカル修正が入ったダメージ値
915  */
916 HIT_POINT critical_shot(player_type *shooter_ptr, WEIGHT weight, int plus_ammo, int plus_bow, HIT_POINT dam)
917 {
918     int i, k;
919     object_type *j_ptr = &shooter_ptr->inventory_list[INVEN_BOW];
920
921     /* Extract "shot" power */
922     i = shooter_ptr->to_h_b + plus_ammo;
923
924     if (shooter_ptr->tval_ammo == TV_BOLT)
925         i = (shooter_ptr->skill_thb + (shooter_ptr->weapon_exp[0][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
926     else
927         i = (shooter_ptr->skill_thb + ((shooter_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + i) * BTH_PLUS_ADJ);
928
929     /* Snipers can shot more critically with crossbows */
930     if (shooter_ptr->concent)
931         i += ((i * shooter_ptr->concent) / 5);
932     if ((shooter_ptr->pclass == CLASS_SNIPER) && (shooter_ptr->tval_ammo == TV_BOLT))
933         i *= 2;
934
935     /* Good bow makes more critical */
936     i += plus_bow * 8 * (shooter_ptr->concent ? shooter_ptr->concent + 5 : 5);
937
938     /* Critical hit */
939     if (randint1(10000) <= i) {
940         k = weight * randint1(500);
941
942         if (k < 900) {
943             msg_print(_("手ごたえがあった!", "It was a good hit!"));
944             dam += (dam / 2);
945         } else if (k < 1350) {
946             msg_print(_("かなりの手ごたえがあった!", "It was a great hit!"));
947             dam *= 2;
948         } else {
949             msg_print(_("会心の一撃だ!", "It was a superb hit!"));
950             dam *= 3;
951         }
952     }
953
954     return (dam);
955 }
956
957 /*!
958  * @brief 射撃武器の攻撃に必要な基本消費エネルギーを返す/Return bow energy
959  * @param sval 射撃武器のアイテム副分類ID
960  * @return 消費する基本エネルギー
961  */
962 ENERGY bow_energy(OBJECT_SUBTYPE_VALUE sval)
963 {
964     ENERGY energy = 10000;
965
966     /* Analyze the launcher */
967     switch (sval) {
968         /* Sling and ammo */
969     case SV_SLING: {
970         energy = 8000;
971         break;
972     }
973
974     /* Short Bow and Arrow */
975     case SV_SHORT_BOW: {
976         energy = 10000;
977         break;
978     }
979
980     /* Long Bow and Arrow */
981     case SV_LONG_BOW: {
982         energy = 10000;
983         break;
984     }
985
986     /* Bow of irresponsiblity and Arrow */
987     case SV_NAMAKE_BOW: {
988         energy = 7777;
989         break;
990     }
991
992     /* Light Crossbow and Bolt */
993     case SV_LIGHT_XBOW: {
994         energy = 12000;
995         break;
996     }
997
998     /* Heavy Crossbow and Bolt */
999     case SV_HEAVY_XBOW: {
1000         energy = 13333;
1001         break;
1002     }
1003     }
1004
1005     return (energy);
1006 }
1007
1008 /*
1009  * Return bow tmul
1010  */
1011 int bow_tmul(OBJECT_SUBTYPE_VALUE sval)
1012 {
1013     int tmul = 0;
1014
1015     /* Analyze the launcher */
1016     switch (sval) {
1017         /* Sling and ammo */
1018     case SV_SLING: {
1019         tmul = 2;
1020         break;
1021     }
1022
1023     /* Short Bow and Arrow */
1024     case SV_SHORT_BOW: {
1025         tmul = 2;
1026         break;
1027     }
1028
1029     /* Long Bow and Arrow */
1030     case SV_LONG_BOW: {
1031         tmul = 3;
1032         break;
1033     }
1034
1035     /* Bow of irresponsiblity and Arrow */
1036     case SV_NAMAKE_BOW: {
1037         tmul = 3;
1038         break;
1039     }
1040
1041     /* Light Crossbow and Bolt */
1042     case SV_LIGHT_XBOW: {
1043         tmul = 3;
1044         break;
1045     }
1046
1047     /* Heavy Crossbow and Bolt */
1048     case SV_HEAVY_XBOW: {
1049         tmul = 4;
1050         break;
1051     }
1052     }
1053
1054     return (tmul);
1055 }
1056
1057 /*!
1058  * @brief 射撃時クリティカルによるダメージ期待値修正計算(スナイパーの集中処理と武器経験値) / critical happens at i / 10000
1059  * @param shooter_ptr 射撃を行うクリーチャー参照ポインタ
1060  * @param plus_ammo 矢弾のダメージ修正
1061  * @param plus_bow 弓のダメージ修正
1062  * @return ダメージ期待値
1063  * @note 基本ダメージ量と重量はこの部位では計算に加わらない。
1064  */
1065 HIT_POINT calc_crit_ratio_shot(player_type *shooter_ptr, HIT_POINT plus_ammo, HIT_POINT plus_bow)
1066 {
1067     HIT_POINT i;
1068     object_type *j_ptr = &shooter_ptr->inventory_list[INVEN_BOW];
1069
1070     /* Extract "shot" power */
1071     i = shooter_ptr->to_h_b + plus_ammo;
1072
1073     if (shooter_ptr->tval_ammo == TV_BOLT)
1074         i = (shooter_ptr->skill_thb + (shooter_ptr->weapon_exp[0][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
1075     else
1076         i = (shooter_ptr->skill_thb + ((shooter_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + i) * BTH_PLUS_ADJ);
1077
1078     /* Snipers can shot more critically with crossbows */
1079     if (shooter_ptr->concent)
1080         i += ((i * shooter_ptr->concent) / 5);
1081     if ((shooter_ptr->pclass == CLASS_SNIPER) && (shooter_ptr->tval_ammo == TV_BOLT))
1082         i *= 2;
1083
1084     /* Good bow makes more critical */
1085     i += plus_bow * 8 * (shooter_ptr->concent ? shooter_ptr->concent + 5 : 5);
1086
1087     if (i < 0)
1088         i = 0;
1089
1090     return i;
1091 }
1092
1093 /*!
1094  * @brief 射撃時クリティカルによるダメージ期待値修正計算(重量依存部分) / critical happens at i / 10000
1095  * @param weight 武器の重量
1096  * @param plus_ammo 矢弾のダメージ修正
1097  * @param plus_bow 弓のダメージ修正
1098  * @param dam 基本ダメージ量
1099  * @return ダメージ期待値
1100  */
1101 HIT_POINT calc_expect_crit_shot(player_type *shooter_ptr, WEIGHT weight, int plus_ammo, int plus_bow, HIT_POINT dam)
1102 {
1103     u32b num;
1104     int i, k, crit;
1105     i = calc_crit_ratio_shot(shooter_ptr, plus_ammo, plus_bow);
1106
1107     k = 0;
1108     num = 0;
1109
1110     crit = MIN(500, 900 / weight);
1111     num += dam * 3 / 2 * crit;
1112     k = crit;
1113
1114     crit = MIN(500, 1350 / weight);
1115     crit -= k;
1116     num += dam * 2 * crit;
1117     k += crit;
1118
1119     if (k < 500) {
1120         crit = 500 - k;
1121         num += dam * 3 * crit;
1122     }
1123
1124     num /= 500;
1125
1126     num *= i;
1127     num += (10000 - i) * dam;
1128     num /= 10000;
1129
1130     return num;
1131 }
1132
1133 /*!
1134  * @brief 攻撃時クリティカルによるダメージ期待値修正計算(重量と毒針処理) / critical happens at i / 10000
1135  * @param shooter_ptr プレーヤーへの参照ポインタ
1136  * @param weight 武器の重量
1137  * @param plus 武器のダメージ修正
1138  * @param dam 基本ダメージ
1139  * @param meichuu 命中値
1140  * @param dokubari 毒針処理か否か
1141  * @return ダメージ期待値
1142  */
1143 HIT_POINT calc_expect_crit(player_type *shooter_ptr, WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, bool dokubari)
1144 {
1145     u32b k, num;
1146     if (dokubari)
1147         return dam;
1148
1149     int i = (weight + (meichuu * 3 + plus * 5) + shooter_ptr->skill_thn);
1150     if (i < 0)
1151         i = 0;
1152
1153     k = weight;
1154     num = 0;
1155
1156     if (k < 400)
1157         num += (2 * dam + 5) * (400 - k);
1158     if (k < 700)
1159         num += (2 * dam + 10) * (MIN(700, k + 650) - MAX(400, k));
1160     if (k > (700 - 650) && k < 900)
1161         num += (3 * dam + 15) * (MIN(900, k + 650) - MAX(700, k));
1162     if (k > (900 - 650) && k < 1300)
1163         num += (3 * dam + 20) * (MIN(1300, k + 650) - MAX(900, k));
1164     if (k > (1300 - 650))
1165         num += (7 * dam / 2 + 25) * MIN(650, k - (1300 - 650));
1166
1167     num /= 650;
1168     if (shooter_ptr->pclass == CLASS_NINJA) {
1169         num *= i;
1170         num += (4444 - i) * dam;
1171         num /= 4444;
1172     } else {
1173         num *= i;
1174         num += (5000 - i) * dam;
1175         num /= 5000;
1176     }
1177
1178     return num;
1179 }