OSDN Git Service

光速移動の状態で広域マップに入ると効果が切れるように修正。
[hengband/hengband.git] / src / effects.c
index 8d21baf..1c7f939 100644 (file)
@@ -1,26 +1,28 @@
 /* File: effects.c */
 
-/* Purpose: effects of various "objects" */
-
 /*
- * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
+ * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
  *
- * This software may be copied and distributed for educational, research, and
- * not for profit purposes provided that this copyright and statement are
- * included in all such copies.
+ * This software may be copied and distributed for educational, research,
+ * and not for profit purposes provided that this copyright and statement
+ * are included in all such copies.  Other copyrights may also apply.
  */
 
+/* Purpose: effects of various "objects" */
+
 #include "angband.h"
 
 void set_action(int typ)
 {
-       if (typ == p_ptr->action)
+       int prev_typ = p_ptr->action;
+
+       if (typ == prev_typ)
        {
                return;
        }
        else
        {
-               switch(p_ptr->action)
+               switch (prev_typ)
                {
                        case ACTION_SEARCH:
                        {
@@ -87,12 +89,24 @@ void set_action(int typ)
 #endif
                                break;
                        }
+                       case ACTION_SPELL:
+                       {
+#ifdef JP
+                               msg_print("¼öʸ¤Î±Ó¾§¤òÃæÃǤ·¤¿¡£");
+#else
+                               msg_print("You stopped spelling all spells.");
+#endif
+                               break;
+                       }
                }
        }
 
        p_ptr->action = typ;
 
-       switch(p_ptr->action)
+       /* If we are requested other action, stop singing */
+       if (prev_typ == ACTION_SING) stop_singing();
+
+       switch (p_ptr->action)
        {
                case ACTION_SEARCH:
                {
@@ -171,11 +185,13 @@ void reset_tim_flags(void)
        p_ptr->tim_regen = 0;       /* Timed -- Regeneration */
        p_ptr->tim_stealth = 0;     /* Timed -- Stealth */
        p_ptr->tim_esp = 0;
-       p_ptr->tim_ffall = 0;
+       p_ptr->wraith_form = 0;     /* Timed -- Wraith Form */
+       p_ptr->tim_levitation = 0;
        p_ptr->tim_sh_touki = 0;
        p_ptr->tim_sh_fire = 0;
        p_ptr->tim_sh_holy = 0;
        p_ptr->tim_eyeeye = 0;
+       p_ptr->magicdef = 0;
        p_ptr->resist_magic = 0;
        p_ptr->tsuyoshi = 0;
        p_ptr->kabenuke = 0;
@@ -195,8 +211,8 @@ void reset_tim_flags(void)
        p_ptr->oppose_cold = 0;     /* Timed -- oppose cold */
        p_ptr->oppose_pois = 0;     /* Timed -- oppose poison */
 
-       p_ptr->word_recall = FALSE;
-       p_ptr->alter_reality = FALSE;
+       p_ptr->word_recall = 0;
+       p_ptr->alter_reality = 0;
        p_ptr->sutemi = FALSE;
        p_ptr->counter = FALSE;
        p_ptr->ele_attack = 0;
@@ -213,9 +229,9 @@ void reset_tim_flags(void)
 
        if (p_ptr->riding)
        {
-               m_list[p_ptr->riding].fast = 0;
-               m_list[p_ptr->riding].slow = 0;
-               m_list[p_ptr->riding].invulner = 0;
+               (void)set_monster_fast(p_ptr->riding, 0);
+               (void)set_monster_slow(p_ptr->riding, 0);
+               (void)set_monster_invulner(p_ptr->riding, 0, FALSE);
        }
 
        if (p_ptr->pclass == CLASS_BARD)
@@ -226,6 +242,93 @@ void reset_tim_flags(void)
 }
 
 
+void dispel_player(void)
+{
+       (void)set_fast(0, TRUE);
+       (void)set_lightspeed(0, TRUE);
+       (void)set_slow(0, TRUE);
+       (void)set_shield(0, TRUE);
+       (void)set_blessed(0, TRUE);
+       (void)set_tsuyoshi(0, TRUE);
+       (void)set_hero(0, TRUE);
+       (void)set_shero(0, TRUE);
+       (void)set_protevil(0, TRUE);
+       (void)set_invuln(0, TRUE);
+       (void)set_wraith_form(0, TRUE);
+       (void)set_kabenuke(0, TRUE);
+       (void)set_tim_res_nether(0, TRUE);
+       (void)set_tim_res_time(0, TRUE);
+       /* by henkma */
+       (void)set_tim_reflect(0,TRUE);
+       (void)set_multishadow(0,TRUE);
+       (void)set_dustrobe(0,TRUE);
+
+       (void)set_tim_invis(0, TRUE);
+       (void)set_tim_infra(0, TRUE);
+       (void)set_tim_esp(0, TRUE);
+       (void)set_tim_regen(0, TRUE);
+       (void)set_tim_stealth(0, TRUE);
+       (void)set_tim_levitation(0, TRUE);
+       (void)set_tim_sh_touki(0, TRUE);
+       (void)set_tim_sh_fire(0, TRUE);
+       (void)set_tim_sh_holy(0, TRUE);
+       (void)set_tim_eyeeye(0, TRUE);
+       (void)set_magicdef(0, TRUE);
+       (void)set_resist_magic(0, TRUE);
+       (void)set_oppose_acid(0, TRUE);
+       (void)set_oppose_elec(0, TRUE);
+       (void)set_oppose_fire(0, TRUE);
+       (void)set_oppose_cold(0, TRUE);
+       (void)set_oppose_pois(0, TRUE);
+       (void)set_ultimate_res(0, TRUE);
+       (void)set_mimic(0, 0, TRUE);
+       (void)set_ele_attack(0, 0);
+       (void)set_ele_immune(0, 0);
+
+       /* Cancel glowing hands */
+       if (p_ptr->special_attack & ATTACK_CONFUSE)
+       {
+               p_ptr->special_attack &= ~(ATTACK_CONFUSE);
+#ifdef JP
+               msg_print("¼ê¤Îµ±¤­¤¬¤Ê¤¯¤Ê¤Ã¤¿¡£");
+#else
+               msg_print("Your hands stop glowing.");
+#endif
+       }
+
+       if (music_singing_any() || hex_spelling_any())
+       {
+#ifdef JP
+               cptr str = (music_singing_any()) ? "²Î" : "¼öʸ";
+#else
+               cptr str = (music_singing_any()) ? "singing" : "spelling";
+#endif
+               p_ptr->magic_num1[1] = p_ptr->magic_num1[0];
+               p_ptr->magic_num1[0] = 0;
+#ifdef JP
+               msg_format("%s¤¬ÅÓÀڤ줿¡£", str);
+#else
+               msg_format("Your %s is interrupted.", str);
+#endif
+               p_ptr->action = ACTION_NONE;
+
+               /* Recalculate bonuses */
+               p_ptr->update |= (PU_BONUS | PU_HP);
+
+               /* Redraw map */
+               p_ptr->redraw |= (PR_MAP | PR_STATUS | PR_STATE);
+
+               /* Update monsters */
+               p_ptr->update |= (PU_MONSTERS);
+
+               /* Window stuff */
+               p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
+
+               p_ptr->energy_need += ENERGY_NEED();
+       }
+}
+
+
 /*
  * Set "p_ptr->tim_mimic", and "p_ptr->mimic_form",
  * notice observable changes
@@ -381,7 +484,7 @@ msg_print("
        if (disturb_state) disturb(0, 0);
 
        /* Fully update the visuals */
-       p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_MONSTERS);
+       p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_MONSTERS | PU_MON_LITE);
 
        /* Redraw map */
        p_ptr->redraw |= (PR_MAP);
@@ -459,6 +562,12 @@ msg_print("
                                p_ptr->action = ACTION_NONE;
                        }
 
+                       /* Sniper */
+                       if (p_ptr->concent) reset_concentration(TRUE);
+
+                       /* Hex */
+                       if (hex_spelling_any()) stop_hex_spell_all();
+
                        notice = TRUE;
                        p_ptr->counter = FALSE;
                        chg_virtue(V_HARMONY, -1);
@@ -665,6 +774,12 @@ msg_print("
                        msg_print("You are paralyzed!");
 #endif
 
+                       /* Sniper */
+                       if (p_ptr->concent) reset_concentration(TRUE);
+
+                       /* Hex */
+                       if (hex_spelling_any()) stop_hex_spell_all();
+
                        p_ptr->counter = FALSE;
                        notice = TRUE;
                }
@@ -735,6 +850,9 @@ msg_print("
                        msg_print("Oh, wow! Everything looks so cosmic now!");
 #endif
 
+                       /* Sniper */
+                       if (p_ptr->concent) reset_concentration(TRUE);
+
                        p_ptr->counter = FALSE;
                        notice = TRUE;
                }
@@ -770,6 +888,9 @@ msg_print("
        /* Redraw map */
        p_ptr->redraw |= (PR_MAP);
 
+       /* Update the health bar */
+       p_ptr->redraw |= (PR_HEALTH | PR_UHEALTH);
+
        /* Update monsters */
        p_ptr->update |= (PU_MONSTERS);
 
@@ -803,7 +924,7 @@ bool set_fast(int v, bool do_dec)
                {
                        if (p_ptr->fast > v) return FALSE;
                }
-               else if (!p_ptr->fast && !p_ptr->lightspeed)
+               else if (!IS_FAST() && !p_ptr->lightspeed)
                {
 #ifdef JP
 msg_print("ÁÇÁ᤯ư¤±¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¡ª");
@@ -820,7 +941,7 @@ msg_print("
        /* Shut */
        else
        {
-               if (p_ptr->fast && !p_ptr->lightspeed && ((p_ptr->pclass != CLASS_BARD) || ((p_ptr->magic_num1[0] != MUSIC_SPEED) && (p_ptr->magic_num1[0] != MUSIC_SHERO))))
+               if (p_ptr->fast && !p_ptr->lightspeed && !music_singing(MUSIC_SPEED) && !music_singing(MUSIC_SHERO))
                {
 #ifdef JP
 msg_print("Æ°¤­¤ÎÁÇÁᤵ¤¬¤Ê¤¯¤Ê¤Ã¤¿¤è¤¦¤À¡£");
@@ -864,6 +985,8 @@ bool set_lightspeed(int v, bool do_dec)
 
        if (p_ptr->is_dead) return FALSE;
 
+       if (p_ptr->wild_mode) v = 0;
+
        /* Open */
        if (v)
        {
@@ -1215,7 +1338,7 @@ bool set_blessed(int v, bool do_dec)
                {
                        if (p_ptr->blessed > v) return FALSE;
                }
-               else if (!p_ptr->blessed)
+               else if (!IS_BLESSED())
                {
 #ifdef JP
 msg_print("¹â·é¤Êµ¤Ê¬¤Ë¤Ê¤Ã¤¿¡ª");
@@ -1230,7 +1353,7 @@ msg_print("
        /* Shut */
        else
        {
-               if (p_ptr->blessed && ((p_ptr->pclass != CLASS_BARD) || (p_ptr->magic_num1[0] != MUSIC_BLESS)))
+               if (p_ptr->blessed && !music_singing(MUSIC_BLESS))
                {
 #ifdef JP
 msg_print("¹â·é¤Êµ¤Ê¬¤¬¾Ã¤¨¼º¤»¤¿¡£");
@@ -1284,7 +1407,7 @@ bool set_hero(int v, bool do_dec)
                {
                        if (p_ptr->hero > v) return FALSE;
                }
-               else if (!p_ptr->hero)
+               else if (!IS_HERO())
                {
 #ifdef JP
 msg_print("¥Ò¡¼¥í¡¼¤Ë¤Ê¤Ã¤¿µ¤¤¬¤¹¤ë¡ª");
@@ -1299,7 +1422,7 @@ msg_print("
        /* Shut */
        else
        {
-               if (p_ptr->hero && ((p_ptr->pclass != CLASS_BARD) || ((p_ptr->magic_num1[0] != MUSIC_HERO) && (p_ptr->magic_num1[0] != MUSIC_SHERO))))
+               if (p_ptr->hero && !music_singing(MUSIC_HERO) && !music_singing(MUSIC_SHERO))
                {
 #ifdef JP
 msg_print("¥Ò¡¼¥í¡¼¤Îµ¤Ê¬¤¬¾Ã¤¨¼º¤»¤¿¡£");
@@ -1559,9 +1682,6 @@ msg_print("
        /* Recalculate bonuses */
        p_ptr->update |= (PU_BONUS);
 
-
-
-
        /* Handle stuff */
        handle_stuff();
 
@@ -1590,7 +1710,7 @@ bool set_invuln(int v, bool do_dec)
                {
                        if (p_ptr->invuln > v) return FALSE;
                }
-               else if (!p_ptr->invuln)
+               else if (!IS_INVULN())
                {
 #ifdef JP
 msg_print("̵Ũ¤À¡ª");
@@ -1619,7 +1739,7 @@ msg_print("̵Ũ
        /* Shut */
        else
        {
-               if (p_ptr->invuln && ((p_ptr->pclass != CLASS_BARD) || (p_ptr->magic_num1[0] != MUSIC_INVULN)))
+               if (p_ptr->invuln && !music_singing(MUSIC_INVULN))
                {
 #ifdef JP
 msg_print("̵Ũ¤Ç¤Ï¤Ê¤¯¤Ê¤Ã¤¿¡£");
@@ -1684,7 +1804,7 @@ bool set_tim_esp(int v, bool do_dec)
                {
                        if (p_ptr->tim_esp > v) return FALSE;
                }
-               else if (!p_ptr->tim_esp)
+               else if (!IS_TIM_ESP())
                {
 #ifdef JP
 msg_print("°Õ¼±¤¬¹­¤¬¤Ã¤¿µ¤¤¬¤¹¤ë¡ª");
@@ -1699,7 +1819,7 @@ msg_print("
        /* Shut */
        else
        {
-               if (p_ptr->tim_esp && ((p_ptr->pclass != CLASS_BARD) || (p_ptr->magic_num1[0] != MUSIC_MIND)))
+               if (p_ptr->tim_esp && !music_singing(MUSIC_MIND))
                {
 #ifdef JP
 msg_print("°Õ¼±¤Ï¸µ¤ËÌá¤Ã¤¿¡£");
@@ -1969,7 +2089,7 @@ bool set_tim_stealth(int v, bool do_dec)
                {
                        if (p_ptr->tim_stealth > v) return FALSE;
                }
-               else if (!p_ptr->tim_stealth)
+               else if (!IS_TIM_STEALTH())
                {
 #ifdef JP
 msg_print("­²»¤¬¾®¤µ¤¯¤Ê¤Ã¤¿¡ª");
@@ -1984,7 +2104,7 @@ msg_print("­
        /* Shut */
        else
        {
-               if (p_ptr->tim_stealth && ((p_ptr->pclass != CLASS_BARD) || (p_ptr->magic_num1[0] != MUSIC_STEALTH)))
+               if (p_ptr->tim_stealth && !music_singing(MUSIC_STEALTH))
                {
 #ifdef JP
 msg_print("­²»¤¬Â礭¤¯¤Ê¤Ã¤¿¡£");
@@ -2089,9 +2209,9 @@ bool set_superstealth(bool set)
 
 
 /*
- * Set "p_ptr->tim_ffall", notice observable changes
+ * Set "p_ptr->tim_levitation", notice observable changes
  */
-bool set_tim_ffall(int v, bool do_dec)
+bool set_tim_levitation(int v, bool do_dec)
 {
        bool notice = FALSE;
 
@@ -2103,11 +2223,11 @@ bool set_tim_ffall(int v, bool do_dec)
        /* Open */
        if (v)
        {
-               if (p_ptr->tim_ffall && !do_dec)
+               if (p_ptr->tim_levitation && !do_dec)
                {
-                       if (p_ptr->tim_ffall > v) return FALSE;
+                       if (p_ptr->tim_levitation > v) return FALSE;
                }
-               else if (!p_ptr->tim_ffall)
+               else if (!p_ptr->tim_levitation)
                {
 #ifdef JP
 msg_print("ÂΤ¬Ãè¤ËÉ⤭»Ï¤á¤¿¡£");
@@ -2122,7 +2242,7 @@ msg_print("
        /* Shut */
        else
        {
-               if (p_ptr->tim_ffall)
+               if (p_ptr->tim_levitation)
                {
 #ifdef JP
 msg_print("¤â¤¦Ãè¤ËÉ⤫¤Ù¤Ê¤¯¤Ê¤Ã¤¿¡£");
@@ -2135,7 +2255,7 @@ msg_print("
        }
 
        /* Use the value */
-       p_ptr->tim_ffall = v;
+       p_ptr->tim_levitation = v;
 
        /* Redraw status bar */
        p_ptr->redraw |= (PR_STATUS);
@@ -2766,6 +2886,9 @@ msg_print("
        /* Disturb */
        if (disturb_state) disturb(0, 0);
 
+       /* Recalculate bonuses */
+       p_ptr->update |= (PU_BONUS);
+
        /* Handle stuff */
        handle_stuff();
 
@@ -3065,7 +3188,7 @@ bool set_oppose_acid(int v, bool do_dec)
                {
                        if (p_ptr->oppose_acid > v) return FALSE;
                }
-               else if (!p_ptr->oppose_acid)
+               else if (!IS_OPPOSE_ACID())
                {
 #ifdef JP
 msg_print("»À¤Ø¤ÎÂÑÀ­¤¬¤Ä¤¤¤¿µ¤¤¬¤¹¤ë¡ª");
@@ -3080,7 +3203,7 @@ msg_print("
        /* Shut */
        else
        {
-               if (p_ptr->oppose_acid && ((p_ptr->pclass != CLASS_BARD) || (p_ptr->magic_num1[0] != MUSIC_RESIST)) && !(p_ptr->special_defense & KATA_MUSOU))
+               if (p_ptr->oppose_acid && !music_singing(MUSIC_RESIST) && !(p_ptr->special_defense & KATA_MUSOU))
                {
 #ifdef JP
 msg_print("»À¤Ø¤ÎÂÑÀ­¤¬Çö¤ì¤¿µ¤¤¬¤¹¤ë¡£");
@@ -3131,7 +3254,7 @@ bool set_oppose_elec(int v, bool do_dec)
                {
                        if (p_ptr->oppose_elec > v) return FALSE;
                }
-               else if (!p_ptr->oppose_elec)
+               else if (!IS_OPPOSE_ELEC())
                {
 #ifdef JP
 msg_print("ÅÅ·â¤Ø¤ÎÂÑÀ­¤¬¤Ä¤¤¤¿µ¤¤¬¤¹¤ë¡ª");
@@ -3146,7 +3269,7 @@ msg_print("
        /* Shut */
        else
        {
-               if (p_ptr->oppose_elec && ((p_ptr->pclass != CLASS_BARD) || (p_ptr->magic_num1[0] != MUSIC_RESIST)) && !(p_ptr->special_defense & KATA_MUSOU))
+               if (p_ptr->oppose_elec && !music_singing(MUSIC_RESIST) && !(p_ptr->special_defense & KATA_MUSOU))
                {
 #ifdef JP
 msg_print("ÅÅ·â¤Ø¤ÎÂÑÀ­¤¬Çö¤ì¤¿µ¤¤¬¤¹¤ë¡£");
@@ -3198,7 +3321,7 @@ bool set_oppose_fire(int v, bool do_dec)
                {
                        if (p_ptr->oppose_fire > v) return FALSE;
                }
-               else if (!p_ptr->oppose_fire)
+               else if (!IS_OPPOSE_FIRE())
                {
 #ifdef JP
 msg_print("²Ð¤Ø¤ÎÂÑÀ­¤¬¤Ä¤¤¤¿µ¤¤¬¤¹¤ë¡ª");
@@ -3213,7 +3336,7 @@ msg_print("
        /* Shut */
        else
        {
-               if (p_ptr->oppose_fire && ((p_ptr->pclass != CLASS_BARD) || (p_ptr->magic_num1[0] != MUSIC_RESIST)) && !(p_ptr->special_defense & KATA_MUSOU))
+               if (p_ptr->oppose_fire && !music_singing(MUSIC_RESIST) && !(p_ptr->special_defense & KATA_MUSOU))
                {
 #ifdef JP
 msg_print("²Ð¤Ø¤ÎÂÑÀ­¤¬Çö¤ì¤¿µ¤¤¬¤¹¤ë¡£");
@@ -3264,7 +3387,7 @@ bool set_oppose_cold(int v, bool do_dec)
                {
                        if (p_ptr->oppose_cold > v) return FALSE;
                }
-               else if (!p_ptr->oppose_cold)
+               else if (!IS_OPPOSE_COLD())
                {
 #ifdef JP
 msg_print("Î䵤¤Ø¤ÎÂÑÀ­¤¬¤Ä¤¤¤¿µ¤¤¬¤¹¤ë¡ª");
@@ -3279,7 +3402,7 @@ msg_print("
        /* Shut */
        else
        {
-               if (p_ptr->oppose_cold && ((p_ptr->pclass != CLASS_BARD) || (p_ptr->magic_num1[0] != MUSIC_RESIST)) && !(p_ptr->special_defense & KATA_MUSOU))
+               if (p_ptr->oppose_cold && !music_singing(MUSIC_RESIST) && !(p_ptr->special_defense & KATA_MUSOU))
                {
 #ifdef JP
 msg_print("Î䵤¤Ø¤ÎÂÑÀ­¤¬Çö¤ì¤¿µ¤¤¬¤¹¤ë¡£");
@@ -3331,7 +3454,7 @@ bool set_oppose_pois(int v, bool do_dec)
                {
                        if (p_ptr->oppose_pois > v) return FALSE;
                }
-               else if (!p_ptr->oppose_pois)
+               else if (!IS_OPPOSE_POIS())
                {
 #ifdef JP
 msg_print("ÆǤؤÎÂÑÀ­¤¬¤Ä¤¤¤¿µ¤¤¬¤¹¤ë¡ª");
@@ -3346,7 +3469,7 @@ msg_print("
        /* Shut */
        else
        {
-               if (p_ptr->oppose_pois && ((p_ptr->pclass != CLASS_BARD) || (p_ptr->magic_num1[0] != MUSIC_RESIST)) && !(p_ptr->special_defense & KATA_MUSOU))
+               if (p_ptr->oppose_pois && !music_singing(MUSIC_RESIST) && !(p_ptr->special_defense & KATA_MUSOU))
                {
 #ifdef JP
 msg_print("ÆǤؤÎÂÑÀ­¤¬Çö¤ì¤¿µ¤¤¬¤¹¤ë¡£");
@@ -3518,6 +3641,12 @@ msg_print("
                        p_ptr->action = ACTION_NONE;
                }
 
+               /* Sniper */
+               if (p_ptr->concent) reset_concentration(TRUE);
+
+               /* Hex */
+               if (hex_spelling_any()) stop_hex_spell_all();
+
                /* Notice */
                notice = TRUE;
        }
@@ -4061,9 +4190,6 @@ msg_print("
 
                if (p_ptr->wild_mode && (new_aux < 2))
                {
-                       p_ptr->wilderness_x = px;
-                       p_ptr->wilderness_y = py;
-                       p_ptr->energy_need = 0;
                        change_wild_mode();
                }
 
@@ -4720,6 +4846,71 @@ take_hit(DAMAGE_LOSELIFE, change / 2, "
 }
 
 
+/*
+ * Change player race
+ */
+void change_race(int new_race, cptr effect_msg)
+{
+       cptr title = race_info[new_race].title;
+       int  old_race = p_ptr->prace;
+
+#ifdef JP
+       msg_format("¤¢¤Ê¤¿¤Ï%s%s¤ËÊѲ½¤·¤¿¡ª", effect_msg, title);
+#else
+       msg_format("You turn into %s %s%s!", (!effect_msg[0] && is_a_vowel(title[0]) ? "an" : "a"), effect_msg, title);
+#endif
+
+       chg_virtue(V_CHANCE, 2);
+
+       if (p_ptr->prace < 32)
+       {
+               p_ptr->old_race1 |= 1L << p_ptr->prace;
+       }
+       else
+       {
+               p_ptr->old_race2 |= 1L << (p_ptr->prace-32);
+       }
+       p_ptr->prace = new_race;
+       rp_ptr = &race_info[p_ptr->prace];
+
+       /* Experience factor */
+       p_ptr->expfact = rp_ptr->r_exp + cp_ptr->c_exp;
+
+       /*
+        * The speed bonus of Klackons and Sprites are disabled
+        * and the experience penalty is decreased.
+        */
+       if (((p_ptr->pclass == CLASS_MONK) || (p_ptr->pclass == CLASS_FORCETRAINER) || (p_ptr->pclass == CLASS_NINJA)) && ((p_ptr->prace == RACE_KLACKON) || (p_ptr->prace == RACE_SPRITE)))
+               p_ptr->expfact -= 15;
+
+       /* Get character's height and weight */
+       get_height_weight();
+
+       /* Hitdice */
+       if (p_ptr->pclass == CLASS_SORCERER)
+               p_ptr->hitdie = rp_ptr->r_mhp/2 + cp_ptr->c_mhp + ap_ptr->a_mhp;
+       else
+               p_ptr->hitdie = rp_ptr->r_mhp + cp_ptr->c_mhp + ap_ptr->a_mhp;
+
+       do_cmd_rerate(FALSE);
+
+       /* The experience level may be modified */
+       check_experience();
+
+       p_ptr->redraw |= (PR_BASIC);
+
+       p_ptr->update |= (PU_BONUS);
+
+       handle_stuff();
+
+       /* Load an autopick preference file */
+       if (old_race != p_ptr->prace) autopick_load_pref(FALSE);
+
+       /* Player's graphic tile may change */
+       lite_spot(py, px);
+}
+
+
 void do_poly_self(void)
 {
        int power = p_ptr->lev;
@@ -4735,7 +4926,7 @@ msg_print("
        if ((power > randint0(20)) && one_in_(3) && (p_ptr->prace != RACE_ANDROID))
        {
                char effect_msg[80] = "";
-               int new_race, expfact, goalexpfact, h_percent;
+               int new_race, expfact, goalexpfact;
 
                /* Some form of racial polymorph... */
                power -= 10;
@@ -4842,78 +5033,7 @@ msg_print("
                }
                while (((new_race == p_ptr->prace) && (expfact > goalexpfact)) || (new_race == RACE_ANDROID));
 
-#ifdef JP
-               msg_format("¤¢¤Ê¤¿¤Ï%s%s¤ËÊѲ½¤·¤¿¡ª", effect_msg,
-                               race_info[new_race].title);
-#else
-               if (effect_msg[0])
-               {
-                       msg_format("You turn into a%s %s!",
-                               ((new_race == RACE_AMBERITE || new_race == RACE_ELF
-                               || new_race == RACE_IMP) ? "n" : ""),
-                               race_info[new_race].title);
-               }
-               else
-               {
-                       msg_format("You turn into a %s%s!", effect_msg,
-                               race_info[new_race].title);
-               }
-#endif
-
-               chg_virtue(V_CHANCE, 2);
-
-               if (p_ptr->prace < 32)
-               {
-                       p_ptr->old_race1 |= 1L << p_ptr->prace;
-               }
-               else
-               {
-                       p_ptr->old_race2 = 1L << (p_ptr->prace-32);
-               }
-               p_ptr->prace = new_race;
-               rp_ptr = &race_info[p_ptr->prace];
-
-               /* Experience factor */
-               p_ptr->expfact = rp_ptr->r_exp + cp_ptr->c_exp;
-
-               if (((p_ptr->pclass == CLASS_MONK) || (p_ptr->pclass == CLASS_FORCETRAINER) || (p_ptr->pclass == CLASS_NINJA)) && ((p_ptr->prace == RACE_KLACKON) || (p_ptr->prace == RACE_SPRITE)))
-                       p_ptr->expfact -= 15;
-
-
-               /* Calculate the height/weight for males */
-               if (p_ptr->psex == SEX_MALE)
-               {
-                       p_ptr->ht = randnor(rp_ptr->m_b_ht, rp_ptr->m_m_ht);
-                       h_percent = (int)(p_ptr->ht) * 100 / (int)(rp_ptr->m_b_ht);
-                       p_ptr->wt = randnor((int)(rp_ptr->m_b_wt) * h_percent /100
-                                           , (int)(rp_ptr->m_m_wt) * h_percent / 300 );
-               }
-
-               /* Calculate the height/weight for females */
-               else if (p_ptr->psex == SEX_FEMALE)
-               {
-                       p_ptr->ht = randnor(rp_ptr->f_b_ht, rp_ptr->f_m_ht);
-                       h_percent = (int)(p_ptr->ht) * 100 / (int)(rp_ptr->f_b_ht);
-                       p_ptr->wt = randnor((int)(rp_ptr->f_b_wt) * h_percent /100
-                                           , (int)(rp_ptr->f_m_wt) * h_percent / 300 );
-               }
-
-               check_experience();
-
-               /* Hitdice */
-               if (p_ptr->pclass == CLASS_SORCERER)
-                       p_ptr->hitdie = rp_ptr->r_mhp/2 + cp_ptr->c_mhp + ap_ptr->a_mhp;
-               else
-                       p_ptr->hitdie = rp_ptr->r_mhp + cp_ptr->c_mhp + ap_ptr->a_mhp;
-
-               do_cmd_rerate(FALSE);
-
-               p_ptr->redraw |= (PR_BASIC);
-
-               p_ptr->update |= (PU_BONUS);
-
-               handle_stuff();
-               lite_spot(py, px);
+               change_race(new_race, effect_msg);
        }
 
        if ((power > randint0(30)) && one_in_(6))
@@ -4937,8 +5057,8 @@ msg_format("%s
                if (one_in_(6))
                {
 #ifdef JP
-msg_print("¸½ºß»Ñ¤ÇÀ¸¤­¤Æ¤¤¤¯¤Î¤Ïº¤Æñ¤Ê¤è¤¦¤À¡ª");
-take_hit(DAMAGE_LOSELIFE, damroll(randint1(10), p_ptr->lev), "Ã×̿Ū¤ÊÆÍÁ³ÊÑ°Û", -1);
+                       msg_print("¸½ºß¤Î»Ñ¤ÇÀ¸¤­¤Æ¤¤¤¯¤Î¤Ïº¤Æñ¤Ê¤è¤¦¤À¡ª");
+                       take_hit(DAMAGE_LOSELIFE, damroll(randint1(10), p_ptr->lev), "Ã×̿Ū¤ÊÆÍÁ³ÊÑ°Û", -1);
 #else
                        msg_print("You find living difficult in your present form!");
                        take_hit(DAMAGE_LOSELIFE, damroll(randint1(10), p_ptr->lev), "a lethal mutation", -1);
@@ -4986,6 +5106,7 @@ take_hit(DAMAGE_LOSELIFE, damroll(randint1(10), p_ptr->lev), "
  * the game when he dies, since the "You die." message is shown before
  * setting the player to "dead".
  */
+
 int take_hit(int damage_type, int damage, cptr hit_from, int monspell)
 {
        int old_chp = p_ptr->chp;
@@ -5018,7 +5139,7 @@ int take_hit(int damage_type, int damage, cptr hit_from, int monspell)
        /* Mega-Hack -- Apply "invulnerability" */
        if ((damage_type != DAMAGE_USELIFE) && (damage_type != DAMAGE_LOSELIFE))
        {
-               if ((p_ptr->invuln || ((p_ptr->pclass == CLASS_BARD) && (p_ptr->magic_num1[0] == MUSIC_INVULN))) && (damage < 9000))
+               if (IS_INVULN() && (damage < 9000))
                {
                        if (damage_type == DAMAGE_FORCE)
                        {
@@ -5041,9 +5162,8 @@ int take_hit(int damage_type, int damage, cptr hit_from, int monspell)
                                return 0;
                        }
                }
-               /* Multishadow effects is determined by turn */
-               if (p_ptr->multishadow && (turn & 1))
+
+               if (CHECK_MULTISHADOW())
                {
                        if (damage_type == DAMAGE_FORCE)
                        {
@@ -5063,7 +5183,7 @@ int take_hit(int damage_type, int damage, cptr hit_from, int monspell)
                                return 0;
                        }
                }
-                   
+
                if (p_ptr->wraith_form)
                {
                        if (damage_type == DAMAGE_FORCE)
@@ -5081,7 +5201,7 @@ int take_hit(int damage_type, int damage, cptr hit_from, int monspell)
                        }
                }
 
-               if ((p_ptr->special_defense & KATA_MUSOU))
+               if (p_ptr->special_defense & KATA_MUSOU)
                {
                        damage /= 2;
                        if ((damage == 0) && one_in_(2)) damage = 1;
@@ -5113,7 +5233,6 @@ int take_hit(int damage_type, int damage, cptr hit_from, int monspell)
        /* Dead player */
        if (p_ptr->chp < 0)
        {
-               char buf[10];
                bool android = (p_ptr->prace == RACE_ANDROID ? TRUE : FALSE);
 
 #ifdef JP       /* »à¤ó¤À»þ¤Ë¶¯À©½ªÎ»¤·¤Æ»à¤ò²óÈò¤Ç¤­¤Ê¤¯¤·¤Æ¤ß¤¿ by Habu */
@@ -5134,62 +5253,94 @@ int take_hit(int damage_type, int damage, cptr hit_from, int monspell)
 
                if (p_ptr->inside_arena)
                {
-                       cptr m_name = r_name+r_info[arena_monsters[p_ptr->arena_number]].name;
+                       cptr m_name = r_name+r_info[arena_info[p_ptr->arena_number].r_idx].name;
 #ifdef JP
                        msg_format("¤¢¤Ê¤¿¤Ï%s¤ÎÁ°¤ËÇÔ¤ìµî¤Ã¤¿¡£", m_name);
 #else
                        msg_format("You are beaten by %s.", m_name);
 #endif
                        msg_print(NULL);
-                       if (record_arena) do_cmd_write_nikki(NIKKI_ARENA, 99, m_name);
+                       if (record_arena) do_cmd_write_nikki(NIKKI_ARENA, -1 - p_ptr->arena_number, m_name);
                }
                else
                {
+                       int q_idx = quest_number(dun_level);
+                       bool seppuku = streq(hit_from, "Seppuku");
+                       bool winning_seppuku = p_ptr->total_winner && seppuku;
+
 #ifdef WORLD_SCORE
                        /* Make screen dump */
                        screen_dump = make_screen_dump();
 #endif
 
                        /* Note cause of death */
+                       if (seppuku)
+                       {
+                               strcpy(p_ptr->died_from, hit_from);
+#ifdef JP
+                               if (!winning_seppuku) strcpy(p_ptr->died_from, "ÀÚÊ¢");
+#endif
+                       }
+                       else
+                       {
+                               char dummy[1024];
 #ifdef JP
-                       sprintf(p_ptr->died_from, "%s%s%s", !p_ptr->paralyzed ? "" : p_ptr->free_act ? "ĦÁü¾õÂÖ¤Ç":"Ëãáã¾õÂÖ¤Ç", p_ptr->image ? "¸¸³Ð¤ËÏĤó¤À" : "", hit_from);
+                               sprintf(dummy, "%s%s%s", !p_ptr->paralyzed ? "" : p_ptr->free_act ? "ĦÁü¾õÂÖ¤Ç" : "Ëãáã¾õÂÖ¤Ç", p_ptr->image ? "¸¸³Ð¤ËÏĤó¤À" : "", hit_from);
 #else
-                       sprintf(p_ptr->died_from, "%s%s", hit_from, !p_ptr->paralyzed ? "" : " while helpless");
+                               sprintf(dummy, "%s%s", hit_from, !p_ptr->paralyzed ? "" : " while helpless");
 #endif
+                               my_strcpy(p_ptr->died_from, dummy, sizeof p_ptr->died_from);
+                       }
 
                        /* No longer a winner */
                        p_ptr->total_winner = FALSE;
 
-                       if (p_ptr->inside_arena)
+                       if (winning_seppuku)
+                       {
 #ifdef JP
-                               strcpy(buf,"¥¢¥ê¡¼¥Ê");
+                               do_cmd_write_nikki(NIKKI_BUNSHOU, 0, "¾¡Íø¤Î¸åÀÚÊ¢¤·¤¿¡£");
 #else
-                               strcpy(buf,"in the Arena");
+                               do_cmd_write_nikki(NIKKI_BUNSHOU, 0, "did Seppuku after the winning.");
 #endif
-                       else if (!dun_level)
+                       }
+                       else
+                       {
+                               char buf[10];
+
+                               if (p_ptr->inside_arena)
 #ifdef JP
-                               strcpy(buf,"ÃϾå");
+                                       strcpy(buf,"¥¢¥ê¡¼¥Ê");
 #else
-                               strcpy(buf,"on the surface");
+                                       strcpy(buf,"in the Arena");
 #endif
-                       else if (quest_number(dun_level) && ((quest_number(dun_level) < MIN_RANDOM_QUEST) && !(quest_number(dun_level) == QUEST_OBERON || quest_number(dun_level) == QUEST_SERPENT)))
+                               else if (!dun_level)
 #ifdef JP
-                               strcpy(buf,"¥¯¥¨¥¹¥È");
+                                       strcpy(buf,"ÃϾå");
 #else
-                               strcpy(buf,"in a quest");
+                                       strcpy(buf,"on the surface");
 #endif
-                       else
+                               else if (q_idx && (is_fixed_quest_idx(q_idx) &&
+                                        !((q_idx == QUEST_OBERON) || (q_idx == QUEST_SERPENT))))
 #ifdef JP
-                               sprintf(buf,"%d³¬", dun_level);
+                                       strcpy(buf,"¥¯¥¨¥¹¥È");
 #else
-                               sprintf(buf,"level %d", dun_level);
+                                       strcpy(buf,"in a quest");
 #endif
+                               else
 #ifdef JP
-                       sprintf(tmp,"%s¤Ç%s¤Ë»¦¤µ¤ì¤¿¡£",buf, p_ptr->died_from);
+                                       sprintf(buf,"%d³¬", dun_level);
 #else
-                       sprintf(tmp,"killed by %s %s.", p_ptr->died_from, buf);
+                                       sprintf(buf,"level %d", dun_level);
 #endif
-                       do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp);
+
+#ifdef JP
+                               sprintf(tmp, "%s¤Ç%s¤Ë»¦¤µ¤ì¤¿¡£", buf, p_ptr->died_from);
+#else
+                               sprintf(tmp, "killed by %s %s.", p_ptr->died_from, buf);
+#endif
+                               do_cmd_write_nikki(NIKKI_BUNSHOU, 0, tmp);
+                       }
+
 #ifdef JP
                        do_cmd_write_nikki(NIKKI_GAMESTART, 1, "-------- ¥²¡¼¥à¥ª¡¼¥Ð¡¼ --------");
 #else
@@ -5200,22 +5351,25 @@ int take_hit(int damage_type, int damage, cptr hit_from, int monspell)
                        flush();
 
 #ifdef JP
-if (get_check_strict("²èÌ̤òÊݸ¤·¤Þ¤¹¤«¡©", CHECK_NO_HISTORY))
+                       if (get_check_strict("²èÌ̤òÊݸ¤·¤Þ¤¹¤«¡©", CHECK_NO_HISTORY))
 #else
                        if (get_check_strict("Dump the screen? ", CHECK_NO_HISTORY))
 #endif
-
                        {
                                do_cmd_save_screen();
                        }
 
                        flush();
 
+                       /* Initialize "last message" buffer */
+                       if (p_ptr->last_message) string_free(p_ptr->last_message);
+                       p_ptr->last_message = NULL;
+
                        /* Hack -- Note death */
                        if (!last_words)
                        {
 #ifdef JP
-msg_format("¤¢¤Ê¤¿¤Ï%s¤Þ¤·¤¿¡£", android ? "²õ¤ì" : "»à¤Ë");
+                               msg_format("¤¢¤Ê¤¿¤Ï%s¤Þ¤·¤¿¡£", android ? "²õ¤ì" : "»à¤Ë");
 #else
                                msg_print(android ? "You are broken." : "You die.");
 #endif
@@ -5224,10 +5378,10 @@ msg_format("
                        }
                        else
                        {
-                               if (streq(p_ptr->died_from, "Seppuku"))
+                               if (winning_seppuku)
                                {
 #ifdef JP
-                                 get_rnd_line("seppuku_j.txt", 0, death_message);
+                                       get_rnd_line("seppuku_j.txt", 0, death_message);
 #else
                                        get_rnd_line("seppuku.txt", 0, death_message);
 #endif
@@ -5235,16 +5389,26 @@ msg_format("
                                else
                                {
 #ifdef JP
-get_rnd_line("death_j.txt", 0, death_message);
+                                       get_rnd_line("death_j.txt", 0, death_message);
 #else
                                        get_rnd_line("death.txt", 0, death_message);
 #endif
                                }
+
+                               do
+                               {
+#ifdef JP
+                                       while (!get_string(winning_seppuku ? "¼­À¤¤Î¶ç: " : "ÃÇËöËâ¤Î¶«¤Ó: ", death_message, 1024)) ;
+#else
+                                       while (!get_string("Last word: ", death_message, 1024)) ;
+#endif
+                               }
 #ifdef JP
-                               while (!get_string(streq(p_ptr->died_from, "Seppuku") ? "¼­À¤¤Î¶ç: " : "ÃÇËöËâ¤Î¶«¤Ó: ", death_message, 1024)) ;
+                               while (winning_seppuku && !get_check_strict("¤è¤í¤·¤¤¤Ç¤¹¤«¡©", CHECK_NO_HISTORY));
 #else
-                               while (!get_string("Last word: ", death_message, 1024)) ;
+                               while (winning_seppuku && !get_check_strict("Are you sure? ", CHECK_NO_HISTORY));
 #endif
+
                                if (death_message[0] == '\0')
                                {
 #ifdef JP
@@ -5253,63 +5417,63 @@ get_rnd_line("death_j.txt", 0, death_message);
                                        strcpy(death_message, android ? "You are broken." : "You die.");
 #endif
                                }
-                               if (streq(p_ptr->died_from, "Seppuku"))
-                               {
+                               else p_ptr->last_message = string_make(death_message);
+
 #ifdef JP
-                                 int i, len;
-                                 int w = Term->wid;
-                                 int h = Term->hgt;
-                                 int msg_pos_x[9] = {  5,  7,  9, 12,  14,  17,  19,  21, 23};
-                                 int msg_pos_y[9] = {  3,  4,  5,  4,   5,   4,   5,   6,  4};
-                                 cptr str;
-                                 char* str2;
-
-                                 Term_clear();
-
-                                 /* ºù»¶¤ë */
-                                 for (i = 0; i < 40; i++) 
-                                   Term_putstr(randint0(w / 2) * 2, randint0(h), 2, TERM_VIOLET, "¦Ô");
-
-                                 str = death_message;
-                                 if (strncmp(str, "¡Ö", 2) == 0) str += 2;
-
-                                 str2 = strstr_j(str, "¡×");
-                                 if (str2 != NULL) *str2 = '\0';
-
-                                 i = 0;
-                                 while (i < 9)
-                                 {
-                                   str2 = strstr_j(str, " ");
-                                   if (str2 == NULL) len = strlen(str);
-                                   else len = str2 - str;
-
-                                   if (len != 0)
-                                   {
-                                     Term_putstr_v(w * 3 / 4 - 2 - msg_pos_x[i] * 2, msg_pos_y[i], len,
-                                                 TERM_WHITE, str);
-                                     if (str2 == NULL) break;
-                                     i++;
-                                   }
-                                   str = str2 + 1;
-                                   if (*str == 0) break;
-                                 }
-
-                                 /* Hide cursor */
-                                 Term_putstr(w-1, h-1, 1, TERM_WHITE, " ");
-
-                                 flush();
+                               if (winning_seppuku)
+                               {
+                                       int i, len;
+                                       int w = Term->wid;
+                                       int h = Term->hgt;
+                                       int msg_pos_x[9] = {  5,  7,  9, 12,  14,  17,  19,  21, 23};
+                                       int msg_pos_y[9] = {  3,  4,  5,  4,   5,   4,   5,   6,  4};
+                                       cptr str;
+                                       char* str2;
+
+                                       Term_clear();
+
+                                       /* ºù»¶¤ë */
+                                       for (i = 0; i < 40; i++)
+                                               Term_putstr(randint0(w / 2) * 2, randint0(h), 2, TERM_VIOLET, "¦Ô");
+
+                                       str = death_message;
+                                       if (strncmp(str, "¡Ö", 2) == 0) str += 2;
+
+                                       str2 = my_strstr(str, "¡×");
+                                       if (str2 != NULL) *str2 = '\0';
+
+                                       i = 0;
+                                       while (i < 9)
+                                       {
+                                               str2 = my_strstr(str, " ");
+                                               if (str2 == NULL) len = strlen(str);
+                                               else len = str2 - str;
+
+                                               if (len != 0)
+                                               {
+                                                       Term_putstr_v(w * 3 / 4 - 2 - msg_pos_x[i] * 2, msg_pos_y[i], len,
+                                                       TERM_WHITE, str);
+                                                       if (str2 == NULL) break;
+                                                       i++;
+                                               }
+                                               str = str2 + 1;
+                                               if (*str == 0) break;
+                                       }
+
+                                       /* Hide cursor */
+                                       Term_putstr(w-1, h-1, 1, TERM_WHITE, " ");
+
+                                       flush();
 #ifdef WORLD_SCORE
-                                 /* Make screen dump */
-                                 screen_dump = make_screen_dump();
+                                       /* Make screen dump */
+                                       screen_dump = make_screen_dump();
 #endif
 
-                                 /* Wait a key press */
-                                 (void)inkey();
-#else
-                                       msg_print(death_message);
-#endif
+                                       /* Wait a key press */
+                                       (void)inkey();
                                }
                                else
+#endif
                                        msg_print(death_message);
                        }
                }
@@ -5322,7 +5486,7 @@ get_rnd_line("death_j.txt", 0, death_message);
        if (p_ptr->chp < warning)
        {
                /* Hack -- bell on first notice */
-               if (alert_hitpoint && (old_chp > warning)) bell();
+               if (old_chp > warning) bell();
 
                sound(SOUND_WARN);
 
@@ -5336,7 +5500,7 @@ get_rnd_line("death_j.txt", 0, death_message);
 #endif
 
 #ifdef JP
-                       sprintf(tmp,"%s¤Ë¤è¤Ã¤Æ¥Ô¥ó¥Á¤Ë´Ù¤¤¤Ã¤¿¡£",hit_from);
+                       sprintf(tmp,"%s¤Ë¤è¤Ã¤Æ¥Ô¥ó¥Á¤Ë´Ù¤Ã¤¿¡£",hit_from);
 #else
                        sprintf(tmp,"A critical situation because of %s.",hit_from);
 #endif
@@ -5361,9 +5525,6 @@ msg_print("*** 
        }
        if (p_ptr->wild_mode && !p_ptr->leaving && (p_ptr->chp < MAX(warning, p_ptr->mhp/5)))
        {
-               p_ptr->wilderness_x = px;
-               p_ptr->wilderness_y = py;
-               p_ptr->energy_need = 0;
                change_wild_mode();
        }
        return damage;
@@ -5373,14 +5534,14 @@ msg_print("*** 
 /*
  * Gain experience
  */
-void gain_exp(s32b amount)
+void gain_exp_64(s32b amount, u32b amount_frac)
 {
        if (p_ptr->is_dead) return;
 
        if (p_ptr->prace == RACE_ANDROID) return;
 
        /* Gain some experience */
-       p_ptr->exp += amount;
+       s64b_add(&(p_ptr->exp), &(p_ptr->exp_frac), amount, amount_frac);
 
        /* Slowly recover from experience drainage */
        if (p_ptr->exp < p_ptr->max_exp)
@@ -5394,6 +5555,15 @@ void gain_exp(s32b amount)
 }
 
 
+/*
+ * Gain experience
+ */
+void gain_exp(s32b amount)
+{
+       gain_exp_64(amount, 0L);
+}
+
+
 void calc_android_exp(void)
 {
        int i;
@@ -5408,7 +5578,7 @@ void calc_android_exp(void)
                object_type forge;
                object_type *q_ptr = &forge;
                u32b value, exp;
-               int level = MAX(get_object_level(o_ptr) - 8, 1);
+               int level = MAX(k_info[o_ptr->k_idx].level - 8, 1);
 
                if ((i == INVEN_RIGHT) || (i == INVEN_LEFT) || (i == INVEN_NECK) || (i == INVEN_LITE)) continue;
                if (!o_ptr->k_idx) continue;
@@ -5420,12 +5590,38 @@ void calc_android_exp(void)
                q_ptr->discount = 0;
                q_ptr->curse_flags = 0L;
 
-               if (o_ptr->name1)
+               if (object_is_fixed_artifact(o_ptr))
                {
                        level = (level + MAX(a_info[o_ptr->name1].level - 8, 5)) / 2;
                        level += MIN(20, a_info[o_ptr->name1].rarity/(a_info[o_ptr->name1].gen_flags & TRG_INSTA_ART ? 10 : 3));
                }
-               else if (o_ptr->name2) level += MAX(3, (e_info[o_ptr->name2].rating - 5)/2);
+               else if (object_is_ego(o_ptr))
+               {
+                       level += MAX(3, (e_info[o_ptr->name2].rating - 5)/2);
+               }
+               else if (o_ptr->art_name)
+               {
+                       s32b total_flags = flag_cost(o_ptr, o_ptr->pval);
+                       int fake_level;
+
+                       if (!object_is_weapon_ammo(o_ptr))
+                       {
+                               /* For armors */
+                               if (total_flags < 15000) fake_level = 10;
+                               else if (total_flags < 35000) fake_level = 25;
+                               else fake_level = 40;
+                       }
+                       else
+                       {
+                               /* For weapons */
+                               if (total_flags < 20000) fake_level = 10;
+                               else if (total_flags < 45000) fake_level = 25;
+                               else fake_level = 40;
+                       }
+
+                       level = MAX(level, (level + MAX(fake_level - 8, 5)) / 2 + 3);
+               }
+
                value = object_value_real(q_ptr);
 
                if (value <= 0) continue;
@@ -5433,7 +5629,7 @@ void calc_android_exp(void)
                if (value > 5000000L) value = 5000000L;
                if ((o_ptr->tval == TV_DRAG_ARMOR) || (o_ptr->tval == TV_CARD)) level /= 2;
 
-               if (o_ptr->name1 || o_ptr->name2 || o_ptr->art_name ||
+               if (object_is_artifact(o_ptr) || object_is_ego(o_ptr) ||
                    (o_ptr->tval == TV_DRAG_ARMOR) ||
                    ((o_ptr->tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM)) ||
                    ((o_ptr->tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD)) ||
@@ -5482,6 +5678,51 @@ void lose_exp(s32b amount)
        check_experience();
 }
 
+
+/*
+ * Drain experience
+ * If resisted to draining, return FALSE
+ */
+bool drain_exp(s32b drain, s32b slip, int hold_life_prob)
+{
+       /* Androids and their mimics are never drained */
+       if (p_ptr->prace == RACE_ANDROID) return FALSE;
+
+       if (p_ptr->hold_life && (randint0(100) < hold_life_prob))
+       {
+               /* Hold experience */
+#ifdef JP
+               msg_print("¤·¤«¤·¼«¸Ê¤ÎÀ¸Ì¿ÎϤò¼é¤ê¤­¤Ã¤¿¡ª");
+#else
+               msg_print("You keep hold of your life force!");
+#endif
+               return FALSE;
+       }
+
+       /* Hold experience failed */
+       if (p_ptr->hold_life)
+       {
+#ifdef JP
+               msg_print("À¸Ì¿ÎϤò¾¯¤·µÛ¤¤¼è¤é¤ì¤¿µ¤¤¬¤¹¤ë¡ª");
+#else
+               msg_print("You feel your life slipping away!");
+#endif
+               lose_exp(slip);
+       }
+       else
+       {
+#ifdef JP
+               msg_print("À¸Ì¿ÎϤ¬ÂΤ«¤éµÛ¤¤¼è¤é¤ì¤¿µ¤¤¬¤¹¤ë¡ª");
+#else
+               msg_print("You feel your life draining away!");
+#endif
+               lose_exp(drain);
+       }
+
+       return TRUE;
+}
+
+
 bool set_ultimate_res(int v, bool do_dec)
 {
        bool notice = FALSE;
@@ -5687,6 +5928,16 @@ bool choose_ele_attack(void)
 
        char choice;
 
+       if (!buki_motteruka(INVEN_RARM) && !buki_motteruka(INVEN_LARM))
+       {
+#ifdef JP
+               msg_format("Éð´ï¤ò»ý¤¿¤Ê¤¤¤ÈËâË¡·õ¤Ï»È¤¨¤Ê¤¤¡£");
+#else
+               msg_format("You cannot use temporary branding with no weapon.");
+#endif
+               return FALSE;
+       }
+
        /* Save screen */
        screen_save();