OSDN Git Service

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