summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-20 02:26:25 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-20 02:26:25 +0000
commitcd4f718dbcb7974ef1762c87b5e13f0a38df0961 (patch)
treea9fda3e09706d01703795039d33ab9db9a6d1a2a /crawl-ref/source
parentf4cd5aede38a820cc5ab7137b8cc1a0927ae7f3e (diff)
downloadcrawl-ref-cd4f718dbcb7974ef1762c87b5e13f0a38df0961.tar.gz
crawl-ref-cd4f718dbcb7974ef1762c87b5e13f0a38df0961.zip
Some wizard/debugging commands:
* 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
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/acr.cc192
-rw-r--r--crawl-ref/source/command.cc3
-rw-r--r--crawl-ref/source/debug.cc485
-rw-r--r--crawl-ref/source/debug.h7
-rw-r--r--crawl-ref/source/directn.cc21
5 files changed, 592 insertions, 116 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index c64a720a74..b4b200708d 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -426,27 +426,10 @@ static void _startup_tutorial()
}
#ifdef WIZARD
-// Returns whether an item of this type can be an artefact, or cursed.
-static bool _item_type_can_be_artefact( int type)
+// Returns whether an item of this type can be cursed.
+static bool _item_type_can_be_cursed( 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);
- else
- return make_book_theme_randart(book);
+ return (type == OBJ_WEAPONS || type == OBJ_ARMOUR || type == OBJ_JEWELLERY);
}
static void _do_wizard_command(int wiz_command, bool silent_fail)
@@ -522,95 +505,11 @@ static void _do_wizard_command(int wiz_command, bool silent_fail)
break;
}
- 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 );
-
- mpr( item.name(DESC_INVENTORY_EQUIP).c_str() );
+ case '+':
+ wizard_make_object_randart();
break;
- }
+
case '|':
// Create all unrandarts.
for (tmp = 1; tmp < NO_UNRANDARTS; tmp++)
@@ -688,10 +587,10 @@ static void _do_wizard_command(int wiz_command, bool silent_fail)
if (item_cursed(item))
do_uncurse_item(item);
- else if (_item_type_can_be_artefact(item.base_type))
+ else if (_item_type_can_be_cursed(item.base_type))
do_curse_item(item);
else
- mpr("That item cannot be cursed.");
+ mpr("That type of item cannot be cursed.");
break;
}
@@ -805,16 +704,77 @@ static void _do_wizard_command(int wiz_command, bool silent_fail)
break;
case 'R':
- sprintf(specs, "Set monster spawn rate to what? (now %d) ",
- env.spawn_random_rate);
- mpr( specs, MSGCH_PROMPT );
+ mpr( "(c)hange spawn rate or (s)pawn monsters? ", MSGCH_PROMPT );
+ tmp = tolower(getch());
- get_input_line( specs, sizeof( specs ) );
- if (specs[0] != '\0')
+ if (tmp != 'c' && tmp != 's')
{
+ canned_msg( MSG_OK );
+ break;
+ }
+
+ if (tmp == 'c')
+ {
+ sprintf(specs, "Set monster spawn rate to what? (now %d) ",
+ env.spawn_random_rate);
+ mpr(specs, MSGCH_PROMPT );
+
+ if (cancelable_get_line( specs, sizeof( specs ) )
+ || strlen(specs) == 0)
+ {
+ canned_msg( MSG_OK );
+ break;
+ }
+
if (tmp = atoi(specs))
env.spawn_random_rate = tmp;
}
+ 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;
+ }
break;
case 'r':
@@ -1065,6 +1025,10 @@ static void _do_wizard_command(int wiz_command, bool silent_fail)
wizard_set_stats();
break;
+ case CONTROL('D'):
+ wizard_edit_durations();
+ break;
+
case '^':
{
if (you.religion == GOD_NO_GOD)
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index eec9382a82..e7d5dbb441 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -763,11 +763,13 @@ static const char *targeting_help_1 =
"<h>Wizard targeting comands:</h>\n"
"<w>g</w>: give item to monster\n"
"<w>s</w>: force monster to shout or speak\n"
+ "<w>S</w>: make monster a summoned monster\n"
"<w>F</w>: cycle monster friendly/good neutral/neutral/hostile\n"
"<w>P</w>: apply divine blessing to monster\n"
"<w>m</w>: move monster or player\n"
"<w>M</w>: cause spell miscast for monster or player\n"
"<w>w</w>: calculate shortest path to any point on the map\n"
+ "<w>~</w>: polymorph monster to specific type\n"
#endif
;
@@ -2260,6 +2262,7 @@ int list_wizard_commands(bool do_redraw_screen)
"<w>^</w> : gain piety\n"
"<w>_</w> : gain religion\n"
"<w>@</w> : set Str Int Dex\n"
+ "<w>Ctrl-D</w> : change enchantments/durations\n"
"\n"
"<yellow>Other player related effects</yellow>\n"
"<w>c</w> : card effect\n"
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index 51bb7ceb5c..806be6e4ab 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -837,6 +837,8 @@ void debug_list_monsters()
std::sort(mon_nums, mon_nums + MAX_MONSTERS, _sort_monster_list);
+ int total_exp = 0, total_adj_exp = 0;
+
std::string prev_name = "";
int count = 0;
@@ -862,6 +864,19 @@ void debug_list_monsters()
nfound++;
count++;
prev_name = name;
+
+ int exp = exper_value(m);
+ total_exp += exp;
+
+ if ((m->flags & (MF_WAS_NEUTRAL | MF_CREATED_FRIENDLY))
+ || m->has_ench(ENCH_ABJ))
+ {
+ continue;
+ }
+ if (m->flags & MF_GOT_HALF_XP)
+ exp /= 2;
+
+ total_adj_exp += exp;
}
char buf[80];
@@ -872,7 +887,13 @@ void debug_list_monsters()
mons.push_back(buf);
mpr_comma_separated_list("Monsters: ", mons);
- mprf("%d monsters", nfound);
+
+ if (total_adj_exp == total_exp)
+ mprf("%d monsters, %d total exp value",
+ nfound, total_exp);
+ else
+ mprf("%d monsters, %d total exp value (%d adjusted)",
+ nfound, total_exp, total_adj_exp);
}
#endif
@@ -1824,8 +1845,119 @@ void wizard_tweak_object(void)
}
}
}
-#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);
+ else
+ return 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 );
+
+ mpr( item.name(DESC_INVENTORY_EQUIP).c_str() );
+}
+#endif
#ifdef DEBUG_DIAGNOSTICS
// Prints a number of useful (for debugging, that is) stats on monsters.
@@ -3750,6 +3882,182 @@ void wizard_set_stats()
you.redraw_evasion = true;
}
+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);
+ }
+ else
+ mpr("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;
+}
+
void wizard_draw_card()
{
msg::streams(MSGCH_PROMPT) << "Which card? " << std::endl;
@@ -3890,6 +4198,33 @@ void debug_place_map()
debug_load_map_by_name(what);
}
+// 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;
+ }
+}
+
// Dismisses all monsters on the level or all monsters that match a user
// specified regex.
void wizard_dismiss_all_monsters(bool force_all)
@@ -3907,6 +4242,18 @@ void wizard_dismiss_all_monsters(bool force_all)
}
}
+ // 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;
+ }
+
// Dismiss all
if (buf[0] == '\0' || force_all)
{
@@ -3916,7 +4263,11 @@ void wizard_dismiss_all_monsters(bool force_all)
monsters *monster = &menv[mon];
if (monster->alive())
+ {
+ if (!keep_item)
+ _vanish_orig_eq(monster);
monster_die(monster, KILL_DISMISSED, NON_MONSTER, false, true);
+ }
}
return;
}
@@ -3928,7 +4279,11 @@ void wizard_dismiss_all_monsters(bool force_all)
monsters *monster = &menv[mon];
if (monster->alive() && tpat.matches(monster->name(DESC_PLAIN)))
+ {
+ if (!keep_item)
+ _vanish_orig_eq(monster);
monster_die(monster, KILL_DISMISSED, NON_MONSTER, false, true);
+ }
}
}
@@ -4376,6 +4731,132 @@ void wizard_move_player_or_monster(const coord_def& where)
already_moving = false;
}
+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.");
+}
+
void debug_pathfind(int mid)
{
if (mid == NON_MONSTER)
diff --git a/crawl-ref/source/debug.h b/crawl-ref/source/debug.h
index 7fe31e996c..22a62a0333 100644
--- a/crawl-ref/source/debug.h
+++ b/crawl-ref/source/debug.h
@@ -73,6 +73,7 @@ void wizard_create_spec_monster(void);
void wizard_create_spec_monster_name(void);
void wizard_create_spec_object(void);
void wizard_tweak_object(void);
+void wizard_make_object_randart(void);
void wizard_exercise_skill(void);
void wizard_set_skill_level(void);
void wizard_set_all_skills(void);
@@ -81,6 +82,7 @@ void wizard_change_species( void );
void wizard_set_xl();
void wizard_get_religion( void );
void wizard_set_stats( void );
+void wizard_edit_durations( void );
void wizard_draw_card();
void wizard_dismiss_all_monsters(bool force_all = false);
void wizard_place_stairs( bool down );
@@ -89,6 +91,7 @@ void wizard_interlevel_travel();
void debug_make_trap( void );
void debug_make_shop( void );
void debug_place_map();
+
// Honest debugging functions.
void debug_item_scan( void );
void debug_mons_scan();
@@ -109,10 +112,14 @@ void debug_stethoscope(int mon);
class monsters;
class coord_def;
+
void wizard_apply_monster_blessing(monsters* mon);
void wizard_give_monster_item(monsters* mon);
void wizard_move_player_or_monster(const coord_def& where);
+void wizard_make_monster_summoned(monsters* mon);
+void wizard_polymorph_monster(monsters* mon);
void debug_make_monster_shout(monsters* mon);
+
void debug_pathfind(int mid);
void debug_miscast( int target );
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index d6d09117d8..f07d04864c 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -1415,6 +1415,27 @@ void direction(dist& moves, targeting_type restricts,
debug_miscast(mid);
break;
+
+ 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 here
+ break;
+
+ 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 here
+ break;
+
+ wizard_polymorph_monster(&menv[mid]);
+ break;
+
#endif
case CMD_TARGET_DESCRIBE:
full_describe_square(moves.target);