Apply the new ground_level method.
[crawl.git] / crawl-ref / source / decks.cc
blob5cacb1549dfdeb39b276f349bb8e40447d47cb33
1 /*
2 * File: decks.cc
3 * Summary: Functions with decks of cards.
4 */
6 #include "AppHdr.h"
8 #include "decks.h"
10 #include <iostream>
11 #include <algorithm>
13 #include "externs.h"
15 #include "acquire.h"
16 #include "beam.h"
17 #include "cio.h"
18 #include "coordit.h"
19 #include "database.h"
20 #include "dgn-actions.h"
21 #include "dungeon.h"
22 #include "effects.h"
23 #include "env.h"
24 #include "files.h"
25 #include "food.h"
26 #include "ghost.h"
27 #include "godwrath.h"
28 #include "invent.h"
29 #include "it_use2.h"
30 #include "item_use.h"
31 #include "itemprop.h"
32 #include "items.h"
33 #include "makeitem.h"
34 #include "maps.h"
35 #include "message.h"
36 #include "misc.h"
37 #include "mon-iter.h"
38 #include "mon-place.h"
39 #include "mon-util.h"
40 #include "mgen_data.h"
41 #include "coord.h"
42 #include "mon-stuff.h"
43 #include "mutation.h"
44 #include "options.h"
45 #include "ouch.h"
46 #include "player.h"
47 #include "player-stats.h"
48 #include "religion.h"
49 #include "godconduct.h"
50 #include "skills2.h"
51 #include "spl-cast.h"
52 #include "spl-damage.h"
53 #include "spl-goditem.h"
54 #include "spl-miscast.h"
55 #include "spl-other.h"
56 #include "spl-selfench.h"
57 #include "spl-summoning.h"
58 #include "spl-transloc.h"
59 #include "spl-util.h"
60 #include "spl-wpnench.h"
61 #include "state.h"
62 #include "stuff.h"
63 #include "terrain.h"
64 #include "transform.h"
65 #include "traps.h"
66 #include "view.h"
67 #include "xom.h"
69 // DECK STRUCTURE: deck.plus is the number of cards the deck *started*
70 // with, deck.plus2 is the number of cards drawn, deck.special is the
71 // deck rarity, deck.props["cards"] holds the list of cards (with the
72 // highest index card being the top card, and index 0 being the bottom
73 // card), deck.props["drawn_cards"] holds the list of drawn cards
74 // (with index 0 being the first drawn), deck.props["card_flags"]
75 // holds the flags for each card, deck.props["num_marked"] is the
76 // number of marked cards left in the deck, and
77 // deck.props["non_brownie_draws"] is the number of non-marked draws
78 // you have to make from that deck before earning brownie points from
79 // it again.
81 // The card type and per-card flags are each stored as unsigned bytes,
82 // for a maximum of 256 different kinds of cards and 8 bits of flags.
84 static void _deck_ident(item_def& deck);
86 struct card_with_weights
88 card_type card;
89 int weight[3];
92 typedef card_with_weights deck_archetype;
94 #define END_OF_DECK {NUM_CARDS, {0,0,0}}
96 const deck_archetype deck_of_transport[] = {
97 { CARD_PORTAL, {5, 5, 5} },
98 { CARD_WARP, {5, 5, 5} },
99 { CARD_SWAP, {5, 5, 5} },
100 { CARD_VELOCITY, {5, 5, 5} },
101 END_OF_DECK
104 const deck_archetype deck_of_emergency[] = {
105 { CARD_TOMB, {5, 5, 5} },
106 { CARD_BANSHEE, {5, 5, 5} },
107 { CARD_DAMNATION, {0, 1, 2} },
108 { CARD_SOLITUDE, {5, 5, 5} },
109 { CARD_WARPWRIGHT, {5, 5, 5} },
110 { CARD_FLIGHT, {5, 5, 5} },
111 END_OF_DECK
114 const deck_archetype deck_of_destruction[] = {
115 { CARD_VITRIOL, {5, 5, 5} },
116 { CARD_FLAME, {5, 5, 5} },
117 { CARD_FROST, {5, 5, 5} },
118 { CARD_VENOM, {5, 5, 5} },
119 { CARD_HAMMER, {5, 5, 5} },
120 { CARD_SPARK, {5, 5, 5} },
121 { CARD_PAIN, {5, 5, 5} },
122 { CARD_TORMENT, {1, 3, 5} },
123 END_OF_DECK
126 const deck_archetype deck_of_battle[] = {
127 { CARD_ELIXIR, {5, 5, 5} },
128 { CARD_BATTLELUST, {5, 5, 5} },
129 { CARD_METAMORPHOSIS, {5, 5, 5} },
130 { CARD_HELM, {5, 5, 5} },
131 { CARD_BLADE, {5, 5, 5} },
132 { CARD_SHADOW, {5, 5, 5} },
133 END_OF_DECK
136 const deck_archetype deck_of_enchantments[] = {
137 { CARD_ELIXIR, {5, 5, 5} },
138 END_OF_DECK
141 const deck_archetype deck_of_summoning[] = {
142 { CARD_CRUSADE, {5, 5, 5} },
143 { CARD_SUMMON_ANIMAL, {5, 5, 5} },
144 { CARD_SUMMON_DEMON, {5, 5, 5} },
145 { CARD_SUMMON_WEAPON, {5, 5, 5} },
146 { CARD_SUMMON_FLYING, {5, 5, 5} },
147 { CARD_SUMMON_SKELETON, {5, 5, 5} },
148 { CARD_SUMMON_UGLY, {5, 5, 5} },
149 END_OF_DECK
152 const deck_archetype deck_of_wonders[] = {
153 { CARD_POTION, {5, 5, 5} },
154 { CARD_FOCUS, {1, 1, 2} },
155 { CARD_SHUFFLE, {0, 1, 2} },
156 { CARD_EXPERIENCE, {5, 5, 5} },
157 { CARD_WILD_MAGIC, {5, 5, 5} },
158 { CARD_HELIX, {5, 5, 5} },
159 { CARD_SAGE, {5, 5, 5} },
160 END_OF_DECK
163 const deck_archetype deck_of_dungeons[] = {
164 { CARD_WATER, {5, 5, 5} },
165 { CARD_GLASS, {5, 5, 5} },
166 { CARD_MAP, {5, 5, 5} },
167 { CARD_DOWSING, {5, 5, 5} },
168 { CARD_SPADE, {5, 5, 5} },
169 { CARD_TROWEL, {5, 5, 5} },
170 { CARD_MINEFIELD, {5, 5, 5} },
171 END_OF_DECK
174 const deck_archetype deck_of_oddities[] = {
175 { CARD_GENIE, {5, 5, 5} },
176 { CARD_BARGAIN, {5, 5, 5} },
177 { CARD_WRATH, {5, 5, 5} },
178 { CARD_XOM, {5, 5, 5} },
179 { CARD_FEAST, {5, 5, 5} },
180 { CARD_FAMINE, {5, 5, 5} },
181 { CARD_CURSE, {5, 5, 5} },
182 END_OF_DECK
185 const deck_archetype deck_of_punishment[] = {
186 { CARD_WRAITH, {5, 5, 5} },
187 { CARD_WILD_MAGIC, {5, 5, 5} },
188 { CARD_WRATH, {5, 5, 5} },
189 { CARD_XOM, {5, 5, 5} },
190 { CARD_FAMINE, {5, 5, 5} },
191 { CARD_CURSE, {5, 5, 5} },
192 { CARD_TOMB, {5, 5, 5} },
193 { CARD_DAMNATION, {5, 5, 5} },
194 { CARD_PORTAL, {5, 5, 5} },
195 { CARD_MINEFIELD, {5, 5, 5} },
196 { CARD_SWINE, {5, 5, 5} },
197 END_OF_DECK
200 static void _check_odd_card(uint8_t flags)
202 if ((flags & CFLAG_ODDITY) && !(flags & CFLAG_SEEN))
203 mpr("This card doesn't seem to belong here.");
206 static bool _card_forbidden(card_type card)
208 if (crawl_state.game_is_zotdef())
209 switch(card)
211 case CARD_TOMB:
212 case CARD_WARPWRIGHT:
213 case CARD_WATER:
214 case CARD_TROWEL:
215 case CARD_MINEFIELD: // with teleport taken away, might be acceptable
216 case CARD_STAIRS:
217 return true;
218 default:
219 break;
221 return false;
224 int cards_in_deck(const item_def &deck)
226 ASSERT(is_deck(deck));
228 const CrawlHashTable &props = deck.props;
229 ASSERT(props.exists("cards"));
231 return (props["cards"].get_vector().size());
234 static void _shuffle_deck(item_def &deck)
236 ASSERT(is_deck(deck));
238 CrawlHashTable &props = deck.props;
239 ASSERT(props.exists("cards"));
241 CrawlVector &cards = props["cards"].get_vector();
243 CrawlVector &flags = props["card_flags"].get_vector();
244 ASSERT(flags.size() == cards.size());
246 // Don't use std::shuffle(), since we want to apply exactly the
247 // same shuffling to both the cards vector and the flags vector.
248 std::vector<vec_size> pos;
249 for (unsigned long i = 0; i < cards.size(); ++i)
250 pos.push_back(random2(cards.size()));
252 for (vec_size i = 0; i < pos.size(); ++i)
254 std::swap(cards[i], cards[pos[i]]);
255 std::swap(flags[i], flags[pos[i]]);
259 card_type get_card_and_flags(const item_def& deck, int idx,
260 uint8_t& _flags)
262 const CrawlHashTable &props = deck.props;
263 const CrawlVector &cards = props["cards"].get_vector();
264 const CrawlVector &flags = props["card_flags"].get_vector();
266 // Negative idx means read from the end.
267 if (idx < 0)
268 idx += static_cast<int>(cards.size());
270 _flags = (uint8_t) flags[idx].get_byte();
272 return static_cast<card_type>(cards[idx].get_byte());
275 static void _set_card_and_flags(item_def& deck, int idx, card_type card,
276 uint8_t _flags)
278 CrawlHashTable &props = deck.props;
279 CrawlVector &cards = props["cards"].get_vector();
280 CrawlVector &flags = props["card_flags"].get_vector();
282 if (idx == -1)
283 idx = static_cast<int>(cards.size()) - 1;
285 cards[idx].get_byte() = card;
286 flags[idx].get_byte() = _flags;
289 const char* card_name(card_type card)
291 switch (card)
293 case CARD_PORTAL: return "the Portal";
294 case CARD_WARP: return "the Warp";
295 case CARD_SWAP: return "Swap";
296 case CARD_VELOCITY: return "Velocity";
297 case CARD_DAMNATION: return "Damnation";
298 case CARD_SOLITUDE: return "Solitude";
299 case CARD_ELIXIR: return "the Elixir";
300 case CARD_BATTLELUST: return "Battlelust";
301 case CARD_METAMORPHOSIS: return "Metamorphosis";
302 case CARD_HELM: return "the Helm";
303 case CARD_BLADE: return "the Blade";
304 case CARD_SHADOW: return "the Shadow";
305 case CARD_POTION: return "the Potion";
306 case CARD_FOCUS: return "Focus";
307 case CARD_SHUFFLE: return "Shuffle";
308 case CARD_EXPERIENCE: return "Experience";
309 case CARD_HELIX: return "the Helix";
310 case CARD_SAGE: return "the Sage";
311 case CARD_DOWSING: return "Dowsing";
312 case CARD_TROWEL: return "the Trowel";
313 case CARD_MINEFIELD: return "the Minefield";
314 case CARD_STAIRS: return "the Stairs";
315 case CARD_GENIE: return "the Genie";
316 case CARD_TOMB: return "the Tomb";
317 case CARD_WATER: return "Water";
318 case CARD_GLASS: return "Vitrification";
319 case CARD_MAP: return "the Map";
320 case CARD_BANSHEE: return "the Banshee";
321 case CARD_WILD_MAGIC: return "Wild Magic";
322 case CARD_CRUSADE: return "the Crusade";
323 case CARD_SUMMON_ANIMAL: return "the Herd";
324 case CARD_SUMMON_DEMON: return "the Pentagram";
325 case CARD_SUMMON_WEAPON: return "the Dance";
326 case CARD_SUMMON_FLYING: return "Foxfire";
327 case CARD_SUMMON_SKELETON: return "the Bones";
328 case CARD_SUMMON_UGLY: return "Repulsiveness";
329 case CARD_SUMMON_ANY: return "Summoning";
330 case CARD_XOM: return "Xom";
331 case CARD_FAMINE: return "Famine";
332 case CARD_FEAST: return "the Feast";
333 case CARD_WARPWRIGHT: return "Warpwright";
334 case CARD_FLIGHT: return "Flight";
335 case CARD_VITRIOL: return "Vitriol";
336 case CARD_FLAME: return "Flame";
337 case CARD_FROST: return "Frost";
338 case CARD_VENOM: return "Venom";
339 case CARD_SPARK: return "the Spark";
340 case CARD_HAMMER: return "the Hammer";
341 case CARD_PAIN: return "Pain";
342 case CARD_TORMENT: return "Torment";
343 case CARD_SPADE: return "the Spade";
344 case CARD_BARGAIN: return "the Bargain";
345 case CARD_WRATH: return "Wrath";
346 case CARD_WRAITH: return "the Wraith";
347 case CARD_CURSE: return "the Curse";
348 case CARD_SWINE: return "the Swine";
349 case NUM_CARDS: return "a buggy card";
351 return "a very buggy card";
354 static const deck_archetype* _random_sub_deck(uint8_t deck_type)
356 const deck_archetype *pdeck = NULL;
357 switch (deck_type)
359 case MISC_DECK_OF_ESCAPE:
360 pdeck = (coinflip() ? deck_of_transport : deck_of_emergency);
361 break;
362 case MISC_DECK_OF_DESTRUCTION: pdeck = deck_of_destruction; break;
363 case MISC_DECK_OF_DUNGEONS: pdeck = deck_of_dungeons; break;
364 case MISC_DECK_OF_SUMMONING: pdeck = deck_of_summoning; break;
365 case MISC_DECK_OF_WONDERS: pdeck = deck_of_wonders; break;
366 case MISC_DECK_OF_PUNISHMENT: pdeck = deck_of_punishment; break;
367 case MISC_DECK_OF_WAR:
368 switch (random2(6))
370 case 0: pdeck = deck_of_destruction; break;
371 case 1: pdeck = deck_of_enchantments; break;
372 case 2: pdeck = deck_of_battle; break;
373 case 3: pdeck = deck_of_summoning; break;
374 case 4: pdeck = deck_of_transport; break;
375 case 5: pdeck = deck_of_emergency; break;
377 break;
378 case MISC_DECK_OF_CHANGES:
379 switch (random2(3))
381 case 0: pdeck = deck_of_battle; break;
382 case 1: pdeck = deck_of_dungeons; break;
383 case 2: pdeck = deck_of_wonders; break;
385 break;
386 case MISC_DECK_OF_DEFENCE:
387 pdeck = (coinflip() ? deck_of_emergency : deck_of_battle);
388 break;
391 ASSERT(pdeck);
393 return (pdeck);
396 static card_type _choose_from_archetype(const deck_archetype* pdeck,
397 deck_rarity_type rarity)
399 // We assume here that common == 0, rare == 1, legendary == 2.
401 // FIXME: We should use one of the various choose_random_weighted
402 // functions here, probably with an iterator, instead of
403 // duplicating the implementation.
405 int totalweight = 0;
406 card_type result = NUM_CARDS;
407 for (int i = 0; pdeck[i].card != NUM_CARDS; ++i)
409 const card_with_weights& cww = pdeck[i];
410 if (_card_forbidden(cww.card))
411 continue;
412 totalweight += cww.weight[rarity];
413 if (x_chance_in_y(cww.weight[rarity], totalweight))
414 result = cww.card;
416 return result;
419 static card_type _random_card(uint8_t deck_type, deck_rarity_type rarity,
420 bool &was_oddity)
422 const deck_archetype *pdeck = _random_sub_deck(deck_type);
424 if (one_chance_in(100))
426 pdeck = deck_of_oddities;
427 was_oddity = true;
430 return _choose_from_archetype(pdeck, rarity);
433 static card_type _random_card(const item_def& item, bool &was_oddity)
435 return _random_card(item.sub_type, deck_rarity(item), was_oddity);
438 static card_type _draw_top_card(item_def& deck, bool message,
439 uint8_t &_flags)
441 CrawlHashTable &props = deck.props;
442 CrawlVector &cards = props["cards"].get_vector();
443 CrawlVector &flags = props["card_flags"].get_vector();
445 int num_cards = cards.size();
446 int idx = num_cards - 1;
448 ASSERT(num_cards > 0);
450 card_type card = get_card_and_flags(deck, idx, _flags);
451 cards.pop_back();
452 flags.pop_back();
454 if (message)
456 if (_flags & CFLAG_MARKED)
457 mprf("You draw %s.", card_name(card));
458 else
459 mprf("You draw a card... It is %s.", card_name(card));
461 _check_odd_card(_flags);
464 return card;
467 static void _push_top_card(item_def& deck, card_type card,
468 uint8_t _flags)
470 CrawlHashTable &props = deck.props;
471 CrawlVector &cards = props["cards"].get_vector();
472 CrawlVector &flags = props["card_flags"].get_vector();
474 cards.push_back((char) card);
475 flags.push_back((char) _flags);
478 static void _remember_drawn_card(item_def& deck, card_type card, bool allow_id)
480 ASSERT(is_deck(deck));
481 CrawlHashTable &props = deck.props;
482 CrawlVector &drawn = props["drawn_cards"].get_vector();
483 drawn.push_back(static_cast<char>(card));
485 // Once you've drawn two cards, you know the deck.
486 if (allow_id && (drawn.size() >= 2 || origin_is_god_gift(deck)))
487 _deck_ident(deck);
490 const std::vector<card_type> get_drawn_cards(const item_def& deck)
492 std::vector<card_type> result;
493 if (is_deck(deck))
495 const CrawlHashTable &props = deck.props;
496 const CrawlVector &drawn = props["drawn_cards"].get_vector();
497 for (unsigned int i = 0; i < drawn.size(); ++i)
499 const char tmp = drawn[i];
500 result.push_back(static_cast<card_type>(tmp));
503 return result;
506 static bool _check_buggy_deck(item_def& deck)
508 std::ostream& strm = msg::streams(MSGCH_DIAGNOSTICS);
509 if (!is_deck(deck))
511 crawl_state.zero_turns_taken();
512 strm << "This isn't a deck at all!" << std::endl;
513 return (true);
516 CrawlHashTable &props = deck.props;
518 if (!props.exists("cards")
519 || props["cards"].get_type() != SV_VEC
520 || props["cards"].get_vector().get_type() != SV_BYTE
521 || cards_in_deck(deck) == 0)
523 crawl_state.zero_turns_taken();
525 if (!props.exists("cards"))
526 strm << "Seems this deck never had any cards in the first place!";
527 else if (props["cards"].get_type() != SV_VEC)
528 strm << "'cards' property isn't a vector.";
529 else
531 if (props["cards"].get_vector().get_type() != SV_BYTE)
532 strm << "'cards' vector doesn't contain bytes.";
534 if (cards_in_deck(deck) == 0)
536 strm << "Strange, this deck is already empty.";
538 int cards_left = 0;
539 if (deck.plus2 >= 0)
540 cards_left = deck.plus - deck.plus2;
541 else
542 cards_left = -deck.plus;
544 if (cards_left != 0)
546 strm << " But there should have been " << cards_left
547 << " cards left.";
551 strm << std::endl
552 << "A swarm of software bugs snatches the deck from you "
553 "and whisks it away."
554 << std::endl;
556 if (deck.link == you.equip[EQ_WEAPON])
557 unwield_item();
559 dec_inv_item_quantity(deck.link, 1);
560 did_god_conduct(DID_CARDS, 1);
562 return (true);
565 bool problems = false;
567 CrawlVector &cards = props["cards"].get_vector();
568 CrawlVector &flags = props["card_flags"].get_vector();
570 vec_size num_cards = cards.size();
571 vec_size num_flags = flags.size();
573 unsigned int num_buggy = 0;
574 unsigned int num_marked = 0;
576 for (vec_size i = 0; i < num_cards; ++i)
578 uint8_t card = cards[i].get_byte();
579 uint8_t _flags = flags[i].get_byte();
580 if (card >= NUM_CARDS)
582 cards.erase(i);
583 flags.erase(i);
584 i--;
585 num_cards--;
586 num_buggy++;
588 else
590 if (_flags & CFLAG_MARKED)
591 num_marked++;
595 if (num_buggy > 0)
597 strm << num_buggy << " buggy cards found in the deck, discarding them."
598 << std::endl;
600 deck.plus2 += num_buggy;
602 num_cards = cards.size();
603 num_flags = cards.size();
605 problems = true;
608 if (num_cards == 0)
610 crawl_state.zero_turns_taken();
612 strm << "Oops, all of the cards seem to be gone." << std::endl
613 << "A swarm of software bugs snatches the deck from you "
614 "and whisks it away." << std::endl;
616 if (deck.link == you.equip[EQ_WEAPON])
617 unwield_item();
619 dec_inv_item_quantity(deck.link, 1);
620 did_god_conduct(DID_CARDS, 1);
622 return (true);
625 if (num_cards > deck.plus)
627 if (deck.plus == 0)
628 strm << "Deck was created with zero cards???" << std::endl;
629 else if (deck.plus < 0)
630 strm << "Deck was created with *negative* cards?!" << std::endl;
631 else
633 strm << "Deck has more cards than it was created with?"
634 << std::endl;
637 deck.plus = num_cards;
638 problems = true;
641 if (num_cards > num_flags)
643 #ifdef WIZARD
644 strm << (num_cards - num_flags) << " more cards than flags.";
645 #else
646 strm << "More cards than flags.";
647 #endif
648 strm << std::endl;
649 for (unsigned int i = num_flags + 1; i <= num_cards; ++i)
650 flags[i] = static_cast<char>(0);
652 problems = true;
654 else if (num_flags > num_cards)
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 << std::endl;
663 for (unsigned int i = num_flags; i > num_cards; --i)
664 flags.erase(i);
666 problems = true;
669 if (props["num_marked"].get_byte() > static_cast<char>(num_cards))
671 strm << "More cards marked than in the deck?" << std::endl;
672 props["num_marked"] = static_cast<char>(num_marked);
673 problems = true;
675 else if (props["num_marked"].get_byte() != static_cast<char>(num_marked))
677 #ifdef WIZARD
679 strm << "Oops, counted " << static_cast<int>(num_marked)
680 << " marked cards, but num_marked is "
681 << (static_cast<int>(props["num_marked"].get_byte()));
682 #else
683 strm << "Oops, book-keeping on marked cards is wrong.";
684 #endif
685 strm << std::endl;
687 props["num_marked"] = static_cast<char>(num_marked);
688 problems = true;
691 if (deck.plus2 >= 0)
693 if (deck.plus != (deck.plus2 + static_cast<long>(num_cards)))
695 #ifdef WIZARD
696 strm << "Have you used " << deck.plus2 << " cards, or "
697 << (deck.plus - num_cards) << "? Oops.";
698 #else
699 strm << "Oops, book-keeping on used cards is wrong.";
700 #endif
701 strm << std::endl;
702 deck.plus2 = deck.plus - num_cards;
703 problems = true;
706 else
708 if (-deck.plus2 != static_cast<long>(num_cards))
710 #ifdef WIZARD
711 strm << "There are " << num_cards << " cards left, not "
712 << (-deck.plus2) << ". Oops.";
713 #else
714 strm << "Oops, book-keeping on cards left is wrong.";
715 #endif
716 strm << std::endl;
717 deck.plus2 = -num_cards;
718 problems = true;
722 if (!problems)
723 return (false);
725 you.wield_change = true;
727 if (!yesno("Problems might not have been completely fixed; "
728 "still use deck?", true, 'n'))
730 crawl_state.zero_turns_taken();
731 return (true);
733 return (false);
736 // Choose a deck from inventory and return its slot (or -1).
737 static int _choose_inventory_deck(const char* prompt)
739 const int slot = prompt_invent_item(prompt,
740 MT_INVLIST, OSEL_DRAW_DECK,
741 true, true, true, 0, -1, NULL,
742 OPER_EVOKE);
744 if (prompt_failed(slot))
745 return -1;
747 if (!is_deck(you.inv[slot]))
749 mpr("That isn't a deck!");
750 return -1;
753 return slot;
756 // Select a deck from inventory and draw a card from it.
757 bool choose_deck_and_draw()
759 const int slot = _choose_inventory_deck("Draw from which deck?");
761 if (slot == -1)
763 crawl_state.zero_turns_taken();
764 return (false);
767 evoke_deck(you.inv[slot]);
768 return (true);
771 static void _deck_ident(item_def& deck)
773 if (in_inventory(deck) && !item_ident(deck, ISFLAG_KNOW_TYPE))
775 set_ident_flags(deck, ISFLAG_KNOW_TYPE);
776 mprf("This is %s.", deck.name(DESC_NOCAP_A).c_str());
777 you.wield_change = true;
781 // This also shuffles the deck.
782 static void _deck_lose_card(item_def& deck)
784 uint8_t flags = 0;
785 // Seen cards are only half as likely to fall out,
786 // marked cards only one-quarter as likely (note that marked
787 // cards are also seen.)
790 _shuffle_deck(deck);
791 get_card_and_flags(deck, -1, flags);
793 while ((flags & CFLAG_MARKED) && coinflip()
794 || (flags & CFLAG_SEEN) && coinflip());
796 _draw_top_card(deck, false, flags);
797 deck.plus2++;
800 // Peek at two cards in a deck, then shuffle them back in.
801 // Return false if the operation was failed/aborted along the way.
802 bool deck_peek()
804 const int slot = _choose_inventory_deck("Peek at which deck?");
805 if (slot == -1)
807 crawl_state.zero_turns_taken();
808 return (false);
810 item_def& deck(you.inv[slot]);
812 if (_check_buggy_deck(deck))
813 return (false);
815 if (cards_in_deck(deck) > 2)
817 _deck_lose_card(deck);
818 mpr("A card falls out of the deck.");
821 CrawlVector &cards = deck.props["cards"].get_vector();
822 const int num_cards = cards.size();
824 card_type card1, card2;
825 uint8_t flags1, flags2;
827 card1 = get_card_and_flags(deck, 0, flags1);
829 if (num_cards == 1)
831 mpr("There's only one card in the deck!");
833 _set_card_and_flags(deck, 0, card1, flags1 | CFLAG_SEEN | CFLAG_MARKED);
834 deck.props["num_marked"]++;
835 deck.plus2 = -1;
836 you.wield_change = true;
838 return (true);
841 card2 = get_card_and_flags(deck, 1, flags2);
843 int already_seen = 0;
844 if (flags1 & CFLAG_SEEN)
845 already_seen++;
846 if (flags2 & CFLAG_SEEN)
847 already_seen++;
849 // Always increase if seen 2, 50% increase if seen 1.
850 if (already_seen && x_chance_in_y(already_seen, 2))
851 deck.props["non_brownie_draws"]++;
853 mprf("You draw two cards from the deck. They are: %s and %s.",
854 card_name(card1), card_name(card2));
856 _set_card_and_flags(deck, 0, card1, flags1 | CFLAG_SEEN);
857 _set_card_and_flags(deck, 1, card2, flags2 | CFLAG_SEEN);
859 mpr("You shuffle the cards back into the deck.");
860 _shuffle_deck(deck);
862 // Peeking identifies the deck.
863 _deck_ident(deck);
865 you.wield_change = true;
866 return (true);
869 // Mark a deck: look at the next four cards, mark them, and shuffle
870 // them back into the deck. The player won't know what order they're
871 // in, and if the top card is non-marked then the player won't
872 // know what the next card is. Return false if the operation was
873 // failed/aborted along the way.
874 bool deck_mark()
876 const int slot = _choose_inventory_deck("Mark which deck?");
877 if (slot == -1)
879 crawl_state.zero_turns_taken();
880 return (false);
882 item_def& deck(you.inv[slot]);
883 if (_check_buggy_deck(deck))
884 return (false);
886 CrawlHashTable &props = deck.props;
887 if (props["num_marked"].get_byte() > 0)
889 mpr("The deck is already marked.");
890 crawl_state.zero_turns_taken();
891 return (false);
894 // Lose some cards, but keep at least two.
895 if (cards_in_deck(deck) > 2)
897 const int num_lost = std::min(cards_in_deck(deck)-2, random2(3) + 1);
898 for (int i = 0; i < num_lost; ++i)
899 _deck_lose_card(deck);
901 if (num_lost == 1)
902 mpr("A card falls out of the deck.");
903 else if (num_lost > 1)
904 mpr("Some cards fall out of the deck.");
907 const int num_cards = cards_in_deck(deck);
908 const int num_to_mark = (num_cards < 4 ? num_cards : 4);
910 if (num_cards == 1)
911 mpr("There's only one card left!");
912 else if (num_cards < 4)
913 mprf("The deck only has %d cards.", num_cards);
915 std::vector<std::string> names;
916 for (int i = 0; i < num_to_mark; ++i)
918 uint8_t flags;
919 card_type card = get_card_and_flags(deck, i, flags);
921 flags |= CFLAG_SEEN | CFLAG_MARKED;
922 _set_card_and_flags(deck, i, card, flags);
924 names.push_back(card_name(card));
926 mpr_comma_separated_list("You draw and mark ", names);
927 props["num_marked"] = (char) num_to_mark;
929 if (num_cards == 1)
931 else if (num_cards < 4)
933 mprf("You shuffle the deck.");
934 deck.plus2 = -num_cards;
936 else
937 mprf("You shuffle the cards back into the deck.");
939 _shuffle_deck(deck);
940 _deck_ident(deck);
941 you.wield_change = true;
943 return (true);
946 static void _redraw_stacked_cards(const std::vector<card_type>& draws,
947 unsigned int selected)
949 for (unsigned int i = 0; i < draws.size(); ++i)
951 cgotoxy(1, i+2);
952 textcolor(selected == i ? WHITE : LIGHTGREY);
953 cprintf("%u - %s", i+1, card_name(draws[i]));
954 clear_to_end_of_line();
958 static void _describe_cards(std::vector<card_type> cards)
960 ASSERT(!cards.empty());
962 std::ostringstream data;
963 for (unsigned int i = 0; i < cards.size(); ++i)
965 std::string name = card_name(cards[i]);
966 std::string desc = getLongDescription(name + " card");
967 if (desc.empty())
968 desc = "No description found.";
970 name = uppercase_first(name);
971 data << "<w>" << name << "</w>\n"
972 << get_linebreak_string(desc, get_number_of_cols())
973 << "\n";
975 formatted_string fs = formatted_string::parse_string(data.str());
976 clrscr();
977 fs.display();
978 wait_for_keypress();
979 redraw_screen();
982 // Stack a deck: look at the next five cards, put them back in any
983 // order, discard the rest of the deck.
984 // Return false if the operation was failed/aborted along the way.
985 bool deck_stack()
987 const int slot = _choose_inventory_deck("Stack which deck?");
988 if (slot == -1)
990 crawl_state.zero_turns_taken();
991 return (false);
994 item_def& deck(you.inv[slot]);
995 if (_check_buggy_deck(deck))
996 return (false);
998 CrawlHashTable &props = deck.props;
999 if (props["num_marked"].get_byte() > 0)
1001 mpr("You can't stack a marked deck.");
1002 crawl_state.zero_turns_taken();
1003 return (false);
1006 _deck_ident(deck);
1007 const int num_cards = cards_in_deck(deck);
1008 const int num_to_stack = (num_cards < 5 ? num_cards : 5);
1010 std::vector<card_type> draws;
1011 std::vector<uint8_t> flags;
1012 for (int i = 0; i < num_cards; ++i)
1014 uint8_t _flags;
1015 card_type card = _draw_top_card(deck, false, _flags);
1017 if (i < num_to_stack)
1019 draws.push_back(card);
1020 flags.push_back(_flags | CFLAG_SEEN | CFLAG_MARKED);
1022 // Rest of deck is discarded.
1025 if (num_cards == 1)
1026 mpr("There's only one card left!");
1027 else if (num_cards < 5)
1028 mprf("The deck only has %d cards.", num_to_stack);
1029 else if (num_cards == 5)
1030 mpr("The deck has exactly five cards.");
1031 else
1033 mprf("You draw the first five cards out of %d and discard the rest.",
1034 num_cards);
1036 more();
1038 if (draws.size() > 1)
1040 bool need_prompt_redraw = true;
1041 unsigned int selected = draws.size();
1042 while (true)
1044 if (need_prompt_redraw)
1046 clrscr();
1047 cgotoxy(1,1);
1048 textcolor(WHITE);
1049 cprintf("Press a digit to select a card, then another digit "
1050 "to swap it.");
1051 cgotoxy(1,10);
1052 cprintf("Press ? for the card descriptions, or Enter to "
1053 "accept.");
1055 _redraw_stacked_cards(draws, selected);
1056 need_prompt_redraw = false;
1059 // Hand-hacked implementation, instead of using Menu. Oh well.
1060 const int c = getch();
1061 if (c == CK_ENTER)
1063 cgotoxy(1,11);
1064 textcolor(LIGHTGREY);
1065 cprintf("Are you sure? (press y or Y to confirm)");
1066 if (toupper(getch()) == 'Y')
1067 break;
1069 cgotoxy(1,11);
1070 clear_to_end_of_line();
1071 continue;
1074 if (c == '?')
1076 _describe_cards(draws);
1077 need_prompt_redraw = true;
1079 else if (c >= '1' && c <= '0' + static_cast<int>(draws.size()))
1081 const unsigned int new_selected = c - '1';
1082 if (selected < draws.size())
1084 std::swap(draws[selected], draws[new_selected]);
1085 std::swap(flags[selected], flags[new_selected]);
1086 selected = draws.size();
1088 else
1089 selected = new_selected;
1091 _redraw_stacked_cards(draws, selected);
1094 redraw_screen();
1097 deck.plus2 = -num_to_stack;
1098 for (unsigned int i = 0; i < draws.size(); ++i)
1100 _push_top_card(deck, draws[draws.size() - 1 - i],
1101 flags[flags.size() - 1 - i]);
1104 props["num_marked"] = static_cast<char>(num_to_stack);
1105 you.wield_change = true;
1107 _check_buggy_deck(deck);
1109 return (true);
1112 // Draw the next three cards, discard two and pick one.
1113 bool deck_triple_draw()
1115 const int slot = _choose_inventory_deck("Triple draw from which deck?");
1116 if (slot == -1)
1118 crawl_state.zero_turns_taken();
1119 return (false);
1122 item_def& deck(you.inv[slot]);
1124 if (_check_buggy_deck(deck))
1125 return (false);
1127 const int num_cards = cards_in_deck(deck);
1129 // We have to identify the deck before removing cards from it.
1130 // Otherwise, _remember_drawn_card() will implicitly call
1131 // _deck_ident() when the deck might have no cards left.
1132 _deck_ident(deck);
1134 if (num_cards == 1)
1136 // Only one card to draw, so just draw it.
1137 evoke_deck(deck);
1138 return (true);
1141 const int num_to_draw = (num_cards < 3 ? num_cards : 3);
1142 std::vector<card_type> draws;
1143 std::vector<uint8_t> flags;
1145 for (int i = 0; i < num_to_draw; ++i)
1147 uint8_t _flags;
1148 card_type card = _draw_top_card(deck, false, _flags);
1150 draws.push_back(card);
1151 flags.push_back(_flags);
1154 int selected = -1;
1155 bool need_prompt_redraw = true;
1156 while (true)
1158 if (need_prompt_redraw)
1160 mpr("You draw... (choose one card, ? for their descriptions)");
1161 for (int i = 0; i < num_to_draw; ++i)
1163 msg::streams(MSGCH_PROMPT) << (static_cast<char>(i + 'a')) << " - "
1164 << card_name(draws[i]) << std::endl;
1166 need_prompt_redraw = false;
1168 const int keyin = tolower(get_ch());
1169 if (keyin == '?')
1171 _describe_cards(draws);
1172 need_prompt_redraw = true;
1174 else if (keyin >= 'a' && keyin < 'a' + num_to_draw)
1176 selected = keyin - 'a';
1177 break;
1179 else
1180 canned_msg(MSG_HUH);
1183 // Note how many cards were removed from the deck.
1184 deck.plus2 += num_to_draw;
1186 // Don't forget to update the number of marked ones, too.
1187 // But don't reduce the number of non-brownie draws.
1188 uint8_t num_marked_left = deck.props["num_marked"].get_byte();
1189 for (int i = 0; i < num_to_draw; ++i)
1191 _remember_drawn_card(deck, draws[i], false);
1192 if (flags[i] & CFLAG_MARKED)
1194 ASSERT(num_marked_left > 0);
1195 --num_marked_left;
1198 deck.props["num_marked"] = num_marked_left;
1200 you.wield_change = true;
1202 // Make deck disappear *before* the card effect, since we
1203 // don't want to unwield an empty deck.
1204 deck_rarity_type rarity = deck_rarity(deck);
1205 if (cards_in_deck(deck) == 0)
1207 mpr("The deck of cards disappears in a puff of smoke.");
1208 if (slot == you.equip[EQ_WEAPON])
1209 unwield_item();
1211 dec_inv_item_quantity(slot, 1);
1214 // Note that card_effect() might cause you to unwield the deck.
1215 card_effect(draws[selected], rarity,
1216 flags[selected] | CFLAG_SEEN | CFLAG_MARKED, false);
1218 return (true);
1221 // This is Nemelex retribution.
1222 void draw_from_deck_of_punishment()
1224 bool oddity;
1225 card_type card = _random_card(MISC_DECK_OF_PUNISHMENT, DECK_RARITY_COMMON,
1226 oddity);
1228 mpr("You draw a card...");
1229 card_effect(card, DECK_RARITY_COMMON);
1232 static int _xom_check_card(item_def &deck, card_type card,
1233 uint8_t flags)
1235 int amusement = 64;
1237 if (!item_type_known(deck))
1238 amusement *= 2;
1239 // Expecting one type of card but got another, real funny.
1240 else if (flags & CFLAG_ODDITY)
1241 amusement = 255;
1243 if (player_in_a_dangerous_place())
1244 amusement *= 2;
1246 switch (card)
1248 case CARD_XOM:
1249 // Handled elsewhere
1250 amusement = 0;
1251 break;
1253 case CARD_DAMNATION:
1254 // Nothing happened, boring.
1255 if (you.level_type != LEVEL_DUNGEON)
1256 amusement = 0;
1257 break;
1259 case CARD_MINEFIELD:
1260 case CARD_FAMINE:
1261 case CARD_CURSE:
1262 case CARD_SWINE:
1263 // Always hilarious.
1264 amusement = 255;
1266 default:
1267 break;
1270 return amusement;
1273 void evoke_deck(item_def& deck)
1275 if (_check_buggy_deck(deck))
1276 return;
1278 int brownie_points = 0;
1279 bool allow_id = in_inventory(deck) && !item_ident(deck, ISFLAG_KNOW_TYPE);
1281 const deck_rarity_type rarity = deck_rarity(deck);
1282 CrawlHashTable &props = deck.props;
1284 uint8_t flags = 0;
1285 card_type card = _draw_top_card(deck, true, flags);
1287 // Oddity cards don't give any information about the deck.
1288 if (flags & CFLAG_ODDITY)
1289 allow_id = false;
1291 // Passive Nemelex retribution: sometimes a card gets swapped out.
1292 // More likely to happen with marked decks.
1293 if (you.penance[GOD_NEMELEX_XOBEH])
1295 int c = 1;
1296 if ((flags & (CFLAG_MARKED | CFLAG_SEEN))
1297 || props["num_marked"].get_byte() > 0)
1299 c = 3;
1302 if (x_chance_in_y(c * you.penance[GOD_NEMELEX_XOBEH], 3000))
1304 card_type old_card = card;
1305 card = _choose_from_archetype(deck_of_punishment, rarity);
1306 if (card != old_card)
1308 simple_god_message(" seems to have exchanged this card "
1309 "behind your back!", GOD_NEMELEX_XOBEH);
1310 mprf("It's actually %s.", card_name(card));
1311 // You never completely appease Nemelex, but the effects
1312 // get less frequent.
1313 you.penance[GOD_NEMELEX_XOBEH] -=
1314 random2((you.penance[GOD_NEMELEX_XOBEH]+18) / 10);
1319 const int amusement = _xom_check_card(deck, card, flags);
1320 const bool no_brownie = (props["non_brownie_draws"].get_byte() > 0);
1322 // Do these before the deck item_def object is gone.
1323 if (flags & CFLAG_MARKED)
1324 props["num_marked"]--;
1325 if (no_brownie)
1326 props["non_brownie_draws"]--;
1328 deck.plus2++;
1329 _remember_drawn_card(deck, card, allow_id);
1331 // Get rid of the deck *before* the card effect because a card
1332 // might cause a wielded deck to be swapped out for something else,
1333 // in which case we don't want an empty deck to go through the
1334 // swapping process.
1335 const bool deck_gone = (cards_in_deck(deck) == 0);
1336 if (deck_gone)
1338 mpr("The deck of cards disappears in a puff of smoke.");
1339 dec_inv_item_quantity(deck.link, 1);
1340 // Finishing the deck will earn a point, even if it
1341 // was marked or stacked.
1342 brownie_points++;
1345 const bool fake_draw = !card_effect(card, rarity, flags, false);
1346 if (fake_draw && !deck_gone)
1347 props["non_brownie_draws"]++;
1349 if (!(flags & CFLAG_MARKED))
1351 // Could a Xom worshipper ever get a stacked deck in the first
1352 // place?
1353 xom_is_stimulated(amusement);
1355 // Nemelex likes gamblers.
1356 if (!no_brownie)
1358 brownie_points++;
1359 if (one_chance_in(3))
1360 brownie_points++;
1363 // You can't ID off a marked card
1364 allow_id = false;
1367 if (!deck_gone && allow_id
1368 && you.skills[SK_EVOCATIONS] > 5 + random2(35))
1370 mpr("Your skill with magical items lets you identify the deck.");
1371 set_ident_flags(deck, ISFLAG_KNOW_TYPE);
1372 msg::streams(MSGCH_EQUIPMENT) << deck.name(DESC_INVENTORY)
1373 << std::endl;
1376 if (!fake_draw)
1377 did_god_conduct(DID_CARDS, brownie_points);
1379 // Always wield change, since the number of cards used/left has
1380 // changed.
1381 you.wield_change = true;
1384 int get_power_level(int power, deck_rarity_type rarity)
1386 int power_level = 0;
1387 switch (rarity)
1389 case DECK_RARITY_COMMON:
1390 break;
1391 case DECK_RARITY_LEGENDARY:
1392 if (x_chance_in_y(power, 500))
1393 ++power_level;
1394 // deliberate fall-through
1395 case DECK_RARITY_RARE:
1396 if (x_chance_in_y(power, 700))
1397 ++power_level;
1398 break;
1400 return power_level;
1403 // Actual card implementations follow.
1404 static void _portal_card(int power, deck_rarity_type rarity)
1406 const int control_level = get_power_level(power, rarity);
1407 bool instant = false;
1408 bool controlled = false;
1409 if (control_level >= 2)
1411 instant = true;
1412 controlled = true;
1414 else if (control_level == 1)
1416 if (coinflip())
1417 instant = true;
1418 else
1419 controlled = true;
1422 int threshold = 6;
1423 const bool was_controlled = player_control_teleport();
1424 const bool short_control = (you.duration[DUR_CONTROL_TELEPORT] > 0
1425 && you.duration[DUR_CONTROL_TELEPORT]
1426 < threshold * BASELINE_DELAY);
1428 if (controlled && (!was_controlled || short_control))
1429 you.set_duration(DUR_CONTROL_TELEPORT, threshold); // Long enough to kick in.
1431 if (instant)
1432 you_teleport_now(true);
1433 else
1434 you_teleport();
1437 static void _warp_card(int power, deck_rarity_type rarity)
1439 if (item_blocks_teleport(true, true))
1441 canned_msg(MSG_STRANGE_STASIS);
1442 return;
1445 const int control_level = get_power_level(power, rarity);
1446 if (control_level >= 2)
1447 blink(1000, false);
1448 else if (control_level == 1)
1449 cast_semi_controlled_blink(power / 4);
1450 else
1451 random_blink(false);
1454 static void _swap_monster_card(int power, deck_rarity_type rarity)
1456 // Swap between you and another monster.
1457 // Don't choose yourself unless there are no monsters nearby.
1458 monster* mon_to_swap = choose_random_nearby_monster(0);
1459 if (!mon_to_swap)
1460 mpr("You spin around.");
1461 else
1462 swap_with_monster(mon_to_swap);
1465 static void _velocity_card(int power, deck_rarity_type rarity)
1467 const int power_level = get_power_level(power, rarity);
1468 if (power_level >= 2)
1469 potion_effect(POT_SPEED, random2(power / 4));
1470 else if (power_level == 1)
1472 cast_fly(random2(power / 4));
1473 cast_swiftness(random2(power / 4));
1475 else
1476 cast_swiftness(random2(power / 4));
1479 static void _damnation_card(int power, deck_rarity_type rarity)
1481 if (you.level_type != LEVEL_DUNGEON)
1483 canned_msg(MSG_NOTHING_HAPPENS);
1484 return;
1487 // Calculate how many extra banishments you get.
1488 const int power_level = get_power_level(power, rarity);
1489 int nemelex_bonus = 0;
1490 if (you.religion == GOD_NEMELEX_XOBEH && !player_under_penance())
1491 nemelex_bonus = you.piety / 20;
1493 int extra_targets = power_level + random2(you.skills[SK_EVOCATIONS]
1494 + nemelex_bonus) / 12;
1496 for (int i = 0; i < 1 + extra_targets; ++i)
1498 // Pick a random monster nearby to banish (or yourself).
1499 monster* mon_to_banish = choose_random_nearby_monster(1);
1501 // Bonus banishments only banish monsters.
1502 if (i != 0 && !mon_to_banish)
1503 continue;
1505 if (!mon_to_banish) // Banish yourself!
1507 banished(DNGN_ENTER_ABYSS, "drawing a card");
1508 break; // Don't banish anything else.
1510 else
1511 mon_to_banish->banish();
1516 static void _warpwright_card(int power, deck_rarity_type rarity)
1518 if (you.level_type == LEVEL_ABYSS)
1520 mpr("The power of the Abyss blocks your magic.");
1521 return;
1524 int count = 0;
1525 coord_def f;
1526 for (adjacent_iterator ai(you.pos()); ai; ++ai)
1527 if (grd(*ai) == DNGN_FLOOR && !find_trap(*ai) && one_chance_in(++count))
1528 f = *ai;
1530 if (count > 0) // found a spot
1532 if (place_specific_trap(f, TRAP_TELEPORT))
1534 // Mark it discovered if enough power.
1535 if (get_power_level(power, rarity) >= 1)
1536 find_trap(f)->reveal();
1541 static void _flight_card(int power, deck_rarity_type rarity)
1543 const int power_level = get_power_level(power, rarity);
1545 // Assume something _will_ happen.
1546 bool success = true;
1548 if (power_level == 0)
1550 if (!transform(random2(power/4), coinflip() ? TRAN_SPIDER : TRAN_BAT,
1551 true))
1553 // Oops, something went wrong here (either because of cursed
1554 // equipment or the possibility of stat loss).
1555 success = false;
1558 else if (power_level >= 1)
1560 cast_fly(random2(power/4));
1561 cast_swiftness(random2(power/4));
1564 if (power_level == 2) // Stacks with the above.
1566 if (is_valid_shaft_level() && grd(you.pos()) == DNGN_FLOOR)
1568 if (place_specific_trap(you.pos(), TRAP_SHAFT))
1570 find_trap(you.pos())->reveal();
1571 mpr("A shaft materialises beneath you!");
1575 if (one_chance_in(4 - power_level))
1576 potion_effect(POT_INVISIBILITY, random2(power)/4);
1577 else if (!success)
1578 canned_msg(MSG_NOTHING_HAPPENS);
1581 static void _minefield_card(int power, deck_rarity_type rarity)
1583 const int power_level = get_power_level(power, rarity);
1584 const int radius = power_level * 2 + 2;
1585 for (radius_iterator ri(you.pos(), radius, false, false, false); ri; ++ri)
1587 if (*ri == you.pos())
1588 continue;
1590 if (grd(*ri) == DNGN_FLOOR && !find_trap(*ri)
1591 && one_chance_in(4 - power_level))
1593 if (you.level_type == LEVEL_ABYSS)
1594 grd(*ri) = coinflip() ? DNGN_DEEP_WATER : DNGN_LAVA;
1595 else
1596 place_specific_trap(*ri, TRAP_RANDOM);
1601 static int stair_draw_count = 0;
1603 // This does not describe an actual card. Instead, it only exists to test
1604 // the stair movement effect in wizard mode ("&c stairs").
1605 static void _stairs_card(int power, deck_rarity_type rarity)
1607 UNUSED(power);
1608 UNUSED(rarity);
1610 you.duration[DUR_REPEL_STAIRS_MOVE] = 0;
1611 you.duration[DUR_REPEL_STAIRS_CLIMB] = 0;
1613 if (feat_stair_direction(grd(you.pos())) == CMD_NO_CMD)
1614 you.duration[DUR_REPEL_STAIRS_MOVE] = 1000;
1615 else
1616 you.duration[DUR_REPEL_STAIRS_CLIMB] = 500; // more annoying
1618 std::vector<coord_def> stairs_avail;
1620 for (radius_iterator ri(you.pos(), LOS_RADIUS, false, true, true); ri; ++ri)
1622 dungeon_feature_type feat = grd(*ri);
1623 if (feat_stair_direction(feat) != CMD_NO_CMD
1624 && feat != DNGN_ENTER_SHOP)
1626 stairs_avail.push_back(*ri);
1630 if (stairs_avail.size() == 0)
1632 mpr("No stairs available to move.");
1633 return;
1636 std::random_shuffle(stairs_avail.begin(), stairs_avail.end());
1638 for (unsigned int i = 0; i < stairs_avail.size(); ++i)
1639 move_stair(stairs_avail[i], stair_draw_count % 2, false);
1641 stair_draw_count++;
1644 static int _drain_monsters(coord_def where, int pow, int, actor *)
1646 if (where == you.pos())
1647 drain_exp();
1648 else
1650 monster* mon = monster_at(where);
1651 if (mon == NULL)
1652 return (0);
1654 if (!mon->drain_exp(&you, false, pow / 50))
1655 simple_monster_message(mon, " is unaffected.");
1658 return (1);
1661 static void _mass_drain(int pow)
1663 apply_area_visible(_drain_monsters, pow, true);
1666 // Return true if it was a "genuine" draw, i.e., there was a monster
1667 // to target. This is still exploitable by finding popcorn monsters.
1668 static bool _damaging_card(card_type card, int power, deck_rarity_type rarity)
1670 bool rc = there_are_monsters_nearby(true, false);
1671 const int power_level = get_power_level(power, rarity);
1673 dist target;
1674 zap_type ztype = ZAP_DEBUGGING_RAY;
1675 const zap_type firezaps[3] = { ZAP_FLAME, ZAP_STICKY_FLAME, ZAP_FIRE };
1676 const zap_type frostzaps[3] = { ZAP_FROST, ZAP_THROW_ICICLE, ZAP_COLD };
1677 const zap_type hammerzaps[3] = { ZAP_STRIKING, ZAP_STONE_ARROW,
1678 ZAP_CRYSTAL_SPEAR };
1679 const zap_type venomzaps[3] = { ZAP_STING, ZAP_VENOM_BOLT,
1680 ZAP_POISON_ARROW };
1681 const zap_type sparkzaps[3] = { ZAP_ELECTRICITY, ZAP_LIGHTNING,
1682 ZAP_ORB_OF_ELECTRICITY };
1683 const zap_type painzaps[2] = { ZAP_AGONY, ZAP_NEGATIVE_ENERGY };
1685 switch (card)
1687 case CARD_VITRIOL:
1688 ztype = (one_chance_in(3) ? ZAP_DEGENERATION : ZAP_BREATHE_ACID);
1689 break;
1691 case CARD_FLAME:
1692 ztype = (coinflip() ? ZAP_FIREBALL : firezaps[power_level]);
1693 break;
1695 case CARD_FROST: ztype = frostzaps[power_level]; break;
1696 case CARD_HAMMER: ztype = hammerzaps[power_level]; break;
1697 case CARD_VENOM: ztype = venomzaps[power_level]; break;
1698 case CARD_SPARK: ztype = sparkzaps[power_level]; break;
1700 case CARD_PAIN:
1701 if (power_level == 2)
1703 mprf("You have drawn %s.", card_name(card));
1704 _mass_drain(power);
1705 return (true);
1707 else
1708 ztype = painzaps[power_level];
1709 break;
1711 default:
1712 break;
1715 std::string prompt = "You have drawn ";
1716 prompt += card_name(card);
1717 prompt += ".";
1719 bolt beam;
1720 beam.range = LOS_RADIUS;
1721 if (spell_direction(target, beam, DIR_NONE, TARG_HOSTILE,
1722 LOS_RADIUS, true, true, false, NULL, prompt.c_str())
1723 && player_tracer(ZAP_DEBUGGING_RAY, power/4, beam))
1725 zapping(ztype, random2(power/4), beam);
1727 else
1728 rc = false;
1730 return (rc);
1733 static void _elixir_card(int power, deck_rarity_type rarity)
1735 int power_level = get_power_level(power, rarity);
1737 if (power_level == 1 && you.hp * 2 > you.hp_max)
1738 power_level = 0;
1740 if (power_level == 0)
1742 if (coinflip())
1743 potion_effect(POT_HEAL_WOUNDS, 40); // power doesn't matter
1744 else
1745 cast_regen(random2(power / 4));
1747 else if (power_level == 1)
1749 set_hp(you.hp_max, false);
1750 you.magic_points = 0;
1752 else if (power_level >= 2)
1754 set_hp(you.hp_max, false);
1755 you.magic_points = you.max_magic_points;
1757 you.redraw_hit_points = true;
1758 you.redraw_magic_points = true;
1761 static void _battle_lust_card(int power, deck_rarity_type rarity)
1763 const int power_level = get_power_level(power, rarity);
1764 if (power_level >= 2)
1766 you.set_duration(DUR_SLAYING, random2(power/6) + 1,
1767 0, "You feel deadly.");
1769 else if (power_level == 1)
1771 you.set_duration(DUR_BUILDING_RAGE, 1,
1772 0, "You feel your rage building.");
1774 else if (power_level == 0)
1775 potion_effect(POT_MIGHT, random2(power/4));
1778 static void _metamorphosis_card(int power, deck_rarity_type rarity)
1780 const int power_level = get_power_level(power, rarity);
1781 transformation_type trans;
1783 if (power_level >= 2)
1784 trans = coinflip() ? TRAN_DRAGON : TRAN_LICH;
1785 else if (power_level == 1)
1786 trans = coinflip() ? TRAN_STATUE : TRAN_BLADE_HANDS;
1787 else
1789 trans = one_chance_in(3) ? TRAN_SPIDER :
1790 coinflip() ? TRAN_ICE_BEAST
1791 : TRAN_BAT;
1794 // Might fail, e.g. because of cursed equipment or potential death by
1795 // stat loss. Aren't we being nice? (jpeg)
1796 if (!transform(random2(power/4), trans, true))
1797 canned_msg(MSG_NOTHING_HAPPENS);
1800 static void _helm_card(int power, deck_rarity_type rarity)
1802 const int power_level = get_power_level(power, rarity);
1803 bool do_phaseshift = false;
1804 bool do_stoneskin = false;
1805 bool do_shield = false;
1806 int num_resists = 0;
1808 // Chances are cumulative.
1809 if (power_level >= 2)
1811 if (coinflip()) do_phaseshift = true;
1812 if (coinflip()) do_stoneskin = true;
1813 if (coinflip()) do_shield = true;
1814 num_resists = random2(4);
1816 if (power_level >= 1)
1818 if (coinflip()) do_phaseshift = true;
1819 if (coinflip()) do_stoneskin = true;
1820 if (coinflip()) do_shield = true;
1822 if (power_level >= 0)
1824 if (coinflip())
1825 do_phaseshift = true;
1826 else
1827 do_stoneskin = true;
1830 if (do_phaseshift)
1831 cast_phase_shift(random2(power/4));
1832 if (do_stoneskin)
1833 cast_stoneskin(random2(power/4));
1834 if (num_resists)
1836 const duration_type possible_resists[4] = {
1837 DUR_RESIST_POISON, DUR_INSULATION,
1838 DUR_RESIST_FIRE, DUR_RESIST_COLD
1840 const char* resist_names[4] = {
1841 "poison", "electricity", "fire", "cold"
1844 for (int i = 0; i < 4 && num_resists; ++i)
1846 // If there are n left, of which we need to choose
1847 // k, we have chance k/n of selecting the next item.
1848 if (x_chance_in_y(num_resists, 4-i))
1850 // Add a temporary resistance.
1851 you.increase_duration(possible_resists[i], random2(power/7) +1);
1852 msg::stream << "You feel resistant to " << resist_names[i]
1853 << '.' << std::endl;
1854 --num_resists;
1859 if (do_shield)
1861 if (you.duration[DUR_MAGIC_SHIELD] == 0)
1862 mpr("A magical shield forms in front of you.");
1863 you.increase_duration(DUR_MAGIC_SHIELD, random2(power/6) + 1);
1867 static void _blade_card(int power, deck_rarity_type rarity)
1869 if (you.species == SP_CAT)
1871 mpr("You feel like a smilodon for a moment.");
1872 return;
1875 // Pause before jumping to the list.
1876 if (Options.auto_list)
1877 more();
1879 wield_weapon(false);
1881 const int power_level = get_power_level(power, rarity);
1882 if (power_level >= 2)
1884 cast_tukimas_dance(random2(power/4));
1886 else if (power_level == 1)
1888 cast_sure_blade(random2(power/4));
1890 else
1892 const brand_type brands[] = {
1893 SPWPN_FLAMING, SPWPN_FREEZING, SPWPN_VENOM, SPWPN_DRAINING,
1894 SPWPN_VORPAL, SPWPN_DISTORTION, SPWPN_PAIN, SPWPN_DUMMY_CRUSHING
1897 if (!brand_weapon(RANDOM_ELEMENT(brands), random2(power/4)))
1899 item_def* wpn = you.weapon();
1901 if (wpn)
1903 mprf("%s vibrate%s crazily for a second.",
1904 wpn->name(DESC_CAP_YOUR).c_str(),
1905 wpn->quantity == 1 ? "s" : "");
1907 else
1908 mprf("Your %s twitch.", your_hand(true).c_str());
1913 static void _shadow_card(int power, deck_rarity_type rarity)
1915 const int power_level = get_power_level(power, rarity);
1917 if (power_level >= 1)
1919 mpr(you.duration[DUR_STEALTH] ? "You feel more catlike."
1920 : "You feel stealthy.");
1921 you.increase_duration(DUR_STEALTH, random2(power/4) + 1);
1924 potion_effect(POT_INVISIBILITY, random2(power/4));
1927 static void _potion_card(int power, deck_rarity_type rarity)
1929 const int power_level = get_power_level(power, rarity);
1930 potion_type pot_effects[] = {
1931 POT_HEAL_WOUNDS, POT_HEAL_WOUNDS, POT_HEAL_WOUNDS,
1932 POT_HEALING, POT_HEALING, POT_HEALING,
1933 POT_RESTORE_ABILITIES, POT_RESTORE_ABILITIES,
1934 POT_POISON, POT_CONFUSION, POT_DEGENERATION
1937 potion_type pot = RANDOM_ELEMENT(pot_effects);
1939 if (power_level >= 1 && coinflip())
1940 pot = (coinflip() ? POT_CURE_MUTATION : POT_MUTATION);
1942 if (power_level >= 2 && one_chance_in(5))
1944 // +1 to a random stat.
1945 const potion_type gain_stat_pots[] = {
1946 POT_GAIN_STRENGTH, POT_GAIN_DEXTERITY, POT_GAIN_INTELLIGENCE
1948 pot = RANDOM_ELEMENT(gain_stat_pots);
1951 potion_effect(pot, random2(power/4));
1954 static void _focus_card(int power, deck_rarity_type rarity)
1956 stat_type best_stat = STAT_STR;
1957 stat_type worst_stat = STAT_STR;
1959 for (int i = 1; i < 3; ++i)
1961 stat_type s = static_cast<stat_type>(i);
1962 const int best_diff = you.max_stat(s) - you.max_stat(best_stat);
1963 if (best_diff > 0 || best_diff == 0 && coinflip())
1964 best_stat = s;
1966 const int worst_diff = you.max_stat(s) - you.max_stat(worst_stat);
1967 if (worst_diff < 0 || worst_diff == 0 && coinflip())
1968 worst_stat = s;
1971 while (best_stat == worst_stat)
1973 best_stat = static_cast<stat_type>(random2(3));
1974 worst_stat = static_cast<stat_type>(random2(3));
1977 std::string cause = "the Focus card";
1979 if (crawl_state.is_god_acting())
1981 god_type which_god = crawl_state.which_god_acting();
1982 if (crawl_state.is_god_retribution())
1983 cause = "the wrath of " + god_name(which_god);
1984 else
1986 if (which_god == GOD_XOM)
1987 cause = "the capriciousness of Xom";
1988 else
1989 cause = "the 'helpfulness' of " + god_name(which_god);
1993 modify_stat(best_stat, 1, true, cause.c_str(), true);
1994 modify_stat(worst_stat, -1, true, cause.c_str(), true);
1997 static void _shuffle_card(int power, deck_rarity_type rarity)
1999 int perm[NUM_STATS] = { 0, 1, 2 };
2000 std::random_shuffle(perm, perm + 3);
2002 FixedVector<int8_t, NUM_STATS> new_base;
2003 for (int i = 0; i < NUM_STATS; ++i)
2004 new_base[perm[i]] = you.base_stats[i];
2006 std::string cause = "the Shuffle card";
2008 if (crawl_state.is_god_acting())
2010 god_type which_god = crawl_state.which_god_acting();
2011 if (crawl_state.is_god_retribution())
2012 cause = "the wrath of " + god_name(which_god);
2013 else
2015 if (which_god == GOD_XOM)
2016 cause = "the capriciousness of Xom";
2017 else
2018 cause = "the 'helpfulness' of " + god_name(which_god);
2022 for (int i = 0; i < NUM_STATS; ++i)
2024 modify_stat(static_cast<stat_type>(i),
2025 new_base[i] - you.base_stats[i],
2026 true, cause.c_str(), true);
2030 static void _experience_card(int power, deck_rarity_type rarity)
2032 const int power_level = get_power_level(power, rarity);
2034 if (you.experience_level < 27)
2036 mpr("You feel more experienced.");
2037 const unsigned long xp_cap = 1 + exp_needed(2 + you.experience_level);
2039 // power_level 2 means automatic level gain.
2040 if (power_level == 2)
2041 you.experience = xp_cap;
2042 else
2044 // Likely to give a level gain (power of ~500 is reasonable
2045 // at high levels even for non-Nemelexites, so 50,000 XP.)
2046 // But not guaranteed.
2047 // Overrides archmagi effect, like potions of experience.
2048 you.experience += power * 100;
2049 if (you.experience > xp_cap)
2050 you.experience = xp_cap;
2053 else
2054 mpr("You feel knowledgeable.");
2056 // Put some free XP into pool; power_level 2 means fill pool
2057 you.exp_available += power * 50;
2058 if (power_level >= 2 || you.exp_available > FULL_EXP_POOL)
2059 you.exp_available = FULL_EXP_POOL;
2061 level_change();
2064 static void _remove_bad_mutation()
2066 // Ensure that only bad mutations are removed.
2067 if (!delete_mutation(RANDOM_BAD_MUTATION, false, false, false, true))
2068 mpr("You feel transcendent for a moment.");
2071 static void _helix_card(int power, deck_rarity_type rarity)
2073 const int power_level = get_power_level(power, rarity);
2075 if (power_level == 0)
2077 switch (how_mutated() ? random2(3) : 0)
2079 case 0:
2080 mutate(RANDOM_MUTATION);
2081 break;
2082 case 1:
2083 delete_mutation(RANDOM_MUTATION);
2084 mutate(RANDOM_MUTATION);
2085 break;
2086 case 2:
2087 delete_mutation(RANDOM_MUTATION);
2088 break;
2091 else if (power_level == 1)
2093 switch (how_mutated() ? random2(3) : 0)
2095 case 0:
2096 mutate(coinflip() ? RANDOM_GOOD_MUTATION : RANDOM_MUTATION);
2097 break;
2098 case 1:
2099 if (coinflip())
2100 _remove_bad_mutation();
2101 else
2102 delete_mutation(RANDOM_MUTATION);
2103 break;
2104 case 2:
2105 if (coinflip())
2107 if (coinflip())
2109 _remove_bad_mutation();
2110 mutate(RANDOM_MUTATION);
2112 else
2114 delete_mutation(RANDOM_MUTATION);
2115 mutate(RANDOM_GOOD_MUTATION);
2118 else
2120 delete_mutation(RANDOM_MUTATION);
2121 mutate(RANDOM_MUTATION);
2123 break;
2126 else
2128 switch (random2(3))
2130 case 0:
2131 _remove_bad_mutation();
2132 break;
2133 case 1:
2134 mutate(RANDOM_GOOD_MUTATION);
2135 break;
2136 case 2:
2137 if (coinflip())
2139 // If you get unlucky, you could get here with no bad
2140 // mutations and simply get a mutation effect. Oh well.
2141 _remove_bad_mutation();
2142 mutate(RANDOM_MUTATION);
2144 else
2146 delete_mutation(RANDOM_MUTATION);
2147 mutate(RANDOM_GOOD_MUTATION);
2149 break;
2154 void sage_card(int power, deck_rarity_type rarity)
2156 const int power_level = get_power_level(power, rarity);
2157 int c; // how much to weight your skills
2158 if (power_level == 0)
2159 c = 0;
2160 else if (power_level == 1)
2161 c = random2(10) + 1;
2162 else
2163 c = 10;
2165 // FIXME: yet another reproduction of random_choose_weighted
2166 // Ah for Python:
2167 // skill = random_choice([x*(40-x)*c/10 for x in skill_levels])
2168 int totalweight = 0;
2169 skill_type result = SK_NONE;
2170 for (int i = SK_FIRST_SKILL; i < NUM_SKILLS; ++i)
2172 skill_type s = static_cast<skill_type>(i);
2173 if (skill_name(s) == NULL)
2174 continue;
2176 if (you.skills[s] < MAX_SKILL_LEVEL)
2178 // Choosing a skill is likelier if you are somewhat skilled in it.
2179 const int curweight = 1 + you.skills[s] * (40 - you.skills[s]) * c;
2180 totalweight += curweight;
2181 if (x_chance_in_y(curweight, totalweight))
2182 result = s;
2186 if (result == SK_NONE)
2187 mpr("You feel omnipotent."); // All skills maxed.
2188 else
2190 you.set_duration(DUR_SAGE, random2(1800) + 200);
2191 you.sage_bonus_skill = result;
2192 you.sage_bonus_degree = power / 25;
2193 mprf(MSGCH_PLAIN, "You feel studious about %s.", skill_name(result));
2197 void create_pond(const coord_def& center, int radius, bool allow_deep)
2199 for (radius_iterator ri(center, radius, false); ri; ++ri)
2201 const coord_def p = *ri;
2202 if (p != you.pos() && coinflip())
2204 if (grd(p) == DNGN_FLOOR)
2206 dungeon_feature_type feat;
2208 if (allow_deep && coinflip())
2209 feat = DNGN_DEEP_WATER;
2210 else
2211 feat = DNGN_SHALLOW_WATER;
2213 dungeon_terrain_changed(p, feat);
2219 static void _deepen_water(const coord_def& center, int radius)
2221 for (radius_iterator ri(center, radius, false); ri; ++ri)
2223 // FIXME The iteration shouldn't affect the later squares in the
2224 // same iteration, i.e., a newly-flooded square shouldn't count
2225 // in the decision as to whether to make the next square flooded.
2226 const coord_def p = *ri;
2227 if (grd(p) == DNGN_SHALLOW_WATER
2228 && p != you.pos()
2229 && x_chance_in_y(1+count_neighbours(p, DNGN_DEEP_WATER), 8))
2231 dungeon_terrain_changed(p, DNGN_DEEP_WATER);
2233 if (grd(p) == DNGN_FLOOR
2234 && random2(3) < random2(count_neighbours(p, DNGN_DEEP_WATER)
2235 + count_neighbours(p, DNGN_SHALLOW_WATER)))
2237 dungeon_terrain_changed(p, DNGN_SHALLOW_WATER);
2242 static void _water_card(int power, deck_rarity_type rarity)
2244 const int power_level = get_power_level(power, rarity);
2245 if (power_level == 0)
2247 mpr("You create a pond!");
2248 create_pond(you.pos(), 4, false);
2250 else if (power_level == 1)
2252 mpr("You feel the tide rushing in!");
2253 create_pond(you.pos(), 6, true);
2254 for (int i = 0; i < 2; ++i)
2255 _deepen_water(you.pos(), 6);
2257 else
2259 mpr("Water floods your area!");
2261 // Flood all visible squares.
2262 for (radius_iterator ri(you.pos(), LOS_RADIUS, false); ri; ++ri)
2264 coord_def p = *ri;
2265 destroy_trap(p);
2266 if (grd(p) == DNGN_FLOOR)
2268 dungeon_feature_type new_feature = DNGN_SHALLOW_WATER;
2269 if (p != you.pos() && coinflip())
2270 new_feature = DNGN_DEEP_WATER;
2271 dungeon_terrain_changed(p, new_feature);
2277 static void _glass_card(int power, deck_rarity_type rarity)
2279 const int power_level = get_power_level(power, rarity);
2280 const int radius = (power_level == 2) ? 1000
2281 : random2(power/40) + 2;
2282 vitrify_area(radius);
2285 static void _dowsing_card(int power, deck_rarity_type rarity)
2287 const int power_level = get_power_level(power, rarity);
2288 bool things_to_do[3] = { false, false, false };
2289 things_to_do[random2(3)] = true;
2291 if (power_level == 1)
2292 things_to_do[random2(3)] = true;
2294 if (power_level >= 2)
2296 for (int i = 0; i < 3; ++i)
2297 things_to_do[i] = true;
2300 if (things_to_do[0])
2301 cast_detect_secret_doors(random2(power/4));
2302 if (things_to_do[1])
2303 detect_traps(random2(power/4));
2304 if (things_to_do[2])
2306 you.set_duration(DUR_TELEPATHY, random2(power/4), 0,
2307 "You feel telepathic!");
2308 detect_creatures(1 + you.duration[DUR_TELEPATHY] / 2 / BASELINE_DELAY,
2309 true);
2313 static bool _trowel_card(int power, deck_rarity_type rarity)
2315 // Early exit: don't clobber important features.
2316 if (is_critical_feature(grd(you.pos())))
2318 mpr("The dungeon trembles momentarily.");
2319 return (false);
2322 const int power_level = get_power_level(power, rarity);
2323 bool done_stuff = false;
2325 // [ds] FIXME: Remove the LEVEL_DUNGEON restriction once Crawl
2326 // handles stacked level_area_types correctly. We should also
2327 // review whether Trowel being able to create infinite portal
2328 // vaults is a Good Thing, because it looks pretty broken to me.
2329 if (power_level >= 2 && you.level_type == LEVEL_DUNGEON
2330 && crawl_state.game_standard_levelgen())
2332 // Generate a portal to something.
2333 const map_def *map = random_map_for_tag("trowel_portal");
2334 if (!map)
2336 mpr("A buggy portal flickers into view, then vanishes.");
2338 else
2341 no_messages n;
2342 dgn_safe_place_map(map, true, true, you.pos());
2344 mpr("A mystic portal forms.");
2346 done_stuff = true;
2348 else if (power_level == 1)
2350 if (coinflip())
2352 // Create a random bad statue and a friendly, timed golem.
2353 // This could be really bad, because they're placed adjacent
2354 // to you...
2355 int num_made = 0;
2357 const monster_type statues[] = {
2358 MONS_ORANGE_STATUE, MONS_SILVER_STATUE, MONS_ICE_STATUE
2361 if (create_monster(
2362 mgen_data::hostile_at(
2363 RANDOM_ELEMENT(statues), "the Trowel card",
2364 true, 0, 0, you.pos())) != -1)
2366 mpr("A menacing statue appears!");
2367 num_made++;
2370 const monster_type golems[] = {
2371 MONS_CLAY_GOLEM, MONS_WOOD_GOLEM, MONS_STONE_GOLEM,
2372 MONS_IRON_GOLEM, MONS_CRYSTAL_GOLEM, MONS_TOENAIL_GOLEM
2375 if (create_monster(
2376 mgen_data(RANDOM_ELEMENT(golems),
2377 BEH_FRIENDLY, &you, 5, 0,
2378 you.pos(), MHITYOU)) != -1)
2380 mpr("You construct a golem!");
2381 num_made++;
2384 if (num_made == 2)
2385 mpr("The constructs glare at each other.");
2387 done_stuff = (num_made > 0);
2389 else
2391 // Do-nothing (effectively): create a cosmetic feature
2392 const coord_def pos = pick_adjacent_free_square(you.pos());
2393 if (in_bounds(pos))
2395 const dungeon_feature_type statfeat[] = {
2396 DNGN_GRANITE_STATUE, DNGN_ORCISH_IDOL
2398 // We leave the items on the square
2399 grd(pos) = RANDOM_ELEMENT(statfeat);
2400 mpr("A statue takes form beside you.");
2401 done_stuff = true;
2405 else
2407 // Generate an altar.
2408 if (grd(you.pos()) == DNGN_FLOOR)
2410 // Might get GOD_NO_GOD and no altar.
2411 god_type rgod = static_cast<god_type>(random2(NUM_GODS));
2413 if (rgod == GOD_JIYVA && jiyva_is_dead())
2414 rgod = GOD_NO_GOD;
2416 grd(you.pos()) = altar_for_god(rgod);
2418 if (grd(you.pos()) != DNGN_FLOOR)
2420 done_stuff = true;
2421 mprf("An altar to %s grows from the floor before you!",
2422 god_name(rgod).c_str());
2427 if (!done_stuff)
2428 canned_msg(MSG_NOTHING_HAPPENS);
2430 return (done_stuff);
2433 static void _genie_card(int power, deck_rarity_type rarity)
2435 if (coinflip())
2437 mpr("A genie takes form and thunders: "
2438 "\"Choose your reward, mortal!\"");
2439 more();
2440 acquirement(OBJ_RANDOM, AQ_CARD_GENIE);
2442 else
2444 mpr("A genie takes form and thunders: "
2445 "\"You disturbed me, fool!\"");
2446 potion_effect(coinflip() ? POT_DEGENERATION : POT_DECAY, 40);
2450 // Special case for *your* god, maybe?
2451 static void _godly_wrath()
2453 int tries = 100;
2454 while (tries-- > 0)
2456 god_type god = static_cast<god_type>(random2(NUM_GODS - 1) + 1);
2458 // Don't recursively make player draw from the Deck of Punishment.
2459 if (god == GOD_NEMELEX_XOBEH)
2460 continue;
2462 // Stop once we find a god willing to punish the player.
2463 if (divine_retribution(god))
2464 break;
2467 if (tries <= 0)
2468 mpr("You somehow manage to escape divine attention...");
2471 static void _curse_card(int power, deck_rarity_type rarity)
2473 const int power_level = get_power_level(power, rarity);
2475 mpr("You feel a malignant aura surround you.");
2476 if (power_level >= 2)
2478 // Curse (almost) everything + chance of decay.
2479 while (curse_an_item(one_chance_in(6), true) && !one_chance_in(1000))
2482 else if (power_level == 1)
2484 // Curse an average of four items.
2486 curse_an_item(false);
2487 while (!one_chance_in(4));
2489 else
2491 // Curse 1.5 items on average.
2492 curse_an_item(false);
2493 if (coinflip())
2494 curse_an_item(false);
2498 static void _crusade_card(int power, deck_rarity_type rarity)
2500 const int power_level = get_power_level(power, rarity);
2501 if (power_level >= 1)
2503 // A chance to convert opponents.
2504 for (monster_iterator mi(you.get_los()); mi; ++mi)
2506 if (mi->friendly()
2507 || mi->holiness() != MH_NATURAL
2508 || mons_is_unique(mi->type)
2509 || mons_immune_magic(*mi)
2510 || player_will_anger_monster(*mi))
2512 continue;
2515 // Note that this bypasses the magic resistance
2516 // (though not immunity) check. Specifically,
2517 // you can convert Killer Klowns this way.
2518 // Might be too good.
2519 if (mi->hit_dice * 35 < random2(power))
2521 simple_monster_message(*mi, " is converted.");
2523 if (one_chance_in(5 - power_level))
2525 mi->attitude = ATT_FRIENDLY;
2527 // If you worship a god that lets you recruit
2528 // permanent followers, or a god allied with one,
2529 // count this as a recruitment.
2530 if (is_good_god(you.religion)
2531 || you.religion == GOD_BEOGH
2532 && mons_genus(mi->type) == MONS_ORC
2533 && !mi->is_summoned()
2534 && !mi->is_shapeshifter())
2536 // Prevent assertion if the monster was
2537 // previously worshipping a different god,
2538 // rather than already worshipping your god or
2539 // being an atheist.
2540 mi->god = GOD_NO_GOD;
2542 mons_make_god_gift(*mi, is_good_god(you.religion) ?
2543 GOD_SHINING_ONE : GOD_BEOGH);
2546 else
2547 mi->add_ench(ENCH_CHARM);
2548 mons_att_changed(*mi);
2552 abjuration(power/4);
2555 static void _summon_demon_card(int power, deck_rarity_type rarity)
2557 const int power_level = get_power_level(power, rarity);
2558 demon_class_type dct;
2559 if (power_level >= 2)
2560 dct = DEMON_GREATER;
2561 else if (power_level == 1)
2562 dct = DEMON_COMMON;
2563 else
2564 dct = DEMON_LESSER;
2566 // FIXME: The manual testing for message printing is there because
2567 // we can't rely on create_monster() to do it for us. This is
2568 // because if you are completely surrounded by walls, create_monster()
2569 // will never manage to give a position which isn't (-1,-1)
2570 // and thus not print the message.
2571 // This hack appears later in this file as well.
2572 if (create_monster(
2573 mgen_data(summon_any_demon(dct), BEH_FRIENDLY, &you,
2574 std::min(power/50 + 1, 6), 0,
2575 you.pos(), MHITYOU),
2576 false) == -1)
2578 mpr("You see a puff of smoke.");
2582 static void _summon_any_monster(int power, deck_rarity_type rarity)
2584 const int power_level = get_power_level(power, rarity);
2585 monster_type mon_chosen = NUM_MONSTERS;
2586 coord_def chosen_spot;
2587 int num_tries;
2589 if (power_level == 0)
2590 num_tries = 1;
2591 else if (power_level == 1)
2592 num_tries = 4;
2593 else
2594 num_tries = 18;
2596 for (int i = 0; i < num_tries; ++i)
2598 int dx, dy;
2601 dx = random2(3) - 1;
2602 dy = random2(3) - 1;
2604 while (dx == 0 && dy == 0);
2606 coord_def delta(dx,dy);
2608 monster_type cur_try;
2611 cur_try = random_monster_at_grid(you.pos() + delta);
2613 while (mons_is_unique(cur_try));
2615 if (mon_chosen == NUM_MONSTERS
2616 || mons_power(mon_chosen) < mons_power(cur_try))
2618 mon_chosen = cur_try;
2619 chosen_spot = you.pos();
2623 if (mon_chosen == NUM_MONSTERS) // Should never happen.
2624 return;
2626 const bool friendly = (power_level > 0 || !one_chance_in(4));
2628 if (create_monster(mgen_data(mon_chosen,
2629 friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
2630 3, 0, chosen_spot, MHITYOU),
2631 false) == -1)
2633 mpr("You see a puff of smoke.");
2637 static void _summon_dancing_weapon(int power, deck_rarity_type rarity)
2639 const int power_level = get_power_level(power, rarity);
2640 const bool friendly = (power_level > 0 || !one_chance_in(4));
2642 const int mon =
2643 create_monster(
2644 mgen_data(MONS_DANCING_WEAPON,
2645 friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
2646 power_level + 3, 0, you.pos(), MHITYOU),
2647 false);
2649 // Given the abundance of Nemelex decks, not setting hard reset
2650 // leaves a trail of weapons behind, most of which just get
2651 // offered to Nemelex again, adding an unnecessary source of
2652 // piety.
2653 if (mon != -1)
2655 // Override the weapon.
2656 ASSERT(menv[mon].weapon() != NULL);
2657 item_def& wpn(*menv[mon].weapon());
2659 // FIXME: Mega-hack (breaks encapsulation too).
2660 wpn.flags &= ~ISFLAG_RACIAL_MASK;
2662 if (power_level == 0)
2664 // Wimpy, negative-enchantment weapon.
2665 wpn.plus = -random2(4);
2666 wpn.plus2 = -random2(4);
2667 wpn.sub_type = (coinflip() ? WPN_DAGGER : WPN_CLUB);
2669 set_item_ego_type(wpn, OBJ_WEAPONS, SPWPN_NORMAL);
2671 else if (power_level == 1)
2673 // This is getting good.
2674 wpn.plus = random2(4) - 1;
2675 wpn.plus2 = random2(4) - 1;
2676 wpn.sub_type = (coinflip() ? WPN_LONG_SWORD : WPN_HAND_AXE);
2678 if (coinflip())
2680 set_item_ego_type(wpn, OBJ_WEAPONS,
2681 coinflip() ? SPWPN_FLAMING : SPWPN_FREEZING);
2683 else
2684 set_item_ego_type(wpn, OBJ_WEAPONS, SPWPN_NORMAL);
2686 else if (power_level == 2)
2688 // Rare and powerful.
2689 wpn.plus = random2(4) + 2;
2690 wpn.plus2 = random2(4) + 2;
2691 wpn.sub_type = (coinflip() ? WPN_KATANA : WPN_EXECUTIONERS_AXE);
2693 set_item_ego_type(wpn, OBJ_WEAPONS,
2694 coinflip() ? SPWPN_SPEED : SPWPN_ELECTROCUTION);
2697 item_colour(wpn);
2699 menv[mon].flags |= MF_HARD_RESET;
2701 ghost_demon newstats;
2702 newstats.init_dancing_weapon(wpn, power / 4);
2704 menv[mon].set_ghost(newstats);
2705 menv[mon].dancing_weapon_init();
2707 else
2708 mpr("You see a puff of smoke.");
2711 static void _summon_flying(int power, deck_rarity_type rarity)
2713 const int power_level = get_power_level(power, rarity);
2714 const bool friendly = (power_level > 0 || !one_chance_in(4));
2716 const monster_type flytypes[] = {
2717 MONS_BUTTERFLY, MONS_BUMBLEBEE, MONS_INSUBSTANTIAL_WISP,
2718 MONS_VAPOUR, MONS_YELLOW_WASP, MONS_RED_WASP
2721 // Choose what kind of monster.
2722 // Be nice and don't summon friendly invisibles.
2723 monster_type result = MONS_PROGRAM_BUG;
2725 result = flytypes[random2(4) + power_level];
2726 while (friendly && mons_class_flag(result, M_INVIS)
2727 && !you.can_see_invisible());
2729 for (int i = 0; i < power_level * 5 + 2; ++i)
2731 create_monster(
2732 mgen_data(result,
2733 friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
2734 std::min(power/50 + 1, 6), 0,
2735 you.pos(), MHITYOU));
2738 if (mons_class_flag(result, M_INVIS) && !you.can_see_invisible()
2739 && !friendly)
2741 mpr("Whatever you just summoned cannot be friendly.");
2745 static void _summon_skeleton(int power, deck_rarity_type rarity)
2747 const int power_level = get_power_level(power, rarity);
2748 const bool friendly = (power_level > 0 || !one_chance_in(4));
2749 const monster_type skeltypes[] = {
2750 MONS_SKELETON_LARGE, MONS_SKELETAL_WARRIOR, MONS_BONE_DRAGON
2753 if (create_monster(mgen_data(skeltypes[power_level],
2754 friendly ? BEH_FRIENDLY : BEH_HOSTILE, &you,
2755 std::min(power/50 + 1, 6), 0,
2756 you.pos(), MHITYOU),
2757 false) == -1)
2759 mpr("You see a puff of smoke.");
2763 static void _summon_ugly(int power, deck_rarity_type rarity)
2765 const int power_level = get_power_level(power, rarity);
2766 const bool friendly = (power_level > 0 || !one_chance_in(4));
2767 monster_type ugly;
2768 if (power_level >= 2)
2769 ugly = MONS_VERY_UGLY_THING;
2770 else if (power_level == 1)
2771 ugly = coinflip() ? MONS_VERY_UGLY_THING : MONS_UGLY_THING;
2772 else
2773 ugly = MONS_UGLY_THING;
2775 if (create_monster(mgen_data(ugly,
2776 friendly ? BEH_FRIENDLY : BEH_HOSTILE,
2777 &you,
2778 std::min(power/50 + 1, 6), 0,
2779 you.pos(), MHITYOU),
2780 false) == -1)
2782 mpr("You see a puff of smoke.");
2786 static int _card_power(deck_rarity_type rarity)
2788 int result = 0;
2790 if (you.penance[GOD_NEMELEX_XOBEH])
2792 result -= you.penance[GOD_NEMELEX_XOBEH];
2794 else if (you.religion == GOD_NEMELEX_XOBEH)
2796 result = you.piety;
2797 result *= (you.skills[SK_EVOCATIONS] + 25);
2798 result /= 27;
2801 result += you.skills[SK_EVOCATIONS] * 9;
2802 if (rarity == DECK_RARITY_RARE)
2803 result += 150;
2804 else if (rarity == DECK_RARITY_LEGENDARY)
2805 result += 300;
2807 if (result < 0)
2808 result = 0;
2810 return (result);
2813 bool card_effect(card_type which_card, deck_rarity_type rarity,
2814 uint8_t flags, bool tell_card)
2816 ASSERT(!_card_forbidden(which_card));
2818 bool rc = true;
2819 const int power = _card_power(rarity);
2821 const god_type god =
2822 (crawl_state.is_god_acting()) ? crawl_state.which_god_acting()
2823 : GOD_NO_GOD;
2825 #ifdef DEBUG_DIAGNOSTICS
2826 msg::streams(MSGCH_DIAGNOSTICS) << "Card power: " << power
2827 << ", rarity: " << static_cast<int>(rarity)
2828 << std::endl;
2829 #endif
2831 if (tell_card)
2833 // These card types will usually give this message in the targeting
2834 // prompt, and the cases where they don't are handled specially.
2835 if (which_card != CARD_VITRIOL && which_card != CARD_FLAME
2836 && which_card != CARD_FROST && which_card != CARD_HAMMER
2837 && which_card != CARD_SPARK && which_card != CARD_PAIN
2838 && which_card != CARD_VENOM)
2840 mprf("You have drawn %s.", card_name(which_card));
2844 if (which_card == CARD_XOM && !crawl_state.is_god_acting())
2846 if (you.religion == GOD_XOM)
2848 // Being a self-centered deity, Xom *always* finds this
2849 // maximally hilarious.
2850 god_speaks(GOD_XOM, "Xom roars with laughter!");
2851 you.gift_timeout = 255;
2853 else if (you.penance[GOD_XOM])
2854 god_speaks(GOD_XOM, "Xom laughs nastily.");
2857 switch (which_card)
2859 case CARD_PORTAL: _portal_card(power, rarity); break;
2860 case CARD_WARP: _warp_card(power, rarity); break;
2861 case CARD_SWAP: _swap_monster_card(power, rarity); break;
2862 case CARD_VELOCITY: _velocity_card(power, rarity); break;
2863 case CARD_DAMNATION: _damnation_card(power, rarity); break;
2864 case CARD_SOLITUDE: cast_dispersal(power/4); break;
2865 case CARD_ELIXIR: _elixir_card(power, rarity); break;
2866 case CARD_BATTLELUST: _battle_lust_card(power, rarity); break;
2867 case CARD_METAMORPHOSIS: _metamorphosis_card(power, rarity); break;
2868 case CARD_HELM: _helm_card(power, rarity); break;
2869 case CARD_BLADE: _blade_card(power, rarity); break;
2870 case CARD_SHADOW: _shadow_card(power, rarity); break;
2871 case CARD_POTION: _potion_card(power, rarity); break;
2872 case CARD_FOCUS: _focus_card(power, rarity); break;
2873 case CARD_SHUFFLE: _shuffle_card(power, rarity); break;
2874 case CARD_EXPERIENCE: _experience_card(power, rarity); break;
2875 case CARD_HELIX: _helix_card(power, rarity); break;
2876 case CARD_SAGE: sage_card(power, rarity); break;
2877 case CARD_WATER: _water_card(power, rarity); break;
2878 case CARD_GLASS: _glass_card(power, rarity); break;
2879 case CARD_DOWSING: _dowsing_card(power, rarity); break;
2880 case CARD_MINEFIELD: _minefield_card(power, rarity); break;
2881 case CARD_STAIRS: _stairs_card(power, rarity); break;
2882 case CARD_GENIE: _genie_card(power, rarity); break;
2883 case CARD_CURSE: _curse_card(power, rarity); break;
2884 case CARD_WARPWRIGHT: _warpwright_card(power, rarity); break;
2885 case CARD_FLIGHT: _flight_card(power, rarity); break;
2886 case CARD_TOMB: entomb(power); break;
2887 case CARD_WRAITH: drain_exp(false); lose_level(); break;
2888 case CARD_WRATH: _godly_wrath(); break;
2889 case CARD_CRUSADE: _crusade_card(power, rarity); break;
2890 case CARD_SUMMON_DEMON: _summon_demon_card(power, rarity); break;
2891 case CARD_SUMMON_ANIMAL: summon_animals(random2(power/3)); break;
2892 case CARD_SUMMON_ANY: _summon_any_monster(power, rarity); break;
2893 case CARD_SUMMON_WEAPON: _summon_dancing_weapon(power, rarity); break;
2894 case CARD_SUMMON_FLYING: _summon_flying(power, rarity); break;
2895 case CARD_SUMMON_SKELETON: _summon_skeleton(power, rarity); break;
2896 case CARD_SUMMON_UGLY: _summon_ugly(power, rarity); break;
2897 case CARD_XOM: xom_acts(5 + random2(power/10)); break;
2898 case CARD_TROWEL: rc = _trowel_card(power, rarity); break;
2899 case CARD_SPADE: your_spells(SPELL_DIG, random2(power/4), false); break;
2900 case CARD_BANSHEE: mass_enchantment(ENCH_FEAR, power, MHITYOU); break;
2901 case CARD_TORMENT: torment(TORMENT_CARDS, you.pos()); break;
2903 case CARD_VENOM:
2904 if (coinflip())
2906 mprf("You have drawn %s.", card_name(which_card));
2907 your_spells(SPELL_OLGREBS_TOXIC_RADIANCE, random2(power/4), false);
2909 else
2910 rc = _damaging_card(which_card, power, rarity);
2911 break;
2913 case CARD_VITRIOL:
2914 case CARD_FLAME:
2915 case CARD_FROST:
2916 case CARD_HAMMER:
2917 case CARD_SPARK:
2918 case CARD_PAIN:
2919 rc = _damaging_card(which_card, power, rarity);
2920 break;
2922 case CARD_BARGAIN:
2923 you.increase_duration(DUR_BARGAIN,
2924 random2(power) + random2(power) + 2);
2925 break;
2927 case CARD_MAP:
2928 if (!magic_mapping(random2(power/10) + 15, random2(power), true))
2929 mpr("The map is blank.");
2930 break;
2932 case CARD_WILD_MAGIC:
2933 // Yes, high power is bad here.
2934 MiscastEffect(&you, god == GOD_NO_GOD ? NON_MONSTER : -god,
2935 SPTYP_RANDOM, random2(power/15) + 5, random2(power),
2936 "a card of wild magic");
2937 break;
2939 case CARD_FAMINE:
2940 if (you.is_undead == US_UNDEAD)
2941 mpr("You feel rather smug.");
2942 else
2943 set_hunger(500, true);
2944 break;
2946 case CARD_FEAST:
2947 if (you.is_undead == US_UNDEAD)
2948 mpr("You feel a horrible emptiness.");
2949 else
2950 set_hunger(12000, true);
2951 break;
2953 case CARD_SWINE:
2954 if (!transform(1 + power/2 + random2(power/2), TRAN_PIG, true))
2956 mpr("You feel like a pig.");
2957 break;
2959 break;
2961 case NUM_CARDS:
2962 // The compiler will complain if any card remains unhandled.
2963 mpr("You have drawn a buggy card!");
2964 break;
2967 if (you.religion == GOD_XOM && !rc)
2969 god_speaks(GOD_XOM, "\"How boring, let's spice things up a little.\"");
2970 xom_acts(abs(you.piety - HALF_MAX_PIETY));
2973 if (you.religion == GOD_NEMELEX_XOBEH && !rc)
2974 simple_god_message(" seems disappointed in you.");
2976 return rc;
2979 bool top_card_is_known(const item_def &deck)
2981 if (!is_deck(deck))
2982 return (false);
2984 uint8_t flags;
2985 get_card_and_flags(deck, -1, flags);
2987 return (flags & CFLAG_MARKED);
2990 card_type top_card(const item_def &deck)
2992 if (!is_deck(deck))
2993 return (NUM_CARDS);
2995 uint8_t flags;
2996 card_type card = get_card_and_flags(deck, -1, flags);
2998 UNUSED(flags);
3000 return (card);
3003 bool is_deck(const item_def &item)
3005 return (item.base_type == OBJ_MISCELLANY
3006 && item.sub_type >= MISC_DECK_OF_ESCAPE
3007 && item.sub_type <= MISC_DECK_OF_DEFENCE);
3010 bool bad_deck(const item_def &item)
3012 if (!is_deck(item))
3013 return (false);
3015 return (!item.props.exists("cards")
3016 || item.props["cards"].get_type() != SV_VEC
3017 || item.props["cards"].get_vector().get_type() != SV_BYTE
3018 || cards_in_deck(item) == 0);
3021 deck_rarity_type deck_rarity(const item_def &item)
3023 ASSERT(is_deck(item));
3025 return static_cast<deck_rarity_type>(item.special);
3028 uint8_t deck_rarity_to_color(deck_rarity_type rarity)
3030 switch (rarity)
3032 case DECK_RARITY_COMMON:
3034 const uint8_t colours[] = {LIGHTBLUE, GREEN, CYAN, RED};
3035 return RANDOM_ELEMENT(colours);
3038 case DECK_RARITY_RARE:
3039 return (coinflip() ? MAGENTA : BROWN);
3041 case DECK_RARITY_LEGENDARY:
3042 return LIGHTMAGENTA;
3045 return (WHITE);
3048 void init_deck(item_def &item)
3050 CrawlHashTable &props = item.props;
3052 ASSERT(is_deck(item));
3053 ASSERT(!props.exists("cards"));
3054 ASSERT(item.plus > 0);
3055 ASSERT(item.plus <= 127);
3056 ASSERT(item.special >= DECK_RARITY_COMMON
3057 && item.special <= DECK_RARITY_LEGENDARY);
3059 const store_flags fl = SFLAG_CONST_TYPE;
3061 props["cards"].new_vector(SV_BYTE, fl).resize((vec_size)item.plus);
3062 props["card_flags"].new_vector(SV_BYTE, fl).resize((vec_size)item.plus);
3063 props["drawn_cards"].new_vector(SV_BYTE, fl);
3065 for (int i = 0; i < item.plus; ++i)
3067 bool was_odd = false;
3068 card_type card = _random_card(item, was_odd);
3070 uint8_t flags = 0;
3071 if (was_odd)
3072 flags = CFLAG_ODDITY;
3074 _set_card_and_flags(item, i, card, flags);
3077 ASSERT(cards_in_deck(item) == item.plus);
3079 props["num_marked"] = (char) 0;
3080 props["non_brownie_draws"] = (char) 0;
3082 props.assert_validity();
3084 item.plus2 = 0;
3085 item.colour = deck_rarity_to_color((deck_rarity_type) item.special);
3088 static void _unmark_deck(item_def& deck)
3090 if (!is_deck(deck))
3091 return;
3093 CrawlHashTable &props = deck.props;
3094 if (!props.exists("card_flags"))
3095 return;
3097 CrawlVector &flags = props["card_flags"].get_vector();
3099 for (unsigned int i = 0; i < flags.size(); ++i)
3101 flags[i] =
3102 static_cast<char>((static_cast<char>(flags[i]) & ~CFLAG_MARKED));
3105 // We'll be mean and leave non_brownie_draws as-is.
3106 props["num_marked"] = static_cast<char>(0);
3109 static void _unmark_and_shuffle_deck(item_def& deck)
3111 if (is_deck(deck))
3113 _unmark_deck(deck);
3114 _shuffle_deck(deck);
3118 void shuffle_all_decks_on_level()
3120 for (int i = 0; i < MAX_ITEMS; ++i)
3122 item_def& item(mitm[i]);
3123 if (item.defined() && is_deck(item))
3125 #ifdef DEBUG_DIAGNOSTICS
3126 mprf(MSGCH_DIAGNOSTICS, "Shuffling: %s on level %d, branch %d",
3127 item.name(DESC_PLAIN).c_str(),
3128 static_cast<int>(you.absdepth0),
3129 static_cast<int>(you.where_are_you));
3130 #endif
3131 _unmark_and_shuffle_deck(item);
3136 static bool _shuffle_inventory_decks()
3138 bool success = false;
3140 for (int i = 0; i < ENDOFPACK; ++i)
3142 item_def& item(you.inv[i]);
3143 if (item.defined() && is_deck(item))
3145 #ifdef DEBUG_DIAGNOSTICS
3146 mprf(MSGCH_DIAGNOSTICS, "Shuffling in inventory: %s",
3147 item.name(DESC_PLAIN).c_str());
3148 #endif
3149 _unmark_and_shuffle_deck(item);
3151 success = true;
3155 return success;
3158 void nemelex_shuffle_decks()
3160 add_daction(DACT_SHUFFLE_DECKS);
3161 _shuffle_inventory_decks();
3163 // Wildly inaccurate, but of similar quality as the old code which
3164 // was triggered by the presence of any deck anywhere.
3165 if (you.num_total_gifts[GOD_NEMELEX_XOBEH])
3166 god_speaks(GOD_NEMELEX_XOBEH, "You hear Nemelex Xobeh chuckle.");