The &" command now shows the total experience value of all monster on the level.
&G now prevents dismissed monsters from dropping their original equipment, except for unrandarts and fixed arts. You can force the dismissed monsters to drop all of their non-summoned items by adding "keepitem" to the regexp string.
&R can now either change the random monster spawn rate for the current level, or immediately spawn a given number of random monsters.
&^D can be used to examine and alter player enchantments/durations.
The targeting command "S" can be used to turn a permanent monster into a summoned one.
The targeting command "~" can be used to polymorph a monster into one of a particular type.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7870 c06c8d41-db1a-0410-9941-cceddc491573
2WWSPLCXLSMBGTXUC33EQ5YBOA5IBFSMJSTZ2TU6HZIMZZWZJWGAC J7VTRSN2BLWL7QJMHG73LBUOUL6WNNT2ZAVEDMGYB6SDX3L5GGYQC 5IWO6LXJBETPTZA7F67UJURUU3FWGFBHRZILC7KQ2KJQSMTIS66AC 3DQXSE4YGFBBDUWK4YEOFWW4UPWILWELFSLP37SL6BERGAZJC5YAC L254F6ZIU2HWGLFFGPIORTN4C3TDQ3E5JZ7Z7GQA5AEDIKL6PKDAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC O7S3ILRELHICJXXTDGMF7KPPZWYHPYCNDPV2I77FZXXH4I454B4QC SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC Y4NA3JSN63RLATF4NNBPSR5CWF5Z7UEMWCGVX4B6NOAR47CGM4GQC HZ7DYCFH4VUDNUBNP5Z2HSYJWJRIVUEQVYWG7NTCMYNZJQT7NIPQC L5CVPV5IUBSO4EE3WK4O6SQGIMIEPSMQONFBWEVGJBR2HATLPZIAC BW3XFNOS6LDAQLHOZ6RXARCMKCY5JVLVDSXDSSAX4DSYM3FANQBAC KFZYPFHHOWRUZEK2PW26EI73Z6I6DLHW2YEJV2CB5XBWFRRNBFXQC FSD7GIK3YLZXWLEH37BU6KV3IUCFGXPQL6IZ7H65YWNRBEKDBX5AC X5OHFTHRXTI5KHFIYFJ6DB3W5MY3JUJKNTL4HF37MKABYNCOBOZAC 3IMZJEIBQTRXX5OLN7NUZ3QSGNVH2VPVTBDESVVWXIYURTHF3VXAC 3FBKOX4Y5QYPMBOCSAMHNZXCY7Z75YDQDL4EJZHZIGDXL7RMZ7TAC ZNMT5CZHP2FC4HTLNA7KYEDGFBXSCUE5QHJOALVPE6RDPHSEDXRQC Y5RFQ6KNJCBQUSV2T6WDR7TPZLZYLOAWBVMUTHDXGOZQDZ2U423AC RV4L36J3DCVW3SONFFYAVK44XJQOFVNPGKHET7VOIFYHWZHCJRNAC J6APXOT4QOGQFONWB7G546VTVF6QG42HVOROMHF7YBDJPR4K26OAC BINKDWGFGUPTOA7IE5KK4ZIELGU5WC3X47MYXOWU4X43EGAC5DUAC UEI5JAVCMN7Y2SACTEZPZSNFJWOJTC55G24Q6LKQCT4XNDH5ZQIAC Y2NYY7HWFZ2LQDK3ACSLGS37F2J2IJ5LRGCIMZYXLEOSVPD3A4DAC 46MRRHVYJ3BS74R2BEVUWEWJCI4FCRBSLZ3NWMQCE6FUCNE5P73QC CCRQESB4ADT4WA7FGLNZZXAJ6G5QMCTYCZIWORBN45P6ZPILC34AC 4FQAKUKUO6PCAZ3N4HUR5XL6E4VA5UQUZ3AEDGRBLVY7W2LMWI7QC 4QRLZDW4KBFG34B3MCG4375NHFR3WKWSLWQKRMQ3OE5R26WCZBBQC 36DYXIWAQTBOCZBCUPYWDKAXVWDU3TRMSM3OCQZGGMWE2KPERJMAC FWNNTOEERPUKXPE4OC52UABFZLKIU3O5GRNNLDK4QI4HR2IOU36QC QO5ZJWQ3JK3PEGBPTQSAYIPEJEHG2M2KTD74227G5VG7DVXUL3BQC YFIVTYI7PMVAXV23DUPXPAQNEY3YSFIXQGSN32I3WVHMMD5XS5DQC CIPVRZGLOZHCERK6YPOBV3P2E4IAB4H6D5EHLRQE2O5E4P4VCBUAC 5BJPWUPLJFS34FUTFJVKA4A52YMIGV6EWDXLNSDCWBJWBGVSQFGQC 7GJR755MBM55KIOP3DGSZIIAEQ5E2PRBHLEXZOU2ZMXHHZ5JI3GQC case CMD_TARGET_WIZARD_MAKE_SUMMONED:if (!you.wizard || !in_bounds(moves.target))break;mid = mgrd(moves.target);if (mid == NON_MONSTER) // can put in terrain description herebreak;wizard_make_monster_summoned(&menv[mid]);break;case CMD_TARGET_WIZARD_POLYMORPH:if (!you.wizard || !in_bounds(moves.target))break;mid = mgrd(moves.target);if (mid == NON_MONSTER) // can put in terrain description herebreak;wizard_polymorph_monster(&menv[mid]);break;
#endif
// Returns whether an item of this type can be an artefact.static bool _item_type_can_be_artefact( int type){return (type == OBJ_WEAPONS || type == OBJ_ARMOUR || type == OBJ_JEWELLERY|| type == OBJ_BOOKS);}static bool _make_book_randart(item_def &book){char type;do{mpr("Make book fixed [t]heme or fixed [l]evel? ", MSGCH_PROMPT);type = tolower(getch());} while (type != 't' && type != 'l');if (type == 'l')return make_book_level_randart(book);elsereturn make_book_theme_randart(book);}void wizard_make_object_randart(){int i = prompt_invent_item( "Make an artefact out of which item?",MT_INVLIST, -1 );if (prompt_failed(i))return;item_def &item(you.inv[i]);if (!_item_type_can_be_artefact(item.base_type)){mpr("That item cannot be turned into an artefact.");return;}int j;// Set j == equipment slot of chosen item, remove old randart benefits.for (j = 0; j < NUM_EQUIP; j++){if (you.equip[j] == i){if (j == EQ_WEAPON)you.wield_change = true;if (is_random_artefact( item ))unuse_randart( i );break;}}if (is_random_artefact(item)){if (!yesno("Is already a randart; wipe and re-use?")){canned_msg( MSG_OK );// If equipped, re-apply benefits.if (j != NUM_EQUIP)use_randart( i );return;}item.special = 0;item.flags &= ~ISFLAG_RANDART;item.props.clear();}mpr("Fake item as gift from which god (ENTER to leave alone): ",MSGCH_PROMPT);char name[80];if (!cancelable_get_line( name, sizeof( name ) ) && name[0]){god_type god = string_to_god(name, false);if (god == GOD_NO_GOD)mpr("No such god, leaving item origin alone.");else{mprf("God gift of %s.", god_name(god, false).c_str());item.orig_monnum = -god;}}if (item.base_type == OBJ_BOOKS){if (!_make_book_randart(item)){mpr("Failed to turn book into randart.");return;}}else if (!make_item_randart( item )){mpr("Failed to turn item into randart.");return;}if (Options.autoinscribe_randarts){add_autoinscription(item,randart_auto_inscription(you.inv[i]));}// If equipped, apply new randart benefits.if (j != NUM_EQUIP)use_randart( i );
static const char* dur_names[NUM_DURATIONS] ={"invis","conf","paralysis","slow","mesmerised","haste","might","levitation","berserker","poisoning","confusing touch","sure blade","backlight","deaths door","fire shield","building rage","exhausted","liquid flames","icy armour","repel missiles","prayer","piety pool","divine vigour","divine stamina","divine shield","regeneration","swiftness","stonemail","controlled flight","teleport","control teleport","breath weapon","transformation","death channel","deflect missiles","forescry","see invisible","weapon brand","silence","condensation shield","stoneskin","repel undead","gourmand","bargain","insulation","resist poison","resist fire","resist cold","slaying","stealth","magic shield","sleep","sage","telepathy","petrified","lowered mr","repel stairs move","repel stairs climb"};void wizard_edit_durations( void ){std::vector<int> durs;size_t max_len = 0;for (int i = 0; i < NUM_DURATIONS; i++){if (!you.duration[i])continue;max_len = std::max(strlen(dur_names[i]), max_len);durs.push_back(i);}if (durs.size() > 0){for (unsigned int i = 0; i < durs.size(); i++){int dur = durs[i];mprf(MSGCH_PROMPT, "%c) %-*s : %d", 'a' + i, max_len,dur_names[dur], you.duration[dur]);}mpr("", MSGCH_PROMPT);mpr("Edit which duration (letter or name)? ", MSGCH_PROMPT);}elsempr("Edit which duration (name)? ", MSGCH_PROMPT);char buf[80];if (cancelable_get_line_autohist(buf, sizeof buf) || strlen(buf) == 0){canned_msg( MSG_OK );return;}strcpy(buf, lowercase_string(trimmed_string(buf)).c_str());if (strlen(buf) == 0){canned_msg( MSG_OK );return;}int choice = -1;if (strlen(buf) == 1){if (durs.size() == 0){mpr("No existing durations to choose from.", MSGCH_PROMPT);return;}choice = buf[0] - 'a';if (choice < 0 || choice >= (int) durs.size()){mpr("Invalid choice.", MSGCH_PROMPT);return;}choice = durs[choice];}else{std::vector<int> matches;std::vector<std::string> match_names;max_len = 0;for (int i = 0; i < NUM_DURATIONS; i++){if (strcmp(dur_names[i], buf) == 0){choice = i;break;}if (strstr(dur_names[i], buf) != NULL){matches.push_back(i);match_names.push_back(dur_names[i]);}}if (choice != -1);else if (matches.size() == 1)choice = matches[0];else if (matches.size() == 0){mprf(MSGCH_PROMPT, "No durations matching '%s'.", buf);return;}else{std::string prefix = "No exact match for duration '";prefix += buf;prefix += "', possible matches are: ";mpr_comma_separated_list(prefix, match_names, " and ", ", ",MSGCH_DIAGNOSTICS);return;}}sprintf(buf, "Set '%s' to: ", dur_names[choice]);int num = _debug_prompt_for_int(buf, false);if (num == 0){mpr("Can't set duration directly to 0, setting it to 1 instead.",MSGCH_PROMPT);num = 1;}you.duration[choice] = num;}
}// Make all of the monster's original equipment disappear, unless it's a fixed// artefact or unrand artefact.static void _vanish_orig_eq(monsters* mons){for (int i = 0; i < NUM_MONSTER_SLOTS; i++){if (mons->inv[i] == NON_ITEM)continue;item_def &item(mitm[mons->inv[i]]);if (!is_valid_item(item))continue;if (item.orig_place != 0 || item.orig_monnum != 0|| !item.inscription.empty()|| is_unrandom_artefact(item)|| is_fixed_artefact(item)|| (item.flags & (ISFLAG_DROPPED | ISFLAG_THROWN | ISFLAG_NOTED_GET| ISFLAG_BEEN_IN_INV) ) ){continue;}item.flags |= ISFLAG_SUMMONED;}
}// Make all of the monsters' original equipment disappear unless "keepitem"// is found in the regex (except for fixed arts and unrand arts).bool keep_item = false;if (strstr(buf, "keepitem") != NULL){std::string str = replace_all(buf, "keepitem", "");trim_string(str);strcpy(buf, str.c_str());keep_item = true;
}void wizard_make_monster_summoned(monsters* mon){int summon_type = 0;if (mon->is_summoned(NULL, &summon_type) || summon_type != 0){mpr("Monster is already summoned.", MSGCH_PROMPT);return;}if (mons_is_unique(mon->type)){mpr("Can't make unique monsters summoned.");return;}int dur = _debug_prompt_for_int("What summon longevity (1 to 6)? ", true);if (dur < 1 || dur > 6){canned_msg( MSG_OK );return;}mpr("[a] clone [b] animated [c] chaos [d] miscast [e] zot", MSGCH_PROMPT);mpr("[f] wrath [g] aid [m] misc [s] spell",MSGCH_PROMPT);mpr("Which summon type? ", MSGCH_PROMPT);char choice = tolower(getch());if (!(choice >= 'a' && choice <= 'g') && choice != 'm' && choice != 's'){canned_msg( MSG_OK );return;}int type = 0;switch (choice){case 'a': type = MON_SUMM_CLONE; break;case 'b': type = MON_SUMM_ANIMATE; break;case 'c': type = MON_SUMM_CHAOS; break;case 'd': type = MON_SUMM_MISCAST; break;case 'e': type = MON_SUMM_ZOT; break;case 'f': type = MON_SUMM_WRATH; break;case 'g': type = MON_SUMM_AID; break;case 'm': type = 0; break;case 's':{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 );return;}spell_type spell = spell_by_name(specs, true);if (spell == SPELL_NO_SPELL){mpr("No such spell.", MSGCH_PROMPT);return;}type = (int) spell;break;}default:DEBUGSTR("Invalid summon type choice.");break;}mon->mark_summoned(dur, true, type);}void wizard_polymorph_monster(monsters* mon){int old_type = mon->type;int type = _debug_prompt_for_monster();if (type == -1){canned_msg( MSG_OK );return;}if (invalid_monster_class(type) || type == MONS_PROGRAM_BUG){mpr("Invalid monster type.", MSGCH_PROMPT);return;}if (type == old_type){mpr("Old type and new type are the same, not polymorphing.");return;}if (mons_species(type) == mons_species(old_type)){mpr("Target species must be different than current species.");return;}monster_polymorph(mon, (monster_type) type, PPT_SAME, true);if (!mon->alive()){mpr("Polymorph killed monster?", MSGCH_ERROR);return;}mon->check_redraw(mon->pos());if (mon->type == old_type)mpr("Polymorph failed.");else if (mon->type != type)mpr("Monster turned into something other than the desired type.");
// Returns whether an item of this type can be an artefact, or cursed.static bool _item_type_can_be_artefact( int type){return (type == OBJ_WEAPONS || type == OBJ_ARMOUR || type == OBJ_JEWELLERY|| type == OBJ_BOOKS);}static bool _make_book_randart(item_def &book)
// Returns whether an item of this type can be cursed.static bool _item_type_can_be_cursed( int type)
char type;do{mpr("Make book fixed [t]heme or fixed [l]evel? ", MSGCH_PROMPT);type = tolower(getch());} while (type != 't' && type != 'l');if (type == 'l')return make_book_level_randart(book);elsereturn make_book_theme_randart(book);
return (type == OBJ_WEAPONS || type == OBJ_ARMOUR || type == OBJ_JEWELLERY);
case '+':{int i = prompt_invent_item( "Make an artefact out of which item?",MT_INVLIST, -1 );if (prompt_failed(i))break;item_def &item(you.inv[i]);if (!_item_type_can_be_artefact(item.base_type)){mpr("That item cannot be turned into an artefact.");break;}int j;// Set j == equipment slot of chosen item, remove old randart benefits.for (j = 0; j < NUM_EQUIP; j++){if (you.equip[j] == i){if (j == EQ_WEAPON)you.wield_change = true;if (is_random_artefact( item ))unuse_randart( i );break;}}if (is_random_artefact(item)){if (!yesno("Is already a randart; wipe and re-use?")){canned_msg( MSG_OK );// If equipped, re-apply benefits.if (j != NUM_EQUIP)use_randart( i );return;}item.special = 0;item.flags &= ~ISFLAG_RANDART;item.props.clear();}mpr("Fake item as gift from which god (ENTER to leave alone): ",MSGCH_PROMPT);char name[80];if (!cancelable_get_line( name, sizeof( name ) ) && name[0]){god_type god = string_to_god(name, false);if (god == GOD_NO_GOD)mpr("No such god, leaving item origin alone.");else{mprf("God gift of %s.", god_name(god, false).c_str());item.orig_monnum = -god;}}if (item.base_type == OBJ_BOOKS){if (!_make_book_randart(item)){mpr("Failed to turn book into randart.");break;}}else if (!make_item_randart( item )){mpr("Failed to turn item into randart.");break;}if (Options.autoinscribe_randarts){add_autoinscription(item,randart_auto_inscription(you.inv[i]));}// If equipped, apply new randart benefits.if (j != NUM_EQUIP)use_randart( i );
}else{// 50 spots are reserved for non-wandering monsters.int max_spawn = MAX_MONSTERS - 50;for (int i = 0; i < MAX_MONSTERS; i++){if (menv[i].alive())max_spawn--;}if (max_spawn <= 0){mpr("Level already filled with monsters, get rid of some ""of them first.", MSGCH_PROMPT);return;}sprintf(specs, "Spawn how many random monsters (max %d)? ",max_spawn);mpr(specs, MSGCH_PROMPT );if (cancelable_get_line( specs, sizeof( specs ) )|| strlen(specs) == 0){canned_msg( MSG_OK );break;}int num = atoi(specs);if (num <= 0){canned_msg( MSG_OK );break;}num = std::max(num, max_spawn);int curr_rate = env.spawn_random_rate;// Each call to spawn_random_monsters() will spawn one with// the rate at 5 or less.env.spawn_random_rate = 5;for (int i = 0; i < num; i++)spawn_random_monsters();env.spawn_random_rate = curr_rate;