summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2007-05-11 23:21:30 +0000
committerharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2007-05-11 23:21:30 +0000
commit8b9d48402b36f994893ab627cf9cf7b0be632d20 (patch)
treeab580bf6017087c5c5ff8b8648e4d8aed4e92d11 /crawl-ref/source
parenta81a0b436a4e8664c76d9e74e462fc2690880851 (diff)
downloadcrawl-ref-8b9d48402b36f994893ab627cf9cf7b0be632d20.tar.gz
crawl-ref-8b9d48402b36f994893ab627cf9cf7b0be632d20.zip
Deck stacking implemented. Five cards (or less, if there are less) are
drawn, you get to stack them in any order, and the rest of the deck is discarded. The next card is inscribed on the deck; the remainder can be seen with 'v'. This is now Nemelex's top ability. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1467 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/abl-show.cc8
-rw-r--r--crawl-ref/source/decks.cc130
-rw-r--r--crawl-ref/source/decks.h1
-rw-r--r--crawl-ref/source/describe.cc15
-rw-r--r--crawl-ref/source/enum.h1
-rw-r--r--crawl-ref/source/itemname.cc5
-rw-r--r--crawl-ref/source/itemprop.cc9
-rw-r--r--crawl-ref/source/itemprop.h2
-rw-r--r--crawl-ref/source/output.cc3
-rw-r--r--crawl-ref/source/religion.cc4
10 files changed, 143 insertions, 35 deletions
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc
index 3a897a841e..55f2b0a801 100644
--- a/crawl-ref/source/abl-show.cc
+++ b/crawl-ref/source/abl-show.cc
@@ -128,7 +128,7 @@ ability_type god_abilities[MAX_NUM_GODS][MAX_GOD_ABILITIES] =
ABIL_TROG_HASTE_SELF, ABIL_NON_ABILITY },
// Nemelex
{ ABIL_NEMELEX_PEEK, ABIL_NEMELEX_TRIPLE_DRAW, ABIL_NON_ABILITY,
- ABIL_NON_ABILITY, ABIL_NON_ABILITY },
+ ABIL_NON_ABILITY, ABIL_NEMELEX_STACK_DECK },
// Elyvilon
{ ABIL_ELYVILON_LESSER_HEALING, ABIL_ELYVILON_PURIFICATION,
ABIL_ELYVILON_HEALING, ABIL_ELYVILON_RESTORATION,
@@ -272,6 +272,7 @@ static const ability_def Ability_List[] =
// Nemelex
{ ABIL_NEMELEX_TRIPLE_DRAW, "Triple Draw", 2, 0, 100, 2, ABFLAG_NONE },
{ ABIL_NEMELEX_PEEK, "Deck Peek", 3, 0, 0, 1, ABFLAG_INSTANT },
+ { ABIL_NEMELEX_STACK_DECK, "Stack Deck", 5, 0, 150, 6, ABFLAG_NONE },
// These six are unused "evil" god abilities:
{ ABIL_CHARM_SNAKE, "Charm Snake", 6, 0, 200, 5, ABFLAG_NONE },
@@ -1563,6 +1564,11 @@ static bool do_ability(const ability_def& abil)
return false;
break;
+ case ABIL_NEMELEX_STACK_DECK:
+ if ( !deck_stack() )
+ return false;
+ break;
+
//jmf: intended as invocations from evil god(s):
case ABIL_CHARM_SNAKE:
cast_snake_charm( you.experience_level * 2
diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc
index 496a50f176..23c0d64c9d 100644
--- a/crawl-ref/source/decks.cc
+++ b/crawl-ref/source/decks.cc
@@ -20,6 +20,7 @@
#include "effects.h"
#include "food.h"
#include "it_use2.h"
+#include "itemprop.h"
#include "items.h"
#include "misc.h"
#include "monplace.h"
@@ -171,33 +172,33 @@ const char* card_name(card_type card)
case CARD_NORMALITY: return "Normality";
case CARD_SHADOW: return "the Shadow";
case CARD_GATE: return "the Gate";
- case CARD_STATUE: return "the Crystal Statue";
+ case CARD_STATUE: return "a statue";
case CARD_ACQUISITION: return "Acquisition";
case CARD_HASTEN: return "Haste";
- case CARD_DEMON_LESSER: return "a little demon";
+ case CARD_DEMON_LESSER: return "a demon";
case CARD_DEMON_COMMON: return "a demon";
- case CARD_DEMON_GREATER: return "a huge demon";
- case CARD_DEMON_SWARM: return "a swarm of little demons";
- case CARD_YAK: return "a huge, shaggy yak";
- case CARD_FIEND: return "a huge, scaly devil";
- case CARD_DRAGON: return "a huge, scaly dragon";
+ 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 very irritated-looking skeletal thing";
+ case CARD_LICH: return "a lich";
case CARD_HORROR_UNSEEN:
- return player_see_invis() ? "a hideous abomination" : "a blank card";
+ return player_see_invis() ? "an abomination" : "a blank card";
case CARD_BLINK: return "Blink";
- case CARD_TELEPORT: return "the Portal of Delayed Transposition";
- case CARD_TELEPORT_NOW: return "the Portal of Instantaneous Transposition";
+ 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 "the Elixir of Health";
- case CARD_HEAL_WOUNDS: return "the Symbol of Immediate Regeneration";
- case CARD_TORMENT: return "the Symbol of Torment";
+ 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_FAMINE: return "Famine";
@@ -209,7 +210,7 @@ const char* card_name(card_type card)
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 for contract bridge";
+ case CARD_RULES_FOR_BRIDGE: return "the rules";
case NUM_CARDS: case CARD_RANDOM: return "a buggy card";
}
return "a very buggy card";
@@ -283,9 +284,7 @@ static bool wielding_deck()
{
if ( you.equip[EQ_WEAPON] == -1 )
return false;
- const item_def& item = you.inv[you.equip[EQ_WEAPON]];
- return ( item.base_type == OBJ_MISCELLANY &&
- subtype_to_decktype(item.sub_type) != DECK_OF_PUNISHMENT );
+ return is_deck(you.inv[you.equip[EQ_WEAPON]]);
}
bool deck_peek()
@@ -296,7 +295,7 @@ bool deck_peek()
return false;
}
item_def& item(you.inv[you.equip[EQ_WEAPON]]);
- if ( item.special != 0 )
+ if ( item.plus2 != 0 )
{
mpr("You already know what the next card will be.");
return false;
@@ -304,7 +303,67 @@ bool deck_peek()
const deck_type dtype = subtype_to_decktype(item.sub_type);
const card_type chosen = choose_one_card(dtype, false);
msg::stream << "You see " << card_name(chosen) << '.' << std::endl;
- item.special = chosen + 1;
+ item.plus2 = chosen + 1;
+ you.wield_change = true;
+ return true;
+}
+
+bool deck_stack()
+{
+ if ( !wielding_deck() )
+ {
+ mpr("You aren't wielding a deck!");
+ return false;
+ }
+ item_def& item(you.inv[you.equip[EQ_WEAPON]]);
+ if ( item.plus2 != 0 )
+ {
+ mpr("You can't stack a marked deck.");
+ return false;
+ }
+ const int num_to_stack = (item.plus < 5 ? item.plus : 5);
+ const deck_type dtype = subtype_to_decktype(item.sub_type);
+
+ std::vector<card_type> draws;
+ for ( int i = 0; i < num_to_stack; ++i )
+ draws.push_back(choose_one_card(dtype, false));
+
+ if ( draws.size() == 1 )
+ mpr("There's only one card left!");
+ else
+ mpr("Order the cards (bottom to top)...", MSGCH_PROMPT);
+
+ item.special = 0;
+
+ while ( draws.size() > 1 )
+ {
+ for ( unsigned int i = 0; i < draws.size(); ++i )
+ {
+ msg::stream << (static_cast<char>(i + 'a')) << " - "
+ << card_name(draws[i]) << std::endl;
+ }
+
+ int selected = -1;
+ while ( 1 )
+ {
+ const int keyin = tolower(get_ch());
+ if (keyin >= 'a' && keyin < 'a' + static_cast<int>(draws.size()))
+ {
+ selected = keyin - 'a';
+ break;
+ }
+ else
+ {
+ canned_msg(MSG_HUH);
+ }
+ }
+ item.special <<= 8;
+ item.special += draws[selected] + 1;
+ draws.erase(draws.begin() + selected);
+ mpr("Next card?", MSGCH_PROMPT);
+ }
+ item.plus2 = draws[0] + 1;
+ item.plus = num_to_stack; // no more deck after the stack
you.wield_change = true;
return true;
}
@@ -318,7 +377,7 @@ bool deck_triple_draw()
}
item_def& item(you.inv[you.equip[EQ_WEAPON]]);
- if ( item.special != 0 )
+ if ( item.plus2 != 0 )
{
mpr("You can't triple draw from a marked deck.");
return false;
@@ -345,9 +404,7 @@ bool deck_triple_draw()
int selected = -1;
while ( 1 )
{
- int keyin = get_ch();
- if ( isalpha(keyin) )
- keyin = tolower(keyin);
+ const int keyin = tolower(get_ch());
if (keyin >= 'a' && keyin < 'a' + num_to_draw)
{
selected = keyin - 'a';
@@ -370,18 +427,35 @@ bool deck_triple_draw()
return true;
}
+// In general, if the next cards in a deck are known, they will
+// be stored in plus2 (the next card) and special (up to 4 cards
+// after that, bitpacked.)
+// Hidden assumption: no more than 126 cards, otherwise the 5th
+// card could clobber the sign bit in special.
void evoke_deck( item_def& deck )
{
const deck_type which_deck = subtype_to_decktype(deck.sub_type);
mpr("You draw a card...");
- if ( deck.special == 0 )
+ if ( deck.plus2 == 0 )
{
deck_of_cards(which_deck);
}
else
{
- cards(static_cast<card_type>(deck.special - 1));
- deck.special = 0;
+ // draw the marked card
+ cards(static_cast<card_type>(deck.plus2 - 1));
+
+ // If there are more marked cards, shift them up
+ if ( deck.special )
+ {
+ const short next_card = (deck.special & 0xFF);
+ deck.special >>= 8;
+ deck.plus2 = next_card;
+ }
+ else
+ {
+ deck.plus2 = 0;
+ }
you.wield_change = true;
}
deck.plus--;
@@ -881,7 +955,7 @@ static void cards(card_type which_card)
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!" );
+ "before you" : "at your feet" );
grd[you.x_pos][you.y_pos] = DNGN_BLUE_FOUNTAIN;
}
else
diff --git a/crawl-ref/source/decks.h b/crawl-ref/source/decks.h
index b0064b464a..671f57c88c 100644
--- a/crawl-ref/source/decks.h
+++ b/crawl-ref/source/decks.h
@@ -23,6 +23,7 @@ void deck_of_cards(deck_type which_deck);
deck_type subtype_to_decktype(int subtype);
bool deck_triple_draw();
bool deck_peek();
+bool deck_stack();
const char* card_name(card_type card);
#endif
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index e6b330cf1f..510d3c5441 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -35,6 +35,7 @@
#include "abl-show.h"
#include "debug.h"
+#include "decks.h"
#include "fight.h"
#include "itemname.h"
#include "itemprop.h"
@@ -3055,6 +3056,20 @@ static std::string describe_misc_item( const item_def &item )
description += "$";
+ if ( is_deck(item) && item.plus2 != 0 )
+ {
+ description += "$Next card(s): ";
+ description += card_name(static_cast<card_type>(item.plus2 - 1));
+ long spec = item.special;
+ while ( spec )
+ {
+ description += ", ";
+ description += card_name(static_cast<card_type>((spec & 0xFF)-1));
+ spec >>= 8;
+ }
+ description += "$";
+ }
+
return (description);
}
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index a6c3fe3ac5..29ed9d632c 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -115,6 +115,7 @@ enum ability_type
ABIL_LUGONU_ABYSS_ENTER,
ABIL_NEMELEX_TRIPLE_DRAW,
ABIL_NEMELEX_PEEK,
+ ABIL_NEMELEX_STACK_DECK,
ABIL_CHARM_SNAKE,
ABIL_TRAN_SERPENT_OF_HELL,
diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc
index 1605a8fd04..2db75c8220 100644
--- a/crawl-ref/source/itemname.cc
+++ b/crawl-ref/source/itemname.cc
@@ -1332,12 +1332,11 @@ std::string item_def::name_aux( bool terse, bool ident ) const
else
{
buff << misc_type_name(item_typ, know_type);
- if ( subtype_to_decktype(item_typ) != DECK_OF_PUNISHMENT &&
- this->special != 0 )
+ if ( is_deck(*this) && item_plus2 != 0 )
{
// an inscribed deck!
buff << " {"
- << card_name(static_cast<card_type>(this->special - 1))
+ << card_name(static_cast<card_type>(item_plus2 - 1))
<< "}";
}
}
diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc
index 6204158da4..bf786ca31f 100644
--- a/crawl-ref/source/itemprop.cc
+++ b/crawl-ref/source/itemprop.cc
@@ -2133,6 +2133,15 @@ bool is_shield_incompatible(const item_def &weapon, const item_def *shield)
&& !is_range_weapon(weapon);
}
+bool is_deck(const item_def &item)
+{
+ return item.base_type == OBJ_MISCELLANY
+ && (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);
+}
+
std::string item_base_name(const item_def &item)
{
switch ( item.base_type )
diff --git a/crawl-ref/source/itemprop.h b/crawl-ref/source/itemprop.h
index c4311fd5e1..98c524b345 100644
--- a/crawl-ref/source/itemprop.h
+++ b/crawl-ref/source/itemprop.h
@@ -148,6 +148,8 @@ bool is_shield(const item_def &item);
bool is_shield_incompatible(const item_def &weapon,
const item_def *shield = NULL);
+bool is_deck(const item_def &item);
+
// Only works for armour/weapons/missiles
std::string item_base_name(const item_def &item);
const char* weapon_base_name(unsigned char subtype);
diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc
index b145a512fd..f1948b024a 100644
--- a/crawl-ref/source/output.cc
+++ b/crawl-ref/source/output.cc
@@ -350,7 +350,8 @@ void print_stats(void)
textcolor(prefcol);
cprintf("%s",
- wpn.name(DESC_INVENTORY, Options.terse_hand).c_str());
+ wpn.name(DESC_INVENTORY,
+ Options.terse_hand).substr(0,38).c_str());
textcolor(LIGHTGREY);
}
else
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 65c5a1edae..3fee742462 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -158,7 +158,7 @@ const char* god_gain_power_messages[MAX_NUM_GODS][MAX_GOD_ABILITIES] =
"draw cards with careful consideration",
"",
"",
- "" },
+ "stack decks" },
// Elyvilon
{ "call upon Elyvilon for minor healing",
"call upon Elyvilon for purification",
@@ -238,7 +238,7 @@ const char* god_lose_power_messages[MAX_NUM_GODS][MAX_GOD_ABILITIES] =
"draw cards with careful consideration",
"",
"",
- "" },
+ "stack decks" },
// Elyvilon
{ "call upon Elyvilon for minor healing",
"call upon Elyvilon for purification",