Use cell_is_solid where appropriate.
[crawl:crawl.git] / crawl-ref / source / decks.cc
1 /**
2  * @file
3  * @brief Functions with decks of cards.
4 **/
5
6 #include "AppHdr.h"
7
8 #include "decks.h"
9
10 #include <iostream>
11 #include <algorithm>
12
13 #include "externs.h"
14
15 #include "act-iter.h"
16 #include "beam.h"
17 #include "cio.h"
18 #include "coordit.h"
19 #include "database.h"
20 #include "dactions.h"
21 #include "describe.h"
22 #include "dungeon.h"
23 #include "effects.h"
24 #include "env.h"
25 #include "files.h"
26 #include "food.h"
27 #include "ghost.h"
28 #include "godwrath.h"
29 #include "invent.h"
30 #include "item_use.h"
31 #include "itemprop.h"
32 #include "items.h"
33 #include "libutil.h"
34 #include "macro.h"
35 #include "makeitem.h"
36 #include "maps.h"
37 #include "message.h"
38 #include "misc.h"
39 #include "mon-place.h"
40 #include "mon-project.h"
41 #include "mon-util.h"
42 #include "mgen_data.h"
43 #include "mon-stuff.h"
44 #include "mutation.h"
45 #include "notes.h"
46 #include "options.h"
47 #include "ouch.h"
48 #include "player.h"
49 #include "player-equip.h"
50 #include "player-stats.h"
51 #include "potion.h"
52 #include "religion.h"
53 #include "godconduct.h"
54 #include "skill_menu.h"
55 #include "skills2.h"
56 #include "spl-cast.h"
57 #include "spl-damage.h"
58 #include "spl-goditem.h"
59 #include "spl-miscast.h"
60 #include "spl-other.h"
61 #include "spl-selfench.h"
62 #include "spl-summoning.h"
63 #include "spl-transloc.h"
64 #include "spl-util.h"
65 #include "spl-wpnench.h"
66 #include "state.h"
67 #include "stuff.h"
68 #include "terrain.h"
69 #include "transform.h"
70 #include "traps.h"
71 #include "uncancel.h"
72 #include "view.h"
73 #include "xom.h"
74
75 // DECK STRUCTURE: deck.plus is the number of cards the deck *started*
76 // with, deck.plus2 is the number of cards drawn, deck.special is the
77 // deck rarity, deck.props["cards"] holds the list of cards (with the
78 // highest index card being the top card, and index 0 being the bottom
79 // card), deck.props["drawn_cards"] holds the list of drawn cards
80 // (with index 0 being the first drawn), deck.props["card_flags"]
81 // holds the flags for each card, deck.props["num_marked"] is the
82 // number of marked cards left in the deck.
83 //
84 // The card type and per-card flags are each stored as unsigned bytes,
85 // for a maximum of 256 different kinds of cards and 8 bits of flags.
86
87 static void _deck_ident(item_def& deck);
88
89 struct card_with_weights
90 {
91     card_type card;
92     int weight[3];
93 };
94
95 typedef card_with_weights deck_archetype;
96
97 #define END_OF_DECK {NUM_CARDS, {0,0,0}}
98
99 const deck_archetype deck_of_transport[] =
100 {
101     { CARD_PORTAL,   {5, 5, 5} },
102     { CARD_WARP,     {5, 5, 5} },
103     { CARD_SWAP,     {5, 5, 5} },
104     { CARD_VELOCITY, {5, 5, 5} },
105     END_OF_DECK
106 };
107
108 const deck_archetype deck_of_emergency[] =
109 {
110     { CARD_TOMB,       {4, 4, 4} },
111     { CARD_BANSHEE,    {5, 5, 5} },
112     { CARD_DAMNATION,  {0, 1, 2} },
113     { CARD_SOLITUDE,   {5, 5, 5} },
114     { CARD_WARPWRIGHT, {5, 5, 5} },
115     { CARD_FLIGHT,     {5, 5, 5} },
116     END_OF_DECK
117 };
118
119 const deck_archetype deck_of_destruction[] =
120 {
121     { CARD_VITRIOL, {5, 5, 5} },
122     { CARD_FLAME,   {5, 5, 5} },
123     { CARD_FROST,   {5, 5, 5} },
124     { CARD_VENOM,   {5, 5, 5} },
125     { CARD_HAMMER,  {5, 5, 5} },
126     { CARD_SPARK,   {5, 5, 5} },
127     { CARD_PAIN,    {5, 5, 3} },
128     { CARD_ORB,     {5, 5, 5} },
129     END_OF_DECK
130 };
131
132 const deck_archetype deck_of_battle[] =
133 {
134     { CARD_ELIXIR,        {5, 5, 5} },
135     { CARD_BATTLELUST,    {5, 5, 5} },
136     { CARD_METAMORPHOSIS, {5, 5, 5} },
137     { CARD_HELM,          {5, 5, 5} },
138     { CARD_BLADE,         {5, 5, 5} },
139     { CARD_SHADOW,        {5, 5, 5} },
140     { CARD_MERCENARY,     {5, 5, 5} },
141     END_OF_DECK
142 };
143
144 const deck_archetype deck_of_enchantments[] =
145 {
146     { CARD_ELIXIR, {5, 5, 5} },
147     END_OF_DECK
148 };
149
150 const deck_archetype deck_of_summoning[] =
151 {
152     { CARD_CRUSADE,         {5, 5, 5} },
153     { CARD_SUMMON_ANIMAL,   {5, 5, 5} },
154     { CARD_SUMMON_DEMON,    {5, 5, 5} },
155     { CARD_SUMMON_WEAPON,   {5, 5, 5} },
156     { CARD_SUMMON_FLYING,   {5, 5, 5} },
157     { CARD_SUMMON_SKELETON, {5, 5, 5} },
158     { CARD_SUMMON_UGLY,     {5, 5, 5} },
159     END_OF_DECK
160 };
161
162 const deck_archetype deck_of_wonders[] =
163 {
164     { CARD_POTION,     {5, 5, 5} },
165     { CARD_FOCUS,      {1, 1, 2} },
166     { CARD_SHUFFLE,    {0, 1, 2} },
167     { CARD_EXPERIENCE, {3, 4, 5} },
168     { CARD_WILD_MAGIC, {5, 5, 5} },
169     { CARD_HELIX,      {5, 5, 5} },
170     { CARD_SAGE,       {5, 5, 5} },
171     { CARD_ALCHEMIST,  {5, 5, 5} },
172     END_OF_DECK
173 };
174
175 const deck_archetype deck_of_dungeons[] =
176 {
177     { CARD_WATER,     {5, 5, 5} },
178     { CARD_GLASS,     {5, 5, 5} },
179     { CARD_DOWSING,   {5, 5, 5} },
180     { CARD_TROWEL,    {5, 5, 3} },
181     { CARD_MINEFIELD, {5, 5, 5} },
182     END_OF_DECK
183 };
184
185 const deck_archetype deck_of_oddities[] =
186 {
187     { CARD_GENIE,   {5, 5, 5} },
188     { CARD_BARGAIN, {5, 5, 5} },
189     { CARD_WRATH,   {5, 5, 5} },
190     { CARD_XOM,     {5, 5, 5} },
191     { CARD_FEAST,   {5, 5, 5} },
192     { CARD_FAMINE,  {5, 5, 5} },
193     { CARD_CURSE,   {5, 5, 5} },
194     END_OF_DECK
195 };
196
197 const deck_archetype deck_of_punishment[] =
198 {
199     { CARD_WRAITH,     {5, 5, 5} },
200     { CARD_WILD_MAGIC, {5, 5, 5} },
201     { CARD_WRATH,      {5, 5, 5} },
202     { CARD_XOM,        {5, 5, 5} },
203     { CARD_FAMINE,     {5, 5, 5} },
204     { CARD_CURSE,      {5, 5, 5} },
205     { CARD_TOMB,       {5, 5, 5} },
206     { CARD_DAMNATION,  {5, 5, 5} },
207     { CARD_PORTAL,     {5, 5, 5} },
208     { CARD_MINEFIELD,  {5, 5, 5} },
209     { CARD_SWINE,      {5, 5, 5} },
210     { CARD_TORMENT,    {5, 5, 5} },
211     END_OF_DECK
212 };
213
214 static void _check_odd_card(uint8_t flags)
215 {
216     if ((flags & CFLAG_ODDITY) && !(flags & CFLAG_SEEN))
217         mpr("This card doesn't seem to belong here.");
218 }
219
220 static bool _card_forbidden(card_type card)
221 {
222     if (crawl_state.game_is_zotdef())
223         switch (card)
224         {
225         case CARD_TOMB:
226         case CARD_WARPWRIGHT:
227         case CARD_WATER:
228         case CARD_TROWEL:
229         case CARD_MINEFIELD: // with teleport taken away, might be acceptable
230         case CARD_STAIRS:
231             return true;
232         default:
233             break;
234         }
235     return false;
236 }
237
238 int cards_in_deck(const item_def &deck)
239 {
240     ASSERT(is_deck(deck));
241
242     const CrawlHashTable &props = deck.props;
243     ASSERT(props.exists("cards"));
244
245     return props["cards"].get_vector().size();
246 }
247
248 static void _shuffle_deck(item_def &deck)
249 {
250     ASSERT(is_deck(deck));
251
252     CrawlHashTable &props = deck.props;
253     ASSERT(props.exists("cards"));
254
255     CrawlVector &cards = props["cards"].get_vector();
256
257     CrawlVector &flags = props["card_flags"].get_vector();
258     ASSERT(flags.size() == cards.size());
259
260     // Don't use shuffle(), since we want to apply exactly the
261     // same shuffling to both the cards vector and the flags vector.
262     vector<vec_size> pos;
263     for (size_t i = 0; i < cards.size(); ++i)
264         pos.push_back(random2(cards.size()));
265
266     for (vec_size i = 0; i < pos.size(); ++i)
267     {
268         swap(cards[i], cards[pos[i]]);
269         swap(flags[i], flags[pos[i]]);
270     }
271 }
272
273 card_type get_card_and_flags(const item_def& deck, int idx,
274                              uint8_t& _flags)
275 {
276     const CrawlHashTable &props = deck.props;
277     const CrawlVector    &cards = props["cards"].get_vector();
278     const CrawlVector    &flags = props["card_flags"].get_vector();
279
280     // Negative idx means read from the end.
281     if (idx < 0)
282         idx += static_cast<int>(cards.size());
283
284     _flags = (uint8_t) flags[idx].get_byte();
285
286     return static_cast<card_type>(cards[idx].get_byte());
287 }
288
289 static void _set_card_and_flags(item_def& deck, int idx, card_type card,
290                                 uint8_t _flags)
291 {
292     CrawlHashTable &props = deck.props;
293     CrawlVector    &cards = props["cards"].get_vector();
294     CrawlVector    &flags = props["card_flags"].get_vector();
295
296     if (idx == -1)
297         idx = static_cast<int>(cards.size()) - 1;
298
299     cards[idx].get_byte() = card;
300     flags[idx].get_byte() = _flags;
301 }
302
303 const char* card_name(card_type card)
304 {
305     switch (card)
306     {
307     case CARD_PORTAL:          return "the Portal";
308     case CARD_WARP:            return "the Warp";
309     case CARD_SWAP:            return "Swap";
310     case CARD_VELOCITY:        return "Velocity";
311     case CARD_DAMNATION:       return "Damnation";
312     case CARD_SOLITUDE:        return "Solitude";
313     case CARD_ELIXIR:          return "the Elixir";
314     case CARD_BATTLELUST:      return "Battlelust";
315     case CARD_METAMORPHOSIS:   return "Metamorphosis";
316     case CARD_HELM:            return "the Helm";
317     case CARD_BLADE:           return "the Blade";
318     case CARD_SHADOW:          return "the Shadow";
319     case CARD_POTION:          return "the Potion";
320     case CARD_FOCUS:           return "Focus";
321     case CARD_SHUFFLE:         return "Shuffle";
322     case CARD_EXPERIENCE:      return "Experience";
323     case CARD_HELIX:           return "the Helix";
324     case CARD_SAGE:            return "the Sage";
325     case CARD_DOWSING:         return "Dowsing";
326     case CARD_TROWEL:          return "the Trowel";
327     case CARD_MINEFIELD:       return "the Minefield";
328     case CARD_STAIRS:          return "the Stairs";
329     case CARD_GENIE:           return "the Genie";
330     case CARD_TOMB:            return "the Tomb";
331     case CARD_WATER:           return "Water";
332     case CARD_GLASS:           return "Vitrification";
333     case CARD_BANSHEE:         return "the Banshee";
334     case CARD_WILD_MAGIC:      return "Wild Magic";
335     case CARD_CRUSADE:         return "the Crusade";
336     case CARD_SUMMON_ANIMAL:   return "the Herd";
337     case CARD_SUMMON_DEMON:    return "the Pentagram";
338     case CARD_SUMMON_WEAPON:   return "the Dance";
339     case CARD_SUMMON_FLYING:   return "Foxfire";
340     case CARD_SUMMON_SKELETON: return "the Bones";
341     case CARD_SUMMON_UGLY:     return "Repulsiveness";
342     case CARD_XOM:             return "Xom";
343     case CARD_FAMINE:          return "Famine";
344     case CARD_FEAST:           return "the Feast";
345     case CARD_WARPWRIGHT:      return "Warpwright";
346     case CARD_FLIGHT:          return "Flight";
347     case CARD_VITRIOL:         return "Vitriol";
348     case CARD_FLAME:           return "Flame";
349     case CARD_FROST:           return "Frost";
350     case CARD_VENOM:           return "Venom";
351     case CARD_SPARK:           return "the Spark";
352     case CARD_HAMMER:          return "the Hammer";
353     case CARD_PAIN:            return "Pain";
354     case CARD_TORMENT:         return "Torment";
355     case CARD_BARGAIN:         return "the Bargain";
356     case CARD_WRATH:           return "Wrath";
357     case CARD_WRAITH:          return "the Wraith";
358     case CARD_CURSE:           return "the Curse";
359     case CARD_SWINE:           return "the Swine";
360     case CARD_ALCHEMIST:       return "the Alchemist";
361     case CARD_ORB:             return "the Orb";
362     case CARD_MERCENARY:       return "the Mercenary";
363     case NUM_CARDS:            return "a buggy card";
364     }
365     return "a very buggy card";
366 }
367
368 static const deck_archetype* _random_sub_deck(uint8_t deck_type)
369 {
370     const deck_archetype *pdeck = NULL;
371     switch (deck_type)
372     {
373     case MISC_DECK_OF_ESCAPE:
374         pdeck = (coinflip() ? deck_of_transport : deck_of_emergency);
375         break;
376     case MISC_DECK_OF_DESTRUCTION: pdeck = deck_of_destruction; break;
377     case MISC_DECK_OF_DUNGEONS:    pdeck = deck_of_dungeons;    break;
378     case MISC_DECK_OF_SUMMONING:   pdeck = deck_of_summoning;   break;
379     case MISC_DECK_OF_WONDERS:     pdeck = deck_of_wonders;     break;
380     case MISC_DECK_OF_PUNISHMENT:  pdeck = deck_of_punishment;  break;
381     case MISC_DECK_OF_WAR:
382         switch (random2(6))
383         {
384         case 0: pdeck = deck_of_destruction;  break;
385         case 1: pdeck = deck_of_enchantments; break;
386         case 2: pdeck = deck_of_battle;       break;
387         case 3: pdeck = deck_of_summoning;    break;
388         case 4: pdeck = deck_of_transport;    break;
389         case 5: pdeck = deck_of_emergency;    break;
390         }
391         break;
392     case MISC_DECK_OF_CHANGES:
393         switch (random2(3))
394         {
395         case 0: pdeck = deck_of_battle;       break;
396         case 1: pdeck = deck_of_dungeons;     break;
397         case 2: pdeck = deck_of_wonders;      break;
398         }
399         break;
400     case MISC_DECK_OF_DEFENCE:
401         pdeck = (coinflip() ? deck_of_emergency : deck_of_battle);
402         break;
403     }
404
405     ASSERT(pdeck);
406
407     return pdeck;
408 }
409
410 static card_type _choose_from_archetype(const deck_archetype* pdeck,
411                                         deck_rarity_type rarity)
412 {
413     // Random rarity should have been replaced by one of the others by now.
414     ASSERT_RANGE(rarity, DECK_RARITY_COMMON, DECK_RARITY_LEGENDARY + 1);
415
416     // FIXME: We should use one of the various choose_random_weighted
417     // functions here, probably with an iterator, instead of
418     // duplicating the implementation.
419
420     int totalweight = 0;
421     card_type result = NUM_CARDS;
422     for (int i = 0; pdeck[i].card != NUM_CARDS; ++i)
423     {
424         const card_with_weights& cww = pdeck[i];
425         if (_card_forbidden(cww.card))
426             continue;
427         totalweight += cww.weight[rarity - DECK_RARITY_COMMON];
428         if (x_chance_in_y(cww.weight[rarity - DECK_RARITY_COMMON], totalweight))
429             result = cww.card;
430     }
431     return result;
432 }
433
434 static card_type _random_card(uint8_t deck_type, deck_rarity_type rarity,
435                               bool &was_oddity)
436 {
437     const deck_archetype *pdeck = _random_sub_deck(deck_type);
438
439     if (one_chance_in(100))
440     {
441         pdeck      = deck_of_oddities;
442         was_oddity = true;
443     }
444
445     return _choose_from_archetype(pdeck, rarity);
446 }
447
448 static card_type _random_card(const item_def& item, bool &was_oddity)
449 {
450     return _random_card(item.sub_type, deck_rarity(item), was_oddity);
451 }
452
453 static card_type _draw_top_card(item_def& deck, bool message,
454                                 uint8_t &_flags)
455 {
456     CrawlHashTable &props = deck.props;
457     CrawlVector    &cards = props["cards"].get_vector();
458     CrawlVector    &flags = props["card_flags"].get_vector();
459
460     int num_cards = cards.size();
461     int idx       = num_cards - 1;
462
463     ASSERT(num_cards > 0);
464
465     card_type card = get_card_and_flags(deck, idx, _flags);
466     cards.pop_back();
467     flags.pop_back();
468
469     if (message)
470     {
471         const char *verb = (_flags & CFLAG_DEALT) ? "deal" : "draw";
472
473         if (_flags & CFLAG_MARKED)
474             mprf("You %s %s.", verb, card_name(card));
475         else
476             mprf("You %s a card... It is %s.", verb, card_name(card));
477
478         _check_odd_card(_flags);
479     }
480
481     return card;
482 }
483
484 static void _push_top_card(item_def& deck, card_type card,
485                            uint8_t _flags)
486 {
487     CrawlHashTable &props = deck.props;
488     CrawlVector    &cards = props["cards"].get_vector();
489     CrawlVector    &flags = props["card_flags"].get_vector();
490
491     cards.push_back((char) card);
492     flags.push_back((char) _flags);
493 }
494
495 static void _remember_drawn_card(item_def& deck, card_type card, bool allow_id)
496 {
497     ASSERT(is_deck(deck));
498     CrawlHashTable &props = deck.props;
499     CrawlVector &drawn = props["drawn_cards"].get_vector();
500     drawn.push_back(static_cast<char>(card));
501
502     // Once you've drawn two cards, you know the deck.
503     if (allow_id && (drawn.size() >= 2 || origin_is_god_gift(deck)))
504         _deck_ident(deck);
505 }
506
507 const vector<card_type> get_drawn_cards(const item_def& deck)
508 {
509     vector<card_type> result;
510     if (is_deck(deck))
511     {
512         const CrawlHashTable &props = deck.props;
513         const CrawlVector &drawn = props["drawn_cards"].get_vector();
514         for (unsigned int i = 0; i < drawn.size(); ++i)
515         {
516             const char tmp = drawn[i];
517             result.push_back(static_cast<card_type>(tmp));
518         }
519     }
520     return result;
521 }
522
523 static bool _check_buggy_deck(item_def& deck)
524 {
525     ostream& strm = msg::streams(MSGCH_DIAGNOSTICS);
526     if (!is_deck(deck))
527     {
528         crawl_state.zero_turns_taken();
529         strm << "This isn't a deck at all!" << endl;
530         return true;
531     }
532
533     CrawlHashTable &props = deck.props;
534
535     if (!props.exists("cards")
536         || props["cards"].get_type() != SV_VEC
537         || props["cards"].get_vector().get_type() != SV_BYTE
538         || cards_in_deck(deck) == 0)
539     {
540         crawl_state.zero_turns_taken();
541
542         if (!props.exists("cards"))
543             strm << "Seems this deck never had any cards in the first place!";
544         else if (props["cards"].get_type() != SV_VEC)
545             strm << "'cards' property isn't a vector.";
546         else
547         {
548             if (props["cards"].get_vector().get_type() != SV_BYTE)
549                 strm << "'cards' vector doesn't contain bytes.";
550
551             if (cards_in_deck(deck) == 0)
552             {
553                 strm << "Strange, this deck is already empty.";
554
555                 int cards_left = 0;
556                 if (deck.plus2 >= 0)
557                     cards_left = deck.plus - deck.plus2;
558                 else
559                     cards_left = -deck.plus;
560
561                 if (cards_left != 0)
562                 {
563                     strm << " But there should have been " <<  cards_left
564                          << " cards left.";
565                 }
566             }
567         }
568         strm << endl
569              << "A swarm of software bugs snatches the deck from you "
570                 "and whisks it away." << endl;
571
572         if (deck.link == you.equip[EQ_WEAPON])
573             unwield_item();
574
575         dec_inv_item_quantity(deck.link, 1);
576         did_god_conduct(DID_CARDS, 1);
577
578         return true;
579     }
580
581     bool problems = false;
582
583     CrawlVector &cards = props["cards"].get_vector();
584     CrawlVector &flags = props["card_flags"].get_vector();
585
586     vec_size num_cards = cards.size();
587     vec_size num_flags = flags.size();
588
589     unsigned int num_buggy     = 0;
590     unsigned int num_marked    = 0;
591
592     for (vec_size i = 0; i < num_cards; ++i)
593     {
594         uint8_t card   = cards[i].get_byte();
595         uint8_t _flags = flags[i].get_byte();
596
597         // Bad card, or "dealt" card not on the top.
598         if (card >= NUM_CARDS
599             || (_flags & CFLAG_DEALT) && i < num_cards - 1)
600         {
601             cards.erase(i);
602             flags.erase(i);
603             i--;
604             num_cards--;
605             num_buggy++;
606         }
607         else if (_flags & CFLAG_MARKED)
608             num_marked++;
609     }
610
611     if (num_buggy > 0)
612     {
613         strm << num_buggy << " buggy cards found in the deck, discarding them."
614              << endl;
615
616         deck.plus2 += num_buggy;
617
618         num_cards = cards.size();
619         num_flags = cards.size();
620
621         problems = true;
622     }
623
624     if (num_cards == 0)
625     {
626         crawl_state.zero_turns_taken();
627
628         strm << "Oops, all of the cards seem to be gone." << endl
629              << "A swarm of software bugs snatches the deck from you "
630                 "and whisks it away." << endl;
631
632         if (deck.link == you.equip[EQ_WEAPON])
633             unwield_item();
634
635         dec_inv_item_quantity(deck.link, 1);
636         did_god_conduct(DID_CARDS, 1);
637
638         return true;
639     }
640
641     if (num_cards > deck.plus)
642     {
643         if (deck.plus == 0)
644             strm << "Deck was created with zero cards???" << endl;
645         else if (deck.plus < 0)
646             strm << "Deck was created with *negative* cards?!" << endl;
647         else
648             strm << "Deck has more cards than it was created with?" << endl;
649
650         deck.plus = num_cards;
651         problems  = true;
652     }
653
654     if (num_cards > num_flags)
655     {
656 #ifdef WIZARD
657         strm << (num_cards - num_flags) << " more cards than flags.";
658 #else
659         strm << "More cards than flags.";
660 #endif
661         strm << endl;
662         for (unsigned int i = num_flags + 1; i <= num_cards; ++i)
663             flags[i] = static_cast<char>(0);
664
665         problems = true;
666     }
667     else if (num_flags > num_cards)
668     {
669 #ifdef WIZARD
670         strm << (num_cards - num_flags) << " more cards than flags.";
671 #else
672         strm << "More cards than flags.";
673 #endif
674         strm << endl;
675
676         for (unsigned int i = num_flags; i > num_cards; --i)
677             flags.erase(i);
678
679         problems = true;
680     }
681
682     if (props["num_marked"].get_byte() > static_cast<char>(num_cards))
683     {
684         strm << "More cards marked than in the deck?" << endl;
685         props["num_marked"] = static_cast<char>(num_marked);
686         problems = true;
687     }
688     else if (props["num_marked"].get_byte() != static_cast<char>(num_marked))
689     {
690 #ifdef WIZARD
691         strm << "Oops, counted " << static_cast<int>(num_marked)
692              << " marked cards, but num_marked is "
693              << (static_cast<int>(props["num_marked"].get_byte()));
694 #else
695         strm << "Oops, book-keeping on marked cards is wrong.";
696 #endif
697         strm << endl;
698
699         props["num_marked"] = static_cast<char>(num_marked);
700         problems = true;
701     }
702
703     if (deck.plus2 >= 0)
704     {
705         if (deck.plus != (deck.plus2 + num_cards))
706         {
707 #ifdef WIZARD
708             strm << "Have you used " << deck.plus2 << " cards, or "
709                  << (deck.plus - num_cards) << "? Oops.";
710 #else
711             strm << "Oops, book-keeping on used cards is wrong.";
712 #endif
713             strm << endl;
714             deck.plus2 = deck.plus - num_cards;
715             problems = true;
716         }
717     }
718     else
719     {
720         if (-deck.plus2 != num_cards)
721         {
722 #ifdef WIZARD
723             strm << "There are " << num_cards << " cards left, not "
724                  << (-deck.plus2) << ".  Oops.";
725 #else
726             strm << "Oops, book-keeping on cards left is wrong.";
727 #endif
728             strm << endl;
729             deck.plus2 = -num_cards;
730             problems = true;
731         }
732     }
733
734     if (!problems)
735         return false;
736
737     you.wield_change = true;
738
739     if (!yesno("Problems might not have been completely fixed; "
740                "still use deck?", true, 'n'))
741     {
742         crawl_state.zero_turns_taken();
743         return true;
744     }
745     return false;
746 }
747
748 // Choose a deck from inventory and return its slot (or -1).
749 static int _choose_inventory_deck(const char* prompt)
750 {
751     const int slot = prompt_invent_item(prompt,
752                                          MT_INVLIST, OSEL_DRAW_DECK,
753                                          true, true, true, 0, -1, NULL,
754                                          OPER_EVOKE);
755
756     if (prompt_failed(slot))
757         return -1;
758
759     if (!is_deck(you.inv[slot]))
760     {
761         mpr("That isn't a deck!");
762         return -1;
763     }
764
765     return slot;
766 }
767
768 // Select a deck from inventory and draw a card from it.
769 bool choose_deck_and_draw()
770 {
771     const int slot = _choose_inventory_deck("Draw from which deck?");
772
773     if (slot == -1)
774     {
775         crawl_state.zero_turns_taken();
776         return false;
777     }
778
779     evoke_deck(you.inv[slot]);
780     return true;
781 }
782
783 static void _deck_ident(item_def& deck)
784 {
785     if (in_inventory(deck) && !item_ident(deck, ISFLAG_KNOW_TYPE))
786     {
787         set_ident_flags(deck, ISFLAG_KNOW_TYPE);
788         mprf("This is %s.", deck.name(DESC_A).c_str());
789         you.wield_change = true;
790     }
791 }
792
793 // This also shuffles the deck.
794 static void _deck_lose_card(item_def& deck)
795 {
796     uint8_t flags = 0;
797     // Seen cards are only half as likely to fall out,
798     // marked cards only one-quarter as likely (note that marked
799     // cards are also seen.)
800     do
801     {
802         _shuffle_deck(deck);
803         get_card_and_flags(deck, -1, flags);
804     }
805     while ((flags & CFLAG_MARKED) && coinflip()
806             || (flags & CFLAG_SEEN) && coinflip());
807
808     _draw_top_card(deck, false, flags);
809     deck.plus2++;
810 }
811
812 // Peek at two cards in a deck, then shuffle them back in.
813 // Return false if the operation was failed/aborted along the way.
814 bool deck_peek()
815 {
816     const int slot = _choose_inventory_deck("Peek at which deck?");
817     if (slot == -1)
818     {
819         crawl_state.zero_turns_taken();
820         return false;
821     }
822     item_def& deck(you.inv[slot]);
823
824     if (_check_buggy_deck(deck))
825         return false;
826
827     if (cards_in_deck(deck) > 2)
828     {
829         _deck_lose_card(deck);
830         mpr("A card falls out of the deck.");
831     }
832
833     CrawlVector &cards     = deck.props["cards"].get_vector();
834     const int    num_cards = cards.size();
835
836     card_type card1, card2;
837     uint8_t flags1, flags2;
838
839     card1 = get_card_and_flags(deck, 0, flags1);
840
841     if (num_cards == 1)
842     {
843         mpr("There's only one card in the deck!");
844
845         _set_card_and_flags(deck, 0, card1, flags1 | CFLAG_SEEN | CFLAG_MARKED);
846         deck.props["num_marked"]++;
847         deck.plus2 = -1;
848         you.wield_change = true;
849
850         return true;
851     }
852
853     card2 = get_card_and_flags(deck, 1, flags2);
854
855     int already_seen = 0;
856     if (flags1 & CFLAG_SEEN)
857         already_seen++;
858     if (flags2 & CFLAG_SEEN)
859         already_seen++;
860
861     mprf("You draw two cards from the deck. They are: %s and %s.",
862          card_name(card1), card_name(card2));
863
864     _set_card_and_flags(deck, 0, card1, flags1 | CFLAG_SEEN);
865     _set_card_and_flags(deck, 1, card2, flags2 | CFLAG_SEEN);
866
867     mpr("You shuffle the cards back into the deck.");
868     _shuffle_deck(deck);
869
870     // Peeking identifies the deck.
871     _deck_ident(deck);
872
873     you.wield_change = true;
874     return true;
875 }
876
877 bool deck_identify_first(int slot)
878 {
879     item_def& deck(you.inv[slot]);
880     if (top_card_is_known(deck))
881         return false;
882
883     uint8_t flags;
884     card_type card = get_card_and_flags(deck, -1, flags);
885
886     _set_card_and_flags(deck, -1, card, flags | CFLAG_SEEN | CFLAG_MARKED);
887     deck.props["num_marked"]++;
888
889     mprf("You get a glimpse of the first card. It is %s.", card_name(card));
890     return true;
891
892 }
893
894 // Draw the top four cards of an unmarked deck and play them all.
895 // Discards the rest of the deck.  Return false if the operation was
896 // failed/aborted along the way.
897 bool deck_deal()
898 {
899     const int slot = _choose_inventory_deck("Deal from which deck?");
900     if (slot == -1)
901     {
902         crawl_state.zero_turns_taken();
903         return false;
904     }
905     item_def& deck(you.inv[slot]);
906     if (_check_buggy_deck(deck))
907         return false;
908
909     CrawlHashTable &props = deck.props;
910     if (props["num_marked"].get_byte() > 0)
911     {
912         mpr("You cannot deal from marked decks.");
913         crawl_state.zero_turns_taken();
914         return false;
915     }
916     if (props["stacked"].get_bool())
917     {
918         mpr("This deck seems insufficiently random for dealing.");
919         crawl_state.zero_turns_taken();
920         return false;
921     }
922
923     const int num_cards = cards_in_deck(deck);
924     _deck_ident(deck);
925
926     if (num_cards == 1)
927         mpr("There's only one card left!");
928     else if (num_cards < 4)
929         mprf("The deck only has %d cards.", num_cards);
930
931     const int num_to_deal = (num_cards < 4 ? num_cards : 4);
932
933     for (int i = 0; i < num_to_deal; ++i)
934     {
935         int last = cards_in_deck(deck) - 1;
936         uint8_t flags;
937
938         // Flag the card as dealt (changes messages and gives no piety).
939         card_type card = get_card_and_flags(deck, last, flags);
940         _set_card_and_flags(deck, last, card, flags | CFLAG_DEALT);
941
942         evoke_deck(deck);
943         redraw_screen();
944     }
945
946     // Nemelex doesn't like dealers with inadequate decks.
947     if (num_to_deal < 4)
948     {
949         mpr("Nemelex gives you another card to finish dealing.");
950         draw_from_deck_of_punishment(true);
951     }
952
953     // If the deck had cards left, exhaust it.
954     if (deck.quantity > 0)
955     {
956         canned_msg(MSG_DECK_EXHAUSTED);
957         if (slot == you.equip[EQ_WEAPON])
958             unwield_item();
959
960         dec_inv_item_quantity(slot, 1);
961     }
962
963     return true;
964 }
965
966 static void _redraw_stacked_cards(const vector<card_type>& draws,
967                                   unsigned int selected)
968 {
969     for (unsigned int i = 0; i < draws.size(); ++i)
970     {
971         cgotoxy(1, i+2);
972         textcolor(selected == i ? WHITE : LIGHTGREY);
973         cprintf("%u - %s", i+1, card_name(draws[i]));
974         clear_to_end_of_line();
975     }
976 }
977
978 static void _describe_cards(vector<card_type> cards)
979 {
980     ASSERT(!cards.empty());
981
982     ostringstream data;
983     for (unsigned int i = 0; i < cards.size(); ++i)
984     {
985         string name = card_name(cards[i]);
986         string desc = getLongDescription(name + " card");
987         if (desc.empty())
988             desc = "No description found.";
989
990         name = uppercase_first(name);
991         data << "<w>" << name << "</w>\n"
992              << get_linebreak_string(desc, get_number_of_cols() - 1)
993              << "\n";
994     }
995     formatted_string fs = formatted_string::parse_string(data.str());
996     clrscr();
997     fs.display();
998     getchm();
999     redraw_screen();
1000 }
1001
1002 // Stack a deck: look at the next five cards, put them back in any
1003 // order, discard the rest of the deck.
1004 // Return false if the operation was failed/aborted along the way.
1005 bool deck_stack()
1006 {
1007     const int slot = _choose_inventory_deck("Stack which deck?");
1008     if (slot == -1)
1009     {
1010         crawl_state.zero_turns_taken();
1011         return false;
1012     }
1013
1014     item_def& deck(you.inv[slot]);
1015     if (_check_buggy_deck(deck))
1016         return false;
1017
1018     CrawlHashTable &props = deck.props;
1019     if (props["num_marked"].get_byte() > 0)
1020     {
1021         mpr("You can't stack a marked deck.");
1022         crawl_state.zero_turns_taken();
1023         return false;
1024     }
1025
1026     _deck_ident(deck);
1027     const int num_cards    = cards_in_deck(deck);
1028
1029     if (num_cards == 1)
1030         mpr("There's only one card left!");
1031     else if (num_cards < 5)
1032         mprf("The deck only has %d cards.", num_cards);
1033     else if (num_cards == 5)
1034         mpr("The deck has exactly five cards.");
1035     else
1036     {
1037         mprf("You draw the first five cards out of %d and discard the rest.",
1038              num_cards);
1039     }
1040     more();
1041
1042     run_uncancel(UNC_STACK_FIVE, slot);
1043     return true;
1044 }
1045
1046 bool stack_five(int slot)
1047 {
1048     item_def& deck(you.inv[slot]);
1049     if (_check_buggy_deck(deck))
1050         return false;
1051
1052     const int num_cards    = cards_in_deck(deck);
1053     const int num_to_stack = (num_cards < 5 ? num_cards : 5);
1054
1055 #ifdef USE_TILE_WEB
1056     tiles_crt_control show_as_menu(CRT_MENU, "deck_stack");
1057 #endif
1058
1059     vector<card_type> draws;
1060     vector<uint8_t>   flags;
1061     for (int i = 0; i < num_cards; ++i)
1062     {
1063         uint8_t   _flags;
1064         card_type card = _draw_top_card(deck, false, _flags);
1065
1066         if (i < num_to_stack)
1067         {
1068             draws.push_back(card);
1069             flags.push_back(_flags | CFLAG_SEEN | CFLAG_MARKED);
1070         }
1071         // Rest of deck is discarded.
1072     }
1073
1074     CrawlHashTable &props = deck.props;
1075     deck.plus2 = -num_to_stack;
1076     props["num_marked"] = static_cast<char>(num_to_stack);
1077     // Remember that the deck was stacked even if it is later unmarked
1078     // (e.g. by Nemelex abandonment).
1079     props["stacked"] = true;
1080     you.wield_change = true;
1081     bool done = true;
1082
1083     if (draws.size() > 1)
1084     {
1085         bool need_prompt_redraw = true;
1086         unsigned int selected = draws.size();
1087         while (true)
1088         {
1089             if (need_prompt_redraw)
1090             {
1091                 clrscr();
1092                 cgotoxy(1,1);
1093                 textcolor(WHITE);
1094                 cprintf("Press a digit to select a card, then another digit "
1095                         "to swap it.");
1096                 cgotoxy(1,10);
1097                 cprintf("Press ? for the card descriptions, or Enter to "
1098                         "accept.");
1099
1100                 _redraw_stacked_cards(draws, selected);
1101                 need_prompt_redraw = false;
1102             }
1103
1104             // Hand-hacked implementation, instead of using Menu. Oh well.
1105             const int c = getchk();
1106             if (c == CK_ENTER)
1107             {
1108                 cgotoxy(1,11);
1109                 textcolor(LIGHTGREY);
1110                 cprintf("Are you done? (press y or Y to confirm)");
1111                 if (toupper(getchk()) == 'Y')
1112                     break;
1113
1114                 cgotoxy(1,11);
1115                 clear_to_end_of_line();
1116                 continue;
1117             }
1118
1119             if (c == '?')
1120             {
1121                 _describe_cards(draws);
1122                 need_prompt_redraw = true;
1123             }
1124             else if (c >= '1' && c <= '0' + static_cast<int>(draws.size()))
1125             {
1126                 const unsigned int new_selected = c - '1';
1127                 if (selected < draws.size())
1128                 {
1129                     swap(draws[selected], draws[new_selected]);
1130                     swap(flags[selected], flags[new_selected]);
1131                     selected = draws.size();
1132                 }
1133                 else
1134                     selected = new_selected;
1135
1136                 _redraw_stacked_cards(draws, selected);
1137             }
1138             else if (c == CK_ESCAPE && crawl_state.seen_hups)
1139             {
1140                 done = false;
1141                 break; // continue on game restore
1142             }
1143         }
1144         redraw_screen();
1145     }
1146     for (unsigned int i = 0; i < draws.size(); ++i)
1147     {
1148         _push_top_card(deck, draws[draws.size() - 1 - i],
1149                        flags[flags.size() - 1 - i]);
1150     }
1151
1152     _check_buggy_deck(deck);
1153     you.wield_change = true;
1154
1155     return done;
1156 }
1157
1158 // Draw the next three cards, discard two and pick one.
1159 bool deck_triple_draw()
1160 {
1161     const int slot = _choose_inventory_deck("Triple draw from which deck?");
1162     if (slot == -1)
1163     {
1164         crawl_state.zero_turns_taken();
1165         return false;
1166     }
1167
1168     run_uncancel(UNC_DRAW_THREE, slot);
1169     return true;
1170 }
1171
1172 bool draw_three(int slot)
1173 {
1174     item_def& deck(you.inv[slot]);
1175
1176     if (_check_buggy_deck(deck))
1177         return false;
1178
1179     const int num_cards = cards_in_deck(deck);
1180
1181     // We have to identify the deck before removing cards from it.
1182     // Otherwise, _remember_drawn_card() will implicitly call
1183     // _deck_ident() when the deck might have no cards left.
1184     _deck_ident(deck);
1185
1186     if (num_cards == 1)
1187     {
1188         // Only one card to draw, so just draw it.
1189         mpr("There's only one card left!");
1190         evoke_deck(deck);
1191         return true;
1192     }
1193
1194     const int num_to_draw = (num_cards < 3 ? num_cards : 3);
1195     vector<card_type> draws;
1196     vector<uint8_t>   flags;
1197
1198     for (int i = 0; i < num_to_draw; ++i)
1199     {
1200         uint8_t _flags;
1201         card_type card = _draw_top_card(deck, false, _flags);
1202
1203         draws.push_back(card);
1204         flags.push_back(_flags);
1205     }
1206
1207     int selected = -1;
1208     bool need_prompt_redraw = true;
1209     while (true)
1210     {
1211         if (need_prompt_redraw)
1212         {
1213             mpr("You draw... (choose one card, ? for their descriptions)");
1214             for (int i = 0; i < num_to_draw; ++i)
1215             {
1216                 msg::streams(MSGCH_PROMPT) << (static_cast<char>(i + 'a')) << " - "
1217                                            << card_name(draws[i]) << endl;
1218             }
1219             need_prompt_redraw = false;
1220         }
1221         const int keyin = toalower(get_ch());
1222
1223         if (crawl_state.seen_hups)
1224         {
1225             // Return the cards, for now.
1226             for (int i = 0; i < num_to_draw; ++i)
1227                 _push_top_card(deck, draws[i], flags[i]);
1228
1229             return false;
1230         }
1231
1232         if (keyin == '?')
1233         {
1234             _describe_cards(draws);
1235             need_prompt_redraw = true;
1236         }
1237         else if (keyin >= 'a' && keyin < 'a' + num_to_draw)
1238         {
1239             selected = keyin - 'a';
1240             break;
1241         }
1242         else
1243             canned_msg(MSG_HUH);
1244     }
1245
1246     // Note how many cards were removed from the deck.
1247     deck.plus2 += num_to_draw;
1248
1249     // Don't forget to update the number of marked ones, too.
1250     // But don't reduce the number of non-brownie draws.
1251     uint8_t num_marked_left = deck.props["num_marked"].get_byte();
1252     for (int i = 0; i < num_to_draw; ++i)
1253     {
1254         _remember_drawn_card(deck, draws[i], false);
1255         if (flags[i] & CFLAG_MARKED)
1256         {
1257             ASSERT(num_marked_left > 0);
1258             --num_marked_left;
1259         }
1260     }
1261     deck.props["num_marked"] = num_marked_left;
1262
1263     you.wield_change = true;
1264
1265     // Make deck disappear *before* the card effect, since we
1266     // don't want to unwield an empty deck.
1267     deck_rarity_type rarity = deck_rarity(deck);
1268     if (cards_in_deck(deck) == 0)
1269     {
1270         canned_msg(MSG_DECK_EXHAUSTED);
1271         if (slot == you.equip[EQ_WEAPON])
1272             unwield_item();
1273
1274         dec_inv_item_quantity(slot, 1);
1275     }
1276
1277     // Note that card_effect() might cause you to unwield the deck.
1278     card_effect(draws[selected], rarity,
1279                 flags[selected] | CFLAG_SEEN | CFLAG_MARKED, false);
1280
1281     return true;
1282 }
1283
1284 // This is Nemelex retribution.  If deal is true, use the word "deal"
1285 // rather than "draw" (for the Deal Four out-of-cards situation).
1286 void draw_from_deck_of_punishment(bool deal)
1287 {
1288     bool oddity;
1289     card_type card = _random_card(MISC_DECK_OF_PUNISHMENT, DECK_RARITY_COMMON,
1290                                   oddity);
1291
1292     mprf("You %s a card...", deal ? "deal" : "draw");
1293     card_effect(card, DECK_RARITY_COMMON, deal ? CFLAG_DEALT : 0);
1294 }
1295
1296 static int _xom_check_card(item_def &deck, card_type card,
1297                            uint8_t flags)
1298 {
1299     int amusement = 64;
1300
1301     if (!item_type_known(deck))
1302         amusement *= 2;
1303     // Expecting one type of card but got another, real funny.
1304     else if (flags & CFLAG_ODDITY)
1305         amusement = 200;
1306
1307     if (player_in_a_dangerous_place())
1308         amusement *= 2;
1309
1310     switch (card)
1311     {
1312     case CARD_XOM:
1313         // Handled elsewhere
1314         amusement = 0;
1315         break;
1316
1317     case CARD_DAMNATION:
1318         // Nothing happened, boring.
1319         if (player_in_branch(BRANCH_ABYSS))
1320             amusement = 0;
1321         break;
1322
1323     case CARD_MINEFIELD:
1324     case CARD_FAMINE:
1325     case CARD_CURSE:
1326     case CARD_SWINE:
1327         // Always hilarious.
1328         amusement = 255;
1329
1330     default:
1331         break;
1332     }
1333
1334     return amusement;
1335 }
1336
1337 void evoke_deck(item_def& deck)
1338 {
1339     if (_check_buggy_deck(deck))
1340         return;
1341
1342     int brownie_points = 0;
1343     bool allow_id = in_inventory(deck) && !item_ident(deck, ISFLAG_KNOW_TYPE);
1344
1345     const deck_rarity_type rarity = deck_rarity(deck);
1346     CrawlHashTable &props = deck.props;
1347
1348     uint8_t flags = 0;
1349     card_type card = _draw_top_card(deck, true, flags);
1350
1351     // Oddity cards don't give any information about the deck.
1352     if (flags & CFLAG_ODDITY)
1353         allow_id = false;
1354
1355     // Passive Nemelex retribution: sometimes a card gets swapped out.
1356     // More likely to happen with marked decks.
1357     if (player_under_penance(GOD_NEMELEX_XOBEH))
1358     {
1359         int c = 1;
1360         if ((flags & (CFLAG_MARKED | CFLAG_SEEN))
1361             || props["num_marked"].get_byte() > 0)
1362         {
1363             c = 3;
1364         }
1365
1366         if (x_chance_in_y(c * you.penance[GOD_NEMELEX_XOBEH], 3000))
1367         {
1368             card_type old_card = card;
1369             card = _choose_from_archetype(deck_of_punishment, rarity);
1370             if (card != old_card)
1371             {
1372                 simple_god_message(" seems to have exchanged this card "
1373                                    "behind your back!", GOD_NEMELEX_XOBEH);
1374                 mprf("It's actually %s.", card_name(card));
1375                 // You never completely appease Nemelex, but the effects
1376                 // get less frequent.
1377                 you.penance[GOD_NEMELEX_XOBEH] -=
1378                     random2((you.penance[GOD_NEMELEX_XOBEH]+18) / 10);
1379             }
1380         }
1381     }
1382
1383     const int amusement   = _xom_check_card(deck, card, flags);
1384
1385     // Do these before the deck item_def object is gone.
1386     if (flags & CFLAG_MARKED)
1387         props["num_marked"]--;
1388
1389     deck.plus2++;
1390     _remember_drawn_card(deck, card, allow_id);
1391
1392     // Get rid of the deck *before* the card effect because a card
1393     // might cause a wielded deck to be swapped out for something else,
1394     // in which case we don't want an empty deck to go through the
1395     // swapping process.
1396     const bool deck_gone = (cards_in_deck(deck) == 0);
1397     if (deck_gone)
1398     {
1399         canned_msg(MSG_DECK_EXHAUSTED);
1400         dec_inv_item_quantity(deck.link, 1);
1401         // Finishing the deck will earn a point, even if it
1402         // was marked or stacked.
1403         brownie_points++;
1404     }
1405
1406     card_effect(card, rarity, flags, false);
1407
1408     if (!(flags & CFLAG_MARKED))
1409     {
1410         // Could a Xom worshipper ever get a stacked deck in the first
1411         // place?
1412         xom_is_stimulated(amusement);
1413
1414         // Nemelex likes gamblers.
1415         brownie_points++;
1416         if (one_chance_in(3))
1417             brownie_points++;
1418
1419         // You can't ID off a marked card
1420         allow_id = false;
1421     }
1422
1423     if (!deck_gone && allow_id
1424         && you.skill(SK_EVOCATIONS) > 5 + random2(35))
1425     {
1426         mpr("Your skill with magical items lets you identify the deck.");
1427         set_ident_flags(deck, ISFLAG_KNOW_TYPE);
1428         msg::streams(MSGCH_EQUIPMENT) << deck.name(DESC_INVENTORY) << endl;
1429     }
1430
1431     // No piety from Deal Four.
1432     if (!(flags & CFLAG_DEALT))
1433         did_god_conduct(DID_CARDS, brownie_points);
1434
1435     // Always wield change, since the number of cards used/left has
1436     // changed.
1437     you.wield_change = true;
1438 }
1439
1440 static int _get_power_level(int power, deck_rarity_type rarity)
1441 {
1442     int power_level = 0;
1443     switch (rarity)
1444     {
1445     case DECK_RARITY_COMMON:
1446         break;
1447     case DECK_RARITY_LEGENDARY:
1448         if (x_chance_in_y(power, 500))
1449             ++power_level;
1450         // deliberate fall-through
1451     case DECK_RARITY_RARE:
1452         if (x_chance_in_y(power, 700))
1453             ++power_level;
1454         break;
1455     case DECK_RARITY_RANDOM:
1456         die("unset deck rarity");
1457     }
1458     dprf("Power level: %d", power_level);
1459     return power_level;
1460 }
1461
1462 // Actual card implementations follow.
1463 static void _portal_card(int power, deck_rarity_type rarity)
1464 {
1465     const int control_level = _get_power_level(power, rarity);
1466     bool controlled = false;
1467
1468     if (x_chance_in_y(control_level, 2))
1469         controlled = true;
1470
1471     int threshold = 9;
1472     const bool was_controlled = player_control_teleport();
1473     const bool short_control = (you.duration[DUR_CONTROL_TELEPORT] > 0
1474                                 && you.duration[DUR_CONTROL_TELEPORT]
1475                                                 < threshold * BASELINE_DELAY);
1476
1477     if (controlled && (!was_controlled || short_control))
1478         you.set_duration(DUR_CONTROL_TELEPORT, threshold); // Long enough to kick in.
1479
1480     if (x_chance_in_y(control_level, 2))
1481         random_blink(false);
1482
1483     you_teleport();
1484 }
1485
1486 static void _warp_card(int power, deck_rarity_type rarity)
1487 {
1488     if (you.no_tele(true, true, true))
1489     {
1490         canned_msg(MSG_STRANGE_STASIS);
1491         return;
1492     }
1493
1494     const int control_level = _get_power_level(power, rarity);
1495     if (control_level >= 2)
1496         blink(1000, false);
1497     else if (control_level == 1 && allow_control_teleport(true))
1498         cast_semi_controlled_blink(power / 4, false, false);
1499     else
1500         random_blink(false);
1501 }
1502
1503 static void _swap_monster_card(int power, deck_rarity_type rarity)
1504 {
1505     // Swap between you and another monster.
1506     // Don't choose yourself unless there are no monsters nearby.
1507     monster* mon_to_swap = choose_random_nearby_monster(0);
1508     if (!mon_to_swap)
1509         mpr("You spin around.");
1510     else
1511         swap_with_monster(mon_to_swap);
1512 }
1513
1514 static void _velocity_card(int power, deck_rarity_type rarity)
1515 {
1516     if (you_worship(GOD_CHEIBRIADOS))
1517         return simple_god_message(" protects you from inadvertent hurry.");
1518
1519     const int power_level = _get_power_level(power, rarity);
1520     if (power_level >= 2)
1521     {
1522         potion_effect(POT_SPEED, random2(power / 4));
1523         cast_swiftness(random2(power / 4));
1524     }
1525     else if (power_level == 1)
1526         potion_effect(POT_SPEED, random2(power / 4));
1527     else
1528         cast_swiftness(random2(power / 4));
1529 }
1530
1531 static void _damnation_card(int power, deck_rarity_type rarity)
1532 {
1533     if (player_in_branch(BRANCH_ABYSS))
1534     {
1535         canned_msg(MSG_NOTHING_HAPPENS);
1536         return;
1537     }
1538
1539     // Calculate how many extra banishments you get.
1540     const int power_level = _get_power_level(power, rarity);
1541     int nemelex_bonus = 0;
1542     if (you_worship(GOD_NEMELEX_XOBEH) && !player_under_penance())
1543         nemelex_bonus = you.piety;
1544
1545     int extra_targets = power_level + random2(you.skill(SK_EVOCATIONS, 20)
1546                                               + nemelex_bonus) / 240;
1547
1548     for (int i = 0; i < 1 + extra_targets; ++i)
1549     {
1550         // Pick a random monster nearby to banish (or yourself).
1551         monster* mon_to_banish = choose_random_nearby_monster(1);
1552
1553         // Bonus banishments only banish monsters.
1554         if (i != 0 && !mon_to_banish)
1555             continue;
1556
1557         if (!mon_to_banish) // Banish yourself!
1558         {
1559             banished("drawing a card");
1560             break;              // Don't banish anything else.
1561         }
1562         else
1563             mon_to_banish->banish(&you);
1564     }
1565
1566 }
1567
1568 static void _warpwright_card(int power, deck_rarity_type rarity)
1569 {
1570     const int power_level = _get_power_level(power, rarity);
1571
1572     if (player_in_branch(BRANCH_ABYSS))
1573     {
1574         mpr("The power of the Abyss blocks your magic.");
1575         return;
1576     }
1577
1578     int count = 0;
1579     coord_def f;
1580     for (adjacent_iterator ai(you.pos()); ai; ++ai)
1581         if (grd(*ai) == DNGN_FLOOR && !find_trap(*ai) && one_chance_in(++count))
1582             f = *ai;
1583
1584     if (count > 0)              // found a spot
1585     {
1586         if (place_specific_trap(f, TRAP_TELEPORT, 1 + random2(5 * power_level)))
1587         {
1588             // Mark it discovered if enough power.
1589             if (x_chance_in_y(power_level, 2))
1590                 find_trap(f)->reveal();
1591         }
1592     }
1593 }
1594
1595 static void _flight_card(int power, deck_rarity_type rarity)
1596 {
1597     const int power_level = _get_power_level(power, rarity);
1598
1599     // Assume something _will_ happen.
1600     bool success = true;
1601
1602     if (power_level == 0)
1603     {
1604         if (!transform(random2(power/4), coinflip() ? TRAN_SPIDER : TRAN_BAT,
1605                        true))
1606         {
1607             // Oops, something went wrong here (either because of cursed
1608             // equipment or the possibility of stat loss).
1609             success = false;
1610         }
1611     }
1612     else if (power_level >= 1)
1613     {
1614         cast_fly(random2(power/4));
1615         if (!you_worship(GOD_CHEIBRIADOS))
1616             cast_swiftness(random2(power/4));
1617         else
1618             simple_god_message(" protects you from inadvertent hurry.");
1619     }
1620
1621     if (power_level == 2) // Stacks with the above.
1622     {
1623         if (is_valid_shaft_level() && grd(you.pos()) == DNGN_FLOOR)
1624         {
1625             if (place_specific_trap(you.pos(), TRAP_SHAFT))
1626             {
1627                 find_trap(you.pos())->reveal();
1628                 mpr("A shaft materialises beneath you!");
1629             }
1630         }
1631     }
1632     if (one_chance_in(4 - power_level))
1633         potion_effect(POT_INVISIBILITY, random2(power)/4);
1634     else if (!success)
1635         canned_msg(MSG_NOTHING_HAPPENS);
1636 }
1637
1638 static void _minefield_card(int power, deck_rarity_type rarity)
1639 {
1640     const int power_level = _get_power_level(power, rarity);
1641     const int radius = power_level * 2 + 2;
1642     for (radius_iterator ri(you.pos(), radius, false, false, false); ri; ++ri)
1643     {
1644         if (*ri == you.pos())
1645             continue;
1646
1647         if (grd(*ri) == DNGN_FLOOR && !find_trap(*ri)
1648             && one_chance_in(4 - power_level))
1649         {
1650             if (player_in_branch(BRANCH_ABYSS))
1651                 grd(*ri) = coinflip() ? DNGN_DEEP_WATER : DNGN_LAVA;
1652             else
1653                 place_specific_trap(*ri, TRAP_RANDOM);
1654         }
1655     }
1656 }
1657
1658 static int stair_draw_count = 0;
1659
1660 // This does not describe an actual card. Instead, it only exists to test
1661 // the stair movement effect in wizard mode ("&c stairs").
1662 static void _stairs_card(int power, deck_rarity_type rarity)
1663 {
1664     UNUSED(power);
1665     UNUSED(rarity);
1666
1667     you.duration[DUR_REPEL_STAIRS_MOVE]  = 0;
1668     you.duration[DUR_REPEL_STAIRS_CLIMB] = 0;
1669
1670     if (feat_stair_direction(grd(you.pos())) == CMD_NO_CMD)
1671         you.duration[DUR_REPEL_STAIRS_MOVE]  = 1000;
1672     else
1673         you.duration[DUR_REPEL_STAIRS_CLIMB] =  500; // more annoying
1674
1675     vector<coord_def> stairs_avail;
1676
1677     for (radius_iterator ri(you.pos(), LOS_RADIUS, false, true, true); ri; ++ri)
1678     {
1679         dungeon_feature_type feat = grd(*ri);
1680         if (feat_stair_direction(feat) != CMD_NO_CMD
1681             && feat != DNGN_ENTER_SHOP)
1682         {
1683             stairs_avail.push_back(*ri);
1684         }
1685     }
1686
1687     if (stairs_avail.empty())
1688     {
1689         mpr("No stairs available to move.");
1690         return;
1691     }
1692
1693     shuffle_array(stairs_avail);
1694
1695     for (unsigned int i = 0; i < stairs_avail.size(); ++i)
1696         move_stair(stairs_avail[i], stair_draw_count % 2, false);
1697
1698     stair_draw_count++;
1699 }
1700
1701 static void _damaging_card(card_type card, int power, deck_rarity_type rarity,
1702                            bool dealt = false)
1703 {
1704     const int power_level = _get_power_level(power, rarity);
1705     const char *participle = dealt ? "dealt" : "drawn";
1706
1707     dist target;
1708     zap_type ztype = ZAP_DEBUGGING_RAY;
1709     const zap_type firezaps[3]   = { ZAP_THROW_FLAME, ZAP_STICKY_FLAME, ZAP_BOLT_OF_FIRE };
1710     const zap_type frostzaps[3]  = { ZAP_THROW_FROST, ZAP_THROW_ICICLE, ZAP_BOLT_OF_COLD };
1711     const zap_type hammerzaps[3] = { ZAP_STONE_ARROW, ZAP_IRON_SHOT,
1712                                      ZAP_LEHUDIBS_CRYSTAL_SPEAR };
1713     const zap_type venomzaps[3]  = { ZAP_STING, ZAP_VENOM_BOLT,
1714                                      ZAP_POISON_ARROW };
1715     const zap_type sparkzaps[3]  = { ZAP_SHOCK, ZAP_LIGHTNING_BOLT,
1716                                      ZAP_ORB_OF_ELECTRICITY };
1717     const zap_type painzaps[2]   = { ZAP_AGONY, ZAP_BOLT_OF_DRAINING };
1718     const zap_type orbzaps[3]    = { ZAP_ISKENDERUNS_MYSTIC_BLAST, ZAP_IOOD, ZAP_IOOD };
1719
1720     switch (card)
1721     {
1722     case CARD_VITRIOL:
1723         ztype = ZAP_BREATHE_ACID;
1724         break;
1725
1726     case CARD_FLAME:
1727         ztype = (coinflip() ? ZAP_FIREBALL : firezaps[power_level]);
1728         break;
1729
1730     case CARD_FROST:  ztype = frostzaps[power_level];  break;
1731     case CARD_HAMMER: ztype = hammerzaps[power_level]; break;
1732     case CARD_VENOM:  ztype = venomzaps[power_level];  break;
1733     case CARD_SPARK:  ztype = sparkzaps[power_level];  break;
1734     case CARD_ORB:    ztype = orbzaps[power_level];    break;
1735
1736     case CARD_PAIN:
1737         if (power_level == 2)
1738         {
1739             mprf("You have %s %s.", participle, card_name(card));
1740             torment(&you, TORMENT_CARDS, you.pos());
1741             return;
1742         }
1743         else
1744             ztype = painzaps[power_level];
1745         break;
1746
1747     default:
1748         break;
1749     }
1750
1751     string prompt = "You have ";
1752     prompt += participle;
1753     prompt += " ";
1754     prompt += card_name(card);
1755     prompt += ".";
1756
1757     bolt beam;
1758     beam.range = LOS_RADIUS;
1759     if (spell_direction(target, beam, DIR_NONE, TARG_HOSTILE,
1760                         LOS_RADIUS, true, true, false, NULL, prompt.c_str())
1761         && player_tracer(ZAP_DEBUGGING_RAY, power/6, beam))
1762     {
1763         if (ztype == ZAP_IOOD)
1764         {
1765             if (power_level == 1)
1766                 cast_iood(&you, power/6, &beam);
1767             else
1768                 cast_iood_burst(power/6, beam.target);
1769         }
1770         else
1771             zapping(ztype, power/6, beam);
1772     }
1773     else if (ztype == ZAP_IOOD && power_level == 2)
1774     {
1775         // cancelled orb bursts just become uncontrolled
1776         cast_iood_burst(power/6, coord_def(-1, -1));
1777     }
1778 }
1779
1780 static void _elixir_card(int power, deck_rarity_type rarity)
1781 {
1782     int power_level = _get_power_level(power, rarity);
1783
1784     you.duration[DUR_ELIXIR_HEALTH] = 0;
1785     you.duration[DUR_ELIXIR_MAGIC] = 0;
1786
1787     if (power_level == 0)
1788     {
1789         if (coinflip())
1790             you.set_duration(DUR_ELIXIR_HEALTH, 1 + random2(3));
1791         else
1792             you.set_duration(DUR_ELIXIR_MAGIC, 3 + random2(5));
1793     }
1794     else if (power_level == 1)
1795     {
1796         if (you.hp * 2 < you.hp_max)
1797             you.set_duration(DUR_ELIXIR_HEALTH, 3 + random2(3));
1798         else
1799             you.set_duration(DUR_ELIXIR_MAGIC, 10);
1800     }
1801     else if (power_level >= 2)
1802     {
1803         you.set_duration(DUR_ELIXIR_HEALTH, 10);
1804         you.set_duration(DUR_ELIXIR_MAGIC, 10);
1805     }
1806 }
1807
1808 static void _battle_lust_card(int power, deck_rarity_type rarity)
1809 {
1810     const int power_level = _get_power_level(power, rarity);
1811     if (power_level >= 2)
1812     {
1813         you.set_duration(DUR_SLAYING, random2(power/6) + 1,
1814                          0, "You feel deadly.");
1815     }
1816     else if (power_level == 1)
1817     {
1818         you.set_duration(DUR_BUILDING_RAGE, 2,
1819                          0, "You feel your rage building.");
1820     }
1821     else if (power_level == 0)
1822         potion_effect(POT_MIGHT, random2(power/4));
1823 }
1824
1825 static void _metamorphosis_card(int power, deck_rarity_type rarity)
1826 {
1827     const int power_level = _get_power_level(power, rarity);
1828     transformation_type trans;
1829
1830     if (power_level >= 2)
1831         trans = coinflip() ? TRAN_DRAGON : TRAN_LICH;
1832     else if (power_level == 1)
1833         trans = coinflip() ? TRAN_STATUE : TRAN_BLADE_HANDS;
1834     else
1835     {
1836         trans = one_chance_in(3) ? TRAN_SPIDER :
1837                 coinflip()       ? TRAN_ICE_BEAST
1838                                  : TRAN_BAT;
1839     }
1840
1841     // Might fail, e.g. because of cursed equipment or potential death by
1842     // stat loss. Aren't we being nice? (jpeg)
1843     if (!transform(random2(power/4), trans, true))
1844         canned_msg(MSG_NOTHING_HAPPENS);
1845 }
1846
1847 static void _helm_card(int power, deck_rarity_type rarity)
1848 {
1849     const int power_level = _get_power_level(power, rarity);
1850     bool do_phaseshift = false;
1851     bool do_stoneskin  = false;
1852     bool do_shield     = false;
1853     bool do_resistance = false;
1854
1855     // Chances are cumulative.
1856     if (power_level >= 2)
1857     {
1858         if (coinflip()) do_phaseshift = true;
1859         if (coinflip()) do_stoneskin  = true;
1860         if (coinflip()) do_shield     = true;
1861         do_resistance = true;
1862     }
1863     if (power_level >= 1)
1864     {
1865         if (coinflip()) do_phaseshift = true;
1866         if (coinflip()) do_stoneskin  = true;
1867         if (coinflip()) do_shield     = true;
1868     }
1869     if (power_level >= 0)
1870     {
1871         if (coinflip())
1872             do_phaseshift = true;
1873         else
1874             do_stoneskin  = true;
1875     }
1876
1877     if (do_phaseshift)
1878         cast_phase_shift(random2(power/4));
1879     if (do_stoneskin)
1880         cast_stoneskin(random2(power/4));
1881     if (do_resistance)
1882     {
1883         mpr("You feel resistant.");
1884         you.increase_duration(DUR_RESISTANCE, random2(power/7) + 1);
1885     }
1886     if (do_shield)
1887     {
1888         if (you.duration[DUR_MAGIC_SHIELD] == 0)
1889             mpr("A magical shield forms in front of you.");
1890         you.increase_duration(DUR_MAGIC_SHIELD, random2(power/6) + 1);
1891     }
1892 }
1893
1894 static void _blade_card(int power, deck_rarity_type rarity)
1895 {
1896     if (you.species == SP_FELID)
1897     {
1898         mpr("You feel like a smilodon for a moment.");
1899         return;
1900     }
1901
1902     // Pause before jumping to the list.
1903     if (Options.auto_list)
1904         more();
1905
1906     // Don't take less time if we're swapping weapons.
1907     int old_time = you.time_taken;
1908     wield_weapon(false);
1909     you.time_taken = old_time;
1910
1911     const int power_level = _get_power_level(power, rarity);
1912     brand_type brand;
1913
1914     if (power_level >= 2)
1915     {
1916         cast_tukimas_dance(random2(power/4));
1917         return;
1918     }
1919     else if (power_level == 1)
1920     {
1921         brand_type brands[] = {SPWPN_DISTORTION, SPWPN_PAIN,
1922             SPWPN_ANTIMAGIC, SPWPN_CHAOS, SPWPN_ELECTROCUTION};
1923         brand = RANDOM_ELEMENT(brands);
1924     }
1925     else
1926     {
1927         brand_type brands[] = {SPWPN_FLAMING, SPWPN_FREEZING, SPWPN_VENOM,
1928             SPWPN_DRAINING, SPWPN_VORPAL};
1929         brand = RANDOM_ELEMENT(brands);
1930     }
1931
1932     if (!brand_weapon(brand, random2(power/4)))
1933     {
1934         item_def* wpn = you.weapon();
1935
1936         if (wpn)
1937         {
1938             mprf("%s vibrate%s crazily for a second.",
1939                  wpn->name(DESC_YOUR).c_str(),
1940                  wpn->quantity == 1 ? "s" : "");
1941         }
1942         else
1943             mprf("Your %s twitch.", you.hand_name(true).c_str());
1944     }
1945 }
1946
1947 static void _shadow_card(int power, deck_rarity_type rarity)
1948 {
1949     const int power_level = _get_power_level(power, rarity);
1950
1951     if (power_level >= 1)
1952     {
1953         mpr(you.duration[DUR_STEALTH] ? "You feel more catlike."
1954                                       : "You feel stealthy.");
1955         you.increase_duration(DUR_STEALTH, random2(power/4) + 1);
1956     }
1957
1958     potion_effect(POT_INVISIBILITY, random2(power/4));
1959 }
1960
1961 static void _potion_card(int power, deck_rarity_type rarity)
1962 {
1963     const int power_level = _get_power_level(power, rarity);
1964     potion_type pot_effects[] =
1965     {
1966         POT_AGILITY, POT_AGILITY, POT_BRILLIANCE,
1967         POT_BRILLIANCE, POT_MIGHT, POT_MIGHT,
1968         POT_CURING, POT_CURING, POT_CONFUSION,
1969         POT_SLOWING, POT_PARALYSIS
1970     };
1971
1972     potion_type pot = RANDOM_ELEMENT(pot_effects);
1973
1974     if (power_level >= 1 && coinflip())
1975         pot = (coinflip() ? POT_MAGIC : POT_INVISIBILITY);
1976
1977     if (power_level >= 2 && coinflip())
1978         pot = (coinflip() ? POT_SPEED : POT_RESISTANCE);
1979
1980     if (you_worship(GOD_CHEIBRIADOS) && pot == POT_SPEED)
1981     {
1982         simple_god_message(" protects you from inadvertent hurry.");
1983         return;
1984     }
1985
1986     potion_effect(pot, random2(power/4));
1987 }
1988
1989 static string _god_wrath_stat_check(string cause_orig)
1990 {
1991     string cause = cause_orig;
1992
1993     if (crawl_state.is_god_acting())
1994     {
1995         god_type which_god = crawl_state.which_god_acting();
1996         if (crawl_state.is_god_retribution())
1997             cause = "the wrath of " + god_name(which_god);
1998         else if (which_god == GOD_XOM)
1999             cause = "the capriciousness of Xom";
2000         else
2001             cause = "the 'helpfulness' of " + god_name(which_god);
2002     }
2003
2004     return cause;
2005 }
2006
2007 static void _focus_card(int power, deck_rarity_type rarity)
2008 {
2009     stat_type best_stat = STAT_STR;
2010     stat_type worst_stat = STAT_STR;
2011
2012     for (int i = 1; i < 3; ++i)
2013     {
2014         stat_type s = static_cast<stat_type>(i);
2015         const int best_diff = you.base_stats[s] - you.base_stats[best_stat];
2016         if (best_diff > 0 || best_diff == 0 && coinflip())
2017             best_stat = s;
2018
2019         const int worst_diff = you.base_stats[s] - you.base_stats[worst_stat];
2020         if (worst_diff < 0 || worst_diff == 0 && coinflip())
2021             worst_stat = s;
2022     }
2023
2024     while (best_stat == worst_stat)
2025     {
2026         best_stat  = static_cast<stat_type>(random2(3));
2027         worst_stat = static_cast<stat_type>(random2(3));
2028     }
2029
2030     const string cause = _god_wrath_stat_check("the Focus card");
2031
2032     modify_stat(best_stat, 1, true, cause.c_str(), true);
2033     modify_stat(worst_stat, -1, true, cause.c_str(), true);
2034 }
2035
2036 static void _shuffle_card(int power, deck_rarity_type rarity)
2037 {
2038     int perm[] = { 0, 1, 2 };
2039     COMPILE_CHECK(ARRAYSZ(perm) == NUM_STATS);
2040     shuffle_array(perm, NUM_STATS);
2041
2042     FixedVector<int8_t, NUM_STATS> new_base;
2043     for (int i = 0; i < NUM_STATS; ++i)
2044         new_base[perm[i]]  = you.base_stats[i];
2045
2046     const string cause = _god_wrath_stat_check("the Shuffle card");
2047
2048     for (int i = 0; i < NUM_STATS; ++i)
2049     {
2050         modify_stat(static_cast<stat_type>(i),
2051                     new_base[i] - you.base_stats[i],
2052                     true, cause.c_str(), true);
2053     }
2054
2055     char buf[128];
2056     snprintf(buf, sizeof(buf),
2057              "Shuffle card: Str %d[%d], Int %d[%d], Dex %d[%d]",
2058              you.base_stats[STAT_STR], you.strength(false),
2059              you.base_stats[STAT_INT], you.intel(false),
2060              you.base_stats[STAT_DEX], you.dex(false));
2061     take_note(Note(NOTE_MESSAGE, 0, 0, buf));
2062 }
2063
2064 static void _experience_card(int power, deck_rarity_type rarity)
2065 {
2066     const int power_level = _get_power_level(power, rarity);
2067
2068     if (you.experience_level < 27)
2069         mpr("You feel more experienced.");
2070     else
2071         mpr("You feel knowledgeable.");
2072
2073     more();
2074     skill_menu(SKMF_EXPERIENCE_CARD, min(200 + power * 50, HIGH_EXP_POOL));
2075
2076     // After level 27, boosts you get don't get increased (matters for
2077     // charging V:$ with no rN+++ and for felids).
2078     const int xp_cap = exp_needed(1 + you.experience_level)
2079                      - exp_needed(you.experience_level);
2080
2081     // power_level 2 means automatic level gain.
2082     if (power_level == 2 && you.experience_level < 27)
2083         adjust_level(1);
2084     else
2085     {
2086         // Likely to give a level gain (power of ~500 is reasonable
2087         // at high levels even for non-Nemelexites, so 50,000 XP.)
2088         // But not guaranteed.
2089         // Overrides archmagi effect, like potions of experience.
2090         you.experience += min(xp_cap, power * 100);
2091         level_change();
2092     }
2093 }
2094
2095 static void _remove_bad_mutation()
2096 {
2097     // Ensure that only bad mutations are removed.
2098     if (!delete_mutation(RANDOM_BAD_MUTATION, "helix card", false, false, false, true))
2099         mpr("You feel transcendent for a moment.");
2100 }
2101
2102 static void _helix_card(int power, deck_rarity_type rarity)
2103 {
2104     const int power_level = _get_power_level(power, rarity);
2105
2106     if (power_level == 0)
2107     {
2108         switch (how_mutated() ? random2(3) : 0)
2109         {
2110         case 0:
2111             mutate(RANDOM_MUTATION, "helix card");
2112             break;
2113         case 1:
2114             delete_mutation(RANDOM_MUTATION, "helix card");
2115             mutate(RANDOM_MUTATION, "helix card");
2116             break;
2117         case 2:
2118             delete_mutation(RANDOM_MUTATION, "helix card");
2119             break;
2120         }
2121     }
2122     else if (power_level == 1)
2123     {
2124         switch (how_mutated() ? random2(3) : 0)
2125         {
2126         case 0:
2127             mutate(coinflip() ? RANDOM_GOOD_MUTATION : RANDOM_MUTATION,
2128                    "helix card");
2129             break;
2130         case 1:
2131             if (coinflip())
2132                 _remove_bad_mutation();
2133             else
2134                 delete_mutation(RANDOM_MUTATION, "helix card");
2135             break;
2136         case 2:
2137             if (coinflip())
2138             {
2139                 if (coinflip())
2140                 {
2141                     _remove_bad_mutation();
2142                     mutate(RANDOM_MUTATION, "helix card");
2143                 }
2144                 else
2145                 {
2146                     delete_mutation(RANDOM_MUTATION, "helix card");
2147                     mutate(RANDOM_GOOD_MUTATION, "helix card");
2148                 }
2149             }
2150             else
2151             {
2152                 delete_mutation(RANDOM_MUTATION, "helix card");
2153                 mutate(RANDOM_MUTATION, "helix card");
2154             }
2155             break;
2156         }
2157     }
2158     else
2159     {
2160         switch (random2(3))
2161         {
2162         case 0:
2163             _remove_bad_mutation();
2164             break;
2165         case 1:
2166             mutate(RANDOM_GOOD_MUTATION, "helix card");
2167             break;
2168         case 2:
2169             if (coinflip())
2170             {
2171                 // If you get unlucky, you could get here with no bad
2172                 // mutations and simply get a mutation effect. Oh well.
2173                 _remove_bad_mutation();
2174                 mutate(RANDOM_MUTATION, "helix card");
2175             }
2176             else
2177             {
2178                 delete_mutation(RANDOM_MUTATION, "helix card");
2179                 mutate(RANDOM_GOOD_MUTATION, "helix card");
2180             }
2181             break;
2182         }
2183     }
2184 }
2185
2186 void sage_card(int power, deck_rarity_type rarity)
2187 {
2188     const int power_level = _get_power_level(power, rarity);
2189     int c;                      // how much to weight your skills
2190     if (power_level == 0)
2191         c = 0;
2192     else if (power_level == 1)
2193         c = random2(10) + 1;
2194     else
2195         c = 10;
2196
2197     // FIXME: yet another reproduction of random_choose_weighted
2198     // Ah for Python:
2199     // skill = random_choice([x*(40-x)*c/10 for x in skill_levels])
2200     int totalweight = 0;
2201     skill_type result = SK_NONE;
2202     for (int i = SK_FIRST_SKILL; i < NUM_SKILLS; ++i)
2203     {
2204         skill_type s = static_cast<skill_type>(i);
2205         if (skill_name(s) == NULL || is_useless_skill(s))
2206             continue;
2207
2208         if (you.skills[s] < MAX_SKILL_LEVEL)
2209         {
2210             // Choosing a skill is likelier if you are somewhat skilled in it.
2211             const int curweight = 1 + you.skills[s] * (40 - you.skills[s]) * c;
2212             totalweight += curweight;
2213             if (x_chance_in_y(curweight, totalweight))
2214                 result = s;
2215         }
2216     }
2217
2218     if (result == SK_NONE)
2219         mpr("You feel omnipotent.");  // All skills maxed.
2220     else
2221     {
2222         int xp = exp_needed(min<int>(you.max_level, 27) + 1)
2223                - exp_needed(min<int>(you.max_level, 27));
2224         xp = xp / 10 + random2(xp / 4);
2225
2226         // There may be concurrent sages for the same skill, with different
2227         // bonus multipliers.
2228         you.sage_skills.push_back(result);
2229         you.sage_xp.push_back(xp);
2230         you.sage_bonus.push_back(power / 25);
2231         mprf(MSGCH_PLAIN, "You feel studious about %s.", skill_name(result));
2232         dprf("Will redirect %d xp, bonus = %d%%\n", xp, (power / 25) * 2);
2233     }
2234 }
2235
2236 void create_pond(const coord_def& center, int radius, bool allow_deep)
2237 {
2238     for (radius_iterator ri(center, radius, false); ri; ++ri)
2239     {
2240         const coord_def p = *ri;
2241         if (p != you.pos() && coinflip())
2242         {
2243             if (grd(p) == DNGN_FLOOR)
2244             {
2245                 dungeon_feature_type feat;
2246
2247                 if (allow_deep && coinflip())
2248                     feat = DNGN_DEEP_WATER;
2249                 else
2250                     feat = DNGN_SHALLOW_WATER;
2251
2252                 dungeon_terrain_changed(p, feat);
2253             }
2254         }
2255     }
2256 }
2257
2258 static void _deepen_water(const coord_def& center, int radius)
2259 {
2260     for (radius_iterator ri(center, radius, false); ri; ++ri)
2261     {
2262         // FIXME: The iteration shouldn't affect the later squares in the
2263         // same iteration, i.e., a newly-flooded square shouldn't count
2264         // in the decision as to whether to make the next square flooded.
2265         const coord_def p = *ri;
2266         if (grd(p) == DNGN_SHALLOW_WATER
2267             && p != you.pos()
2268             && x_chance_in_y(1+count_neighbours(p, DNGN_DEEP_WATER), 8))
2269         {
2270             dungeon_terrain_changed(p, DNGN_DEEP_WATER);
2271         }
2272         if (grd(p) == DNGN_FLOOR
2273             && random2(3) < random2(count_neighbours(p, DNGN_DEEP_WATER)
2274                                     + count_neighbours(p, DNGN_SHALLOW_WATER)))
2275         {
2276             dungeon_terrain_changed(p, DNGN_SHALLOW_WATER);
2277         }
2278     }
2279 }
2280
2281 static void _water_card(int power, deck_rarity_type rarity)
2282 {
2283     const int power_level = _get_power_level(power, rarity);
2284     if (power_level == 0)
2285     {
2286         mpr("You create a pond!");
2287         create_pond(you.pos(), 4, false);
2288     }
2289     else if (power_level == 1)
2290     {
2291         mpr("You feel the tide rushing in!");
2292         create_pond(you.pos(), 6, true);
2293         for (int i = 0; i < 2; ++i)
2294             _deepen_water(you.pos(), 6);
2295     }
2296     else
2297     {
2298         mpr("Water floods your area!");
2299
2300         // Flood all visible squares.
2301         vector<coord_def> vis;
2302         for (radius_iterator ri(you.pos(), LOS_RADIUS, false); ri; ++ri)
2303             vis.push_back(*ri);
2304
2305         // Killing a monster can trigger events that change visibility,
2306         // so we need to pre-fetch the list of what's visible.
2307         for (vector<coord_def>::const_iterator ri = vis.begin();
2308              ri != vis.end(); ++ri)
2309         {
2310             coord_def p = *ri;
2311             destroy_trap(p);
2312             if (grd(p) == DNGN_FLOOR || grd(p) == DNGN_SHALLOW_WATER)
2313             {
2314                 dungeon_feature_type new_feature = DNGN_SHALLOW_WATER;
2315                 if (p != you.pos() && coinflip())
2316                     new_feature = DNGN_DEEP_WATER;
2317                 dungeon_terrain_changed(p, new_feature);
2318             }
2319         }
2320     }
2321 }
2322
2323 static void _glass_card(int power, deck_rarity_type rarity)
2324 {
2325     const int power_level = _get_power_level(power, rarity);
2326     const int radius = (power_level == 2) ? 1000
2327                                           : random2(power/40) + 2;
2328     vitrify_area(radius);
2329 }
2330
2331 static void _dowsing_card(int power, deck_rarity_type rarity)
2332 {
2333     const int power_level = _get_power_level(power, rarity);
2334     bool things_to_do[3] = { false, false, false };
2335     things_to_do[random2(3)] = true;
2336
2337     if (power_level == 1)
2338         things_to_do[random2(3)] = true;
2339
2340     if (power_level >= 2)
2341     {
2342         for (int i = 0; i < 3; ++i)
2343             things_to_do[i] = true;
2344     }
2345
2346     if (things_to_do[0])
2347         magic_mapping(random2(power/8) + 18, random2(power), false);
2348     if (things_to_do[1])
2349     {
2350         if (detect_traps(random2(power/4)))
2351             mpr("You sense traps nearby.");
2352         if (detect_items(random2(power/4)))
2353             mpr("You sense items nearby.");
2354     }
2355     if (things_to_do[2])
2356     {
2357         you.set_duration(DUR_TELEPATHY, random2(power/4), 0,
2358                          "You feel telepathic!");
2359         detect_creatures(1 + you.duration[DUR_TELEPATHY] / 2 / BASELINE_DELAY,
2360                          true);
2361     }
2362 }
2363
2364 static void _create_altar(coord_def pos)
2365 {
2366     god_type god = random_god();
2367
2368     grd(pos) = altar_for_god(god);
2369     ASSERT(grd(pos) != DNGN_FLOOR);
2370     mprf("An altar to %s grows from the floor before you!",
2371          god_name(god).c_str());
2372 }
2373
2374 static void _trowel_card(int power, deck_rarity_type rarity)
2375 {
2376     coord_def p;
2377     for (distance_iterator di(you.pos(), true, false); di; ++di)
2378     {
2379         if (cell_is_solid(*di) || is_critical_feature(grd(*di)))
2380             continue;
2381         p = *di;
2382         break;
2383     }
2384
2385     if (p.origin()) // can't happen outside wizmode
2386         return mpr("The dungeon trembles momentarily.");
2387
2388     const int power_level = _get_power_level(power, rarity);
2389     bool done_stuff = false;
2390
2391     if (power_level >= 2 && crawl_state.game_standard_levelgen())
2392     {
2393         // Vetoes are done too late, should not pass random_map_for_tag()
2394         // at all.  Thus, allow retries.
2395         int tries;
2396         for (tries = 100; tries > 0; tries--)
2397         {
2398             // Generate a portal to something.
2399             const map_def *map = random_map_for_tag("trowel_portal", true, true);
2400
2401             if (!map)
2402                 break;
2403
2404             {
2405                 no_messages n;
2406                 if (dgn_safe_place_map(map, true, true, p))
2407                 {
2408                     tries = -1; // hrm no_messages
2409                     break;
2410                 }
2411             }
2412         }
2413         if (tries > -1)
2414             mpr("A portal flickers into view, then vanishes.");
2415         else
2416             mpr("A mystic portal forms.");
2417         return;
2418     }
2419     else if (power_level == 1)
2420     {
2421         if (coinflip())
2422         {
2423             // Create a random bad statue and a friendly, timed golem.
2424             // This could be really bad, because they're placed adjacent
2425             // to you...
2426             int num_made = 0;
2427
2428             const monster_type statues[] =
2429             {
2430                 MONS_ORANGE_STATUE, MONS_SILVER_STATUE, MONS_ICE_STATUE
2431             };
2432
2433             if (create_monster(
2434                     mgen_data::hostile_at(
2435                         RANDOM_ELEMENT(statues), "the Trowel card",
2436                         true, 0, 0, you.pos())))
2437             {
2438                 mpr("A menacing statue appears!");
2439                 num_made++;
2440             }
2441
2442             const monster_type golems[] =
2443             {
2444                 MONS_CLAY_GOLEM, MONS_STONE_GOLEM, MONS_IRON_GOLEM,
2445                 MONS_CRYSTAL_GOLEM, MONS_TOENAIL_GOLEM
2446             };
2447
2448             if (create_monster(
2449                     mgen_data(RANDOM_ELEMENT(golems),
2450                               BEH_FRIENDLY, &you, 5, 0,
2451                               you.pos(), MHITYOU)))
2452             {
2453                 mpr("You construct a golem!");
2454                 num_made++;
2455             }
2456
2457             if (num_made == 2)
2458                 mpr("The constructs glare at each other.");
2459
2460             done_stuff = (num_made > 0);
2461         }
2462         else
2463         {
2464             // Do-nothing (effectively): create a cosmetic feature
2465             const coord_def pos = pick_adjacent_free_square(you.pos());
2466             if (in_bounds(pos))
2467             {
2468                 const dungeon_feature_type statfeat[] =
2469                 {
2470                     DNGN_GRANITE_STATUE, DNGN_ORCISH_IDOL
2471                 };
2472                 // We leave the items on the square
2473                 grd(pos) = RANDOM_ELEMENT(statfeat);
2474                 mpr("A statue takes form beside you.");
2475                 done_stuff = true;
2476             }
2477         }
2478     }
2479     else
2480     {
2481         _create_altar(p);
2482         done_stuff = true;
2483     }
2484
2485     if (!done_stuff)
2486         canned_msg(MSG_NOTHING_HAPPENS);
2487 }
2488
2489 static void _genie_card(int power, deck_rarity_type rarity)
2490 {
2491     if (coinflip())
2492     {
2493         mpr("A genie takes form and thunders: "
2494             "\"Choose your reward, mortal!\"");
2495         more();
2496         run_uncancel(UNC_ACQUIREMENT, AQ_CARD_GENIE);
2497     }
2498     else
2499     {
2500         mpr("A genie takes form and thunders: "
2501             "\"You disturbed me, fool!\"");
2502         potion_effect(coinflip() ? POT_DEGENERATION : POT_DECAY, 40);
2503     }
2504 }
2505
2506 // Special case for *your* god, maybe?
2507 static void _godly_wrath()
2508 {
2509     int tries = 100;
2510     while (tries-- > 0)
2511     {
2512         god_type god = random_god();
2513
2514         // Don't recursively make player draw from the Deck of Punishment.
2515         if (god == GOD_NEMELEX_XOBEH)
2516             continue;
2517
2518         // Stop once we find a god willing to punish the player.
2519         if (divine_retribution(god))
2520             break;
2521     }
2522
2523     if (tries <= 0)
2524         mpr("You somehow manage to escape divine attention...");
2525 }
2526
2527 static void _curse_card(int power, deck_rarity_type rarity)
2528 {
2529     const int power_level = _get_power_level(power, rarity);
2530
2531     mpr("You feel a malignant aura surround you.");
2532     if (power_level >= 2)
2533     {
2534         // Curse (almost) everything.
2535         while (curse_an_item(true) && !one_chance_in(1000))
2536             ;
2537     }
2538     else if (power_level == 1)
2539     {
2540         // Curse an average of four items.
2541         do
2542             curse_an_item();
2543         while (!one_chance_in(4));
2544     }
2545     else
2546     {
2547         // Curse 1.5 items on average.
2548         curse_an_item();
2549         if (coinflip())
2550             curse_an_item();
2551     }
2552 }
2553
2554 static void _crusade_card(int power, deck_rarity_type rarity)
2555 {
2556     const int power_level = _get_power_level(power, rarity);
2557     if (power_level >= 1)
2558     {
2559         // A chance to convert opponents.
2560         for (monster_near_iterator mi(you.pos(), LOS_NO_TRANS); mi; ++mi)
2561         {
2562             if (mi->friendly()
2563                || mi->holiness() != MH_NATURAL
2564                || mons_is_unique(mi->type)
2565                || mons_immune_magic(*mi)
2566                || player_will_anger_monster(*mi))
2567             {
2568                 continue;
2569             }
2570
2571             // Note that this bypasses the magic resistance
2572             // (though not immunity) check.  Specifically,
2573             // you can convert Killer Klowns this way.
2574             // Might be too good.
2575             if (mi->hit_dice * 35 < random2(power))
2576             {
2577                 simple_monster_message(*mi, " is converted.");
2578                 mi->add_ench(ENCH_CHARM);
2579                 mons_att_changed(*mi);
2580             }
2581         }
2582     }
2583     cast_mass_abjuration(power/4);
2584 }
2585
2586 static void _summon_demon_card(int power, deck_rarity_type rarity)
2587 {
2588     const int power_level = _get_power_level(power, rarity);
2589     monster_type dct;
2590     if (power_level >= 2)
2591         dct = RANDOM_DEMON_GREATER;
2592     else if (power_level == 1)
2593         dct = RANDOM_DEMON_COMMON;
2594     else
2595         dct = RANDOM_DEMON_LESSER;
2596
2597     // FIXME: The manual testing for message printing is there because
2598     // we can't rely on create_monster() to do it for us. This is
2599     // because if you are completely surrounded by walls, create_monster()
2600     // will never manage to give a position which isn't (-1,-1)
2601     // and thus not print the message.
2602     // This hack appears later in this file as well.
2603     if (!create_monster(
2604             mgen_data(summon_any_demon(dct), BEH_FRIENDLY, &you,
2605                       5 - power_level, 0, you.pos(), MHITYOU),
2606             false))
2607     {
2608         mpr("You see a puff of smoke.");
2609     }
2610 }
2611
2612 static void _summon_animals(int power)
2613 {
2614     // Maybe we should just generate a Lair monster instead (and
2615     // guarantee that it is mobile)?
2616     const monster_type animals[] =
2617     {
2618         MONS_ORANGE_RAT, MONS_SHEEP, MONS_YAK,
2619         MONS_HOG, MONS_SOLDIER_ANT, MONS_WOLF,
2620         MONS_GRIZZLY_BEAR, MONS_POLAR_BEAR, MONS_BLACK_BEAR,
2621         MONS_AGATE_SNAIL, MONS_BORING_BEETLE, MONS_BASILISK,
2622         MONS_KOMODO_DRAGON, MONS_SPINY_FROG, MONS_HOUND,
2623         MONS_ELEPHANT, MONS_HIPPOGRIFF, MONS_GRIFFON
2624     };
2625
2626     int count = 0;
2627     const int count_max = 8;
2628
2629     int pow_left = power + 1;
2630
2631     const bool varied = coinflip();
2632
2633     monster_type mon = MONS_PROGRAM_BUG;
2634
2635     while (pow_left >= 0 && count < count_max)
2636     {
2637         // Pick a random monster and subtract its cost.
2638         if (varied || count == 0)
2639             mon = RANDOM_ELEMENT(animals);
2640
2641         const int pow_spent = mons_power(mon) * 3;
2642
2643         // Allow a certain degree of overuse, but not too much.
2644         // Guarantee at least two summons.
2645         if (pow_spent >= pow_left * 2 && count >= 2)
2646             break;
2647
2648         pow_left -= pow_spent;
2649         count++;
2650
2651         const bool friendly = (random2(power) > 4);
2652
2653         create_monster(
2654             mgen_data(mon,
2655                       friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
2656                       4, 0, you.pos(), MHITYOU));
2657     }
2658 }
2659
2660 static void _summon_dancing_weapon(int power, deck_rarity_type rarity)
2661 {
2662     const int power_level = _get_power_level(power, rarity);
2663
2664     monster *mon =
2665         create_monster(
2666             mgen_data(MONS_DANCING_WEAPON, BEH_FRIENDLY, &you,
2667                       power_level + 2, 0, you.pos(), MHITYOU),
2668             false);
2669
2670     // Given the abundance of Nemelex decks, not setting hard reset
2671     // leaves a trail of weapons behind, most of which just get
2672     // offered to Nemelex again, adding an unnecessary source of
2673     // piety.
2674     if (mon)
2675     {
2676         // Override the weapon.
2677         ASSERT(mon->weapon() != NULL);
2678         item_def& wpn(*mon->weapon());
2679
2680         set_equip_race(wpn, ISFLAG_NO_RACE);
2681
2682         if (power_level == 0)
2683         {
2684             // Wimpy, negative-enchantment weapon.
2685             wpn.plus  = -random2(4);
2686             wpn.plus2 = -random2(4);
2687             wpn.sub_type = (coinflip() ? WPN_SHORT_SWORD : WPN_HAMMER);
2688
2689             set_item_ego_type(wpn, OBJ_WEAPONS, SPWPN_NORMAL);
2690         }
2691         else if (power_level == 1)
2692         {
2693             // This is getting good.
2694             wpn.plus  = random2(4) - 1;
2695             wpn.plus2 = random2(4) - 1;
2696             wpn.sub_type = (coinflip() ? WPN_LONG_SWORD : WPN_TRIDENT);
2697
2698             if (coinflip())
2699             {
2700                 set_item_ego_type(wpn, OBJ_WEAPONS,
2701                                   coinflip() ? SPWPN_FLAMING : SPWPN_FREEZING);
2702             }
2703             else
2704                 set_item_ego_type(wpn, OBJ_WEAPONS, SPWPN_NORMAL);
2705         }
2706         else if (power_level == 2)
2707         {
2708             // Rare and powerful.
2709             wpn.plus  = random2(4) + 2;
2710             wpn.plus2 = random2(4) + 2;
2711             wpn.sub_type = (coinflip() ? WPN_DIRE_FLAIL : WPN_EXECUTIONERS_AXE);
2712
2713             set_item_ego_type(wpn, OBJ_WEAPONS,
2714                               coinflip() ? SPWPN_SPEED : SPWPN_ELECTROCUTION);
2715         }
2716
2717         item_colour(wpn);
2718
2719         mon->flags |= MF_HARD_RESET;
2720
2721         ghost_demon newstats;
2722         newstats.init_dancing_weapon(wpn, power / 4);
2723
2724         mon->set_ghost(newstats);
2725         mon->ghost_demon_init();
2726     }
2727     else
2728         mpr("You see a puff of smoke.");
2729 }
2730
2731 static void _summon_flying(int power, deck_rarity_type rarity)
2732 {
2733     const int power_level = _get_power_level(power, rarity);
2734
2735     const monster_type flytypes[] =
2736     {
2737         MONS_BUTTERFLY, MONS_FIREFLY, MONS_INSUBSTANTIAL_WISP,
2738         MONS_VAMPIRE_MOSQUITO, MONS_VAPOUR, MONS_YELLOW_WASP,
2739         MONS_RED_WASP
2740     };
2741
2742     // Choose what kind of monster.
2743     monster_type result = flytypes[random2(5) + power_level];
2744     const int how_many = 2 + random2(3) + power_level * 3;
2745     bool hostile_invis = false;
2746
2747     for (int i = 0; i < how_many; ++i)
2748     {
2749         const bool friendly = !one_chance_in(power_level + 4);
2750
2751         create_monster(
2752             mgen_data(result,
2753                       friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
2754                       3, 0, you.pos(), MHITYOU));
2755
2756         if (mons_class_flag(result, M_INVIS) && !you.can_see_invisible() && !friendly)
2757             hostile_invis = true;
2758     }
2759
2760     if (hostile_invis)
2761         mpr("You sense the presence of something unfriendly.");
2762 }
2763
2764 static void _summon_skeleton(int power, deck_rarity_type rarity)
2765 {
2766     const int power_level = _get_power_level(power, rarity);
2767     const bool friendly = !one_chance_in(4 + power_level * 2);
2768     const monster_type skeltypes[] =
2769     {
2770         MONS_SKELETON, MONS_SKELETAL_WARRIOR, MONS_BONE_DRAGON
2771     };
2772
2773     if (!create_monster(mgen_data(skeltypes[power_level],
2774                                   friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
2775                                   min(power/50 + 1, 5), 0,
2776                                   you.pos(), MHITYOU),
2777                         false))
2778     {
2779         mpr("You see a puff of smoke.");
2780     }
2781 }
2782
2783 static void _summon_ugly(int power, deck_rarity_type rarity)
2784 {
2785     const int power_level = _get_power_level(power, rarity);
2786     const bool friendly = !one_chance_in(4 + power_level * 2);
2787     monster_type ugly;
2788     if (power_level >= 2)
2789         ugly = MONS_VERY_UGLY_THING;
2790     else if (power_level == 1)
2791         ugly = coinflip() ? MONS_VERY_UGLY_THING : MONS_UGLY_THING;
2792     else
2793         ugly = MONS_UGLY_THING;
2794
2795     if (!create_monster(mgen_data(ugly,
2796                                   friendly ? BEH_FRIENDLY : BEH_HOSTILE,
2797                                   &you,
2798                                   min(power/50 + 1, 5), 0,
2799                                   you.pos(), MHITYOU),
2800                         false))
2801     {
2802         mpr("You see a puff of smoke.");
2803     }
2804 }
2805
2806 static void _mercenary_card(int power, deck_rarity_type rarity)
2807 {
2808     const int power_level = _get_power_level(power, rarity);
2809     const monster_type merctypes[] =
2810     {
2811         MONS_BIG_KOBOLD, MONS_MERFOLK, MONS_NAGA,
2812         MONS_TENGU, MONS_ORC_KNIGHT, MONS_CENTAUR_WARRIOR,
2813         MONS_SPRIGGAN_RIDER, MONS_OGRE_MAGE, MONS_MINOTAUR,
2814         RANDOM_BASE_DRACONIAN, MONS_DEEP_ELF_BLADEMASTER,
2815     };
2816
2817     const int merc = power_level + random2(3 * (power_level + 1));
2818     ASSERT(merc < (int)ARRAYSZ(merctypes));
2819
2820     mgen_data mg(merctypes[merc], BEH_HOSTILE, &you,
2821                  0, 0, you.pos(), MHITYOU, MG_FORCE_BEH, you.religion);
2822
2823     mg.extra_flags |= MF_NO_REWARD;
2824
2825     // This is a bit of a hack to use give_monster_proper_name to feed
2826     // the mgen_data, but it gets the job done.
2827     monster tempmon;
2828     tempmon.type = merctypes[merc];
2829     if (give_monster_proper_name(&tempmon, false))
2830         mg.mname = tempmon.mname;
2831     else
2832         mg.mname = make_name(random_int(), false);
2833
2834     monster *mon = create_monster(mg);
2835
2836     if (!mon)
2837     {
2838         mpr("You see a puff of smoke.");
2839         return;
2840     }
2841
2842     mon->props["dbname"].get_string() = mons_class_name(merctypes[merc]);
2843
2844     redraw_screen(); // We want to see the monster while it's asking to be paid.
2845
2846     if (player_will_anger_monster(mon))
2847     {
2848         simple_monster_message(mon, " is repulsed!");
2849         return;
2850     }
2851
2852     const int fee = fuzz_value(exper_value(mon), 15, 15);
2853     if (fee > you.gold)
2854     {
2855         mprf("You cannot afford %s fee of %d gold!",
2856              mon->name(DESC_ITS).c_str(), fee);
2857         simple_monster_message(mon, " attacks!");
2858         return;
2859     }
2860
2861     mon->props["mercenary_fee"] = fee;
2862     run_uncancel(UNC_MERCENARY, mon->mid);
2863 }
2864
2865 bool recruit_mercenary(int mid)
2866 {
2867     monster *mon = monster_by_mid(mid);
2868     if (!mon)
2869         return true; // wut?
2870
2871     int fee = mon->props["mercenary_fee"].get_int();
2872     const string prompt = make_stringf("Pay %s fee of %d gold?",
2873                                        mon->name(DESC_ITS).c_str(), fee);
2874     bool paid = yesno(prompt.c_str(), false, 0);
2875     if (crawl_state.seen_hups)
2876         return false;
2877
2878     mon->props.erase("mercenary_fee");
2879     if (!paid)
2880     {
2881         simple_monster_message(mon, " attacks!");
2882         return true;
2883     }
2884
2885     simple_monster_message(mon, " joins your ranks!");
2886     mon->attitude = ATT_FRIENDLY;
2887     mons_att_changed(mon);
2888     you.del_gold(fee);
2889     return true;
2890 }
2891
2892 static void _alchemist_card(int power, deck_rarity_type rarity)
2893 {
2894     const int power_level = _get_power_level(power, rarity);
2895     const int orig_gold = you.gold;
2896     int gold_available = min(you.gold, random2avg(100, 2) * (1 + power_level));
2897
2898     you.del_gold(gold_available);
2899     dprf("%d gold available to spend.", gold_available);
2900
2901     // Spend some gold to regain health.
2902     int hp = min(gold_available / 3, you.hp_max - you.hp);
2903     if (hp > 0)
2904     {
2905         inc_hp(hp);
2906         gold_available -= hp * 2;
2907         mpr("You feel better.");
2908         dprf("Gained %d health, %d gold remaining.", hp, gold_available);
2909     }
2910     // Maybe spend some more gold to regain magic.
2911     int mp = min(gold_available / 5, you.max_magic_points - you.magic_points);
2912     if (mp > 0 && x_chance_in_y(power_level + 1, 5))
2913     {
2914         inc_mp(mp);
2915         gold_available -= mp * 5;
2916         mpr("You feel your power returning.");
2917         dprf("Gained %d magic, %d gold remaining.", mp, gold_available);
2918     }
2919
2920     // Add back any remaining gold.
2921     you.add_gold(gold_available);
2922     const int gold_used = orig_gold - you.gold;
2923     if (gold_used > 0)
2924         mprf("%d of your gold pieces vanish!", gold_used);
2925     else
2926         canned_msg(MSG_NOTHING_HAPPENS);
2927 }
2928
2929 static int _card_power(deck_rarity_type rarity)
2930 {
2931     int result = 0;
2932
2933     if (player_under_penance(GOD_NEMELEX_XOBEH))
2934         result -= you.penance[GOD_NEMELEX_XOBEH];
2935     else if (you_worship(GOD_NEMELEX_XOBEH))
2936     {
2937         result = you.piety;
2938         result *= (you.skill(SK_EVOCATIONS, 100) + 2500);
2939         result /= 2700;
2940     }
2941
2942     result += you.skill(SK_EVOCATIONS, 9);
2943     if (rarity == DECK_RARITY_RARE)
2944         result += 150;
2945     else if (rarity == DECK_RARITY_LEGENDARY)
2946         result += 300;
2947
2948     if (result < 0)
2949         result = 0;
2950
2951     return result;
2952 }
2953
2954 void card_effect(card_type which_card, deck_rarity_type rarity,
2955                  uint8_t flags, bool tell_card)
2956 {
2957     ASSERT(!_card_forbidden(which_card));
2958
2959     const char *participle = (flags & CFLAG_DEALT) ? "dealt" : "drawn";
2960     const int power = _card_power(rarity);
2961
2962     const god_type god =
2963         (crawl_state.is_god_acting()) ? crawl_state.which_god_acting()
2964                                       : GOD_NO_GOD;
2965
2966     dprf("Card power: %d, rarity: %d", power, rarity);
2967
2968     if (tell_card)
2969     {
2970         // These card types will usually give this message in the targetting
2971         // prompt, and the cases where they don't are handled specially.
2972         if (which_card != CARD_VITRIOL && which_card != CARD_FLAME
2973             && which_card != CARD_FROST && which_card != CARD_HAMMER
2974             && which_card != CARD_SPARK && which_card != CARD_PAIN
2975             && which_card != CARD_VENOM && which_card != CARD_ORB)
2976         {
2977             mprf("You have %s %s.", participle, card_name(which_card));
2978         }
2979     }
2980
2981     if (which_card == CARD_XOM && !crawl_state.is_god_acting())
2982     {
2983         if (you_worship(GOD_XOM))
2984         {
2985             // Being a self-centered deity, Xom *always* finds this
2986             // maximally hilarious.
2987             god_speaks(GOD_XOM, "Xom roars with laughter!");
2988             you.gift_timeout = 200;
2989         }
2990         else if (player_under_penance(GOD_XOM))
2991             god_speaks(GOD_XOM, "Xom laughs nastily.");
2992     }
2993
2994     switch (which_card)
2995     {
2996     case CARD_PORTAL:           _portal_card(power, rarity); break;
2997     case CARD_WARP:             _warp_card(power, rarity); break;
2998     case CARD_SWAP:             _swap_monster_card(power, rarity); break;
2999     case CARD_VELOCITY:         _velocity_card(power, rarity); break;
3000     case CARD_DAMNATION:        _damnation_card(power, rarity); break;