OSDN Git Service

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