Many of the cards don't work yet (e.g., all Summoning cards); this will be fixed in the near future. Deck rarity, by the way, is encoded in its colour. Yuck - but I was out of bits in the item_def struct. Better ideas welcome.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1594 c06c8d41-db1a-0410-9941-cceddc491573
3KAINFIXO7WNWGUGZB43EUNFRS2ZPBLQZDTY456QACMRHYIJ7WDAC
KFZYPFHHOWRUZEK2PW26EI73Z6I6DLHW2YEJV2CB5XBWFRRNBFXQC
ILOED4VB4I6VPAUTR75ZWX6MXDYXB5DO2EDK2UH67O3HNKWV23RQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
APMT6XTVAD4ZCXCMUPTW5KCNR7TXW6W37SNYUP5A6NLFLXT3BCYQC
XRZPPYWPWUOM4SFNI6BHKH2UKJQNLKOV6Y7XIEPEZXE5QYRT26PAC
DTO3EUKWHZ5RJNGNCFYXSOVTIPVXPP637F2W7WFGYKJ7JK7VNKNQC
RR2J4VLJCZSAKY3HNS334KI4YUAPOMSETO2HGCGEEIUCUJAYAGSQC
H7BW6SEIQ57X6V4BM2RX54W42W6BH5XJBAS6FYCYKLQQG43ZMU4QC
VNHFP63ZLLZU3A3PLXP4BITX57DUIYDHFOHQYK3BOBHV3S64G26QC
CIPVRZGLOZHCERK6YPOBV3P2E4IAB4H6D5EHLRQE2O5E4P4VCBUAC
2ESKXYN266CEMLSL6DNCKG4REDO34FXL4ODVGMWDJTNJRKMXWCRQC
3XZOL3FFQZITUJIGDD6B6V6ZYMBN524JKNN6ZPJAXEC7RY433I3QC
QKGDOYIYKE6B36ION5O2DRW65DWWPZMYNWJVH7LJJ7FPGGM2MYAQC
2IJDLTWK74ULETLFTIPUIY2MSG6RNONVAFNFE7MADPT6UNYSSBDAC
X5WLJCJVW55SXZVP7IKP7ADCJIGNKN4PKAXFECVR6TNK7XSMZR7QC
TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC
GBUB77EAYHOFY6GQ5IY3ZSBC7FSQFZZKYNBD5QMCQFIKFLYLWHOQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
RYT42Z6CED4KV5CCJ45CHZ3DQGLFMDCVH6CSQZNXOILULDG4MXVQC
YCL3W2PFE6ILTGBFODCSXNPDIA46KVSZP2TI7HDMYAOEJT65RIEAC
int thing_created = NON_ITEM;
int gift_type = MISC_DECK_OF_TRICKS;
misc_item_type gift_type;
if ( random2(200) <= you.piety )
{
// make a pure deck
misc_item_type pure_decks[] = {
MISC_DECK_OF_ESCAPE,
MISC_DECK_OF_DESTRUCTION,
MISC_DECK_OF_DUNGEONS,
MISC_DECK_OF_SUMMONING,
MISC_DECK_OF_WONDERS
};
gift_type = pure_decks[random2(ARRAYSIZE(pure_decks))];
}
else
{
// make a mixed deck
misc_item_type mixed_decks[] = {
MISC_DECK_OF_WAR,
MISC_DECK_OF_CHANGES,
MISC_DECK_OF_DEFENSE
};
gift_type = mixed_decks[random2(ARRAYSIZE(mixed_decks))];
}
if (random2(200) <= you.piety && one_chance_in(4))
gift_type = MISC_DECK_OF_SUMMONINGS;
if (random2(200) <= you.piety && coinflip())
gift_type = MISC_DECK_OF_WONDERS;
if (random2(200) <= you.piety && one_chance_in(4))
gift_type = MISC_DECK_OF_POWER;
thing_created = items( 1, OBJ_MISCELLANY, gift_type,
true, 1, MAKE_ITEM_RANDOM_RACE );
int thing_created = items( 1, OBJ_MISCELLANY, gift_type,
true, 1, MAKE_ITEM_RANDOM_RACE );
// mv: others are possible but less often
// btw. chances of generating decks are almost the same as
// before, other chances are now distributed more steadily
|| (mitm[p].sub_type == MISC_DECK_OF_POWER && !one_chance_in(12))
|| (mitm[p].sub_type == MISC_DECK_OF_SUMMONINGS && !one_chance_in(3))
|| (mitm[p].sub_type == MISC_DECK_OF_TRICKS && !one_chance_in(3))
|| (mitm[p].sub_type == MISC_DECK_OF_WONDERS && !one_chance_in(3))
);
|| (mitm[p].sub_type == MISC_DECK_OF_PUNISHMENT)
// pure decks are rare in the dungeon
|| ((mitm[p].sub_type == MISC_DECK_OF_ESCAPE ||
mitm[p].sub_type == MISC_DECK_OF_DESTRUCTION ||
mitm[p].sub_type == MISC_DECK_OF_DUNGEONS ||
mitm[p].sub_type == MISC_DECK_OF_SUMMONING ||
mitm[p].sub_type == MISC_DECK_OF_WONDERS) &&
!one_chance_in(5)));
&& (item.sub_type == MISC_DECK_OF_TRICKS
|| item.sub_type == MISC_DECK_OF_SUMMONINGS
|| item.sub_type == MISC_DECK_OF_POWER
|| item.sub_type == MISC_DECK_OF_WONDERS);
&& (item.sub_type >= MISC_DECK_OF_ESCAPE &&
item.sub_type <= MISC_DECK_OF_DEFENSE);
}
deck_rarity_type deck_rarity(const item_def &item)
{
ASSERT( is_deck(item) );
switch (item.colour)
{
case BLACK: case BLUE: case GREEN: case CYAN: case RED:
default:
return DECK_RARITY_COMMON;
case MAGENTA: case BROWN:
return DECK_RARITY_RARE;
case LIGHTMAGENTA:
return DECK_RARITY_LEGENDARY;
}
case MISC_DECK_OF_POWER: return "deck of power";
case MISC_DECK_OF_SUMMONINGS: return "deck of summonings";
case MISC_DECK_OF_TRICKS: return "deck of tricks";
case MISC_DECK_OF_ESCAPE: return "deck of escape";
case MISC_DECK_OF_DESTRUCTION: return "deck of destruction";
case MISC_DECK_OF_DUNGEONS: return "deck of dungeons";
case MISC_DECK_OF_SUMMONING: return "deck of summonings";
break;
case MISC_DECK_OF_WONDERS:
case MISC_DECK_OF_SUMMONINGS:
case MISC_DECK_OF_TRICKS:
case MISC_DECK_OF_POWER:
evoke_deck(wpn);
pract = 1;
char redraw_hit_points;
char redraw_magic_points;
char redraw_strength;
char redraw_intelligence;
char redraw_dexterity;
char redraw_experience;
char redraw_armour_class;
bool redraw_hit_points;
bool redraw_magic_points;
bool redraw_strength;
bool redraw_intelligence;
bool redraw_dexterity;
bool redraw_experience;
bool redraw_armour_class;
BUILD_QUIT = -1, // all done, don't continue
BUILD_SKIP = 1, // skip further generation
BUILD_CONTINUE = 0 // continue generation
BUILD_QUIT = -1, // all done, don't continue
BUILD_SKIP = 1, // skip further generation
BUILD_CONTINUE = 0 // continue generation
CARD_BLANK = 0, // 0
CARD_BUTTERFLY,
CARD_WRAITH,
CARD_EXPERIENCE,
CARD_WEALTH,
CARD_INTELLIGENCE, // 5
CARD_STRENGTH,
CARD_QUICKSILVER,
CARD_STUPIDITY,
CARD_WEAKNESS,
CARD_SLOTH, // 10
CARD_BLANK = 0,
CARD_PORTAL, // "the mover"
CARD_WARP, // "the jumper"
CARD_SWAP, // "swap"
CARD_VELOCITY, // "the runner"
CARD_TOMB, // "the wall"
CARD_BANSHEE, // "the scream"
CARD_DAMNATION, // banishment
CARD_SOLITUDE, // dispersal
CARD_WARPWRIGHT, // create teleport trap
CARD_VITRIOL, // acid damage
CARD_FLAME, // fire damage
CARD_FROST, // cold damage
CARD_HAMMER, // pure damage
CARD_ELIXIR, // healing
CARD_BATTLELUST, // melee boosts
CARD_METAMORPHOSIS, // transformation
CARD_HELM, // defense
CARD_BLADE, // weapon boosts
CARD_SHADOW, // assassin skills
CARD_SUMMON_ANIMAL,
CARD_SUMMON_DEMON,
CARD_SUMMON_WEAPON,
CARD_SUMMON_ANY,
CARD_POTION,
CARD_FOCUS,
CARD_FREAK,
CARD_DEATH,
CARD_NORMALITY,
CARD_SHADOW, // 15
CARD_GATE,
CARD_STATUE,
CARD_ACQUISITION,
CARD_HASTEN,
CARD_DEMON_LESSER, // 20
CARD_DEMON_COMMON,
CARD_DEMON_GREATER,
CARD_DEMON_SWARM,
CARD_YAK,
CARD_FIEND, // 25
CARD_DRAGON,
CARD_GOLEM,
CARD_THING_FUGLY,
CARD_LICH,
CARD_HORROR_UNSEEN, // 30
CARD_BLINK,
CARD_TELEPORT,
CARD_TELEPORT_NOW,
CARD_RAGE,
CARD_LEVITY, // 35
CARD_VENOM,
CARD_EXPERIENCE,
CARD_WILD_MAGIC,
CARD_GENETIC_ENGINEER, // remove one *bad* mutation
CARD_MAP, // magic mapping
CARD_DOWSING, // detect SD/traps/items/monsters
CARD_SPADE, // dig
CARD_TROWEL, // create feature/vault
CARD_MINEFIELD, // plant traps
CARD_GENIE, // acquirement OR rotting/deterioration
CARD_BARGAIN, // shopping discount
CARD_WRATH, // Godly wrath
CARD_WRAITH, // drain XP
CARD_WILD_MAGIC,
CARD_VIOLENCE,
CARD_PROTECTION,
CARD_KNOWLEDGE, // 50
CARD_MAZE,
CARD_PANDEMONIUM,
CARD_IMPRISONMENT,
CARD_RULES_FOR_BRIDGE, // 54
NUM_CARDS, // must remain last regular member {dlb}
CARD_RANDOM = 255 // must remain final member {dlb}
CARD_FAMINE,
CARD_CURSE, // Curse your items
NUM_CARDS
"A deck of highly mysterious and magical cards. One may "
"draw a random card from it, but should be prepared to "
"suffer the possible consequences! ";
"A deck of magical cards, mainly dealing with various "
"forms of escape. Incautious use may lead to being "
"dumped from the frying pan into the fire! ";
break;
case MISC_DECK_OF_DESTRUCTION:
description +=
"A deck of magical cards, most of which hurl death "
"and destruction at one's foes (or, if unlucky, at oneself.) ";
case MISC_DECK_OF_SUMMONINGS:
case MISC_DECK_OF_DUNGEONS:
description +=
"A deck of magical cards which deal with shaping the "
"dungeon. Unlike most other decks, the cards from this deck "
"tend to be ignored by Nemelex, who prefers more amusing "
"pursuits. ";
break;
case MISC_DECK_OF_SUMMONING:
break;
case MISC_DECK_OF_WONDERS:
description +=
"A deck of highly mysterious and magical cards, which can "
"permanently alter the drawer's physical and mental "
"condition, for better or worse. ";
break;
case MISC_DECK_OF_PUNISHMENT:
description +=
"A deck of magical cards which wreak havoc on the user. ";
break;
case MISC_DECK_OF_WAR:
description +=
"A deck of magical cards which are useful before and during "
"battle. ";
break;
case MISC_DECK_OF_CHANGES:
description +=
"A deck of magical cards which induce changes in the user "
"or his environment. ";
break;
case MISC_DECK_OF_DEFENSE:
description +=
"A deck of magical cards, most of which defend the user "
"from harm in various ways. ";
case MISC_DECK_OF_TRICKS:
description +=
"A deck of magical cards, full of amusing tricks. ";
break;
case MISC_DECK_OF_POWER:
description += "A deck of powerful magical cards. ";
case NUM_MISCELLANY:
description += "A buggy miscellaneous item.";
static card_type deck_of_wonders[] =
{
CARD_BLANK,
CARD_BUTTERFLY,
CARD_WRAITH,
CARD_EXPERIENCE,
CARD_WEALTH,
CARD_INTELLIGENCE,
CARD_STRENGTH,
CARD_QUICKSILVER,
CARD_STUPIDITY,
CARD_WEAKNESS,
CARD_SLOTH,
CARD_SHUFFLE,
CARD_FREAK,
CARD_DEATH,
CARD_NORMALITY,
CARD_SHADOW,
CARD_GATE,
CARD_STATUE,
CARD_ACQUISITION,
CARD_HASTEN,
CARD_LICH,
CARD_XOM,
CARD_DECAY,
CARD_ALTAR,
CARD_FOUNTAIN,
CARD_MAZE,
CARD_PANDEMONIUM
#define VECFROM(x) (x), (x) + ARRAYSIZE(x)
#define DEFVEC(Z) static std::vector<card_type> Z(VECFROM(a_##Z))
static card_type a_deck_of_transport[] = {
CARD_PORTAL, CARD_WARP, CARD_SWAP, CARD_VELOCITY
static card_type deck_of_summoning[] =
{
CARD_STATUE,
CARD_DEMON_LESSER,
CARD_DEMON_COMMON,
CARD_DEMON_GREATER,
CARD_DEMON_SWARM,
CARD_YAK,
CARD_FIEND,
CARD_DRAGON,
CARD_GOLEM,
CARD_THING_FUGLY,
CARD_HORROR_UNSEEN
DEFVEC(deck_of_transport);
static card_type a_deck_of_emergency[] = {
CARD_TOMB, CARD_BANSHEE, CARD_DAMNATION, CARD_SOLITUDE, CARD_WARPWRIGHT
};
DEFVEC(deck_of_emergency);
static card_type a_deck_of_destruction[] = {
CARD_VITRIOL, CARD_FLAME, CARD_FROST, CARD_HAMMER
};
DEFVEC(deck_of_destruction);
static card_type a_deck_of_battle[] = {
CARD_ELIXIR, CARD_BATTLELUST, CARD_METAMORPHOSIS,
CARD_HELM, CARD_BLADE, CARD_SHADOW
};
DEFVEC(deck_of_battle);
static card_type a_deck_of_enchantments[] = {
CARD_ELIXIR
};
DEFVEC(deck_of_enchantments);
static card_type a_deck_of_summoning[] = {
CARD_SUMMON_ANIMAL, CARD_SUMMON_DEMON, CARD_SUMMON_WEAPON
static card_type deck_of_tricks[] =
{
CARD_BLANK,
CARD_BUTTERFLY,
CARD_BLINK,
CARD_TELEPORT,
CARD_TELEPORT_NOW,
CARD_RAGE,
CARD_LEVITY,
CARD_HEALING,
CARD_WILD_MAGIC,
CARD_DEMON_LESSER,
CARD_HASTEN
DEFVEC(deck_of_summoning);
static card_type a_deck_of_wonders[] = {
CARD_POTION, CARD_FOCUS, CARD_SHUFFLE,
CARD_EXPERIENCE, CARD_WILD_MAGIC, CARD_GENETIC_ENGINEER
static card_type deck_of_power[] =
{
CARD_BLANK,
CARD_DEMON_COMMON,
CARD_DEMON_GREATER,
CARD_TELEPORT_NOW,
CARD_VENOM,
CARD_XOM,
CARD_HEAL_WOUNDS,
CARD_FAMINE,
CARD_FEAST,
CARD_WILD_MAGIC,
CARD_VIOLENCE,
CARD_PROTECTION,
CARD_KNOWLEDGE,
CARD_HASTEN,
CARD_TORMENT,
CARD_DEMON_SWARM,
CARD_SLOW
DEFVEC(deck_of_wonders);
static card_type a_deck_of_dungeons[] = {
CARD_MAP, CARD_DOWSING, CARD_SPADE, CARD_TROWEL, CARD_MINEFIELD
// Supposed to be bad, small chance of OK... Nemelex wouldn't like a game
// that didn't have some chance of "losing".
static card_type deck_of_punishment[] =
{
CARD_BLANK,
CARD_BUTTERFLY,
CARD_WRAITH,
CARD_WEALTH,
CARD_STUPIDITY,
CARD_WEAKNESS,
CARD_SLOTH,
CARD_SHUFFLE,
CARD_FREAK,
CARD_DEATH,
CARD_NORMALITY,
CARD_SHADOW,
CARD_GATE,
CARD_DEMON_SWARM,
CARD_RAGE,
CARD_VENOM,
CARD_SLOW,
CARD_DECAY,
CARD_TORMENT,
CARD_FAMINE,
CARD_WILD_MAGIC,
CARD_MAZE,
CARD_PANDEMONIUM
DEFVEC(deck_of_dungeons);
static card_type a_deck_of_oddities[] = {
CARD_GENIE, CARD_BARGAIN, CARD_WRATH, CARD_XOM,
CARD_FEAST, CARD_FAMINE, CARD_CURSE
#define DECK_WONDERS_SIZE ARRAYSIZE(deck_of_wonders)
#define DECK_SUMMONING_SIZE ARRAYSIZE(deck_of_summoning)
#define DECK_TRICKS_SIZE ARRAYSIZE(deck_of_tricks)
#define DECK_POWER_SIZE ARRAYSIZE(deck_of_power)
#define DECK_PUNISHMENT_SIZE ARRAYSIZE(deck_of_punishment)
DEFVEC(deck_of_oddities);
static card_type a_deck_of_punishment[] = {
CARD_WRAITH, CARD_WILD_MAGIC, CARD_WRATH,
CARD_XOM, CARD_FAMINE, CARD_CURSE, CARD_TOMB,
CARD_DAMNATION, CARD_PORTAL, CARD_MINEFIELD
};
case CARD_BLANK: return "a blank card";
case CARD_BUTTERFLY: return "Butterfly";
case CARD_WRAITH: return "the Wraith";
case CARD_EXPERIENCE: return "Experience";
case CARD_WEALTH: return "Wealth";
case CARD_INTELLIGENCE: return "the Brain";
case CARD_STRENGTH: return "Strength";
case CARD_QUICKSILVER: return "Quicksilver";
case CARD_STUPIDITY: return "Stupidity";
case CARD_WEAKNESS: return "Weakness";
case CARD_SLOTH: return "the Slug";
case CARD_SHUFFLE: return "Shuffle";
case CARD_FREAK: return "the Freak";
case CARD_DEATH: return "Death";
case CARD_NORMALITY: return "Normality";
case CARD_BLANK: return "blank card";
case CARD_PORTAL: return "the Portal";
case CARD_WARP: return "the Warp";
case CARD_SWAP: return "Swap";
case CARD_VELOCITY: return "Velocity";
case CARD_DAMNATION: return "Damnation";
case CARD_SOLITUDE: return "Solitude";
case CARD_ELIXIR: return "the Elixir";
case CARD_BATTLELUST: return "Battlelust";
case CARD_METAMORPHOSIS: return "Metamorphosis";
case CARD_HELM: return "the Helm";
case CARD_BLADE: return "the Blade";
case CARD_GATE: return "the Gate";
case CARD_STATUE: return "a statue";
case CARD_ACQUISITION: return "Acquisition";
case CARD_HASTEN: return "Haste";
case CARD_DEMON_LESSER: return "a demon";
case CARD_DEMON_COMMON: return "a demon";
case CARD_DEMON_GREATER: return "a demon";
case CARD_DEMON_SWARM: return "a demon";
case CARD_YAK: return "a yak";
case CARD_FIEND: return "a devil";
case CARD_DRAGON: return "a dragon";
case CARD_GOLEM: return "a statue";
case CARD_THING_FUGLY: return "a very ugly thing";
case CARD_LICH: return "a lich";
case CARD_HORROR_UNSEEN:
return player_see_invis() ? "an abomination" : "a blank card";
case CARD_BLINK: return "Blink";
case CARD_TELEPORT: return "the Portal";
case CARD_TELEPORT_NOW: return "the Portal";
case CARD_RAGE: return "Rage";
case CARD_LEVITY: return "Levity";
case CARD_VENOM: return "Venom";
case CARD_XOM: return "the card of Xom";
case CARD_SLOW: return "Slowness";
case CARD_DECAY: return "Decay";
case CARD_HEALING: return "Health";
case CARD_HEAL_WOUNDS: return "Health";
case CARD_TORMENT: return "Torment";
case CARD_FOUNTAIN: return "the Fountain";
case CARD_ALTAR: return "the Altar";
case CARD_POTION: return "the Potion";
case CARD_FOCUS: return "Focus";
case CARD_SHUFFLE: return "Shuffle";
case CARD_EXPERIENCE: return "Experience";
case CARD_GENETIC_ENGINEER: return "Genetics";
case CARD_DOWSING: return "Dowsing";
case CARD_TROWEL: return "the Trowel";
case CARD_MINEFIELD: return "the Minefield";
case CARD_GENIE: return "the Genie";
case CARD_TOMB: return "the Tomb";
case CARD_MAP: return "the Map";
case CARD_BANSHEE: return "the Banshee";
case CARD_WILD_MAGIC: return "Wild Magic";
case CARD_SUMMON_ANIMAL: return "the Herd";
case CARD_SUMMON_DEMON: return "the Pentagram";
case CARD_SUMMON_WEAPON: return "the Dance";
case CARD_SUMMON_ANY: return "Summoning";
case CARD_XOM: return "Xom";
case CARD_WILD_MAGIC: return "Wild Magic";
case CARD_VIOLENCE: return "Violence";
case CARD_PROTECTION: return "Protection";
case CARD_KNOWLEDGE: return "Knowledge";
case CARD_MAZE: return "the Maze";
case CARD_PANDEMONIUM: return "Pandemonium";
case CARD_IMPRISONMENT: return "the Prison";
case CARD_RULES_FOR_BRIDGE: return "the rules";
case NUM_CARDS: case CARD_RANDOM: return "a buggy card";
case CARD_WARPWRIGHT: return "Warpwright";
case CARD_VITRIOL: return "Vitriol";
case CARD_FLAME: return "Flame";
case CARD_FROST: return "Frost";
case CARD_HAMMER: return "the Hammer";
case CARD_SPADE: return "the Spade";
case CARD_BARGAIN: return "the Bargain";
case CARD_WRATH: return "Wrath";
case CARD_WRAITH: return "the Wraith";
case CARD_CURSE: return "the Curse";
case NUM_CARDS: return "a buggy card";
card_type *deck = deck_of_wonders;
int max_card = 0;
switch (which_deck)
std::vector<card_type> *pdeck = NULL;
switch ( item.sub_type )
case DECK_OF_WONDERS:
deck = deck_of_wonders;
max_card = DECK_WONDERS_SIZE;
case MISC_DECK_OF_ESCAPE:
pdeck = (coinflip() ? &deck_of_transport : &deck_of_emergency);
case DECK_OF_SUMMONING:
deck = deck_of_summoning;
max_card = DECK_SUMMONING_SIZE;
break;
case DECK_OF_TRICKS:
deck = deck_of_tricks;
max_card = DECK_TRICKS_SIZE;
case MISC_DECK_OF_DESTRUCTION: pdeck = &deck_of_destruction; break;
case MISC_DECK_OF_DUNGEONS: pdeck = &deck_of_dungeons; break;
case MISC_DECK_OF_SUMMONING: pdeck = &deck_of_summoning; break;
case MISC_DECK_OF_WONDERS: pdeck = &deck_of_wonders; break;
case MISC_DECK_OF_PUNISHMENT: pdeck = &deck_of_punishment; break;
case MISC_DECK_OF_WAR:
switch ( random2(6) )
{
case 0: pdeck = &deck_of_destruction; break;
case 1: pdeck = &deck_of_enchantments; break;
case 2: pdeck = &deck_of_battle; break;
case 3: pdeck = &deck_of_summoning; break;
case 4: pdeck = &deck_of_transport; break;
case 5: pdeck = &deck_of_emergency; break;
}
case DECK_OF_POWER:
deck = deck_of_power;
max_card = DECK_POWER_SIZE;
case MISC_DECK_OF_CHANGES:
switch ( random2(3) )
{
case 0: pdeck = &deck_of_battle; break;
case 1: pdeck = &deck_of_dungeons; break;
case 2: pdeck = &deck_of_wonders; break;
}
case DECK_OF_PUNISHMENT:
deck = deck_of_punishment;
max_card = DECK_PUNISHMENT_SIZE;
case MISC_DECK_OF_DEFENSE:
pdeck = (coinflip() ? &deck_of_emergency : &deck_of_battle);
// returns the deck type, of DECK_OF_PUNISHMENT if none
deck_type subtype_to_decktype(int subtype)
{
switch ( subtype )
{
case MISC_DECK_OF_WONDERS:
return DECK_OF_WONDERS;
case MISC_DECK_OF_POWER:
return DECK_OF_POWER;
case MISC_DECK_OF_SUMMONINGS:
return DECK_OF_SUMMONING;
case MISC_DECK_OF_TRICKS:
return DECK_OF_TRICKS;
default: // sentinel
return DECK_OF_PUNISHMENT;
}
}
card_effect(choose_one_card(which_deck, true));
int power_level = 0;
switch ( rarity )
{
case DECK_RARITY_COMMON:
break;
case DECK_RARITY_LEGENDARY:
if ( random2(500) < power )
++power_level;
// deliberate fall-through
case DECK_RARITY_RARE:
if ( random2(700) < power )
++power_level;
break;
}
return power_level;
FixedVector < int, 5 > dvar;
FixedVector < int, 5 > mvar;
int dvar1 = 0;
int loopy = 0; // general purpose loop variable {dlb}
bool success = false; // for summoning messages {dlb}
bool failMsg = true;
int summ_dur, summ_beh, summ_num;
if (which_card == CARD_BLANK && one_chance_in(10))
which_card = CARD_RULES_FOR_BRIDGE;
switch (which_card)
const int control_level = get_power_level(power, rarity);
bool instant = false;
bool controlled = false;
if ( control_level >= 2 )
{
instant = true;
controlled = true;
}
else if ( control_level == 1 )
if (create_monster( MONS_BUTTERFLY, summ_dur, BEH_FRIENDLY,
you.x_pos, you.y_pos, MHITYOU, 250 ) != -1)
{
mpr("A brightly coloured insect flies from the card!");
}
break;
if ( controlled && !was_controlled )
you.duration[DUR_CONTROL_TELEPORT] = 0;
}
case CARD_WRAITH:
mpr("You have drawn the Wraith.");
void warp_card(int power, deck_rarity_type rarity)
{
const int control_level = get_power_level(power, rarity);
if ( control_level >= 2 )
blink();
else if ( control_level == 1 )
cast_semi_controlled_blink(power / 4);
else
random_blink(false);
}
case CARD_EXPERIENCE:
mpr( "You have drawn Experience." );
potion_effect( POT_EXPERIENCE, 0 );
break;
case CARD_WEALTH:
mpr("You have drawn Wealth.");
you.gold += roll_dice( 2, 20 * you.skills[SK_EVOCATIONS] );
you.redraw_gold = 1;
break;
case CARD_INTELLIGENCE:
mpr("You have drawn the Brain!");
you.intel += 1 + random2( you.skills[SK_EVOCATIONS] ) / 7;
if (you.max_intel < you.intel)
you.max_intel = you.intel;
you.redraw_intelligence = 1;
break;
case CARD_STRENGTH:
mpr("You have drawn Strength!");
you.strength += 1 + random2( you.skills[SK_EVOCATIONS] ) / 7;
if (you.max_strength < you.strength)
you.max_strength = you.strength;
you.redraw_strength = 1;
break;
case CARD_QUICKSILVER:
mpr("You have drawn the Quicksilver card.");
you.dex += 1 + random2( you.skills[SK_EVOCATIONS] ) / 7;
if (you.max_dex < you.dex)
you.max_dex = you.dex;
you.redraw_dexterity = 1;
break;
case CARD_STUPIDITY:
mpr("You have drawn Stupidity!");
you.intel -= (2 + random2avg(3, 2));
if (you.intel < 4)
you.intel = 0;
if (you.skills[SK_EVOCATIONS] < random2(30))
you.max_intel--;
you.redraw_intelligence = 1;
break;
case CARD_WEAKNESS:
mpr("You have drawn Weakness.");
you.strength -= (2 + random2avg(3, 2));
if (you.strength < 4)
you.strength = 0;
if (you.skills[SK_EVOCATIONS] < random2(30))
you.max_strength--;
you.redraw_strength = 1;
break;
case CARD_SLOTH:
mpr("You have drawn the Slug.");
you.dex -= (2 + random2avg(3, 2));
if (you.dex < 4)
you.dex = 0;
if (you.skills[SK_EVOCATIONS] < random2(30))
you.max_dex--;
you.redraw_dexterity = 1;
break;
void velocity_card(int power, deck_rarity_type rarity)
{
const int power_level = get_power_level(power, rarity);
if ( power_level >= 2 )
{
potion_effect( POT_SPEED, random2(power / 4) );
}
else if ( power_level == 1 )
{
potion_effect( POT_LEVITATION, random2(power / 4) );
cast_swiftness( random2(power/4) );
}
else
{
cast_swiftness( random2(power/4) );
}
}
dvar[STAT_STRENGTH] = you.strength;
dvar[STAT_DEXTERITY] = you.dex;
dvar[STAT_INTELLIGENCE] = you.intel;
int ystart = you.y_pos - 9, xstart = you.x_pos - 9;
int yend = you.y_pos + 9, xend = you.x_pos + 9;
if ( xstart < 0 ) xstart = 0;
if ( ystart < 0 ) ystart = 0;
if ( xend >= GXM ) xend = GXM;
if ( ystart >= GYM ) yend = GYM;
mvar[STAT_STRENGTH] = you.max_strength;
mvar[STAT_DEXTERITY] = you.max_dex;
mvar[STAT_INTELLIGENCE] = you.max_intel;
/* monster check */
for ( int y = ystart; y < yend; ++y )
for ( int x = xstart; x < xend; ++x )
if ( see_grid(x,y) && mgrd[x][y] != NON_MONSTER )
if ( one_chance_in(++mons_count) )
mon_to_banish = mgrd[x][y];
you.redraw_strength = 1;
you.redraw_intelligence = 1;
you.redraw_dexterity = 1;
burden_change();
break;
case CARD_FREAK:
mpr("You have drawn the Freak!");
for (loopy = 0; loopy < 6; loopy++)
if ( fx >= 0 ) // found a spot
{
if ( place_specific_trap(fx, fy, TRAP_TELEPORT) )
if (!mutate(100, failMsg))
failMsg = false;
// mark it discovered if enough power
if ( get_power_level(power, rarity) >= 1 )
{
const int i = trap_at_xy(fx, fy);
if (i != -1) // should always happen
grd[fx][fy] = trap_category(env.trap[i].type);
}
case CARD_DEATH:
mpr("Oh no! You have drawn the Death card!");
void damaging_card( card_type card, int power, deck_rarity_type rarity )
{
dist target;
bolt beam;
zap_type ztype;
switch ( card )
{
case CARD_VITRIOL: ztype = ZAP_BREATHE_ACID; break;
case CARD_FLAME: ztype = ZAP_BREATHE_FIRE; break;
case CARD_FROST: ztype = ZAP_BREATHE_FROST; break;
case CARD_HAMMER: ztype = ZAP_BREATHE_POWER; break;
default: ztype = ZAP_DEBUGGING_RAY; break;
}
case CARD_SHADOW:
mpr("You have drawn the Shadow.");
create_monster( MONS_SOUL_EATER, 0, BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, 250 );
break;
case CARD_GATE:
mpr("You have drawn the Gate!");
if (you.level_type == LEVEL_ABYSS)
banished(DNGN_EXIT_ABYSS, "drew the Gate");
else if (you.level_type == LEVEL_LABYRINTH)
canned_msg(MSG_NOTHING_HAPPENS);
if ( power_level == 0 )
{
if ( coinflip() )
potion_effect( POT_HEAL_WOUNDS, 40 ); // doesn't matter
{
mpr("You are cast into the Abyss!");
banished(DNGN_ENTER_ABYSS, "drew the Gate");
}
break;
cast_regen( random2(power / 4) );
}
else if ( power_level == 1 )
{
you.hp = you.hp_max;
you.magic_points = 0;
}
else if ( power_level >= 2 )
{
you.hp = you.hp_max;
you.magic_points = you.max_magic_points;
}
}
case CARD_STATUE:
mpr("You have drawn the Crystal Statue.");
create_monster( MONS_CRYSTAL_GOLEM, 0, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target, 250 );
break;
void battle_lust_card(int power, deck_rarity_type rarity)
{
const int power_level = get_power_level(power, rarity);
if ( power_level >= 2 )
{
// temporary ring of slaying effect XXX
}
else if ( power_level == 1 )
go_berserk(false);
else if ( power_level == 0 )
potion_effect(POT_MIGHT, random2(power/4));
}
case CARD_ACQUISITION:
mpr( "You have drawn Acquisition!" );
mpr( "The card unfolds to form a scroll of paper." );
acquirement( OBJ_RANDOM, AQ_CARD_ACQUISITION );
break;
void metamorphosis_card(int power, deck_rarity_type rarity)
{
const int power_level = get_power_level(power, rarity);
transformation_type trans;
if ( power_level >= 2 )
trans = (coinflip() ? TRAN_DRAGON : TRAN_LICH);
else
trans = (coinflip() ? TRAN_STATUE : TRAN_BLADE_HANDS);
transform(random2(power/4), trans);
}
case CARD_HASTEN:
mpr("You have drawn Haste.");
potion_effect( POT_SPEED, 5 * you.skills[SK_EVOCATIONS] );
break;
void helm_card(int power, deck_rarity_type rarity)
{
const int power_level = get_power_level(power, rarity);
bool do_forescry = false;
bool do_stoneskin = false;
bool do_shield = false;
int num_resists = 0;
if ( power_level >= 2 )
{
if ( coinflip() ) do_forescry = true;
if ( coinflip() ) do_stoneskin = true;
if ( coinflip() ) do_shield = true;
num_resists = random2(4);
}
if ( power_level >= 1 )
{
if ( coinflip() ) do_forescry = true;
if ( coinflip() ) do_stoneskin = true;
if ( coinflip() ) do_shield = true;
}
if ( power_level >= 0 )
{
if ( coinflip() )
do_forescry = true;
else
do_stoneskin = true;
}
if (create_monster( summon_any_demon( DEMON_LESSER ), summ_dur,
BEH_FRIENDLY, you.x_pos, you.y_pos, you.pet_target,
250 ) != -1)
{
mpr("The picture comes to life!");
}
break;
case CARD_DEMON_COMMON:
mpr("On the card is a picture of a demon.");
summ_dur = cap_int(1 + random2(3) + you.skills[SK_EVOCATIONS] / 4, 6);
if (create_monster( summon_any_demon( DEMON_COMMON ), summ_dur,
BEH_FRIENDLY, you.x_pos, you.y_pos, you.pet_target,
250 ) != -1)
{
mpr("The picture comes to life!");
}
break;
case CARD_DEMON_GREATER:
mpr("On the card is a picture of a huge demon.");
summ_beh = (you.skills[SK_EVOCATIONS] > random2(30)) ? BEH_FRIENDLY
: BEH_CHARMED;
if (summ_beh == BEH_CHARMED)
mpr( "You don't feel so good about this..." );
// Do one of: vorpalise, sure blade, dancing weapon
// XXX XXX FIXME Hard to do now, because you have to
// wield the deck in order to evoke it!
void blade_card(int power, deck_rarity_type rarity)
{
return;
const int power_level = get_power_level(power, rarity);
if ( power_level >= 2 )
{
dancing_weapon( random2(power/4), false );
}
else if ( power_level == 1 )
{
cast_sure_blade( random2(power/4) );
}
else
{
brand_weapon(SPWPN_VORPAL, random2(power/4)); // maybe other brands?
}
}
if (create_monster( summon_any_demon( DEMON_GREATER ), 5,
summ_beh, you.x_pos, you.y_pos,
you.pet_target, 250 ) != -1)
{
mpr("The picture comes to life!");
}
break;
void shadow_card(int power, deck_rarity_type rarity)
{
const int power_level = get_power_level(power, rarity);
if ( power_level >= 1 )
{
// XXX add a stealth attribute here
}
potion_effect(POT_INVISIBILITY, random2(power/4));
}
case CARD_DEMON_SWARM:
mpr("On the card is a picture of a swarm of little demons.");
void potion_card(int power, deck_rarity_type rarity)
{
const int power_level = get_power_level(power, rarity);
potion_type pot_effects[] = {
POT_HEAL_WOUNDS, POT_HEAL_WOUNDS, POT_HEAL_WOUNDS,
POT_HEALING, POT_HEALING, POT_HEALING,
POT_RESTORE_ABILITIES, POT_RESTORE_ABILITIES,
POT_POISON, POT_CONFUSION, POT_DEGENERATION
};
for (loopy = 0; loopy < summ_num; loopy++)
{
if (create_monster( summon_any_demon( DEMON_LESSER ), 6,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, 250 ) != -1)
{
success = true;
}
}
if ( power_level >= 2 && one_chance_in(5) )
pot = POT_MAGIC;
case CARD_YAK:
mpr("On the card is a picture of a huge shaggy yak.");
void focus_card(int power, deck_rarity_type rarity)
{
char* max_statp[] = { &you.max_strength, &you.max_intel, &you.max_dex };
char* base_statp[] = { &you.strength, &you.intel, &you.dex };
int best_stat = 0;
int worst_stat = 0;
summ_dur = cap_int(2 + you.skills[SK_EVOCATIONS] / 2, 6);
if (create_monster( MONS_DEATH_YAK, summ_dur, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target, 250 ) != -1)
{
mpr("The picture comes to life!");
}
break;
for ( int i = 1; i < 3; ++i )
{
const int best_diff = *max_statp[i] - *max_statp[best_stat];
if ( best_diff > 0 || (best_diff == 0 && coinflip()) )
best_stat = i;
const int worst_diff = *max_statp[i] - *max_statp[worst_stat];
if ( worst_diff < 0 || (worst_diff == 0 && coinflip()) )
worst_stat = i;
}
summ_dur = cap_int(2 + you.skills[SK_EVOCATIONS] / 6, 6);
if (create_monster( MONS_FIEND, summ_dur, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target, 250 ) != -1)
{
mpr("The picture comes to life!");
}
break;
(*max_statp[best_stat])++;
(*max_statp[worst_stat])--;
(*base_statp[best_stat])++;
(*base_statp[worst_stat])--;
you.redraw_strength = true;
you.redraw_intelligence = true;
you.redraw_dexterity = true;
}
summ_dur = cap_int(3 + you.skills[SK_EVOCATIONS] / 6, 6);
if (create_monster( (coinflip() ? MONS_DRAGON : MONS_ICE_DRAGON),
summ_dur, BEH_FRIENDLY, you.x_pos, you.y_pos,
you.pet_target, 250 ) != -1)
{
mpr("The picture comes to life!");
}
break;
void genetic_engineer_card(int power, deck_rarity_type rarity)
{
mutation_type bad_mutations[] = {
MUT_FAST_METABOLISM, MUT_WEAK, MUT_DOPEY, MUT_CLUMSY,
MUT_TELEPORT, MUT_DEFORMED, MUT_LOST, MUT_DETERIORATION,
MUT_BLURRY_VISION, MUT_FRAIL
};
case CARD_GOLEM:
mpr("On the card is a picture of a statue.");
mutation_type which_mut;
int numfound = 0;
for ( unsigned int i = 0; i < ARRAYSIZE(bad_mutations); ++i )
{
if (you.mutation[bad_mutations[i]] > you.demon_pow[bad_mutations[i]])
if ( one_chance_in(++numfound) )
which_mut = bad_mutations[i];
}
if ( numfound )
delete_mutation(which_mut);
}
summ_dur = cap_int(2 + you.skills[SK_EVOCATIONS] / 4, 6);
if (create_monster( MONS_CLAY_GOLEM + random2(6), summ_dur,
BEH_FRIENDLY, you.x_pos, you.y_pos,
you.pet_target, 250 ) != -1)
{
mpr("The picture comes to life!");
}
break;
void dowsing_card(int power, deck_rarity_type rarity)
{
const int power_level = get_power_level(power, rarity);
bool things_to_do[3] = { false, false, false };
things_to_do[random2(3)] = true;
summ_dur = cap_int(2 + you.skills[SK_EVOCATIONS] / 4, 6);
if (create_monster( MONS_VERY_UGLY_THING, summ_dur, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target, 250 ) != -1)
{
mpr("The picture comes to life!");
}
break;
if ( power_level >= 2 )
for ( int i = 0; i < 3; ++i )
things_to_do[i] = true;
case CARD_LICH:
mpr( "On the card is a picture of a very irritated-looking "
"skeletal thing." );
if ( things_to_do[0] )
cast_detect_secret_doors( random2(power/4) );
if ( things_to_do[1] )
detect_traps( random2(power/4) );
if ( things_to_do[2] )
detect_creatures( random2(power/4) );
}
summ_dur = cap_int(2 + you.skills[SK_EVOCATIONS] / 4, 6);
if (create_monster( MONS_UNSEEN_HORROR, summ_dur, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target, 250 ) != -1)
{
if (player_see_invis())
{
mpr("The picture comes to life!");
}
}
break;
void genie_card(int power, deck_rarity_type rarity)
{
if ( coinflip() )
acquirement( OBJ_RANDOM, AQ_CARD_ACQUISITION );
else
potion_effect( coinflip() ? POT_DEGENERATION : POT_DECAY, 40 );
}
case CARD_TELEPORT:
mpr("You have drawn the Portal of Delayed Transposition.");
you_teleport();
break;
if ( you.penance[GOD_NEMELEX_XOBEH] )
{
result -= you.penance[GOD_NEMELEX_XOBEH];
}
else if ( you.religion == GOD_NEMELEX_XOBEH && you.duration[DUR_PRAYER] )
{
result = you.piety;
result *= (you.skills[SK_INVOCATIONS] + 25);
result /= 27;
}
case CARD_TELEPORT_NOW:
mpr( "You have drawn the Portal of Instantaneous Transposition." );
you_teleport_now( true, true ); // in abyss, always to new area
break;
result += you.skills[SK_EVOCATIONS] * 9;
if ( rarity == DECK_RARITY_RARE )
result += random2(result / 2);
if ( rarity == DECK_RARITY_LEGENDARY )
result += random2(result);
case CARD_VENOM:
mpr("You have drawn Venom.");
poison_player( 2 + random2( 7 - you.skills[SK_EVOCATIONS] / 5 ) );
break;
switch (which_card)
{
case CARD_BLANK: break;
case CARD_PORTAL: portal_card(power, rarity); break;
case CARD_WARP: warp_card(power, rarity); break;
case CARD_SWAP: swap_monster_card(power, rarity); break;
case CARD_VELOCITY: velocity_card(power, rarity); break;
case CARD_DAMNATION: damnation_card(power, rarity); break;
case CARD_SOLITUDE: cast_dispersal(power/4); break;
case CARD_ELIXIR: elixir_card(power, rarity); break;
case CARD_BATTLELUST: battle_lust_card(power, rarity); break;
case CARD_METAMORPHOSIS: metamorphosis_card(power, rarity); break;
case CARD_HELM: helm_card(power, rarity); break;
case CARD_BLADE: blade_card(power, rarity); break;
case CARD_SHADOW: shadow_card(power, rarity); break;
case CARD_POTION: potion_card(power, rarity); break;
case CARD_FOCUS: focus_card(power, rarity); break;
case CARD_SHUFFLE: shuffle_card(power, rarity); break;
case CARD_EXPERIENCE: potion_effect(POT_EXPERIENCE, power/4); break;
case CARD_GENETIC_ENGINEER: genetic_engineer_card(power, rarity); break;
case CARD_DOWSING: dowsing_card(power, rarity); break;
case CARD_TROWEL: trowel_card(power, rarity); break;
case CARD_MINEFIELD: minefield_card(power, rarity); break;
case CARD_GENIE: genie_card(power, rarity); break;
case CARD_TOMB: entomb(); break;
case CARD_XOM:
mpr("You have drawn the card of Xom!");
xom_acts( true, 5 + random2( you.skills[SK_EVOCATIONS] ));
case CARD_WARPWRIGHT: case CARD_SPADE: case CARD_WRATH:
case CARD_WRAITH: case CARD_CURSE: case CARD_BARGAIN:
mpr("Sorry, this card is not yet available.");
case CARD_HEAL_WOUNDS:
mpr("You have drawn the Symbol of Immediate Regeneration.");
potion_effect( POT_HEAL_WOUNDS, 5 * you.skills[SK_EVOCATIONS] );
case CARD_WILD_MAGIC:
// yes, high power is bad here
miscast_effect( SPTYP_RANDOM, random2(power/15) + 5,
random2(power), 0 );
case CARD_TORMENT:
mpr("You have drawn the Symbol of Torment.");
torment( TORMENT_CARDS, you.x_pos, you.y_pos );
break;
case CARD_FOUNTAIN:
// what about checking whether there are items there, too? {dlb}
mpr("You have drawn the Fountain.");
case CARD_SUMMON_ANIMAL: break;
case CARD_SUMMON_DEMON: break;
case CARD_SUMMON_WEAPON: break;
case CARD_SUMMON_ANY: break;
if (grd[you.x_pos][you.y_pos] == DNGN_FLOOR)
{
mprf("A beautiful fountain of clear blue water grows from the "
"floor %s!",
(you.species == SP_NAGA || you.species == SP_CENTAUR) ?
"before you" : "at your feet" );
grd[you.x_pos][you.y_pos] = DNGN_BLUE_FOUNTAIN;
}
else
{
canned_msg(MSG_NOTHING_HAPPENS);
}
break;
if (you.religion == GOD_NO_GOD ||
grd[you.x_pos][you.y_pos] != DNGN_FLOOR)
{
canned_msg(MSG_NOTHING_HAPPENS);
}
else
{
const dungeon_feature_type altar =
static_cast<dungeon_feature_type>(
DNGN_ALTAR_ZIN + you.religion - 1 );
mprf("An altar grows from the floor %s!",
(you.species == SP_NAGA || you.species == SP_CENTAUR)
? "before you" : "at your feet");
grd[you.x_pos][you.y_pos] = altar;
}
break;
case CARD_XOM: xom_acts(5 + random2(power/10)); break;
break;
case CARD_WILD_MAGIC:
mpr( "You have drawn Wild Magic." );
miscast_effect( SPTYP_RANDOM, random2(15) + 5, random2(250), 0 );
break;
case CARD_VIOLENCE:
mpr("You have drawn Violence.");
acquirement( OBJ_WEAPONS, AQ_CARD_VIOLENCE );
case CARD_PROTECTION:
mpr("You have drawn Protection.");
acquirement( OBJ_ARMOUR, AQ_CARD_PROTECTION );
break;
case CARD_KNOWLEDGE:
mpr("You have drawn Knowledge.");
acquirement( OBJ_BOOKS, AQ_CARD_KNOWLEDGE );
break;
case CARD_MAZE:
mpr("You have drawn the Maze!");
more();
if (you.level_type == LEVEL_DUNGEON)
banished( DNGN_ENTER_LABYRINTH );
break;
case CARD_PANDEMONIUM:
mpr("You have drawn the Pandemonium card!");
more();
if (you.level_type == LEVEL_PANDEMONIUM)
banished(DNGN_EXIT_PANDEMONIUM);
else if (you.level_type == LEVEL_LABYRINTH)
canned_msg(MSG_NOTHING_HAPPENS);
else
banished(DNGN_ENTER_PANDEMONIUM);
break;
case CARD_RULES_FOR_BRIDGE:
mpr("You have drawn the rules for contract bridge.");
mpr("How intriguing!");
break;
case CARD_IMPRISONMENT:
mpr("You have drawn the Prison!");
entomb();
break;