diff options
-rw-r--r-- | crawl-ref/source/abl-show.cc | 8 | ||||
-rw-r--r-- | crawl-ref/source/decks.cc | 130 | ||||
-rw-r--r-- | crawl-ref/source/decks.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/describe.cc | 15 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/itemname.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/itemprop.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/itemprop.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/output.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/religion.cc | 4 |
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", |