summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-03 08:42:03 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-03 08:42:03 +0000
commit0bd8f00f48363b713105ba476661176913316ef4 (patch)
treeb28e2b1895a6d2cc087162d306d701bc725a13d5 /crawl-ref
parent400b9fc5049359bf0f8b6e51c1b0561ec77cd727 (diff)
downloadcrawl-ref-0bd8f00f48363b713105ba476661176913316ef4.tar.gz
crawl-ref-0bd8f00f48363b713105ba476661176913316ef4.zip
The arena now prevents undesired random monsters from being placed by telling
pick_random_monster() to try something else, rather than by culling them after they're placed. By default the arena prevents zero xp monsters from being randomly placed. To allow them to be placed use the spec tag "allow_zero_xp". Removed the arena spec tag "alert", since it's no longer needed. Added the arena spec tag "cycle_random", which if set causes pick_random_monster() to cycle through all the monsters valid for the level_id chosen as the arena's place. Produces a greater variety of monsters when using test spawners. If arena mode is dumping message to the output file then prefix error messages with "ERROR: " and diagnostic messages with "DIAG: " git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8165 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/arena.cc154
-rw-r--r--crawl-ref/source/arena.h15
-rw-r--r--crawl-ref/source/monplace.cc16
-rw-r--r--crawl-ref/source/monstuff.cc12
4 files changed, 130 insertions, 67 deletions
diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc
index 035aa6caa2..34aed4a9e3 100644
--- a/crawl-ref/source/arena.cc
+++ b/crawl-ref/source/arena.cc
@@ -10,6 +10,7 @@
#include "libutil.h"
#include "maps.h"
#include "message.h"
+#include "mon-pick.h"
#include "mon-util.h"
#include "monstuff.h"
#include "monplace.h"
@@ -46,13 +47,16 @@ namespace arena
int trials_done = 0;
int team_a_wins = 0;
- bool allow_summons = true;
- bool no_immobile = false;
- bool do_alert = false;
+ bool allow_summons = true;
+ bool allow_zero_xp = false;
+ bool allow_immobile = true;
std::string arena_type = "";
faction faction_a(true);
faction faction_b(false);
coord_def place_a, place_b;
+ bool contest_canceled = false;
+ bool cycle_random = false;
+ int cycle_random_pos = -1;
FILE *file = NULL;
int message_pos = 0;
@@ -90,45 +94,6 @@ namespace arena
}
}
- void alert_faction(bool friendly)
- {
- int alerter = 0;
- for (int i = 0; i < MAX_MONSTERS; i++)
- {
- const monsters *mon = &menv[i];
- if (!mon->alive())
- continue;
- if (mons_friendly(mon) != friendly)
- {
- alerter = i;
- break;
- }
- }
-
- // Move player aside so that behaviour_event() default src_pos
- // isn't the same as the player's position, in order to avoid an
- // assertion.
- you.position = coord_def(-1, -1);
-
- for (int i = 0; i < MAX_MONSTERS; i++)
- {
- monsters *mon = &menv[i];
- if (!mon->alive())
- continue;
- if (mons_friendly(mon) == friendly)
- behaviour_event(mon, ME_ALERT, alerter);
- }
- }
-
- void alert_monsters()
- {
- if (!do_alert)
- return;
-
- alert_faction(true);
- alert_faction(false);
- }
-
void list_eq(int imon)
{
if (!Options.arena_list_eq || file == NULL)
@@ -266,9 +231,11 @@ namespace arena
Options.arena_force_ai =
strip_bool_tag(spec, "force_ai", Options.arena_force_ai);
- allow_summons = !strip_tag(spec, "no_summons");
- do_alert = strip_tag(spec, "alert");
- no_immobile = strip_tag(spec, "no_immobile");
+ allow_summons = !strip_tag(spec, "no_summons");
+ allow_immobile = !strip_tag(spec, "no_immobile");
+ allow_zero_xp = strip_tag(spec, "allow_zero_xp");
+
+ cycle_random = strip_tag(spec, "cycle_random");
const int ntrials = strip_number_tag(spec, "t:");
if (ntrials != TAG_UNFOUND && ntrials >= 1 && ntrials <= 99
@@ -296,6 +263,12 @@ namespace arena
arena_place.c_str(),
err.c_str());
}
+ if (place.level_type == LEVEL_LABYRINTH)
+ throw (std::string("Can't set arena place to the "
+ "labyrinth."));
+ else if (place.level_type == LEVEL_PORTAL_VAULT)
+ throw (std::string("Can't set arena place to a portal "
+ "vault."));
}
std::vector<std::string> factions = split_string(" v ", spec);
@@ -338,7 +311,6 @@ namespace arena
faction_a.place_at(place_a);
faction_b.place_at(place_b);
adjust_monsters();
- alert_monsters();
}
void show_fight_banner(bool after_fight = false)
@@ -503,28 +475,23 @@ namespace arena
if (!Options.arena_dump_msgs || file == NULL)
return;
+ std::vector<int> channels;
std::vector<std::string> messages =
get_recent_messages(message_pos,
- !Options.arena_dump_msgs_all);
+ !Options.arena_dump_msgs_all,
+ &channels);
for (unsigned int i = 0; i < messages.size(); i++)
- fprintf(file, "%s\n", messages[i].c_str());
- }
-
- void cull_immobile()
- {
- if (!no_immobile)
- return;
-
- for (int i = 0; i < MAX_MONSTERS; i++)
{
- monsters* mon = &menv[i];
-
- if (!mon->alive())
- continue;
-
- if (mons_is_stationary(mon) && mon->is_summoned())
- monster_die(mon, KILL_DISMISSED, NON_MONSTER, true, true);
+ std::string msg = messages[i];
+ int chan = channels[i];
+
+ if (chan == MSGCH_ERROR)
+ msg = "ERROR: " + msg;
+ else if (chan == MSGCH_DIAGNOSTICS)
+ msg = "DIAG: " + msg;
+
+ fprintf(file, "%s\n", msg.c_str());
}
}
@@ -541,7 +508,9 @@ namespace arena
if (ch == ESCAPE || tolower(ch) == 'q' ||
ch == CONTROL('G'))
{
- end(0, false, "Canceled contest at user request");
+ contest_canceled = true;
+ mpr("Canceled contest at user request");
+ return;
}
}
@@ -554,7 +523,6 @@ namespace arena
you.hunger = 10999;
//report_foes();
world_reacts();
- cull_immobile();
delay(Options.arena_delay);
mesclr();
dump_messages();
@@ -648,7 +616,7 @@ namespace arena
if (trials_done < total_trials)
delay(Options.arena_delay * 5);
- } while (trials_done < total_trials);
+ } while (!contest_canceled && trials_done < total_trials);
if (total_trials > 0)
{
@@ -662,6 +630,60 @@ namespace arena
}
}
+/////////////////////////////////////////////////////////////////////////////
+
+// Various arena callbacks
+
+monster_type arena_pick_random_monster(const level_id &place, int power,
+ int &lev_mons)
+{
+ if (!arena::cycle_random)
+ return (RANDOM_MONSTER);
+
+ for (int tries = 0; tries <= NUM_MONSTERS; tries++)
+ {
+ arena::cycle_random_pos++;
+ if (arena::cycle_random_pos >= NUM_MONSTERS)
+ arena::cycle_random_pos = 0;
+
+ const monster_type type = (monster_type) arena::cycle_random_pos;
+
+ if (mons_rarity(type, place) == 0)
+ continue;
+
+ if (arena_veto_random_monster(type))
+ continue;
+
+ return (type);
+ }
+
+ end(1, false, "No random monsters for place '%s'",
+ arena::place.describe().c_str());
+ return (NUM_MONSTERS);
+}
+
+bool arena_veto_random_monster(monster_type type)
+{
+ if (!arena::allow_immobile && mons_class_is_stationary(type))
+ return (true);
+ if (!arena::allow_zero_xp && mons_class_flag(type, M_NO_EXP_GAIN))
+ return (true);
+
+ return (false);
+}
+
+void arena_placed_monster(monsters *monster, const mgen_data &mg,
+ bool first_band_member)
+{
+}
+
+void arena_monster_died(monsters *monster, killer_type killer,
+ int killer_index, bool silent)
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
void run_arena()
{
arena::global_setup();
diff --git a/crawl-ref/source/arena.h b/crawl-ref/source/arena.h
index 864e643d24..8352860538 100644
--- a/crawl-ref/source/arena.h
+++ b/crawl-ref/source/arena.h
@@ -2,7 +2,22 @@
#define ARENA_H
#include "AppHdr.h"
+#include "enum.h"
+
+class level_id;
+class monsters;
+class mgen_data;
void run_arena();
+monster_type arena_pick_random_monster(const level_id &place, int power,
+ int &lev_mons);
+
+bool arena_veto_random_monster(monster_type type);
+
+void arena_placed_monster(monsters *monster, const mgen_data &mg,
+ bool first_band_member);
+
+void arena_monster_died(monsters *monster, killer_type killer,
+ int killer_index, bool silent);
#endif
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index 2f7e77754e..dd15159111 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -12,6 +12,7 @@
#include "monplace.h"
+#include "arena.h"
#include "branch.h"
#include "directn.h" // for the Compass
#include "externs.h"
@@ -314,6 +315,13 @@ monster_type pick_random_monster(const level_id &place)
monster_type pick_random_monster(const level_id &place, int power,
int &lev_mons)
{
+ if (crawl_state.arena)
+ {
+ monster_type type = arena_pick_random_monster(place, power, lev_mons);
+ if (type != RANDOM_MONSTER)
+ return (type);
+ }
+
if (place.level_type == LEVEL_LABYRINTH)
return (MONS_PROGRAM_BUG);
@@ -387,6 +395,8 @@ monster_type pick_random_monster(const level_id &place, int power,
if (count == 2000)
return (MONS_PROGRAM_BUG);
+ if (crawl_state.arena && arena_veto_random_monster(mon_type))
+ continue;
}
while (random2avg(100, 2) > mons_rare_abyss(mon_type)
&& !one_chance_in(100));
@@ -412,6 +422,9 @@ monster_type pick_random_monster(const level_id &place, int power,
if (count == 2000)
return (MONS_PROGRAM_BUG);
+ if (crawl_state.arena && arena_veto_random_monster(mon_type))
+ continue;
+
level = mons_level(mon_type, place);
diff = level - lev_mons;
chance = mons_rarity(mon_type, place) - (diff * diff);
@@ -1135,6 +1148,9 @@ static int _place_monster_aux(const mgen_data &mg,
if (player_monster_visible(&menv[id]) && mons_near(&menv[id]))
seen_monster(&menv[id]);
+ if (crawl_state.arena)
+ arena_placed_monster(&menv[id], mg, first_band_member);
+
return (id);
}
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index c3d5290a88..f083d43f1c 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -20,6 +20,7 @@
#include "externs.h"
+#include "arena.h"
#include "beam.h"
#include "cloud.h"
#include "database.h"
@@ -997,6 +998,9 @@ void monster_die(monsters *monster, killer_type killer,
if (!silent && _monster_avoided_death(monster, killer, killer_index))
return;
+ if (crawl_state.arena)
+ arena_monster_died(monster, killer, killer_index, silent);
+
mons_clear_trapping_net(monster);
// Update list of monsters beholding player.
@@ -3584,7 +3588,13 @@ static void _arena_set_foe(monsters *mons)
else if (nearest_unseen != -1)
{
mons->target = menv[nearest_unseen].pos();
- mons->behaviour = BEH_WANDER;
+ if (mons->type == MONS_TEST_SPAWNER)
+ {
+ mons->foe = nearest_unseen;
+ mons->behaviour = BEH_SEEK;
+ }
+ else
+ mons->behaviour = BEH_WANDER;
}
else
{