items first.
Removed arena tag "move_spawners", replaced it with "move_summons", which moves summons to a random location as soon as they're placed.
Added tag "summon_throttle:", which if set prevents summons from being placed if the summoner has N or more allies.
Make arena monsters ignore test spawners, since spawners are only pseudo-monsters placed in order to summons real monsters (plus attacking them is a waste of time since they're unkillable).
Tell the arena when a corpse is placed.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8349 c06c8d41-db1a-0410-9941-cceddc491573
3HBQJBTXTMATEKEZ7ANDLAXVKS4F45YS647KYWNKQE32GQW22S3AC
USIGLWEX5AA7IJ2U6ZMKFMMVZMRAKC3TKXAPBOF457DP4ND6ZT5AC
IA4AZVXJEZP6QRPKUUPBLZQWY36PSN4UMGXVLINXJNTKJR2NXHEAC
2RJUPYKEDZZCW4GDG6WLEDVYF32ADC4W5I42KSKHN3MWEBCWSAHQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
TZMLB4SJENS4JWIPIG7HFOFRIOZYYH5YB4TG7ZGBYT63C5B3MXDQC
KOVRG7IPNFPXQNBFVMYEY7T6WM55CHJ37I4E763S6EJ6IZH32FYAC
YJC3XCYRRQGOL2OCWAJJKBS6BGUHBVHWEL72HHEHRC6HG7WAHIOAC
HM6NOS7BN5665KWIFGBXOHZIDMRSVCESN72GMGI6NVBFZGCF3L6QC
ED62QWGKBPORWVKDFOQRKJXEIWZVNGR3O4KWQBDSRNPT36AYOQYAC
2J3TK3NYTO5XO6IHLTV5O6B3HYN2NHXD5ST3WLL5KPTUOVS5F3RQC
PKXXBHS3LWLPZI2QVRX22MSQ4R2626IXRSNHFFYHXYTLJJQU54LQC
R32CQ6FQJTQLB35P3HENIDCBDT3UWXBBCDAAUWHUQO6G6NKEDPKQC
CKKQS65COJ4KKOWYCKSEAPTH2X6HZSCFOT62JQOK5QDSILBKSFDAC
AAHHHRIYK53GIYQOZIGCBFI6ZM3SKN7OBRNLHQ5WVKV73MPK2H5QC
PTZ3HVXCKCJ3R2Q6R2MYNSNFJMZ5ZGJEGLBNFC5WG5VQROS6HR3QC
MB3ZKRP3CSLCJJSXQ44QTAME4M4OOAQLNQ2K3D3AFQV5FO6H3EPQC
WGM77XP66ZEIRWAOKAJDICJ4ZBEUKGAEY6MZQQJ2LUWG5PCG722QC
3EREXXQMWTOWPI5ZV4UABEIR4RTGPNM7V2O6CG2EOFPHA5GEB2WAC
Y26UG3JWXZG3USM5R36UIZAZWVSC67ZKPE6CSIP3SUBVPB7MZSGQC
K4CJM2GNQKZAPQT3FD2FSG4IXBUUZS42VSXH3QCVSWTZ3JOZT6YQC
// Don't fight test spawners, since they're only pseduo-monsters
// placed to spawn real monsters, plus they're impossible to kill.
// But test spawners can fight each other, to give them a target o
// spawn against.
if (other->type == MONS_TEST_SPAWNER
&& mons->type != MONS_TEST_SPAWNER)
{
continue;
}
allow_summons = !strip_tag(spec, "no_summons");
allow_immobile = !strip_tag(spec, "no_immobile");
allow_bands = !strip_tag(spec, "no_bands");
allow_zero_xp = strip_tag(spec, "allow_zero_xp");
real_summons = strip_tag(spec, "real_summons");
do_move_spawners = strip_tag(spec, "move_spawners");
allow_summons = !strip_tag(spec, "no_summons");
allow_animate = !strip_tag(spec, "no_animate");
allow_immobile = !strip_tag(spec, "no_immobile");
allow_bands = !strip_tag(spec, "no_bands");
allow_zero_xp = strip_tag(spec, "allow_zero_xp");
real_summons = strip_tag(spec, "real_summons");
move_summons = strip_tag(spec, "move_summons");
summon_throttle = strip_number_tag(spec, "summon_throttle:");
// Move test spawners to a new position every turn to scatter each
// faction all over the arena.
void move_spawners()
// Try to prevent random luck from letting one spawner fill up the
// arena with so many monsters that the other spawner can never get
// back on even footing.
void balance_spawners()
if (!mon->alive() || mon->type != MONS_TEST_SPAWNER)
continue;
monster_teleport(mon, true, true);
for (unsigned int i = 0; i < b_spawners.size(); i++)
{
int idx = b_spawners[i];
menv[idx].speed_increment *= faction_a.active_members;
menv[idx].speed_increment /= faction_b.active_members;
if (!arena::allow_chain_summons)
arena::zap_summons(monster);
if (arena::move_summons)
monster_teleport(monster, true, true);
if (!arena::allow_chain_summons || !arena::allow_animate)
arena::adjust_spells(monster, !arena::allow_chain_summons,
!arena::allow_animate);
if (corpse != -1 && corpse != NON_ITEM)
arena::item_drop_times[corpse] = arena::turns;
// Won't be dropping any items.
if (monster->flags & MF_HARD_RESET)
return;
for (int i = 0; i < NUM_MONSTER_SLOTS; i++)
{
int idx = monster->inv[i];
if (idx == NON_ITEM)
continue;
if (mitm[idx].flags & ISFLAG_SUMMONED)
continue;
arena::item_drop_times[idx] = arena::turns;
}
// Culls the items which have been on the floor the longest, culling the newest
// items last. Items which a monster dropped voluntarily or because of
// being polymorphed, rather than because of dying, are culled earlier than
// they should be, but it's not like we have to be fair to the arena monsters.
case OBJ_MISSILES:
if (item.sub_type == MI_JAVELIN
|| item.sub_type == MI_THROWING_NET)
{
ammo.push_back(i);
}
else
// Arrows/needles/etc on the floor are just clutter.
cull = true;
break;
// Cull half of items on the floor.
const int cull_target = items.size() / 2;
int cull_count = 0;
case OBJ_CORPSES:
if (item.sub_type == CORPSE_SKELETON)
// If it's rotted away into a skeleton then there's no one
// around who can uses corpses.
cull = true;
else
corpses.push_back(i);
// Arrows/needles/etc on the floor is just clutter.
if (item.base_type != OBJ_MISSILES
|| item.sub_type == MI_JAVELIN
|| item.sub_type == MI_THROWING_NET)
{
ammo.push_back(idx);
continue;
}
}
DESTROY_ITEM(idx);
if (cull_count >= cull_target)
// Get rid of oldest corpses first.
std::sort(corpses.begin(), corpses.end(), _sort_corpses);
std::vector<int>* lists[] = {&corpses, &ammo, &egos, &potions,
&scrolls, &wands, &artefacts, NULL};
#ifdef DEBUG_DIAGNOSTICS
const char* list_names[] = {"corpses", "ammo", "egos", "potions",
"scrolls", "wands", "artefacts"};
#endif
const int count1 = cull_count;
for (unsigned int i = 0; i < ammo.size(); i++)
{
DESTROY_ITEM(ammo[i]);
if (cull_count >= cull_target)
break;
}
std::vector<int>* vec = lists[i];
for (unsigned int j = 0; j < vec->size(); j++)
{
DESTROY_ITEM((*vec)[j]);
if (cull_count >= cull_target)
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Arena culled %d %s, done.", j + 1,
list_names[i]);
#endif
return (first_avail);
}
} // for (unsigned int j = 0; j < vec->size(); j++)