diff options
Diffstat (limited to 'crawl-ref/source/debug.cc')
-rw-r--r-- | crawl-ref/source/debug.cc | 555 |
1 files changed, 522 insertions, 33 deletions
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc index 532448dbc5..e6c0eb867b 100644 --- a/crawl-ref/source/debug.cc +++ b/crawl-ref/source/debug.cc @@ -82,6 +82,7 @@ #include "skills2.h" #include "spl-cast.h" #include "spl-util.h" +#include "state.h" #include "stuff.h" #include "terrain.h" #include "traps.h" @@ -331,7 +332,11 @@ void cast_spec_spell(void) if (spell == -1) canned_msg( MSG_OK ); else - your_spells( static_cast<spell_type>(spell), 0, false ); + if (your_spells( static_cast<spell_type>(spell), 0, false ) + == SPRET_ABORT) + { + crawl_state.cancel_cmd_repeat(); + } } #endif @@ -345,17 +350,28 @@ void cast_spec_spell(void) void cast_spec_spell_name(void) { char specs[80]; + mpr( "Cast which spell by name? ", MSGCH_PROMPT ); get_input_line( specs, sizeof( specs ) ); - + + if (specs[0] == '\0') + { + canned_msg( MSG_OK ); + crawl_state.cancel_cmd_repeat(); + return; + } + spell_type type = spell_by_name(specs, true); if (type == SPELL_NO_SPELL) { mpr((one_chance_in(20)) ? "Maybe you should go back to WIZARD school." - : "I couldn't find that spell."); + : "I couldn't find that spell."); + crawl_state.cancel_cmd_repeat(); return; } - your_spells(type, 0, false); + + if (your_spells(type, 0, false) == SPRET_ABORT) + crawl_state.cancel_cmd_repeat(); } #endif @@ -430,7 +446,7 @@ void create_spec_monster_name(int x, int y) // Need to set a name for the player ghost if (mspec.mid == MONS_PLAYER_GHOST) { - unsigned char mid = mgrd[x][y]; + unsigned short mid = mgrd[x][y]; if (mid >= MAX_MONSTERS || menv[mid].type != MONS_PLAYER_GHOST) { @@ -668,6 +684,244 @@ void debug_list_monsters() #endif #ifdef WIZARD + +static void rune_from_specs(const char* _specs, item_def &item) +{ + char specs[80]; + char obj_name[ ITEMNAME_SIZE ]; + + item.sub_type = MISC_RUNE_OF_ZOT; + + if (strstr(_specs, "rune of zot")) + strncpy(specs, _specs, strlen(_specs) - strlen(" of zot")); + else + strcpy(specs, _specs); + + if (strlen(specs) > 4) + { + for (int i = 0; i < NUM_RUNE_TYPES; i++) + { + item.plus = i; + + strcpy(obj_name, item.name(DESC_PLAIN).c_str()); + + if (strstr(strlwr(obj_name), specs)) + return; + } + } + + while (true) + { + mpr( +"[a] iron [b] obsidian [c] icy [d] bone [e] slimy [f] silver", + MSGCH_PROMPT); + mpr( +"[g] serpentine [h] elven [i] golden [j] decaying [k] barnacle [l] demonic", + MSGCH_PROMPT); + mpr( +"[m] abyssal [n] glowing [o] magical [p] fiery [q] dark [r] buggy", + MSGCH_PROMPT); + mpr("Which rune (ESC to exit)? ", MSGCH_PROMPT); + + int keyin = tolower( get_ch() ); + + if (keyin == ESCAPE || keyin == ' ' + || keyin == '\r' || keyin == '\n') + { + canned_msg( MSG_OK ); + item.base_type = OBJ_UNASSIGNED; + return; + } + + if (keyin < 'a' || keyin > 'r') + continue; + + rune_type types[] = { + RUNE_DIS, + RUNE_GEHENNA, + RUNE_COCYTUS, + RUNE_TARTARUS, + RUNE_SLIME_PITS, + RUNE_VAULTS, + RUNE_SNAKE_PIT, + RUNE_ELVEN_HALLS, + RUNE_TOMB, + RUNE_SWAMP, + RUNE_SHOALS, + + RUNE_DEMONIC, + RUNE_ABYSSAL, + + RUNE_MNOLEG, + RUNE_LOM_LOBON, + RUNE_CEREBOV, + RUNE_GLOORX_VLOQ, + NUM_RUNE_TYPES + }; + + item.plus = static_cast<int>(types[keyin - 'a']); + + return; + } +} + +static void deck_from_specs(const char* _specs, item_def &item) +{ + std::string specs = _specs; + std::string type_str = ""; + + trim_string(specs); + + if (specs.find(" of ") != std::string::npos) + { + type_str = specs.substr(specs.find(" of ") + 4); + + if (type_str.find("card") != std::string::npos + || type_str.find("deck") != std::string::npos) + { + type_str = ""; + } + + trim_string(type_str); + } + + misc_item_type types[] = { + MISC_DECK_OF_ESCAPE, + MISC_DECK_OF_DESTRUCTION, + MISC_DECK_OF_DUNGEONS, + MISC_DECK_OF_SUMMONING, + MISC_DECK_OF_WONDERS, + MISC_DECK_OF_PUNISHMENT, + MISC_DECK_OF_WAR, + MISC_DECK_OF_CHANGES, + MISC_DECK_OF_DEFENSE, + NUM_MISCELLANY + }; + + item.special = DECK_RARITY_COMMON; + item.sub_type = NUM_MISCELLANY; + + if (type_str != "") + { + for (int i = 0; types[i] != NUM_MISCELLANY; i++) + { + item.sub_type = types[i]; + item.plus = 1; + init_deck(item); + // Remove "plain " from front + std::string name = item.name(DESC_PLAIN).substr(6); + item.props.clear(); + + if (name.find(type_str) != std::string::npos) + break; + } + } + + if (item.sub_type == NUM_MISCELLANY) + { + while (true) + { + mpr( +"[a] escape [b] destruction [c] dungeons [d] summoning [e] wonders", + MSGCH_PROMPT); + mpr( +"[f] punishment [g] war [h] changes [i] defense", + MSGCH_PROMPT); + mpr("Which deck (ESC to exit)? "); + + int keyin = tolower( get_ch() ); + + if (keyin == ESCAPE || keyin == ' ' + || keyin == '\r' || keyin == '\n') + { + canned_msg( MSG_OK ); + item.base_type = OBJ_UNASSIGNED; + return; + } + + if (keyin < 'a' || keyin > 'i') + continue; + + item.sub_type = types[keyin - 'a']; + break; + } + } + + const char* rarities[] = { + "plain", + "ornate", + "legendary", + NULL + }; + + int rarity_val = -1; + + for (int i = 0; rarities[i] != NULL; i++) + if (specs.find(rarities[i]) != std::string::npos) + { + rarity_val = i; + break; + } + + if (rarity_val == -1) + { + while (true) + { + mpr("[a] plain [b] ornate [c] legendary? (ESC to exit)", + MSGCH_PROMPT); + + int keyin = tolower( get_ch() ); + + if (keyin == ESCAPE || keyin == ' ' + || keyin == '\r' || keyin == '\n') + { + canned_msg( MSG_OK ); + item.base_type = OBJ_UNASSIGNED; + return; + } + + switch (keyin) + { + case 'p': keyin = 'a'; break; + case 'o': keyin = 'b'; break; + case 'l': keyin = 'c'; break; + } + + if (keyin < 'a' || keyin > 'c') + continue; + + rarity_val = keyin - 'a'; + break; + } + } + + int base = static_cast<int>(DECK_RARITY_COMMON); + deck_rarity_type rarity = + static_cast<deck_rarity_type>(base + rarity_val); + item.special = rarity; + + int num = debug_prompt_for_int("How many cards? ", false); + + if (num <= 0) + { + canned_msg( MSG_OK ); + item.base_type = OBJ_UNASSIGNED; + return; + } + + item.plus = num; + + init_deck(item); +} + +static void rune_or_deck_from_specs(const char* specs, item_def &item) +{ + if (strstr(specs, "rune")) + rune_from_specs(specs, item); + else if (strstr(specs, "deck")) + deck_from_specs(specs, item); +} + //--------------------------------------------------------------- // // create_spec_object @@ -812,6 +1066,11 @@ void create_spec_object() mpr( "What type of item? ", MSGCH_PROMPT ); get_input_line( specs, sizeof( specs ) ); + std::string temp = specs; + trim_string(temp); + lowercase(temp); + strcpy(specs, temp.c_str()); + if (specs[0] == '\0') { canned_msg( MSG_OK ); @@ -830,7 +1089,19 @@ void create_spec_object() mitm[thing_created].quantity = 1; set_ident_flags( mitm[thing_created], ISFLAG_IDENT_MASK ); - if (class_wanted == OBJ_ARMOUR) + if (class_wanted == OBJ_MISCELLANY) + { + // Leaves object unmodified if it wasn't a rune or deck + rune_or_deck_from_specs(specs, mitm[thing_created]); + + if (mitm[thing_created].base_type == OBJ_UNASSIGNED) + { + // Rune or deck creation canceled, clean up item + destroy_item(thing_created); + return; + } + } + else if (class_wanted == OBJ_ARMOUR) { if (strstr( "naga barding", specs )) { @@ -867,7 +1138,7 @@ void create_spec_object() mitm[thing_created].sub_type = i; strcpy(obj_name,mitm[thing_created].name(DESC_PLAIN).c_str()); - ptr = strstr( strlwr(obj_name), strlwr(specs) ); + ptr = strstr( strlwr(obj_name), specs ); if (ptr != NULL) { // earliest match is the winner @@ -961,8 +1232,8 @@ void create_spec_object() break; case OBJ_MISCELLANY: - // Runes to "demonic", decks have 50 cards, ignored elsewhere? - mitm[thing_created].plus = 50; + if (!is_rune(mitm[thing_created]) && !is_deck(mitm[thing_created])) + mitm[thing_created].plus = 50; break; case OBJ_FOOD: @@ -976,7 +1247,9 @@ void create_spec_object() } } - item_colour( mitm[thing_created] ); + // Deck colour (which control rarity) already set + if (!is_deck(mitm[thing_created])) + item_colour( mitm[thing_created] ); move_item_to_grid( &thing_created, you.x_pos, you.y_pos ); @@ -1063,7 +1336,7 @@ void tweak_object(void) return; char *end; - int new_value = strtol( specs, &end, 10 ); + int new_value = strtol( specs, &end, 0 ); if (new_value == 0 && end == specs) return; @@ -1175,8 +1448,8 @@ void stethoscope(int mwh) (menv[i].foe == MHITNOT) ? "none" : (menv[menv[i].foe].type == -1) ? "unassigned monster" : menv[menv[i].foe].name(DESC_PLAIN, true).c_str()), - menv[i].foe, - menv[i].foe_memory, + menv[i].foe, + menv[i].foe_memory, menv[i].target_x, menv[i].target_y ); // print resistances @@ -1221,6 +1494,8 @@ static void dump_item( const char *name, int num, const item_def &item ) get_ident_type( item.base_type, item.sub_type ) ); mprf(" x: %d; y: %d; link: %d", item.x, item.y, item.link ); + + crawl_state.cancel_cmd_repeat(); } //--------------------------------------------------------------- @@ -1507,43 +1782,224 @@ void debug_set_all_skills(void) // //--------------------------------------------------------------- #ifdef WIZARD + +static const char *mutation_type_names[] = { + "tough skin", + "strong", + "clever", + "agile", + "green scales", + "black scales", + "grey scales", + "boney plates", + "repulsion field", + "poison resistance", + "carnivorous", + "herbivorous", + "heat resistance", + "cold resistance", + "shock resistance", + "regeneration", + "fast metabolism", + "slow metabolism", + "weak", + "dopey", + "clumsy", + "teleport control", + "teleport", + "magic resistance", + "fast", + "acute vision", + "deformed", + "teleport at will", + "spit poison", + "mapping", + "breathe flames", + "blink", + "horns", + "strong stiff", + "flexible weak", + "scream", + "clarity", + "berserk", + "deterioration", + "blurry vision", + "mutation resistance", + "frail", + "robust", + "torment resistance", + "negative energy resistance", + "summon minor demons", + "summon demons", + "hurl hellfire", + "call torment", + "raise dead", + "control demons", + "pandemonium", + "death strength", + "channel hell", + "drain life", + "throw flames", + "throw frost", + "smite", + "claws", + "fangs", + "hooves", + "talons", + "paws", + "breathe poison", + "stinger", + "big wings", + "blue marks", + "green marks", + "drifting", + "saprovorous", + "shaggy fur", + "high mp", + "low mp", + "sleepiness", + "", + // from here on scales + "red scales", + "nacreous scales", + "grey2 scales", + "metallic scales", + "black2 scales", + "white scales", + "yellow scales", + "brown scales", + "blue scales", + "purple scales", + "speckled scales", + "orange scales", + "indigo scales", + "red2 scales", + "iridescent scales", + "patterned scales" +}; + bool debug_add_mutation(void) { bool success = false; char specs[80]; + if ((sizeof(mutation_type_names) / sizeof(char*)) != NUM_MUTATIONS) + { + mprf("Mutation name list has %d entries, but there are %d " + "mutations total; update mutation_type_names in debug.cc " + "to reflect current list.", + (sizeof(mutation_type_names) / sizeof(char*)), + (int) NUM_MUTATIONS); + crawl_state.cancel_cmd_repeat(); + return (false); + } + + if (you.mutation[MUT_MUTATION_RESISTANCE] > 0 && + !crawl_state.is_replaying_keys()) + { + const char* msg; + + if (you.mutation[MUT_MUTATION_RESISTANCE] == 3) + msg = "You are immune to mutations, remove immunity?"; + else + msg = "You are resistant to mutations, remove resistance?"; + + if (yesno(msg)) + { + you.mutation[MUT_MUTATION_RESISTANCE] = 0; + crawl_state.cancel_cmd_repeat(); + } + } + + bool force = yesno("Force mutation to happen?"); + + if (you.mutation[MUT_MUTATION_RESISTANCE] == 3 && !force) + { + mpr("Can't mutate when immune to mutations without forcing it."); + crawl_state.cancel_cmd_repeat(); + return (false); + } + // Yeah, the gaining message isn't too good for this... but // there isn't an array of simple mutation names. -- bwr - mpr( "Which mutation (by message when getting mutation)? ", MSGCH_PROMPT ); + mpr( "Which mutation ('any' for any, 'xom' for xom mutation)? ", + MSGCH_PROMPT ); get_input_line( specs, sizeof( specs ) ); if (specs[0] == '\0') return (false); + if (strcasecmp(specs, "any") == 0) + { + int old_resist = you.mutation[MUT_MUTATION_RESISTANCE]; + + success = mutate(RANDOM_MUTATION, true, force); + + if (old_resist < you.mutation[MUT_MUTATION_RESISTANCE] && !force) + crawl_state.cancel_cmd_repeat("Your mutation resistance has " + "increased."); + return (success); + } + + if (strcasecmp(specs, "xom") == 0) + return mutate(RANDOM_XOM_MUTATION, true, force); + + std::vector<int> partial_matches; mutation_type mutation = NUM_MUTATIONS; for (int i = 0; i < NUM_MUTATIONS; i++) { - char mut_name[80]; - const mutation_type m = static_cast<mutation_type>(i); - strncpy( mut_name, mutation_name( m, 1 ), sizeof( mut_name ) ); - - char *ptr = strstr( strlwr(mut_name), strlwr(specs) ); - if (ptr != NULL) + if (strcasecmp(specs, mutation_type_names[i]) == 0) { - // we take the first mutation that matches - mutation = m; + mutation = (mutation_type) i; break; } + + if (strstr(mutation_type_names[i] , strlwr(specs) )) + partial_matches.push_back(i); } + // If only one matching mutation, use that. if (mutation == NUM_MUTATIONS) - mpr("I can't warp you that way!"); + { + if (partial_matches.size() == 1) + mutation = (mutation_type) partial_matches[0]; + } + + if (mutation == NUM_MUTATIONS) + { + crawl_state.cancel_cmd_repeat(); + + if (partial_matches.size() == 0) + mpr("No matching mutation names."); + else + { + std::vector<std::string> matches; + + for (unsigned int i = 0, size = partial_matches.size(); + i < size; i++) + { + matches.push_back(mutation_type_names[partial_matches[i]]); + } + std::string prefix = "No exact match for mutation '" + + std::string(specs) + "', possible matches are: "; + + // Use mpr_comma_separated_list() because the list + // might be *LONG*. + mpr_comma_separated_list(prefix, matches, " and ", ", ", + MSGCH_DIAGNOSTICS); + } + + return (false); + } else { - mprf("Found: %s", mutation_name( mutation, 1 ) ); + mprf("Found #%d: %s (\"%s\")", (int) mutation, + mutation_type_names[mutation], mutation_name( mutation, 1 ) ); - const int levels = debug_prompt_for_int( "How many levels? ", false ); + const int levels = + debug_prompt_for_int( "How many levels to increase or decrease? ", + false ); if (levels == 0) { @@ -1554,7 +2010,7 @@ bool debug_add_mutation(void) { for (int i = 0; i < levels; i++) { - if (mutate( mutation )) + if (mutate( mutation, true, force )) success = true; } } @@ -1562,7 +2018,7 @@ bool debug_add_mutation(void) { for (int i = 0; i < -levels; i++) { - if (delete_mutation( mutation )) + if (delete_mutation( mutation, force )) success = true; } } @@ -2336,12 +2792,17 @@ void debug_card() mpr("Unknown card."); return; } - + + std::string wanted = buf; + lowercase(wanted); + bool found_card = false; for ( int i = 0; i < NUM_CARDS; ++i ) { const card_type c = static_cast<card_type>(i); - if ( strstr(card_name(c), buf) != NULL ) + std::string card = card_name(c); + lowercase(card); + if ( card.find(wanted) != std::string::npos ) { card_effect(c, DECK_RARITY_LEGENDARY); found_card = true; @@ -2463,14 +2924,42 @@ void debug_place_map() debug_load_map_by_name(what); } -void debug_dismiss_all_monsters() +void debug_dismiss_all_monsters(bool force_all) { - // Genocide... "unsummon" all the monsters from the level. + char buf[80]; + if (!force_all) + { + mpr("Regex of monsters to dismiss (ENTER for all): ", MSGCH_PROMPT); + bool validline = !cancelable_get_line(buf, sizeof buf, 80); + + if (!validline) + { + canned_msg( MSG_OK ); + return; + } + } + + // Dismiss all + if (buf[0] == '\0' || force_all) + { + // Genocide... "unsummon" all the monsters from the level. + for (int mon = 0; mon < MAX_MONSTERS; mon++) + { + monsters *monster = &menv[mon]; + + if (monster->alive()) + monster_die(monster, KILL_DISMISSED, 0); + } + return; + } + + // Dismiss by regex + text_pattern tpat(buf); for (int mon = 0; mon < MAX_MONSTERS; mon++) { monsters *monster = &menv[mon]; - if (monster->alive()) + if (monster->alive() && tpat.matches(monster->name(DESC_PLAIN))) monster_die(monster, KILL_DISMISSED, 0); } } @@ -2523,7 +3012,7 @@ static void debug_destroy_doors() // f) Counts number of turns needed to explore the level. void debug_test_explore() { - debug_dismiss_all_monsters(); + debug_dismiss_all_monsters(true); debug_kill_traps(); forget_map(100); |