X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fbldg.c;h=47eab3d57b13f3403c0ced3d4e5d26f178e2aab8;hb=61fd54c1ee47a6c98fdd7d549f313f36c14f20b0;hp=7e2d59488684ee94196d0f5a2ae1a692b2393c9f;hpb=1cb0e90bf318d74999293d9d8813e8783f3eb3c6;p=hengband%2Fhengband.git diff --git a/src/bldg.c b/src/bldg.c index 7e2d59488..47eab3d57 100644 --- a/src/bldg.c +++ b/src/bldg.c @@ -13,9 +13,15 @@ */ #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" @@ -28,16 +34,38 @@ #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; + } + } + } +}