summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/Kills.cc3
-rw-r--r--crawl-ref/source/abl-show.cc7
-rw-r--r--crawl-ref/source/abyss.cc12
-rw-r--r--crawl-ref/source/beam.cc4
-rw-r--r--crawl-ref/source/command.cc4
-rw-r--r--crawl-ref/source/debug.cc22
-rw-r--r--crawl-ref/source/decks.cc72
-rw-r--r--crawl-ref/source/directn.cc6
-rw-r--r--crawl-ref/source/dungeon.cc388
-rw-r--r--crawl-ref/source/dungeon.h1
-rw-r--r--crawl-ref/source/effects.cc18
-rw-r--r--crawl-ref/source/externs.h6
-rw-r--r--crawl-ref/source/fight.cc26
-rw-r--r--crawl-ref/source/hiscores.cc2
-rw-r--r--crawl-ref/source/it_use3.cc40
-rw-r--r--crawl-ref/source/item_use.cc6
-rw-r--r--crawl-ref/source/lev-pand.cc21
-rw-r--r--crawl-ref/source/mapdef.cc17
-rw-r--r--crawl-ref/source/mapdef.h14
-rw-r--r--crawl-ref/source/mon-data.h10
-rw-r--r--crawl-ref/source/mon-util.cc56
-rw-r--r--crawl-ref/source/mon-util.h2
-rw-r--r--crawl-ref/source/monplace.cc780
-rw-r--r--crawl-ref/source/monplace.h158
-rw-r--r--crawl-ref/source/monstuff.cc26
-rw-r--r--crawl-ref/source/mstuff2.cc95
-rw-r--r--crawl-ref/source/religion.cc90
-rw-r--r--crawl-ref/source/spells2.cc128
-rw-r--r--crawl-ref/source/spells2.h2
-rw-r--r--crawl-ref/source/spells3.cc18
-rw-r--r--crawl-ref/source/spells4.cc65
-rw-r--r--crawl-ref/source/spells4.h3
-rw-r--r--crawl-ref/source/spl-cast.cc145
-rw-r--r--crawl-ref/source/stuff.cc6
-rw-r--r--crawl-ref/source/stuff.h1
-rw-r--r--crawl-ref/source/tags.cc7
-rw-r--r--crawl-ref/source/tags.h3
-rw-r--r--crawl-ref/source/tile1.cc8
-rw-r--r--crawl-ref/source/xom.cc23
39 files changed, 1227 insertions, 1068 deletions
diff --git a/crawl-ref/source/Kills.cc b/crawl-ref/source/Kills.cc
index 6402e82f62..7831568323 100644
--- a/crawl-ref/source/Kills.cc
+++ b/crawl-ref/source/Kills.cc
@@ -612,7 +612,8 @@ kill_monster_desc::kill_monster_desc(const monsters *mon)
break;
default: break;
}
- if (modifier != M_NORMAL) monnum = mon->number;
+ if (modifier != M_NORMAL)
+ monnum = mon->base_monster;
if (mon->has_ench(ENCH_SHAPESHIFTER) ||
mon->has_ench(ENCH_GLOWING_SHAPESHIFTER))
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc
index 0f97a557a9..1ab70b9a0f 100644
--- a/crawl-ref/source/abl-show.cc
+++ b/crawl-ref/source/abl-show.cc
@@ -1544,7 +1544,9 @@ static bool _do_ability(const ability_def& abil)
case ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB:
summon_ice_beast_etc( 20 + you.skills[SK_INVOCATIONS] * 3,
- MONS_NEQOXEC + random2(5), true );
+ static_cast<monster_type>(
+ MONS_NEQOXEC + random2(5)),
+ true );
exercise(SK_INVOCATIONS, 2 + random2(3));
break;
@@ -1601,7 +1603,8 @@ static bool _do_ability(const ability_def& abil)
case ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB:
summon_ice_beast_etc( 20 + you.skills[SK_INVOCATIONS] * 3,
- MONS_EXECUTIONER + random2(5),
+ static_cast<monster_type>(
+ MONS_EXECUTIONER + random2(5)),
true );
exercise(SK_INVOCATIONS, 6 + random2(6));
diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc
index b1e2741ef5..b53669672a 100644
--- a/crawl-ref/source/abyss.cc
+++ b/crawl-ref/source/abyss.cc
@@ -433,11 +433,12 @@ void area_shift(void)
xom_check_nearness();
+ mgen_data mons;
+ mons.level_type = LEVEL_ABYSS;
+ mons.proximity = PROX_AWAY_FROM_PLAYER;
+
for (unsigned int mcount = 0; mcount < 15; mcount++)
- {
- mons_place( RANDOM_MONSTER, BEH_HOSTILE, MHITNOT, false, 1, 1,
- LEVEL_ABYSS, PROX_AWAY_FROM_PLAYER ); // PROX_ANYWHERE?
- }
+ mons_place(mons);
// And allow monsters in transit another chance to return.
place_transiting_monsters();
@@ -599,8 +600,7 @@ static bool spawn_corrupted_servant_near(const coord_def &pos)
one_chance_in(5 + you.skills[SK_INVOCATIONS] / 4)?
BEH_HOSTILE : BEH_NEUTRAL;
const int mid =
- create_monster( mons, 5, beh, p.x, p.y, MHITNOT, MONS_PROGRAM_BUG );
-
+ create_monster( mgen_data( mons, beh, 5, p ) );
return (mid != -1);
}
return (false);
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 6244ecea12..9041ba1232 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -2989,7 +2989,9 @@ static void _affect_place_explosion_clouds(bolt &beam, int x, int y)
if (grd[x][y] == DNGN_FLOOR && mgrd[x][y] == NON_MONSTER
&& one_chance_in(4))
{
- mons_place( MONS_FIRE_VORTEX, BEH_HOSTILE, MHITNOT, true, x, y );
+ mons_place(
+ mgen_data::hostile_at(
+ MONS_FIRE_VORTEX, coord_def(x, y)));
}
}
}
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index 247cbfe1f4..527907745b 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -927,10 +927,10 @@ static bool do_description(std::string key, std::string footer = "")
case MONS_RED_DRACONIAN:
case MONS_WHITE_DRACONIAN:
case MONS_PALE_DRACONIAN:
- mon.number = mon_num;
+ mon.base_monster = mon_num;
break;
default:
- mon.number = 0;
+ mon.base_monster = MONS_PROGRAM_BUG;
break;
}
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index 25c355d1be..6ab2eb2a63 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -394,9 +394,12 @@ void create_spec_monster(void)
if (mon == -1)
canned_msg( MSG_OK );
else
- create_monster( mon, 0, BEH_SLEEP,
- you.x_pos, you.y_pos, MHITNOT, MONS_PROGRAM_BUG,
- true );
+ {
+ create_monster(
+ mgen_data::sleeper_at(
+ static_cast<monster_type>(mon),
+ you.pos()));
+ }
} // end create_spec_monster()
#endif
@@ -435,7 +438,7 @@ void create_spec_monster_name(int x, int y)
mons_spec mspec = mlist.get_monster(0);
if (!force_place && mspec.mid != -1)
{
- coord_def place = find_newmons_square(mspec.mid, x, y);
+ coord_def place = find_newmons_square(mspec.mid, coord_def(x, y));
if (in_bounds(place))
{
x = place.x;
@@ -1431,13 +1434,16 @@ void stethoscope(int mwh)
// print stats and other info
mprf(MSGCH_DIAGNOSTICS,
"HD=%d (%lu) HP=%d/%d AC=%d EV=%d MR=%d SP=%d "
- "energy=%d num=%d flags=%04lx",
+ "energy=%d%s%s num=%d flags=%04lx",
menv[i].hit_dice,
menv[i].experience,
menv[i].hit_points, menv[i].max_hit_points,
menv[i].ac, menv[i].ev,
mons_resist_magic( &menv[i] ),
menv[i].speed, menv[i].speed_increment,
+ menv[i].base_monster != MONS_PROGRAM_BUG ? " base=" : "",
+ menv[i].base_monster != MONS_PROGRAM_BUG ?
+ get_monster_data(menv[i].base_monster)->name : "",
menv[i].number, menv[i].flags );
// print behaviour information
@@ -2516,8 +2522,10 @@ void error_message_to_player(void)
static int create_fsim_monster(int mtype, int hp)
{
const int mi =
- create_monster( mtype, 0, BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITNOT, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data::hostile_at(
+ static_cast<monster_type>(mtype),
+ you.pos() ) );
if (mi == -1)
return (mi);
diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc
index 14c67f1a8e..ceb76498d7 100644
--- a/crawl-ref/source/decks.cc
+++ b/crawl-ref/source/decks.cc
@@ -2307,9 +2307,9 @@ static bool _trowel_card(int power, deck_rarity_type rarity)
MONS_ORANGE_STATUE, MONS_SILVER_STATUE, MONS_ICE_STATUE
};
- if ( create_monster(RANDOM_ELEMENT(statues), 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG) != -1 )
+ if (create_monster(
+ mgen_data(RANDOM_ELEMENT(statues),
+ BEH_HOSTILE, 0, you.pos(), MHITYOU)) != -1)
{
mpr("A menacing statue appears!");
num_made++;
@@ -2320,9 +2320,10 @@ static bool _trowel_card(int power, deck_rarity_type rarity)
MONS_IRON_GOLEM, MONS_CRYSTAL_GOLEM, MONS_TOENAIL_GOLEM
};
- if ( create_monster(RANDOM_ELEMENT(golems), 5, BEH_FRIENDLY,
- you.x_pos, you.y_pos, you.pet_target,
- MONS_PROGRAM_BUG) != -1 )
+ if (create_monster(
+ mgen_data( RANDOM_ELEMENT(golems),
+ BEH_FRIENDLY, 5, you.pos(),
+ you.pet_target )) != -1)
{
mpr("You construct a golem!");
num_made++;
@@ -2489,9 +2490,10 @@ static void _summon_demon_card(int power, deck_rarity_type rarity)
else
dct = DEMON_LESSER;
- create_monster( summon_any_demon(dct), std::min(power/50,6),
- BEH_FRIENDLY, you.x_pos, you.y_pos, you.pet_target,
- MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( summon_any_demon(dct), BEH_FRIENDLY,
+ std::min(power / 50, 6),
+ you.pos(), you.pet_target ));
}
static void _summon_any_monster(int power, deck_rarity_type rarity)
@@ -2539,11 +2541,11 @@ static void _summon_any_monster(int power, deck_rarity_type rarity)
const bool friendly = (power_level > 0 || !one_chance_in(4));
- create_monster( mon_chosen, 3,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- chosen_x, chosen_y,
- friendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( mon_chosen,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ 3, coord_def(chosen_x, chosen_y),
+ MHITYOU ) );
}
static void _summon_dancing_weapon(int power, deck_rarity_type rarity)
@@ -2551,12 +2553,12 @@ static void _summon_dancing_weapon(int power, deck_rarity_type rarity)
const int power_level = get_power_level(power, rarity);
const bool friendly = (power_level > 0 || !one_chance_in(4));
- const int mon = create_monster( MONS_DANCING_WEAPON, power_level + 3,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- you.x_pos, you.y_pos,
- friendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG, false, false, false,
- true );
+ const int mon =
+ create_monster(
+ mgen_data( MONS_DANCING_WEAPON,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ power_level + 3, you.pos(),
+ friendly ? you.pet_target : MHITYOU ));
// Given the abundance of Nemelex decks, not setting hard reset
// leaves a trail of weapons behind, most of which just get
@@ -2624,11 +2626,12 @@ static void _summon_flying(int power, deck_rarity_type rarity)
for ( int i = 0; i < power_level * 5 + 2; ++i )
{
- create_monster(result, std::min(power/50, 6),
+ create_monster(
+ mgen_data( result,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- you.x_pos, you.y_pos,
- friendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG);
+ std::min(power/50, 6),
+ you.pos(),
+ friendly ? you.pet_target : MHITYOU ));
}
}
@@ -2640,11 +2643,13 @@ static void _summon_skeleton(int power, deck_rarity_type rarity)
MONS_SKELETON_LARGE, MONS_SKELETAL_WARRIOR, MONS_SKELETAL_DRAGON
};
- create_monster(skeltypes[power_level], std::min(power/50,6),
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- you.x_pos, you.y_pos,
- friendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG);
+ create_monster(
+ mgen_data(
+ skeltypes[power_level],
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ std::min(power/50,6),
+ you.pos(),
+ friendly ? you.pet_target : MHITYOU ));
}
static void _summon_ugly(int power, deck_rarity_type rarity)
@@ -2659,11 +2664,12 @@ static void _summon_ugly(int power, deck_rarity_type rarity)
else
ugly = MONS_UGLY_THING;
- create_monster(ugly, std::min(power/50,6),
+ create_monster(
+ mgen_data( ugly,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- you.x_pos, you.y_pos,
- friendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG);
+ std::min(power/50,6),
+ you.pos(),
+ friendly ? you.pet_target : MHITYOU));
}
static int _card_power(deck_rarity_type rarity)
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index e1ef6b8547..18ff4e67d2 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -2073,11 +2073,11 @@ static void describe_monster(const monsters *mon)
if (player_beheld_by(mon))
mpr("You are beheld by her song.", MSGCH_EXAMINE);
- if (mon->type == MONS_HYDRA)
- {
+ // XXX: Not strictly correct if we add any other monster with a
+ // variable number of attacks.
+ if (mon->has_hydra_multi_attack())
mprf(MSGCH_EXAMINE, "It has %d head%s.", mon->number,
(mon->number > 1? "s" : ""));
- }
print_wounds(mon);
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index e2db1acb61..f7a1c55901 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -79,7 +79,7 @@
struct pit_mons_def
{
- int type;
+ monster_type type;
int rare;
};
@@ -759,7 +759,7 @@ static void _reset_level()
menv[i].type = -1;
for (int i = 0; i < 20; i++)
- env.mons_alloc[i] = -1;
+ env.mons_alloc[i] = MONS_PROGRAM_BUG;
mgrd.init(NON_MONSTER);
igrd.init(NON_ITEM);
@@ -2773,7 +2773,7 @@ static bool _make_room(int sx,int sy,int ex,int ey,int max_doors, int doorlevel)
return true;
} //end make_room()
-static int _pick_unique(int lev)
+static monster_type _pick_unique(int lev)
{
int which_unique =
((lev > 19) ? random_range(MONS_LOUISE, MONS_BORIS) :
@@ -2796,7 +2796,7 @@ static int _pick_unique(int lev)
which_unique = MONS_POLYPHEMUS;
}
- return (which_unique);
+ return static_cast<monster_type>(which_unique);
}
// Place uniques on the level.
@@ -2817,14 +2817,15 @@ static int _place_uniques(int level_number, char level_type)
while (one_chance_in(3))
{
- int which_unique = -1; // 30 in total
+ monster_type which_unique = MONS_PROGRAM_BUG; // 30 in total
- while (which_unique < 0 || you.unique_creatures[which_unique])
+ while (which_unique == MONS_PROGRAM_BUG
+ || you.unique_creatures[which_unique])
{
// sometimes, we just quit if a unique is already placed.
- if (which_unique >= 0 && !one_chance_in(3))
+ if (which_unique != MONS_PROGRAM_BUG && !one_chance_in(3))
{
- which_unique = -1;
+ which_unique = MONS_PROGRAM_BUG;
break;
}
@@ -2833,13 +2834,16 @@ static int _place_uniques(int level_number, char level_type)
// usually, we'll have quit after a few tries. Make sure we don't
// create unique[-1] by accident.
- if (which_unique == -1)
+ if (which_unique == MONS_PROGRAM_BUG)
break;
- // note: unique_creatures 40 + used by unique demons
- if (place_monster( not_used, which_unique, level_number,
- BEH_SLEEP, MHITNOT, false, 1, 1, true,
- PROX_ANYWHERE, MONS_PROGRAM_BUG, 0, MMT_NO_MONS ))
+ mgen_data mg( which_unique, BEH_SLEEP, 0,
+ coord_def(), MHITNOT, MG_PERMIT_BANDS,
+ MONS_PROGRAM_BUG, 0, BLACK,
+ level_number, PROX_ANYWHERE );
+ mg.map_mask = MMT_NO_MONS;
+
+ if (place_monster(mg) != -1)
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Placed %s",
@@ -2851,19 +2855,23 @@ static int _place_uniques(int level_number, char level_type)
return num_placed;
}
-static int _place_monster_vector(std::vector<int> montypes,
+static int _place_monster_vector(std::vector<monster_type> montypes,
int level_number, int num_to_place)
{
int result = 0;
- int not_used = 0;
+
+ mgen_data mg;
+ mg.power = level_number;
+ mg.behaviour = BEH_SLEEP;
+ mg.flags |= MG_PERMIT_BANDS;
+ mg.map_mask |= MMT_NO_MONS;
+
for (int i = 0; i < num_to_place; i++)
- if (place_monster( not_used, montypes[random2(montypes.size())],
- level_number, BEH_SLEEP, MHITNOT,
- false, 1, 1, true, PROX_ANYWHERE,
- MONS_PROGRAM_BUG, 0, MMT_NO_MONS ))
- {
+ {
+ mg.cls = montypes[random2(montypes.size())];
+ if (place_monster(mg) != -1)
++result;
- }
+ }
return result;
}
@@ -2872,7 +2880,7 @@ static int _place_monster_vector(std::vector<int> montypes,
static void _place_aquatic_monsters(int level_number, char level_type)
{
int lava_spaces = 0, water_spaces = 0;
- std::vector<int> swimming_things(4u, NON_MONSTER);
+ std::vector<monster_type> swimming_things(4u, MONS_PROGRAM_BUG);
// count the number of lava and water tiles {dlb}:
for (int x = 0; x < GXM; x++)
@@ -2888,21 +2896,24 @@ static void _place_aquatic_monsters(int level_number, char level_type)
{
for (int i = 0; i < 4; i++)
{
- swimming_things[i] = MONS_LAVA_WORM + random2(3);
+ swimming_things[i] =
+ static_cast<monster_type>(
+ MONS_LAVA_WORM + random2(3) );
if (one_chance_in(30))
swimming_things[i] = MONS_SALAMANDER;
}
_place_monster_vector(swimming_things, level_number,
std::min(random2avg(9, 2)
- + (random2(lava_spaces) / 10), 15));
+ + (random2(lava_spaces) / 10), 15));
}
if (water_spaces > 49)
{
for (int i = 0; i < 4; i++)
{
- swimming_things[i] = MONS_BIG_FISH + random2(4);
+ swimming_things[i] =
+ static_cast<monster_type>(MONS_BIG_FISH + random2(4));
if (player_in_branch( BRANCH_SWAMP ) && !one_chance_in(3))
swimming_things[i] = MONS_SWAMP_WORM;
else if (player_in_branch( BRANCH_SHOALS ))
@@ -2929,7 +2940,6 @@ static void _place_aquatic_monsters(int level_number, char level_type)
static void _builder_monsters(int level_number, char level_type, int mon_wanted)
{
- int not_used = 0;
if (level_type == LEVEL_PANDEMONIUM
|| player_in_branch(BRANCH_ECUMENICAL_TEMPLE))
{
@@ -2938,9 +2948,12 @@ static void _builder_monsters(int level_number, char level_type, int mon_wanted)
for (int i = 0; i < mon_wanted; i++)
{
- place_monster( not_used, RANDOM_MONSTER, level_number, BEH_SLEEP,
- MHITNOT, false, 1, 1, true, PROX_ANYWHERE,
- MONS_PROGRAM_BUG, 0, MMT_NO_MONS );
+ mgen_data mg;
+ mg.power = level_number;
+ mg.flags |= MG_PERMIT_BANDS;
+ mg.map_mask |= MMT_NO_MONS;
+
+ place_monster(mg);
}
_place_uniques(level_number, level_type);
@@ -2950,10 +2963,10 @@ static void _builder_monsters(int level_number, char level_type, int mon_wanted)
else
{
if (one_chance_in(3))
- mons_place( MONS_CURSE_SKULL, BEH_SLEEP, MHITNOT, false, 0, 0 );
+ mons_place( mgen_data( MONS_CURSE_SKULL, BEH_SLEEP ) );
if (one_chance_in(7))
- mons_place( MONS_CURSE_SKULL, BEH_SLEEP, MHITNOT, false, 0, 0 );
+ mons_place( mgen_data( MONS_CURSE_SKULL, BEH_SLEEP ) );
}
}
@@ -3127,7 +3140,7 @@ static void _specr_2(spec_room &sr)
// then place a "lord of the pit" of lord_type at (lordx, lordy).
static void _fill_monster_pit( spec_room &sr, FixedVector<pit_mons_def,
MAX_PIT_MONSTERS> &pit_list, int density,
- int lord_type, int lordx, int lordy )
+ monster_type lord_type, int lordx, int lordy )
{
int i, x, y;
@@ -3163,7 +3176,15 @@ static void _fill_monster_pit( spec_room &sr, FixedVector<pit_mons_def,
// put the boss monster down
if (lord_type != MONS_PROGRAM_BUG)
- mons_place( lord_type, BEH_SLEEP, MHITNOT, true, lordx, lordy );
+ {
+ mgen_data mg;
+ mg.cls = lord_type;
+ mg.behaviour = BEH_SLEEP;
+ mg.pos = coord_def(lordx, lordy);
+
+ mons_place(
+ mgen_data::sleeper_at(lord_type, coord_def(lordx, lordy)));
+ }
// place monsters and give them items {dlb}:
for (x = sr.x1; x <= sr.x2; x++)
@@ -3183,8 +3204,10 @@ static void _fill_monster_pit( spec_room &sr, FixedVector<pit_mons_def,
for (i = 0; i < num_types; i++)
if (roll < pit_list[i].rare)
{
- mons_place( pit_list[i].type, BEH_SLEEP, MHITNOT,
- true, x, y );
+ mons_place(
+ mgen_data::sleeper_at(
+ pit_list[i].type,
+ coord_def(x, y)));
break;
}
}
@@ -3201,7 +3224,7 @@ static void _special_room(int level_number, spec_room &sr)
unsigned char i; // general purpose loop variable {dlb}
int temp_rand = 0; // probability determination {dlb}
- FixedVector < int, 10 > mons_alloc; // was [20] {dlb}
+ FixedVector < monster_type, 10 > mons_alloc; // was [20] {dlb}
char lordx = 0, lordy = 0;
@@ -3299,8 +3322,10 @@ static void _special_room(int level_number, spec_room &sr)
if (one_chance_in(4))
continue;
- mons_place( mons_alloc[random2(10)], BEH_SLEEP, MHITNOT,
- true, x, y );
+ mons_place(
+ mgen_data::sleeper_at(
+ mons_alloc[random2(10)],
+ coord_def(x, y)));
}
break;
@@ -3333,13 +3358,16 @@ static void _special_room(int level_number, spec_room &sr)
if (x == lordx && y == lordy)
continue;
- mons_place( mons_alloc[random2(10)], BEH_SLEEP, MHITNOT,
- true, x, y );
+ mons_place(
+ mgen_data::sleeper_at(
+ mons_alloc[random2(10)],
+ coord_def(x, y) ));
}
// put the boss monster down
- mons_place( MONS_BIG_KOBOLD, BEH_SLEEP, MHITNOT, true, lordx, lordy );
-
+ mons_place(
+ mgen_data::sleeper_at( MONS_BIG_KOBOLD,
+ coord_def(lordx, lordy) ));
break;
case SROOM_TREASURY:
@@ -3372,9 +3400,11 @@ static void _special_room(int level_number, spec_room &sr)
}
// place guardian {dlb}:
- mons_place( MONS_GUARDIAN_NAGA, BEH_SLEEP, MHITNOT, true,
- sr.x1 + random2( sr.x2 - sr.x1 ),
- sr.y1 + random2( sr.y2 - sr.y1 ) );
+ mons_place(
+ mgen_data::sleeper_at(
+ MONS_GUARDIAN_NAGA,
+ coord_def(sr.x1 + random2( sr.x2 - sr.x1 ),
+ sr.y1 + random2( sr.y2 - sr.y1 )) ));
break;
case SROOM_BEEHIVE:
@@ -3427,13 +3457,18 @@ static void _beehive(spec_room &sr)
// the hive is chock full of bees!
- mons_place( one_chance_in(7) ? MONS_KILLER_BEE_LARVA
- : MONS_KILLER_BEE,
- BEH_SLEEP, MHITNOT, true, x, y );
+ mons_place(
+ mgen_data::sleeper_at(
+ one_chance_in(7) ?
+ MONS_KILLER_BEE_LARVA : MONS_KILLER_BEE,
+ coord_def(x, y)));
}
- mons_place( MONS_QUEEN_BEE, BEH_SLEEP, MHITNOT, true, queenx, queeny );
-} // end beehive()
+ mons_place(
+ mgen_data::sleeper_at(
+ MONS_QUEEN_BEE,
+ coord_def(queenx, queeny )));
+}
// used for placement of vaults
static bool _may_overwrite_feature(const dungeon_feature_type grid,
@@ -4490,22 +4525,21 @@ bool dgn_place_monster(mons_spec &mspec,
grd[vx][vy] = habitat2grid(habitat);
}
- int mindex = NON_MONSTER;
- const bool placed
- = place_monster( mindex, mid, monster_level,
- m_generate_awake ? BEH_WANDER : BEH_SLEEP,
- MHITNOT, true, vx, vy, false,
- PROX_ANYWHERE, mspec.monnum);
+ mgen_data mg(static_cast<monster_type>(mid));
+ mg.power = monster_level;
+ mg.behaviour = m_generate_awake ? BEH_WANDER : BEH_SLEEP;
+ mg.base_type = mspec.monbase;
+ mg.number = mspec.number;
+ mg.colour = mspec.colour;
+ mg.pos = coord_def(vx, vy);
- if (placed && mindex != -1 && mindex != NON_MONSTER)
+ const int mindex = place_monster(mg);
+ if (mindex != -1)
{
- if (mspec.colour != BLACK)
- menv[mindex].colour = mspec.colour;
-
if (mspec.items.size() > 0)
_dgn_give_mon_spec_items(mspec, mindex, mid, monster_level);
}
- return (placed);
+ return (mindex != -1);
}
return (false);
}
@@ -4618,8 +4652,6 @@ static int _vault_grid( vault_placement &place,
int rune_subst,
bool following )
{
- int not_used;
-
keyed_mapspec *mapsp = following? NULL : place.map.mapspec_for_key(vgrid);
if (mapsp)
{
@@ -4661,8 +4693,8 @@ static int _vault_grid( vault_placement &place,
if (vgrid == 'F' && one_chance_in(100))
{
vgrid = '.';
- place_monster( not_used, _random_evil_statue(), 30, BEH_HOSTILE,
- MHITNOT, true, vx, vy, false);
+ create_monster(
+ mgen_data::hostile_at( _random_evil_statue(), coord_def(vx, vy) ));
}
// first, set base tile for grids {dlb}:
@@ -4831,13 +4863,13 @@ static int _vault_grid( vault_placement &place,
if (vgrid == 'S' || vgrid == 'H')
{
- const int mtype = (vgrid == 'H') ? MONS_ORANGE_STATUE
- : MONS_SILVER_STATUE;
+ const monster_type mtype =
+ (vgrid == 'H') ? MONS_ORANGE_STATUE : MONS_SILVER_STATUE;
grd[vx][vy] = DNGN_FLOOR;
- place_monster( not_used, mtype, 30, BEH_HOSTILE,
- MHITNOT, true, vx, vy, false);
+ create_monster(
+ mgen_data::hostile_at( mtype, coord_def(vx, vy) ));
}
// finally, handle grids that place monsters {dlb}:
@@ -6241,7 +6273,10 @@ static void _labyrinth_place_items(const coord_def &end)
static void _labyrinth_place_exit(const coord_def &end)
{
_labyrinth_place_items(end);
- mons_place( MONS_MINOTAUR, BEH_SLEEP, MHITNOT, true, end.x, end.y );
+ mons_place(
+ mgen_data::sleeper_at(
+ MONS_MINOTAUR,
+ end));
grd(end) = DNGN_ESCAPE_HATCH_UP;
}
@@ -7115,16 +7150,18 @@ static void _morgue(spec_room &sr)
for (y = sr.y1; y <= sr.y2; y++)
if (grd[x][y] == DNGN_FLOOR || grd[x][y] == DNGN_BUILDER_SPECIAL_FLOOR)
{
- int mon_type;
temp_rand = random2(24);
- mon_type = ((temp_rand > 11) ? MONS_ZOMBIE_SMALL : // 50.0%
- (temp_rand > 7) ? MONS_WIGHT : // 16.7%
- (temp_rand > 3) ? MONS_NECROPHAGE : // 16.7%
- (temp_rand > 0) ? MONS_WRAITH // 12.5%
- : MONS_VAMPIRE); // 4.2%
+ const monster_type mon_type =
+ ((temp_rand > 11) ? MONS_ZOMBIE_SMALL : // 50.0%
+ (temp_rand > 7) ? MONS_WIGHT : // 16.7%
+ (temp_rand > 3) ? MONS_NECROPHAGE : // 16.7%
+ (temp_rand > 0) ? MONS_WRAITH // 12.5%
+ : MONS_VAMPIRE); // 4.2%
- mons_place( mon_type, BEH_SLEEP, MHITNOT, true, x, y );
+ mons_place(
+ mgen_data::sleeper_at(
+ mon_type, coord_def(x, y) ));
}
} // end morgue()
@@ -7205,203 +7242,6 @@ bool place_specific_trap(int spec_x, int spec_y, trap_type spec_type)
return false;
} // end place_specific_trap()
-void define_zombie( int mid, int ztype, int cs, int power )
-{
- int mons_sec2 = 0;
- int zombie_size = 0;
- bool ignore_rarity = false;
- int test, cls;
-
- if (power > 27)
- power = 27;
-
- // set size based on zombie class (cs)
- switch(cs)
- {
- case MONS_ZOMBIE_SMALL:
- case MONS_SIMULACRUM_SMALL:
- case MONS_SKELETON_SMALL:
- zombie_size = Z_SMALL;
- break;
-
- case MONS_ZOMBIE_LARGE:
- case MONS_SIMULACRUM_LARGE:
- case MONS_SKELETON_LARGE:
- zombie_size = Z_BIG;
- break;
-
- case MONS_SPECTRAL_THING:
- zombie_size = -1;
- break;
-
- default:
- // this should NEVER happen.
- perror("\ncreate_zombie() got passed incorrect zombie type!\n");
- end(0);
- break;
- }
-
- // that is, random creature from which to fashion undead
- if (ztype == MONS_PROGRAM_BUG)
- {
- // how OOD this zombie can be.
- int relax = 5;
-
- // pick an appropriate creature to make a zombie out of,
- // levelwise. The old code was generating absolutely
- // incredible OOD zombies.
- while (true)
- {
- // this limit can be updated if mons->number goes >8 bits..
- test = random2(182); // not guaranteed to be valid, so..
- cls = mons_species(test);
- if (cls == MONS_PROGRAM_BUG)
- continue;
-
- // on certain branches, zombie creation will fail if we use
- // the mons_rarity() functions, because (for example) there
- // are NO zombifiable "native" abyss creatures. Other branches
- // where this is a problem are hell levels and the crypt.
- // we have to watch for summoned zombies on other levels, too,
- // such as the Temple, HoB, and Slime Pits.
- if (you.level_type != LEVEL_DUNGEON
- || player_in_hell()
- || player_in_branch( BRANCH_HALL_OF_ZOT )
- || player_in_branch( BRANCH_VESTIBULE_OF_HELL )
- || player_in_branch( BRANCH_ECUMENICAL_TEMPLE )
- || player_in_branch( BRANCH_CRYPT )
- || player_in_branch( BRANCH_TOMB )
- || player_in_branch( BRANCH_HALL_OF_BLADES )
- || player_in_branch( BRANCH_SNAKE_PIT )
- || player_in_branch( BRANCH_SLIME_PITS )
- || one_chance_in(1000))
- {
- ignore_rarity = true;
- }
-
- // don't make out-of-rarity zombies when we don't have to
- if (!ignore_rarity && mons_rarity(cls) == 0)
- continue;
-
- // monster class must be zombifiable
- if (!mons_zombie_size(cls))
- continue;
-
- // if skeleton, monster must have a skeleton
- if ((cs == MONS_SKELETON_SMALL || cs == MONS_SKELETON_LARGE)
- && !mons_skeleton(cls))
- {
- continue;
- }
-
- // size must match, but you can make a spectral thing out of anything.
- if (mons_zombie_size(cls) != zombie_size && zombie_size != -1)
- continue;
-
- // hack -- non-dungeon zombies are always made out of nastier
- // monsters
- if (you.level_type != LEVEL_DUNGEON && mons_power(cls) > 8)
- break;
-
- // check for rarity.. and OOD - identical to mons_place()
- int level, diff, chance;
-
- level = mons_level( cls ) - 4;
- diff = level - power;
-
- chance = (ignore_rarity) ? 100
- : mons_rarity(cls) - (diff * diff) / 2;
-
- if (power > level - relax && power < level + relax
- && random2avg(100, 2) <= chance)
- {
- break;
- }
-
- // every so often, we'll relax the OOD restrictions. Avoids
- // infinite loops (if we don't do this, things like creating
- // a large skeleton on level 1 may hang the game!)
- if (one_chance_in(5))
- relax++;
- }
-
- // set type and secondary appropriately
- menv[mid].number = cls;
- mons_sec2 = cls;
- }
- else
- {
- menv[mid].number = mons_species(ztype);
- mons_sec2 = menv[mid].number;
- }
-
- menv[mid].type = menv[mid].number;
-
- define_monster(mid);
-
- menv[mid].hit_points = hit_points( menv[mid].hit_dice, 6, 5 );
- menv[mid].max_hit_points = menv[mid].hit_points;
-
- menv[mid].ac -= 2;
-
- if (menv[mid].ac < 0)
- menv[mid].ac = 0;
-
- menv[mid].ev -= 5;
-
- if (menv[mid].ev < 0)
- menv[mid].ev = 0;
-
- menv[mid].speed -= 2;
-
- if (menv[mid].speed < 3)
- menv[mid].speed = 3;
-
- menv[mid].speed_increment = 70;
-
- if (cs == MONS_ZOMBIE_SMALL || cs == MONS_ZOMBIE_LARGE)
- {
- menv[mid].type = ((mons_zombie_size(menv[mid].number) == Z_BIG)
- ? MONS_ZOMBIE_LARGE : MONS_ZOMBIE_SMALL);
- }
- else if (cs == MONS_SKELETON_SMALL || cs == MONS_SKELETON_LARGE)
- {
- menv[mid].hit_points = hit_points( menv[mid].hit_dice, 5, 4 );
- menv[mid].max_hit_points = menv[mid].hit_points;
-
- menv[mid].ac -= 4;
-
- if (menv[mid].ac < 0)
- menv[mid].ac = 0;
-
- menv[mid].ev -= 2;
-
- if (menv[mid].ev < 0)
- menv[mid].ev = 0;
-
- menv[mid].type = ((mons_zombie_size( menv[mid].number ) == Z_BIG)
- ? MONS_SKELETON_LARGE : MONS_SKELETON_SMALL);
- }
- else if (cs == MONS_SIMULACRUM_SMALL || cs == MONS_SIMULACRUM_LARGE)
- {
- // Simulacrum aren't tough, but you can create piles of them. -- bwr
- menv[mid].hit_points = hit_points( menv[mid].hit_dice, 1, 4 );
- menv[mid].max_hit_points = menv[mid].hit_points;
- menv[mid].type = ((mons_zombie_size( menv[mid].number ) == Z_BIG)
- ? MONS_SIMULACRUM_LARGE : MONS_SIMULACRUM_SMALL);
- }
- else if (cs == MONS_SPECTRAL_THING)
- {
- menv[mid].hit_points = hit_points( menv[mid].hit_dice, 4, 4 );
- menv[mid].max_hit_points = menv[mid].hit_points;
- menv[mid].ac += 4;
- menv[mid].type = MONS_SPECTRAL_THING;
- }
-
- menv[mid].number = mons_sec2;
- menv[mid].colour = mons_class_colour(cs);
-} // end define_zombie()
-
static void _build_river( dungeon_feature_type river_type ) //mv
{
int i,j;
diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h
index d5da281228..b1fe5f3c59 100644
--- a/crawl-ref/source/dungeon.h
+++ b/crawl-ref/source/dungeon.h
@@ -311,7 +311,6 @@ bool dgn_place_map(int map, bool generating_level, bool clobber,
const coord_def &pos = coord_def(-1, -1));
void level_clear_vault_memory();
void level_welcome_messages();
-void define_zombie(int mid, int ztype, int cs, int power);
bool is_wall(int feature);
bool place_specific_trap(int spec_x, int spec_y, trap_type spec_type);
void place_spec_shop(int level_number, int shop_x, int shop_y,
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index e5cf28d11c..b68dda8cd7 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -2232,8 +2232,8 @@ static void hell_effects()
if (summon_instead)
{
- create_monster( which_beastie, 0, BEH_HOSTILE, you.x_pos,
- you.y_pos, MHITYOU, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( which_beastie, BEH_HOSTILE, 0, you.pos(), MHITYOU ));
}
else
{
@@ -2250,18 +2250,14 @@ static void hell_effects()
// try to summon at least one and up to five random monsters {dlb}
if (one_chance_in(3))
{
- create_monster( RANDOM_MONSTER, 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU, MONS_PROGRAM_BUG );
+ mgen_data mg;
+ mg.pos = you.pos();
+ mg.foe = MHITYOU;
+ create_monster(mg);
for (int i = 0; i < 4; i++)
- {
if (one_chance_in(3))
- {
- create_monster( RANDOM_MONSTER, 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG );
- }
- }
+ create_monster(mg);
}
}
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index d0d3349e4e..da0067ad31 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1037,6 +1037,7 @@ public:
unsigned long flags; // bitfield of boolean flags
unsigned long experience;
+ monster_type base_monster; // zombie base monster, draconian colour
unsigned int number; // #heads (hydra), etc.
int colour;
@@ -1076,6 +1077,9 @@ public:
int foe_distance() const;
bool needs_berserk(bool check_spells = true) const;
+ // Has a hydra-like variable number of attacks based on mons->number.
+ bool has_hydra_multi_attack() const;
+
bool has_ench(enchant_type ench) const;
bool has_ench(enchant_type ench, enchant_type ench2) const;
mon_enchant get_ench(enchant_type ench,
@@ -1414,7 +1418,7 @@ public:
FixedVector< shop_struct, MAX_SHOPS > shop; // shop list
FixedVector< trap_struct, MAX_TRAPS > trap; // trap list
- FixedVector< int, 20 > mons_alloc;
+ FixedVector< monster_type, 20 > mons_alloc;
map_markers markers;
double elapsed_time; // used during level load
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 0002593197..d371ec79a9 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -2343,16 +2343,20 @@ bool melee_attack::chop_hydra_head( int dam,
def_name(DESC_NOCAP_THE).c_str() );
}
- if (wpn_brand == SPWPN_FLAMING)
+ // Only living hydras get to regenerate heads.
+ if (defender->holiness() == MH_NATURAL)
{
- if (defender_visible)
- mpr( "The flame cauterises the wound!" );
- }
- else if (def->number < 19)
- {
- simple_monster_message( def, " grows two more!" );
- def->number += 2;
- heal_monster( def, 8 + random2(8), true );
+ if (wpn_brand == SPWPN_FLAMING)
+ {
+ if (defender_visible)
+ mpr( "The flame cauterises the wound!" );
+ }
+ else if (def->number < 19)
+ {
+ simple_monster_message( def, " grows two more!" );
+ def->number += 2;
+ heal_monster( def, 8 + random2(8), true );
+ }
}
}
@@ -2364,7 +2368,7 @@ bool melee_attack::chop_hydra_head( int dam,
bool melee_attack::decapitate_hydra(int dam, int damage_type)
{
- if (defender->id() == MONS_HYDRA)
+ if (defender->atype() == ACT_MONSTER && def->has_hydra_multi_attack())
{
const int dam_type = (damage_type != -1) ? damage_type
: attacker->damage_type();
@@ -3723,7 +3727,7 @@ void melee_attack::mons_apply_attack_flavour(const mon_attack_def &attk)
void melee_attack::mons_perform_attack_rounds()
{
- const int nrounds = atk->type == MONS_HYDRA? atk->number : 4;
+ const int nrounds = atk->has_hydra_multi_attack()? atk->number : 4;
const coord_def pos = defender->pos();
// Melee combat, tell attacker to wield its melee weapon.
diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc
index fdce0be304..d9521e419c 100644
--- a/crawl-ref/source/hiscores.cc
+++ b/crawl-ref/source/hiscores.cc
@@ -788,7 +788,7 @@ void scorefile_entry::init_death_cause(int dam, int dsrc,
if (monster->type >= 0 && monster->type < NUM_MONSTERS)
{
death_source = monster->type;
- mon_num = monster->number;
+ mon_num = monster->base_monster;
// Previously the weapon was only used for dancing weapons,
// but now we pass it in as a string through the scorefile
diff --git a/crawl-ref/source/it_use3.cc b/crawl-ref/source/it_use3.cc
index 7ca11eb85b..f3e63901b0 100644
--- a/crawl-ref/source/it_use3.cc
+++ b/crawl-ref/source/it_use3.cc
@@ -225,9 +225,9 @@ void special_wielded()
if (random2(8) <= player_spec_death())
{
did_god_conduct( DID_NECROMANCY, 1 );
- create_monster( MONS_SHADOW, 2, BEH_FRIENDLY,
- you.x_pos, you.y_pos, you.pet_target,
- MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(MONS_SHADOW, BEH_FRIENDLY,
+ 2, you.pos(), you.pet_target));
}
show_green = DARKGREY;
@@ -370,10 +370,9 @@ static bool evoke_horn_of_geryon()
else
{
mpr("You produce a hideous howling noise!");
- create_monster( MONS_BEAST, 4, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG,
- false, false, false, true );
+ create_monster(
+ mgen_data( MONS_BEAST, BEH_HOSTILE,
+ 4, you.pos(), MHITYOU ));
}
return rc;
}
@@ -389,9 +388,9 @@ static bool evoke_sceptre_of_asmodeus()
const monster_type mtype = (one_chance_in(4) ? MONS_FIEND :
summon_any_demon(DEMON_COMMON));
const bool good_summon =
- (create_monster( mtype, 6, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG) != -1);
+ create_monster(
+ mgen_data( mtype, BEH_HOSTILE,
+ 6, you.pos(), MHITYOU )) != -1;
if (good_summon)
{
@@ -699,9 +698,10 @@ static bool efreet_flask(void)
mpr("You open the flask...");
- const int efreet = create_monster( MONS_EFREET, 0, beha,
- you.x_pos, you.y_pos, hitting,
- MONS_PROGRAM_BUG );
+ const int efreet =
+ create_monster(
+ mgen_data( MONS_EFREET, beha, 0, you.pos(), hitting ) );
+
if (efreet != -1)
{
monsters *mon = &menv[efreet];
@@ -883,9 +883,9 @@ void tome_of_power(int slot)
}
else if (one_chance_in(36))
{
- if (create_monster( MONS_ABOMINATION_SMALL, 6, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG ) != -1)
+ if (create_monster(
+ mgen_data( MONS_ABOMINATION_SMALL, BEH_HOSTILE, 6,
+ you.pos(), MHITYOU )) != -1)
{
mpr("A horrible Thing appears!");
mpr("It doesn't look too friendly.");
@@ -950,7 +950,7 @@ void skill_manual(int slot)
static bool box_of_beasts()
{
- int beasty = MONS_PROGRAM_BUG; // error trapping {dlb}
+ monster_type beasty = MONS_PROGRAM_BUG;
int temp_rand = 0; // probability determination {dlb}
int ret = false;
@@ -982,9 +982,9 @@ static bool box_of_beasts()
hitting = MHITYOU;
}
- if (create_monster( beasty, 2 + random2(4), beha,
- you.x_pos, you.y_pos, hitting,
- MONS_PROGRAM_BUG ) != -1)
+ if (create_monster(
+ mgen_data( beasty, beha, 2 + random2(4),
+ you.pos(), hitting ) ) != -1)
{
mpr("...and something leaps out!");
xom_is_stimulated(14);
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index a6c10853d4..ca537e4443 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -4213,9 +4213,9 @@ void read_scroll( int slot )
break;
case SCR_SUMMONING:
- if (create_monster( MONS_ABOMINATION_SMALL, 6, BEH_FRIENDLY,
- you.x_pos, you.y_pos, you.pet_target,
- MONS_PROGRAM_BUG ) != -1)
+ if (create_monster(
+ mgen_data( MONS_ABOMINATION_SMALL, BEH_FRIENDLY, 6,
+ you.pos(), you.pet_target )) != -1)
{
mpr("A horrible Thing appears!");
}
diff --git a/crawl-ref/source/lev-pand.cc b/crawl-ref/source/lev-pand.cc
index 4e4308de08..9efabf1e9b 100644
--- a/crawl-ref/source/lev-pand.cc
+++ b/crawl-ref/source/lev-pand.cc
@@ -116,7 +116,8 @@ void init_pandemonium(void)
}
if (one_chance_in(10))
- env.mons_alloc[pc] = MONS_HELLION + random2(10);
+ env.mons_alloc[pc] =
+ static_cast<monster_type>(MONS_HELLION + random2(10));
if (one_chance_in(30))
env.mons_alloc[pc] = MONS_RED_DEVIL;
@@ -125,17 +126,21 @@ void init_pandemonium(void)
env.mons_alloc[pc] = MONS_IMP;
if (one_chance_in(20))
- env.mons_alloc[pc] = MONS_DEMONIC_CRAWLER + random2(5);
+ env.mons_alloc[pc] =
+ static_cast<monster_type>(MONS_DEMONIC_CRAWLER + random2(5));
}
if (one_chance_in(8))
- env.mons_alloc[7] = MONS_EXECUTIONER + random2(5);
+ env.mons_alloc[7] =
+ static_cast<monster_type>(MONS_EXECUTIONER + random2(5));
if (one_chance_in(5))
- env.mons_alloc[8] = MONS_EXECUTIONER + random2(5);
+ env.mons_alloc[8] =
+ static_cast<monster_type>(MONS_EXECUTIONER + random2(5));
if (one_chance_in(3))
- env.mons_alloc[9] = MONS_EXECUTIONER + random2(5);
+ env.mons_alloc[9] =
+ static_cast<monster_type>(MONS_EXECUTIONER + random2(5));
if (one_chance_in(10))
env.mons_alloc[7 + random2(3)] = MONS_FIEND;
@@ -170,6 +175,8 @@ void pandemonium_mons(void)
}
while (!mons_pan(pan_mons));
}
- mons_place(pan_mons, BEH_HOSTILE, MHITNOT, false, 50,50,
- LEVEL_PANDEMONIUM);
+ mgen_data mg(static_cast<monster_type>(pan_mons));
+ mg.level_type = LEVEL_PANDEMONIUM;
+
+ mons_place(mg);
} // end pandemonium_mons()
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index 26fb4f78aa..35c95428b8 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -1988,7 +1988,8 @@ mons_list::mons_spec_slot mons_list::parse_mons_spec(std::string spec)
}
mspec.mid = nspec.mid;
- mspec.monnum = nspec.monnum;
+ mspec.monbase = nspec.monbase;
+ mspec.number = nspec.number;
}
if (mspec.items.size() > 0)
@@ -2072,8 +2073,8 @@ void mons_list::get_zombie_type(std::string s, mons_spec &spec) const
{
s = s.substr(spectre.length());
spec.mid = MONS_SPECTRAL_THING;
- spec.monnum = get_monster_by_name(s, true);
- if (!mons_zombie_size(spec.monnum))
+ spec.monbase = get_monster_by_name(s, true);
+ if (!mons_zombie_size(spec.monbase))
spec.mid = MONS_PROGRAM_BUG;
return;
}
@@ -2084,9 +2085,9 @@ void mons_list::get_zombie_type(std::string s, mons_spec &spec) const
s = s.substr(0, s.length() - strlen(zombie_types[mod - 1]));
trim_string(s);
- spec.monnum = get_monster_by_name(s, true);
+ spec.monbase = get_monster_by_name(s, true);
- const int zombie_size = mons_zombie_size(spec.monnum);
+ const int zombie_size = mons_zombie_size(spec.monbase);
if (!zombie_size)
{
spec.mid = MONS_PROGRAM_BUG;
@@ -2104,7 +2105,7 @@ mons_spec mons_list::get_hydra_spec(const std::string &name) const
else if (nheads > 19)
nheads = 19;
- return mons_spec(MONS_HYDRA, nheads);
+ return mons_spec(MONS_HYDRA, MONS_PROGRAM_BUG, nheads);
}
// Handle draconians specified as:
@@ -2156,7 +2157,7 @@ mons_spec mons_list::drac_monspec(std::string name) const
const monster_type colour = get_monster_by_name(name, true);
if (colour != MONS_PROGRAM_BUG)
{
- spec.monnum = colour;
+ spec.monbase = colour;
return (spec);
}
@@ -2166,7 +2167,7 @@ mons_spec mons_list::drac_monspec(std::string name) const
return (MONS_PROGRAM_BUG);
std::string scolour = name.substr(0, wordend);
- if ((spec.monnum = draconian_colour_by_name(scolour)) == MONS_PROGRAM_BUG)
+ if ((spec.monbase = draconian_colour_by_name(scolour)) == MONS_PROGRAM_BUG)
return (MONS_PROGRAM_BUG);
name = trimmed_string(name.substr(wordend + 1));
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index 822b811b5c..c6fcd7cef3 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -397,20 +397,22 @@ class mons_spec
{
public:
int mid;
- int monnum; // The zombified monster for zombies, or head
- // count for hydras, or colour for draconians.
+ monster_type monbase; // Base monster for zombies and dracs.
+ int number; // Head count for hydras
int genweight, mlevel;
bool fix_mons;
bool generate_awake;
- int colour;
+ int colour;
item_list items;
- mons_spec(int id = RANDOM_MONSTER, int num = MONS_PROGRAM_BUG,
+ mons_spec(int id = RANDOM_MONSTER,
+ monster_type base = MONS_PROGRAM_BUG,
+ int num = 0,
int gw = 10, int ml = 0,
bool _fixmons = false, bool awaken = false)
- : mid(id), monnum(num), genweight(gw), mlevel(ml), fix_mons(_fixmons),
- generate_awake(awaken), colour(BLACK), items()
+ : mid(id), monbase(base), number(num), genweight(gw), mlevel(ml),
+ fix_mons(_fixmons), generate_awake(awaken), colour(BLACK), items()
{
}
};
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 8a71d38485..f9b2366b84 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -1453,7 +1453,7 @@
220, 12, MONS_YELLOW_WASP, MONS_YELLOW_WASP, MH_NATURAL, -3,
{ {AT_STING, AF_PARALYSE, 13}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 4, 3, 5, 0 },
- 5, 14, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_INSECT,
+ 5, 14, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_INSECT,
HT_LAND, 15, DEFAULT_ENERGY, MONUSE_NOTHING, SIZE_TINY
},
@@ -1464,7 +1464,7 @@
100, 10, MONS_GIANT_MOSQUITO, MONS_GIANT_MOSQUITO, MH_NATURAL, -3,
{ {AT_BITE, AF_DISEASE, 10}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 1, 3, 5, 0 },
- 0, 13, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_WHINE, I_PLANT,
+ 0, 13, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_WHINE, I_PLANT,
HT_LAND, 12, DEFAULT_ENERGY, MONUSE_NOTHING, SIZE_TINY
},
@@ -1475,7 +1475,7 @@
200, 10, MONS_GIANT_BLOWFLY, MONS_GIANT_BLOWFLY, MH_NATURAL, -3,
{ {AT_BITE, AF_PLAIN, 13}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 5, 3, 5, 0 },
- 2, 15, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_BUZZ, I_PLANT,
+ 2, 15, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_BUZZ, I_PLANT,
HT_LAND, 19, DEFAULT_ENERGY, MONUSE_NOTHING, SIZE_TINY
},
@@ -1486,7 +1486,7 @@
400, 14, MONS_YELLOW_WASP, MONS_RED_WASP, MH_NATURAL, -3,
{ {AT_STING, AF_PARALYSE, 23}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 8, 3, 5, 0 },
- 7, 14, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_BUZZ, I_PLANT,
+ 7, 14, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_BUZZ, I_PLANT,
HT_LAND, 15, DEFAULT_ENERGY, MONUSE_NOTHING, SIZE_TINY
},
@@ -1756,7 +1756,7 @@
1800, 11, MONS_HYDRA, MONS_HYDRA, MH_NATURAL, -3,
{ {AT_BITE, AF_PLAIN, 18}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 13, 3, 5, 0 },
- 0, 5, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_ROAR, I_INSECT,
+ 0, 5, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_ROAR, I_INSECT,
HT_LAND, 10, DEFAULT_ENERGY, MONUSE_OPEN_DOORS, SIZE_BIG
},
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 438a31f08e..0358b23b1d 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -554,7 +554,7 @@ monster_type draco_subspecies( const monsters *mon )
monster_type ret = mons_species( mon->type );
if (ret == MONS_DRACONIAN && mon->type != MONS_DRACONIAN)
- ret = static_cast<monster_type>( mon->number );
+ ret = static_cast<monster_type>( mon->base_monster );
return (ret);
}
@@ -665,9 +665,9 @@ int mons_colour(const monsters *monster)
return (monster->colour);
}
-int mons_zombie_base(const monsters *monster)
+monster_type mons_zombie_base(const monsters *monster)
{
- return (monster->number);
+ return (monster->base_monster);
}
bool mons_class_is_zombified(int mc)
@@ -1368,6 +1368,7 @@ void define_monster(monsters &mons)
int mcls = mons.type;
int hd, hp, hp_max, ac, ev, speed;
int monnumber = mons.number;
+ monster_type monbase = mons.base_monster;
const monsterentry *m = get_monster_data(mcls);
int col = mons_class_colour(mons.type);
mon_spellbook_type spells = MST_NO_SPELLS;
@@ -1389,9 +1390,7 @@ void define_monster(monsters &mons)
hd = 4 + random2(4);
ac = 3 + random2(7);
ev = 7 + random2(6);
-
- if (monnumber == MONS_PROGRAM_BUG) // ??
- col = random_colour();
+ col = random_colour();
break;
case MONS_ZOMBIE_SMALL:
@@ -1406,9 +1405,7 @@ void define_monster(monsters &mons)
hd = 8 + random2(4);
ac = 5 + random2avg(9, 2);
ev = 3 + random2(5);
-
- if (monnumber == MONS_PROGRAM_BUG)
- col = random_colour();
+ col = random_colour();
break;
case MONS_BEAST:
@@ -1492,10 +1489,9 @@ void define_monster(monsters &mons)
// White draconians will never be draconian scorchers, but
// apart from that, anything goes.
do
- {
- monnumber = MONS_BLACK_DRACONIAN + random2(8);
- }
- while (drac_colour_incompatible(mcls, monnumber));
+ monbase =
+ static_cast<monster_type>(MONS_BLACK_DRACONIAN + random2(8));
+ while (drac_colour_incompatible(mcls, monbase));
break;
}
case MONS_DRACONIAN_KNIGHT:
@@ -1510,7 +1506,7 @@ void define_monster(monsters &mons)
spells = (coinflip() ? MST_DEEP_ELF_CONJURER_I
: MST_DEEP_ELF_CONJURER_II);
- monnumber = MONS_BLACK_DRACONIAN + random2(8);
+ monbase = static_cast<monster_type>(MONS_BLACK_DRACONIAN + random2(8));
break;
}
case MONS_HUMAN:
@@ -1544,7 +1540,10 @@ void define_monster(monsters &mons)
mons.speed = speed;
mons.speed_increment = 70;
- if (mons.number == MONS_PROGRAM_BUG)
+ if (mons.base_monster == MONS_PROGRAM_BUG)
+ mons.base_monster = monbase;
+
+ if (mons.number == 0)
mons.number = monnumber;
mons.flags = 0L;
@@ -1669,13 +1668,13 @@ static std::string _str_monam(const monsters& mon, description_level_type desc,
{
case MONS_SPECTRAL_THING:
result += "spectral ";
- nametype = mon.number;
+ nametype = mon.base_monster;
break;
case MONS_ZOMBIE_SMALL: case MONS_ZOMBIE_LARGE:
case MONS_SKELETON_SMALL: case MONS_SKELETON_LARGE:
case MONS_SIMULACRUM_SMALL: case MONS_SIMULACRUM_LARGE:
- nametype = mon.number;
+ nametype = mon.base_monster;
break;
case MONS_DRACONIAN_CALLER:
@@ -1685,11 +1684,8 @@ static std::string _str_monam(const monsters& mon, description_level_type desc,
case MONS_DRACONIAN_ANNIHILATOR:
case MONS_DRACONIAN_KNIGHT:
case MONS_DRACONIAN_SCORCHER:
- if (mon.number != 0) // database search
- {
- result += draconian_colour_name(
- static_cast<monster_type>( mon.number ) ) + " ";
- }
+ if (mon.base_monster != MONS_PROGRAM_BUG) // database search
+ result += draconian_colour_name(mon.base_monster) + " ";
break;
default:
@@ -2572,6 +2568,7 @@ void monsters::reset()
flags = 0;
experience = 0L;
type = -1;
+ base_monster = MONS_PROGRAM_BUG;
hit_points = 0;
max_hit_points = 0;
hit_dice = 0;
@@ -2594,6 +2591,7 @@ void monsters::init_with(const monsters &mon)
{
mname = mon.mname;
type = mon.type;
+ base_monster = mon.base_monster;
hit_points = mon.hit_points;
max_hit_points = mon.max_hit_points;
hit_dice = mon.hit_dice;
@@ -4503,6 +4501,12 @@ void monsters::load_spells(mon_spellbook_type book)
#endif
}
+bool monsters::has_hydra_multi_attack() const
+{
+ return (type == MONS_HYDRA ||
+ (mons_is_zombified(this) && base_monster == MONS_HYDRA));
+}
+
bool monsters::has_ench(enchant_type ench) const
{
return (enchantments.find(ench) != enchantments.end());
@@ -5768,9 +5772,9 @@ void monsters::react_to_damage(int damage)
continue;
const int nmons =
- mons_place( jelly, sbehaviour, foe, true, jpos.x, jpos.y,
- you.level_type, PROX_ANYWHERE, MONS_PROGRAM_BUG,
- 0, false );
+ mons_place(
+ mgen_data( jelly, sbehaviour, 0, jpos,
+ foe, true ) );
if (nmons != -1 && nmons != NON_MONSTER)
{
@@ -6245,7 +6249,7 @@ mon_body_shape get_mon_shape(const monsters *mon)
if (mon->type == MONS_PLAYER_GHOST)
return _get_ghost_shape(mon);
else if (mons_is_zombified(mon))
- return get_mon_shape(mon->number);
+ return get_mon_shape(mon->base_monster);
else
return get_mon_shape(mon->type);
}
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index fc1715ba8b..042cf1b12a 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -537,7 +537,7 @@ int mons_speed(int mclass);
* called from: dungeon - mon-util - spells2
* *********************************************************************** */
int mons_zombie_size(int mc);
-int mons_zombie_base(const monsters *monster);
+monster_type mons_zombie_base(const monsters *monster);
bool mons_class_is_zombified(int mc);
bool mons_is_zombified(const monsters *monster);
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index c74d4cdb2a..2bcc8bc2a2 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -44,11 +44,16 @@
#define BIG_BAND 20
-static int band_member(band_type band, int power);
+static void _define_zombie( int mid, monster_type ztype,
+ monster_type cs, int power );
+static monster_type _band_member(band_type band, int power);
static band_type choose_band(int mon_type, int power, int &band_size );
-static int place_monster_aux(int mon_type, beh_type behaviour, int target,
- int px, int py, int power, int extra,
- bool first_band_member, int dur = 0);
+// static int _place_monster_aux(int mon_type, beh_type behaviour, int target,
+// int px, int py, int power, int extra,
+// bool first_band_member, int dur = 0);
+
+static int _place_monster_aux(const mgen_data &mg,
+ bool first_band_member);
// Returns whether actual_grid is compatible with grid_wanted for monster
// movement (or for monster generation, if generation is true).
@@ -181,10 +186,10 @@ static void hell_spawn_random_monsters()
if (one_chance_in(genodds))
{
- proximity_type prox =
+ mgen_data mg(WANDERING_MONSTER);
+ mg.proximity =
(one_chance_in(10) ? PROX_NEAR_STAIRS : PROX_AWAY_FROM_PLAYER);
- mons_place( WANDERING_MONSTER, BEH_HOSTILE, MHITNOT, false,
- 50, 50, LEVEL_DUNGEON, prox );
+ mons_place(mg);
viewwindow(true, false);
}
}
@@ -209,16 +214,16 @@ void spawn_random_monsters()
if (you.char_direction == GDT_ASCENDING)
prox = (one_chance_in(6) ? PROX_CLOSE_TO_PLAYER : PROX_ANYWHERE);
- mons_place( WANDERING_MONSTER, BEH_HOSTILE, MHITNOT, false,
- 50, 50, LEVEL_DUNGEON, prox );
+ mgen_data mg(WANDERING_MONSTER);
+ mg.proximity = prox;
+ mons_place( mg );
viewwindow(true, false);
}
// place Abyss monsters.
if (you.level_type == LEVEL_ABYSS && one_chance_in(5))
{
- mons_place( WANDERING_MONSTER, BEH_HOSTILE, MHITNOT, false,
- 50, 50, LEVEL_ABYSS, PROX_ANYWHERE );
+ mons_place(mgen_data(WANDERING_MONSTER));
viewwindow(true, false);
}
@@ -356,28 +361,37 @@ bool drac_colour_incompatible(int drac, int colour)
return (drac == MONS_DRACONIAN_SCORCHER && colour == MONS_WHITE_DRACONIAN);
}
-static int resolve_monster_type(int mon_type, proximity_type proximity,
- int num, int px, int py, unsigned mmask,
- dungeon_char_type *stair_type,
- int *lev_mons)
+static monster_type resolve_monster_type(monster_type mon_type,
+ proximity_type proximity,
+ monster_type base_type,
+ coord_def &pos,
+ unsigned mmask,
+ dungeon_char_type *stair_type,
+ int *lev_mons)
{
if (mon_type == RANDOM_DRACONIAN)
{
// Pick any random drac, constrained by colour if requested.
do
mon_type =
- random_range(MONS_BLACK_DRACONIAN, MONS_DRACONIAN_SCORCHER);
- while (num != MONS_PROGRAM_BUG
- && mon_type != num
+ static_cast<monster_type>(
+ random_range(MONS_BLACK_DRACONIAN,
+ MONS_DRACONIAN_SCORCHER));
+ while (base_type != MONS_PROGRAM_BUG
+ && mon_type != base_type
&& (mons_species(mon_type) == mon_type
- || drac_colour_incompatible(mon_type, num)));
+ || drac_colour_incompatible(mon_type, base_type)));
}
else if (mon_type == RANDOM_BASE_DRACONIAN)
- mon_type = random_range(MONS_BLACK_DRACONIAN, MONS_PALE_DRACONIAN);
+ mon_type =
+ static_cast<monster_type>(
+ random_range(MONS_BLACK_DRACONIAN, MONS_PALE_DRACONIAN));
else if (mon_type == RANDOM_NONBASE_DRACONIAN)
- mon_type = random_range(MONS_DRACONIAN_CALLER, MONS_DRACONIAN_SCORCHER);
+ mon_type =
+ static_cast<monster_type>(
+ random_range(MONS_DRACONIAN_CALLER, MONS_DRACONIAN_SCORCHER));
- // (2) take care of random monsters
+ // (2) take care of non-drac random monsters
if (mon_type == RANDOM_MONSTER)
{
level_id place = level_id::current();
@@ -388,21 +402,17 @@ static int resolve_monster_type(int mon_type, proximity_type proximity,
int pval = 0;
while (++tries <= 320)
{
- px = 5 + random2(GXM - 10);
- py = 5 + random2(GYM - 10);
+ pos = random_in_bounds();
- if (mgrd[px][py] != NON_MONSTER
- || (px == you.x_pos && py == you.y_pos))
- {
+ if (mgrd(pos) != NON_MONSTER || pos == you.pos())
continue;
- }
// Is the grid verboten?
- if (!unforbidden( coord_def(px, py), mmask ))
+ if (!unforbidden( pos, mmask ))
continue;
// don't generate monsters on top of teleport traps
- int trap = trap_at_xy(px, py);
+ int trap = trap_at_xy(pos.x, pos.y);
if (trap >= 0)
{
if (!can_place_on_trap(mon_type, env.trap[trap].type))
@@ -411,7 +421,7 @@ static int resolve_monster_type(int mon_type, proximity_type proximity,
// check whether there's a stair
// and whether it leads to another branch
- pval = near_stairs(coord_def(px, py), 1,
+ pval = near_stairs(pos, 1,
*stair_type, place.branch);
// no monsters spawned in the Temple
@@ -455,57 +465,49 @@ static int resolve_monster_type(int mon_type, proximity_type proximity,
return (mon_type);
}
-bool place_monster(int &id, int mon_type, int power, beh_type behaviour,
- int target, bool summoned, int px, int py, bool allow_bands,
- proximity_type proximity, int extra, int dur,
- unsigned mmask)
+int place_monster(mgen_data mg)
{
int band_size = 0;
- int band_monsters[BIG_BAND]; // band monster types
- int lev_mons = power; // final 'power'
- int i;
+ monster_type band_monsters[BIG_BAND]; // band monster types
int tries = 0;
int pval = 0;
dungeon_char_type stair_type = NUM_DCHAR_TYPES;
-
- // set initial id to -1 (unsuccessful create)
- id = -1;
+ int id = -1;
// (1) early out (summoned to occupied grid)
- if (summoned && mgrd[px][py] != NON_MONSTER)
+ if (mg.use_position() && mgrd(mg.pos) != NON_MONSTER)
return (false);
- mon_type =
- resolve_monster_type(mon_type, proximity, extra,
- px, py, mmask, &stair_type,
- &lev_mons);
+ mg.cls =
+ resolve_monster_type(mg.cls, mg.proximity, mg.base_type,
+ mg.pos, mg.map_mask,
+ &stair_type, &mg.power);
- if (mon_type == MONS_PROGRAM_BUG || mon_type == -1)
+ if (mg.cls == MONS_PROGRAM_BUG)
return (false);
// (3) decide on banding (good lord!)
band_size = 1;
- band_monsters[0] = mon_type;
+ band_monsters[0] = mg.cls;
- if (allow_bands)
+ if (mg.permit_bands())
{
- const band_type band = choose_band(mon_type, power, band_size);
+ const band_type band = choose_band(mg.cls, mg.power, band_size);
band_size ++;
-
- for (i = 1; i < band_size; i++)
- band_monsters[i] = band_member( band, power );
+ for (int i = 1; i < band_size; i++)
+ band_monsters[i] = _band_member( band, mg.power );
}
- if (proximity == PROX_NEAR_STAIRS)
+ if (mg.proximity == PROX_NEAR_STAIRS)
{
// for some cases disallow monsters on stairs
- if (mons_class_is_stationary( mon_type )
- || pval == 2
- && (mons_speed(mon_type) == 0 || grd[px][py] == DNGN_LAVA
- || grd[px][py] == DNGN_DEEP_WATER))
+ if (mons_class_is_stationary( mg.cls )
+ || (pval == 2
+ && (mons_speed(mg.cls) == 0 || grd(mg.pos) == DNGN_LAVA
+ || grd(mg.pos) == DNGN_DEEP_WATER)))
{
- proximity = PROX_AWAY_FROM_PLAYER;
+ mg.proximity = PROX_AWAY_FROM_PLAYER;
}
}
@@ -516,7 +518,7 @@ bool place_monster(int &id, int mon_type, int power, beh_type behaviour,
// player shoved out of the way?
bool shoved = false;
- if (!summoned)
+ if (!mg.use_position())
{
tries = 0;
@@ -525,104 +527,90 @@ bool place_monster(int &id, int mon_type, int power, beh_type behaviour,
// b) compatible
// c) in the 'correct' proximity to the player
dungeon_feature_type grid_wanted =
- habitat2grid( mons_habitat_by_type(mon_type) );
+ habitat2grid( mons_habitat_by_type(mg.cls) );
while (true)
{
- // handled above, won't change anymore
- if (proximity == PROX_NEAR_STAIRS && tries)
- {
- proximity = PROX_AWAY_FROM_PLAYER;
- tries = 0;
- }
// Dropped number of tries from 60.
- else if (tries >= 45)
+ if (tries++ >= 45)
return (false);
- tries ++;
-
// placement already decided for PROX_NEAR_STAIRS
- if (proximity != PROX_NEAR_STAIRS)
- {
- px = 5 + random2(GXM - 10);
- py = 5 + random2(GYM - 10);
- }
+ if (mg.proximity != PROX_NEAR_STAIRS)
+ mg.pos = random_in_bounds();
// Let's recheck these even for PROX_NEAR_STAIRS, just in case
-
// occupied?
- if (mgrd[px][py] != NON_MONSTER
- || px == you.x_pos && py == you.y_pos)
- {
+ if (mgrd(mg.pos) != NON_MONSTER || mg.pos == you.pos())
continue;
- }
// Is the monster happy where we want to put it?
- if (!grid_compatible(grid_wanted, grd[px][py], true))
+ if (!grid_compatible(grid_wanted, grd(mg.pos), true))
continue;
// Is the grid verboten?
- if (!unforbidden( coord_def(px, py), mmask ))
+ if (!unforbidden( mg.pos, mg.map_mask ))
continue;
// don't generate monsters on top of teleport traps
// (how did they get there?)
- int trap = trap_at_xy(px, py);
+ int trap = trap_at_xy(mg.pos.x, mg.pos.y);
if (trap >= 0)
{
- if (!can_place_on_trap(mon_type, env.trap[trap].type))
+ if (!can_place_on_trap(mg.cls, env.trap[trap].type))
continue;
}
// check proximity to player
proxOK = true;
- switch (proximity)
+ switch (mg.proximity)
{
- case PROX_ANYWHERE:
- if (grid_distance( you.x_pos, you.y_pos, px, py ) < 2 + random2(3))
- {
- proxOK = false;
- }
- break;
+ case PROX_ANYWHERE:
+ if (grid_distance( you.x_pos, you.y_pos,
+ mg.pos.x, mg.pos.y ) < 2 + random2(3))
+ {
+ proxOK = false;
+ }
+ break;
- case PROX_CLOSE_TO_PLAYER:
- case PROX_AWAY_FROM_PLAYER:
- close_to_player = (distance(you.x_pos, you.y_pos, px, py) < 64);
+ case PROX_CLOSE_TO_PLAYER:
+ case PROX_AWAY_FROM_PLAYER:
+ close_to_player =
+ (distance(you.x_pos, you.y_pos,
+ mg.pos.x, mg.pos.y) < 64);
+
+ if (mg.proximity == PROX_CLOSE_TO_PLAYER && !close_to_player
+ || mg.proximity == PROX_AWAY_FROM_PLAYER && close_to_player)
+ {
+ proxOK = false;
+ }
+ break;
- if (proximity == PROX_CLOSE_TO_PLAYER && !close_to_player
- || proximity == PROX_AWAY_FROM_PLAYER && close_to_player)
+ case PROX_NEAR_STAIRS:
+ if (pval == 2) // player on stairs
+ {
+ // 0 speed monsters can't shove player out of their way.
+ if (mons_speed(mg.cls) == 0)
{
proxOK = false;
+ break;
}
- break;
-
- case PROX_NEAR_STAIRS:
- if (pval == 2) // player on stairs
+ // swap the monster and the player spots, unless the
+ // monster was generated in lava or deep water.
+ if (grd(mg.pos) == DNGN_LAVA ||
+ grd(mg.pos) == DNGN_DEEP_WATER)
{
- // 0 speed monsters can't shove player out of their way.
- if (mons_speed(mon_type) == 0)
- {
- proxOK = false;
- break;
- }
- // swap the monster and the player spots, unless the
- // monster was generated in lava or deep water.
- if (grd[px][py] == DNGN_LAVA || grd[px][py] == DNGN_DEEP_WATER)
- {
- proxOK = false;
- break;
- }
- shoved = true;
- int tpx = px;
- int tpy = py;
- px = you.x_pos;
- py = you.y_pos;
- you.moveto(tpx, tpy);
+ proxOK = false;
+ break;
}
-
- proxOK = (pval > 0);
- break;
+ shoved = true;
+ coord_def mpos = mg.pos;
+ mg.pos = you.pos();
+ you.moveto(mpos);
+ }
+ proxOK = (pval > 0);
+ break;
}
if (!proxOK)
@@ -633,16 +621,14 @@ bool place_monster(int &id, int mon_type, int power, beh_type behaviour,
} // end while.. place first monster
}
- id = place_monster_aux( mon_type, behaviour, target, px, py, lev_mons,
- extra, true);
+ id = _place_monster_aux(mg, true);
- // now, forget about banding if the first placement failed, or there's too
- // many monsters already, or we successfully placed by stairs
- if (id < 0 || id+30 > MAX_MONSTERS)
- return false;
+ // Bail out now if we failed.
+ if (id == -1)
+ return (id);
// message to player from stairwell/gate appearance?
- if (see_grid(px, py) && proximity == PROX_NEAR_STAIRS)
+ if (see_grid(mg.pos) && mg.proximity == PROX_NEAR_STAIRS)
{
std::string msg;
@@ -672,41 +658,43 @@ bool place_monster(int &id, int mon_type, int power, beh_type behaviour,
}
// special case: must update the view for monsters created in player LOS
- viewwindow(1, false);
+ viewwindow(true, false);
}
- // monsters placed by stairs don't bring the whole band up/down/through
- // with them
- if (proximity == PROX_NEAR_STAIRS)
- return (true);
+ // now, forget about banding if the first placement failed, or there's too
+ // many monsters already, or we successfully placed by stairs
+ if (id >= MAX_MONSTERS - 30 || mg.proximity == PROX_NEAR_STAIRS)
+ return (id);
// Not PROX_NEAR_STAIRS, so will it will be part of a band, if there
// is any.
if (band_size > 1)
menv[id].flags |= MF_BAND_MEMBER;
+ mgen_data band_template = mg;
// (5) for each band monster, loop call to place_monster_aux().
- for (i = 1; i < band_size; i++)
+ for (int i = 1; i < band_size; i++)
{
+ if (band_monsters[i] == MONS_PROGRAM_BUG)
+ break;
+
+ band_template.cls = band_monsters[i];
const int band_id =
- place_monster_aux( band_monsters[i], behaviour, target, px, py,
- lev_mons, extra, false, dur);
-
+ _place_monster_aux( band_template, false );
if (band_id != -1 && band_id != NON_MONSTER)
menv[band_id].flags |= MF_BAND_MEMBER;
}
// placement of first monster, at least, was a success.
- return (true);
+ return (id);
}
-static int place_monster_aux( int mon_type, beh_type behaviour, int target,
- int px, int py, int power, int extra,
- bool first_band_member, int dur )
+static int _place_monster_aux( const mgen_data &mg,
+ bool first_band_member )
{
- int id, i;
+ int id = -1;
dungeon_feature_type grid_wanted = DNGN_UNSEEN;
- int fx = 0, fy = 0; // final x,y
+ coord_def fpos;
// gotta be able to pick an ID
for (id = 0; id < MAX_MONSTERS; id++)
@@ -714,42 +702,39 @@ static int place_monster_aux( int mon_type, beh_type behaviour, int target,
break;
if (id == MAX_MONSTERS)
- return -1;
+ return (-1);
menv[id].reset();
// setup habitat and placement
// If the space is occupied, try some neighbouring square instead.
- if (first_band_member && mgrd[px][py] == NON_MONSTER
- && (px != you.x_pos || py != you.y_pos))
+ if (first_band_member && mgrd(mg.pos) == NON_MONSTER
+ && mg.pos != you.pos())
{
- fx = px;
- fy = py;
+ fpos = mg.pos;
}
else
{
- grid_wanted = habitat2grid( mons_habitat_by_type(mon_type) );
+ grid_wanted = habitat2grid( mons_habitat_by_type(mg.cls) );
+ int i = 0;
// we'll try 1000 times for a good spot
- for (i = 0; i < 1000; i++)
+ for ( ; i < 1000; i++)
{
- fx = px + random2(7) - 3;
- fy = py + random2(7) - 3;
+ fpos = mg.pos + coord_def( random_range(-3, 3),
+ random_range(-3, 3) );
// occupied?
- if (mgrd[fx][fy] != NON_MONSTER
- || fx == you.x_pos && fy == you.y_pos)
- {
+ if (mgrd(fpos) != NON_MONSTER || fpos == you.pos())
continue;
- }
- if (!grid_compatible(grid_wanted, grd[fx][fy], true))
+ if (!grid_compatible(grid_wanted, grd(fpos), true))
continue;
// don't generate monsters on top of teleport traps
// (how do they get there?)
- int trap = trap_at_xy(fx, fy);
- if (trap >= 0 && !can_place_on_trap(mon_type, env.trap[trap].type))
+ int trap = trap_at_xy(fpos.x, fpos.y);
+ if (trap >= 0 && !can_place_on_trap(mg.cls, env.trap[trap].type))
continue;
// cool.. passes all tests
@@ -762,47 +747,48 @@ static int place_monster_aux( int mon_type, beh_type behaviour, int target,
}
// now, actually create the monster (wheeee!)
- menv[id].type = mon_type;
+ menv[id].type = mg.cls;
+ menv[id].base_monster = mg.base_type;
- menv[id].number = extra;
+ menv[id].number = mg.number;
- menv[id].x = fx;
- menv[id].y = fy;
+ menv[id].x = fpos.x;
+ menv[id].y = fpos.y;
// link monster into monster grid
- mgrd[fx][fy] = id;
+ mgrd(fpos) = id;
// generate a brand shiny new monster, or zombie
- if (mons_class_is_zombified(mon_type))
- define_zombie( id, extra, mon_type, power );
+ if (mons_class_is_zombified(mg.cls))
+ _define_zombie( id, mg.base_type, mg.cls, mg.power );
else
define_monster(id);
// The return of Boris is now handled in monster_die()...
// not setting this for Boris here allows for multiple Borises
// in the dungeon at the same time. -- bwr
- if (mons_is_unique(mon_type))
- you.unique_creatures[mon_type] = true;
+ if (mons_is_unique(mg.cls))
+ you.unique_creatures[mg.cls] = true;
- if (mons_class_flag(mon_type, M_INVIS))
+ if (mons_class_flag(mg.cls, M_INVIS))
menv[id].add_ench(ENCH_INVIS);
- if (mons_class_flag(mon_type, M_CONFUSED))
+ if (mons_class_flag(mg.cls, M_CONFUSED))
menv[id].add_ench(ENCH_CONFUSION);
- if (mon_type == MONS_SHAPESHIFTER)
+ if (mg.cls == MONS_SHAPESHIFTER)
menv[id].add_ench(ENCH_SHAPESHIFTER);
- if (mon_type == MONS_GLOWING_SHAPESHIFTER)
+ if (mg.cls == MONS_GLOWING_SHAPESHIFTER)
menv[id].add_ench(ENCH_GLOWING_SHAPESHIFTER);
- if (mon_type == MONS_GIANT_BAT || mon_type == MONS_UNSEEN_HORROR
- || mon_type == MONS_GIANT_BLOWFLY)
+ if (mg.cls == MONS_GIANT_BAT || mg.cls == MONS_UNSEEN_HORROR
+ || mg.cls == MONS_GIANT_BLOWFLY)
{
menv[id].flags |= MF_BATTY;
}
- if (monster_can_submerge(&menv[id], grd[fx][fy])
+ if (monster_can_submerge(&menv[id], grd(fpos))
&& !one_chance_in(5))
{
menv[id].add_ench(ENCH_SUBMERGED);
@@ -810,34 +796,33 @@ static int place_monster_aux( int mon_type, beh_type behaviour, int target,
menv[id].flags |= MF_JUST_SUMMONED;
- if (mon_type == MONS_DANCING_WEAPON && extra != 1) // ie not from spell
+ if (mg.cls == MONS_DANCING_WEAPON && mg.number != 1) // ie not from spell
{
- give_item( id, power );
+ give_item( id, mg.power );
if (menv[id].inv[MSLOT_WEAPON] != NON_ITEM)
menv[id].colour = mitm[ menv[id].inv[MSLOT_WEAPON] ].colour;
}
- else if (mons_itemuse(mon_type) >= MONUSE_STARTING_EQUIPMENT)
+ else if (mons_itemuse(mg.cls) >= MONUSE_STARTING_EQUIPMENT)
{
- give_item( id, power );
+ give_item( id, mg.power );
// Give these monsters a second weapon -- bwr
- if (mons_wields_two_weapons(static_cast<monster_type>(mon_type)))
- give_item( id, power );
+ if (mons_wields_two_weapons(mg.cls))
+ give_item( id, mg.power );
unwind_var<int> save_speedinc(menv[id].speed_increment);
menv[id].wield_melee_weapon(false);
}
// give manticores 8 to 16 spike volleys.
- // they're not spellcasters so this doesn't screw anything up.
- if (mon_type == MONS_MANTICORE)
+ if (mg.cls == MONS_MANTICORE)
menv[id].number = 8 + random2(9);
// set attitude, behaviour and target
menv[id].attitude = ATT_HOSTILE;
- menv[id].behaviour = behaviour;
+ menv[id].behaviour = mg.behaviour;
- if (mons_is_statue(mon_type))
+ if (mons_is_statue(mg.cls))
menv[id].behaviour = BEH_WANDER;
menv[id].foe_memory = 0;
@@ -846,22 +831,22 @@ static int place_monster_aux( int mon_type, beh_type behaviour, int target,
// monster wander.. if you want sleeping
// hostiles, use BEH_SLEEP since the default
// attitude is hostile.
- if (behaviour > NUM_BEHAVIOURS)
+ if (mg.behaviour > NUM_BEHAVIOURS)
{
- if (behaviour == BEH_FRIENDLY || behaviour == BEH_GOD_GIFT)
+ if (mg.behaviour == BEH_FRIENDLY || mg.behaviour == BEH_GOD_GIFT)
menv[id].attitude = ATT_FRIENDLY;
- if (behaviour == BEH_NEUTRAL)
+ if (mg.behaviour == BEH_NEUTRAL)
menv[id].attitude = ATT_NEUTRAL;
menv[id].behaviour = BEH_WANDER;
}
// dur should always be 1-6 for monsters that can be abjured.
- if (dur >= 1 && dur <= 6)
- menv[id].mark_summoned( dur, true );
+ if (mg.abjuration_duration >= 1 && mg.abjuration_duration <= 6)
+ menv[id].mark_summoned( mg.abjuration_duration, true );
- menv[id].foe = target;
+ menv[id].foe = mg.foe;
// Initialise pandemonium demons
if (menv[id].type == MONS_PANDEMONIUM_DEMON)
@@ -872,14 +857,224 @@ static int place_monster_aux( int mon_type, beh_type behaviour, int target,
menv[id].pandemon_init();
}
- mark_interesting_monst(&menv[id], behaviour);
+ mark_interesting_monst(&menv[id], mg.behaviour);
if (player_monster_visible(&menv[id]) && mons_near(&menv[id]))
seen_monster(&menv[id]);
return (id);
-} // end place_monster_aux()
+}
+
+static monster_type _pick_random_zombie()
+{
+ static std::vector<monster_type> zombifiable;
+ if (zombifiable.empty())
+ {
+ for (int i = 0; i < NUM_MONSTERS; ++i)
+ {
+ if (mons_species(i) != i || i == MONS_PROGRAM_BUG)
+ continue;
+
+ const monster_type mcls = static_cast<monster_type>(i);
+ if (!mons_zombie_size(mcls))
+ continue;
+
+ zombifiable.push_back(mcls);
+ }
+ }
+ return (zombifiable[ random2(zombifiable.size()) ]);
+}
+
+static void _define_zombie( int mid, monster_type ztype,
+ monster_type cs, int power )
+{
+ monster_type mons_sec2 = MONS_PROGRAM_BUG;
+ int zombie_size = 0;
+ bool ignore_rarity = false;
+ monster_type cls = MONS_PROGRAM_BUG;
+
+ if (power > 27)
+ power = 27;
+
+ // set size based on zombie class (cs)
+ switch (cs)
+ {
+ case MONS_ZOMBIE_SMALL:
+ case MONS_SIMULACRUM_SMALL:
+ case MONS_SKELETON_SMALL:
+ zombie_size = Z_SMALL;
+ break;
+
+ case MONS_ZOMBIE_LARGE:
+ case MONS_SIMULACRUM_LARGE:
+ case MONS_SKELETON_LARGE:
+ zombie_size = Z_BIG;
+ break;
+
+ case MONS_SPECTRAL_THING:
+ zombie_size = -1;
+ break;
+
+ default:
+ // this should NEVER happen.
+ perror("\ncreate_zombie() got passed incorrect zombie type!\n");
+ end(0);
+ break;
+ }
+
+ // that is, random creature from which to fashion undead
+ if (ztype == MONS_PROGRAM_BUG)
+ {
+ // how OOD this zombie can be.
+ int relax = 5;
+
+ // pick an appropriate creature to make a zombie out of,
+ // levelwise. The old code was generating absolutely
+ // incredible OOD zombies.
+ while (true)
+ {
+ cls = _pick_random_zombie();
+
+ // on certain branches, zombie creation will fail if we use
+ // the mons_rarity() functions, because (for example) there
+ // are NO zombifiable "native" abyss creatures. Other branches
+ // where this is a problem are hell levels and the crypt.
+ // we have to watch for summoned zombies on other levels, too,
+ // such as the Temple, HoB, and Slime Pits.
+ if (you.level_type != LEVEL_DUNGEON
+ || player_in_hell()
+ || player_in_branch( BRANCH_HALL_OF_ZOT )
+ || player_in_branch( BRANCH_VESTIBULE_OF_HELL )
+ || player_in_branch( BRANCH_ECUMENICAL_TEMPLE )
+ || player_in_branch( BRANCH_CRYPT )
+ || player_in_branch( BRANCH_TOMB )
+ || player_in_branch( BRANCH_HALL_OF_BLADES )
+ || player_in_branch( BRANCH_SNAKE_PIT )
+ || player_in_branch( BRANCH_SLIME_PITS )
+ || one_chance_in(1000))
+ {
+ ignore_rarity = true;
+ }
+
+ // don't make out-of-rarity zombies when we don't have to
+ if (!ignore_rarity && mons_rarity(cls) == 0)
+ continue;
+
+ // if skeleton, monster must have a skeleton
+ if ((cs == MONS_SKELETON_SMALL || cs == MONS_SKELETON_LARGE)
+ && !mons_skeleton(cls))
+ {
+ continue;
+ }
+
+ // size must match, but you can make a spectral thing out
+ // of anything.
+ if (mons_zombie_size(cls) != zombie_size && zombie_size != -1)
+ continue;
+
+ // hack -- non-dungeon zombies are always made out of nastier
+ // monsters
+ if (you.level_type != LEVEL_DUNGEON && mons_power(cls) > 8)
+ break;
+
+ // check for rarity.. and OOD - identical to mons_place()
+ int level, diff, chance;
+
+ level = mons_level( cls ) - 4;
+ diff = level - power;
+
+ chance = (ignore_rarity) ? 100
+ : mons_rarity(cls) - (diff * diff) / 2;
+
+ if (power > level - relax && power < level + relax
+ && random2avg(100, 2) <= chance)
+ {
+ break;
+ }
+
+ // every so often, we'll relax the OOD restrictions. Avoids
+ // infinite loops (if we don't do this, things like creating
+ // a large skeleton on level 1 may hang the game!)
+ if (one_chance_in(5))
+ relax++;
+ }
+
+ // set type and secondary appropriately
+ menv[mid].base_monster = cls;
+ mons_sec2 = cls;
+ }
+ else
+ {
+ menv[mid].base_monster = mons_species(ztype);
+ mons_sec2 = menv[mid].base_monster;
+ }
+
+ menv[mid].type = menv[mid].base_monster;
+
+ define_monster(mid);
+
+ menv[mid].hit_points = hit_points( menv[mid].hit_dice, 6, 5 );
+ menv[mid].max_hit_points = menv[mid].hit_points;
+
+ menv[mid].ac -= 2;
+
+ if (menv[mid].ac < 0)
+ menv[mid].ac = 0;
+
+ menv[mid].ev -= 5;
+
+ if (menv[mid].ev < 0)
+ menv[mid].ev = 0;
+ menv[mid].speed -= 2;
+
+ if (menv[mid].speed < 3)
+ menv[mid].speed = 3;
+
+ menv[mid].speed_increment = 70;
+
+ if (cs == MONS_ZOMBIE_SMALL || cs == MONS_ZOMBIE_LARGE)
+ {
+ menv[mid].type = ((mons_zombie_size(menv[mid].base_monster) == Z_BIG)
+ ? MONS_ZOMBIE_LARGE : MONS_ZOMBIE_SMALL);
+ }
+ else if (cs == MONS_SKELETON_SMALL || cs == MONS_SKELETON_LARGE)
+ {
+ menv[mid].hit_points = hit_points( menv[mid].hit_dice, 5, 4 );
+ menv[mid].max_hit_points = menv[mid].hit_points;
+
+ menv[mid].ac -= 4;
+
+ if (menv[mid].ac < 0)
+ menv[mid].ac = 0;
+
+ menv[mid].ev -= 2;
+
+ if (menv[mid].ev < 0)
+ menv[mid].ev = 0;
+
+ menv[mid].type = ((mons_zombie_size( menv[mid].base_monster ) == Z_BIG)
+ ? MONS_SKELETON_LARGE : MONS_SKELETON_SMALL);
+ }
+ else if (cs == MONS_SIMULACRUM_SMALL || cs == MONS_SIMULACRUM_LARGE)
+ {
+ // Simulacrum aren't tough, but you can create piles of them. -- bwr
+ menv[mid].hit_points = hit_points( menv[mid].hit_dice, 1, 4 );
+ menv[mid].max_hit_points = menv[mid].hit_points;
+ menv[mid].type = ((mons_zombie_size( menv[mid].base_monster ) == Z_BIG)
+ ? MONS_SIMULACRUM_LARGE : MONS_SIMULACRUM_SMALL);
+ }
+ else if (cs == MONS_SPECTRAL_THING)
+ {
+ menv[mid].hit_points = hit_points( menv[mid].hit_dice, 4, 4 );
+ menv[mid].max_hit_points = menv[mid].hit_points;
+ menv[mid].ac += 4;
+ menv[mid].type = MONS_SPECTRAL_THING;
+ }
+
+ menv[mid].base_monster = mons_sec2;
+ menv[mid].colour = mons_class_colour(cs);
+}
static band_type choose_band( int mon_type, int power, int &band_size )
{
@@ -1177,13 +1372,13 @@ static band_type choose_band( int mon_type, int power, int &band_size )
return (band);
}
-static int band_member(band_type band, int power)
+static monster_type _band_member(band_type band, int power)
{
- int mon_type = -1;
+ monster_type mon_type = MONS_PROGRAM_BUG;
int temp_rand;
if (band == BAND_NO_BAND)
- return -1;
+ return (MONS_PROGRAM_BUG);
switch (band)
{
@@ -1281,14 +1476,16 @@ static int band_member(band_type band, int power)
case BAND_PANDEMONIUM_DEMON:
if (one_chance_in(7))
- mon_type = random_choose_weighted(50, MONS_LICH,
- 10, MONS_ANCIENT_LICH,
- 0);
+ mon_type = static_cast<monster_type>(
+ random_choose_weighted(50, MONS_LICH,
+ 10, MONS_ANCIENT_LICH,
+ 0));
else if (one_chance_in(6))
- mon_type = random_choose_weighted(50, MONS_ABOMINATION_SMALL,
- 40, MONS_ABOMINATION_LARGE,
- 10, MONS_TENTACLED_MONSTROSITY,
- 0);
+ mon_type = static_cast<monster_type>(
+ random_choose_weighted(50, MONS_ABOMINATION_SMALL,
+ 40, MONS_ABOMINATION_LARGE,
+ 10, MONS_TENTACLED_MONSTROSITY,
+ 0));
else
mon_type =
summon_any_demon(
@@ -1493,7 +1690,7 @@ void mark_interesting_monst(struct monsters* monster, beh_type behaviour)
// PUBLIC FUNCTION -- mons_place().
-static int pick_zot_exit_defender()
+static monster_type pick_zot_exit_defender()
{
if (one_chance_in(11))
return (MONS_PANDEMONIUM_DEMON);
@@ -1508,12 +1705,13 @@ static int pick_zot_exit_defender()
(temp_rand > 13) ? MONS_RED_DEVIL // 7.25%
: MONS_PIT_FIEND); // 5.07%
- return (mon_type);
+ return static_cast<monster_type>(mon_type);
}
-int mons_place( int mon_type, beh_type behaviour, int target, bool summoned,
- int px, int py, int level_type, proximity_type proximity,
- int extra, int dur, bool permit_bands )
+int mons_place( mgen_data mg )
+ // int mon_type, beh_type behaviour, int target, bool summoned,
+ // int px, int py, int level_type, proximity_type proximity,
+ // int extra, int dur, bool permit_bands )
{
int mon_count = 0;
for (int il = 0; il < MAX_MONSTERS; il++)
@@ -1522,85 +1720,80 @@ int mons_place( int mon_type, beh_type behaviour, int target, bool summoned,
mon_count++;
}
- if (mon_type == WANDERING_MONSTER)
+ if (mg.cls == WANDERING_MONSTER)
{
- if (mon_count > 150)
+ if (mon_count > MAX_MONSTERS - 50)
return (-1);
- mon_type = RANDOM_MONSTER;
+ mg.cls = RANDOM_MONSTER;
}
// all monsters have been assigned? {dlb}
- if (mon_count > MAX_MONSTERS - 2)
+ if (mon_count >= MAX_MONSTERS - 1)
return (-1);
// this gives a slight challenge to the player as they ascend the
// dungeon with the Orb
- if (you.char_direction == GDT_ASCENDING && mon_type == RANDOM_MONSTER
- && you.level_type == LEVEL_DUNGEON && !summoned)
+ if (you.char_direction == GDT_ASCENDING && mg.cls == RANDOM_MONSTER
+ && you.level_type == LEVEL_DUNGEON && !mg.summoned())
{
- mon_type = pick_zot_exit_defender();
- permit_bands = true;
+ mg.cls = pick_zot_exit_defender();
+ mg.flags |= MG_PERMIT_BANDS;
}
- if (mon_type == RANDOM_MONSTER
- || level_type == LEVEL_PANDEMONIUM)
- {
- permit_bands = true;
- }
+ if (mg.cls == RANDOM_MONSTER || mg.level_type == LEVEL_PANDEMONIUM)
+ mg.flags |= MG_PERMIT_BANDS;
int mid = -1;
// translate level_type
- int power;
-
- switch (level_type)
+ switch (mg.level_type)
{
case LEVEL_PANDEMONIUM:
- power = 52; // sigh..
+ mg.power = 52; // sigh..
break;
case LEVEL_ABYSS:
- power = 51;
+ mg.power = 51;
break;
- case LEVEL_DUNGEON: // intentional fallthrough
+ case LEVEL_DUNGEON:
default:
- power = you.your_level;
+ mg.power = you.your_level;
break;
}
- if (!place_monster( mid, mon_type, power, behaviour, target, summoned,
- px, py, permit_bands, proximity, extra, dur ))
- {
+ mid = place_monster(mg);
+ if (mid == -1)
return (-1);
- }
+
+ monsters *creation = &menv[mid];
- if (mid != -1)
+ // look at special cases: CHARMED, FRIENDLY, HOSTILE, GOD_GIFT
+ // alert summoned being to player's presence
+ if (mg.behaviour > NUM_BEHAVIOURS)
{
- struct monsters *const creation = &menv[mid];
-
- // look at special cases: CHARMED, FRIENDLY, HOSTILE, GOD_GIFT
- // alert summoned being to player's presence
- if (behaviour > NUM_BEHAVIOURS)
- {
- if (behaviour == BEH_FRIENDLY || behaviour == BEH_GOD_GIFT)
- creation->flags |= MF_CREATED_FRIENDLY;
+ if (mg.behaviour == BEH_FRIENDLY || mg.behaviour == BEH_GOD_GIFT)
+ creation->flags |= MF_CREATED_FRIENDLY;
- if (behaviour == BEH_GOD_GIFT)
- creation->flags |= MF_GOD_GIFT;
+ if (mg.behaviour == BEH_GOD_GIFT)
+ creation->flags |= MF_GOD_GIFT;
- if (behaviour == BEH_CHARMED)
- {
- creation->attitude = ATT_HOSTILE;
- creation->add_ench(ENCH_CHARM);
- }
+ if (!(mg.flags & MG_FORCE_BEH) && player_angers_monster(creation))
+ creation->attitude = ATT_HOSTILE;
- // make summoned being aware of player's presence
- behaviour_event(creation, ME_ALERT, MHITYOU);
+ if (mg.behaviour == BEH_CHARMED)
+ {
+ creation->attitude = ATT_HOSTILE;
+ creation->add_ench(ENCH_CHARM);
}
- }
+ // make summoned being aware of player's presence
+ behaviour_event(creation, ME_ALERT, MHITYOU);
+
+ if (creation->type == MONS_RAKSHASA_FAKE && !one_chance_in(3))
+ creation->add_ench(ENCH_INVIS);
+ }
return (mid);
-} // end mons_place()
+}
static dungeon_feature_type _monster_habitat_feature(int mtype)
{
@@ -1680,7 +1873,7 @@ coord_def find_newmons_square_contiguous(monster_type mons_class,
return (in_bounds(p)? p : coord_def(-1, -1));
}
-coord_def find_newmons_square(int mons_class, int x, int y)
+coord_def find_newmons_square(int mons_class, const coord_def &p)
{
FixedVector < char, 2 > empty;
coord_def pos(-1, -1);
@@ -1696,7 +1889,7 @@ coord_def find_newmons_square(int mons_class, int x, int y)
// Might be better if we chose a space and tried to match the monster
// to it in the case of RANDOM_MONSTER, that way if the target square
// is surrounded by water of lava this function would work. -- bwr
- if (empty_surrounds( x, y, spcw, 2, true, empty ))
+ if (empty_surrounds( p.x, p.y, spcw, 2, true, empty ))
{
pos.x = empty[0];
pos.y = empty[1];
@@ -1727,81 +1920,28 @@ bool player_angers_monster(monsters *creation)
return (false);
}
-int create_monster( int cls, int dur, beh_type beha, int cr_x, int cr_y,
- int hitting, int zsec, bool permit_bands,
- bool force_place, bool force_behaviour,
- bool player_made )
+int create_monster( mgen_data mg )
{
int summd = -1;
- coord_def pos;
- if (force_place && mons_class_can_pass(cls, grd[cr_x][cr_y])
- && mgrd[cr_x][cr_y] == NON_MONSTER
- && (cr_x != you.x_pos || cr_y != you.y_pos))
- {
- pos.x = cr_x;
- pos.y = cr_y;
- }
- else
- pos = find_newmons_square(cls, cr_x, cr_y);
+ if (!(mg.force_place()
+ && in_bounds(mg.pos)
+ && mons_class_can_pass(mg.cls, grd(mg.pos))
+ && mgrd(mg.pos) == NON_MONSTER
+ && mg.pos != you.pos()))
+ mg.pos = find_newmons_square(mg.cls, mg.pos);
- if (pos.x != -1 && pos.y != -1)
- {
- summd = mons_place( cls, beha, hitting, true, pos.x, pos.y,
- you.level_type, PROX_ANYWHERE, zsec,
- dur, permit_bands );
- }
+ if (in_bounds(mg.pos))
+ summd = mons_place( mg );
// determine whether creating a monster is successful (summd != -1) {dlb}:
// then handle the outcome {dlb}:
- if (summd == -1)
- {
- if (see_grid( cr_x, cr_y ))
- mpr("You see a puff of smoke.");
- }
- else
- {
- monsters *const creation = &menv[summd];
-
- // dur should always be ENCH_ABJ_xx
- if (dur >= 1 && dur <= 6)
- creation->mark_summoned( dur, true );
-
- // player summons do not give XP or other bonuses
- // (you can still train skills on them though)
- if ( player_made )
- creation->flags |= MF_CREATED_FRIENDLY;
-
- // look at special cases: CHARMED, FRIENDLY, HOSTILE, GOD_GIFT
- // alert summoned being to player's presence
- if (beha > NUM_BEHAVIOURS)
- {
- if (beha == BEH_FRIENDLY || beha == BEH_GOD_GIFT)
- creation->flags |= MF_CREATED_FRIENDLY;
-
- if (beha == BEH_GOD_GIFT)
- creation->flags |= MF_GOD_GIFT;
-
- if (!force_behaviour && player_angers_monster(creation))
- beha = BEH_HOSTILE;
-
- if (beha == BEH_CHARMED)
- {
- creation->attitude = ATT_HOSTILE;
- creation->add_ench(ENCH_CHARM);
- }
-
- // make summoned being aware of player's presence
- behaviour_event(creation, ME_ALERT, MHITYOU);
- }
-
- if (creation->type == MONS_RAKSHASA_FAKE && !one_chance_in(3))
- creation->add_ench(ENCH_INVIS);
- }
+ if (summd == -1 && see_grid( mg.pos ))
+ mpr("You see a puff of smoke.");
// the return value is either -1 (failure of some sort)
// or the index of the monster placed (if I read things right) {dlb}
return (summd);
-} // end create_monster()
+}
bool empty_surrounds(int emx, int emy, dungeon_feature_type spc_wanted,
diff --git a/crawl-ref/source/monplace.h b/crawl-ref/source/monplace.h
index daf972dfa9..13e1320922 100644
--- a/crawl-ref/source/monplace.h
+++ b/crawl-ref/source/monplace.h
@@ -92,6 +92,127 @@ enum proximity_type // proximity to player to create monster
PROX_NEAR_STAIRS
};
+enum mgen_flag_type
+{
+ MG_PERMIT_BANDS = 0x1,
+ MG_FORCE_PLACE = 0x2,
+ MG_FORCE_BEH = 0x4,
+ MG_PLAYER_MADE = 0x8
+};
+
+// A structure with all the data needed to whip up a new monster.
+struct mgen_data
+{
+ // Monster type.
+ monster_type cls;
+
+ // If the monster is zombie-like, or a specialised draconian, this
+ // is the base monster that the monster is based on - should be
+ // set to MONS_PROGRAM_BUG when not used.
+ monster_type base_type;
+
+ // Determines the behaviour of the monster after it is generated. This
+ // behaviour is an unholy combination of monster attitude
+ // (friendly, hostile) and monster initial state (asleep, wandering).
+ // XXX: Could use splitting up these aspects.
+ beh_type behaviour;
+
+ // For summoned monsters, this is a measure of how long the summon will
+ // hang around, on a scale of 1-6, 6 being longest. Use 0 for monsters
+ // that aren't summoned.
+ int abjuration_duration;
+
+ // Where the monster will be created.
+ coord_def pos;
+
+ // The monster's foe, i.e. which monster it will want to attack. foe
+ // may be an index into the monster array (0 - (MAX_MONSTERS-1)), or
+ // it may be MHITYOU to indicate that the monster wants to attack the
+ // player, or MHITNOT, to indicate that the monster has no foe and is
+ // just wandering around.
+ int foe;
+
+ // Generation flags from mgen_flag_type.
+ unsigned flags;
+
+ // The number of hydra heads or manticore attack volleys. Note:
+ // in older version this field was used for both this and for base_type.
+ int number;
+
+ // The colour of the monster
+ int colour;
+
+ // A measure of how powerful the generated monster should be (for
+ // randomly chosen monsters), usually equal to the absolute depth
+ // that the player is in the dungeon.
+ int power;
+
+ // How close to or far from the player the monster should be created.
+ // Is usually used only when the initial position (pos) is unspecified.
+ proximity_type proximity;
+
+ // What place we're in, or pretending to be in, usually the place
+ // the player is actually in.
+ level_area_type level_type;
+
+ // Some predefined vaults (aka maps) include flags to suppress random
+ // generation of monsters. When generating monsters, this is a mask of
+ // map flags to honour (such as MMT_NO_MONS to specify that we shouldn't
+ // randomly generate a monster inside a map that doesn't want it). These
+ // map flags are usually respected only when a dungeon level is being
+ // constructed, since at future points vault information may no longer
+ // be available (vault metadata is not preserved across game saves).
+ unsigned map_mask;
+
+ mgen_data(monster_type mt = RANDOM_MONSTER,
+ beh_type beh = BEH_HOSTILE,
+ int abj = 0,
+ const coord_def &p = coord_def(-1, -1),
+ int mfoe = MHITNOT,
+ unsigned monflags = 0,
+ monster_type base = MONS_PROGRAM_BUG,
+ int monnumber = 0,
+ int moncolour = BLACK,
+ int monpower = you.your_level,
+ proximity_type prox = PROX_ANYWHERE,
+ level_area_type ltype = you.level_type)
+
+ : cls(mt), base_type(base), behaviour(beh),
+ abjuration_duration(abj), pos(p), foe(mfoe), flags(monflags),
+ number(monnumber), colour(moncolour), power(monpower),
+ proximity(prox), level_type(ltype), map_mask(0)
+ {
+ }
+
+ bool permit_bands() const { return (flags & MG_PERMIT_BANDS); }
+ bool force_place() const { return (flags & MG_FORCE_PLACE); }
+
+ // Is there a valid position set on this struct that we want to use
+ // when placing the monster?
+ bool use_position() const { return in_bounds(pos); }
+
+ bool summoned() const { return (abjuration_duration > 0); }
+
+ static mgen_data sleeper_at(monster_type what,
+ const coord_def &where)
+ {
+ return mgen_data(what, BEH_SLEEP, 0, where);
+ }
+
+ static mgen_data hostile_at(monster_type what,
+ const coord_def &where)
+ {
+ return mgen_data(what, BEH_HOSTILE, 0, where);
+ }
+
+ static mgen_data alert_hostile_at(monster_type what,
+ const coord_def &where,
+ int abj_deg = 0)
+ {
+ return mgen_data(what, BEH_HOSTILE, abj_deg, where, MHITYOU);
+ }
+};
+
// last updated 13mar2001 {gdl}
/* ***********************************************************************
* called from: acr - lev-pand - monplace - dungeon
@@ -111,11 +232,16 @@ enum proximity_type // proximity to player to create monster
* 2 = don't place the monster near the player
* 3 = place the monster near stairs (regardless of player pos)
* *********************************************************************** */
-int mons_place( int mon_type, beh_type behaviour, int target, bool summoned,
- int px, int py, int level_type = LEVEL_DUNGEON,
- proximity_type proximity = PROX_ANYWHERE,
- int extra = MONS_PROGRAM_BUG,
- int dur = 0, bool permit_bands = false );
+
+int mons_place( mgen_data mg );
+
+/* int mons_place( int mon_type, beh_type behaviour, int target, bool summoned, */
+/* int px, int py, int level_type = LEVEL_DUNGEON, */
+/* proximity_type proximity = PROX_ANYWHERE, */
+/* int extra = MONS_PROGRAM_BUG, */
+/* int dur = 0, bool permit_bands = false ); */
+
+int create_monster( mgen_data mg );
// last updated 12may2000 {dlb}
/* ***********************************************************************
@@ -123,10 +249,10 @@ int mons_place( int mon_type, beh_type behaviour, int target, bool summoned,
* items - monstuff - mstuff2 - religion - spell - spells -
* spells2 - spells3 - spells4
* *********************************************************************** */
-int create_monster( int cls, int dur, beh_type beha, int cr_x, int cr_y,
- int hitting, int zsec, bool permit_bands = false,
- bool force_place = false, bool force_behaviour = false,
- bool player_made = false );
+/* int create_monster( int cls, int dur, beh_type beha, int cr_x, int cr_y, */
+/* int hitting, int zsec, bool permit_bands = false, */
+/* bool force_place = false, bool force_behaviour = false, */
+/* bool player_made = false ); */
class level_id;
monster_type pick_random_monster(const level_id &place,
@@ -160,11 +286,13 @@ monster_type summon_any_demon( demon_class_type demon_class );
* mons_place(). If you need to put a monster somewhere, use mons_place().
* Summoned creatures can be created with create_monster().
* *********************************************************************** */
-bool place_monster( int &id, int mon_type, int power, beh_type behaviour,
- int target, bool summoned, int px, int py, bool allow_bands,
- proximity_type proximity = PROX_ANYWHERE,
- int extra = MONS_PROGRAM_BUG, int dur = 0,
- unsigned mmask = 0 );
+int place_monster( mgen_data mg );
+
+ // int &id, int mon_type, int power, beh_type behaviour,
+ // int target, bool summoned, int px, int py, bool allow_bands,
+ // proximity_type proximity = PROX_ANYWHERE,
+ // int extra = MONS_PROGRAM_BUG, int dur = 0,
+ // unsigned mmask = 0 );
monster_type rand_dragon( dragon_class_type type );
bool drac_colour_incompatible(int drac, int colour);
@@ -185,7 +313,7 @@ bool monster_habitable_grid(int monster_class,
int flies = -1,
bool paralysed = false);
bool monster_can_submerge(const monsters *mons, dungeon_feature_type grid);
-coord_def find_newmons_square(int mons_class, int x, int y);
+coord_def find_newmons_square(int mons_class, const coord_def &p);
coord_def find_newmons_square_contiguous(monster_type mons_class,
const coord_def &start,
int maxdistance = 3);
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 0d3f6d01bb..ec4f265c00 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -1003,9 +1003,10 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
&& mons_holiness(monster) == MH_NATURAL
&& mons_weight(mons_species(monster->type)))
{
- if (create_monster( MONS_SPECTRAL_THING, 0, BEH_FRIENDLY,
- monster->x, monster->y, you.pet_target,
- mons_species(monster->type)) != -1)
+ if (create_monster(
+ mgen_data( MONS_SPECTRAL_THING, BEH_FRIENDLY,
+ 0, monster->pos(), you.pet_target,
+ 0, mons_species(monster->type) )) != -1)
{
if (death_message)
mpr("A glowing mist starts to gather...");
@@ -1441,7 +1442,7 @@ static bool _valid_morph( monsters *monster, int new_mclass )
|| new_mclass == MONS_SHAPESHIFTER
|| new_mclass == MONS_GLOWING_SHAPESHIFTER
- // These require manual setting of mons.number to indicate
+ // These require manual setting of mons.base_monster to indicate
// what they are a skeleton/zombie/simulacrum/spectral thing of,
// which we currently aren't smart enough to handle.
|| mons_class_is_zombified(new_mclass)
@@ -1582,8 +1583,9 @@ bool monster_polymorph( monsters *monster, monster_type targetc,
const char old_ench_countdown = monster->ench_countdown;
// deal with mons_sec
- monster->type = targetc;
- monster->number = MONS_PROGRAM_BUG;
+ monster->type = targetc;
+ monster->base_monster = MONS_PROGRAM_BUG;
+ monster->number = 0;
mon_enchant abj = monster->get_ench(ENCH_ABJ);
mon_enchant charm = monster->get_ench(ENCH_CHARM);
@@ -3637,9 +3639,9 @@ static bool _handle_scroll(monsters *monster)
if (mons_near(monster))
{
simple_monster_message(monster, " reads a scroll.");
- create_monster( MONS_ABOMINATION_SMALL, 2,
- SAME_ATTITUDE(monster), monster->x, monster->y,
- monster->foe, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(MONS_ABOMINATION_SMALL, SAME_ATTITUDE(monster),
+ 2, monster->pos(), monster->foe) );
read = true;
ident = ID_KNOWN_TYPE;
}
@@ -6069,14 +6071,14 @@ static bool _monster_move(monsters *monster)
{
if (mons_is_zombified(monster))
{
- // for zombies, monster type is kept in mon->number
- if (mons_itemuse(monster->number) >= MONUSE_OPEN_DOORS)
+ // for zombies, monster type is kept in mon->base_monster
+ if (mons_itemuse(monster->base_monster) >= MONUSE_OPEN_DOORS)
{
_mons_open_door(monster, newpos);
return true;
}
}
- else if (mons_itemuse(monster->type) >= MONUSE_OPEN_DOORS)
+ else if (mons_itemuse(monster->base_monster) >= MONUSE_OPEN_DOORS)
{
_mons_open_door(monster, newpos);
return true;
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index a4d2a3dec1..53efe61242 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -488,9 +488,9 @@ static void _do_high_level_summon(monsters *monster, bool monsterNearby,
const monster_type which_mons = mpicker();
if (which_mons == MONS_PROGRAM_BUG)
continue;
- create_monster( which_mons, duration,
- SAME_ATTITUDE(monster), monster->x, monster->y,
- monster->foe, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( which_mons, SAME_ATTITUDE(monster), duration,
+ monster->pos(), monster->foe ));
}
}
@@ -577,9 +577,9 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast)
}
}
- create_monster( mons, 5, SAME_ATTITUDE(monster),
- monster->x, monster->y, monster->foe,
- MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( mons, SAME_ATTITUDE(monster), 5,
+ monster->pos(), monster->foe ) );
}
return;
@@ -591,9 +591,9 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast)
for (sumcount = 0; sumcount < sumcount2; sumcount++)
{
- create_monster( RANDOM_MONSTER, 5, SAME_ATTITUDE(monster),
- monster->x, monster->y, monster->foe,
- MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( RANDOM_MONSTER, SAME_ATTITUDE(monster), 5,
+ monster->pos(), monster->foe ) );
}
return;
@@ -602,9 +602,9 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast)
for (sumcount = 0; sumcount < sumcount2; sumcount++)
{
- create_monster( MONS_RAKSHASA_FAKE, 3,
- SAME_ATTITUDE(monster), monster->x, monster->y,
- monster->foe, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( MONS_RAKSHASA_FAKE, SAME_ATTITUDE(monster), 3,
+ monster->pos(), monster->foe ) );
}
return;
@@ -631,9 +631,9 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast)
MONS_VERY_UGLY_THING : MONS_UGLY_THING;
}
- create_monster( mons, duration, SAME_ATTITUDE(monster),
- monster->x, monster->y,
- monster->foe, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( mons, SAME_ATTITUDE(monster), duration,
+ monster->pos(), monster->foe ) );
}
return;
@@ -649,9 +649,11 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast)
duration = std::min(2 + monster->hit_dice / 5, 6);
for (sumcount = 0; sumcount < sumcount2; sumcount++)
{
- create_monster( summon_any_demon(DEMON_LESSER), duration,
- SAME_ATTITUDE(monster), monster->x, monster->y,
- monster->foe, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( summon_any_demon(DEMON_LESSER),
+ SAME_ATTITUDE(monster),
+ duration, monster->pos(),
+ monster->foe ));
}
return;
@@ -662,22 +664,22 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast)
for (sumcount = 0; sumcount < sumcount2; sumcount++)
{
- create_monster( MONS_UFETUBUS, duration, SAME_ATTITUDE(monster),
- monster->x, monster->y, monster->foe,
- MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(MONS_UFETUBUS, SAME_ATTITUDE(monster), duration,
+ monster->pos(), monster->foe));
}
return;
case SPELL_SUMMON_BEAST: // Geryon
- create_monster( MONS_BEAST, 4, SAME_ATTITUDE(monster),
- monster->x, monster->y, monster->foe,
- MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(MONS_BEAST, SAME_ATTITUDE(monster), 4,
+ monster->pos(), monster->foe));
return;
case SPELL_SUMMON_ICE_BEAST:
- create_monster( MONS_ICE_BEAST, 5, SAME_ATTITUDE(monster),
- monster->x, monster->y, monster->foe,
- MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(MONS_ICE_BEAST, SAME_ATTITUDE(monster), 5,
+ monster->pos(), monster->foe));
return;
case SPELL_SUMMON_MUSHROOMS: // Summon swarms of icky crawling fungi.
@@ -689,11 +691,12 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast)
duration = std::min(2 + monster->hit_dice / 5, 6);
for (int i = 0; i < sumcount2; ++i)
{
- create_monster(MONS_WANDERING_MUSHROOM, duration,
- SAME_ATTITUDE(monster),
- monster->x, monster->y,
- monster->foe,
- MONS_PROGRAM_BUG);
+ create_monster(
+ mgen_data(MONS_WANDERING_MUSHROOM,
+ SAME_ATTITUDE(monster),
+ duration,
+ monster->pos(),
+ monster->foe));
}
return;
@@ -731,9 +734,12 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast)
duration = std::min(2 + monster->hit_dice / 10, 6);
for (sumcount = 0; sumcount < sumcount2; sumcount++)
{
- create_monster( summon_any_demon(DEMON_GREATER), duration,
- SAME_ATTITUDE(monster), monster->x, monster->y,
- monster->foe, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(summon_any_demon(DEMON_GREATER),
+ SAME_ATTITUDE(monster),
+ duration,
+ monster->pos(),
+ monster->foe));
}
return;
@@ -747,7 +753,7 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast)
duration = std::min(2 + monster->hit_dice / 10, 6);
{
- std::vector<int> monsters;
+ std::vector<monster_type> monsters;
for (sumcount = 0; sumcount < sumcount2; sumcount++)
{
@@ -763,10 +769,9 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast)
for (int i = 0, size = monsters.size(); i < size; ++i)
{
- create_monster( monsters[i], duration,
- SAME_ATTITUDE(monster),
- monster->x, monster->y, monster->foe,
- MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(monsters[i], SAME_ATTITUDE(monster), duration,
+ monster->pos(), monster->foe));
}
}
return;
@@ -2309,11 +2314,11 @@ bool silver_statue_effects(monsters *mons)
"'s eyes glow " + weird_glow_colour() + '.';
simple_monster_message(mons, msg.c_str(), MSGCH_WARN);
- create_monster( summon_any_demon((coinflip() ? DEMON_COMMON
- : DEMON_LESSER)),
- 5, BEH_HOSTILE,
- you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(
+ summon_any_demon((coinflip() ? DEMON_COMMON
+ : DEMON_LESSER)),
+ BEH_HOSTILE, 5, you.pos(), MHITYOU ));
return (true);
}
return (false);
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 7ab5ce1ce7..8a623f9bcd 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -1047,9 +1047,10 @@ static bool _beogh_blessing_reinforcement()
else
follower_type = RANDOM_ELEMENT(followers);
- int monster = create_monster(follower_type, 0, BEH_GOD_GIFT,
- you.x_pos, you.y_pos, you.pet_target,
- MONS_PROGRAM_BUG);
+ int monster =
+ create_monster(
+ mgen_data(follower_type, BEH_GOD_GIFT, 0,
+ you.pos(), you.pet_target));
if (monster != -1)
{
monsters *mon = &menv[monster];
@@ -1467,9 +1468,9 @@ static void _do_god_gift(bool prayed_for)
monster_type thing_called =
_random_servant(GOD_YREDELEMNUL);
- if (create_monster(thing_called, 0, BEH_FRIENDLY,
- you.x_pos, you.y_pos, you.pet_target,
- MAKE_ITEM_RANDOM_RACE) != -1)
+ if (create_monster(
+ mgen_data(thing_called, BEH_FRIENDLY, 0,
+ you.pos(), you.pet_target)) != -1)
{
simple_god_message(" grants you an undead servant!");
more();
@@ -2873,9 +2874,9 @@ static bool _tso_retribution()
int how_many = 1 + random2(you.experience_level / 5) + random2(3);
for (int i = 0; i < how_many; i++)
- if (create_monster( MONS_DAEVA, 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG ) != -1)
+ if (create_monster(
+ mgen_data(MONS_DAEVA, BEH_HOSTILE, 0,
+ you.pos(), MHITYOU )) != -1)
{
success = true;
}
@@ -2972,9 +2973,9 @@ static bool _zin_retribution()
bool success = false;
for (int i = 0; i < how_many; i++)
- if (create_monster(MONS_ANGEL, 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data(MONS_ANGEL, BEH_HOSTILE, 0,
+ you.pos(), MHITYOU)) != -1)
{
success = true;
}
@@ -3119,9 +3120,13 @@ static bool _makhleb_retribution()
if (random2(you.experience_level) > 7 && !one_chance_in(5))
{
- const bool success = create_monster(MONS_EXECUTIONER + random2(5), 0,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG) != -1;
+ const bool success =
+ create_monster(
+ mgen_data(
+ static_cast<monster_type>(
+ MONS_EXECUTIONER + random2(5)),
+ BEH_HOSTILE, 0,
+ you.pos(), MHITYOU)) != -1;
simple_god_message(success ?
" sends a greater servant after you!" :
"'s greater servant is unavoidably detained.",
@@ -3133,9 +3138,12 @@ static bool _makhleb_retribution()
int how_many = 1 + (you.experience_level / 7);
for (int i = 0; i < how_many; i++)
- if (create_monster(MONS_NEQOXEC + random2(5), 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data(
+ static_cast<monster_type>(
+ MONS_NEQOXEC + random2(5)),
+ BEH_HOSTILE, 0,
+ you.pos(), MHITYOU)) != -1)
success = true;
simple_god_message(success ?
@@ -3158,8 +3166,9 @@ static bool _kikubaaqudgha_retribution()
int how_many = 1 + (you.experience_level / 5) + random2(3);
for (int i = 0; i < how_many; i++)
- if (create_monster(MONS_REAPER, 0, BEH_HOSTILE, you.x_pos,
- you.y_pos, MHITYOU, MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data(MONS_REAPER, BEH_HOSTILE, 0, you.pos(),
+ MHITYOU)) != -1)
success = true;
if (success)
@@ -3193,9 +3202,9 @@ static bool _yredelemnul_retribution()
{
monster_type punisher = _random_servant(GOD_YREDELEMNUL);
- if (create_monster(punisher, 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data(punisher, BEH_HOSTILE, 0,
+ you.pos(), MHITYOU)) != -1)
count++;
}
@@ -3355,9 +3364,11 @@ static bool _beogh_retribution()
set_ident_flags( item, ISFLAG_KNOW_TYPE );
// now create monster
- int mons = create_monster( MONS_DANCING_WEAPON, 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG );
+ int mons =
+ create_monster(
+ mgen_data::alert_hostile_at(
+ MONS_DANCING_WEAPON,
+ you.pos() ));
// hand item information over to monster
if (mons != -1)
@@ -3411,9 +3422,10 @@ static bool _beogh_retribution()
punisher = MONS_ORC;
bool success =
- (create_monster(punisher, 0, BEH_HOSTILE, you.x_pos,
- you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG, true) != -1);
+ (create_monster(
+ mgen_data::alert_hostile_at(
+ punisher,
+ you.pos())) != -1);
simple_god_message(success ?
" sends forth an army of orcs." :
@@ -3437,9 +3449,9 @@ static bool _okawaru_retribution()
{
monster_type punisher = _random_servant(GOD_OKAWARU);
- if (create_monster(punisher, 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data::alert_hostile_at(
+ punisher, you.pos())) != -1)
{
success = true;
}
@@ -3529,9 +3541,10 @@ static bool _lugonu_retribution()
if (random2(you.experience_level) > 7 && !one_chance_in(5))
{
bool success = false;
- if (create_monster(MONS_GREEN_DEATH + random2(3), 0,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data::alert_hostile_at(
+ static_cast<monster_type>(MONS_GREEN_DEATH + random2(3)),
+ you.pos())) != -1)
{
success = true;
}
@@ -3548,9 +3561,10 @@ static bool _lugonu_retribution()
for (int loopy = 0; loopy < how_many; loopy++)
{
- if (create_monster(MONS_NEQOXEC + random2(5), 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data::alert_hostile_at(
+ static_cast<monster_type>(MONS_NEQOXEC + random2(5)),
+ you.pos())) != -1)
{
success = true;
}
diff --git a/crawl-ref/source/spells2.cc b/crawl-ref/source/spells2.cc
index 11f69b5836..7c19f33153 100644
--- a/crawl-ref/source/spells2.cc
+++ b/crawl-ref/source/spells2.cc
@@ -439,7 +439,7 @@ static int raise_corpse( int corps, int corx, int cory,
returnVal = 0;
else if (actual != 0)
{
- int type;
+ monster_type type = MONS_PROGRAM_BUG;
if (mitm[corps].sub_type == CORPSE_BODY)
{
if (mons_zombie_size(mitm[corps].plus) == Z_SMALL)
@@ -455,8 +455,11 @@ static int raise_corpse( int corps, int corx, int cory,
type = MONS_SKELETON_LARGE;
}
- create_monster( type, 0, corps_beh, corx, cory, corps_hit,
- mitm[corps].plus );
+ create_monster(
+ mgen_data(
+ type, corps_beh, 0,
+ coord_def(corx, cory), corps_hit,
+ 0, static_cast<monster_type>(mitm[corps].plus)));
destroy_item(corps);
}
@@ -468,7 +471,7 @@ void cast_twisted(int power, beh_type corps_beh, int corps_hit)
{
int total_mass = 0;
int num_corpses = 0;
- int type_resurr = MONS_ABOMINATION_SMALL;
+ monster_type type_resurr = MONS_ABOMINATION_SMALL;
char colour;
unsigned char rotted = 0;
@@ -535,8 +538,11 @@ void cast_twisted(int power, beh_type corps_beh, int corps_hit)
else
colour = LIGHTRED;
- int mon = create_monster( type_resurr, 0, corps_beh, you.x_pos, you.y_pos,
- corps_hit, colour );
+ mgen_data mg( type_resurr, corps_beh, 0,
+ you.pos(), corps_hit, 0, MONS_PROGRAM_BUG, 0,
+ colour );
+
+ int mon = create_monster(mg);
if (mon == -1)
mpr("The corpses collapse into a pulpy mess.");
@@ -1240,7 +1246,7 @@ char burn_freeze(int pow, beam_type flavour)
bool summon_elemental(int pow, int restricted_type,
unsigned char unfriendly)
{
- int type_summoned = MONS_PROGRAM_BUG; // error trapping {dlb}
+ monster_type type_summoned = MONS_PROGRAM_BUG;
struct dist smove;
int dir_x;
@@ -1347,12 +1353,12 @@ bool summon_elemental(int pow, int restricted_type,
&& random2(100) >= unfriendly);
- if (create_monster( type_summoned, numsc,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- targ_x, targ_y,
- friendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG, false, false,
- false, true ) == -1)
+ if (create_monster(
+ mgen_data( type_summoned,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ numsc,
+ coord_def(targ_x, targ_y),
+ friendly ? you.pet_target : MHITYOU )) != -1)
{
return (false);
}
@@ -1409,11 +1415,11 @@ void summon_small_mammals(int pow)
break;
}
- create_monster( thing_called, 3, BEH_FRIENDLY,
- you.x_pos, you.y_pos, you.pet_target,
- MONS_PROGRAM_BUG, false, false, false, true);
+ create_monster(
+ mgen_data( thing_called, BEH_FRIENDLY, 3,
+ you.pos(), you.pet_target ));
}
-} // end summon_small_mammals()
+}
void summon_animals(int pow)
{
@@ -1451,11 +1457,11 @@ void summon_animals(int pow)
bool friendly = (random2(pow) > 4);
- create_monster( mon_chosen, 4,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- you.x_pos, you.y_pos,
- friendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG, false, false, false, true);
+ create_monster(
+ mgen_data( mon_chosen,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, 4,
+ you.pos(),
+ friendly ? you.pet_target : MHITYOU ));
}
}
@@ -1469,12 +1475,12 @@ void summon_scorpions(int pow)
{
bool friendly = (random2(pow) > 3);
- if (create_monster( MONS_SCORPION, 3,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- you.x_pos, you.y_pos,
- friendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG, false, false,
- false, true) != -1)
+ if (create_monster(
+ mgen_data(MONS_SCORPION,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ 3,
+ you.pos(),
+ friendly ? you.pet_target : MHITYOU)) != -1)
{
mprf("A scorpion appears.%s",
friendly ? "" : " It doesn't look very happy.");
@@ -1493,12 +1499,12 @@ void summon_ugly_thing(int pow)
bool friendly = (random2(pow) > 3);
- if (create_monster(ugly, numsc,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- you.x_pos, you.y_pos,
- friendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG, false, false,
- false, true) != -1)
+ if (create_monster(
+ mgen_data(ugly,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ numsc,
+ you.pos(),
+ friendly ? you.pet_target : MHITYOU)) != -1)
{
const char *prefix = (ugly == MONS_VERY_UGLY_THING) ? " very " : "n ";
@@ -1507,7 +1513,7 @@ void summon_ugly_thing(int pow)
}
} // end summon_ugly_thing()
-void summon_ice_beast_etc(int pow, int ibc, bool divine_gift)
+void summon_ice_beast_etc(int pow, monster_type ibc, bool divine_gift)
{
int numsc = std::min(2 + (random2(pow) / 4), 6);
beh_type beha = divine_gift ? BEH_GOD_GIFT : BEH_FRIENDLY;
@@ -1555,10 +1561,10 @@ void summon_ice_beast_etc(int pow, int ibc, bool divine_gift)
}
}
- int monster = create_monster( ibc, numsc, beha,
- you.x_pos, you.y_pos, hitting,
- MONS_PROGRAM_BUG, false, false,
- false, true );
+ int monster =
+ create_monster(
+ mgen_data(ibc, beha, numsc,
+ you.pos(), hitting));
if (monster != -1)
{
if (ibc == MONS_DAEVA)
@@ -1626,9 +1632,11 @@ bool summon_berserker(int pow, bool god_gift)
mon = MONS_STONE_GIANT;
}
- int mons = create_monster( mon, numsc, beha, you.x_pos, you.y_pos,
- god_gift ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG );
+ int mons =
+ create_monster(
+ mgen_data( mon, beha, numsc,
+ you.pos(),
+ god_gift ? you.pet_target : MHITYOU ));
if (mons != -1)
{
@@ -1653,7 +1661,7 @@ bool summon_berserker(int pow, bool god_gift)
bool summon_swarm( int pow, bool unfriendly, bool god_gift )
{
- int thing_called = MONS_PROGRAM_BUG; // error trapping {dlb}
+ monster_type thing_called = MONS_PROGRAM_BUG;
int numsc = 2 + random2(pow) / 10 + random2(pow) / 25;
bool summoned = false;
@@ -1718,11 +1726,10 @@ bool summon_swarm( int pow, bool unfriendly, bool god_gift )
else if (!unfriendly && random2(pow) > 7)
behaviour = BEH_FRIENDLY;
- if (create_monster( thing_called, 3, behaviour,
- you.x_pos, you.y_pos,
- !unfriendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG, false, false,
- false, true ) != -1)
+ if (create_monster(
+ mgen_data( thing_called, behaviour, 3,
+ you.pos(),
+ !unfriendly ? you.pet_target : MHITYOU )) != -1)
{
summoned = true;
}
@@ -1734,7 +1741,7 @@ bool summon_swarm( int pow, bool unfriendly, bool god_gift )
void summon_undead(int pow)
{
int temp_rand = 0;
- int thing_called = MONS_PROGRAM_BUG; // error trapping {dlb}
+ monster_type thing_called = MONS_PROGRAM_BUG;
int numsc = 1 + random2(pow) / 30 + random2(pow) / 30;
numsc = stepdown_value(numsc, 2, 2, 6, 8); //see stuff.cc {dlb}
@@ -1751,12 +1758,11 @@ void summon_undead(int pow)
bool friendly = (random2(pow) > 5);
- if (create_monster( thing_called, 5,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- you.x_pos, you.y_pos,
- friendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG, false, false,
- false, true ) != -1)
+ if (create_monster(
+ mgen_data(thing_called,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, 5,
+ you.pos(),
+ friendly ? you.pet_target : MHITYOU)) != -1)
{
if (friendly)
mpr("An insubstantial figure forms in the air.");
@@ -1807,17 +1813,17 @@ void summon_things( int pow )
while (big_things > 0)
{
- create_monster( MONS_TENTACLED_MONSTROSITY, 6, BEH_FRIENDLY,
- you.x_pos, you.y_pos, you.pet_target,
- MONS_PROGRAM_BUG, false, false, false, true );
+ create_monster(
+ mgen_data(MONS_TENTACLED_MONSTROSITY, BEH_FRIENDLY, 6,
+ you.pos(), you.pet_target));
big_things--;
}
while (numsc > 0)
{
- create_monster( MONS_ABOMINATION_LARGE, 6, BEH_FRIENDLY,
- you.x_pos, you.y_pos, you.pet_target,
- MONS_PROGRAM_BUG, false, false, false, true );
+ create_monster(
+ mgen_data(MONS_ABOMINATION_LARGE, BEH_FRIENDLY, 6,
+ you.pos(), you.pet_target ));
numsc--;
}
diff --git a/crawl-ref/source/spells2.h b/crawl-ref/source/spells2.h
index 98a969c0b1..8efb768298 100644
--- a/crawl-ref/source/spells2.h
+++ b/crawl-ref/source/spells2.h
@@ -132,7 +132,7 @@ bool restore_stat(unsigned char which_stat, unsigned char stat_gain,
/* ***********************************************************************
* called from: ability - spell
* *********************************************************************** */
-void summon_ice_beast_etc(int pow, int ibc, bool divine_gift = false);
+void summon_ice_beast_etc(int pow, monster_type ibc, bool divine_gift = false);
// last updated 24may2000 {dlb}
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index 36dd8baf38..a1ab61f9e3 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -432,7 +432,8 @@ void simulacrum(int power)
|| (you.inv[ chunk ].base_type == OBJ_FOOD
&& you.inv[ chunk ].sub_type == FOOD_CHUNK)))
{
- const int mons_type = you.inv[ chunk ].plus;
+ const monster_type mons_type =
+ static_cast<monster_type>(you.inv[ chunk ].plus);
// Can't create more than the available chunks
if (you.inv[ chunk ].quantity < max_num)
@@ -444,9 +445,11 @@ void simulacrum(int power)
for (int i = 0; i < max_num; i++)
{
- if (create_monster( MONS_SIMULACRUM_SMALL, 6,
- BEH_FRIENDLY, you.x_pos, you.y_pos,
- you.pet_target, mons_type ) != -1)
+ if (create_monster(
+ mgen_data(MONS_SIMULACRUM_SMALL,
+ BEH_FRIENDLY, 6,
+ you.pos(), you.pet_target,
+ 0, mons_type)) != -1)
{
summoned++;
}
@@ -503,9 +506,10 @@ bool dancing_weapon(int pow, bool force_hostile, bool silent)
hitting = MHITYOU;
}
- summs = create_monster(MONS_DANCING_WEAPON, numsc, beha,
- you.x_pos, you.y_pos, hitting,
- MONS_PROGRAM_BUG);
+ summs =
+ create_monster(
+ mgen_data(MONS_DANCING_WEAPON, beha, numsc,
+ you.pos(), hitting));
if (summs == -1)
failed = true;
}
diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc
index e2ff3ab3c1..0150125569 100644
--- a/crawl-ref/source/spells4.cc
+++ b/crawl-ref/source/spells4.cc
@@ -426,10 +426,9 @@ void cast_summon_butterflies(int pow)
for (int scount = 1; scount < num; scount++)
{
- create_monster( MONS_BUTTERFLY, 3, BEH_FRIENDLY,
- you.x_pos, you.y_pos, you.pet_target,
- MONS_PROGRAM_BUG, false, false,
- false, true );
+ create_monster(
+ mgen_data(MONS_BUTTERFLY, BEH_FRIENDLY, 3,
+ you.pos(), you.pet_target));
}
}
@@ -466,15 +465,14 @@ void cast_summon_large_mammal(int pow)
}
}
- create_monster( mon, 3, BEH_FRIENDLY,
- you.x_pos, you.y_pos, you.pet_target,
- MONS_PROGRAM_BUG, false, false,
- false, true );
+ create_monster(
+ mgen_data( mon, BEH_FRIENDLY, 3,
+ you.pos(), you.pet_target ));
}
void cast_sticks_to_snakes(int pow)
{
- int mon;
+ monster_type mon = MONS_PROGRAM_BUG;
int how_many = 0;
int max = 1 + random2( 1 + you.skills[SK_TRANSMIGRATION] ) / 4;
int dur = std::min(3 + random2(pow) / 20, 5);
@@ -511,10 +509,9 @@ void cast_sticks_to_snakes(int pow)
mon = MONS_SMALL_SNAKE;
}
- if (create_monster( mon, dur, beha,
- you.x_pos, you.y_pos, hitting,
- MONS_PROGRAM_BUG, false, false,
- false, true ) != -1)
+ if (create_monster(
+ mgen_data( mon, beha, dur,
+ you.pos(), hitting )) != -1)
{
how_many++;
}
@@ -557,10 +554,9 @@ void cast_sticks_to_snakes(int pow)
if (pow > 20 && one_chance_in(3))
mon = MONS_BROWN_SNAKE;
- if (create_monster( mon, dur, beha,
- you.x_pos, you.y_pos, hitting,
- MONS_PROGRAM_BUG, false, false,
- false, true ) != -1)
+ if (create_monster(
+ mgen_data( mon, beha, dur,
+ you.pos(), hitting )) != -1)
{
how_many++;
}
@@ -593,12 +589,11 @@ void cast_summon_dragon(int pow)
// a very high level spell so it might be okay). -- bwr
const bool friendly = (random2(pow) > 5);
- if (create_monster( MONS_DRAGON, 3,
- friendly ? BEH_FRIENDLY : BEH_HOSTILE,
- you.x_pos, you.y_pos,
- friendly ? you.pet_target : MHITYOU,
- MONS_PROGRAM_BUG, false, false,
- false, true ) != -1)
+ if (create_monster(
+ mgen_data( MONS_DRAGON,
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE, 3,
+ you.pos(),
+ friendly ? you.pet_target : MHITYOU )) != -1)
{
mprf("A dragon appears.%s",
friendly ? "" : " It doesn't look very happy.");
@@ -638,11 +633,10 @@ void cast_conjure_ball_lightning( int pow )
ty = you.y_pos;
}
- int mon = mons_place( MONS_BALL_LIGHTNING, BEH_FRIENDLY, MHITNOT,
- true, tx, ty );
-
- // int mon = create_monster( MONS_BALL_LIGHTNING, 0, BEH_FRIENDLY,
- // tx, ty, MHITNOT, MONS_PROGRAM_BUG );
+ int mon =
+ mons_place(
+ mgen_data( MONS_BALL_LIGHTNING, BEH_FRIENDLY, 0,
+ coord_def(tx, ty) ));
if (mon != -1)
{
@@ -1826,21 +1820,6 @@ void cast_fulsome_distillation( int powc )
}
}
-void make_shuggoth(int x, int y, int hp)
-{
- int mon = create_monster( MONS_SHUGGOTH, 100 + random2avg(58, 3),
- BEH_HOSTILE, x, y, MHITNOT, MONS_PROGRAM_BUG,
- false, false, false, true );
-
- if (mon != -1)
- {
- menv[mon].hit_points = hp;
- menv[mon].max_hit_points = hp;
- }
-
- return;
-} // end make_shuggoth()
-
static int rot_living(int x, int y, int pow, int message)
{
UNUSED( message );
diff --git a/crawl-ref/source/spells4.h b/crawl-ref/source/spells4.h
index d3b0bf36d1..937bdabe13 100644
--- a/crawl-ref/source/spells4.h
+++ b/crawl-ref/source/spells4.h
@@ -57,9 +57,6 @@ void cast_dispersal(int pow);
void cast_snake_charm(int pow);
void cast_stoneskin(int pow);
-void cast_shuggoth_seed(int powc);
-void make_shuggoth(int x, int y, int hp);
-
int cast_semi_controlled_blink(int pow);
bool cast_portal_projectile(int pow, bolt& beam);
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index 8d96ab7d45..77d9b034f7 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -1581,8 +1581,9 @@ spret_type your_spells( spell_type spell, int powc, bool allow_fail )
if (dem_beh == BEH_CHARMED)
mpr("You don't feel so good about this...");
- create_monster( summon_any_demon(DEMON_GREATER), 5, dem_beh,
- you.x_pos, you.y_pos, MHITYOU, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( summon_any_demon(DEMON_GREATER), dem_beh, 5,
+ you.pos(), MHITYOU ));
}
break;
@@ -1796,9 +1797,9 @@ spret_type your_spells( spell_type spell, int powc, bool allow_fail )
case SPELL_SHADOW_CREATURES:
{
mpr( "Wisps of shadow whirl around you..." );
- create_monster( RANDOM_MONSTER, 2, BEH_FRIENDLY,
- you.x_pos, you.y_pos, you.pet_target,
- MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( RANDOM_MONSTER, BEH_FRIENDLY, 2,
+ you.pos(), you.pet_target ));
break;
}
@@ -2358,8 +2359,9 @@ static void _miscast_translocation(int severity, const char* cause)
break;
case 5:
mpr("Space twists in upon itself!");
- create_monster( MONS_SPATIAL_VORTEX, 3, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data( MONS_SPATIAL_VORTEX, BEH_HOSTILE, 3,
+ you.pos(), MHITYOU ));
break;
}
break;
@@ -2391,9 +2393,9 @@ static void _miscast_translocation(int severity, const char* cause)
const int count = 2 + random2(3);
for (int i = 0; i < count; ++i)
{
- create_monster( MONS_SPATIAL_VORTEX, 3,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(MONS_SPATIAL_VORTEX, BEH_HOSTILE, 3,
+ you.pos(), MHITYOU));
}
}
break;
@@ -2485,15 +2487,16 @@ static void _miscast_summoning(int severity, const char* cause)
case 3:
mpr("Space twists in upon itself!");
- create_monster( MONS_SPATIAL_VORTEX, 3, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(MONS_SPATIAL_VORTEX, BEH_HOSTILE, 3,
+ you.pos(), MHITYOU));
break;
case 4:
case 5:
- if (create_monster( summon_any_demon(DEMON_LESSER), 5,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG ) != -1)
+ if (create_monster(
+ mgen_data(summon_any_demon(DEMON_LESSER),
+ BEH_HOSTILE, 5, you.pos(), MHITYOU)) != -1)
{
mpr("Something appears in a flash of light!");
}
@@ -2510,18 +2513,20 @@ static void _miscast_summoning(int severity, const char* cause)
const int count = 2 + random2(3);
for (int i = 0; i < count; ++i)
{
- create_monster( MONS_SPATIAL_VORTEX, 3,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(MONS_SPATIAL_VORTEX,
+ BEH_HOSTILE, 3,
+ you.pos(), MHITYOU));
}
}
break;
case 1:
case 2:
- if (create_monster( summon_any_demon(DEMON_COMMON), 5,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data(summon_any_demon(DEMON_COMMON),
+ BEH_HOSTILE, 5,
+ you.pos(), MHITYOU)) != -1)
{
mpr("Something forms out of thin air!");
}
@@ -2531,27 +2536,23 @@ static void _miscast_summoning(int severity, const char* cause)
case 4:
case 5:
mpr("A chorus of chattering voices calls out to you!");
- create_monster( summon_any_demon(DEMON_LESSER), 5,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(summon_any_demon(DEMON_LESSER),
+ BEH_HOSTILE, 5, you.pos(), MHITYOU));
- create_monster( summon_any_demon(DEMON_LESSER), 5,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data(summon_any_demon(DEMON_LESSER),
+ BEH_HOSTILE, 5, you.pos(), MHITYOU));
if (coinflip())
- {
- create_monster( summon_any_demon(DEMON_LESSER), 5,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG );
- }
-
+ create_monster(
+ mgen_data(summon_any_demon(DEMON_LESSER),
+ BEH_HOSTILE, 5, you.pos(), MHITYOU));
+
if (coinflip())
- {
- create_monster( summon_any_demon(DEMON_LESSER), 5,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG );
- }
+ create_monster(
+ mgen_data(summon_any_demon(DEMON_LESSER),
+ BEH_HOSTILE, 5, you.pos(), MHITYOU));
break;
}
break;
@@ -2560,18 +2561,20 @@ static void _miscast_summoning(int severity, const char* cause)
switch (random2(4))
{
case 0:
- if (create_monster( MONS_ABOMINATION_SMALL, 0, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG ) != -1)
+ if (create_monster(
+ mgen_data::alert_hostile_at(
+ MONS_ABOMINATION_SMALL,
+ you.pos())) != -1)
{
mpr("Something forms out of thin air.");
}
break;
case 1:
- if (create_monster( summon_any_demon(DEMON_GREATER), 0,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG ) != -1)
+ if (create_monster(
+ mgen_data::alert_hostile_at(
+ summon_any_demon(DEMON_GREATER),
+ you.pos())) != -1)
{
mpr("You sense a hostile presence.");
}
@@ -2580,20 +2583,18 @@ static void _miscast_summoning(int severity, const char* cause)
case 2:
mpr("Something turns its malign attention towards you...");
- create_monster( summon_any_demon(DEMON_COMMON), 3,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data::alert_hostile_at(
+ summon_any_demon(DEMON_COMMON), you.pos(), 3));
- create_monster( summon_any_demon(DEMON_COMMON), 3,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data::alert_hostile_at(
+ summon_any_demon(DEMON_COMMON), you.pos(), 3));
if (coinflip())
- {
- create_monster(summon_any_demon(DEMON_COMMON), 3,
- BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITYOU, MONS_PROGRAM_BUG);
- }
+ create_monster(
+ mgen_data::alert_hostile_at(
+ summon_any_demon(DEMON_COMMON), you.pos(), 3));
break;
case 3:
@@ -2797,23 +2798,19 @@ static void _miscast_necromancy(int severity, const char* cause)
case 0:
mpr("Flickering shadows surround you.");
- create_monster( MONS_SHADOW, 2, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG );
+ create_monster(
+ mgen_data::alert_hostile_at(
+ MONS_SHADOW, you.pos(), 2));
if (coinflip())
- {
- create_monster( MONS_SHADOW, 2, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG );
- }
+ create_monster(
+ mgen_data::alert_hostile_at(
+ MONS_SHADOW, you.pos(), 2));
if (coinflip())
- {
- create_monster( MONS_SHADOW, 2, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG );
- }
+ create_monster(
+ mgen_data::alert_hostile_at(
+ MONS_SHADOW, you.pos(), 2));
break;
case 1:
@@ -2866,18 +2863,18 @@ static void _miscast_necromancy(int severity, const char* cause)
break;
case 4:
- if (create_monster( MONS_SOUL_EATER, 4, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data::alert_hostile_at(
+ MONS_SOUL_EATER, you.pos(), 4)) != -1)
{
mpr("Something reaches out for you...");
}
break;
case 5:
- if (create_monster( MONS_REAPER, 4, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU,
- MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data::alert_hostile_at(
+ MONS_REAPER, you.pos(), 4)) != -1)
{
mpr("Death has come for you...");
}
diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc
index 099f0b81f5..fb9ea9b870 100644
--- a/crawl-ref/source/stuff.cc
+++ b/crawl-ref/source/stuff.cc
@@ -1101,6 +1101,12 @@ bool map_bounds( int x, int y )
&& y >= Y_BOUND_1 && y <= Y_BOUND_2);
}
+coord_def random_in_bounds()
+{
+ return coord_def( random_range(MAPGEN_BORDER, GXM - MAPGEN_BORDER - 1),
+ random_range(MAPGEN_BORDER, GYM - MAPGEN_BORDER - 1) );
+}
+
// Returns a random location in (x_pos, y_pos)... the grid will be
// DNGN_FLOOR if clear, and NON_MONSTER if empty. Exclusive tells
// if we're using in_bounds() or map_bounds() restriction.
diff --git a/crawl-ref/source/stuff.h b/crawl-ref/source/stuff.h
index 8d07f41206..08eba87624 100644
--- a/crawl-ref/source/stuff.h
+++ b/crawl-ref/source/stuff.h
@@ -109,6 +109,7 @@ int yesnoquit( const char* str, bool safe = true, int safeanswer = 0,
bool in_bounds( int x, int y );
bool map_bounds( int x, int y );
+coord_def random_in_bounds();
inline bool in_bounds(const coord_def &p)
{
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 92b4c994ee..4a3f586a66 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -1784,6 +1784,7 @@ static void marshall_monster(writer &th, const monsters &m)
marshallShort(th, m.hit_points);
marshallShort(th, m.max_hit_points);
marshallShort(th, m.number);
+ marshallShort(th, m.base_monster);
marshallShort(th, m.colour);
for (int j = 0; j < NUM_MONSTER_SLOTS; j++)
@@ -2047,6 +2048,10 @@ static void unmarshall_monster(reader &th, monsters &m)
m.hit_points = unmarshallShort(th);
m.max_hit_points = unmarshallShort(th);
m.number = unmarshallShort(th);
+ if (_tag_minor_version >= TAG_MINOR_MONBASE)
+ m.base_monster = static_cast<monster_type>(unmarshallShort(th));
+ else
+ m.base_monster = static_cast<monster_type>(m.number);
m.colour = unmarshallShort(th);
@@ -2071,7 +2076,7 @@ static void tag_read_level_monsters(reader &th, char minorVersion)
// how many mons_alloc?
count = unmarshallByte(th);
for (i = 0; i < count; ++i)
- env.mons_alloc[i] = unmarshallShort(th);
+ env.mons_alloc[i] = static_cast<monster_type>( unmarshallShort(th) );
// how many monsters?
count = unmarshallShort(th);
diff --git a/crawl-ref/source/tags.h b/crawl-ref/source/tags.h
index b7ff700e69..3b96dec779 100644
--- a/crawl-ref/source/tags.h
+++ b/crawl-ref/source/tags.h
@@ -54,7 +54,8 @@ enum tag_minor_version
TAG_MINOR_QUIVER = 3, // Added quiver
TAG_MINOR_MAPMARK = 4, // Added sizes to map markers
TAG_MINOR_MONNAM = 5, // Monsters get individual names
- TAG_MINOR_VERSION = 5 // Current version
+ TAG_MINOR_MONBASE = 6, // Zombie base monster gets its own field.
+ TAG_MINOR_VERSION = 6 // Current version
};
diff --git a/crawl-ref/source/tile1.cc b/crawl-ref/source/tile1.cc
index b8ed61ebad..2d1909fece 100644
--- a/crawl-ref/source/tile1.cc
+++ b/crawl-ref/source/tile1.cc
@@ -299,12 +299,8 @@ static int _tileidx_monster_base(int mon_idx, bool detected)
return TILE_MONS_GRIFFON;
case MONS_HYDRA:
- {
- // Number of heads
- int heads = mon->number;
- if (heads > 7) heads = 7;
- return TILE_MONS_HYDRA + heads - 1;
- }
+ // Number of heads
+ return TILE_MONS_HYDRA + std::min(mon->number, 7) - 1;
case MONS_SKELETON_SMALL:
return TILE_MONS_SKELETON_SMALL;
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc
index 617517fd7e..ca1c9635fb 100644
--- a/crawl-ref/source/xom.cc
+++ b/crawl-ref/source/xom.cc
@@ -523,9 +523,10 @@ static bool xom_is_good(int sever)
if (!is_demonic)
numdifferent++;
- summons[i] = create_monster(mon, 3, BEH_GOD_GIFT,
- you.x_pos, you.y_pos,
- you.pet_target, MONS_PROGRAM_BUG);
+ summons[i] =
+ create_monster(
+ mgen_data(mon, BEH_GOD_GIFT, 3,
+ you.pos(), you.pet_target));
if (summons[i] != -1)
success = true;
@@ -606,8 +607,8 @@ static bool xom_is_good(int sever)
beh_type beh = (different && hostiletype) ? BEH_HOSTILE
: BEH_GOD_GIFT;
- if (create_monster(mon, 6, beh, you.x_pos, you.y_pos,
- you.pet_target, MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data(mon, beh, 6, you.pos(), you.pet_target)) != -1)
{
if (different)
god_speaks(GOD_XOM, _get_xom_speech("single holy summon"));
@@ -686,9 +687,9 @@ static bool xom_is_good(int sever)
beh_type beh = (different && hostiletype) ? BEH_HOSTILE
: BEH_GOD_GIFT;
- if (create_monster(xom_random_demon(sever, one_chance_in(8)),
- 0, beh, you.x_pos, you.y_pos,
- you.pet_target, MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data(xom_random_demon(sever, one_chance_in(8)),
+ beh, 0, you.pos(), you.pet_target)) != -1)
{
if (different)
god_speaks(GOD_XOM, _get_xom_speech("single major holy summon"));
@@ -853,9 +854,9 @@ static bool xom_is_bad(int sever)
for (int i = 0; i < numdemons; i++)
{
- if (create_monster(xom_random_punishment_demon(sever),
- 4, BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITNOT, MONS_PROGRAM_BUG) != -1)
+ if (create_monster(
+ mgen_data(xom_random_punishment_demon(sever),
+ BEH_HOSTILE, 4, you.pos())) != -1)
{
success = true;
}