1 #include "market/arena.h"
2 #include "cmd-building/cmd-building.h"
3 #include "core/asking-player.h"
4 #include "core/show-file.h"
5 #include "core/stuff-handler.h"
6 #include "core/window-redrawer.h"
7 #include "dungeon/dungeon.h"
8 #include "floor/floor-mode-changer.h"
9 #include "io/input-key-acceptor.h"
10 #include "main/sound-of-music.h"
11 #include "market/arena-info-table.h"
12 #include "market/building-actions-table.h"
13 #include "market/building-util.h"
14 #include "monster-race/monster-race-hook.h"
15 #include "monster-race/monster-race.h"
16 #include "monster-race/race-flags-resistance.h"
17 #include "monster-race/race-flags1.h"
18 #include "monster-race/race-flags7.h"
19 #include "monster/monster-list.h"
20 #include "monster/monster-util.h"
21 #include "status/buff-setter.h"
22 #include "system/building-type-definition.h"
23 #include "system/floor-type-definition.h"
24 #include "term/screen-processor.h"
25 #include "util/int-char-converter.h"
26 #include "view/display-messages.h"
27 #include "world/world.h"
30 * @brief 優勝時のメッセージを表示し、賞金を与える
31 * @param player_ptr プレーヤーへの参照ポインタ
32 * @return まだ優勝していないか、挑戦者モンスターとの戦いではFALSE
34 static bool process_ostensible_arena_victory(player_type *player_ptr)
36 if (player_ptr->arena_number != MAX_ARENA_MONS)
40 prt(_("アリーナの優勝者!", " Arena Victor!"), 5, 0);
41 prt(_("おめでとう!あなたは全ての敵を倒しました。", "Congratulations! You have defeated all before you."), 7, 0);
42 prt(_("賞金として $1,000,000 が与えられます。", "For that, receive the prize: 1,000,000 gold pieces"), 8, 0);
46 player_ptr->au += 1000000L;
47 msg_print(_("スペースキーで続行", "Press the space bar to continue"));
49 player_ptr->arena_number++;
55 * @param player_ptr プレーヤーへの参照ポインタ
56 * @return まだパワー・ワイアーム以下を倒していないならFALSE、倒していたらTRUE
58 static bool battle_metal_babble(player_type *player_ptr)
60 if (player_ptr->arena_number <= MAX_ARENA_MONS)
63 if (player_ptr->arena_number >= MAX_ARENA_MONS + 2) {
64 msg_print(_("あなたはアリーナに入り、しばらくの間栄光にひたった。", "You enter the arena briefly and bask in your glory."));
69 msg_print(_("君のために最強の挑戦者を用意しておいた。", "The strongest challenger is waiting for you."));
71 if (!get_check(_("挑戦するかね?", "Do you fight? "))) {
72 msg_print(_("残念だ。", "We are disappointed."));
76 msg_print(_("死ぬがよい。", "Die, maggots."));
79 player_ptr->exit_bldg = FALSE;
80 reset_tim_flags(player_ptr);
82 /* Save the surface floor as saved floor */
83 prepare_change_floor_mode(player_ptr, CFM_SAVE_FLOORS);
85 player_ptr->current_floor_ptr->inside_arena = TRUE;
86 player_ptr->leaving = TRUE;
87 player_ptr->leave_bldg = TRUE;
91 static void go_to_arena(player_type *player_ptr)
93 if (process_ostensible_arena_victory(player_ptr))
96 if (battle_metal_babble(player_ptr))
99 if (player_ptr->riding && (player_ptr->pclass != CLASS_BEASTMASTER) && (player_ptr->pclass != CLASS_CAVALRY)) {
100 msg_print(_("ペットに乗ったままではアリーナへ入れさせてもらえなかった。", "You don't have permission to enter with pet."));
105 player_ptr->exit_bldg = FALSE;
106 reset_tim_flags(player_ptr);
107 prepare_change_floor_mode(player_ptr, CFM_SAVE_FLOORS);
109 player_ptr->current_floor_ptr->inside_arena = TRUE;
110 player_ptr->leaving = TRUE;
111 player_ptr->leave_bldg = TRUE;
114 static void see_arena_poster(player_type *player_ptr)
116 if (player_ptr->arena_number == MAX_ARENA_MONS) {
117 msg_print(_("あなたは勝利者だ。 アリーナでのセレモニーに参加しなさい。", "You are victorious. Enter the arena for the ceremony."));
121 if (player_ptr->arena_number > MAX_ARENA_MONS) {
122 msg_print(_("あなたはすべての敵に勝利した。", "You have won against all foes."));
127 r_ptr = &r_info[arena_info[player_ptr->arena_number].r_idx];
128 concptr name = r_ptr->name.c_str();
129 msg_format(_("%s に挑戦するものはいないか?", "Do I hear any challenges against: %s"), name);
131 player_ptr->monster_race_idx = arena_info[player_ptr->arena_number].r_idx;
132 player_ptr->window_flags |= (PW_MONSTER);
133 handle_stuff(player_ptr);
137 * @brief 闘技場に入るコマンドの処理 / on_defeat_arena_monster commands
138 * @param player_ptr プレーヤーへの参照ポインタ
139 * @param cmd 闘技場処理のID
142 void arena_comm(player_type *player_ptr, int cmd)
146 go_to_arena(player_ptr);
149 see_arena_poster(player_ptr);
151 case BACT_ARENA_RULES:
154 /* Peruse the on_defeat_arena_monster help file */
155 (void)show_file(player_ptr, TRUE, _("arena_j.txt", "arena.txt"), NULL, 0, 0);
162 * @brief モンスター闘技場に参加するモンスターを更新する。
163 * @param player_ptr プレーヤーへの参照ポインタ
166 void update_gambling_monsters(player_type *player_ptr)
174 for (i = 0; i < current_world_ptr->max_d_idx; i++) {
175 if (max_dl < max_dlv[i])
179 mon_level = randint1(MIN(max_dl, 122)) + 5;
180 if (randint0(100) < 60) {
181 i = randint1(MIN(max_dl, 122)) + 5;
182 mon_level = MAX(i, mon_level);
185 if (randint0(100) < 30) {
186 i = randint1(MIN(max_dl, 122)) + 5;
187 mon_level = MAX(i, mon_level);
193 for (i = 0; i < 4; i++) {
197 get_mon_num_prep(player_ptr, monster_can_entry_arena, NULL);
198 r_idx = get_mon_num(player_ptr, 0, mon_level, GMN_ARENA);
202 if ((r_info[r_idx].flags1 & RF1_UNIQUE) || (r_info[r_idx].flags7 & RF7_UNIQUE2)) {
203 if ((r_info[r_idx].level + 10) > mon_level)
207 for (j = 0; j < i; j++)
208 if (r_idx == battle_mon[j])
215 battle_mon[i] = r_idx;
216 if (r_info[r_idx].level < 45)
220 for (i = 0; i < 4; i++) {
221 monster_race *r_ptr = &r_info[battle_mon[i]];
222 int num_taisei = count_bits(r_ptr->flagsr & (RFR_IM_ACID | RFR_IM_ELEC | RFR_IM_FIRE | RFR_IM_COLD | RFR_IM_POIS));
224 if (r_ptr->flags1 & RF1_FORCE_MAXHP)
225 power[i] = r_ptr->hdice * r_ptr->hside * 2;
227 power[i] = r_ptr->hdice * (r_ptr->hside + 1);
228 power[i] = power[i] * (100 + r_ptr->level) / 100;
229 if (r_ptr->speed > 110)
230 power[i] = power[i] * (r_ptr->speed * 2 - 110) / 100;
231 if (r_ptr->speed < 110)
232 power[i] = power[i] * (r_ptr->speed - 20) / 100;
234 power[i] = power[i] * (num_taisei * 2 + 5) / 10;
235 else if (r_ptr->ability_flags.has(RF_ABILITY::INVULNER))
236 power[i] = power[i] * 4 / 3;
237 else if (r_ptr->ability_flags.has(RF_ABILITY::HEAL))
238 power[i] = power[i] * 4 / 3;
239 else if (r_ptr->ability_flags.has(RF_ABILITY::DRAIN_MANA))
240 power[i] = power[i] * 11 / 10;
241 if (r_ptr->flags1 & RF1_RAND_25)
242 power[i] = power[i] * 9 / 10;
243 if (r_ptr->flags1 & RF1_RAND_50)
244 power[i] = power[i] * 9 / 10;
245 if (r_ptr->flagsr & RFR_RES_ALL)
247 if (r_ptr->arena_ratio)
248 power[i] = power[i] * r_ptr->arena_ratio / 100;
252 for (i = 0; i < 4; i++) {
255 power[i] = total * 60 / power[i];
256 if (tekitou && ((power[i] < 160) || power[i] > 1500))
258 if ((power[i] < 160) && randint0(20))
261 power[i] = 100 + randint1(5);
262 mon_odds[i] = power[i];
271 * @brief モンスター闘技場のメインルーチン
272 * @param player_ptr プレーヤーへの参照ポインタ
275 bool monster_arena_comm(player_type *player_ptr)
279 char out_val[MAX_MONSTER_NAME], tmp_str[80];
282 if ((current_world_ptr->game_turn - current_world_ptr->arena_start_turn) > TURNS_PER_TICK * 250) {
283 update_gambling_monsters(player_ptr);
284 current_world_ptr->arena_start_turn = current_world_ptr->game_turn;
290 if (player_ptr->au <= 1) {
291 msg_print(_("おい!おまえ一文なしじゃないか!こっから出ていけ!", "Hey! You don't have gold - get out of here!"));
299 prt(_("モンスター 倍率", "Monsters Odds"), 4, 4);
300 for (int i = 0; i < 4; i++) {
301 char buf[MAX_MONSTER_NAME];
302 monster_race *r_ptr = &r_info[battle_mon[i]];
304 sprintf(buf, _("%d) %-58s %4ld.%02ld倍", "%d) %-58s %4ld.%02ld"), i + 1,
305 _(format("%s%s", r_ptr->name.c_str(), (r_ptr->flags1 & RF1_UNIQUE) ? "もどき" : " "),
306 format("%s%s", (r_ptr->flags1 & RF1_UNIQUE) ? "Fake " : "", r_ptr->name.c_str())),
307 (long int)mon_odds[i] / 100, (long int)mon_odds[i] % 100);
311 prt(_("どれに賭けますか:", "Which monster: "), 0, 0);
320 if (i >= '1' && i <= '4') {
321 sel_monster = i - '1';
322 battle_odds = mon_odds[sel_monster];
331 for (int i = 0; i < 4; i++)
332 if (i != sel_monster)
333 clear_bldg(i + 5, i + 5);
335 maxbet = player_ptr->lev * 200;
337 /* We can't bet more than we have */
338 maxbet = MIN(maxbet, player_ptr->au);
342 sprintf(tmp_str, _("賭け金 (1-%ld)?", "Your wager (1-%ld) ? "), (long int)maxbet);
345 * Use get_string() because we may need more than
346 * the s16b value returned by get_quantity().
348 if (!get_string(tmp_str, out_val, 32)) {
353 for (p = out_val; *p == ' '; p++)
357 if (wager > player_ptr->au) {
358 msg_print(_("おい!金が足りないじゃないか!出ていけ!", "Hey! You don't have the gold - get out of here!"));
363 } else if (wager > maxbet) {
364 msg_format(_("%ldゴールドだけ受けよう。残りは取っときな。", "I'll take %ld gold of that. Keep the rest."), (long int)maxbet);
367 } else if (wager < 1) {
368 msg_print(_("OK、1ゴールドでいこう。", "Ok, we'll start with 1 gold."));
373 battle_odds = MAX(wager + 1, wager * battle_odds / 100);
375 player_ptr->au -= wager;
376 reset_tim_flags(player_ptr);
378 prepare_change_floor_mode(player_ptr, CFM_SAVE_FLOORS);
380 player_ptr->phase_out = TRUE;
381 player_ptr->leaving = TRUE;
382 player_ptr->leave_bldg = TRUE;