summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-02 20:36:51 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-02 20:36:51 +0000
commit78edf358eefc57dbe3f7bcd257cbf6b9d319149a (patch)
tree3579a9ce46b2cb7525c914079a05246c19dbdae8 /crawl-ref/source
parent17125f250661e8430e320f4c05d74094235f0cf3 (diff)
downloadcrawl-ref-78edf358eefc57dbe3f7bcd257cbf6b9d319149a.tar.gz
crawl-ref-78edf358eefc57dbe3f7bcd257cbf6b9d319149a.zip
Make monster behaviour in arenas smarter, allow delay:N in arena spec to set arena_delay.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8129 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/arena.cc32
-rw-r--r--crawl-ref/source/arena.map70
-rw-r--r--crawl-ref/source/mon-util.cc4
-rw-r--r--crawl-ref/source/mon-util.h3
-rw-r--r--crawl-ref/source/monplace.cc5
-rw-r--r--crawl-ref/source/monplace.h1
-rw-r--r--crawl-ref/source/monstuff.cc103
7 files changed, 179 insertions, 39 deletions
diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc
index fdd0cc40e9..aefd29729d 100644
--- a/crawl-ref/source/arena.cc
+++ b/crawl-ref/source/arena.cc
@@ -52,6 +52,8 @@ namespace arena
std::string arena_type = "";
faction faction_a(true);
faction faction_b(false);
+ coord_def place_a, place_b;
+
FILE *file = NULL;
int message_pos = 0;
level_id place;
@@ -75,6 +77,17 @@ namespace arena
}
}
}
+
+ for (int i = 0; i < MAX_MONSTERS; i++)
+ {
+ monsters *mon = &menv[i];
+ if (!mon->alive())
+ continue;
+
+ const bool friendly = mons_friendly(mon);
+ // Set target to the opposite faction's home base.
+ mon->target = friendly ? place_b : place_a;
+ }
}
void alert_faction(bool friendly)
@@ -264,6 +277,10 @@ namespace arena
if (arena_type.empty())
arena_type = "default";
+ const int arena_delay = strip_number_tag(spec, "delay:");
+ if (arena_delay >= 0 && arena_delay < 2000)
+ Options.arena_delay = arena_delay;
+
std::string arena_place = strip_tag_prefix(spec, "arena_place:");
if (!arena_place.empty())
{
@@ -313,8 +330,8 @@ namespace arena
unwind_var< FixedVector<bool, NUM_MONSTERS> >
uniq(you.unique_creatures);
- coord_def place_a(dgn_find_feature_marker(DNGN_STONE_STAIRS_UP_I));
- coord_def place_b(dgn_find_feature_marker(DNGN_STONE_STAIRS_DOWN_I));
+ place_a = dgn_find_feature_marker(DNGN_STONE_STAIRS_UP_I);
+ place_b = dgn_find_feature_marker(DNGN_STONE_STAIRS_DOWN_I);
faction_a.place_at(place_a);
faction_b.place_at(place_b);
adjust_monsters();
@@ -515,8 +532,15 @@ namespace arena
cursor_control coff(false);
while (fight_is_on())
{
- if (kbhit() && getch() == ESCAPE)
- end(0, false, "Canceled contest at user request");
+ if (kbhit())
+ {
+ const int ch = getch();
+ if (ch == ESCAPE || tolower(ch) == 'q' ||
+ ch == CONTROL('G'))
+ {
+ end(0, false, "Canceled contest at user request");
+ }
+ }
viewwindow(true, false);
unwind_var<coord_def> pos(you.position);
diff --git a/crawl-ref/source/arena.map b/crawl-ref/source/arena.map
new file mode 100644
index 0000000000..5c29a0769f
--- /dev/null
+++ b/crawl-ref/source/arena.map
@@ -0,0 +1,70 @@
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################{{{{...{{{{{{{{#################################
+################################.{{{.{{{.{.{{{{#################################
+################################{{{{.{.{{{{{{{{#################################
+################################{{{{{{{{{{.{{.{#################################
+################################{{.{{.{{{{{{{{{#################################
+################################{{{{.{{{{{{{{{{#################################
+################################.{{{{{{{.{{{{{{#################################
+################################.{.{{{{{{{{{{{{#################################
+################################{{{{{{{.{{{{{{.#################################
+################################{{{{{.{{{{{{{{{#################################
+################################..{{{{{{{{.{{{{#################################
+################################{.{{{{{{{{{{{{{#################################
+################################{{{{.{{{{{{{{.{#################################
+################################{{{{.{{{.{{{{{{#################################
+################################.{{.{..{{{{{{{{#################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
+################################################################################
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 871395b42f..afbdd7e52f 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -3167,7 +3167,7 @@ const char *mons_pronoun(monster_type mon_type, pronoun_type variant,
// Checks if the monster can use smiting/torment to attack without
// unimpeded LOS to the player.
-static bool _mons_can_smite(const monsters *monster)
+bool mons_has_smite_attack(const monsters *monster)
{
if (monster->type == MONS_FIEND)
return (true);
@@ -3214,7 +3214,7 @@ bool monster_shover(const monsters *m)
return (false);
// Smiters profit from staying back and smiting.
- if (_mons_can_smite(m))
+ if (mons_has_smite_attack(m))
return (false);
int mchar = me->showchar;
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index b69d594470..a7c2da68b7 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -775,9 +775,10 @@ monster_type mons_genus(int mc);
monster_type mons_species(int mc);
bool mons_looks_stabbable(const monsters *m);
-
bool mons_looks_distracted(const monsters *m);
+bool mons_has_smite_attack(const monsters *monster);
+
bool check_mons_resist_magic(const monsters *monster, int pow);
bool mons_class_is_confusable(int mc);
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index dfbdd9eb94..20d5c5f88a 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -2598,6 +2598,11 @@ void monster_pathfind::set_range(int r)
range = r;
}
+coord_def monster_pathfind::next_pos(const coord_def &c) const
+{
+ return c + Compass[prev[c.x][c.y]];
+}
+
// The main method in the monster_pathfind class.
// Returns true if a path was found, else false.
bool monster_pathfind::init_pathfind(monsters *mon, coord_def dest, bool diag,
diff --git a/crawl-ref/source/monplace.h b/crawl-ref/source/monplace.h
index 0d633aca64..8d98254c17 100644
--- a/crawl-ref/source/monplace.h
+++ b/crawl-ref/source/monplace.h
@@ -362,6 +362,7 @@ public:
// public methods
void set_range(int r);
+ coord_def next_pos(const coord_def &p) const;
bool init_pathfind(monsters *mon, coord_def dest,
bool diag = true, bool msg = false,
bool pass_unmapped = false);
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index dcadfc5910..6258f57a18 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -3479,6 +3479,42 @@ static bool _handle_monster_patrolling(monsters *mon)
return (false);
}
+static void _check_wander_target(monsters *mon, bool isPacified = false,
+ dungeon_feature_type can_move = DNGN_UNSEEN)
+{
+ // default wander behaviour
+ if (mon->pos() == mon->target
+ || mons_is_batty(mon) || !isPacified && one_chance_in(20))
+ {
+ bool need_target = true;
+
+ if (!can_move)
+ can_move = (mons_amphibious(mon))
+ ? DNGN_DEEP_WATER : DNGN_SHALLOW_WATER;
+
+ if (mon->is_travelling())
+ need_target = _handle_monster_travelling(mon, can_move);
+
+ // If we still need a target because we're not travelling
+ // (any more), check for patrol routes instead.
+ if (need_target && mon->is_patrolling())
+ need_target = _handle_monster_patrolling(mon);
+
+ // XXX: This is really dumb wander behaviour... instead of
+ // changing the goal square every turn, better would be to
+ // have the monster store a direction and have the monster
+ // head in that direction for a while, then shift the
+ // direction to the left or right. We're changing this so
+ // wandering monsters at least appear to have some sort of
+ // attention span. -- bwr
+ if (need_target)
+ {
+ mon->target.set(10 + random2(GXM - 10),
+ 10 + random2(GYM - 10));
+ }
+ }
+}
+
static void _arena_set_foe(monsters *mons)
{
const int mind = monster_index(mons);
@@ -3495,7 +3531,9 @@ static void _arena_set_foe(monsters *mons)
continue;
const int distance = grid_distance(mons->pos(), other->pos());
- if (best_distance == -1 || distance < best_distance)
+ if ((best_distance == -1 || distance < best_distance)
+ && mons->can_see(other))
+
{
best_distance = distance;
nearest = i;
@@ -3506,12 +3544,16 @@ static void _arena_set_foe(monsters *mons)
{
mons->foe = nearest;
mons->target = menv[nearest].pos();
+ mons->behaviour = BEH_SEEK;
}
else
{
mons->foe = MHITNOT;
- mons->target = mons->pos();
+ mons->behaviour = BEH_WANDER;
}
+
+ if (mons->behaviour == BEH_WANDER)
+ _check_wander_target(mons);
}
//---------------------------------------------------------------
@@ -3566,8 +3608,6 @@ static void _handle_behaviour(monsters *mon)
mon->foe = MHITNOT;
if (mon->foe == MHITNOT || mon->foe == MHITYOU)
_arena_set_foe(mon);
- if (mon->behaviour == BEH_WANDER)
- mon->behaviour = BEH_SEEK;
return;
}
@@ -3584,6 +3624,7 @@ static void _handle_behaviour(monsters *mon)
const dungeon_feature_type can_move =
(mons_amphibious(mon)) ? DNGN_DEEP_WATER : DNGN_SHALLOW_WATER;
+
// Validate current target exists.
if (mon->foe != MHITNOT && mon->foe != MHITYOU
&& !menv[mon->foe].alive())
@@ -3921,32 +3962,7 @@ static void _handle_behaviour(monsters *mon)
break;
}
- // default wander behaviour
- if (mon->pos() == mon->target
- || mons_is_batty(mon) || !isPacified && one_chance_in(20))
- {
- bool need_target = true;
- if (mon->is_travelling())
- need_target = _handle_monster_travelling(mon, can_move);
-
- // If we still need a target because we're not travelling
- // (any more), check for patrol routes instead.
- if (need_target && patrolling)
- need_target = _handle_monster_patrolling(mon);
-
- // XXX: This is really dumb wander behaviour... instead of
- // changing the goal square every turn, better would be to
- // have the monster store a direction and have the monster
- // head in that direction for a while, then shift the
- // direction to the left or right. We're changing this so
- // wandering monsters at least appear to have some sort of
- // attention span. -- bwr
- if (need_target)
- {
- mon->target.set(10 + random2(GXM - 10),
- 10 + random2(GYM - 10));
- }
- }
+ _check_wander_target(mon, isPacified, can_move);
// During their wanderings, monsters will eventually relax
// their guard (stupid ones will do so faster, smart
@@ -4375,6 +4391,28 @@ static void _handle_movement(monsters *monster)
else
{
delta = monster->target - monster->pos();
+
+ if (crawl_state.arena)
+ {
+ const bool ranged =
+ mons_has_ranged_attack(monster)
+ || mons_has_ranged_spell(monster);
+
+ // Smiters are happy if they have clear visibility through glass,
+ // but other monsters must go around.
+ const bool glass_ok = mons_has_smite_attack(monster);
+
+ // Monsters in the arena are smarter than the norm and
+ // always pathfind to their targets.
+ if (delta.abs() > 2
+ && (!ranged ||
+ !monster->mon_see_grid(monster->target, !glass_ok)))
+ {
+ monster_pathfind mp;
+ if (mp.init_pathfind(monster, monster->target))
+ delta = mp.next_pos(monster->pos()) - monster->pos();
+ }
+ }
}
// Move the monster.
@@ -6010,7 +6048,8 @@ static bool _handle_spell(monsters *monster, bolt &beem)
// beam-type spells requiring tracers
if (spell_needs_tracer(spell_cast))
{
- const bool explode = spell_is_direct_explosion(spell_cast);
+ const bool explode =
+ spell_is_direct_explosion(spell_cast);
fire_tracer(monster, beem, explode);
// Good idea?
if (mons_should_fire(beem))
@@ -6844,7 +6883,7 @@ static void _handle_monster_move(int i, monsters *monster)
{
// Prevents unfriendlies from nuking you from offscreen.
// How nice!
- if (mons_friendly(monster) || mons_near(monster))
+ if (mons_friendly(monster) || mons_near(monster, monster->foe))
{
// [ds] Special abilities shouldn't overwhelm spellcasting
// in monsters that have both. This aims to give them both