OSDN Git Service

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