Revert "Track who destroys an item; incur Nemelex penance for deck destruction."
[crawl.git] / crawl-ref / source / misc.cc
1 /**
2  * @file
3  * @brief Misc functions.
4 **/
5
6 #include "AppHdr.h"
7
8 #include "misc.h"
9
10 #include <string.h>
11 #include <algorithm>
12
13 #if !defined(__IBMCPP__) && !defined(TARGET_COMPILER_VC)
14 #include <unistd.h>
15 #endif
16
17 #include <cstdlib>
18 #include <cstdio>
19 #include <cmath>
20
21 #include "externs.h"
22 #include "misc.h"
23
24 #include "abyss.h"
25 #include "areas.h"
26 #include "artefact.h"
27 #include "clua.h"
28 #include "cloud.h"
29 #include "coordit.h"
30 #include "database.h"
31 #include "delay.h"
32 #include "describe.h"
33 #include "dgn-shoals.h"
34 #include "dgnevent.h"
35 #include "env.h"
36 #include "exercise.h"
37 #include "feature.h"
38 #include "fight.h"
39 #include "files.h"
40 #include "fprop.h"
41 #include "food.h"
42 #include "ghost.h"
43 #include "godabil.h"
44 #include "godpassive.h"
45 #include "itemname.h"
46 #include "itemprop.h"
47 #include "items.h"
48 #include "item_use.h"
49 #include "libutil.h"
50 #include "makeitem.h"
51 #include "mapmark.h"
52 #include "message.h"
53 #include "mgen_data.h"
54 #include "mon-death.h"
55 #include "mon-place.h"
56 #include "mon-pathfind.h"
57 #include "mon-info.h"
58 #include "mon-iter.h"
59 #include "mon-stuff.h"
60 #include "ng-setup.h"
61 #include "notes.h"
62 #include "ouch.h"
63 #include "player.h"
64 #include "player-stats.h"
65 #include "random.h"
66 #include "religion.h"
67 #include "godconduct.h"
68 #include "shopping.h"
69 #include "skills.h"
70 #include "skills2.h"
71 #include "spl-clouds.h"
72 #include "state.h"
73 #include "stuff.h"
74 #include "target.h"
75 #include "terrain.h"
76 #include "tileview.h"
77 #include "transform.h"
78 #include "traps.h"
79 #include "travel.h"
80 #include "hints.h"
81 #include "view.h"
82 #include "shout.h"
83 #include "xom.h"
84
85 static void _create_monster_hide(const item_def corpse)
86 {
87     // kiku_receive_corpses() creates corpses that are easily scummed
88     // for hides.  We prevent this by setting "never_hide" as an item
89     // property of corpses it creates.
90     if (corpse.props.exists("never_hide"))
91         return;
92
93     monster_type mons_class = corpse.mon_type;
94     armour_type type;
95
96     // These values cannot be set by a reasonable formula: {dlb}
97     if (mons_genus(mons_class) == MONS_TROLL)
98         mons_class = MONS_TROLL;
99     switch (mons_class)
100     {
101     case MONS_DRAGON:         type = ARM_FIRE_DRAGON_HIDE;    break;
102     case MONS_TROLL:          type = ARM_TROLL_HIDE;          break;
103     case MONS_ICE_DRAGON:     type = ARM_ICE_DRAGON_HIDE;     break;
104     case MONS_STEAM_DRAGON:   type = ARM_STEAM_DRAGON_HIDE;   break;
105     case MONS_MOTTLED_DRAGON: type = ARM_MOTTLED_DRAGON_HIDE; break;
106     case MONS_STORM_DRAGON:   type = ARM_STORM_DRAGON_HIDE;   break;
107     case MONS_GOLDEN_DRAGON:  type = ARM_GOLD_DRAGON_HIDE;    break;
108     case MONS_SWAMP_DRAGON:   type = ARM_SWAMP_DRAGON_HIDE;   break;
109     case MONS_PEARL_DRAGON:   type = ARM_PEARL_DRAGON_HIDE;   break;
110     default:
111         die("an unknown hide drop");
112     }
113
114     int o = items(0, OBJ_ARMOUR, type, true, 0, MAKE_ITEM_NO_RACE, 0, 0, -1,
115                   true);
116     if (o == NON_ITEM)
117         return;
118     item_def& item = mitm[o];
119
120     do_uncurse_item(item, false);
121     const monster_type montype =
122         static_cast<monster_type>(corpse.orig_monnum);
123     if (!invalid_monster_type(montype) && mons_is_unique(montype))
124         item.inscription = mons_type_name(montype, DESC_PLAIN);
125
126     const coord_def pos = item_pos(corpse);
127     if (!pos.origin())
128         move_item_to_grid(&o, pos);
129 }
130
131 void maybe_drop_monster_hide(const item_def corpse)
132 {
133     if (monster_descriptor(corpse.mon_type, MDSC_LEAVES_HIDE) && !one_chance_in(3))
134         _create_monster_hide(corpse);
135 }
136
137 int get_max_corpse_chunks(monster_type mons_class)
138 {
139     return (mons_weight(mons_class) / 150);
140 }
141
142 void turn_corpse_into_skeleton(item_def &item)
143 {
144     ASSERT(item.base_type == OBJ_CORPSES);
145     ASSERT(item.sub_type == CORPSE_BODY);
146
147     // Some monsters' corpses lack the structure to leave skeletons
148     // behind.
149     if (!mons_skeleton(item.mon_type))
150         return;
151
152     item.sub_type = CORPSE_SKELETON;
153     item.special  = FRESHEST_CORPSE; // reset rotting counter
154     item.colour   = LIGHTGREY;
155 }
156
157 static void _maybe_bleed_monster_corpse(const item_def corpse)
158 {
159     // Only fresh corpses bleed enough to colour the ground.
160     if (!food_is_rotten(corpse))
161     {
162         const coord_def pos = item_pos(corpse);
163         if (!pos.origin())
164         {
165             const int max_chunks = get_max_corpse_chunks(corpse.mon_type);
166             bleed_onto_floor(pos, corpse.mon_type, max_chunks, true);
167         }
168     }
169 }
170
171 void turn_corpse_into_chunks(item_def &item, bool bloodspatter,
172                              bool make_hide)
173 {
174     ASSERT(item.base_type == OBJ_CORPSES);
175     ASSERT(item.sub_type == CORPSE_BODY);
176     const item_def corpse = item;
177     const int max_chunks = get_max_corpse_chunks(item.mon_type);
178
179     // Only fresh corpses bleed enough to colour the ground.
180     if (bloodspatter)
181         _maybe_bleed_monster_corpse(corpse);
182
183     item.base_type = OBJ_FOOD;
184     item.sub_type  = FOOD_CHUNK;
185     item.quantity  = 1 + random2(max_chunks);
186     item.quantity  = stepdown_value(item.quantity, 4, 4, 12, 12);
187
188     // Don't mark it as dropped if we are forcing autopickup of chunks.
189     if (is_bad_food(item) && you.force_autopickup[OBJ_FOOD][FOOD_CHUNK] <= 0)
190         item.flags |= ISFLAG_DROPPED;
191     else if (you.species != SP_VAMPIRE)
192         item.flags &= ~(ISFLAG_THROWN | ISFLAG_DROPPED);
193
194     // Happens after the corpse has been butchered.
195     if (make_hide)
196         maybe_drop_monster_hide(corpse);
197 }
198
199 static void _turn_corpse_into_skeleton_and_chunks(item_def &item, bool prefer_chunks)
200 {
201     item_def copy = item;
202
203     // Complicated logic, but unless we use the original, both could fail if
204     // mitm[] is overstuffed.
205     if (prefer_chunks)
206     {
207         turn_corpse_into_chunks(item);
208         turn_corpse_into_skeleton(copy);
209     }
210     else
211     {
212         turn_corpse_into_chunks(copy);
213         turn_corpse_into_skeleton(item);
214     }
215
216     copy_item_to_grid(copy, item_pos(item));
217 }
218
219 void butcher_corpse(item_def &item, maybe_bool skeleton, bool chunks)
220 {
221     item_was_destroyed(item);
222     if (!mons_skeleton(item.mon_type))
223         skeleton = MB_FALSE;
224     if (skeleton == MB_TRUE || skeleton == MB_MAYBE && one_chance_in(3))
225     {
226         if (chunks)
227             _turn_corpse_into_skeleton_and_chunks(item, skeleton != MB_TRUE);
228         else
229         {
230             _maybe_bleed_monster_corpse(item);
231             maybe_drop_monster_hide(item);
232             turn_corpse_into_skeleton(item);
233         }
234     }
235     else
236     {
237         if (chunks)
238             turn_corpse_into_chunks(item);
239         else
240         {
241             _maybe_bleed_monster_corpse(item);
242             maybe_drop_monster_hide(item);
243             destroy_item(item.index());
244         }
245     }
246 }
247
248 // Initialise blood potions with a vector of timers.
249 void init_stack_blood_potions(item_def &stack, int age)
250 {
251     ASSERT(is_blood_potion(stack));
252
253     CrawlHashTable &props = stack.props;
254     props.clear(); // sanity measure
255     props["timer"].new_vector(SV_INT, SFLAG_CONST_TYPE);
256     CrawlVector &timer = props["timer"].get_vector();
257
258     if (age == -1)
259     {
260         if (stack.sub_type == POT_BLOOD)
261             age = 2500;
262         else // coagulated blood
263             age = 500;
264     }
265     // For a newly created stack, all potions use the same timer.
266     const int max_age = you.num_turns + age;
267 #ifdef DEBUG_BLOOD_POTIONS
268     mprf(MSGCH_DIAGNOSTICS, "newly created stack will time out at turn %d",
269                             max_age);
270 #endif
271     for (int i = 0; i < stack.quantity; i++)
272         timer.push_back(max_age);
273
274     stack.special = 0;
275     ASSERT(timer.size() == stack.quantity);
276     props.assert_validity();
277 }
278
279 // Sort a CrawlVector<int>, should probably be done properly with templates.
280 static void _int_sort(CrawlVector &vec)
281 {
282     vector<int> help;
283     while (!vec.empty())
284     {
285         help.push_back(vec[vec.size()-1].get_int());
286         vec.pop_back();
287     }
288
289     sort(help.begin(), help.end());
290
291     while (!help.empty())
292     {
293         vec.push_back(help[help.size()-1]);
294         help.pop_back();
295     }
296 }
297
298 static void _compare_blood_quantity(item_def &stack, int timer_size)
299 {
300     if (timer_size != stack.quantity)
301     {
302         mprf(MSGCH_WARN,
303              "ERROR: blood potion quantity (%d) doesn't match timer (%d)",
304              stack.quantity, timer_size);
305
306         // sanity measure
307         stack.quantity = timer_size;
308     }
309 }
310
311 void maybe_coagulate_blood_potions_floor(int obj)
312 {
313     item_def &blood = mitm[obj];
314     ASSERT(blood.defined());
315     ASSERT(is_blood_potion(blood));
316
317     CrawlHashTable &props = blood.props;
318     if (!props.exists("timer"))
319         init_stack_blood_potions(blood, blood.special);
320
321     ASSERT(props.exists("timer"));
322     CrawlVector &timer = props["timer"].get_vector();
323     ASSERT(!timer.empty());
324     _compare_blood_quantity(blood, timer.size());
325
326     // blood.sub_type could be POT_BLOOD or POT_BLOOD_COAGULATED
327     // -> need different handling
328     int rot_limit  = you.num_turns;
329     int coag_limit = you.num_turns + 500; // check 500 turns later
330
331     // First count whether coagulating is even necessary.
332     int rot_count  = 0;
333     int coag_count = 0;
334     vector<int> age_timer;
335     int current;
336     while (!timer.empty())
337     {
338         current = timer[timer.size()-1].get_int();
339         if (current > coag_limit
340             || blood.sub_type == POT_BLOOD_COAGULATED && current > rot_limit)
341         {
342             // Still some time until rotting/coagulating.
343             break;
344         }
345
346         timer.pop_back();
347         if (current <= rot_limit)
348             rot_count++;
349         else if (blood.sub_type == POT_BLOOD && current <= coag_limit)
350         {
351             coag_count++;
352             age_timer.push_back(current);
353         }
354     }
355
356     if (!rot_count && !coag_count)
357         return; // Nothing to be done.
358
359 #ifdef DEBUG_BLOOD_POTIONS
360     mprf(MSGCH_DIAGNOSTICS, "in maybe_coagulate_blood_potions_FLOOR "
361                             "(turns: %d)", you.num_turns);
362
363     mprf(MSGCH_DIAGNOSTICS, "Something happened at pos (%d, %d)!",
364                             blood.x, blood.y);
365     mprf(MSGCH_DIAGNOSTICS, "coagulated: %d, rotted: %d, total: %d",
366                             coag_count, rot_count, blood.quantity);
367     more();
368 #endif
369
370     if (!coag_count) // Some potions rotted away.
371     {
372         dec_mitm_item_quantity(obj, rot_count);
373         // Timer is already up to date.
374         return;
375     }
376
377     // Coagulated blood cannot coagulate any further...
378     ASSERT(blood.sub_type == POT_BLOOD);
379
380     if (!blood.held_by_monster())
381     {
382         // Now that coagulating is necessary, check square for
383         // !coagulated blood.
384         ASSERT(blood.pos.x >= 0);
385         ASSERT(blood.pos.y >= 0);
386         for (stack_iterator si(blood.pos); si; ++si)
387         {
388             if (si->base_type == OBJ_POTIONS
389                 && si->sub_type == POT_BLOOD_COAGULATED)
390             {
391                 // Merge with existing stack.
392                 CrawlHashTable &props2 = si->props;
393                 if (!props2.exists("timer"))
394                     init_stack_blood_potions(*si, si->special);
395
396                 ASSERT(props2.exists("timer"));
397                 CrawlVector &timer2 = props2["timer"].get_vector();
398                 ASSERT(timer2.size() == si->quantity);
399
400                 // Update timer -> push(pop).
401                 while (!age_timer.empty())
402                 {
403                     const int val = age_timer.back();
404                     age_timer.pop_back();
405                     timer2.push_back(val);
406                 }
407                 _int_sort(timer2);
408                 inc_mitm_item_quantity(si.link(), coag_count);
409                 ASSERT(timer2.size() == si->quantity);
410                 dec_mitm_item_quantity(obj, rot_count + coag_count);
411                 return;
412             }
413         }
414     }
415     // If we got here, nothing was found! (Or it's in a monster's
416     // inventory.)
417
418     // Entire stack is gone, rotted or coagulated.
419     // -> Change potions to coagulated type.
420     if (rot_count + coag_count == blood.quantity)
421     {
422         ASSERT(timer.empty());
423
424         // Update subtype.
425         blood.sub_type = POT_BLOOD_COAGULATED;
426         item_colour(blood);
427
428         // Re-fill vector.
429         int val;
430         while (!age_timer.empty())
431         {
432             val = age_timer[age_timer.size() - 1];
433             age_timer.pop_back();
434             timer.push_back(val);
435         }
436         dec_mitm_item_quantity(obj, rot_count);
437         _compare_blood_quantity(blood, timer.size());
438         return;
439     }
440
441     // Else, create a new stack of potions.
442     int o = get_mitm_slot(20);
443     if (o == NON_ITEM)
444         return;
445
446     item_def &item = mitm[o];
447     item.base_type = OBJ_POTIONS;
448     item.sub_type  = POT_BLOOD_COAGULATED;
449     item.quantity  = coag_count;
450     item.plus      = 0;
451     item.plus2     = 0;
452     item.special   = 0;
453     item.flags     = 0;
454     item_colour(item);
455
456     CrawlHashTable &props_new = item.props;
457     props_new["timer"].new_vector(SV_INT, SFLAG_CONST_TYPE);
458     CrawlVector &timer_new = props_new["timer"].get_vector();
459
460     int val;
461     while (!age_timer.empty())
462     {
463         val = age_timer[age_timer.size() - 1];
464         age_timer.pop_back();
465         timer_new.push_back(val);
466     }
467     ASSERT(timer_new.size() == coag_count);
468     props_new.assert_validity();
469
470     if (blood.held_by_monster())
471         move_item_to_grid(&o, blood.holding_monster()->pos());
472     else
473         move_item_to_grid(&o, blood.pos);
474
475     dec_mitm_item_quantity(obj, rot_count + coag_count);
476     _compare_blood_quantity(blood, timer.size());
477 }
478
479 static string _get_desc_quantity(const int quant, const int total)
480 {
481     if (total == quant)
482         return "Your";
483     else if (quant == 1)
484         return "One of your";
485     else if (quant == 2)
486         return "Two of your";
487     else if (quant >= (total * 3) / 4)
488         return "Most of your";
489     else
490         return "Some of your";
491 }
492
493 // Prints messages for blood potions coagulating in inventory (coagulate = true)
494 // or whenever potions are cursed into potions of decay (coagulate = false).
495 static void _potion_stack_changed_message(item_def &potion, int num_changed,
496                                           string verb)
497 {
498     ASSERT(num_changed > 0);
499
500     verb = replace_all(verb, "%s", num_changed == 1 ? "s" : "");
501     mprf(MSGCH_ROTTEN_MEAT, "%s %s %s.",
502          _get_desc_quantity(num_changed, potion.quantity).c_str(),
503          potion.name(DESC_PLAIN, false).c_str(),
504          verb.c_str());
505 }
506
507 // Returns true if "equipment weighs less" message needed.
508 // Also handles coagulation messages.
509 bool maybe_coagulate_blood_potions_inv(item_def &blood)
510 {
511     ASSERT(blood.defined());
512     ASSERT(is_blood_potion(blood));
513
514     CrawlHashTable &props = blood.props;
515     if (!props.exists("timer"))
516         init_stack_blood_potions(blood, blood.special);
517
518     ASSERT(props.exists("timer"));
519     CrawlVector &timer = props["timer"].get_vector();
520     _compare_blood_quantity(blood, timer.size());
521     ASSERT(!timer.empty());
522
523     // blood.sub_type could be POT_BLOOD or POT_BLOOD_COAGULATED
524     // -> need different handling
525     int rot_limit  = you.num_turns;
526     int coag_limit = you.num_turns + 500; // check 500 turns later
527
528     // First count whether coagulating is even necessary.
529     int rot_count  = 0;
530     int coag_count = 0;
531     vector<int> age_timer;
532     int current;
533     const int size = timer.size();
534     for (int i = 0; i < size; i++)
535     {
536         current = timer[timer.size()-1].get_int();
537         if (current > coag_limit
538             || blood.sub_type == POT_BLOOD_COAGULATED && current > rot_limit)
539         {
540             // Still some time until rotting/coagulating.
541             break;
542         }
543
544         timer.pop_back();
545         if (current <= rot_limit)
546             rot_count++;
547         else if (blood.sub_type == POT_BLOOD && current <= coag_limit)
548         {
549             coag_count++;
550             age_timer.push_back(current);
551         }
552     }
553
554     if (!rot_count && !coag_count)
555         return false; // Nothing to be done.
556
557 #ifdef DEBUG_BLOOD_POTIONS
558     mprf(MSGCH_DIAGNOSTICS, "in maybe_coagulate_blood_potions_INV "
559                             "(turns: %d)", you.num_turns);
560
561     mprf(MSGCH_DIAGNOSTICS, "coagulated: %d, rotted: %d, total: %d",
562                             coag_count, rot_count, blood.quantity);
563     more();
564 #endif
565
566     // just in case
567     you.wield_change  = true;
568     you.redraw_quiver = true;
569
570     const bool knew_coag  = (get_ident_type(OBJ_POTIONS, POT_BLOOD_COAGULATED)
571                                 == ID_KNOWN_TYPE);
572
573     if (!coag_count) // Some potions rotted away, but none coagulated.
574     {
575         // Only coagulated blood can rot.
576         ASSERT(blood.sub_type == POT_BLOOD_COAGULATED);
577         _potion_stack_changed_message(blood, rot_count, "rot%s away");
578         bool destroyed = dec_inv_item_quantity(blood.link, rot_count);
579
580         if (!knew_coag)
581         {
582             set_ident_type(OBJ_POTIONS, POT_BLOOD_COAGULATED, ID_KNOWN_TYPE);
583             if (!destroyed)
584                 mpr_nocap(blood.name(DESC_INVENTORY).c_str());
585         }
586
587         if (!destroyed)
588             _compare_blood_quantity(blood, timer.size());
589
590         return true;
591     }
592
593     // Coagulated blood cannot coagulate any further...
594     ASSERT(blood.sub_type == POT_BLOOD);
595
596     const bool knew_blood = get_ident_type(OBJ_POTIONS, POT_BLOOD)
597                                 == ID_KNOWN_TYPE;
598
599     _potion_stack_changed_message(blood, coag_count, "coagulate%s");
600
601     request_autoinscribe();
602
603     // Identify both blood and coagulated blood, if necessary.
604     if (!knew_blood)
605         set_ident_type(OBJ_POTIONS, POT_BLOOD, ID_KNOWN_TYPE);
606
607     if (!knew_coag)
608         set_ident_type(OBJ_POTIONS, POT_BLOOD_COAGULATED, ID_KNOWN_TYPE);
609
610     // Now that coagulating is necessary, check inventory for !coagulated blood.
611     for (int m = 0; m < ENDOFPACK; m++)
612     {
613         if (!you.inv[m].defined())
614             continue;
615
616         if (you.inv[m].base_type == OBJ_POTIONS
617             && you.inv[m].sub_type == POT_BLOOD_COAGULATED)
618         {
619             CrawlHashTable &props2 = you.inv[m].props;
620             if (!props2.exists("timer"))
621                 init_stack_blood_potions(you.inv[m], you.inv[m].special);
622
623             ASSERT(props2.exists("timer"));
624             CrawlVector &timer2 = props2["timer"].get_vector();
625             if (!dec_inv_item_quantity(blood.link, coag_count + rot_count))
626             {
627                 _compare_blood_quantity(blood, timer.size());
628                 if (!knew_blood)
629                     mpr_nocap(blood.name(DESC_INVENTORY).c_str());
630             }
631
632             // Update timer -> push(pop).
633             int val;
634             while (!age_timer.empty())
635             {
636                 val = age_timer[age_timer.size() - 1];
637                 age_timer.pop_back();
638                 timer2.push_back(val);
639             }
640
641             you.inv[m].quantity += coag_count;
642             ASSERT(timer2.size() == you.inv[m].quantity);
643             if (!knew_coag)
644                 mpr_nocap(you.inv[m].name(DESC_INVENTORY).c_str());
645
646             // re-sort timer
647             _int_sort(timer2);
648
649             return (rot_count > 0);
650         }
651     }
652
653     // If entire stack has coagulated, simply change subtype.
654     if (rot_count + coag_count == blood.quantity)
655     {
656         ASSERT(timer.empty());
657         // Update subtype.
658         blood.sub_type = POT_BLOOD_COAGULATED;
659         item_colour(blood);
660
661         // Re-fill vector.
662         int val;
663         while (!age_timer.empty())
664         {
665             val = age_timer[age_timer.size() - 1];
666             age_timer.pop_back();
667             timer.push_back(val);
668         }
669         blood.quantity -= rot_count;
670         // Stack still exists because of coag_count.
671         _compare_blood_quantity(blood, timer.size());
672
673         if (!knew_coag)
674             mpr_nocap(blood.name(DESC_INVENTORY).c_str());
675
676         return (rot_count > 0);
677     }
678
679     // Else, create new stack in inventory.
680     int freeslot = find_free_slot(blood);
681     if (freeslot >= 0 && freeslot < ENDOFPACK)
682     {
683         item_def &item   = you.inv[freeslot];
684         item.clear();
685
686         item.link        = freeslot;
687         item.slot        = index_to_letter(item.link);
688         item.base_type   = OBJ_POTIONS;
689         item.sub_type    = POT_BLOOD_COAGULATED;
690         item.quantity    = coag_count;
691         item.plus        = 0;
692         item.plus2       = 0;
693         item.special     = 0;
694         item.flags       = (ISFLAG_KNOW_TYPE & ISFLAG_BEEN_IN_INV);
695         item.pos.set(-1, -1);
696         item_colour(item);
697
698         CrawlHashTable &props_new = item.props;
699         props_new["timer"].new_vector(SV_INT, SFLAG_CONST_TYPE);
700         CrawlVector &timer_new = props_new["timer"].get_vector();
701
702         int val;
703         while (!age_timer.empty())
704         {
705             val = age_timer[age_timer.size() - 1];
706             age_timer.pop_back();
707             timer_new.push_back(val);
708         }
709
710         ASSERT(timer_new.size() == coag_count);
711         props_new.assert_validity();
712
713         blood.quantity -= coag_count + rot_count;
714         _compare_blood_quantity(blood, timer.size());
715
716         if (!knew_blood)
717             mpr_nocap(blood.name(DESC_INVENTORY).c_str());
718         if (!knew_coag)
719             mpr_nocap(item.name(DESC_INVENTORY).c_str());
720
721         return (rot_count > 0);
722     }
723
724     mprf("You can't carry %s right now.", coag_count > 1 ? "them" : "it");
725
726     // No space in inventory, check floor.
727     int o = igrd(you.pos());
728     while (o != NON_ITEM)
729     {
730         if (mitm[o].base_type == OBJ_POTIONS
731             && mitm[o].sub_type == POT_BLOOD_COAGULATED)
732         {
733             // Merge with existing stack.
734             CrawlHashTable &props2 = mitm[o].props;
735             if (!props2.exists("timer"))
736                 init_stack_blood_potions(mitm[o], mitm[o].special);
737
738             ASSERT(props2.exists("timer"));
739             CrawlVector &timer2 = props2["timer"].get_vector();
740             ASSERT(timer2.size() == mitm[o].quantity);
741
742             // Update timer -> push(pop).
743             int val;
744             while (!age_timer.empty())
745             {
746                 val = age_timer[age_timer.size() - 1];
747                 age_timer.pop_back();
748                 timer2.push_back(val);
749             }
750             _int_sort(timer2);
751
752             inc_mitm_item_quantity(o, coag_count);
753             ASSERT(timer2.size() == mitm[o].quantity);
754             dec_inv_item_quantity(blood.link, rot_count + coag_count);
755             _compare_blood_quantity(blood, timer.size());
756             if (!knew_blood)
757                 mpr_nocap(blood.name(DESC_INVENTORY).c_str());
758
759             return true;
760         }
761         o = mitm[o].link;
762     }
763     // If we got here nothing was found!
764
765     // Create a new stack of potions.
766     o = get_mitm_slot();
767     if (o == NON_ITEM)
768         return false;
769
770     // These values are common to all: {dlb}
771     mitm[o].base_type = OBJ_POTIONS;
772     mitm[o].sub_type  = POT_BLOOD_COAGULATED;
773     mitm[o].quantity  = coag_count;
774     mitm[o].plus      = 0;
775     mitm[o].plus2     = 0;
776     mitm[o].special   = 0;
777     mitm[o].flags     = (ISFLAG_KNOW_TYPE & ISFLAG_BEEN_IN_INV);
778     item_colour(mitm[o]);
779
780     CrawlHashTable &props_new = mitm[o].props;
781     props_new["timer"].new_vector(SV_INT, SFLAG_CONST_TYPE);
782     CrawlVector &timer_new = props_new["timer"].get_vector();
783
784     int val;
785     while (!age_timer.empty())
786     {
787         val = age_timer[age_timer.size() - 1];
788         age_timer.pop_back();
789         timer_new.push_back(val);
790     }
791
792     ASSERT(timer_new.size() == coag_count);
793     props_new.assert_validity();
794     move_item_to_grid(&o, you.pos());
795
796     if (!dec_inv_item_quantity(blood.link, coag_count + rot_count))
797     {
798         _compare_blood_quantity(blood, timer.size());
799         if (!knew_blood)
800             mpr_nocap(blood.name(DESC_INVENTORY).c_str());
801     }
802     return true;
803 }
804
805 // Removes the oldest timer of a stack of blood potions.
806 // Mostly used for (q)uaff and (f)ire.
807 int remove_oldest_blood_potion(item_def &stack)
808 {
809     ASSERT(stack.defined());
810     ASSERT(is_blood_potion(stack));
811
812     CrawlHashTable &props = stack.props;
813     if (!props.exists("timer"))
814         init_stack_blood_potions(stack, stack.special);
815     ASSERT(props.exists("timer"));
816     CrawlVector &timer = props["timer"].get_vector();
817     ASSERT(!timer.empty());
818
819     // Assuming already sorted, and first (oldest) potion valid.
820     const int val = timer[timer.size() - 1].get_int();
821     timer.pop_back();
822
823     // The quantity will be decreased elsewhere.
824     return val;
825 }
826
827 // Used whenever copies of blood potions have to be cleaned up.
828 void remove_newest_blood_potion(item_def &stack, int quant)
829 {
830     ASSERT(stack.defined());
831     ASSERT(is_blood_potion(stack));
832
833     CrawlHashTable &props = stack.props;
834     if (!props.exists("timer"))
835         init_stack_blood_potions(stack, stack.special);
836     ASSERT(props.exists("timer"));
837     CrawlVector &timer = props["timer"].get_vector();
838     ASSERT(!timer.empty());
839
840     if (quant == -1)
841         quant = timer.size() - stack.quantity;
842
843     // Overwrite newest potions with oldest ones.
844     int repeats = stack.quantity;
845     if (repeats > quant)
846         repeats = quant;
847
848     for (int i = 0; i < repeats; i++)
849     {
850         timer[i] = timer[timer.size() - 1];
851         timer.pop_back();
852     }
853
854     // Now remove remaining oldest potions...
855     repeats = quant - repeats;
856     for (int i = 0; i < repeats; i++)
857         timer.pop_back();
858
859     // ... and re-sort.
860     _int_sort(timer);
861 }
862
863 void merge_blood_potion_stacks(item_def &source, item_def &dest, int quant)
864 {
865     if (!source.defined() || !dest.defined())
866         return;
867
868     ASSERT_RANGE(quant, 1, source.quantity + 1);
869     ASSERT(is_blood_potion(source));
870     ASSERT(is_blood_potion(dest));
871
872     CrawlHashTable &props = source.props;
873     if (!props.exists("timer"))
874         init_stack_blood_potions(source, source.special);
875     ASSERT(props.exists("timer"));
876     CrawlVector &timer = props["timer"].get_vector();
877     ASSERT(!timer.empty());
878
879     CrawlHashTable &props2 = dest.props;
880     if (!props2.exists("timer"))
881         init_stack_blood_potions(dest, dest.special);
882     ASSERT(props2.exists("timer"));
883     CrawlVector &timer2 = props2["timer"].get_vector();
884
885     // Update timer -> push(pop).
886     for (int i = 0; i < quant; i++)
887     {
888         timer2.push_back(timer[timer.size() - 1].get_int());
889         timer.pop_back();
890     }
891
892     // Re-sort timer.
893     _int_sort(timer2);
894 }
895
896 bool check_blood_corpses_on_ground()
897 {
898     for (stack_iterator si(you.pos(), true); si; ++si)
899     {
900         if (si->base_type == OBJ_CORPSES && si->sub_type == CORPSE_BODY
901             && !food_is_rotten(*si)
902             && mons_has_blood(si->mon_type))
903         {
904             return true;
905         }
906     }
907     return false;
908 }
909
910 // Deliberately don't check for rottenness here, so this check
911 // can also be used to verify whether you *could* have bottled
912 // a now rotten corpse.
913 bool can_bottle_blood_from_corpse(monster_type mons_class)
914 {
915     if (you.species != SP_VAMPIRE || you.experience_level < 6
916         || !mons_has_blood(mons_class))
917     {
918         return false;
919     }
920
921     int chunk_type = mons_corpse_effect(mons_class);
922     if (chunk_type == CE_CLEAN || chunk_type == CE_CONTAMINATED)
923         return true;
924
925     return false;
926 }
927
928 int num_blood_potions_from_corpse(monster_type mons_class, int chunk_type)
929 {
930     if (chunk_type == -1)
931         chunk_type = mons_corpse_effect(mons_class);
932
933     // Max. amount is about one third of the max. amount for chunks.
934     const int max_chunks = get_max_corpse_chunks(mons_class);
935
936     // Max. amount is about one third of the max. amount for chunks.
937     int pot_quantity = max_chunks / 3;
938     pot_quantity = stepdown_value(pot_quantity, 2, 2, 6, 6);
939
940     // Halve number of potions obtained from contaminated chunk type corpses.
941     if (chunk_type == CE_CONTAMINATED)
942         pot_quantity /= 2;
943
944     if (pot_quantity < 1)
945         pot_quantity = 1;
946
947     return pot_quantity;
948 }
949
950 // If autopickup is active, the potions are auto-picked up after creation.
951 void turn_corpse_into_blood_potions(item_def &item)
952 {
953     ASSERT(item.base_type == OBJ_CORPSES);
954     ASSERT(!food_is_rotten(item));
955
956     const item_def corpse = item;
957     const monster_type mons_class = corpse.mon_type;
958
959     ASSERT(can_bottle_blood_from_corpse(mons_class));
960
961     item.base_type = OBJ_POTIONS;
962     item.sub_type  = POT_BLOOD;
963     item_colour(item);
964     item.flags    &= ~(ISFLAG_THROWN | ISFLAG_DROPPED);
965
966     item.quantity = num_blood_potions_from_corpse(mons_class);
967
968     // Initialise timer depending on corpse age:
969     // almost rotting: age = 100 --> potion timer =  500 --> will coagulate soon
970     // freshly killed: age = 200 --> potion timer = 2500 --> fresh !blood
971     init_stack_blood_potions(item, (item.special - 100) * 20 + 500);
972
973     // Happens after the blood has been bottled.
974     maybe_drop_monster_hide(corpse);
975 }
976
977 void turn_corpse_into_skeleton_and_blood_potions(item_def &item)
978 {
979     item_def blood_potions = item;
980
981     if (mons_skeleton(item.mon_type))
982         turn_corpse_into_skeleton(item);
983
984     int o = get_mitm_slot();
985     if (o != NON_ITEM)
986     {
987         turn_corpse_into_blood_potions(blood_potions);
988         copy_item_to_grid(blood_potions, you.pos());
989     }
990 }
991
992 static bool allow_bleeding_on_square(const coord_def& where)
993 {
994     // No bleeding onto sanctuary ground, please.
995     // Also not necessary if already covered in blood.
996     if (is_bloodcovered(where) || is_sanctuary(where))
997         return false;
998
999     // No spattering into lava or water.
1000     if (grd(where) >= DNGN_LAVA && grd(where) < DNGN_FLOOR)
1001         return false;
1002
1003     // No spattering into fountains (other than blood).
1004     if (grd(where) == DNGN_FOUNTAIN_BLUE
1005         || grd(where) == DNGN_FOUNTAIN_SPARKLING)
1006     {
1007         return false;
1008     }
1009
1010     // The good gods like to keep their altars pristine.
1011     if (is_good_god(feat_altar_god(grd(where))))
1012         return false;
1013
1014     return true;
1015 }
1016
1017 bool maybe_bloodify_square(const coord_def& where)
1018 {
1019     if (!allow_bleeding_on_square(where))
1020         return false;
1021
1022     env.pgrid(where) |= FPROP_BLOODY;
1023     return true;
1024 }
1025
1026 /*
1027  * Rotate the wall blood splat tile, so that it is facing the source.
1028  *
1029  * Wall blood splat tiles are drawned with the blood dripping down. We need
1030  * the tile to be facing an orthogonal empty space for the effect to look
1031  * good. We choose the empty space closest to the source of the blood.
1032  *
1033  * @param where Coordinates of the wall where there is a blood splat.
1034  * @param from Coordinates of the source of the blood.
1035  * @param old_blood blood splats created at level generation are old and can
1036  * have some blood inscriptions. Only for south facing splats, so you don't
1037  * have to turn your head to read the inscriptions.
1038  */
1039 static void _orient_wall_blood(const coord_def& where, coord_def from,
1040                                bool old_blood)
1041 {
1042     if (!feat_is_wall(env.grid(where)))
1043         return;
1044
1045     if (from == INVALID_COORD)
1046         from = where;
1047
1048     coord_def closer = INVALID_COORD;
1049     int dist = INT_MAX;
1050     los_def ld(from, opc_solid);
1051     ld.update();
1052
1053     for (orth_adjacent_iterator ai(where); ai; ++ai)
1054     {
1055         if (in_bounds(*ai) && !cell_is_solid(*ai) && ld.see_cell(*ai)
1056             && (distance2(*ai, from) < dist
1057                 || distance2(*ai, from) == dist && coinflip()))
1058         {
1059             closer = *ai;
1060             dist = distance2(*ai, from);
1061         }
1062     }
1063
1064     // If we didn't find anything, the wall is in a corner.
1065     // We don't want blood tile there.
1066     if (closer == INVALID_COORD)
1067     {
1068         env.pgrid(where) &= ~FPROP_BLOODY;
1069         return;
1070     }
1071
1072     const coord_def diff = where - closer;
1073     if (diff == coord_def(1, 0))
1074         env.pgrid(where) |= FPROP_BLOOD_WEST;
1075     else if (diff == coord_def(0, 1))
1076         env.pgrid(where) |= FPROP_BLOOD_NORTH;
1077     else if (diff == coord_def(-1, 0))
1078         env.pgrid(where) |= FPROP_BLOOD_EAST;
1079     else if (old_blood && one_chance_in(10))
1080         env.pgrid(where) |= FPROP_OLD_BLOOD;
1081 }
1082
1083 static void _maybe_bloodify_square(const coord_def& where, int amount,
1084                                    bool spatter = false,
1085                                    bool smell_alert = true,
1086                                    const coord_def& from = INVALID_COORD,
1087                                    const bool old_blood = false)
1088 {
1089     if (amount < 1)
1090         return;
1091
1092     bool may_bleed = allow_bleeding_on_square(where);
1093     if (!spatter && !may_bleed)
1094         return;
1095
1096     bool ignite_blood = player_mutation_level(MUT_IGNITE_BLOOD)
1097                         && you.see_cell(where);
1098
1099     if (ignite_blood)
1100         amount *= 2;
1101
1102     if (x_chance_in_y(amount, 20))
1103     {
1104         dprf("might bleed now; square: (%d, %d); amount = %d",
1105              where.x, where.y, amount);
1106         if (may_bleed)
1107         {
1108             env.pgrid(where) |= FPROP_BLOODY;
1109             _orient_wall_blood(where, from, old_blood);
1110
1111             if (smell_alert && in_bounds(where))
1112                 blood_smell(12, where);
1113
1114             if (ignite_blood
1115                 && !cell_is_solid(where)
1116                 && env.cgrid(where) == EMPTY_CLOUD)
1117             {
1118                 place_cloud(CLOUD_FIRE, where, 5 + random2(6), &you);
1119             }
1120         }
1121
1122         if (spatter)
1123         {
1124             // Smaller chance of spattering surrounding squares.
1125             for (adjacent_iterator ai(where); ai; ++ai)
1126             {
1127                 _maybe_bloodify_square(*ai, amount/15, false, true, from,
1128                                        old_blood);
1129             }
1130         }
1131     }
1132 }
1133
1134 // Currently flavour only: colour ground (and possibly adjacent squares) red.
1135 // "damage" depends on damage taken (or hitpoints, if damage higher),
1136 // or, for sacrifices, on the number of chunks possible to get out of a corpse.
1137 void bleed_onto_floor(const coord_def& where, monster_type montype,
1138                       int damage, bool spatter, bool smell_alert,
1139                       const coord_def& from, const bool old_blood)
1140 {
1141     ASSERT_IN_BOUNDS(where);
1142
1143     if (montype == MONS_PLAYER && !you.can_bleed())
1144         return;
1145
1146     if (montype != NUM_MONSTERS && montype != MONS_PLAYER)
1147     {
1148         monster m;
1149         m.type = montype;
1150         if (!m.can_bleed())
1151             return;
1152     }
1153
1154     _maybe_bloodify_square(where, damage, spatter, smell_alert, from,
1155                            old_blood);
1156 }
1157
1158 void blood_spray(const coord_def& origin, monster_type montype, int level)
1159 {
1160     los_def ld(origin, opc_solid);
1161
1162     ld.update();
1163
1164     int tries = 0;
1165     for (int i = 0; i < level; ++i)
1166     {
1167         // Blood drops are small and light and suffer a lot of wind
1168         // resistance.
1169         int range = random2(8) + 1;
1170
1171         while (tries < 5000)
1172         {
1173             ++tries;
1174
1175             coord_def bloody = origin;
1176             bloody.x += random_range(-range, range);
1177             bloody.y += random_range(-range, range);
1178
1179             if (in_bounds(bloody) && ld.see_cell(bloody))
1180             {
1181                 bleed_onto_floor(bloody, montype, 99, false, true, origin);
1182                 break;
1183             }
1184         }
1185     }
1186 }
1187
1188 static void _spatter_neighbours(const coord_def& where, int chance,
1189                                 const coord_def& from = INVALID_COORD)
1190 {
1191     for (adjacent_iterator ai(where, false); ai; ++ai)
1192     {
1193         if (!allow_bleeding_on_square(*ai))
1194             continue;
1195
1196         if (one_chance_in(chance))
1197         {
1198             env.pgrid(*ai) |= FPROP_BLOODY;
1199             _orient_wall_blood(where, from, true);
1200             _spatter_neighbours(*ai, chance+1, from);
1201         }
1202     }
1203 }
1204
1205 void generate_random_blood_spatter_on_level(const map_bitmask *susceptible_area)
1206 {
1207     const int max_cluster = 7 + random2(9);
1208
1209     // Lower chances for large bloodshed areas if we have many clusters,
1210     // but increase chances if we have few.
1211     // Chances for startprob are [1..3] for 7-9 clusters,
1212     //                       ... [1..4] for 10-12 clusters, and
1213     //                       ... [2..5] for 13-15 clusters.
1214
1215     int min_prob = 1;
1216     int max_prob = 4;
1217
1218     if (max_cluster < 10)
1219         max_prob--;
1220     else if (max_cluster > 12)
1221         min_prob++;
1222
1223     for (int i = 0; i < max_cluster; ++i)
1224     {
1225         const coord_def c = random_in_bounds();
1226
1227         if (susceptible_area && !(*susceptible_area)(c))
1228             continue;
1229
1230         // startprob is used to initialise the chance for neighbours
1231         // being spattered, which will be decreased by 1 per recursion
1232         // round. We then use one_chance_in(chance) to determine
1233         // whether to spatter a given grid or not. Thus, startprob = 1
1234         // means that initially all surrounding grids will be
1235         // spattered (3x3), and the _higher_ startprob the _lower_ the
1236         // overall chance for spattering and the _smaller_ the
1237         // bloodshed area.
1238         const int startprob = min_prob + random2(max_prob);
1239
1240         maybe_bloodify_square(c);
1241
1242         _spatter_neighbours(c, startprob);
1243     }
1244 }
1245
1246 void search_around()
1247 {
1248     ASSERT(!crawl_state.game_is_arena());
1249
1250     int base_skill = you.skill(SK_TRAPS, 100);
1251     int skill = (2/(1+exp(-(base_skill+120)/325.0))-1) * 225
1252                 + (base_skill/200.0) + 15;
1253
1254     if (you.religion == GOD_ASHENZARI && !player_under_penance())
1255         skill += you.piety * 2;
1256
1257      if (you.duration[DUR_SWIFTNESS])
1258         skill = skill / 2;
1259
1260     int farskill = skill;
1261     if (int mut = you.mutation[MUT_BLURRY_VISION])
1262         farskill >>= mut;
1263     // Traps and doors stepdown skill:
1264     // skill/(2x-1) for squares at distance x
1265     int max_dist = div_rand_round(farskill, 32);
1266     if (max_dist > 5)
1267         max_dist = 5;
1268     if (max_dist < 1)
1269         max_dist = 1;
1270
1271     for (radius_iterator ri(you.pos(), max_dist); ri; ++ri)
1272     {
1273         // Must have LOS, with no translucent walls in the way.
1274         if (grd(*ri) != DNGN_UNDISCOVERED_TRAP || !you.see_cell_no_trans(*ri))
1275             continue;
1276
1277         int dist = ri->range(you.pos());
1278
1279         // Own square is not excluded; may be flying.
1280         // XXX: Currently, flying over a trap will always detect it.
1281
1282         int effective = (dist <= 1) ? skill : farskill / (dist * 2 - 1);
1283
1284         trap_def* ptrap = find_trap(*ri);
1285         if (!ptrap)
1286         {
1287             // Maybe we shouldn't kill the trap for debugging
1288             // purposes - oh well.
1289             grd(*ri) = DNGN_FLOOR;
1290             dprf("You found a buggy trap! It vanishes!");
1291             continue;
1292         }
1293
1294         if (effective > ptrap->skill_rnd)
1295         {
1296             ptrap->reveal();
1297             mprf("You found %s trap!",
1298                  ptrap->name(DESC_A).c_str());
1299             learned_something_new(HINT_SEEN_TRAP, *ri);
1300             practise(EX_TRAP_FOUND);
1301         }
1302     }
1303 }
1304
1305 void emergency_untransform()
1306 {
1307     mpr("You quickly transform back into your natural form.");
1308     untransform(false, true); // We're already entering the water.
1309
1310     if (you.species == SP_MERFOLK)
1311         merfolk_start_swimming(false);
1312 }
1313
1314 void merfolk_start_swimming(bool stepped)
1315 {
1316     if (you.fishtail)
1317         return;
1318
1319     if (stepped)
1320         mpr("Your legs become a tail as you enter the water.");
1321     else
1322         mpr("Your legs become a tail as you dive into the water.");
1323
1324     if (you.invisible())
1325         mpr("...but don't expect to remain undetected.");
1326
1327     you.fishtail = true;
1328     remove_one_equip(EQ_BOOTS);
1329     you.redraw_evasion = true;
1330
1331 #ifdef USE_TILE
1332     init_player_doll();
1333 #endif
1334 }
1335
1336 void merfolk_stop_swimming()
1337 {
1338     if (!you.fishtail)
1339         return;
1340     you.fishtail = false;
1341     unmeld_one_equip(EQ_BOOTS);
1342     you.redraw_evasion = true;
1343
1344 #ifdef USE_TILE
1345     init_player_doll();
1346 #endif
1347 }
1348
1349 // Update the trackers after the player changed level.
1350 void trackers_init_new_level(bool transit)
1351 {
1352     travel_init_new_level();
1353 }
1354
1355 string weird_glowing_colour()
1356 {
1357     return getMiscString("glowing_colour_name");
1358 }
1359
1360 string weird_writing()
1361 {
1362     return getMiscString("writing_name");
1363 }
1364
1365 string weird_smell()
1366 {
1367     return getMiscString("smell_name");
1368 }
1369
1370 string weird_sound()
1371 {
1372     return getMiscString("sound_name");
1373 }
1374
1375 bool scramble(void)
1376 {
1377     ASSERT(!crawl_state.game_is_arena());
1378
1379     // Statues are too stiff and heavy to scramble out of the water.
1380     if (you.form == TRAN_STATUE || you.cannot_move())
1381         return false;
1382
1383     const int max_carry = carrying_capacity();
1384     // When highly encumbered, scrambling out is hard to do.
1385     return (you.burden < (max_carry / 2) + random2(max_carry / 2));
1386 }
1387
1388 bool go_berserk(bool intentional, bool potion)
1389 {
1390     ASSERT(!crawl_state.game_is_arena());
1391
1392     if (!you.can_go_berserk(intentional, potion))
1393         return false;
1394
1395     if (stasis_blocks_effect(true,
1396                              true,
1397                              "%s thrums violently and saps your rage.",
1398                              3,
1399                              "%s vibrates violently and saps your rage."))
1400     {
1401         return false;
1402     }
1403
1404     if (crawl_state.game_is_hints())
1405         Hints.hints_berserk_counter++;
1406
1407     mpr("A red film seems to cover your vision as you go berserk!");
1408
1409     if (you.duration[DUR_FINESSE] > 0)
1410     {
1411         you.duration[DUR_FINESSE] = 0; // Totally incompatible.
1412         mpr("Finesse? Hah! Time to rip out guts!");
1413     }
1414
1415     if (you.religion == GOD_CHEIBRIADOS)
1416     {
1417         // Che makes berserk not speed you up.
1418         // Unintentional would be forgiven "just this once" every time.
1419         // Intentional could work as normal, but that would require storing
1420         // whether you transgressed to start it -- so we just consider this
1421         // a part of your penance.
1422         if (intentional)
1423         {
1424             did_god_conduct(DID_HASTY, 8);
1425             simple_god_message(" forces you to slow down.");
1426         }
1427         else
1428             simple_god_message(" protects you from inadvertent hurry.");
1429     }
1430     else
1431         mpr("You feel yourself moving faster!");
1432
1433     mpr("You feel mighty!");
1434
1435     // Cutting the duration in half since berserk causes haste and hasted
1436     // actions have half the usual delay. This keeps player turns
1437     // approximately consistent withe previous versions. -cao
1438     // Only 1.5 now, but I'm keeping the reduction as a nerf. -1KB
1439     int berserk_duration = (20 + random2avg(19,2)) / 2;
1440
1441     you.increase_duration(DUR_BERSERK, berserk_duration);
1442
1443     calc_hp();
1444     you.hp = you.hp * 3 / 2;
1445
1446     deflate_hp(you.hp_max, false);
1447
1448     if (!you.duration[DUR_MIGHT])
1449         notify_stat_change(STAT_STR, 5, true, "going berserk");
1450
1451     if (you.berserk_penalty != NO_BERSERK_PENALTY)
1452         you.berserk_penalty = 0;
1453
1454     you.redraw_quiver = true; // Account for no firing.
1455
1456     if (you.species == SP_LAVA_ORC)
1457     {
1458         mpr("You burn with rage!");
1459         // This will get sqrt'd later, so.
1460         you.temperature = TEMP_MAX;
1461     }
1462     return true;
1463 }
1464
1465 // Returns true if the monster has a path to the player, or it has to be
1466 // assumed that this is the case.
1467 static bool _mons_has_path_to_player(const monster* mon, bool want_move = false)
1468 {
1469     if (mons_is_stationary(mon) && !mons_is_tentacle(mon->type))
1470     {
1471         int dist = grid_distance(you.pos(), mon->pos());
1472         if (want_move)
1473             dist--;
1474         if (dist >= 2)
1475             return false;
1476     }
1477
1478     // Short-cut if it's already adjacent.
1479     if (grid_distance(mon->pos(), you.pos()) <= 1)
1480         return true;
1481
1482     // If the monster is awake and knows a path towards the player
1483     // (even though the player cannot know this) treat it as unsafe.
1484     if (mon->travel_target == MTRAV_PLAYER)
1485         return true;
1486
1487     if (mon->travel_target == MTRAV_KNOWN_UNREACHABLE)
1488         return false;
1489
1490     // Try to find a path from monster to player, using the map as it's
1491     // known to the player and assuming unknown terrain to be traversable.
1492     monster_pathfind mp;
1493     const int range = mons_tracking_range(mon);
1494     // Use a large safety margin.  x4 should be ok.
1495     if (range > 0)
1496         mp.set_range(range * 4);
1497
1498     if (mp.init_pathfind(mon, you.pos(), true, false, true))
1499         return true;
1500
1501     // Now we know the monster cannot possibly reach the player.
1502     mon->travel_target = MTRAV_KNOWN_UNREACHABLE;
1503
1504     return false;
1505 }
1506
1507 bool mons_can_hurt_player(const monster* mon, const bool want_move)
1508 {
1509     // FIXME: This takes into account whether the player knows the map!
1510     //        It should, for the purposes of i_feel_safe. [rob]
1511     // It also always returns true for sleeping monsters, but that's okay
1512     // for its current purposes. (Travel interruptions and tension.)
1513     if (_mons_has_path_to_player(mon, want_move))
1514         return true;
1515
1516     // Even if the monster can not actually reach the player it might
1517     // still use some ranged form of attack.
1518     if (you.see_cell_no_trans(mon->pos())
1519         && mons_has_known_ranged_attack(mon))
1520     {
1521         return true;
1522     }
1523
1524     return false;
1525 }
1526
1527 // Returns true if a monster can be considered safe regardless
1528 // of distance.
1529 static bool _mons_is_always_safe(const monster *mon)
1530 {
1531     return (mon->wont_attack()
1532             || mon->type == MONS_BUTTERFLY
1533             || mon->withdrawn()
1534             || mon->type == MONS_BALLISTOMYCETE && mon->number == 0);
1535 }
1536
1537 bool mons_is_safe(const monster* mon, const bool want_move,
1538                   const bool consider_user_options, bool check_dist)
1539 {
1540     // Short-circuit plants, some vaults have tons of those.
1541     // Except for inactive ballistos, players may still want these.
1542     if (mons_is_firewood(mon) && mon->type != MONS_BALLISTOMYCETE)
1543         return true;
1544
1545     int  dist    = grid_distance(you.pos(), mon->pos());
1546
1547     bool is_safe = (_mons_is_always_safe(mon)
1548                     || check_dist
1549                        && (mon->pacified() && dist > 1
1550 #ifdef WIZARD
1551                            // Wizmode skill setting enforces hiddenness.
1552                            || you.skills[SK_STEALTH] > 27 && dist > 2
1553 #endif
1554                            // Only seen through glass walls or within water?
1555                            // Assuming that there are no water-only/lava-only
1556                            // monsters capable of throwing or zapping wands.
1557                            || !mons_can_hurt_player(mon, want_move)));
1558
1559 #ifdef CLUA_BINDINGS
1560     if (consider_user_options)
1561     {
1562         bool moving = (!you.delay_queue.empty()
1563                           && delay_is_run(you.delay_queue.front().type)
1564                           && you.delay_queue.front().type != DELAY_REST
1565                        || you.running < RMODE_NOT_RUNNING
1566                        || want_move);
1567
1568         bool result = is_safe;
1569
1570         monster_info mi(mon, MILEV_SKIP_SAFE);
1571         if (clua.callfn("ch_mon_is_safe", "Ibbd>b",
1572                         &mi, is_safe, moving, dist,
1573                         &result))
1574         {
1575             is_safe = result;
1576         }
1577     }
1578 #endif
1579
1580     return is_safe;
1581 }
1582
1583 // Return all nearby monsters in range (default: LOS) that the player
1584 // is able to recognise as being monsters (i.e. no submerged creatures.)
1585 //
1586 // want_move       (??) Somehow affects what monsters are considered dangerous
1587 // just_check      Return zero or one monsters only
1588 // dangerous_only  Return only "dangerous" monsters
1589 // require_visible Require that monsters be visible to the player
1590 // range           search radius (defaults: LOS)
1591 //
1592 vector<monster* > get_nearby_monsters(bool want_move,
1593                                       bool just_check,
1594                                       bool dangerous_only,
1595                                       bool consider_user_options,
1596                                       bool require_visible,
1597                                       bool check_dist,
1598                                       int range)
1599 {
1600     ASSERT(!crawl_state.game_is_arena());
1601
1602     if (range == -1)
1603         range = LOS_RADIUS;
1604
1605     vector<monster* > mons;
1606
1607     // Sweep every visible square within range.
1608     for (radius_iterator ri(you.pos(), range); ri; ++ri)
1609     {
1610         if (monster* mon = monster_at(*ri))
1611         {
1612             if (mon->alive()
1613                 && (!require_visible || mon->visible_to(&you))
1614                 && !mon->submerged()
1615                 && (!dangerous_only || !mons_is_safe(mon, want_move,
1616                                                      consider_user_options,
1617                                                      check_dist)))
1618             {
1619                 mons.push_back(mon);
1620                 if (just_check) // stop once you find one
1621                     break;
1622             }
1623         }
1624     }
1625     return mons;
1626 }
1627
1628 static bool _exposed_monsters_nearby(bool want_move)
1629 {
1630     const int radius = want_move ? 2 : 1;
1631     for (radius_iterator ri(you.pos(), radius); ri; ++ri)
1632         if (env.map_knowledge(*ri).flags & MAP_INVISIBLE_MONSTER)
1633             return true;
1634     return false;
1635 }
1636
1637 bool i_feel_safe(bool announce, bool want_move, bool just_monsters,
1638                  bool check_dist, int range)
1639 {
1640     if (!just_monsters)
1641     {
1642         // check clouds
1643         if (in_bounds(you.pos()) && env.cgrid(you.pos()) != EMPTY_CLOUD)
1644         {
1645             const int cloudidx = env.cgrid(you.pos());
1646             const cloud_type type = env.cloud[cloudidx].type;
1647
1648             if (is_damaging_cloud(type, want_move))
1649             {
1650                 if (announce)
1651                 {
1652                     mprf(MSGCH_WARN, "You're standing in a cloud of %s!",
1653                          cloud_name_at_index(cloudidx).c_str());
1654                 }
1655                 return false;
1656             }
1657         }
1658
1659         // No monster will attack you inside a sanctuary,
1660         // so presence of monsters won't matter -- until it starts shrinking...
1661         if (is_sanctuary(you.pos()) && env.sanctuary_time >= 5)
1662             return true;
1663     }
1664
1665     // Monster check.
1666     vector<monster* > visible =
1667         get_nearby_monsters(want_move, !announce, true, true, true,
1668                             check_dist, range);
1669
1670     // Announce the presence of monsters (Eidolos).
1671     string msg;
1672     if (visible.size() == 1)
1673     {
1674         const monster& m = *visible[0];
1675         const string monname = mons_is_mimic(m.type) ? "A mimic"
1676                                                      : m.name(DESC_A);
1677         msg = make_stringf("%s is nearby!", monname.c_str());
1678     }
1679     else if (visible.size() > 1)
1680         msg = "There are monsters nearby!";
1681     else if (_exposed_monsters_nearby(want_move))
1682         msg = "There is a strange disturbance nearby!";
1683     else
1684         return true;
1685
1686     if (announce)
1687         mpr(msg, MSGCH_WARN);
1688
1689     return false;
1690 }
1691
1692 bool there_are_monsters_nearby(bool dangerous_only, bool require_visible,
1693                                bool consider_user_options)
1694 {
1695     return (!get_nearby_monsters(false, true, dangerous_only,
1696                                  consider_user_options,
1697                                  require_visible).empty());
1698 }
1699
1700 static const char *shop_types[] = {
1701     "weapon",
1702     "armour",
1703     "antique weapon",
1704     "antique armour",
1705     "antiques",
1706     "jewellery",
1707     "wand",
1708     "book",
1709     "food",
1710     "distillery",
1711     "scroll",
1712     "general"
1713 };
1714
1715 int str_to_shoptype(const string &s)
1716 {
1717     if (s == "random" || s == "any")
1718         return SHOP_RANDOM;
1719
1720     for (unsigned i = 0; i < ARRAYSZ(shop_types); ++i)
1721     {
1722         if (s == shop_types[i])
1723             return i;
1724     }
1725     return -1;
1726 }
1727
1728 void list_shop_types()
1729 {
1730     mprnojoin("Available shop types: ");
1731     for (unsigned i = 0; i < ARRAYSZ(shop_types); ++i)
1732         mpr_nocap(shop_types[i]);
1733 }
1734
1735 // General threat = sum_of_logexpervalues_of_nearby_unfriendly_monsters.
1736 // Highest threat = highest_logexpervalue_of_nearby_unfriendly_monsters.
1737 static void monster_threat_values(double *general, double *highest,
1738                                   bool *invis)
1739 {
1740     *invis = false;
1741
1742     double sum = 0;
1743     int highest_xp = -1;
1744
1745     for (monster_iterator mi(you.get_los()); mi; ++mi)
1746     {
1747         if (!mi->friendly())
1748         {
1749             const int xp = exper_value(*mi);
1750             const double log_xp = log((double)xp);
1751             sum += log_xp;
1752             if (xp > highest_xp)
1753             {
1754                 highest_xp = xp;
1755                 *highest   = log_xp;
1756             }
1757             if (!you.can_see(*mi))
1758                 *invis = true;
1759         }
1760     }
1761
1762     *general = sum;
1763 }
1764
1765 bool player_in_a_dangerous_place(bool *invis)
1766 {
1767     bool junk;
1768     if (invis == NULL)
1769         invis = &junk;
1770
1771     const double logexp = log((double)you.experience);
1772     double gen_threat = 0.0, hi_threat = 0.0;
1773     monster_threat_values(&gen_threat, &hi_threat, invis);
1774
1775     return (gen_threat > logexp * 1.3 || hi_threat > logexp / 2);
1776 }
1777
1778 static void _drop_tomb(const coord_def& pos, bool premature, bool zin)
1779 {
1780     int count = 0;
1781     monster* mon = monster_at(pos);
1782
1783     // Don't wander on duty!
1784     if (mon)
1785         mon->behaviour = BEH_SEEK;
1786
1787     bool seen_change = false;
1788     for (adjacent_iterator ai(pos); ai; ++ai)
1789     {
1790         // "Normal" tomb (card or monster spell)
1791         if (!zin && revert_terrain_change(*ai, TERRAIN_CHANGE_TOMB))
1792         {
1793             count++;
1794             if (you.see_cell(*ai))
1795                 seen_change = true;
1796         }
1797         // Zin's Imprison.
1798         else if (zin && revert_terrain_change(*ai, TERRAIN_CHANGE_IMPRISON))
1799         {
1800             vector<map_marker*> markers = env.markers.get_markers_at(*ai);
1801             for (int i = 0, size = markers.size(); i < size; ++i)
1802             {
1803                 map_marker *mark = markers[i];
1804                 if (mark->property("feature_description")
1805                     == "a gleaming silver wall")
1806                 {
1807                     env.markers.remove(mark);
1808                 }
1809             }
1810
1811             env.grid_colours(*ai) = 0;
1812             tile_clear_flavour(*ai);
1813             tile_init_flavour(*ai);
1814             count++;
1815             if (you.see_cell(*ai))
1816                 seen_change = true;
1817         }
1818     }
1819
1820     if (count)
1821     {
1822         if (seen_change && !zin)
1823             mprf("The walls disappear%s!", premature ? " prematurely" : "");
1824         else if (seen_change && zin)
1825         {
1826             mprf("Zin %s %s %s.",
1827                  (mon) ? "releases"
1828                        : "dismisses",
1829                  (mon) ? mon->name(DESC_THE).c_str()
1830                        : "the silver walls,",
1831                  (mon) ? make_stringf("from %s prison",
1832                              mon->pronoun(PRONOUN_POSSESSIVE).c_str()).c_str()
1833                        : "but there is nothing inside them");
1834         }
1835         else
1836         {
1837             if (!silenced(you.pos()))
1838                 mpr("You hear a deep rumble.", MSGCH_SOUND);
1839             else
1840                 mpr("You feel the ground shudder.");
1841         }
1842     }
1843 }
1844
1845 static vector<map_malign_gateway_marker*> _get_malign_gateways()
1846 {
1847     vector<map_malign_gateway_marker*> mm_markers;
1848
1849     vector<map_marker*> markers = env.markers.get_all(MAT_MALIGN);
1850     for (int i = 0, size = markers.size(); i < size; ++i)
1851     {
1852         map_marker *mark = markers[i];
1853         if (mark->get_type() != MAT_MALIGN)
1854             continue;
1855
1856         map_malign_gateway_marker *mmark = dynamic_cast<map_malign_gateway_marker*>(mark);
1857
1858         mm_markers.push_back(mmark);
1859     }
1860
1861     return mm_markers;
1862 }
1863
1864 int count_malign_gateways()
1865 {
1866     return _get_malign_gateways().size();
1867 }
1868
1869 void timeout_malign_gateways(int duration)
1870 {
1871     // Passing 0 should allow us to just touch the gateway and see
1872     // if it should decay. This, in theory, should resolve the one
1873     // turn delay between it timing out and being recastable. -due
1874     vector<map_malign_gateway_marker*> markers = _get_malign_gateways();
1875
1876     for (int i = 0, size = markers.size(); i < size; ++i)
1877     {
1878         map_malign_gateway_marker *mmark = markers[i];
1879
1880         if (duration)
1881             mmark->duration -= duration;
1882
1883         if (mmark->duration > 0)
1884             big_cloud(CLOUD_TLOC_ENERGY, 0, mmark->pos, 3+random2(10), 2+random2(5));
1885         else
1886         {
1887             monster* mons = monster_at(mmark->pos);
1888             if (mmark->monster_summoned && !mons)
1889             {
1890                 // The marker hangs around until later.
1891                 if (env.grid(mmark->pos) == DNGN_MALIGN_GATEWAY)
1892                     env.grid(mmark->pos) = DNGN_FLOOR;
1893
1894                 env.markers.remove(mmark);
1895             }
1896             else if (!mmark->monster_summoned && !mons)
1897             {
1898                 bool is_player = mmark->is_player;
1899                 actor* caster = 0;
1900                 if (is_player)
1901                     caster = &you;
1902
1903                 mgen_data mg = mgen_data(MONS_ELDRITCH_TENTACLE,
1904                                          mmark->behaviour,
1905                                          caster,
1906                                          0,
1907                                          0,
1908                                          mmark->pos,
1909                                          MHITNOT,
1910                                          MG_FORCE_PLACE,
1911                                          mmark->god);
1912                 if (!is_player)
1913                     mg.non_actor_summoner = mmark->summoner_string;
1914
1915                 if (monster *tentacle = create_monster(mg))
1916                 {
1917                     tentacle->flags |= MF_NO_REWARD;
1918                     tentacle->add_ench(ENCH_PORTAL_TIMER);
1919                     mon_enchant kduration = mon_enchant(ENCH_PORTAL_PACIFIED, 4,
1920                         caster, (random2avg(mmark->power, 6)-random2(4))*10);
1921                     tentacle->props["base_position"].get_coord()
1922                                         = tentacle->pos();
1923                     tentacle->add_ench(kduration);
1924
1925                     mmark->monster_summoned = true;
1926                 }
1927             }
1928         }
1929     }
1930 }
1931
1932 void timeout_tombs(int duration)
1933 {
1934     if (!duration)
1935         return;
1936
1937     vector<map_marker*> markers = env.markers.get_all(MAT_TOMB);
1938
1939     for (int i = 0, size = markers.size(); i < size; ++i)
1940     {
1941         map_marker *mark = markers[i];
1942         if (mark->get_type() != MAT_TOMB)
1943             continue;
1944
1945         map_tomb_marker *cmark = dynamic_cast<map_tomb_marker*>(mark);
1946         cmark->duration -= duration;
1947
1948         // Empty tombs disappear early.
1949         monster* mon_entombed = monster_at(cmark->pos);
1950         bool empty_tomb = !(mon_entombed || you.pos() == cmark->pos);
1951         bool zin = (cmark->source == -GOD_ZIN);
1952
1953         if (cmark->duration <= 0 || empty_tomb)
1954         {
1955             _drop_tomb(cmark->pos, empty_tomb, zin);
1956
1957             monster* mon_src =
1958                 !invalid_monster_index(cmark->source) ? &menv[cmark->source]
1959                                                       : NULL;
1960             // A monster's Tomb of Doroklohe spell.
1961             if (mon_src
1962                 && mon_src == mon_entombed)
1963             {
1964                 mon_src->lose_energy(EUT_SPELL);
1965             }
1966
1967             env.markers.remove(cmark);
1968         }
1969     }
1970 }
1971
1972 void timeout_terrain_changes(int duration, bool force)
1973 {
1974     if (!duration && !force)
1975         return;
1976
1977     int num_seen[NUM_TERRAIN_CHANGE_TYPES] = {0};
1978
1979     vector<map_marker*> markers = env.markers.get_all(MAT_TERRAIN_CHANGE);
1980
1981     for (int i = 0, size = markers.size(); i < size; ++i)
1982     {
1983         map_terrain_change_marker *marker =
1984                 dynamic_cast<map_terrain_change_marker*>(markers[i]);
1985
1986         if (marker->duration != INFINITE_DURATION)
1987             marker->duration -= duration;
1988
1989         monster* mon_src = monster_by_mid(marker->mon_num);
1990         if (marker->duration <= 0
1991             || (marker->mon_num != 0
1992                 && (!mon_src || !mon_src->alive() || mon_src->pacified())))
1993         {
1994             if (you.see_cell(marker->pos))
1995                 num_seen[marker->change_type]++;
1996             revert_terrain_change(marker->pos, marker->change_type);
1997         }
1998     }
1999
2000     if (num_seen[TERRAIN_CHANGE_DOOR_SEAL] > 1)
2001         mpr("The seals upon the doors fade away.");
2002     else if (num_seen[TERRAIN_CHANGE_DOOR_SEAL] > 0)
2003         mpr("The seal upon the door fades away.");
2004 }
2005
2006 void bring_to_safety()
2007 {
2008     if (player_in_branch(BRANCH_ABYSS))
2009         return abyss_teleport(true);
2010
2011     if (crawl_state.game_is_zotdef() && !orb_position().origin())
2012     {
2013         // In ZotDef, it's not the safety of your sorry butt that matters.
2014         for (distance_iterator di(env.orb_pos, true, false); di; ++di)
2015             if (!monster_at(*di)
2016                 && !(env.pgrid(*di) & FPROP_NO_TELE_INTO))
2017             {
2018                 you.moveto(*di);
2019                 return;
2020             }
2021     }
2022
2023     coord_def best_pos, pos;
2024     double min_threat = 1e38;
2025     int tries = 0;
2026
2027     // Up to 100 valid spots, but don't lock up when there's none.  This can happen
2028     // on tiny Zig/portal rooms with a bad summon storm and you in cloud / over water.
2029     while (tries < 100000 && min_threat > 0)
2030     {
2031         pos.x = random2(GXM);
2032         pos.y = random2(GYM);
2033         if (!in_bounds(pos)
2034             || grd(pos) != DNGN_FLOOR
2035             || env.cgrid(pos) != EMPTY_CLOUD
2036             || monster_at(pos)
2037             || env.pgrid(pos) & FPROP_NO_TELE_INTO
2038             || crawl_state.game_is_sprint()
2039                && distance2(pos, you.pos()) > dist_range(10))
2040         {
2041             tries++;
2042             continue;
2043         }
2044
2045         for (adjacent_iterator ai(pos); ai; ++ai)
2046             if (grd(*ai) == DNGN_SLIMY_WALL)
2047             {
2048                 tries++;
2049                 continue;
2050             }
2051
2052         bool junk;
2053         double gen_threat = 0.0, hi_threat = 0.0;
2054         monster_threat_values(&gen_threat, &hi_threat, &junk);
2055         const double threat = gen_threat * hi_threat;
2056
2057         if (threat < min_threat)
2058         {
2059             best_pos = pos;
2060             min_threat = threat;
2061         }
2062         tries += 1000;
2063     }
2064
2065     if (min_threat != 1e38)
2066         you.moveto(best_pos);
2067 }
2068
2069 // This includes ALL afflictions, unlike wizard/Xom revive.
2070 void revive()
2071 {
2072     adjust_level(-1);
2073     // Allow a spare after two levels (we just lost one); the exact value
2074     // doesn't matter here.
2075     you.attribute[ATTR_LIFE_GAINED] = 0;
2076
2077     you.disease = 0;
2078     you.magic_contamination = 0;
2079     set_hunger(HUNGER_DEFAULT, true);
2080     restore_stat(STAT_ALL, 0, true);
2081     you.rotting = 0;
2082
2083     you.attribute[ATTR_DIVINE_REGENERATION] = 0;
2084     you.attribute[ATTR_DELAYED_FIREBALL] = 0;
2085     clear_trapping_net();
2086     you.attribute[ATTR_DIVINE_VIGOUR] = 0;
2087     you.attribute[ATTR_DIVINE_STAMINA] = 0;
2088     you.attribute[ATTR_DIVINE_SHIELD] = 0;
2089     if (you.duration[DUR_WEAPON_BRAND])
2090         set_item_ego_type(*you.weapon(), OBJ_WEAPONS, SPWPN_NORMAL);
2091     if (you.form)
2092         untransform();
2093     you.clear_beholders();
2094     you.clear_fearmongers();
2095     you.attribute[ATTR_DIVINE_DEATH_CHANNEL] = 0;
2096     you.attribute[ATTR_INVIS_UNCANCELLABLE] = 0;
2097     you.attribute[ATTR_FLIGHT_UNCANCELLABLE] = 0;
2098     if (you.duration[DUR_SCRYING])
2099         you.xray_vision = false;
2100
2101     for (int dur = 0; dur < NUM_DURATIONS; dur++)
2102         if (dur != DUR_GOURMAND && dur != DUR_PIETY_POOL)
2103             you.duration[dur] = 0;
2104
2105     // Stat death that wasn't cleared might be:
2106     // * permanent (focus card): our fix is spot on
2107     // * long-term (mutation): we induce some penalty, ok
2108     // * short-term (-stat item): could be done better...
2109     unfocus_stats();
2110     you.stat_zero.init(0);
2111
2112     unrot_hp(9999);
2113     set_hp(9999);
2114     set_mp(9999);
2115     you.dead = false;
2116
2117     // Remove silence.
2118     invalidate_agrid();
2119
2120     if (you.hp_max <= 0)
2121     {
2122         you.lives = 0;
2123         mpr("You are too frail to live.");
2124         // possible only with an extreme abuse of Borgnjor's
2125         ouch(INSTANT_DEATH, NON_MONSTER, KILLED_BY_DRAINING);
2126     }
2127
2128     mpr("You rejoin the land of the living...");
2129     more();
2130
2131     burden_change();
2132 }
2133
2134 ////////////////////////////////////////////////////////////////////////////
2135 // Living breathing dungeon stuff.
2136 //
2137
2138 static vector<coord_def> sfx_seeds;
2139
2140 void setup_environment_effects()
2141 {
2142     sfx_seeds.clear();
2143
2144     for (int x = X_BOUND_1; x <= X_BOUND_2; ++x)
2145     {
2146         for (int y = Y_BOUND_1; y <= Y_BOUND_2; ++y)
2147         {
2148             if (!in_bounds(x, y))
2149                 continue;
2150
2151             const int grid = grd[x][y];
2152             if (grid == DNGN_LAVA
2153                     || (grid == DNGN_SHALLOW_WATER
2154                         && player_in_branch(BRANCH_SWAMP)))
2155             {
2156                 const coord_def c(x, y);
2157                 sfx_seeds.push_back(c);
2158             }
2159         }
2160     }
2161     dprf("%u environment effect seeds", (unsigned int)sfx_seeds.size());
2162 }
2163
2164 static void apply_environment_effect(const coord_def &c)
2165 {
2166     const dungeon_feature_type grid = grd(c);
2167     // Don't apply if if the feature doesn't want it.
2168     if (testbits(env.pgrid(c), FPROP_NO_CLOUD_GEN))
2169         return;
2170     if (grid == DNGN_LAVA)
2171         check_place_cloud(CLOUD_BLACK_SMOKE, c, random_range(4, 8), 0);
2172     else if (one_chance_in(3) && grid == DNGN_SHALLOW_WATER)
2173         check_place_cloud(CLOUD_MIST,        c, random_range(2, 5), 0);
2174 }
2175
2176 static const int Base_Sfx_Chance = 5;
2177 void run_environment_effects()
2178 {
2179     if (!you.time_taken)
2180         return;
2181
2182     dungeon_events.fire_event(DET_TURN_ELAPSED);
2183
2184     // Each square in sfx_seeds has this chance of doing something special
2185     // per turn.
2186     const int sfx_chance = Base_Sfx_Chance * you.time_taken / 10;
2187     const int nseeds = sfx_seeds.size();
2188
2189     // If there are a large number of seeds, speed things up by fudging the
2190     // numbers.
2191     if (nseeds > 50)
2192     {
2193         int nsels = div_rand_round(sfx_seeds.size() * sfx_chance, 100);
2194         if (one_chance_in(5))
2195             nsels += random2(nsels * 3);
2196
2197         for (int i = 0; i < nsels; ++i)
2198             apply_environment_effect(sfx_seeds[ random2(nseeds) ]);
2199     }
2200     else
2201     {
2202         for (int i = 0; i < nseeds; ++i)
2203         {
2204             if (random2(100) >= sfx_chance)
2205                 continue;
2206
2207             apply_environment_effect(sfx_seeds[i]);
2208         }
2209     }
2210
2211     run_corruption_effects(you.time_taken);
2212     shoals_apply_tides(div_rand_round(you.time_taken, BASELINE_DELAY),
2213                        false, true);
2214     timeout_tombs(you.time_taken);
2215     timeout_malign_gateways(you.time_taken);
2216     timeout_phoenix_markers(you.time_taken);
2217     timeout_terrain_changes(you.time_taken);
2218     run_cloud_spreaders(you.time_taken);
2219 }
2220
2221 coord_def pick_adjacent_free_square(const coord_def& p)
2222 {
2223     int num_ok = 0;
2224     coord_def result(-1, -1);
2225
2226     for (adjacent_iterator ai(p); ai; ++ai)
2227     {
2228         if (grd(*ai) == DNGN_FLOOR && monster_at(*ai) == NULL
2229             && one_chance_in(++num_ok))
2230         {
2231             result = *ai;
2232         }
2233     }
2234
2235     return result;
2236 }
2237
2238 // Converts a movement speed to a duration. i.e., answers the
2239 // question: if the monster is so fast, how much time has it spent in
2240 // its last movement?
2241 //
2242 // If speed is 10 (normal),    one movement is a duration of 10.
2243 // If speed is 1  (very slow), each movement is a duration of 100.
2244 // If speed is 15 (50% faster than normal), each movement is a duration of
2245 // 6.6667.
2246 int speed_to_duration(int speed)
2247 {
2248     if (speed < 1)
2249         speed = 10;
2250     else if (speed > 100)
2251         speed = 100;
2252
2253     return div_rand_round(100, speed);
2254 }
2255
2256 bool bad_attack(const monster *mon, string& adj, string& suffix)
2257 {
2258     ASSERT(!crawl_state.game_is_arena());
2259     if (!you.can_see(mon))
2260         return false;
2261
2262     adj.clear();
2263     suffix.clear();
2264
2265     if (is_sanctuary(you.pos()) || is_sanctuary(mon->pos()))
2266         suffix = ", despite your sanctuary";
2267
2268     if (mon->friendly())
2269     {
2270         if (you.religion == GOD_OKAWARU)
2271             adj = "your ally the ";
2272         else
2273             adj = "your ";
2274         return true;
2275     }
2276
2277     if (is_unchivalric_attack(&you, mon)
2278         && you.religion == GOD_SHINING_ONE
2279         && !tso_unchivalric_attack_safe_monster(mon))
2280     {
2281         adj += "helpless ";
2282     }
2283     if (mon->neutral() && is_good_god(you.religion))
2284         adj += "neutral ";
2285     else if (mon->wont_attack())
2286         adj += "non-hostile ";
2287
2288     if (you.religion == GOD_JIYVA && mons_is_slime(mon)
2289         && !(mon->is_shapeshifter() && (mon->flags & MF_KNOWN_SHIFTER)))
2290     {
2291         return true;
2292     }
2293
2294     return !adj.empty() || !suffix.empty();
2295 }
2296
2297 bool stop_attack_prompt(const monster* mon, bool beam_attack,
2298                         coord_def beam_target, bool autohit_first,
2299                         bool *prompted)
2300 {
2301     if (prompted)
2302         *prompted = false;
2303
2304     if (crawl_state.disables[DIS_CONFIRMATIONS])
2305         return false;
2306
2307     if (you.confused() || !you.can_see(mon))
2308         return false;
2309
2310     string adj, suffix;
2311     if (!bad_attack(mon, adj, suffix))
2312         return false;
2313
2314     // Listed in the form: "your rat", "Blork the orc".
2315     string mon_name = mon->name(DESC_PLAIN);
2316     if (!mon_name.find("the ")) // no "your the royal jelly" nor "the the RJ"
2317         mon_name.erase(0, 4);
2318     if (adj.find("your"))
2319         adj = "the " + adj;
2320     mon_name = adj + mon_name;
2321     string verb;
2322     if (beam_attack)
2323     {
2324         verb = "fire ";
2325         if (beam_target == mon->pos())
2326             verb += "at ";
2327         else if (you.pos() < beam_target && beam_target < mon->pos()
2328                  || you.pos() > beam_target && beam_target > mon->pos())
2329         {
2330             if (autohit_first)
2331                 return false;
2332
2333             verb += "in " + apostrophise(mon_name) + " direction";
2334             mon_name = "";
2335         }
2336         else
2337             verb += "through ";
2338     }
2339     else
2340         verb = "attack ";
2341
2342     snprintf(info, INFO_SIZE, "Really %s%s%s?",
2343              verb.c_str(), mon_name.c_str(), suffix.c_str());
2344
2345     if (prompted)
2346         *prompted = true;
2347
2348     if (yesno(info, false, 'n'))
2349         return false;
2350     else
2351     {
2352         canned_msg(MSG_OK);
2353         return true;
2354     }
2355 }
2356
2357 bool stop_attack_prompt(targetter &hitfunc, string verb,
2358                         bool (*affects)(const actor *victim))
2359 {
2360     if (crawl_state.disables[DIS_CONFIRMATIONS])
2361         return false;
2362
2363     if (crawl_state.which_god_acting() == GOD_XOM)
2364         return false;
2365
2366     if (you.confused())
2367         return false;
2368
2369     string adj, suffix;
2370     counted_monster_list victims;
2371     for (distance_iterator di(hitfunc.origin, false, true, LOS_RADIUS); di; ++di)
2372     {
2373         if (hitfunc.is_affected(*di) <= AFF_NO)
2374             continue;
2375         const monster* mon = monster_at(*di);
2376         if (!mon || !you.can_see(mon))
2377             continue;
2378         if (affects && !affects(mon))
2379             continue;
2380         string adjn, suffixn;
2381         if (bad_attack(mon, adjn, suffixn))
2382         {
2383             if (victims.empty()) // record the adjectives for the first listed
2384                 adj = adjn, suffix = suffixn;
2385             victims.add(mon);
2386         }
2387     }
2388
2389     if (victims.empty())
2390         return false;
2391
2392     // Listed in the form: "your rat", "Blork the orc".
2393     string mon_name = victims.describe(DESC_PLAIN);
2394     if (!mon_name.find("the ")) // no "your the royal jelly" nor "the the RJ"
2395         mon_name.erase(0, 4);
2396     if (adj.find("your"))
2397         adj = "the " + adj;
2398     mon_name = adj + mon_name;
2399
2400     snprintf(info, INFO_SIZE, "Really %s %s%s?",
2401              verb.c_str(), mon_name.c_str(), suffix.c_str());
2402
2403     if (yesno(info, false, 'n'))
2404         return false;
2405     else
2406     {
2407         canned_msg(MSG_OK);
2408         return true;
2409     }
2410 }
2411
2412 bool is_orckind(const actor *act)
2413 {
2414     if (mons_genus(act->mons_species()) == MONS_ORC)
2415         return true;
2416
2417     if (act->is_monster())
2418     {
2419         const monster* mon = act->as_monster();
2420         if (mons_is_zombified(mon)
2421             && mons_genus(mon->base_monster) == MONS_ORC)
2422         {
2423             return true;
2424         }
2425         if (mons_is_ghost_demon(mon->type)
2426             && (mon->ghost->species == SP_HILL_ORC
2427                 || mon->ghost->species == SP_LAVA_ORC))
2428         {
2429             return true;
2430         }
2431     }
2432
2433     return false;
2434 }
2435
2436 bool is_dragonkind(const actor *act)
2437 {
2438     if (mons_genus(act->mons_species()) == MONS_DRAGON
2439         || mons_genus(act->mons_species()) == MONS_DRACONIAN)
2440     {
2441         return true;
2442     }
2443
2444     if (act->is_player())
2445         return (you.form == TRAN_DRAGON);
2446
2447     // Else the actor is a monster.
2448     const monster* mon = act->as_monster();
2449
2450     if (mons_is_zombified(mon)
2451         && (mons_genus(mon->base_monster) == MONS_DRAGON
2452             || mons_genus(mon->base_monster) == MONS_DRACONIAN))
2453     {
2454         return true;
2455     }
2456
2457     if (mons_is_ghost_demon(mon->type)
2458         && species_genus(mon->ghost->species) == GENPC_DRACONIAN)
2459     {
2460         return true;
2461     }
2462
2463     return false;
2464 }
2465
2466 // Make the player swap positions with a given monster.
2467 void swap_with_monster(monster* mon_to_swap)
2468 {
2469     monster& mon(*mon_to_swap);
2470     ASSERT(mon.alive());
2471     const coord_def newpos = mon.pos();
2472
2473     // Be nice: no swapping into uninhabitable environments.
2474     if (!you.is_habitable(newpos) || !mon.is_habitable(you.pos()))
2475     {
2476         mpr("You spin around.");
2477         return;
2478     }
2479
2480     const bool mon_caught = mon.caught();
2481     const bool you_caught = you.attribute[ATTR_HELD];
2482
2483     // If it was submerged, it surfaces first.
2484     mon.del_ench(ENCH_SUBMERGED);
2485
2486     mprf("You swap places with %s.", mon.name(DESC_THE).c_str());
2487
2488     // Pick the monster up.
2489     mgrd(newpos) = NON_MONSTER;
2490     mon.moveto(you.pos());
2491
2492     // Plunk it down.
2493     mgrd(mon.pos()) = mon_to_swap->mindex();
2494
2495     if (you_caught)
2496     {
2497         check_net_will_hold_monster(&mon);
2498         if (!mon_caught)
2499         {
2500             you.attribute[ATTR_HELD] = 0;
2501             you.redraw_quiver = true;
2502         }
2503     }
2504
2505     // Move you to its previous location.
2506     move_player_to_grid(newpos, false, true);
2507
2508     if (mon_caught)
2509     {
2510         if (you.body_size(PSIZE_BODY) >= SIZE_GIANT)
2511         {
2512             int net = get_trapping_net(you.pos());
2513             if (net != NON_ITEM)
2514                 destroy_item(net);
2515             mprf("The %s rips apart!", (net == NON_ITEM) ? "web" : "net");
2516             you.attribute[ATTR_HELD] = 0;
2517             you.redraw_quiver = true;
2518         }
2519         else
2520         {
2521             you.attribute[ATTR_HELD] = 10;
2522             if (get_trapping_net(you.pos()) != NON_ITEM)
2523                 mpr("You become entangled in the net!");
2524             else
2525                 mpr("You get stuck in the web!");
2526             you.redraw_quiver = true; // Account for being in a net.
2527             // Xom thinks this is hilarious if you trap yourself this way.
2528             if (you_caught)
2529                 xom_is_stimulated(12);
2530             else
2531                 xom_is_stimulated(200);
2532         }
2533
2534         if (!you_caught)
2535             mon.del_ench(ENCH_HELD, true);
2536     }
2537 }
2538
2539 /**
2540  * Identify a worn piece of jewellery's type.
2541  */
2542 void wear_id_type(item_def &item)
2543 {
2544     if (item_type_known(item))
2545         return;
2546     set_ident_type(item.base_type, item.sub_type, ID_KNOWN_TYPE);
2547     set_ident_flags(item, ISFLAG_KNOW_TYPE);
2548     mprf("You are wearing: %s",
2549          item.name(DESC_INVENTORY_EQUIP).c_str());
2550 }
2551
2552 static void _maybe_id_jewel(jewellery_type ring_type = NUM_JEWELLERY,
2553                             jewellery_type amulet_type = NUM_JEWELLERY,
2554                             artefact_prop_type artp = ARTP_NUM_PROPERTIES)
2555 {
2556     for (int i = EQ_LEFT_RING; i < NUM_EQUIP; ++i)
2557     {
2558         if (player_wearing_slot(i))
2559         {
2560             item_def& item = you.inv[you.equip[i]];
2561             if (item.sub_type == ring_type || item.sub_type == amulet_type)
2562                 wear_id_type(item);
2563             bool known;
2564             if (artp != ARTP_NUM_PROPERTIES && is_artefact(item)
2565                 && artefact_wpn_property(item, artp, known)
2566                 && !known)
2567             {
2568                 artefact_wpn_learn_prop(item, artp);
2569                 mprf("You are wearing: %s",
2570                      item.name(DESC_INVENTORY_EQUIP).c_str());
2571             }
2572         }
2573     }
2574 }
2575
2576 void maybe_id_ring_hunger()
2577 {
2578     _maybe_id_jewel(RING_HUNGER, NUM_JEWELLERY, ARTP_METABOLISM);
2579     _maybe_id_jewel(RING_SUSTENANCE, NUM_JEWELLERY, ARTP_METABOLISM);
2580 }
2581
2582 void maybe_id_ring_see_invis()
2583 {
2584     _maybe_id_jewel(RING_SEE_INVISIBLE, NUM_JEWELLERY, ARTP_EYESIGHT);
2585 }
2586
2587 void maybe_id_clarity()
2588 {
2589     _maybe_id_jewel(NUM_JEWELLERY, AMU_CLARITY, ARTP_CLARITY);
2590 }
2591
2592 void maybe_id_resist(beam_type flavour)
2593 {
2594     switch (flavour)
2595     {
2596     case BEAM_FIRE:
2597     case BEAM_LAVA:
2598         _maybe_id_jewel(RING_PROTECTION_FROM_FIRE, NUM_JEWELLERY, ARTP_FIRE);
2599         break;
2600
2601     case BEAM_COLD:
2602     case BEAM_ICE:
2603         _maybe_id_jewel(RING_PROTECTION_FROM_COLD, NUM_JEWELLERY, ARTP_COLD);
2604         break;
2605
2606     case BEAM_ELECTRICITY:
2607         _maybe_id_jewel(NUM_JEWELLERY, NUM_JEWELLERY, ARTP_ELECTRICITY);
2608         break;
2609
2610     case BEAM_POISON:
2611     case BEAM_POISON_ARROW:
2612     case BEAM_MEPHITIC:
2613         _maybe_id_jewel(RING_POISON_RESISTANCE, NUM_JEWELLERY, ARTP_POISON);
2614         break;
2615
2616     case BEAM_NEG:
2617         _maybe_id_jewel(RING_LIFE_PROTECTION, AMU_WARDING, ARTP_NEGATIVE_ENERGY);
2618         break;
2619
2620     case BEAM_STEAM:
2621         // rF+ grants rSteam, all possibly unidentified sources of rSteam are rF
2622         _maybe_id_jewel(RING_PROTECTION_FROM_FIRE, NUM_JEWELLERY, ARTP_FIRE);
2623         break;
2624
2625     case BEAM_MALMUTATE:
2626         _maybe_id_jewel(NUM_JEWELLERY, AMU_RESIST_MUTATION);
2627         break;
2628
2629     default: ;
2630     }
2631 }
2632
2633 bool maybe_id_weapon(item_def &item, const char *msg)
2634 {
2635     // Do we need to identify an artefact brand?
2636     bool do_art_brand = false;
2637     iflags_t id = 0;
2638
2639     // Weapons you have wielded or know enough about.
2640     if (item.base_type == OBJ_WEAPONS
2641         && !(item.flags & ISFLAG_KNOW_PLUSES))
2642     {
2643         int min_skill20 = ((int)item.rnd) * 2 / 3;
2644
2645         if (item.flags & ISFLAG_KNOW_CURSE
2646             && item.flags & ISFLAG_KNOW_TYPE
2647             && you.skill(is_range_weapon(item) ? range_skill(item)
2648                          : weapon_skill(item), 20, true) > min_skill20)
2649         {
2650             id = ISFLAG_KNOW_PLUSES;
2651         }
2652         else if (is_throwable(&you, item)
2653                  && you.skill(SK_THROWING, 20, true) > min_skill20)
2654         {
2655             id = ISFLAG_KNOW_PLUSES | ISFLAG_KNOW_CURSE;
2656             if (is_artefact(item))
2657                 do_art_brand = !artefact_known_wpn_property(item, ARTP_BRAND);
2658             else
2659                 id |= ISFLAG_KNOW_TYPE;
2660         }
2661     }
2662
2663     if ((item.flags | id) != item.flags || do_art_brand)
2664     {
2665         set_ident_flags(item, id);
2666         if (do_art_brand)
2667             artefact_wpn_learn_prop(item, ARTP_BRAND);
2668         if (msg)
2669             mprf("%s%s", msg, item.name(DESC_INVENTORY_EQUIP).c_str());
2670         you.wield_change = true;
2671         return true;
2672     }
2673
2674     return false;
2675 }
2676
2677 void auto_id_inventory()
2678 {
2679     for (int i = 0; i < ENDOFPACK; i++)
2680     {
2681         item_def& item = you.inv[i];
2682         if (item.defined())
2683         {
2684             maybe_id_weapon(item, "You determine that you are carrying: ");
2685             god_id_item(item, false);
2686         }
2687     }
2688 }
2689
2690 // Reduce damage by AC.
2691 // In most cases, we want AC to mostly stop weak attacks completely but affect
2692 // strong ones less, but the regular formula is too hard to apply well to cases
2693 // when damage is spread into many small chunks.
2694 //
2695 // Every point of damage is processed independently.  Every point of AC has
2696 // an independent 1/81 chance of blocking that damage.
2697 //
2698 // AC 20 stops 22% of damage, AC 40 -- 39%, AC 80 -- 63%.
2699 int apply_chunked_AC(int dam, int ac)
2700 {
2701     double chance = pow(80.0/81, ac);
2702     uint64_t cr = chance * (((uint64_t)1) << 32);
2703
2704     int hurt = 0;
2705     for (int i = 0; i < dam; i++)
2706         if (random_int() < cr)
2707             hurt++;
2708
2709     return hurt;
2710 }
2711
2712 void entered_malign_portal(actor* act)
2713 {
2714     if (you.can_see(act))
2715     {
2716         mprf("The portal repels %s, its terrible forces doing untold damage!",
2717              act->is_player() ? "you" : act->name(DESC_THE).c_str());
2718     }
2719
2720     act->blink(false);
2721     if (act->is_player())
2722         ouch(roll_dice(2, 4), NON_MONSTER, KILLED_BY_WILD_MAGIC, "a malign gateway");
2723     else
2724         act->hurt(NULL, roll_dice(2, 4));
2725 }
2726
2727 void handle_real_time(time_t t)
2728 {
2729     you.real_time += min<time_t>(t - you.last_keypress_time, IDLE_TIME_CLAMP);
2730     you.last_keypress_time = t;
2731 }
2732
2733 string part_stack_string(const int num, const int total)
2734 {
2735     if (num == total)
2736         return "Your";
2737
2738     string ret  = uppercase_first(number_in_words(num));
2739            ret += " of your";
2740
2741     return ret;
2742 }
2743
2744 unsigned int breakpoint_rank(int val, const int breakpoints[],
2745                              unsigned int num_breakpoints)
2746 {
2747     unsigned int result = 0;
2748     while (result < num_breakpoints && val >= breakpoints[result])
2749         ++result;
2750
2751     return result;
2752 }
2753
2754 void counted_monster_list::add(const monster* mons)
2755 {
2756     const string name = mons->name(DESC_PLAIN);
2757     for (counted_list::iterator i = list.begin(); i != list.end(); ++i)
2758     {
2759         if (i->first->name(DESC_PLAIN) == name)
2760         {
2761             i->second++;
2762             return;
2763         }
2764     }
2765     list.push_back(counted_monster(mons, 1));
2766 }
2767
2768 int counted_monster_list::count()
2769 {
2770     int nmons = 0;
2771     for (counted_list::const_iterator i = list.begin(); i != list.end(); ++i)
2772         nmons += i->second;
2773     return nmons;
2774 }
2775
2776 string counted_monster_list::describe(description_level_type desc)
2777 {
2778     string out;
2779
2780     for (counted_list::const_iterator i = list.begin(); i != list.end();)
2781     {
2782         const counted_monster &cm(*i);
2783         if (i != list.begin())
2784         {
2785             ++i;
2786             out += (i == list.end() ? " and " : ", ");
2787         }
2788         else
2789             ++i;
2790
2791         out += cm.second > 1 ? pluralise(cm.first->name(desc))
2792                              : cm.first->name(desc);
2793     }
2794     return out;
2795 }
2796
2797
2798
2799 bool move_stairs(coord_def orig, coord_def dest)
2800 {
2801     const dungeon_feature_type stair_feat = grd(orig);
2802
2803     if (feat_stair_direction(stair_feat) == CMD_NO_CMD)
2804         return false;
2805
2806     // The player can't use shops to escape, so don't bother.
2807     if (stair_feat == DNGN_ENTER_SHOP)
2808         return false;
2809
2810     // Don't move around notable terrain the player is aware of if it's
2811     // out of sight.
2812     if (is_notable_terrain(stair_feat)
2813         && env.map_knowledge(orig).known() && !you.see_cell(orig))
2814     {
2815         return false;
2816     }
2817
2818     return slide_feature_over(orig, dest);
2819 }