OSDN Git Service

[Refactor] #37353 賭け闘技場に関する定義を bldg.c/h へ移動.
[hengband/hengband.git] / src / bldg.c
index 7e2d594..47eab3d 100644 (file)
 */
 
 #include "angband.h"
+#include "util.h"
+
+#include "core.h"
+#include "cmd-dump.h"
 #include "floor.h"
 #include "floor-events.h"
 #include "floor-save.h"
+#include "autopick.h"
+#include "objectkind.h"
 #include "object-boost.h"
 #include "object-flavor.h"
 #include "object-hook.h"
 
 #include "avatar.h"
 #include "bldg.h"
+#include "dungeon.h"
 #include "mutation.h"
 #include "quest.h"
 #include "artifact.h"
 #include "cmd-spell.h"
 #include "rumor.h"
 #include "player-status.h"
+#include "spells.h"
 #include "spells-status.h"
 #include "realm-hex.h"
 #include "dungeon-file.h"
 
+#include "files.h"
+#include "player-effects.h"
+#include "scores.h"
+#include "shoot.h"
+#include "view-mainwindow.h"
+#include "monsterrace.h"
+#include "autopick.h"
+
+
+/*
+ * Buildings
+ */
+building_type building[MAX_BLDG];
+
+MONRACE_IDX battle_mon[4];
+u32b mon_odds[4];
+int battle_odds;
+PRICE kakekin;
+int sel_monster;
+
 /*!
  * @brief 闘技場のモンスターID及び報酬アイテムテーブル
  */
@@ -88,12 +116,6 @@ const arena_type arena_info[MAX_ARENA_MONS + 2] =
        { MON_HAGURE,        TV_SCROLL, SV_SCROLL_ARTIFACT            },
 };
 
-
-/*!
- * ループ中で / hack as in leave_store in store.c
- */
-static bool leave_bldg = FALSE;
-
 /*!
  * @brief 施設毎に設定された種族、職業、魔法領域フラグがプレイヤーと一致するかを判定する。
  * @details 各種ギルドや寺院など、特定の職業ならば優遇措置を得られる施設、
@@ -170,7 +192,7 @@ static bool is_member(building_type *bldg)
  * @param max_row 末尾行番号
  * @return なし
  */
-static void clear_bldg(int min_row, int max_row)
+void clear_bldg(int min_row, int max_row)
 {
        int   i;
 
@@ -326,7 +348,7 @@ static void arena_comm(int cmd)
 
                                                p_ptr->inside_arena = TRUE;
                                                p_ptr->leaving = TRUE;
-                                               leave_bldg = TRUE;
+                                               p_ptr->leave_bldg = TRUE;
                                        }
                                        else
                                        {
@@ -356,7 +378,7 @@ static void arena_comm(int cmd)
 
                                p_ptr->inside_arena = TRUE;
                                p_ptr->leaving = TRUE;
-                               leave_bldg = TRUE;
+                               p_ptr->leave_bldg = TRUE;
                        }
                        break;
                case BACT_POSTER:
@@ -1635,7 +1657,7 @@ static bool kakutoujou(void)
                        p_ptr->inside_battle = TRUE;
                        p_ptr->leaving = TRUE;
 
-                       leave_bldg = TRUE;
+                       p_ptr->leave_bldg = TRUE;
                        screen_load();
 
                        return (TRUE);
@@ -1770,10 +1792,10 @@ static bool kankin(void)
        GAME_TEXT o_name[MAX_NLEN];
        object_type *o_ptr;
 
-       /* Loop for inventory and right/left arm */
+       /* Loop for p_ptr->inventory_list and right/left arm */
        for (i = 0; i <= INVEN_LARM; i++)
        {
-               o_ptr = &inventory[i];
+               o_ptr = &p_ptr->inventory_list[i];
 
                /* Living Tsuchinoko worthes $1000000 */
                if ((o_ptr->tval == TV_CAPTURE) && (o_ptr->pval == MON_TSUCHINOKO))
@@ -1796,7 +1818,7 @@ static bool kankin(void)
 
        for (i = 0; i < INVEN_PACK; i++)
        {
-               o_ptr = &inventory[i];
+               o_ptr = &p_ptr->inventory_list[i];
 
                /* Corpse of Tsuchinoko worthes $200000 */
                if ((o_ptr->tval == TV_CORPSE) && (o_ptr->sval == SV_CORPSE) && (o_ptr->pval == MON_TSUCHINOKO))
@@ -1819,7 +1841,7 @@ static bool kankin(void)
 
        for (i = 0; i < INVEN_PACK; i++)
        {
-               o_ptr = &inventory[i];
+               o_ptr = &p_ptr->inventory_list[i];
 
                /* Bones of Tsuchinoko worthes $100000 */
                if ((o_ptr->tval == TV_CORPSE) && (o_ptr->sval == SV_SKELETON) && (o_ptr->pval == MON_TSUCHINOKO))
@@ -1842,7 +1864,7 @@ static bool kankin(void)
 
        for (i = 0; i < INVEN_PACK; i++)
        {
-               o_ptr = &inventory[i];
+               o_ptr = &p_ptr->inventory_list[i];
                if ((o_ptr->tval == TV_CORPSE) && (o_ptr->sval == SV_CORPSE) && (streq(r_name + r_info[o_ptr->pval].name, r_name + r_info[today_mon].name)))
                {
                        char buf[MAX_NLEN+20];
@@ -1863,7 +1885,7 @@ static bool kankin(void)
 
        for (i = 0; i < INVEN_PACK; i++)
        {
-               o_ptr = &inventory[i];
+               o_ptr = &p_ptr->inventory_list[i];
 
                if ((o_ptr->tval == TV_CORPSE) && (o_ptr->sval == SV_SKELETON) && (streq(r_name + r_info[o_ptr->pval].name, r_name + r_info[today_mon].name)))
                {
@@ -1888,7 +1910,7 @@ static bool kankin(void)
                /* Need reverse order --- Positions will be changed in the loop */
                for (i = INVEN_PACK-1; i >= 0; i--)
                {
-                       o_ptr = &inventory[i];
+                       o_ptr = &p_ptr->inventory_list[i];
                        if ((o_ptr->tval == TV_CORPSE) && (o_ptr->pval == current_world_ptr->bounty_r_idx[j]))
                        {
                                char buf[MAX_NLEN+20];
@@ -2236,124 +2258,6 @@ static void town_history(void)
 }
 
 /*!
- * @brief 射撃時クリティカルによるダメージ期待値修正計算(スナイパーの集中処理と武器経験値) / critical happens at i / 10000
- * @param plus_ammo 矢弾のダメージ修正
- * @param plus_bow 弓のダメージ修正
- * @return ダメージ期待値
- * @note 基本ダメージ量と重量はこの部位では計算に加わらない。
- */
-HIT_POINT calc_crit_ratio_shot(HIT_POINT plus_ammo, HIT_POINT plus_bow)
-{
-       HIT_POINT i;
-       object_type *j_ptr =  &inventory[INVEN_BOW];
-       
-       /* Extract "shot" power */
-       i = p_ptr->to_h_b + plus_ammo;
-       
-       if (p_ptr->tval_ammo == TV_BOLT)
-               i = (p_ptr->skill_thb + (p_ptr->weapon_exp[0][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
-       else
-               i = (p_ptr->skill_thb + ((p_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + i) * BTH_PLUS_ADJ);
-
-       /* Snipers can shot more critically with crossbows */
-       if (p_ptr->concent) i += ((i * p_ptr->concent) / 5);
-       if ((p_ptr->pclass == CLASS_SNIPER) && (p_ptr->tval_ammo == TV_BOLT)) i *= 2;
-       
-       /* Good bow makes more critical */
-       i += plus_bow * 8 * (p_ptr->concent ? p_ptr->concent + 5 : 5);
-       
-       if (i < 0) i = 0;
-       
-       return i;
-}
-
-/*!
- * @brief 射撃時クリティカルによるダメージ期待値修正計算(重量依存部分) / critical happens at i / 10000
- * @param weight 武器の重量
- * @param plus_ammo 矢弾のダメージ修正
- * @param plus_bow 弓のダメージ修正
- * @param dam 基本ダメージ量
- * @return ダメージ期待値
- */
-HIT_POINT calc_expect_crit_shot(WEIGHT weight, int plus_ammo, int plus_bow,  HIT_POINT dam)
-{
-       u32b num;
-       int i, k, crit;
-       i = calc_crit_ratio_shot(plus_ammo, plus_bow);
-       
-       k = 0;
-       num = 0;
-       
-       crit = MIN(500, 900/weight);
-       num += dam * 3 /2 * crit;
-       k = crit;
-       
-       crit = MIN(500, 1350/weight);
-       crit -= k;
-       num += dam * 2 * crit;
-       k += crit;
-       
-       if(k < 500)
-       {
-               crit = 500 - k;
-               num += dam * 3 * crit;
-       }
-       
-       num /= 500;
-       
-       num *= i;
-       num += (10000 - i) * dam;
-       num /= 10000;
-       
-       return num;
-}
-
-/*!
- * @brief 攻撃時クリティカルによるダメージ期待値修正計算(重量と毒針処理) / critical happens at i / 10000
- * @param weight 武器の重量
- * @param plus 武器のダメージ修正
- * @param dam 基本ダメージ
- * @param meichuu 命中値
- * @param dokubari 毒針処理か否か
- * @return ダメージ期待値
- */
-HIT_POINT calc_expect_crit(WEIGHT weight, int plus, HIT_POINT dam, s16b meichuu, bool dokubari)
-{
-       u32b k, num;
-       int i;
-       
-       if(dokubari) return dam;
-       
-       i = (weight + (meichuu * 3 + plus * 5) + p_ptr->skill_thn);
-       if (i < 0) i = 0;
-       
-       k = weight;
-       num = 0;
-       
-       if (k < 400)                                            num += (2 * dam + 5) * (400 - k);
-       if (k < 700)                                            num += (2 * dam + 10) * (MIN(700, k + 650) - MAX(400, k));
-       if (k > (700 - 650) && k < 900)         num += (3 * dam + 15) * (MIN(900, k + 650) - MAX(700, k));
-       if (k > (900 - 650) && k < 1300)                num += (3 * dam + 20) * (MIN(1300, k + 650) - MAX(900, k));
-       if (k > (1300 - 650))                                   num += (7 * dam / 2 + 25) * MIN(650, k - (1300 - 650));
-       
-       num /= 650;
-       if(p_ptr->pclass == CLASS_NINJA)
-       {
-               num *= i;
-               num += (4444 - i) * dam;
-               num /= 4444;
-       }
-       else
-       {
-               num *= i;
-               num += (5000 - i) * dam;
-               num /= 5000;
-       }
-       
-       return num;
-}
-
-/*!
  * @brief 攻撃時スレイによるダメージ期待値修正計算 / critical happens at i / 10000
  * @param dam 基本ダメージ
  * @param mult スレイ倍率(掛け算部分)
@@ -2740,7 +2644,7 @@ static PRICE compare_weapons(PRICE bcost)
        clear_bldg(0, 22);
 
        /* Store copy of original wielded weapon */
-       i_ptr = &inventory[INVEN_RARM];
+       i_ptr = &p_ptr->inventory_list[INVEN_RARM];
        object_copy(&orig_weapon, i_ptr);
 
        item_tester_hook = item_tester_hook_orthodox_melee_weapons;
@@ -3588,7 +3492,7 @@ static void building_recharge_all(void)
        /* Calculate cost */
        for ( i = 0; i < INVEN_PACK; i++)
        {
-               o_ptr = &inventory[i];
+               o_ptr = &p_ptr->inventory_list[i];
                                
                /* skip non magic device */
                if (o_ptr->tval < TV_STAFF || o_ptr->tval > TV_ROD) continue;
@@ -3652,7 +3556,7 @@ static void building_recharge_all(void)
        
        for (i = 0; i < INVEN_PACK; i++)
        {
-               o_ptr = &inventory[i];
+               o_ptr = &p_ptr->inventory_list[i];
                k_ptr = &k_info[o_ptr->k_idx];
 
                /* skip non magic device */
@@ -3701,84 +3605,6 @@ static void building_recharge_all(void)
 }
 
 /*!
- * @brief 町間のテレポートを行うメインルーチン。
- * @return テレポート処理を決定したか否か
- */
-bool tele_town(void)
-{
-       int i;
-       POSITION x, y;
-       int num = 0;
-
-       if (current_floor_ptr->dun_level)
-       {
-               msg_print(_("この魔法は地上でしか使えない!", "This spell can only be used on the surface!"));
-               return FALSE;
-       }
-
-       if (p_ptr->inside_arena || p_ptr->inside_battle)
-       {
-               msg_print(_("この魔法は外でしか使えない!", "This spell can only be used outside!"));
-               return FALSE;
-       }
-
-       screen_save();
-       clear_bldg(4, 10);
-
-       for (i = 1; i < max_towns; i++)
-       {
-               char buf[80];
-
-               if ((i == NO_TOWN) || (i == SECRET_TOWN) || (i == p_ptr->town_num) || !(p_ptr->visit & (1L << (i - 1)))) continue;
-
-               sprintf(buf, "%c) %-20s", I2A(i - 1), town_info[i].name);
-               prt(buf, 5 + i, 5);
-               num++;
-       }
-
-       if (!num)
-       {
-               msg_print(_("まだ行けるところがない。", "You have not yet visited any town."));
-               msg_print(NULL);
-               screen_load();
-               return FALSE;
-       }
-
-       prt(_("どこに行きますか:", "Which town you go: "), 0, 0);
-       while(1)
-       {
-               i = inkey();
-
-               if (i == ESCAPE)
-               {
-                       screen_load();
-                       return FALSE;
-               }
-               else if ((i < 'a') || (i > ('a'+max_towns-2))) continue;
-               else if (((i-'a'+1) == p_ptr->town_num) || ((i-'a'+1) == NO_TOWN) || ((i-'a'+1) == SECRET_TOWN) || !(p_ptr->visit & (1L << (i-'a')))) continue;
-               break;
-       }
-
-       for (y = 0; y < current_world_ptr->max_wild_y; y++)
-       {
-               for (x = 0; x < current_world_ptr->max_wild_x; x++)
-               {
-                       if(wilderness[y][x].town == (i-'a'+1))
-                       {
-                               p_ptr->wilderness_y = y;
-                               p_ptr->wilderness_x = x;
-                       }
-               }
-       }
-
-       p_ptr->leaving = TRUE;
-       leave_bldg = TRUE;
-       p_ptr->teleport_town = TRUE;
-       screen_load();
-       return TRUE;
-}
-
-/*!
  * @brief 施設でモンスターの情報を知るメインルーチン / research_mon -KMW-
  * @return 常にTRUEを返す。
  * @todo 返り値が意味不明なので直した方が良いかもしれない。
@@ -3981,7 +3807,6 @@ static bool research_mon(void)
                                old_i = i;
                        }
 
-                       /* Command */
                        query = inkey();
 
                        /* Normal commands */
@@ -4240,43 +4065,6 @@ static void bldg_process_command(building_type *bldg, int i)
 }
 
 /*!
- * @brief クエスト入り口にプレイヤーが乗った際の処理 / Do building commands
- * @return なし
- */
-void do_cmd_quest(void)
-{
-       if(p_ptr->wild_mode) return;
-
-       take_turn(p_ptr, 100);
-
-       if (!cave_have_flag_bold(p_ptr->y, p_ptr->x, FF_QUEST_ENTER))
-       {
-               msg_print(_("ここにはクエストの入口はない。", "You see no quest level here."));
-               return;
-       }
-       else
-       {
-               msg_print(_("ここにはクエストへの入口があります。", "There is an entry of a quest."));
-               if (!get_check(_("クエストに入りますか?", "Do you enter? "))) return;
-               if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON))
-                       msg_print(_("『とにかく入ってみようぜぇ。』", ""));
-               else if(p_ptr->pseikaku == SEIKAKU_CHARGEMAN) msg_print("『全滅してやるぞ!』");
-
-               /* Player enters a new quest */
-               p_ptr->oldpy = 0;
-               p_ptr->oldpx = 0;
-
-               leave_quest_check();
-
-               if (quest[p_ptr->inside_quest].type != QUEST_TYPE_RANDOM) current_floor_ptr->dun_level = 1;
-               p_ptr->inside_quest = current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].special;
-
-               p_ptr->leaving = TRUE;
-       }
-}
-
-
-/*!
  * @brief 施設入り口にプレイヤーが乗った際の処理 / Do building commands
  * @return なし
  */
@@ -4311,7 +4099,7 @@ void do_cmd_bldg(void)
        }
        else if ((which == 2) && p_ptr->inside_arena)
        {
-               if (!p_ptr->exit_bldg && m_cnt > 0)
+               if (!p_ptr->exit_bldg && current_floor_ptr->m_cnt > 0)
                {
                        prt(_("ゲートは閉まっている。モンスターがあなたを待っている!", "The gates are closed.  The monster awaits!"), 0, 0);
                }
@@ -4365,11 +4153,11 @@ void do_cmd_bldg(void)
        command_new = 0;
 
        show_building(bldg);
-       leave_bldg = FALSE;
+       p_ptr->leave_bldg = FALSE;
 
        play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_BUILD);
 
-       while (!leave_bldg)
+       while (!p_ptr->leave_bldg)
        {
                validcmd = FALSE;
                prt("", 1, 0);
@@ -4380,7 +4168,7 @@ void do_cmd_bldg(void)
 
                if (command == ESCAPE)
                {
-                       leave_bldg = TRUE;
+                       p_ptr->leave_bldg = TRUE;
                        p_ptr->inside_arena = FALSE;
                        p_ptr->inside_battle = FALSE;
                        break;
@@ -4423,3 +4211,96 @@ void do_cmd_bldg(void)
        p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_EQUIPPY | PR_MAP);
        p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
 }
+
+
+/*!
+ * @brief 今日の賞金首を確定する / Determine today's bounty monster
+ * @return なし
+ * @note conv_old is used if loaded 0.0.3 or older save file
+ */
+void determine_today_mon(bool conv_old)
+{
+       int max_dl = 3, i;
+       bool old_inside_battle = p_ptr->inside_battle;
+       monster_race *r_ptr;
+
+       if (!conv_old)
+       {
+               for (i = 0; i < max_d_idx; i++)
+               {
+                       if (max_dlv[i] < d_info[i].mindepth) continue;
+                       if (max_dl < max_dlv[i]) max_dl = max_dlv[i];
+               }
+       }
+       else max_dl = MAX(max_dlv[DUNGEON_ANGBAND], 3);
+
+       p_ptr->inside_battle = TRUE;
+       get_mon_num_prep(NULL, NULL);
+
+       while (1)
+       {
+               today_mon = get_mon_num(max_dl);
+               r_ptr = &r_info[today_mon];
+
+               if (r_ptr->flags1 & RF1_UNIQUE) continue;
+               if (r_ptr->flags7 & (RF7_NAZGUL | RF7_UNIQUE2)) continue;
+               if (r_ptr->flags2 & RF2_MULTIPLY) continue;
+               if ((r_ptr->flags9 & (RF9_DROP_CORPSE | RF9_DROP_SKELETON)) != (RF9_DROP_CORPSE | RF9_DROP_SKELETON)) continue;
+               if (r_ptr->level < MIN(max_dl / 2, 40)) continue;
+               if (r_ptr->rarity > 10) continue;
+               break;
+       }
+
+       p_ptr->today_mon = 0;
+       p_ptr->inside_battle = old_inside_battle;
+}
+
+
+
+/*!
+ * @brief 賞金首となるユニークを確定する / Determine bounty uniques
+ * @return なし
+ */
+void determine_bounty_uniques(void)
+{
+       int i, j;
+       MONRACE_IDX tmp;
+       monster_race *r_ptr;
+
+       get_mon_num_prep(NULL, NULL);
+       for (i = 0; i < MAX_KUBI; i++)
+       {
+               while (1)
+               {
+                       current_world_ptr->bounty_r_idx[i] = get_mon_num(MAX_DEPTH - 1);
+                       r_ptr = &r_info[current_world_ptr->bounty_r_idx[i]];
+
+                       if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
+
+                       if (!(r_ptr->flags9 & (RF9_DROP_CORPSE | RF9_DROP_SKELETON))) continue;
+
+                       if (r_ptr->rarity > 100) continue;
+
+                       if (no_questor_or_bounty_uniques(current_world_ptr->bounty_r_idx[i])) continue;
+
+                       for (j = 0; j < i; j++)
+                               if (current_world_ptr->bounty_r_idx[i] == current_world_ptr->bounty_r_idx[j]) break;
+
+                       if (j == i) break;
+               }
+       }
+
+       /* Sort them */
+       for (i = 0; i < MAX_KUBI - 1; i++)
+       {
+               for (j = i; j < MAX_KUBI; j++)
+               {
+                       if (r_info[current_world_ptr->bounty_r_idx[i]].level > r_info[current_world_ptr->bounty_r_idx[j]].level)
+                       {
+                               tmp = current_world_ptr->bounty_r_idx[i];
+                               current_world_ptr->bounty_r_idx[i] = current_world_ptr->bounty_r_idx[j];
+                               current_world_ptr->bounty_r_idx[j] = tmp;
+                       }
+               }
+       }
+}