1 #include "system/angband.h"
2 #include "object/chest.h"
4 #include "main/sound-definitions-table.h"
6 #include "spell/spells-type.h"
7 #include "spell/spells-summon.h"
8 #include "floor/floor.h"
10 #include "player/player-status.h"
11 #include "player/player-damage.h"
12 #include "player/player-class.h"
13 #include "player/player-effects.h"
15 #include "spell/spells2.h"
16 #include "spell/spells3.h"
19 * @brief 箱からアイテムを引き出す /
20 * Allocates objects upon opening a chest -BEN-
21 * @param scatter TRUEならばトラップによるアイテムの拡散処理
22 * @param y 箱の存在するマスのY座標
23 * @param x 箱の存在するマスのX座標
24 * @param o_idx 箱のオブジェクトID
28 * Disperse treasures from the given chest, centered at (x,y).
30 * Small chests often contain "gold", while Large chests always contain
31 * items. Wooden chests contain 2 items, Iron chests contain 4 items,
32 * and Steel chests contain 6 items. The "value" of the items in a
33 * chest is based on the "power" of the chest, which is in turn based
34 * on the level on which the chest is generated.
37 void chest_death(player_type *owner_ptr, bool scatter, POSITION y, POSITION x, OBJECT_IDX o_idx)
42 BIT_FLAGS mode = AM_GOOD | AM_FORBID_CHEST;
47 floor_type *floor_ptr = owner_ptr->current_floor_ptr;
48 object_type *o_ptr = &floor_ptr->o_list[o_idx];
50 /* Small chests often hold "gold" */
51 small = (o_ptr->sval < SV_CHEST_MIN_LARGE);
53 /* Determine how much to drop (see above) */
54 number = (o_ptr->sval % SV_CHEST_MIN_LARGE) * 2;
56 if (o_ptr->sval == SV_CHEST_KANDUME)
61 floor_ptr->object_level = o_ptr->xtra3;
65 /* Determine the "value" of the items */
66 floor_ptr->object_level = ABS(o_ptr->pval) + 10;
69 /* Zero pval means empty chest */
70 if (!o_ptr->pval) number = 0;
73 /* Drop some objects (non-chests) */
74 for (; number > 0; --number)
79 /* Small chests often drop gold */
80 if (small && (randint0(100) < 25))
83 if (!make_gold(floor_ptr, q_ptr)) continue;
86 /* Otherwise drop an item */
89 /* Make a good object */
90 if (!make_object(owner_ptr, q_ptr, mode)) continue;
93 /* If chest scatters its contents, pick any floor square. */
97 for (i = 0; i < 200; i++)
99 /* Pick a totally random spot. */
100 y = randint0(MAX_HGT);
101 x = randint0(MAX_WID);
103 /* Must be an empty floor. */
104 if (!is_cave_empty_bold(owner_ptr, y, x)) continue;
106 /* Place the object there. */
107 (void)drop_near(owner_ptr, q_ptr, -1, y, x);
113 /* Normally, drop object near the chest. */
114 else (void)drop_near(owner_ptr, q_ptr, -1, y, x);
117 /* Reset the object level */
118 floor_ptr->object_level = floor_ptr->base_level;
130 * Chests have traps too.
131 * @param y 箱の存在するマスのY座標
132 * @param x 箱の存在するマスのX座標
133 * @param o_idx 箱のオブジェクトID
137 * Exploding chest destroys contents (and traps).
138 * Note that the chest itself is never destroyed.
141 void chest_trap(player_type *target_ptr, POSITION y, POSITION x, OBJECT_IDX o_idx)
145 object_type *o_ptr = &target_ptr->current_floor_ptr->o_list[o_idx];
147 int mon_level = o_ptr->xtra3;
149 /* Ignore disarmed chests */
150 if (o_ptr->pval <= 0) return;
152 /* Obtain the traps */
153 trap = chest_traps[o_ptr->pval];
156 if (trap & (CHEST_LOSE_STR))
158 msg_print(_("仕掛けられていた小さな針に刺されてしまった!", "A small needle has pricked you!"));
159 take_hit(target_ptr, DAMAGE_NOESCAPE, damroll(1, 4), _("毒針", "a poison needle"), -1);
160 (void)do_dec_stat(target_ptr, A_STR);
163 /* Lose constitution */
164 if (trap & (CHEST_LOSE_CON))
166 msg_print(_("仕掛けられていた小さな針に刺されてしまった!", "A small needle has pricked you!"));
167 take_hit(target_ptr, DAMAGE_NOESCAPE, damroll(1, 4), _("毒針", "a poison needle"), -1);
168 (void)do_dec_stat(target_ptr, A_CON);
172 if (trap & (CHEST_POISON))
174 msg_print(_("突如吹き出した緑色のガスに包み込まれた!", "A puff of green gas surrounds you!"));
175 if (!(target_ptr->resist_pois || is_oppose_pois(target_ptr)))
177 (void)set_poisoned(target_ptr, target_ptr->poisoned + 10 + randint1(20));
182 if (trap & (CHEST_PARALYZE))
184 msg_print(_("突如吹き出した黄色いガスに包み込まれた!", "A puff of yellow gas surrounds you!"));
185 if (!target_ptr->free_act)
187 (void)set_paralyzed(target_ptr, target_ptr->paralyzed + 10 + randint1(20));
191 /* Summon monsters */
192 if (trap & (CHEST_SUMMON))
194 int num = 2 + randint1(3);
195 msg_print(_("突如吹き出した煙に包み込まれた!", "You are enveloped in a cloud of smoke!"));
196 for (i = 0; i < num; i++)
198 if (randint1(100)<target_ptr->current_floor_ptr->dun_level)
199 activate_hi_summon(target_ptr, target_ptr->y, target_ptr->x, FALSE);
201 (void)summon_specific(target_ptr, 0, y, x, mon_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
205 /* Elemental summon. */
206 if (trap & (CHEST_E_SUMMON))
208 msg_print(_("宝を守るためにエレメンタルが現れた!", "Elemental beings appear to protect their treasures!"));
209 for (i = 0; i < randint1(3) + 5; i++)
211 (void)summon_specific(target_ptr, 0, y, x, mon_level, SUMMON_ELEMENTAL, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
215 /* Force clouds, then summon birds. */
216 if (trap & (CHEST_BIRD_STORM))
218 msg_print(_("鳥の群れがあなたを取り巻いた!", "A storm of birds swirls around you!"));
220 for (i = 0; i < randint1(3) + 3; i++)
221 (void)fire_meteor(target_ptr, -1, GF_FORCE, y, x, o_ptr->pval / 5, 7);
223 for (i = 0; i < randint1(5) + o_ptr->pval / 5; i++)
225 (void)summon_specific(target_ptr, 0, y, x, mon_level, SUMMON_BIRD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
229 /* Various colorful summonings. */
230 if (trap & (CHEST_H_SUMMON))
235 msg_print(_("炎と硫黄の雲の中に悪魔が姿を現した!", "Demons materialize in clouds of fire and brimstone!"));
236 for (i = 0; i < randint1(3) + 2; i++)
238 (void)fire_meteor(target_ptr, -1, GF_FIRE, y, x, 10, 5);
239 (void)summon_specific(target_ptr, 0, y, x, mon_level, SUMMON_DEMON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
243 /* Summon dragons. */
246 msg_print(_("暗闇にドラゴンの影がぼんやりと現れた!", "Draconic forms loom out of the darkness!"));
247 for (i = 0; i < randint1(3) + 2; i++)
249 (void)summon_specific(target_ptr, 0, y, x, mon_level, SUMMON_DRAGON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
253 /* Summon hybrids. */
256 msg_print(_("奇妙な姿の怪物が襲って来た!", "Creatures strange and twisted assault you!"));
257 for (i = 0; i < randint1(5) + 3; i++)
259 (void)summon_specific(target_ptr, 0, y, x, mon_level, SUMMON_HYBRID, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
263 /* Summon vortices (scattered) */
266 msg_print(_("渦巻が合体し、破裂した!", "Vortices coalesce and wreak destruction!"));
267 for (i = 0; i < randint1(3) + 2; i++)
269 (void)summon_specific(target_ptr, 0, y, x, mon_level, SUMMON_VORTEX, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
275 if ((trap & (CHEST_RUNES_OF_EVIL)) && o_ptr->k_idx)
277 /* Determine how many nasty tricks can be played. */
278 int nasty_tricks_count = 4 + randint0(3);
280 msg_print(_("恐ろしい声が響いた: 「暗闇が汝をつつまん!」", "Hideous voices bid: 'Let the darkness have thee!'"));
281 /* This is gonna hurt... */
282 for (; nasty_tricks_count > 0; nasty_tricks_count--)
284 /* ...but a high saving throw does help a little. */
285 if (randint1(100 + o_ptr->pval * 2) > target_ptr->skill_sav)
287 if (one_in_(6)) take_hit(target_ptr, DAMAGE_NOESCAPE, damroll(5, 20), _("破滅のトラップの宝箱", "a chest dispel-player trap"), -1);
288 else if (one_in_(5)) (void)set_cut(target_ptr,target_ptr->cut + 200);
291 if (!target_ptr->free_act)
292 (void)set_paralyzed(target_ptr, target_ptr->paralyzed + 2 +
295 (void)set_stun(target_ptr, target_ptr->stun + 10 +
298 else if (one_in_(3)) apply_disenchant(target_ptr, 0);
301 (void)do_dec_stat(target_ptr, A_STR);
302 (void)do_dec_stat(target_ptr, A_DEX);
303 (void)do_dec_stat(target_ptr, A_CON);
304 (void)do_dec_stat(target_ptr, A_INT);
305 (void)do_dec_stat(target_ptr, A_WIS);
306 (void)do_dec_stat(target_ptr, A_CHR);
308 else (void)fire_meteor(target_ptr, -1, GF_NETHER, y, x, 150, 1);
313 /* Aggravate monsters. */
314 if (trap & (CHEST_ALARM))
316 msg_print(_("けたたましい音が鳴り響いた!", "An alarm sounds!"));
317 aggravate_monsters(target_ptr, 0);
321 if ((trap & (CHEST_EXPLODE)) && o_ptr->k_idx)
323 msg_print(_("突然、箱が爆発した!", "There is a sudden explosion!"));
324 msg_print(_("箱の中の物はすべて粉々に砕け散った!", "Everything inside the chest is destroyed!"));
326 sound(SOUND_EXPLODE);
327 take_hit(target_ptr, DAMAGE_ATTACK, damroll(5, 8), _("爆発する箱", "an exploding chest"), -1);
329 /* Scatter contents. */
330 if ((trap & (CHEST_SCATTER)) && o_ptr->k_idx)
332 msg_print(_("宝箱の中身はダンジョンじゅうに散乱した!", "The contents of the chest scatter all over the dungeon!"));
333 chest_death(target_ptr, TRUE, y, x, o_idx);