3 * Summary: Functions with decks of cards.
20 #include "dgn-actions.h"
38 #include "mon-place.h"
40 #include "mgen_data.h"
42 #include "mon-stuff.h"
47 #include "player-stats.h"
49 #include "godconduct.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"
60 #include "spl-wpnench.h"
64 #include "transform.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
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
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} },
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} },
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} },
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} },
136 const deck_archetype deck_of_enchantments
[] = {
137 { CARD_ELIXIR
, {5, 5, 5} },
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} },
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} },
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} },
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} },
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} },
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())
212 case CARD_WARPWRIGHT
:
215 case CARD_MINEFIELD
: // with teleport taken away, might be acceptable
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
,
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.
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
,
278 CrawlHashTable
&props
= deck
.props
;
279 CrawlVector
&cards
= props
["cards"].get_vector();
280 CrawlVector
&flags
= props
["card_flags"].get_vector();
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
)
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
;
359 case MISC_DECK_OF_ESCAPE
:
360 pdeck
= (coinflip() ? deck_of_transport
: deck_of_emergency
);
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
:
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;
378 case MISC_DECK_OF_CHANGES
:
381 case 0: pdeck
= deck_of_battle
; break;
382 case 1: pdeck
= deck_of_dungeons
; break;
383 case 2: pdeck
= deck_of_wonders
; break;
386 case MISC_DECK_OF_DEFENCE
:
387 pdeck
= (coinflip() ? deck_of_emergency
: deck_of_battle
);
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.
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
))
412 totalweight
+= cww
.weight
[rarity
];
413 if (x_chance_in_y(cww
.weight
[rarity
], totalweight
))
419 static card_type
_random_card(uint8_t deck_type
, deck_rarity_type rarity
,
422 const deck_archetype
*pdeck
= _random_sub_deck(deck_type
);
424 if (one_chance_in(100))
426 pdeck
= deck_of_oddities
;
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
,
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
);
456 if (_flags
& CFLAG_MARKED
)
457 mprf("You draw %s.", card_name(card
));
459 mprf("You draw a card... It is %s.", card_name(card
));
461 _check_odd_card(_flags
);
467 static void _push_top_card(item_def
& deck
, card_type card
,
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
)))
490 const std::vector
<card_type
> get_drawn_cards(const item_def
& deck
)
492 std::vector
<card_type
> result
;
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
));
506 static bool _check_buggy_deck(item_def
& deck
)
508 std::ostream
& strm
= msg::streams(MSGCH_DIAGNOSTICS
);
511 crawl_state
.zero_turns_taken();
512 strm
<< "This isn't a deck at all!" << std::endl
;
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.";
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.";
540 cards_left
= deck
.plus
- deck
.plus2
;
542 cards_left
= -deck
.plus
;
546 strm
<< " But there should have been " << cards_left
552 << "A swarm of software bugs snatches the deck from you "
553 "and whisks it away."
556 if (deck
.link
== you
.equip
[EQ_WEAPON
])
559 dec_inv_item_quantity(deck
.link
, 1);
560 did_god_conduct(DID_CARDS
, 1);
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
)
590 if (_flags
& CFLAG_MARKED
)
597 strm
<< num_buggy
<< " buggy cards found in the deck, discarding them."
600 deck
.plus2
+= num_buggy
;
602 num_cards
= cards
.size();
603 num_flags
= cards
.size();
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
])
619 dec_inv_item_quantity(deck
.link
, 1);
620 did_god_conduct(DID_CARDS
, 1);
625 if (num_cards
> deck
.plus
)
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
;
633 strm
<< "Deck has more cards than it was created with?"
637 deck
.plus
= num_cards
;
641 if (num_cards
> num_flags
)
644 strm
<< (num_cards
- num_flags
) << " more cards than flags.";
646 strm
<< "More cards than flags.";
649 for (unsigned int i
= num_flags
+ 1; i
<= num_cards
; ++i
)
650 flags
[i
] = static_cast<char>(0);
654 else if (num_flags
> num_cards
)
657 strm
<< (num_cards
- num_flags
) << " more cards than flags.";
659 strm
<< "More cards than flags.";
663 for (unsigned int i
= num_flags
; i
> num_cards
; --i
)
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
);
675 else if (props
["num_marked"].get_byte() != static_cast<char>(num_marked
))
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()));
683 strm
<< "Oops, book-keeping on marked cards is wrong.";
687 props
["num_marked"] = static_cast<char>(num_marked
);
693 if (deck
.plus
!= (deck
.plus2
+ static_cast<long>(num_cards
)))
696 strm
<< "Have you used " << deck
.plus2
<< " cards, or "
697 << (deck
.plus
- num_cards
) << "? Oops.";
699 strm
<< "Oops, book-keeping on used cards is wrong.";
702 deck
.plus2
= deck
.plus
- num_cards
;
708 if (-deck
.plus2
!= static_cast<long>(num_cards
))
711 strm
<< "There are " << num_cards
<< " cards left, not "
712 << (-deck
.plus2
) << ". Oops.";
714 strm
<< "Oops, book-keeping on cards left is wrong.";
717 deck
.plus2
= -num_cards
;
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();
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
,
744 if (prompt_failed(slot
))
747 if (!is_deck(you
.inv
[slot
]))
749 mpr("That isn't a deck!");
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?");
763 crawl_state
.zero_turns_taken();
767 evoke_deck(you
.inv
[slot
]);
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
)
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.)
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
);
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.
804 const int slot
= _choose_inventory_deck("Peek at which deck?");
807 crawl_state
.zero_turns_taken();
810 item_def
& deck(you
.inv
[slot
]);
812 if (_check_buggy_deck(deck
))
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
);
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"]++;
836 you
.wield_change
= true;
841 card2
= get_card_and_flags(deck
, 1, flags2
);
843 int already_seen
= 0;
844 if (flags1
& CFLAG_SEEN
)
846 if (flags2
& CFLAG_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.");
862 // Peeking identifies the deck.
865 you
.wield_change
= 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.
876 const int slot
= _choose_inventory_deck("Mark which deck?");
879 crawl_state
.zero_turns_taken();
882 item_def
& deck(you
.inv
[slot
]);
883 if (_check_buggy_deck(deck
))
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();
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
);
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);
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
)
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
;
931 else if (num_cards
< 4)
933 mprf("You shuffle the deck.");
934 deck
.plus2
= -num_cards
;
937 mprf("You shuffle the cards back into the deck.");
941 you
.wield_change
= 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
)
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");
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())
975 formatted_string fs
= formatted_string::parse_string(data
.str());
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.
987 const int slot
= _choose_inventory_deck("Stack which deck?");
990 crawl_state
.zero_turns_taken();
994 item_def
& deck(you
.inv
[slot
]);
995 if (_check_buggy_deck(deck
))
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();
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
)
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.
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.");
1033 mprf("You draw the first five cards out of %d and discard the rest.",
1038 if (draws
.size() > 1)
1040 bool need_prompt_redraw
= true;
1041 unsigned int selected
= draws
.size();
1044 if (need_prompt_redraw
)
1049 cprintf("Press a digit to select a card, then another digit "
1052 cprintf("Press ? for the card descriptions, or Enter to "
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();
1064 textcolor(LIGHTGREY
);
1065 cprintf("Are you sure? (press y or Y to confirm)");
1066 if (toupper(getch()) == 'Y')
1070 clear_to_end_of_line();
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();
1089 selected
= new_selected
;
1091 _redraw_stacked_cards(draws
, selected
);
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
);
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?");
1118 crawl_state
.zero_turns_taken();
1122 item_def
& deck(you
.inv
[slot
]);
1124 if (_check_buggy_deck(deck
))
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.
1136 // Only one card to draw, so just draw it.
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
)
1148 card_type card
= _draw_top_card(deck
, false, _flags
);
1150 draws
.push_back(card
);
1151 flags
.push_back(_flags
);
1155 bool need_prompt_redraw
= 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());
1171 _describe_cards(draws
);
1172 need_prompt_redraw
= true;
1174 else if (keyin
>= 'a' && keyin
< 'a' + num_to_draw
)
1176 selected
= keyin
- 'a';
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);
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
])
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);
1221 // This is Nemelex retribution.
1222 void draw_from_deck_of_punishment()
1225 card_type card
= _random_card(MISC_DECK_OF_PUNISHMENT
, DECK_RARITY_COMMON
,
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
,
1237 if (!item_type_known(deck
))
1239 // Expecting one type of card but got another, real funny.
1240 else if (flags
& CFLAG_ODDITY
)
1243 if (player_in_a_dangerous_place())
1249 // Handled elsewhere
1253 case CARD_DAMNATION
:
1254 // Nothing happened, boring.
1255 if (you
.level_type
!= LEVEL_DUNGEON
)
1259 case CARD_MINEFIELD
:
1263 // Always hilarious.
1273 void evoke_deck(item_def
& deck
)
1275 if (_check_buggy_deck(deck
))
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
;
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
)
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
])
1296 if ((flags
& (CFLAG_MARKED
| CFLAG_SEEN
))
1297 || props
["num_marked"].get_byte() > 0)
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"]--;
1326 props
["non_brownie_draws"]--;
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);
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.
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
1353 xom_is_stimulated(amusement
);
1355 // Nemelex likes gamblers.
1359 if (one_chance_in(3))
1363 // You can't ID off a marked card
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
)
1377 did_god_conduct(DID_CARDS
, brownie_points
);
1379 // Always wield change, since the number of cards used/left has
1381 you
.wield_change
= true;
1384 int get_power_level(int power
, deck_rarity_type rarity
)
1386 int power_level
= 0;
1389 case DECK_RARITY_COMMON
:
1391 case DECK_RARITY_LEGENDARY
:
1392 if (x_chance_in_y(power
, 500))
1394 // deliberate fall-through
1395 case DECK_RARITY_RARE
:
1396 if (x_chance_in_y(power
, 700))
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)
1414 else if (control_level
== 1)
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.
1432 you_teleport_now(true);
1437 static void _warp_card(int power
, deck_rarity_type rarity
)
1439 if (item_blocks_teleport(true, true))
1441 canned_msg(MSG_STRANGE_STASIS
);
1445 const int control_level
= get_power_level(power
, rarity
);
1446 if (control_level
>= 2)
1448 else if (control_level
== 1)
1449 cast_semi_controlled_blink(power
/ 4);
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);
1460 mpr("You spin around.");
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));
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
);
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
)
1505 if (!mon_to_banish
) // Banish yourself!
1507 banished(DNGN_ENTER_ABYSS
, "drawing a card");
1508 break; // Don't banish anything 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.");
1526 for (adjacent_iterator
ai(you
.pos()); ai
; ++ai
)
1527 if (grd(*ai
) == DNGN_FLOOR
&& !find_trap(*ai
) && one_chance_in(++count
))
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
,
1553 // Oops, something went wrong here (either because of cursed
1554 // equipment or the possibility of stat loss).
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);
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())
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
;
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
)
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;
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.");
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);
1644 static int _drain_monsters(coord_def where
, int pow
, int, actor
*)
1646 if (where
== you
.pos())
1650 monster
* mon
= monster_at(where
);
1654 if (!mon
->drain_exp(&you
, false, pow
/ 50))
1655 simple_monster_message(mon
, " is unaffected.");
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
);
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
,
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
};
1688 ztype
= (one_chance_in(3) ? ZAP_DEGENERATION
: ZAP_BREATHE_ACID
);
1692 ztype
= (coinflip() ? ZAP_FIREBALL
: firezaps
[power_level
]);
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;
1701 if (power_level
== 2)
1703 mprf("You have drawn %s.", card_name(card
));
1708 ztype
= painzaps
[power_level
];
1715 std::string prompt
= "You have drawn ";
1716 prompt
+= card_name(card
);
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
);
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
)
1740 if (power_level
== 0)
1743 potion_effect(POT_HEAL_WOUNDS
, 40); // power doesn't matter
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
;
1789 trans
= one_chance_in(3) ? TRAN_SPIDER
:
1790 coinflip() ? TRAN_ICE_BEAST
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)
1825 do_phaseshift
= true;
1827 do_stoneskin
= true;
1831 cast_phase_shift(random2(power
/4));
1833 cast_stoneskin(random2(power
/4));
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
;
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.");
1875 // Pause before jumping to the list.
1876 if (Options
.auto_list
)
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));
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();
1903 mprf("%s vibrate%s crazily for a second.",
1904 wpn
->name(DESC_CAP_YOUR
).c_str(),
1905 wpn
->quantity
== 1 ? "s" : "");
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())
1966 const int worst_diff
= you
.max_stat(s
) - you
.max_stat(worst_stat
);
1967 if (worst_diff
< 0 || worst_diff
== 0 && coinflip())
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
);
1986 if (which_god
== GOD_XOM
)
1987 cause
= "the capriciousness of Xom";
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
);
2015 if (which_god
== GOD_XOM
)
2016 cause
= "the capriciousness of Xom";
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
;
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
;
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
;
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)
2080 mutate(RANDOM_MUTATION
);
2083 delete_mutation(RANDOM_MUTATION
);
2084 mutate(RANDOM_MUTATION
);
2087 delete_mutation(RANDOM_MUTATION
);
2091 else if (power_level
== 1)
2093 switch (how_mutated() ? random2(3) : 0)
2096 mutate(coinflip() ? RANDOM_GOOD_MUTATION
: RANDOM_MUTATION
);
2100 _remove_bad_mutation();
2102 delete_mutation(RANDOM_MUTATION
);
2109 _remove_bad_mutation();
2110 mutate(RANDOM_MUTATION
);
2114 delete_mutation(RANDOM_MUTATION
);
2115 mutate(RANDOM_GOOD_MUTATION
);
2120 delete_mutation(RANDOM_MUTATION
);
2121 mutate(RANDOM_MUTATION
);
2131 _remove_bad_mutation();
2134 mutate(RANDOM_GOOD_MUTATION
);
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
);
2146 delete_mutation(RANDOM_MUTATION
);
2147 mutate(RANDOM_GOOD_MUTATION
);
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)
2160 else if (power_level
== 1)
2161 c
= random2(10) + 1;
2165 // FIXME: yet another reproduction of random_choose_weighted
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
)
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
))
2186 if (result
== SK_NONE
)
2187 mpr("You feel omnipotent."); // All skills maxed.
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
;
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
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);
2259 mpr("Water floods your area!");
2261 // Flood all visible squares.
2262 for (radius_iterator
ri(you
.pos(), LOS_RADIUS
, false); ri
; ++ri
)
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
,
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.");
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");
2336 mpr("A buggy portal flickers into view, then vanishes.");
2342 dgn_safe_place_map(map
, true, true, you
.pos());
2344 mpr("A mystic portal forms.");
2348 else if (power_level
== 1)
2352 // Create a random bad statue and a friendly, timed golem.
2353 // This could be really bad, because they're placed adjacent
2357 const monster_type statues
[] = {
2358 MONS_ORANGE_STATUE
, MONS_SILVER_STATUE
, MONS_ICE_STATUE
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!");
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
2376 mgen_data(RANDOM_ELEMENT(golems
),
2377 BEH_FRIENDLY
, &you
, 5, 0,
2378 you
.pos(), MHITYOU
)) != -1)
2380 mpr("You construct a golem!");
2385 mpr("The constructs glare at each other.");
2387 done_stuff
= (num_made
> 0);
2391 // Do-nothing (effectively): create a cosmetic feature
2392 const coord_def pos
= pick_adjacent_free_square(you
.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.");
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())
2416 grd(you
.pos()) = altar_for_god(rgod
);
2418 if (grd(you
.pos()) != DNGN_FLOOR
)
2421 mprf("An altar to %s grows from the floor before you!",
2422 god_name(rgod
).c_str());
2428 canned_msg(MSG_NOTHING_HAPPENS
);
2430 return (done_stuff
);
2433 static void _genie_card(int power
, deck_rarity_type rarity
)
2437 mpr("A genie takes form and thunders: "
2438 "\"Choose your reward, mortal!\"");
2440 acquirement(OBJ_RANDOM
, AQ_CARD_GENIE
);
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()
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
)
2462 // Stop once we find a god willing to punish the player.
2463 if (divine_retribution(god
))
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));
2491 // Curse 1.5 items on average.
2492 curse_an_item(false);
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
)
2507 || mi
->holiness() != MH_NATURAL
2508 || mons_is_unique(mi
->type
)
2509 || mons_immune_magic(*mi
)
2510 || player_will_anger_monster(*mi
))
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
);
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)
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.
2573 mgen_data(summon_any_demon(dct
), BEH_FRIENDLY
, &you
,
2574 std::min(power
/50 + 1, 6), 0,
2575 you
.pos(), MHITYOU
),
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
;
2589 if (power_level
== 0)
2591 else if (power_level
== 1)
2596 for (int i
= 0; i
< num_tries
; ++i
)
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.
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
),
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));
2644 mgen_data(MONS_DANCING_WEAPON
,
2645 friendly
? BEH_FRIENDLY
: BEH_HOSTILE
, &you
,
2646 power_level
+ 3, 0, you
.pos(), MHITYOU
),
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
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
);
2680 set_item_ego_type(wpn
, OBJ_WEAPONS
,
2681 coinflip() ? SPWPN_FLAMING
: SPWPN_FREEZING
);
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
);
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();
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
)
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()
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
),
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));
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
;
2773 ugly
= MONS_UGLY_THING
;
2775 if (create_monster(mgen_data(ugly
,
2776 friendly
? BEH_FRIENDLY
: BEH_HOSTILE
,
2778 std::min(power
/50 + 1, 6), 0,
2779 you
.pos(), MHITYOU
),
2782 mpr("You see a puff of smoke.");
2786 static int _card_power(deck_rarity_type rarity
)
2790 if (you
.penance
[GOD_NEMELEX_XOBEH
])
2792 result
-= you
.penance
[GOD_NEMELEX_XOBEH
];
2794 else if (you
.religion
== GOD_NEMELEX_XOBEH
)
2797 result
*= (you
.skills
[SK_EVOCATIONS
] + 25);
2801 result
+= you
.skills
[SK_EVOCATIONS
] * 9;
2802 if (rarity
== DECK_RARITY_RARE
)
2804 else if (rarity
== DECK_RARITY_LEGENDARY
)
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
));
2819 const int power
= _card_power(rarity
);
2821 const god_type god
=
2822 (crawl_state
.is_god_acting()) ? crawl_state
.which_god_acting()
2825 #ifdef DEBUG_DIAGNOSTICS
2826 msg::streams(MSGCH_DIAGNOSTICS
) << "Card power: " << power
2827 << ", rarity: " << static_cast<int>(rarity
)
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.");
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;
2906 mprf("You have drawn %s.", card_name(which_card
));
2907 your_spells(SPELL_OLGREBS_TOXIC_RADIANCE
, random2(power
/4), false);
2910 rc
= _damaging_card(which_card
, power
, rarity
);
2919 rc
= _damaging_card(which_card
, power
, rarity
);
2923 you
.increase_duration(DUR_BARGAIN
,
2924 random2(power
) + random2(power
) + 2);
2928 if (!magic_mapping(random2(power
/10) + 15, random2(power
), true))
2929 mpr("The map is blank.");
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");
2940 if (you
.is_undead
== US_UNDEAD
)
2941 mpr("You feel rather smug.");
2943 set_hunger(500, true);
2947 if (you
.is_undead
== US_UNDEAD
)
2948 mpr("You feel a horrible emptiness.");
2950 set_hunger(12000, true);
2954 if (!transform(1 + power
/2 + random2(power
/2), TRAN_PIG
, true))
2956 mpr("You feel like a pig.");
2962 // The compiler will complain if any card remains unhandled.
2963 mpr("You have drawn a buggy card!");
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.");
2979 bool top_card_is_known(const item_def
&deck
)
2985 get_card_and_flags(deck
, -1, flags
);
2987 return (flags
& CFLAG_MARKED
);
2990 card_type
top_card(const item_def
&deck
)
2996 card_type card
= get_card_and_flags(deck
, -1, flags
);
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
)
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
)
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
;
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
);
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();
3085 item
.colour
= deck_rarity_to_color((deck_rarity_type
) item
.special
);
3088 static void _unmark_deck(item_def
& deck
)
3093 CrawlHashTable
&props
= deck
.props
;
3094 if (!props
.exists("card_flags"))
3097 CrawlVector
&flags
= props
["card_flags"].get_vector();
3099 for (unsigned int i
= 0; i
< flags
.size(); ++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
)
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
));
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());
3149 _unmark_and_shuffle_deck(item
);
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.");