OSDN Git Service

[Refactor] #38997 acid_minus_ac() に player_type * 引数を追加.
[hengband/hengband.git] / src / player-damage.c
1 #include "angband.h"
2 #include "core.h"
3 #include "util.h"
4 #include "term.h"
5
6 #include "avatar.h"
7 #include "cmd-dump.h"
8 #include "realm-song.h"
9 #include "floor.h"
10 #include "artifact.h"
11 #include "object-flavor.h"
12 #include "object-hook.h"
13 #include "object-broken.h"
14 #include "player-move.h"
15 #include "player-damage.h"
16 #include "player-personality.h"
17 #include "player-status.h"
18 #include "player-effects.h"
19 #include "player-class.h"
20 #include "monster-spell.h"
21 #include "world.h"
22 #include "view-mainwindow.h"
23 #include "quest.h"
24 #include "report.h"
25 #include "wild.h"
26 #include "save.h"
27 #include "files.h"
28
29
30 /*!
31 * @brief アイテムが酸で破損するかどうかを判定する
32 * @param o_ptr アイテムの情報参照ポインタ
33 * @return 破損するならばTRUEを返す
34 * Note that amulets, rods, and high-level spell books are immune
35 * to "p_ptr->inventory_list damage" of any kind.  Also sling ammo and shovels.
36 * Does a given class of objects (usually) hate acid?
37 * Note that acid can either melt or corrode something.
38 */
39 bool hates_acid(object_type *o_ptr)
40 {
41         /* Analyze the type */
42         switch (o_ptr->tval)
43         {
44                 /* Wearable items */
45         case TV_ARROW:
46         case TV_BOLT:
47         case TV_BOW:
48         case TV_SWORD:
49         case TV_HAFTED:
50         case TV_POLEARM:
51         case TV_HELM:
52         case TV_CROWN:
53         case TV_SHIELD:
54         case TV_BOOTS:
55         case TV_GLOVES:
56         case TV_CLOAK:
57         case TV_SOFT_ARMOR:
58         case TV_HARD_ARMOR:
59         case TV_DRAG_ARMOR:
60         {
61                 return (TRUE);
62         }
63
64         /* Staffs/Scrolls are wood/paper */
65         case TV_STAFF:
66         case TV_SCROLL:
67         {
68                 return (TRUE);
69         }
70
71         /* Ouch */
72         case TV_CHEST:
73         {
74                 return (TRUE);
75         }
76
77         /* Junk is useless */
78         case TV_SKELETON:
79         case TV_BOTTLE:
80         case TV_JUNK:
81         {
82                 return (TRUE);
83         }
84         }
85
86         return (FALSE);
87 }
88
89
90 /*!
91 * @brief アイテムが電撃で破損するかどうかを判定する /
92 * Does a given object (usually) hate electricity?
93 * @param o_ptr アイテムの情報参照ポインタ
94 * @return 破損するならばTRUEを返す
95 */
96 bool hates_elec(object_type *o_ptr)
97 {
98         switch (o_ptr->tval)
99         {
100         case TV_RING:
101         case TV_WAND:
102         {
103                 return (TRUE);
104         }
105         }
106
107         return (FALSE);
108 }
109
110
111 /*!
112 * @brief アイテムが火炎で破損するかどうかを判定する /
113 * Does a given object (usually) hate fire?
114 * @param o_ptr アイテムの情報参照ポインタ
115 * @return 破損するならばTRUEを返す
116 * @details
117 * Hafted/Polearm weapons have wooden shafts.
118 * Arrows/Bows are mostly wooden.
119 */
120 bool hates_fire(object_type *o_ptr)
121 {
122         /* Analyze the type */
123         switch (o_ptr->tval)
124         {
125                 /* Wearable */
126         case TV_LITE:
127         case TV_ARROW:
128         case TV_BOW:
129         case TV_HAFTED:
130         case TV_POLEARM:
131         case TV_BOOTS:
132         case TV_GLOVES:
133         case TV_CLOAK:
134         case TV_SOFT_ARMOR:
135         {
136                 return (TRUE);
137         }
138
139         /* Books */
140         case TV_LIFE_BOOK:
141         case TV_SORCERY_BOOK:
142         case TV_NATURE_BOOK:
143         case TV_CHAOS_BOOK:
144         case TV_DEATH_BOOK:
145         case TV_TRUMP_BOOK:
146         case TV_ARCANE_BOOK:
147         case TV_CRAFT_BOOK:
148         case TV_DAEMON_BOOK:
149         case TV_CRUSADE_BOOK:
150         case TV_MUSIC_BOOK:
151         case TV_HISSATSU_BOOK:
152         case TV_HEX_BOOK:
153         {
154                 return (TRUE);
155         }
156
157         /* Chests */
158         case TV_CHEST:
159         {
160                 return (TRUE);
161         }
162
163         /* Staffs/Scrolls burn */
164         case TV_STAFF:
165         case TV_SCROLL:
166         {
167                 return (TRUE);
168         }
169         }
170
171         return (FALSE);
172 }
173
174
175 /*!
176 * @brief アイテムが冷気で破損するかどうかを判定する /
177 * Does a given object (usually) hate cold?
178 * @param o_ptr アイテムの情報参照ポインタ
179 * @return 破損するならばTRUEを返す
180 */
181 bool hates_cold(object_type *o_ptr)
182 {
183         switch (o_ptr->tval)
184         {
185         case TV_POTION:
186         case TV_FLASK:
187         case TV_BOTTLE:
188         {
189                 return (TRUE);
190         }
191         }
192
193         return (FALSE);
194 }
195
196
197 /*!
198 * @brief アイテムが酸で破損するかどうかを判定する(メインルーチン) /
199 * Melt something
200 * @param o_ptr アイテムの情報参照ポインタ
201 * @return 破損するならばTRUEを返す
202 * @todo 統合を検討
203 */
204 int set_acid_destroy(object_type *o_ptr)
205 {
206         BIT_FLAGS flgs[TR_FLAG_SIZE];
207         if (!hates_acid(o_ptr)) return (FALSE);
208         object_flags(o_ptr, flgs);
209         if (have_flag(flgs, TR_IGNORE_ACID)) return (FALSE);
210         return (TRUE);
211 }
212
213
214 /*!
215 * @brief アイテムが電撃で破損するかどうかを判定する(メインルーチン) /
216 * Electrical damage
217 * @param o_ptr アイテムの情報参照ポインタ
218 * @return 破損するならばTRUEを返す
219 * @todo 統合を検討
220 */
221 int set_elec_destroy(object_type *o_ptr)
222 {
223         BIT_FLAGS flgs[TR_FLAG_SIZE];
224         if (!hates_elec(o_ptr)) return (FALSE);
225         object_flags(o_ptr, flgs);
226         if (have_flag(flgs, TR_IGNORE_ELEC)) return (FALSE);
227         return (TRUE);
228 }
229
230
231 /*!
232 * @brief アイテムが火炎で破損するかどうかを判定する(メインルーチン) /
233 * Burn something
234 * @param o_ptr アイテムの情報参照ポインタ
235 * @return 破損するならばTRUEを返す
236 * @todo 統合を検討
237 */
238 int set_fire_destroy(object_type *o_ptr)
239 {
240         BIT_FLAGS flgs[TR_FLAG_SIZE];
241         if (!hates_fire(o_ptr)) return (FALSE);
242         object_flags(o_ptr, flgs);
243         if (have_flag(flgs, TR_IGNORE_FIRE)) return (FALSE);
244         return (TRUE);
245 }
246
247
248 /*!
249 * @brief アイテムが冷気で破損するかどうかを判定する(メインルーチン) /
250 * Freeze things
251 * @param o_ptr アイテムの情報参照ポインタ
252 * @return 破損するならばTRUEを返す
253 * @todo 統合を検討
254 */
255 int set_cold_destroy(object_type *o_ptr)
256 {
257         BIT_FLAGS flgs[TR_FLAG_SIZE];
258         if (!hates_cold(o_ptr)) return (FALSE);
259         object_flags(o_ptr, flgs);
260         if (have_flag(flgs, TR_IGNORE_COLD)) return (FALSE);
261         return (TRUE);
262 }
263
264
265 /*!
266 * @brief アイテムが指定確率で破損するかどうかを判定する /
267 * Destroys a type of item on a given percent chance
268 * @param typ 破損判定関数ポインタ
269 * @param perc 基本確率
270 * @return 破損したアイテムの数
271 * @details
272 * Note that missiles are no longer necessarily all destroyed
273 * Destruction taken from "melee.c" code for "stealing".
274 * New-style wands and rods handled correctly. -LM-
275 * Returns number of items destroyed.
276 */
277 int inven_damage(inven_func typ, int perc)
278 {
279         INVENTORY_IDX i;
280         int j, k, amt;
281         object_type *o_ptr;
282         GAME_TEXT o_name[MAX_NLEN];
283
284         if (CHECK_MULTISHADOW()) return 0;
285
286         if (p_ptr->inside_arena) return 0;
287
288         /* Count the casualties */
289         k = 0;
290
291         /* Scan through the slots backwards */
292         for (i = 0; i < INVEN_PACK; i++)
293         {
294                 o_ptr = &p_ptr->inventory_list[i];
295                 if (!o_ptr->k_idx) continue;
296
297                 /* Hack -- for now, skip artifacts */
298                 if (object_is_artifact(o_ptr)) continue;
299
300                 /* Give this item slot a shot at death */
301                 if ((*typ)(o_ptr))
302                 {
303                         /* Count the casualties */
304                         for (amt = j = 0; j < o_ptr->number; ++j)
305                         {
306                                 if (randint0(100) < perc) amt++;
307                         }
308
309                         /* Some casualities */
310                         if (amt)
311                         {
312                                 object_desc(o_name, o_ptr, OD_OMIT_PREFIX);
313
314                                 msg_format(_("%s(%c)が%s壊れてしまった!", "%sour %s (%c) %s destroyed!"),
315 #ifdef JP
316                                         o_name, index_to_label(i), ((o_ptr->number > 1) ?
317                                                 ((amt == o_ptr->number) ? "全部" : (amt > 1 ? "何個か" : "一個")) : ""));
318 #else
319                                         ((o_ptr->number > 1) ? ((amt == o_ptr->number) ? "All of y" :
320                                                 (amt > 1 ? "Some of y" : "One of y")) : "Y"), o_name, index_to_label(i), ((amt > 1) ? "were" : "was"));
321 #endif
322
323 #ifdef JP
324                                 if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (p_ptr->inventory_list[INVEN_BOW].name1 == ART_CRIMSON))
325                                         msg_print("やりやがったな!");
326                                 else if ((p_ptr->pseikaku == SEIKAKU_CHARGEMAN))
327                                 {
328                                         if (randint0(2) == 0) msg_print(_("ジュラル星人め!", ""));
329                                         else msg_print(_("弱い者いじめは止めるんだ!", ""));
330                                 }
331 #endif
332
333                                 /* Potions smash open */
334                                 if (object_is_potion(o_ptr))
335                                 {
336                                         (void)potion_smash_effect(0, p_ptr->y, p_ptr->x, o_ptr->k_idx);
337                                 }
338
339                                 /* Reduce the charges of rods/wands */
340                                 reduce_charges(o_ptr, amt);
341
342                                 /* Destroy "amt" items */
343                                 inven_item_increase(i, -amt);
344                                 inven_item_optimize(i);
345
346                                 /* Count the casualties */
347                                 k += amt;
348                         }
349                 }
350         }
351
352         /* Return the casualty count */
353         return (k);
354 }
355
356
357 /*!
358 * @brief 酸攻撃による装備のAC劣化処理 /
359 * Acid has hit the player, attempt to affect some armor.
360 * @return 装備による軽減があったならTRUEを返す
361 * @details
362 * Note that the "base armor" of an object never changes.
363 * If any armor is damaged (or resists), the player takes less damage.
364 */
365 static bool acid_minus_ac(player_type *creature_ptr)
366 {
367         object_type *o_ptr = NULL;
368         BIT_FLAGS flgs[TR_FLAG_SIZE];
369         GAME_TEXT o_name[MAX_NLEN];
370
371         /* Pick a (possibly empty) creature_ptr->inventory_list slot */
372         switch (randint1(7))
373         {
374         case 1: o_ptr = &creature_ptr->inventory_list[INVEN_RARM]; break;
375         case 2: o_ptr = &creature_ptr->inventory_list[INVEN_LARM]; break;
376         case 3: o_ptr = &creature_ptr->inventory_list[INVEN_BODY]; break;
377         case 4: o_ptr = &creature_ptr->inventory_list[INVEN_OUTER]; break;
378         case 5: o_ptr = &creature_ptr->inventory_list[INVEN_HANDS]; break;
379         case 6: o_ptr = &creature_ptr->inventory_list[INVEN_HEAD]; break;
380         case 7: o_ptr = &creature_ptr->inventory_list[INVEN_FEET]; break;
381         }
382
383         if (!o_ptr->k_idx) return (FALSE);
384         if (!object_is_armour(o_ptr)) return (FALSE);
385
386         object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
387         object_flags(o_ptr, flgs);
388         /* No damage left to be done */
389         if (o_ptr->ac + o_ptr->to_a <= 0)
390         {
391                 msg_format(_("%sは既にボロボロだ!", "Your %s is already crumble!"), o_name);
392                 return (FALSE);
393         }
394
395         /* Object resists */
396         if (have_flag(flgs, TR_IGNORE_ACID))
397         {
398                 msg_format(_("しかし%sには効果がなかった!", "Your %s is unaffected!"), o_name);
399                 return (TRUE);
400         }
401
402         msg_format(_("%sが酸で腐食した!", "Your %s is corroded!"), o_name);
403
404         /* Damage the item */
405         o_ptr->to_a--;
406
407         /* Calculate bonuses */
408         creature_ptr->update |= (PU_BONUS);
409         creature_ptr->window |= (PW_EQUIP | PW_PLAYER);
410
411         calc_android_exp(creature_ptr);
412
413         /* Item was damaged */
414         return (TRUE);
415 }
416
417
418 /*!
419 * @brief 酸属性によるプレイヤー損害処理 /
420 * Hurt the player with Acid
421 * @param dam 基本ダメージ量
422 * @param kb_str ダメージ原因記述
423 * @param monspell 原因となったモンスター特殊攻撃ID
424 * @param aura オーラよるダメージが原因ならばTRUE
425 * @return 修正HPダメージ量
426 */
427 HIT_POINT acid_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
428 {
429         HIT_POINT get_damage;
430         int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
431         bool double_resist = IS_OPPOSE_ACID();
432
433         /* Total Immunity */
434         if (p_ptr->immune_acid || (dam <= 0))
435         {
436                 learn_spell(monspell);
437                 return 0;
438         }
439
440         /* Vulnerability (Ouch!) */
441         if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
442         if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
443
444         /* Resist the damage */
445         if (p_ptr->resist_acid) dam = (dam + 2) / 3;
446         if (double_resist) dam = (dam + 2) / 3;
447
448         if (aura || !CHECK_MULTISHADOW())
449         {
450                 if ((!(double_resist || p_ptr->resist_acid)) &&
451                         one_in_(HURT_CHANCE))
452                         (void)do_dec_stat(p_ptr, A_CHR);
453
454                 /* If any armor gets hit, defend the player */
455                 if (acid_minus_ac(p_ptr)) dam = (dam + 1) / 2;
456         }
457
458         get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
459
460         /* Inventory damage */
461         if (!aura && !(double_resist && p_ptr->resist_acid))
462                 inven_damage(set_acid_destroy, inv);
463         return get_damage;
464 }
465
466
467 /*!
468 * @brief 電撃属性によるプレイヤー損害処理 /
469 * Hurt the player with electricity
470 * @param dam 基本ダメージ量
471 * @param kb_str ダメージ原因記述
472 * @param monspell 原因となったモンスター特殊攻撃ID
473 * @param aura オーラよるダメージが原因ならばTRUE
474 * @return 修正HPダメージ量
475 */
476 HIT_POINT elec_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
477 {
478         HIT_POINT get_damage;
479         int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
480         bool double_resist = IS_OPPOSE_ELEC();
481
482         /* Total immunity */
483         if (p_ptr->immune_elec || (dam <= 0))
484         {
485                 learn_spell(monspell);
486                 return 0;
487         }
488
489         /* Vulnerability (Ouch!) */
490         if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
491         if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
492         if (PRACE_IS_(p_ptr, RACE_ANDROID)) dam += dam / 3;
493
494         /* Resist the damage */
495         if (p_ptr->resist_elec) dam = (dam + 2) / 3;
496         if (double_resist) dam = (dam + 2) / 3;
497
498         if (aura || !CHECK_MULTISHADOW())
499         {
500                 if ((!(double_resist || p_ptr->resist_elec)) &&
501                         one_in_(HURT_CHANCE))
502                         (void)do_dec_stat(p_ptr, A_DEX);
503         }
504
505         get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
506
507         /* Inventory damage */
508         if (!aura && !(double_resist && p_ptr->resist_elec))
509                 inven_damage(set_elec_destroy, inv);
510
511         return get_damage;
512 }
513
514
515 /*!
516 * @brief 火炎属性によるプレイヤー損害処理 /
517 * Hurt the player with Fire
518 * @param dam 基本ダメージ量
519 * @param kb_str ダメージ原因記述
520 * @param monspell 原因となったモンスター特殊攻撃ID
521 * @param aura オーラよるダメージが原因ならばTRUE
522 * @return 修正HPダメージ量
523 */
524 HIT_POINT fire_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
525 {
526         HIT_POINT get_damage;
527         int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
528         bool double_resist = IS_OPPOSE_FIRE();
529
530         /* Totally immune */
531         if (p_ptr->immune_fire || (dam <= 0))
532         {
533                 learn_spell(monspell);
534                 return 0;
535         }
536
537         /* Vulnerability (Ouch!) */
538         if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
539         if (PRACE_IS_(p_ptr, RACE_ENT)) dam += dam / 3;
540         if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
541
542         /* Resist the damage */
543         if (p_ptr->resist_fire) dam = (dam + 2) / 3;
544         if (double_resist) dam = (dam + 2) / 3;
545
546         if (aura || !CHECK_MULTISHADOW())
547         {
548                 if ((!(double_resist || p_ptr->resist_fire)) &&
549                         one_in_(HURT_CHANCE))
550                         (void)do_dec_stat(p_ptr, A_STR);
551         }
552
553         get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
554
555         /* Inventory damage */
556         if (!aura && !(double_resist && p_ptr->resist_fire))
557                 inven_damage(set_fire_destroy, inv);
558
559         return get_damage;
560 }
561
562
563 /*!
564 * @brief 冷気属性によるプレイヤー損害処理 /
565 * Hurt the player with Cold
566 * @param dam 基本ダメージ量
567 * @param kb_str ダメージ原因記述
568 * @param monspell 原因となったモンスター特殊攻撃ID
569 * @param aura オーラよるダメージが原因ならばTRUE
570 * @return 修正HPダメージ量
571 */
572 HIT_POINT cold_dam(HIT_POINT dam, concptr kb_str, int monspell, bool aura)
573 {
574         HIT_POINT get_damage;
575         int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
576         bool double_resist = IS_OPPOSE_COLD();
577
578         /* Total immunity */
579         if (p_ptr->immune_cold || (dam <= 0))
580         {
581                 learn_spell(monspell);
582                 return 0;
583         }
584
585         /* Vulnerability (Ouch!) */
586         if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
587         if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
588
589         /* Resist the damage */
590         if (p_ptr->resist_cold) dam = (dam + 2) / 3;
591         if (double_resist) dam = (dam + 2) / 3;
592
593         if (aura || !CHECK_MULTISHADOW())
594         {
595                 if ((!(double_resist || p_ptr->resist_cold)) &&
596                         one_in_(HURT_CHANCE))
597                         (void)do_dec_stat(p_ptr, A_STR);
598         }
599
600         get_damage = take_hit(aura ? DAMAGE_NOESCAPE : DAMAGE_ATTACK, dam, kb_str, monspell);
601
602         /* Inventory damage */
603         if (!aura && !(double_resist && p_ptr->resist_cold))
604                 inven_damage(set_cold_destroy, inv);
605
606         return get_damage;
607 }
608
609
610 /*
611  * Decreases players hit points and sets death flag if necessary
612  *
613  * Invulnerability needs to be changed into a "shield"
614  *
615  * Hack -- this function allows the user to save (or quit)
616  * the game when he dies, since the "You die." message is shown before
617  * setting the player to "dead".
618  */
619
620 int take_hit(int damage_type, HIT_POINT damage, concptr hit_from, int monspell)
621 {
622         int old_chp = p_ptr->chp;
623
624         char death_message[1024];
625         char tmp[1024];
626
627         int warning = (p_ptr->mhp * hitpoint_warn / 10);
628         if (p_ptr->is_dead) return 0;
629
630         if (p_ptr->sutemi) damage *= 2;
631         if (p_ptr->special_defense & KATA_IAI) damage += (damage + 4) / 5;
632
633         if (easy_band) damage = (damage + 1) / 2;
634
635         if (damage_type != DAMAGE_USELIFE)
636         {
637                 disturb(TRUE, TRUE);
638                 if (auto_more)
639                 {
640                         p_ptr->now_damaged = TRUE;
641                 }
642         }
643
644         if (monspell >= 0) learn_spell(monspell);
645
646         /* Mega-Hack -- Apply "invulnerability" */
647         if ((damage_type != DAMAGE_USELIFE) && (damage_type != DAMAGE_LOSELIFE))
648         {
649                 if (IS_INVULN() && (damage < 9000))
650                 {
651                         if (damage_type == DAMAGE_FORCE)
652                         {
653                                 msg_print(_("バリアが切り裂かれた!", "The attack cuts your shield of invulnerability open!"));
654                         }
655                         else if (one_in_(PENETRATE_INVULNERABILITY))
656                         {
657                                 msg_print(_("無敵のバリアを破って攻撃された!", "The attack penetrates your shield of invulnerability!"));
658                         }
659                         else
660                         {
661                                 return 0;
662                         }
663                 }
664
665                 if (CHECK_MULTISHADOW())
666                 {
667                         if (damage_type == DAMAGE_FORCE)
668                         {
669                                 msg_print(_("幻影もろとも体が切り裂かれた!", "The attack hits Shadow together with you!"));
670                         }
671                         else if (damage_type == DAMAGE_ATTACK)
672                         {
673                                 msg_print(_("攻撃は幻影に命中し、あなたには届かなかった。", "The attack hits Shadow, you are unharmed!"));
674                                 return 0;
675                         }
676                 }
677
678                 if (p_ptr->wraith_form)
679                 {
680                         if (damage_type == DAMAGE_FORCE)
681                         {
682                                 msg_print(_("半物質の体が切り裂かれた!", "The attack cuts through your ethereal body!"));
683                         }
684                         else
685                         {
686                                 damage /= 2;
687                                 if ((damage == 0) && one_in_(2)) damage = 1;
688                         }
689                 }
690
691                 if (p_ptr->special_defense & KATA_MUSOU)
692                 {
693                         damage /= 2;
694                         if ((damage == 0) && one_in_(2)) damage = 1;
695                 }
696         } /* not if LOSELIFE USELIFE */
697
698         /* Hurt the player */
699         p_ptr->chp -= damage;
700         if (damage_type == DAMAGE_GENO && p_ptr->chp < 0)
701         {
702                 damage += p_ptr->chp;
703                 p_ptr->chp = 0;
704         }
705
706         /* Display the hitpoints */
707         p_ptr->redraw |= (PR_HP);
708
709         p_ptr->window |= (PW_PLAYER);
710
711         if (damage_type != DAMAGE_GENO && p_ptr->chp == 0)
712         {
713                 chg_virtue(p_ptr, V_SACRIFICE, 1);
714                 chg_virtue(p_ptr, V_CHANCE, 2);
715         }
716
717         /* Dead player */
718         if (p_ptr->chp < 0)
719         {
720                 bool android = (p_ptr->prace == RACE_ANDROID ? TRUE : FALSE);
721
722 #ifdef JP       /* 死んだ時に強制終了して死を回避できなくしてみた by Habu */
723                 if (!cheat_save)
724                         if (!save_player()) msg_print("セーブ失敗!");
725 #endif
726
727                 sound(SOUND_DEATH);
728
729                 chg_virtue(p_ptr, V_SACRIFICE, 10);
730
731                 handle_stuff();
732                 p_ptr->leaving = TRUE;
733
734                 /* Note death */
735                 p_ptr->is_dead = TRUE;
736
737                 if (p_ptr->inside_arena)
738                 {
739                         concptr m_name = r_name + r_info[arena_info[p_ptr->arena_number].r_idx].name;
740                         msg_format(_("あなたは%sの前に敗れ去った。", "You are beaten by %s."), m_name);
741                         msg_print(NULL);
742                         if (record_arena) do_cmd_write_nikki(NIKKI_ARENA, -1 - p_ptr->arena_number, m_name);
743                 }
744                 else
745                 {
746                         QUEST_IDX q_idx = quest_number(current_floor_ptr->dun_level);
747                         bool seppuku = streq(hit_from, "Seppuku");
748                         bool winning_seppuku = p_ptr->total_winner && seppuku;
749
750                         play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_GAMEOVER);
751
752 #ifdef WORLD_SCORE
753                         /* Make screen dump */
754                         screen_dump = make_screen_dump();
755 #endif
756
757                         /* Note cause of death */
758                         if (seppuku)
759                         {
760                                 strcpy(p_ptr->died_from, hit_from);
761 #ifdef JP
762                                 if (!winning_seppuku) strcpy(p_ptr->died_from, "切腹");
763 #endif
764                         }
765                         else
766                         {
767                                 char dummy[1024];
768 #ifdef JP
769                                 sprintf(dummy, "%s%s%s", !p_ptr->paralyzed ? "" : p_ptr->free_act ? "彫像状態で" : "麻痺状態で", p_ptr->image ? "幻覚に歪んだ" : "", hit_from);
770 #else
771                                 sprintf(dummy, "%s%s", hit_from, !p_ptr->paralyzed ? "" : " while helpless");
772 #endif
773                                 my_strcpy(p_ptr->died_from, dummy, sizeof p_ptr->died_from);
774                         }
775
776                         /* No longer a winner */
777                         p_ptr->total_winner = FALSE;
778
779                         if (winning_seppuku)
780                         {
781                                 do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("勝利の後切腹した。", "did Seppuku after the winning."));
782                         }
783                         else
784                         {
785                                 char buf[20];
786
787                                 if (p_ptr->inside_arena)
788                                         strcpy(buf, _("アリーナ", "in the Arena"));
789                                 else if (!current_floor_ptr->dun_level)
790                                         strcpy(buf, _("地上", "on the surface"));
791                                 else if (q_idx && (is_fixed_quest_idx(q_idx) &&
792                                         !((q_idx == QUEST_OBERON) || (q_idx == QUEST_SERPENT))))
793                                         strcpy(buf, _("クエスト", "in a quest"));
794                                 else
795                                         sprintf(buf, _("%d階", "level %d"), (int)current_floor_ptr->dun_level);
796
797                                 sprintf(tmp, _("%sで%sに殺された。", "killed by %s %s."), buf, p_ptr->died_from);
798                                 do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp);
799                         }
800
801                         do_cmd_write_nikki(NIKKI_GAMESTART, 1, _("-------- ゲームオーバー --------", "--------   Game  Over   --------"));
802                         do_cmd_write_nikki(NIKKI_BUNSHOU, 1, "\n\n\n\n");
803
804                         flush();
805
806                         if (get_check_strict(_("画面を保存しますか?", "Dump the screen? "), CHECK_NO_HISTORY))
807                         {
808                                 do_cmd_save_screen();
809                         }
810
811                         flush();
812
813                         /* Initialize "last message" buffer */
814                         if (p_ptr->last_message) string_free(p_ptr->last_message);
815                         p_ptr->last_message = NULL;
816
817                         /* Hack -- Note death */
818                         if (!last_words)
819                         {
820 #ifdef JP
821                                 msg_format("あなたは%sました。", android ? "壊れ" : "死に");
822 #else
823                                 msg_print(android ? "You are broken." : "You die.");
824 #endif
825
826                                 msg_print(NULL);
827                         }
828                         else
829                         {
830                                 if (winning_seppuku)
831                                 {
832                                         get_rnd_line(_("seppuku_j.txt", "seppuku.txt"), 0, death_message);
833                                 }
834                                 else
835                                 {
836                                         get_rnd_line(_("death_j.txt", "death.txt"), 0, death_message);
837                                 }
838
839                                 do
840                                 {
841 #ifdef JP
842                                         while (!get_string(winning_seppuku ? "辞世の句: " : "断末魔の叫び: ", death_message, 1024));
843 #else
844                                         while (!get_string("Last word: ", death_message, 1024));
845 #endif
846                                 } while (winning_seppuku && !get_check_strict(_("よろしいですか?", "Are you sure? "), CHECK_NO_HISTORY));
847
848                                 if (death_message[0] == '\0')
849                                 {
850 #ifdef JP
851                                         strcpy(death_message, format("あなたは%sました。", android ? "壊れ" : "死に"));
852 #else
853                                         strcpy(death_message, android ? "You are broken." : "You die.");
854 #endif
855                                 }
856                                 else p_ptr->last_message = string_make(death_message);
857
858 #ifdef JP
859                                 if (winning_seppuku)
860                                 {
861                                         int i, len;
862                                         int w = Term->wid;
863                                         int h = Term->hgt;
864                                         int msg_pos_x[9] = { 5,  7,  9, 12,  14,  17,  19,  21, 23 };
865                                         int msg_pos_y[9] = { 3,  4,  5,  4,   5,   4,   5,   6,  4 };
866                                         concptr str;
867                                         char* str2;
868
869                                         Term_clear();
870
871                                         /* 桜散る */
872                                         for (i = 0; i < 40; i++)
873                                                 Term_putstr(randint0(w / 2) * 2, randint0(h), 2, TERM_VIOLET, "υ");
874
875                                         str = death_message;
876                                         if (strncmp(str, "「", 2) == 0) str += 2;
877
878                                         str2 = my_strstr(str, "」");
879                                         if (str2 != NULL) *str2 = '\0';
880
881                                         i = 0;
882                                         while (i < 9)
883                                         {
884                                                 str2 = my_strstr(str, " ");
885                                                 if (str2 == NULL) len = strlen(str);
886                                                 else len = str2 - str;
887
888                                                 if (len != 0)
889                                                 {
890                                                         Term_putstr_v(w * 3 / 4 - 2 - msg_pos_x[i] * 2, msg_pos_y[i], len,
891                                                                 TERM_WHITE, str);
892                                                         if (str2 == NULL) break;
893                                                         i++;
894                                                 }
895                                                 str = str2 + 1;
896                                                 if (*str == 0) break;
897                                         }
898
899                                         /* Hide cursor */
900                                         Term_putstr(w - 1, h - 1, 1, TERM_WHITE, " ");
901
902                                         flush();
903 #ifdef WORLD_SCORE
904                                         /* Make screen dump */
905                                         screen_dump = make_screen_dump();
906 #endif
907
908                                         /* Wait a key press */
909                                         (void)inkey();
910                                 }
911                                 else
912 #endif
913                                         msg_print(death_message);
914                         }
915                 }
916
917                 /* Dead */
918                 return damage;
919         }
920
921         handle_stuff();
922
923         /* Hitpoint warning */
924         if (p_ptr->chp < warning)
925         {
926                 /* Hack -- bell on first notice */
927                 if (old_chp > warning) bell();
928
929                 sound(SOUND_WARN);
930
931                 if (record_danger && (old_chp > warning))
932                 {
933                         if (p_ptr->image && damage_type == DAMAGE_ATTACK)
934                                 hit_from = _("何か", "something");
935
936                         sprintf(tmp, _("%sによってピンチに陥った。", "A critical situation because of %s."), hit_from);
937                         do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp);
938                 }
939
940                 if (auto_more)
941                 {
942                         /* stop auto_more even if DAMAGE_USELIFE */
943                         p_ptr->now_damaged = TRUE;
944                 }
945
946                 msg_print(_("*** 警告:低ヒット・ポイント! ***", "*** LOW HITPOINT WARNING! ***"));
947                 msg_print(NULL);
948                 flush();
949         }
950         if (p_ptr->wild_mode && !p_ptr->leaving && (p_ptr->chp < MAX(warning, p_ptr->mhp / 5)))
951         {
952                 change_wild_mode(FALSE);
953         }
954         return damage;
955 }