#include "artifact.h"
#include "avatar.h"
#include "spells-status.h"
+#include "object-hook.h"
+#include "monsterrace-hook.h"
+#include "mutation.h"
+#include "patron.h"
+
+/* Hack, monk armour */
+static bool monk_armour_aux;
+static bool monk_notify_aux;
/*
* Return alignment title
bool old_mighty_throw = p_ptr->mighty_throw;
/* Current feature under player. */
- feature_type *f_ptr = &f_info[grid_array[p_ptr->y][p_ptr->x].feat];
+ feature_type *f_ptr = &f_info[current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].feat];
/* Save the old armor class */
ARMOUR_CLASS old_dis_ac = p_ptr->dis_ac;
/* Start with "normal" speed */
new_speed = 110;
- /* Start with a single blow per turn */
+ /* Start with a single blow per current_world_ptr->game_turn */
p_ptr->num_blow[0] = 1;
p_ptr->num_blow[1] = 1;
- /* Start with a single shot per turn */
+ /* Start with a single shot per current_world_ptr->game_turn */
p_ptr->num_fire = 100;
/* Reset the "xtra" tval */
p_ptr->hidarite = FALSE;
p_ptr->no_flowed = FALSE;
- p_ptr->align = friend_align;
+ p_ptr->align = 0;
if (p_ptr->mimic_form) tmp_rp_ptr = &mimic_info[p_ptr->mimic_form];
else tmp_rp_ptr = &race_info[p_ptr->prace];
}
else
{
- monster_type *riding_m_ptr = &m_list[p_ptr->riding];
+ monster_type *riding_m_ptr = ¤t_floor_ptr->m_list[p_ptr->riding];
monster_race *riding_r_ptr = &r_info[riding_m_ptr->r_idx];
SPEED speed = riding_m_ptr->mspeed;
}
else
{
- penalty = r_info[m_list[p_ptr->riding].r_idx].level - p_ptr->skill_exp[GINOU_RIDING] / 80;
+ penalty = r_info[current_floor_ptr->m_list[p_ptr->riding].r_idx].level - p_ptr->skill_exp[GINOU_RIDING] / 80;
penalty += 30;
if (penalty < 30) penalty = 30;
}
}
else
{
- penalty = r_info[m_list[p_ptr->riding].r_idx].level - p_ptr->skill_exp[GINOU_RIDING] / 80;
+ penalty = r_info[current_floor_ptr->m_list[p_ptr->riding].r_idx].level - p_ptr->skill_exp[GINOU_RIDING] / 80;
penalty += 30;
if (penalty < 30) penalty = 30;
}
if ((inventory[i].tval == TV_CRAFT_BOOK) && (inventory[i].sval == 2)) have_kabe = TRUE;
}
- for (this_o_idx = grid_array[p_ptr->y][p_ptr->x].o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (this_o_idx = current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].o_idx; this_o_idx; this_o_idx = next_o_idx)
{
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
+ o_ptr = ¤t_floor_ptr->o_list[this_o_idx];
next_o_idx = o_ptr->next_o_idx;
#if 0
}
/* max radius is 14 (was 5) without rewriting other code -- */
- /* see grid_array.c:update_lite() and defines.h:LITE_MAX */
+ /* see current_floor_ptr->grid_array.c:update_lite() and defines.h:LITE_MAX */
if (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS && p_ptr->cur_lite > 1)
p_ptr->cur_lite = 1;
creature_ptr->update &= ~(PU_AUTODESTROY);
autopick_delayed_alter();
}
-
- /* Combine the pack */
if (creature_ptr->update & (PU_COMBINE))
{
creature_ptr->update &= ~(PU_COMBINE);
if (o_ptr->k_idx && check_book_realm(o_ptr->tval, o_ptr->sval)) return FALSE;
}
- for (i = grid_array[p_ptr->y][p_ptr->x].o_idx; i; i = o_ptr->next_o_idx)
+ for (i = current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].o_idx; i; i = o_ptr->next_o_idx)
{
- o_ptr = &o_list[i];
+ o_ptr = ¤t_floor_ptr->o_list[i];
if (o_ptr->k_idx && (o_ptr->marked & OM_FOUND) && check_book_realm(o_ptr->tval, o_ptr->sval)) return FALSE;
}
{
creature_ptr->energy_use = 0;
}
+
+/*!
+ * @brief プレイヤーを指定座標に配置する / Place the player in the dungeon XXX XXX
+ * @param x 配置先X座標
+ * @param y 配置先Y座標
+ * @return 配置に成功したらTRUE
+ */
+bool player_place(POSITION y, POSITION x)
+{
+ /* Paranoia XXX XXX */
+ if (current_floor_ptr->grid_array[y][x].m_idx != 0) return FALSE;
+
+ /* Save player location */
+ p_ptr->y = y;
+ p_ptr->x = x;
+
+ /* Success */
+ return TRUE;
+}
+
+/*!
+ * @brief 種族アンバライトが出血時パターンの上に乗った際のペナルティ処理
+ * @return なし
+ */
+void wreck_the_pattern(void)
+{
+ int to_ruin = 0;
+ POSITION r_y, r_x;
+ int pattern_type = f_info[current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].feat].subtype;
+
+ if (pattern_type == PATTERN_TILE_WRECKED)
+ {
+ /* Ruined already */
+ return;
+ }
+
+ msg_print(_("パターンを血で汚してしまった!", "You bleed on the Pattern!"));
+ msg_print(_("何か恐ろしい事が起こった!", "Something terrible happens!"));
+
+ if (!IS_INVULN()) take_hit(DAMAGE_NOESCAPE, damroll(10, 8), _("パターン損壊", "corrupting the Pattern"), -1);
+ to_ruin = randint1(45) + 35;
+
+ while (to_ruin--)
+ {
+ scatter(&r_y, &r_x, p_ptr->y, p_ptr->x, 4, 0);
+
+ if (pattern_tile(r_y, r_x) &&
+ (f_info[current_floor_ptr->grid_array[r_y][r_x].feat].subtype != PATTERN_TILE_WRECKED))
+ {
+ cave_set_feat(r_y, r_x, feat_pattern_corrupted);
+ }
+ }
+
+ cave_set_feat(p_ptr->y, p_ptr->x, feat_pattern_corrupted);
+}
+
+
+/*!
+ * @brief ELDRITCH_HORRORによるプレイヤーの精神破壊処理
+ * @param m_ptr ELDRITCH_HORRORを引き起こしたモンスターの参照ポインタ
+ * @param necro 暗黒領域魔法の詠唱失敗によるものならばTRUEを返す
+ * @return なし
+ */
+void sanity_blast(monster_type *m_ptr, bool necro)
+{
+ int power = 100;
+
+ if (p_ptr->inside_battle || !character_dungeon) return;
+
+ if (!necro && m_ptr)
+ {
+ GAME_TEXT m_name[MAX_NLEN];
+ monster_race *r_ptr = &r_info[m_ptr->ap_r_idx];
+
+ power = r_ptr->level / 2;
+
+ monster_desc(m_name, m_ptr, 0);
+
+ if (!(r_ptr->flags1 & RF1_UNIQUE))
+ {
+ if (r_ptr->flags1 & RF1_FRIENDS)
+ power /= 2;
+ }
+ else power *= 2;
+
+ if (!is_loading_now)
+ return; /* No effect yet, just loaded... */
+
+ if (!m_ptr->ml)
+ return; /* Cannot see it for some reason */
+
+ if (!(r_ptr->flags2 & RF2_ELDRITCH_HORROR))
+ return;
+
+ if (is_pet(m_ptr))
+ return; /* Pet eldritch horrors are safe most of the time */
+
+ if (randint1(100) > power) return;
+
+ if (saving_throw(p_ptr->skill_sav - power))
+ {
+ return; /* Save, no adverse effects */
+ }
+
+ if (p_ptr->image)
+ {
+ /* Something silly happens... */
+ msg_format(_("%s%sの顔を見てしまった!", "You behold the %s visage of %s!"),
+ funny_desc[randint0(MAX_SAN_FUNNY)], m_name);
+
+ if (one_in_(3))
+ {
+ msg_print(funny_comments[randint0(MAX_SAN_COMMENT)]);
+ p_ptr->image = p_ptr->image + randint1(r_ptr->level);
+ }
+
+ return; /* Never mind; we can't see it clearly enough */
+ }
+
+ /* Something frightening happens... */
+ msg_format(_("%s%sの顔を見てしまった!", "You behold the %s visage of %s!"),
+ horror_desc[randint0(MAX_SAN_HORROR)], m_name);
+
+ r_ptr->r_flags2 |= RF2_ELDRITCH_HORROR;
+
+ /* Demon characters are unaffected */
+ if (prace_is_(RACE_IMP) || prace_is_(RACE_DEMON) || (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_DEMON)) return;
+ if (p_ptr->wizard) return;
+
+ /* Undead characters are 50% likely to be unaffected */
+ if (prace_is_(RACE_SKELETON) || prace_is_(RACE_ZOMBIE)
+ || prace_is_(RACE_VAMPIRE) || prace_is_(RACE_SPECTRE) ||
+ (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_UNDEAD))
+ {
+ if (saving_throw(25 + p_ptr->lev)) return;
+ }
+ }
+ else if (!necro)
+ {
+ monster_race *r_ptr;
+ GAME_TEXT m_name[MAX_NLEN];
+ concptr desc;
+
+ get_mon_num_prep(get_nightmare, NULL);
+
+ r_ptr = &r_info[get_mon_num(MAX_DEPTH)];
+ power = r_ptr->level + 10;
+ desc = r_name + r_ptr->name;
+
+ get_mon_num_prep(NULL, NULL);
+
+#ifndef JP
+ if (!(r_ptr->flags1 & RF1_UNIQUE))
+ sprintf(m_name, "%s %s", (is_a_vowel(desc[0]) ? "an" : "a"), desc);
+ else
+#endif
+ sprintf(m_name, "%s", desc);
+
+ if (!(r_ptr->flags1 & RF1_UNIQUE))
+ {
+ if (r_ptr->flags1 & RF1_FRIENDS) power /= 2;
+ }
+ else power *= 2;
+
+ if (saving_throw(p_ptr->skill_sav * 100 / power))
+ {
+ msg_format(_("夢の中で%sに追いかけられた。", "%^s chases you through your dreams."), m_name);
+ /* Safe */
+ return;
+ }
+
+ if (p_ptr->image)
+ {
+ /* Something silly happens... */
+ msg_format(_("%s%sの顔を見てしまった!", "You behold the %s visage of %s!"),
+ funny_desc[randint0(MAX_SAN_FUNNY)], m_name);
+
+ if (one_in_(3))
+ {
+ msg_print(funny_comments[randint0(MAX_SAN_COMMENT)]);
+ p_ptr->image = p_ptr->image + randint1(r_ptr->level);
+ }
+
+ /* Never mind; we can't see it clearly enough */
+ return;
+ }
+
+ /* Something frightening happens... */
+ msg_format(_("%s%sの顔を見てしまった!", "You behold the %s visage of %s!"),
+ horror_desc[randint0(MAX_SAN_HORROR)], desc);
+
+ r_ptr->r_flags2 |= RF2_ELDRITCH_HORROR;
+
+ if (!p_ptr->mimic_form)
+ {
+ switch (p_ptr->prace)
+ {
+ /* Demons may make a saving throw */
+ case RACE_IMP:
+ case RACE_DEMON:
+ if (saving_throw(20 + p_ptr->lev)) return;
+ break;
+ /* Undead may make a saving throw */
+ case RACE_SKELETON:
+ case RACE_ZOMBIE:
+ case RACE_SPECTRE:
+ case RACE_VAMPIRE:
+ if (saving_throw(10 + p_ptr->lev)) return;
+ break;
+ }
+ }
+ else
+ {
+ /* Demons may make a saving throw */
+ if (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_DEMON)
+ {
+ if (saving_throw(20 + p_ptr->lev)) return;
+ }
+ /* Undead may make a saving throw */
+ else if (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_UNDEAD)
+ {
+ if (saving_throw(10 + p_ptr->lev)) return;
+ }
+ }
+ }
+ else
+ {
+ msg_print(_("ネクロノミコンを読んで正気を失った!", "Your sanity is shaken by reading the Necronomicon!"));
+ }
+
+ if (saving_throw(p_ptr->skill_sav - power))
+ {
+ return;
+ }
+
+ do {
+ (void)do_dec_stat(A_INT);
+ } while (randint0(100) > p_ptr->skill_sav && one_in_(2));
+
+ do {
+ (void)do_dec_stat(A_WIS);
+ } while (randint0(100) > p_ptr->skill_sav && one_in_(2));
+
+ switch (randint1(21))
+ {
+ case 1:
+ if (!(p_ptr->muta3 & MUT3_MORONIC) && one_in_(5))
+ {
+ if ((p_ptr->stat_use[A_INT] < 4) && (p_ptr->stat_use[A_WIS] < 4))
+ {
+ msg_print(_("あなたは完璧な馬鹿になったような気がした。しかしそれは元々だった。", "You current_world_ptr->game_turn into an utter moron!"));
+ }
+ else
+ {
+ msg_print(_("あなたは完璧な馬鹿になった!", "You current_world_ptr->game_turn into an utter moron!"));
+ }
+
+ if (p_ptr->muta3 & MUT3_HYPER_INT)
+ {
+ msg_print(_("あなたの脳は生体コンピュータではなくなった。", "Your brain is no longer a living computer."));
+ p_ptr->muta3 &= ~(MUT3_HYPER_INT);
+ }
+ p_ptr->muta3 |= MUT3_MORONIC;
+ }
+ break;
+ case 2:
+ case 3:
+ case 4:
+ if (!(p_ptr->muta2 & MUT2_COWARDICE) && !p_ptr->resist_fear)
+ {
+ msg_print(_("あなたはパラノイアになった!", "You become paranoid!"));
+
+ /* Duh, the following should never happen, but anyway... */
+ if (p_ptr->muta3 & MUT3_FEARLESS)
+ {
+ msg_print(_("あなたはもう恐れ知らずではなくなった。", "You are no longer fearless."));
+ p_ptr->muta3 &= ~(MUT3_FEARLESS);
+ }
+
+ p_ptr->muta2 |= MUT2_COWARDICE;
+ }
+ break;
+ case 5:
+ case 6:
+ case 7:
+ if (!(p_ptr->muta2 & MUT2_HALLU) && !p_ptr->resist_chaos)
+ {
+ msg_print(_("幻覚をひき起こす精神錯乱に陥った!", "You are afflicted by a hallucinatory insanity!"));
+ p_ptr->muta2 |= MUT2_HALLU;
+ }
+ break;
+ case 8:
+ case 9:
+ case 10:
+ if (!(p_ptr->muta2 & MUT2_BERS_RAGE))
+ {
+ msg_print(_("激烈な感情の発作におそわれるようになった!", "You become subject to fits of berserk rage!"));
+ p_ptr->muta2 |= MUT2_BERS_RAGE;
+ }
+ break;
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ /* Brain smash */
+ if (!p_ptr->resist_conf)
+ {
+ (void)set_confused(p_ptr->confused + randint0(4) + 4);
+ }
+ if (!p_ptr->free_act)
+ {
+ (void)set_paralyzed(p_ptr->paralyzed + randint0(4) + 4);
+ }
+ if (!p_ptr->resist_chaos)
+ {
+ (void)set_image(p_ptr->image + randint0(250) + 150);
+ }
+ break;
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ /* Amnesia */
+ if (lose_all_info())
+ msg_print(_("あまりの恐怖に全てのことを忘れてしまった!", "You forget everything in your utmost terror!"));
+ break;
+ }
+
+ p_ptr->update |= PU_BONUS;
+ handle_stuff();
+}
+
+
+/*!
+ * @brief プレイヤーの経験値について整合性のためのチェックと調整を行う /
+ * Advance experience levels and print experience
+ * @return なし
+ */
+void check_experience(void)
+{
+ bool level_reward = FALSE;
+ bool level_mutation = FALSE;
+ bool level_inc_stat = FALSE;
+ bool android = (p_ptr->prace == RACE_ANDROID ? TRUE : FALSE);
+ PLAYER_LEVEL old_lev = p_ptr->lev;
+
+ /* Hack -- lower limit */
+ if (p_ptr->exp < 0) p_ptr->exp = 0;
+ if (p_ptr->max_exp < 0) p_ptr->max_exp = 0;
+ if (p_ptr->max_max_exp < 0) p_ptr->max_max_exp = 0;
+
+ /* Hack -- upper limit */
+ if (p_ptr->exp > PY_MAX_EXP) p_ptr->exp = PY_MAX_EXP;
+ if (p_ptr->max_exp > PY_MAX_EXP) p_ptr->max_exp = PY_MAX_EXP;
+ if (p_ptr->max_max_exp > PY_MAX_EXP) p_ptr->max_max_exp = PY_MAX_EXP;
+
+ /* Hack -- maintain "max" experience */
+ if (p_ptr->exp > p_ptr->max_exp) p_ptr->max_exp = p_ptr->exp;
+
+ /* Hack -- maintain "max max" experience */
+ if (p_ptr->max_exp > p_ptr->max_max_exp) p_ptr->max_max_exp = p_ptr->max_exp;
+
+ /* Redraw experience */
+ p_ptr->redraw |= (PR_EXP);
+ handle_stuff();
+
+
+ /* Lose levels while possible */
+ while ((p_ptr->lev > 1) &&
+ (p_ptr->exp < ((android ? player_exp_a : player_exp)[p_ptr->lev - 2] * p_ptr->expfact / 100L)))
+ {
+ /* Lose a level */
+ p_ptr->lev--;
+ p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
+ p_ptr->redraw |= (PR_LEV | PR_TITLE);
+ p_ptr->window |= (PW_PLAYER);
+ handle_stuff();
+ }
+
+
+ /* Gain levels while possible */
+ while ((p_ptr->lev < PY_MAX_LEVEL) &&
+ (p_ptr->exp >= ((android ? player_exp_a : player_exp)[p_ptr->lev - 1] * p_ptr->expfact / 100L)))
+ {
+ /* Gain a level */
+ p_ptr->lev++;
+
+ /* Save the highest level */
+ if (p_ptr->lev > p_ptr->max_plv)
+ {
+ p_ptr->max_plv = p_ptr->lev;
+
+ if ((p_ptr->pclass == CLASS_CHAOS_WARRIOR) ||
+ (p_ptr->muta2 & MUT2_CHAOS_GIFT))
+ {
+ level_reward = TRUE;
+ }
+ if (p_ptr->prace == RACE_BEASTMAN)
+ {
+ if (one_in_(5)) level_mutation = TRUE;
+ }
+ level_inc_stat = TRUE;
+
+ do_cmd_write_nikki(NIKKI_LEVELUP, p_ptr->lev, NULL);
+ }
+
+ sound(SOUND_LEVEL);
+
+ msg_format(_("レベル %d にようこそ。", "Welcome to level %d."), p_ptr->lev);
+
+ p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
+ p_ptr->redraw |= (PR_LEV | PR_TITLE | PR_EXP);
+ p_ptr->window |= (PW_PLAYER | PW_SPELL | PW_INVEN);
+
+ /* HPとMPの上昇量を表示 */
+ level_up = 1;
+ handle_stuff();
+
+ level_up = 0;
+
+ if (level_inc_stat)
+ {
+ if (!(p_ptr->max_plv % 10))
+ {
+ int choice;
+ screen_save();
+ while (1)
+ {
+ int n;
+ char tmp[32];
+
+ cnv_stat(p_ptr->stat_max[0], tmp);
+ prt(format(_(" a) 腕力 (現在値 %s)", " a) Str (cur %s)"), tmp), 2, 14);
+ cnv_stat(p_ptr->stat_max[1], tmp);
+ prt(format(_(" b) 知能 (現在値 %s)", " a) Int (cur %s)"), tmp), 3, 14);
+ cnv_stat(p_ptr->stat_max[2], tmp);
+ prt(format(_(" c) 賢さ (現在値 %s)", " a) Wis (cur %s)"), tmp), 4, 14);
+ cnv_stat(p_ptr->stat_max[3], tmp);
+ prt(format(_(" d) 器用 (現在値 %s)", " a) Dex (cur %s)"), tmp), 5, 14);
+ cnv_stat(p_ptr->stat_max[4], tmp);
+ prt(format(_(" e) 耐久 (現在値 %s)", " a) Con (cur %s)"), tmp), 6, 14);
+ cnv_stat(p_ptr->stat_max[5], tmp);
+ prt(format(_(" f) 魅力 (現在値 %s)", " a) Chr (cur %s)"), tmp), 7, 14);
+
+ prt("", 8, 14);
+ prt(_(" どの能力値を上げますか?", " Which stat do you want to raise?"), 1, 14);
+
+ while (1)
+ {
+ choice = inkey();
+ if ((choice >= 'a') && (choice <= 'f')) break;
+ }
+ for (n = 0; n < A_MAX; n++)
+ if (n != choice - 'a')
+ prt("", n + 2, 14);
+ if (get_check(_("よろしいですか?", "Are you sure? "))) break;
+ }
+ do_inc_stat(choice - 'a');
+ screen_load();
+ }
+ else if (!(p_ptr->max_plv % 2))
+ do_inc_stat(randint0(6));
+ }
+
+ if (level_mutation)
+ {
+ msg_print(_("あなたは変わった気がする...", "You feel different..."));
+ (void)gain_mutation(p_ptr, 0);
+ level_mutation = FALSE;
+ }
+
+ /*
+ * 報酬でレベルが上ると再帰的に check_experience() が
+ * 呼ばれるので順番を最後にする。
+ */
+ if (level_reward)
+ {
+ gain_level_reward(0);
+ level_reward = FALSE;
+ }
+
+ p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
+ p_ptr->redraw |= (PR_LEV | PR_TITLE);
+ p_ptr->window |= (PW_PLAYER | PW_SPELL);
+ handle_stuff();
+ }
+
+ /* Load an autopick preference file */
+ if (old_lev != p_ptr->lev) autopick_load_pref(FALSE);
+}
+