3 * Summary: Monster related debugging functions.
4 * Written by: Linley Henzell and Jesse Jones
26 #include "map_knowledge.h"
29 #include "mgen_data.h"
31 #include "mon-pathfind.h"
32 #include "mon-place.h"
33 #include "mon-speak.h"
34 #include "mon-stuff.h"
40 #include "spl-miscast.h"
48 // Creates a specific monster by mon type number.
49 void wizard_create_spec_monster(void)
51 int mon
= prompt_for_int("Which monster by number? ", true);
53 if (mon
== -1 || (mon
>= NUM_MONSTERS
54 && mon
!= RANDOM_MONSTER
55 && mon
!= RANDOM_DRACONIAN
56 && mon
!= RANDOM_BASE_DRACONIAN
57 && mon
!= RANDOM_NONBASE_DRACONIAN
58 && mon
!= WANDERING_MONSTER
))
65 mgen_data::sleeper_at(
66 static_cast<monster_type
>(mon
), you
.pos()));
70 // Creates a specific monster by name. Uses the same patterns as
72 void wizard_create_spec_monster_name()
75 mpr("Which monster by name? ", MSGCH_PROMPT
);
76 if (cancelable_get_line_autohist(specs
, sizeof specs
) || !*specs
)
83 std::string err
= mlist
.add_mons(specs
);
88 // Try for a partial match, but not if the user accidentally entered
89 // only a few letters.
90 monster_type partial
= get_monster_by_name(specs
);
91 if (strlen(specs
) >= 3 && partial
!= MONS_NO_MONSTER
)
94 newerr
= mlist
.add_mons(mons_type_name(partial
, DESC_PLAIN
));
104 mons_spec mspec
= mlist
.get_monster(0);
107 mpr("Such a monster couldn't be found.", MSGCH_DIAGNOSTICS
);
111 int type
= mspec
.mid
;
112 if (mons_class_is_zombified(mspec
.mid
))
113 type
= mspec
.monbase
;
115 coord_def place
= find_newmons_square(type
, you
.pos());
116 if (!in_bounds(place
))
118 // Try again with habitat HT_LAND.
119 // (Will be changed to the necessary terrain type in dgn_place_monster.)
120 place
= find_newmons_square(MONS_NO_MONSTER
, you
.pos());
123 if (!in_bounds(place
))
125 mpr("Found no space to place monster.", MSGCH_DIAGNOSTICS
);
129 // Wizmode users should be able to conjure up uniques even if they
130 // were already created. Yay, you can meet 3 Sigmunds at once! :p
131 if (mons_is_unique(mspec
.mid
) && you
.unique_creatures
[mspec
.mid
])
132 you
.unique_creatures
[mspec
.mid
] = false;
134 if (dgn_place_monster(mspec
, you
.absdepth0
, place
, true, false) == -1)
136 mpr("Unable to place monster.", MSGCH_DIAGNOSTICS
);
140 if (mspec
.mid
== MONS_KRAKEN
)
142 unsigned short mid
= mgrd(place
);
144 if (mid
>= MAX_MONSTERS
|| menv
[mid
].type
!= MONS_KRAKEN
)
146 for (mid
= 0; mid
< MAX_MONSTERS
; mid
++)
148 if (menv
[mid
].type
== MONS_KRAKEN
&& menv
[mid
].alive())
150 menv
[mid
].colour
= element_colour(ETC_KRAKEN
);
155 if (mid
>= MAX_MONSTERS
)
157 mpr("Couldn't find player kraken!");
162 // FIXME: This is a bit useless, seeing how you cannot set the
163 // ghost's stats, brand or level, among other things.
164 if (mspec
.mid
== MONS_PLAYER_GHOST
)
166 unsigned short mid
= mgrd(place
);
168 if (mid
>= MAX_MONSTERS
|| menv
[mid
].type
!= MONS_PLAYER_GHOST
)
170 for (mid
= 0; mid
< MAX_MONSTERS
; mid
++)
172 if (menv
[mid
].type
== MONS_PLAYER_GHOST
173 && menv
[mid
].alive())
180 if (mid
>= MAX_MONSTERS
)
182 mpr("Couldn't find player ghost, probably going to crash.");
187 monster
&mon
= menv
[mid
];
190 ghost
.name
= "John Doe";
193 msgwin_get_line("Make player ghost which species? (case-sensitive) ",
194 input_str
, sizeof(input_str
));
196 species_type sp_id
= get_species_by_abbrev(input_str
);
197 if (sp_id
== SP_UNKNOWN
)
198 sp_id
= str_to_species(input_str
);
199 if (sp_id
== SP_UNKNOWN
)
201 mpr("No such species, making it Human.");
204 ghost
.species
= static_cast<species_type
>(sp_id
);
206 msgwin_get_line("Give player ghost which background? ",
207 input_str
, sizeof(input_str
));
209 int job_id
= get_job_by_abbrev(input_str
);
211 if (job_id
== JOB_UNKNOWN
)
212 job_id
= get_job_by_name(input_str
);
214 if (job_id
== JOB_UNKNOWN
)
216 mpr("No such background, making it a Fighter.");
217 job_id
= JOB_FIGHTER
;
219 ghost
.job
= static_cast<job_type
>(job_id
);
222 mon
.set_ghost(ghost
);
224 ghosts
.push_back(ghost
);
228 static bool _sort_monster_list(int a
, int b
)
230 const monster
* m1
= &menv
[a
];
231 const monster
* m2
= &menv
[b
];
233 if (m1
->alive() != m2
->alive())
235 else if (!m1
->alive())
238 if (m1
->type
== m2
->type
)
240 if (!m1
->alive() || !m2
->alive())
243 return (m1
->name(DESC_PLAIN
, true) < m2
->name(DESC_PLAIN
, true));
246 const unsigned glyph1
= mons_char(m1
->type
);
247 const unsigned glyph2
= mons_char(m2
->type
);
248 if (glyph1
!= glyph2
)
250 return (glyph1
< glyph2
);
253 return (m1
->type
< m2
->type
);
256 void debug_list_monsters()
258 std::vector
<std::string
> mons
;
261 int mon_nums
[MAX_MONSTERS
];
263 for (int i
= 0; i
< MAX_MONSTERS
; ++i
)
266 std::sort(mon_nums
, mon_nums
+ MAX_MONSTERS
, _sort_monster_list
);
268 int total_exp
= 0, total_adj_exp
= 0, total_nonuniq_exp
= 0;
270 std::string prev_name
= "";
273 for (int i
= 0; i
< MAX_MONSTERS
; ++i
)
275 const int idx
= mon_nums
[i
];
276 if (invalid_monster_index(idx
))
279 const monster
* mi(&menv
[idx
]);
283 std::string name
= mi
->name(DESC_PLAIN
, true);
285 if (prev_name
!= name
&& count
> 0)
289 snprintf(buf
, sizeof(buf
), "%d %s", count
,
290 pluralise(prev_name
).c_str());
292 snprintf(buf
, sizeof(buf
), "%s", prev_name
.c_str());
301 int exp
= exper_value(mi
);
303 if (!mons_is_unique(mi
->type
))
304 total_nonuniq_exp
+= exp
;
306 if ((mi
->flags
& (MF_WAS_NEUTRAL
| MF_NO_REWARD
))
307 || mi
->has_ench(ENCH_ABJ
))
311 if (mi
->flags
& MF_GOT_HALF_XP
)
314 total_adj_exp
+= exp
;
319 snprintf(buf
, sizeof(buf
), "%d %s", count
, pluralise(prev_name
).c_str());
321 snprintf(buf
, sizeof(buf
), "%s", prev_name
.c_str());
324 mpr_comma_separated_list("Monsters: ", mons
);
326 if (total_adj_exp
== total_exp
)
328 mprf("%d monsters, %d total exp value (%d non-uniq)",
329 nfound
, total_exp
, total_nonuniq_exp
);
333 mprf("%d monsters, %d total exp value (%d non-uniq, %d adjusted)",
334 nfound
, total_exp
, total_nonuniq_exp
, total_adj_exp
);
338 void wizard_spawn_control()
340 mpr("(c)hange spawn rate or (s)pawn monsters? ", MSGCH_PROMPT
);
341 const int c
= tolower(getchm());
348 mprf(MSGCH_PROMPT
, "Set monster spawn rate to what? (now %d, lower value = higher rate) ",
349 env
.spawn_random_rate
);
351 if (!cancelable_get_line(specs
, sizeof(specs
)))
353 const int rate
= atoi(specs
);
356 env
.spawn_random_rate
= rate
;
363 // 50 spots are reserved for non-wandering monsters.
364 int max_spawn
= MAX_MONSTERS
- 50;
365 for (monster_iterator mi
; mi
; ++mi
)
371 mpr("Level already filled with monsters, get rid of some "
372 "of them first.", MSGCH_PROMPT
);
376 mprf(MSGCH_PROMPT
, "Spawn how many random monsters (max %d)? ",
379 if (!cancelable_get_line(specs
, sizeof(specs
)))
381 const int num
= std::min(atoi(specs
), max_spawn
);
384 int curr_rate
= env
.spawn_random_rate
;
385 // Each call to spawn_random_monsters() will spawn one with
386 // the rate at 5 or less.
387 env
.spawn_random_rate
= 5;
389 for (int i
= 0; i
< num
; ++i
)
390 spawn_random_monsters();
392 env
.spawn_random_rate
= curr_rate
;
402 // Prints a number of useful (for debugging, that is) stats on monsters.
403 void debug_stethoscope(int mon
)
410 if (mon
!= RANDOM_MONSTER
)
414 mpr("Which monster?", MSGCH_PROMPT
);
416 direction(stth
, direction_chooser_args());
422 stethpos
= stth
.target
;
424 stethpos
= you
.pos() + stth
.delta
;
426 if (env
.cgrid(stethpos
) != EMPTY_CLOUD
)
428 mprf(MSGCH_DIAGNOSTICS
, "cloud type: %d delay: %d",
429 env
.cloud
[ env
.cgrid(stethpos
) ].type
,
430 env
.cloud
[ env
.cgrid(stethpos
) ].decay
);
433 if (!monster_at(stethpos
))
435 mprf(MSGCH_DIAGNOSTICS
, "item grid = %d", igrd(stethpos
));
442 monster
& mons(menv
[i
]);
444 // Print type of monster.
445 mprf(MSGCH_DIAGNOSTICS
, "%s (id #%d; type=%d loc=(%d,%d) align=%s)",
446 mons
.name(DESC_CAP_THE
, true).c_str(),
447 i
, mons
.type
, mons
.pos().x
, mons
.pos().y
,
448 ((mons
.attitude
== ATT_HOSTILE
) ? "hostile" :
449 (mons
.attitude
== ATT_FRIENDLY
) ? "friendly" :
450 (mons
.attitude
== ATT_NEUTRAL
) ? "neutral" :
451 (mons
.attitude
== ATT_GOOD_NEUTRAL
) ? "good neutral":
452 (mons
.attitude
== ATT_STRICT_NEUTRAL
) ? "strictly neutral"
453 : "unknown alignment"));
455 // Print stats and other info.
456 mprf(MSGCH_DIAGNOSTICS
,
457 "HD=%d (%u) HP=%d/%d AC=%d(%d) EV=%d MR=%d SP=%d "
458 "energy=%d%s%s mid=%u num=%d stealth=%d flags=%04"PRIx64
,
461 mons
.hit_points
, mons
.max_hit_points
,
462 mons
.ac
, mons
.armour_class(),
465 mons
.speed
, mons
.speed_increment
,
466 mons
.base_monster
!= MONS_NO_MONSTER
? " base=" : "",
467 mons
.base_monster
!= MONS_NO_MONSTER
?
468 get_monster_data(mons
.base_monster
)->name
: "",
469 mons
.mid
, mons
.number
, mons
.stealth(), mons
.flags
);
471 // Print habitat and behaviour information.
472 const habitat_type hab
= mons_habitat(&mons
);
474 mprf(MSGCH_DIAGNOSTICS
,
475 "hab=%s beh=%s(%d) foe=%s(%d) mem=%d target=(%d,%d) "
476 "firing_pos=(%d,%d) god=%s",
477 ((hab
== HT_LAND
) ? "land" :
478 (hab
== HT_AMPHIBIOUS
) ? "amphibious" :
479 (hab
== HT_WATER
) ? "water" :
480 (hab
== HT_LAVA
) ? "lava" :
481 (hab
== HT_ROCK
) ? "rock"
483 (mons
.asleep() ? "sleep" :
484 mons_is_wandering(&mons
) ? "wander" :
485 mons_is_seeking(&mons
) ? "seek" :
486 mons_is_fleeing(&mons
) ? "flee" :
487 mons_is_cornered(&mons
) ? "cornered" :
488 mons_is_panicking(&mons
) ? "panic" :
489 mons_is_lurking(&mons
) ? "lurk"
492 ((mons
.foe
== MHITYOU
) ? "you" :
493 (mons
.foe
== MHITNOT
) ? "none" :
494 (menv
[mons
.foe
].type
== MONS_NO_MONSTER
) ? "unassigned monster"
495 : menv
[mons
.foe
].name(DESC_PLAIN
, true).c_str()),
498 mons
.target
.x
, mons
.target
.y
,
499 mons
.firing_pos
.x
, mons
.firing_pos
.y
,
500 god_name(mons
.god
).c_str());
502 // Print resistances.
503 mprf(MSGCH_DIAGNOSTICS
, "resist: fire=%d cold=%d elec=%d pois=%d neg=%d "
504 "acid=%d sticky=%s rot=%s",
509 mons
.res_negative_energy(),
511 mons
.res_sticky_flame() ? "yes" : "no",
512 mons
.res_rotting() ? "yes" : "no");
514 mprf(MSGCH_DIAGNOSTICS
, "ench: %s",
515 mons
.describe_enchantments().c_str());
517 std::ostringstream spl
;
518 const monster_spells
&hspell_pass
= mons
.spells
;
519 bool found_spell
= false;
520 for (int k
= 0; k
< NUM_MONSTER_SPELL_SLOTS
; ++k
)
522 if (hspell_pass
[k
] != SPELL_NO_SPELL
)
531 if (hspell_pass
[k
] >= NUM_SPELLS
)
532 spl
<< "buggy spell";
534 spl
<< spell_title(hspell_pass
[k
]);
536 spl
<< " (" << static_cast<int>(hspell_pass
[k
]) << ")";
540 mprf(MSGCH_DIAGNOSTICS
, "spells: %s", spl
.str().c_str());
542 if (mons_is_ghost_demon(mons
.type
))
544 ASSERT(mons
.ghost
.get());
545 const ghost_demon
&ghost
= *mons
.ghost
;
546 mprf(MSGCH_DIAGNOSTICS
, "Ghost damage: %d; brand: %d; att_type: %d; "
548 ghost
.damage
, ghost
.brand
, ghost
.att_type
, ghost
.att_flav
);
552 // Detects all monsters on the level, using their exact positions.
553 void wizard_detect_creatures()
555 for (monster_iterator mi
; mi
; ++mi
)
557 env
.map_knowledge(mi
->pos()).set_monster(monster_info(*mi
));
558 env
.map_knowledge(mi
->pos()).set_detected_monster(mi
->type
);
562 // Dismisses all monsters on the level or all monsters that match a user
564 void wizard_dismiss_all_monsters(bool force_all
)
569 mpr("Regex of monsters to dismiss (ENTER for all): ", MSGCH_PROMPT
);
570 bool validline
= !cancelable_get_line_autohist(buf
, sizeof buf
);
579 dismiss_monsters(buf
);
580 // If it was turned off turn autopickup back on if all monsters went away.
582 autotoggle_autopickup(false);
585 void debug_make_monster_shout(monster
* mon
)
587 mpr("Make the monster (S)hout or (T)alk? ", MSGCH_PROMPT
);
589 char type
= (char) getchm(KMC_DEFAULT
);
590 type
= tolower(type
);
592 if (type
!= 's' && type
!= 't')
598 int num_times
= prompt_for_int("How many times? ", false);
608 if (silenced(you
.pos()))
609 mpr("You are silenced and likely won't hear any shouts.");
610 else if (silenced(mon
->pos()))
611 mpr("The monster is silenced and likely won't give any shouts.");
613 for (int i
= 0; i
< num_times
; ++i
)
614 force_monster_shout(mon
);
618 if (mon
->invisible())
619 mpr("The monster is invisible and likely won't speak.");
621 if (silenced(you
.pos()) && !silenced(mon
->pos()))
623 mpr("You are silenced but the monster isn't; you will "
624 "probably hear/see nothing.");
626 else if (!silenced(you
.pos()) && silenced(mon
->pos()))
627 mpr("The monster is silenced and likely won't say anything.");
628 else if (silenced(you
.pos()) && silenced(mon
->pos()))
630 mpr("Both you and the monster are silenced, so you likely "
631 "won't hear anything.");
634 for (int i
= 0; i
< num_times
; ++i
)
641 static bool _force_suitable(const monster
* mon
)
643 return (mon
->alive());
646 void wizard_apply_monster_blessing(monster
* mon
)
648 mpr("Apply blessing of (B)eogh, The (S)hining One, or (R)andomly? ",
651 char type
= (char) getchm(KMC_DEFAULT
);
652 type
= tolower(type
);
654 if (type
!= 'b' && type
!= 's' && type
!= 'r')
659 god_type god
= GOD_NO_GOD
;
660 if (type
== 'b' || type
== 'r' && coinflip())
663 god
= GOD_SHINING_ONE
;
665 if (!bless_follower(mon
, god
, _force_suitable
, true))
666 mprf("%s won't bless this monster for you!", god_name(god
).c_str());
669 void wizard_give_monster_item(monster
* mon
)
671 mon_itemuse_type item_use
= mons_itemuse(mon
);
672 if (item_use
< MONUSE_STARTING_EQUIPMENT
)
674 mpr("That type of monster can't use any items.");
678 int player_slot
= prompt_invent_item("Give which item to monster?",
681 if (player_slot
== PROMPT_ABORT
)
684 for (int i
= 0; i
< NUM_EQUIP
; ++i
)
685 if (you
.equip
[i
] == player_slot
)
687 mpr("Can't give equipped items to a monster.");
691 item_def
&item
= you
.inv
[player_slot
];
692 mon_inv_type mon_slot
= NUM_MONSTER_SLOTS
;
694 switch (item
.base_type
)
698 // Let wizard specify which slot to put weapon into via
700 if (item
.inscription
.find("first") != std::string::npos
701 || item
.inscription
.find("primary") != std::string::npos
)
703 mpr("Putting weapon into primary slot by inscription");
704 mon_slot
= MSLOT_WEAPON
;
707 else if (item
.inscription
.find("second") != std::string::npos
708 || item
.inscription
.find("alt") != std::string::npos
)
710 mpr("Putting weapon into alt slot by inscription");
711 mon_slot
= MSLOT_ALT_WEAPON
;
715 // For monsters which can wield two weapons, prefer whichever
716 // slot is empty (if there is an empty slot).
717 if (mons_wields_two_weapons(mon
))
719 if (mon
->inv
[MSLOT_WEAPON
] == NON_ITEM
)
721 mpr("Dual wielding monster, putting into empty primary slot");
722 mon_slot
= MSLOT_WEAPON
;
725 else if (mon
->inv
[MSLOT_ALT_WEAPON
] == NON_ITEM
)
727 mpr("Dual wielding monster, putting into empty alt slot");
728 mon_slot
= MSLOT_ALT_WEAPON
;
733 // Try to replace a ranged weapon with a ranged weapon and
734 // a non-ranged weapon with a non-ranged weapon
735 if (mon
->inv
[MSLOT_WEAPON
] != NON_ITEM
736 && (is_range_weapon(mitm
[mon
->inv
[MSLOT_WEAPON
]])
737 == is_range_weapon(item
)))
739 mpr("Replacing primary slot with similar weapon");
740 mon_slot
= MSLOT_WEAPON
;
743 if (mon
->inv
[MSLOT_ALT_WEAPON
] != NON_ITEM
744 && (is_range_weapon(mitm
[mon
->inv
[MSLOT_ALT_WEAPON
]])
745 == is_range_weapon(item
)))
747 mpr("Replacing alt slot with similar weapon");
748 mon_slot
= MSLOT_ALT_WEAPON
;
752 // Prefer the empty slot (if any)
753 if (mon
->inv
[MSLOT_WEAPON
] == NON_ITEM
)
755 mpr("Putting weapon into empty primary slot");
756 mon_slot
= MSLOT_WEAPON
;
759 else if (mon
->inv
[MSLOT_ALT_WEAPON
] == NON_ITEM
)
761 mpr("Putting weapon into empty alt slot");
762 mon_slot
= MSLOT_ALT_WEAPON
;
766 // Default to primary weapon slot
767 mpr("Defaulting to primary slot");
768 mon_slot
= MSLOT_WEAPON
;
773 // May only return shield or armour slot.
774 equipment_type eq
= get_armour_slot(item
);
776 // Force non-shield, non-body armour to be worn anyway.
780 mon_slot
= equip_slot_to_mslot(eq
);
784 mon_slot
= MSLOT_MISSILE
;
787 mon_slot
= MSLOT_WAND
;
790 mon_slot
= MSLOT_SCROLL
;
793 mon_slot
= MSLOT_POTION
;
796 mon_slot
= MSLOT_MISCELLANY
;
799 mpr("You can't give that type of item to a monster.");
803 if (item_use
== MONUSE_STARTING_EQUIPMENT
804 && !mons_is_unique(mon
->type
))
809 case MSLOT_ALT_WEAPON
:
815 mpr("That type of monster can only use weapons and armour.");
820 int index
= get_item_slot(10);
821 if (index
== NON_ITEM
)
823 mpr("Too many items on level, bailing.");
827 // Move monster's old item to player's inventory as last step.
828 int old_eq
= NON_ITEM
;
829 bool unequipped
= false;
830 if (mon_slot
!= NUM_MONSTER_SLOTS
831 && mon
->inv
[mon_slot
] != NON_ITEM
832 && !items_stack(item
, mitm
[mon
->inv
[mon_slot
]]))
834 old_eq
= mon
->inv
[mon_slot
];
835 // Alternative weapons don't get (un)wielded unless the monster
836 // can wield two weapons.
837 if (mon_slot
!= MSLOT_ALT_WEAPON
|| mons_wields_two_weapons(mon
))
839 mon
->unequip(*(mon
->mslot_item(mon_slot
)), mon_slot
, 1, true);
842 mon
->inv
[mon_slot
] = NON_ITEM
;
847 unwind_var
<int> save_speedinc(mon
->speed_increment
);
848 if (!mon
->pickup_item(mitm
[index
], false, true))
850 mpr("Monster wouldn't take item.");
851 if (old_eq
!= NON_ITEM
&& mon_slot
!= NUM_MONSTER_SLOTS
)
853 mon
->inv
[mon_slot
] = old_eq
;
855 mon
->equip(mitm
[old_eq
], mon_slot
, 1);
862 // Item is gone from player's inventory.
863 dec_inv_item_quantity(player_slot
, item
.quantity
);
865 if ((mon
->flags
& MF_HARD_RESET
) && !(item
.flags
& ISFLAG_SUMMONED
))
867 mprf(MSGCH_WARN
, "WARNING: Monster has MF_HARD_RESET and all its "
868 "items will disappear when it does.");
870 else if ((item
.flags
& ISFLAG_SUMMONED
) && !mon
->is_summoned())
872 mprf(MSGCH_WARN
, "WARNING: Item is summoned and will disappear when "
873 "the monster does.");
875 // Monster's old item moves to player's inventory.
876 if (old_eq
!= NON_ITEM
)
878 mpr("Fetching monster's old item.");
879 if (mitm
[old_eq
].flags
& ISFLAG_SUMMONED
)
881 mprf(MSGCH_WARN
, "WARNING: Item is summoned and shouldn't really "
882 "be anywhere but in the inventory of a summoned monster.");
884 mitm
[old_eq
].pos
.reset();
885 mitm
[old_eq
].link
= NON_ITEM
;
886 move_item_to_player(old_eq
, mitm
[old_eq
].quantity
);
890 static void _move_player(const coord_def
& where
)
892 if (!you
.can_pass_through_feat(grd(where
)))
893 grd(where
) = DNGN_FLOOR
;
894 move_player_to_grid(where
, false, true);
897 static void _move_monster(const coord_def
& where
, int mid1
)
900 direction_chooser_args args
;
901 args
.needs_path
= false;
902 args
.top_prompt
= "Move monster to where?";
903 direction(moves
, args
);
905 if (!moves
.isValid
|| !in_bounds(moves
.target
))
908 monster
* mon1
= &menv
[mid1
];
910 const int mid2
= mgrd(moves
.target
);
911 monster
* mon2
= monster_at(moves
.target
);
913 mon1
->moveto(moves
.target
);
914 mgrd(moves
.target
) = mid1
;
915 mon1
->check_redraw(moves
.target
);
922 mon1
->check_redraw(where
);
926 void wizard_move_player_or_monster(const coord_def
& where
)
928 crawl_state
.cancel_cmd_again();
929 crawl_state
.cancel_cmd_repeat();
931 static bool already_moving
= false;
935 mpr("Already doing a move command.");
939 already_moving
= true;
941 int mid
= mgrd(where
);
943 if (mid
== NON_MONSTER
)
945 if (crawl_state
.arena_suspended
)
947 mpr("You can't move yourself into the arena.");
954 _move_monster(where
, mid
);
956 already_moving
= false;
959 void wizard_make_monster_summoned(monster
* mon
)
962 if (mon
->is_summoned(NULL
, &summon_type
) || summon_type
!= 0)
964 mpr("Monster is already summoned.", MSGCH_PROMPT
);
968 int dur
= prompt_for_int("What summon longevity (1 to 6)? ", true);
970 if (dur
< 1 || dur
> 6)
976 mpr("[a] clone [b] animated [c] chaos [d] miscast [e] zot", MSGCH_PROMPT
);
977 mpr("[f] wrath [g] aid [m] misc [s] spell",
980 mpr("Which summon type? ", MSGCH_PROMPT
);
982 char choice
= tolower(getchm());
984 if (!(choice
>= 'a' && choice
<= 'g') && choice
!= 'm' && choice
!= 's')
994 case 'a': type
= MON_SUMM_CLONE
; break;
995 case 'b': type
= MON_SUMM_ANIMATE
; break;
996 case 'c': type
= MON_SUMM_CHAOS
; break;
997 case 'd': type
= MON_SUMM_MISCAST
; break;
998 case 'e': type
= MON_SUMM_ZOT
; break;
999 case 'f': type
= MON_SUMM_WRATH
; break;
1000 case 'g': type
= MON_SUMM_AID
; break;
1001 case 'm': type
= 0; break;
1007 msgwin_get_line("Cast which spell by name? ",
1008 specs
, sizeof(specs
));
1010 if (specs
[0] == '\0')
1016 spell_type spell
= spell_by_name(specs
, true);
1017 if (spell
== SPELL_NO_SPELL
)
1019 mpr("No such spell.", MSGCH_PROMPT
);
1027 die("Invalid summon type choice.");
1031 mon
->mark_summoned(dur
, true, type
);
1032 mpr("Monster is now summoned.");
1035 void wizard_polymorph_monster(monster
* mon
)
1037 monster_type old_type
= mon
->type
;
1038 monster_type type
= debug_prompt_for_monster();
1040 if (type
== NUM_MONSTERS
)
1046 if (invalid_monster_type(type
))
1048 mpr("Invalid monster type.", MSGCH_PROMPT
);
1052 if (type
== old_type
)
1054 mpr("Old type and new type are the same, not polymorphing.");
1058 if (mons_species(type
) == mons_species(old_type
))
1060 mpr("Target species must be different from current species.");
1064 monster_polymorph(mon
, type
, PPT_SAME
, true);
1068 mpr("Polymorph killed monster?", MSGCH_ERROR
);
1072 mon
->check_redraw(mon
->pos());
1074 if (mon
->type
== old_type
)
1075 mpr("Polymorph failed.");
1076 else if (mon
->type
!= type
)
1077 mpr("Monster turned into something other than the desired type.");
1080 void debug_pathfind(int mid
)
1082 if (mid
== NON_MONSTER
)
1085 mpr("Choose a destination!");
1091 bool chose
= show_map(ldest
, false, true, false);
1100 monster
& mon
= menv
[mid
];
1101 mprf("Attempting to calculate a path from (%d, %d) to (%d, %d)...",
1102 mon
.pos().x
, mon
.pos().y
, dest
.x
, dest
.y
);
1103 monster_pathfind mp
;
1104 bool success
= mp
.init_pathfind(&mon
, dest
, true, true);
1107 std::vector
<coord_def
> path
= mp
.backtrack();
1108 std::string path_str
;
1109 mpr("Here's the shortest path: ");
1110 for (unsigned int i
= 0; i
< path
.size(); ++i
)
1112 snprintf(info
, INFO_SIZE
, "(%d, %d) ", path
[i
].x
, path
[i
].y
);
1115 mpr(path_str
.c_str());
1116 mprf("-> path length: %d", path
.size());
1119 path
= mp
.calc_waypoints();
1122 mpr("And here are the needed waypoints: ");
1123 for (unsigned int i
= 0; i
< path
.size(); ++i
)
1125 snprintf(info
, INFO_SIZE
, "(%d, %d) ", path
[i
].x
, path
[i
].y
);
1128 mpr(path_str
.c_str());
1129 mprf("-> #waypoints: %d", path
.size());
1133 static void _miscast_screen_update()
1137 you
.redraw_status_flags
=
1138 REDRAW_LINE_1_MASK
| REDRAW_LINE_2_MASK
| REDRAW_LINE_3_MASK
;
1142 update_monster_pane();
1146 void debug_miscast(int target_index
)
1148 crawl_state
.cancel_cmd_repeat();
1151 if (target_index
== NON_MONSTER
)
1154 target
= &menv
[target_index
];
1156 if (!target
->alive())
1158 mpr("Can't make already dead target miscast.");
1163 mpr("Miscast which school or spell, by name? ", MSGCH_PROMPT
);
1164 if (cancelable_get_line_autohist(specs
, sizeof specs
) || !*specs
)
1170 spell_type spell
= spell_by_name(specs
, true);
1171 spschool_flag_type school
= school_by_name(specs
);
1173 // Prefer exact matches for school name over partial matches for
1175 if (school
!= SPTYP_NONE
1176 && (strcasecmp(specs
, spelltype_short_name(school
)) == 0
1177 || strcasecmp(specs
, spelltype_long_name(school
)) == 0))
1179 spell
= SPELL_NO_SPELL
;
1182 if (spell
== SPELL_NO_SPELL
&& school
== SPTYP_NONE
)
1184 mpr("No matching spell or spell school.");
1187 else if (spell
!= SPELL_NO_SPELL
&& school
!= SPTYP_NONE
)
1189 mprf("Ambiguous: can be spell '%s' or school '%s'.",
1190 spell_title(spell
), spelltype_short_name(school
));
1194 int disciplines
= 0;
1195 if (spell
!= SPELL_NO_SPELL
)
1197 disciplines
= get_spell_disciplines(spell
);
1199 if (disciplines
== 0)
1201 mprf("Spell '%s' has no disciplines.", spell_title(spell
));
1206 if (is_holy_spell(spell
))
1208 mpr("Can't miscast holy spells.");
1212 if (spell
!= SPELL_NO_SPELL
)
1213 mprf("Miscasting spell %s.", spell_title(spell
));
1215 mprf("Miscasting school %s.", spelltype_long_name(school
));
1217 if (spell
!= SPELL_NO_SPELL
)
1218 mpr("Enter spell_power,spell_failure: ", MSGCH_PROMPT
);
1221 mpr("Enter miscast_level or spell_power,spell_failure: ",
1225 if (cancelable_get_line_autohist(specs
, sizeof specs
) || !*specs
)
1231 int level
= -1, pow
= -1, fail
= -1;
1233 if (strchr(specs
, ','))
1235 std::vector
<std::string
> nums
= split_string(",", specs
);
1236 pow
= atoi(nums
[0].c_str());
1237 fail
= atoi(nums
[1].c_str());
1239 if (pow
<= 0 || fail
<= 0)
1247 if (spell
!= SPELL_NO_SPELL
)
1249 mpr("Can only enter fixed miscast level for schools, not spells.");
1253 level
= atoi(specs
);
1261 mpr("Miscast level can be at most 3.");
1266 // Handle repeats ourselves since miscasts are likely to interrupt
1267 // command repetions, especially if the player is the target.
1268 int repeats
= prompt_for_int("Number of repetitions? ", true);
1275 // Supress "nothing happens" message for monster miscasts which are
1276 // only harmless messages, since a large number of those are missing
1277 // monster messages.
1278 nothing_happens_when_type nothing
= NH_DEFAULT
;
1279 if (target_index
!= NON_MONSTER
&& level
== 0)
1282 MiscastEffect
*miscast
;
1284 if (spell
!= SPELL_NO_SPELL
)
1286 miscast
= new MiscastEffect(target
, target_index
, spell
, pow
, fail
,
1293 miscast
= new MiscastEffect(target
, target_index
, school
,
1294 level
, "wizard testing miscast",
1299 miscast
= new MiscastEffect(target
, target_index
, school
,
1300 pow
, fail
, "wizard testing miscast",
1304 // Merely creating the miscast object causes one miscast effect to
1308 _miscast_screen_update();
1310 while (target
->alive() && repeats
-- > 0)
1314 mpr("Key pressed, interrupting miscast testing.");
1319 miscast
->do_miscast();
1321 _miscast_screen_update();
1329 mpr("(C)reate or (L)oad bones file?", MSGCH_PROMPT
);
1330 const char c
= tolower(getchm());