OSDN Git Service

b05e9f0260e76503bad847af6feed77ced8e0976
[hengband/hengband.git] / src / chest.c
1 
2 #include "angband.h"
3 #include "spells-summon.h"
4 #include "player-status.h"
5
6 /*!
7 * @brief 箱からアイテムを引き出す /
8 * Allocates objects upon opening a chest    -BEN-
9 * @param scatter TRUEならばトラップによるアイテムの拡散処理
10 * @param y 箱の存在するマスのY座標
11 * @param x 箱の存在するマスのX座標
12 * @param o_idx 箱のオブジェクトID
13 * @return なし
14 * @details
15 * <pre>
16 * Disperse treasures from the given chest, centered at (x,y).
17 *
18 * Small chests often contain "gold", while Large chests always contain
19 * items.  Wooden chests contain 2 items, Iron chests contain 4 items,
20 * and Steel chests contain 6 items.  The "value" of the items in a
21 * chest is based on the "power" of the chest, which is in current_world_ptr->game_turn based
22 * on the level on which the chest is generated.
23 * </pre>
24 */
25 void chest_death(bool scatter, POSITION y, POSITION x, OBJECT_IDX o_idx)
26 {
27         int number;
28
29         bool small;
30         BIT_FLAGS mode = AM_GOOD;
31
32         object_type forge;
33         object_type *q_ptr;
34
35         object_type *o_ptr = &current_floor_ptr->o_list[o_idx];
36
37
38         /* Small chests often hold "gold" */
39         small = (o_ptr->sval < SV_CHEST_MIN_LARGE);
40
41         /* Determine how much to drop (see above) */
42         number = (o_ptr->sval % SV_CHEST_MIN_LARGE) * 2;
43
44         if (o_ptr->sval == SV_CHEST_KANDUME)
45         {
46                 number = 5;
47                 small = FALSE;
48                 mode |= AM_GREAT;
49                 current_floor_ptr->object_level = o_ptr->xtra3;
50         }
51         else
52         {
53                 /* Determine the "value" of the items */
54                 current_floor_ptr->object_level = ABS(o_ptr->pval) + 10;
55         }
56
57         /* Zero pval means empty chest */
58         if (!o_ptr->pval) number = 0;
59
60         /* Opening a chest */
61         opening_chest = TRUE;
62
63         /* Drop some objects (non-chests) */
64         for (; number > 0; --number)
65         {
66                 q_ptr = &forge;
67                 object_wipe(q_ptr);
68
69                 /* Small chests often drop gold */
70                 if (small && (randint0(100) < 25))
71                 {
72                         /* Make some gold */
73                         if (!make_gold(q_ptr)) continue;
74                 }
75
76                 /* Otherwise drop an item */
77                 else
78                 {
79                         /* Make a good object */
80                         if (!make_object(q_ptr, mode)) continue;
81                 }
82
83                 /* If chest scatters its contents, pick any floor square. */
84                 if (scatter)
85                 {
86                         int i;
87                         for (i = 0; i < 200; i++)
88                         {
89                                 /* Pick a totally random spot. */
90                                 y = randint0(MAX_HGT);
91                                 x = randint0(MAX_WID);
92
93                                 /* Must be an empty floor. */
94                                 if (!cave_empty_bold(y, x)) continue;
95
96                                 /* Place the object there. */
97                                 (void)drop_near(q_ptr, -1, y, x);
98
99                                 /* Done. */
100                                 break;
101                         }
102                 }
103                 /* Normally, drop object near the chest. */
104                 else (void)drop_near(q_ptr, -1, y, x);
105         }
106
107         /* Reset the object level */
108         current_floor_ptr->object_level = current_floor_ptr->base_level;
109
110         /* No longer opening a chest */
111         opening_chest = FALSE;
112
113         /* Empty */
114         o_ptr->pval = 0;
115
116         /* Known */
117         object_known(o_ptr);
118 }
119
120
121 /*!
122 * @brief 箱のトラップ処理 /
123 * Chests have traps too.
124 * @param y 箱の存在するマスのY座標
125 * @param x 箱の存在するマスのX座標
126 * @param o_idx 箱のオブジェクトID
127 * @return なし
128 * @details
129 * <pre>
130 * Exploding chest destroys contents (and traps).
131 * Note that the chest itself is never destroyed.
132 * </pre>
133 */
134 void chest_trap(POSITION y, POSITION x, OBJECT_IDX o_idx)
135 {
136         int i, trap;
137
138         object_type *o_ptr = &current_floor_ptr->o_list[o_idx];
139
140         int mon_level = o_ptr->xtra3;
141
142         /* Ignore disarmed chests */
143         if (o_ptr->pval <= 0) return;
144
145         /* Obtain the traps */
146         trap = chest_traps[o_ptr->pval];
147
148         /* Lose strength */
149         if (trap & (CHEST_LOSE_STR))
150         {
151                 msg_print(_("仕掛けられていた小さな針に刺されてしまった!", "A small needle has pricked you!"));
152                 take_hit(DAMAGE_NOESCAPE, damroll(1, 4), _("毒針", "a poison needle"), -1);
153                 (void)do_dec_stat(A_STR);
154         }
155
156         /* Lose constitution */
157         if (trap & (CHEST_LOSE_CON))
158         {
159                 msg_print(_("仕掛けられていた小さな針に刺されてしまった!", "A small needle has pricked you!"));
160                 take_hit(DAMAGE_NOESCAPE, damroll(1, 4), _("毒針", "a poison needle"), -1);
161                 (void)do_dec_stat(A_CON);
162         }
163
164         /* Poison */
165         if (trap & (CHEST_POISON))
166         {
167                 msg_print(_("突如吹き出した緑色のガスに包み込まれた!", "A puff of green gas surrounds you!"));
168                 if (!(p_ptr->resist_pois || IS_OPPOSE_POIS()))
169                 {
170                         (void)set_poisoned(p_ptr->poisoned + 10 + randint1(20));
171                 }
172         }
173
174         /* Paralyze */
175         if (trap & (CHEST_PARALYZE))
176         {
177                 msg_print(_("突如吹き出した黄色いガスに包み込まれた!", "A puff of yellow gas surrounds you!"));
178                 if (!p_ptr->free_act)
179                 {
180                         (void)set_paralyzed(p_ptr->paralyzed + 10 + randint1(20));
181                 }
182         }
183
184         /* Summon monsters */
185         if (trap & (CHEST_SUMMON))
186         {
187                 int num = 2 + randint1(3);
188                 msg_print(_("突如吹き出した煙に包み込まれた!", "You are enveloped in a cloud of smoke!"));
189                 for (i = 0; i < num; i++)
190                 {
191                         if (randint1(100)<current_floor_ptr->dun_level)
192                                 activate_hi_summon(p_ptr->y, p_ptr->x, FALSE);
193                         else
194                                 (void)summon_specific(0, y, x, mon_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0');
195                 }
196         }
197
198         /* Elemental summon. */
199         if (trap & (CHEST_E_SUMMON))
200         {
201                 msg_print(_("宝を守るためにエレメンタルが現れた!", "Elemental beings appear to protect their treasures!"));
202                 for (i = 0; i < randint1(3) + 5; i++)
203                 {
204                         (void)summon_specific(0, y, x, mon_level, SUMMON_ELEMENTAL, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0');
205                 }
206         }
207
208         /* Force clouds, then summon birds. */
209         if (trap & (CHEST_BIRD_STORM))
210         {
211                 msg_print(_("鳥の群れがあなたを取り巻いた!", "A storm of birds swirls around you!"));
212
213                 for (i = 0; i < randint1(3) + 3; i++)
214                         (void)fire_meteor(-1, GF_FORCE, y, x, o_ptr->pval / 5, 7);
215
216                 for (i = 0; i < randint1(5) + o_ptr->pval / 5; i++)
217                 {
218                         (void)summon_specific(0, y, x, mon_level, SUMMON_BIRD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0');
219                 }
220         }
221
222         /* Various colorful summonings. */
223         if (trap & (CHEST_H_SUMMON))
224         {
225                 /* Summon demons. */
226                 if (one_in_(4))
227                 {
228                         msg_print(_("炎と硫黄の雲の中に悪魔が姿を現した!", "Demons materialize in clouds of fire and brimstone!"));
229                         for (i = 0; i < randint1(3) + 2; i++)
230                         {
231                                 (void)fire_meteor(-1, GF_FIRE, y, x, 10, 5);
232                                 (void)summon_specific(0, y, x, mon_level, SUMMON_DEMON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0');
233                         }
234                 }
235
236                 /* Summon dragons. */
237                 else if (one_in_(3))
238                 {
239                         msg_print(_("暗闇にドラゴンの影がぼんやりと現れた!", "Draconic forms loom out of the darkness!"));
240                         for (i = 0; i < randint1(3) + 2; i++)
241                         {
242                                 (void)summon_specific(0, y, x, mon_level, SUMMON_DRAGON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0');
243                         }
244                 }
245
246                 /* Summon hybrids. */
247                 else if (one_in_(2))
248                 {
249                         msg_print(_("奇妙な姿の怪物が襲って来た!", "Creatures strange and twisted assault you!"));
250                         for (i = 0; i < randint1(5) + 3; i++)
251                         {
252                                 (void)summon_specific(0, y, x, mon_level, SUMMON_HYBRID, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0');
253                         }
254                 }
255
256                 /* Summon vortices (scattered) */
257                 else
258                 {
259                         msg_print(_("渦巻が合体し、破裂した!", "Vortices coalesce and wreak destruction!"));
260                         for (i = 0; i < randint1(3) + 2; i++)
261                         {
262                                 (void)summon_specific(0, y, x, mon_level, SUMMON_VORTEX, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0');
263                         }
264                 }
265         }
266
267         /* Dispel player. */
268         if ((trap & (CHEST_RUNES_OF_EVIL)) && o_ptr->k_idx)
269         {
270                 /* Determine how many nasty tricks can be played. */
271                 int nasty_tricks_count = 4 + randint0(3);
272
273                 msg_print(_("恐ろしい声が響いた:  「暗闇が汝をつつまん!」", "Hideous voices bid:  'Let the darkness have thee!'"));
274                 /* This is gonna hurt... */
275                 for (; nasty_tricks_count > 0; nasty_tricks_count--)
276                 {
277                         /* ...but a high saving throw does help a little. */
278                         if (randint1(100 + o_ptr->pval * 2) > p_ptr->skill_sav)
279                         {
280                                 if (one_in_(6)) take_hit(DAMAGE_NOESCAPE, damroll(5, 20), _("破滅のトラップの宝箱", "a chest dispel-player trap"), -1);
281                                 else if (one_in_(5)) (void)set_cut(p_ptr->cut + 200);
282                                 else if (one_in_(4))
283                                 {
284                                         if (!p_ptr->free_act)
285                                                 (void)set_paralyzed(p_ptr->paralyzed + 2 +
286                                                         randint0(6));
287                                         else
288                                                 (void)set_stun(p_ptr->stun + 10 +
289                                                         randint0(100));
290                                 }
291                                 else if (one_in_(3)) apply_disenchant(0);
292                                 else if (one_in_(2))
293                                 {
294                                         (void)do_dec_stat(A_STR);
295                                         (void)do_dec_stat(A_DEX);
296                                         (void)do_dec_stat(A_CON);
297                                         (void)do_dec_stat(A_INT);
298                                         (void)do_dec_stat(A_WIS);
299                                         (void)do_dec_stat(A_CHR);
300                                 }
301                                 else (void)fire_meteor(-1, GF_NETHER, y, x, 150, 1);
302                         }
303                 }
304         }
305
306         /* Aggravate monsters. */
307         if (trap & (CHEST_ALARM))
308         {
309                 msg_print(_("けたたましい音が鳴り響いた!", "An alarm sounds!"));
310                 aggravate_monsters(0);
311         }
312
313         /* Explode */
314         if ((trap & (CHEST_EXPLODE)) && o_ptr->k_idx)
315         {
316                 msg_print(_("突然、箱が爆発した!", "There is a sudden explosion!"));
317                 msg_print(_("箱の中の物はすべて粉々に砕け散った!", "Everything inside the chest is destroyed!"));
318                 o_ptr->pval = 0;
319                 sound(SOUND_EXPLODE);
320                 take_hit(DAMAGE_ATTACK, damroll(5, 8), _("爆発する箱", "an exploding chest"), -1);
321         }
322         /* Scatter contents. */
323         if ((trap & (CHEST_SCATTER)) && o_ptr->k_idx)
324         {
325                 msg_print(_("宝箱の中身はダンジョンじゅうに散乱した!", "The contents of the chest scatter all over the dungeon!"));
326                 chest_death(TRUE, y, x, o_idx);
327                 o_ptr->pval = 0;
328         }
329 }
330