This is mostly just refactoring, but there are a couple gameplay changes:
Forbid merging/splitting when a slime creature is disabled in some way (confused paralyzed etc.)
Experimentally stop requiring slime creatures to be at full HP to split.
ZESQYXHCJSDMADLHSEXSXGKDXP4FKBOEWNN5GDZ5TIA5FFGCZAOAC NGCKHVIDFH356RCHG2UP5D5CIY6YSXFK5CBWRB3JZPPHASGWL2KQC OAALFABK5WQJDVRP5ZBLYT5VG22XCAMVIFEW2I7IAYUPLRMYWCFAC LL7ZA3RH2A6WGA7YD7XWIZFYG5QNFNSA3UMSUFUMIHHSJZ3SWR4QC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC AR3VHZCH5RGEGEFCV2SDOHTTA4WEE4UT3RC3NFA5QNAMGRZTGUVAC H4WHW2YDD5VBZNBL5UNDCAGIDG6K4IVSMN72PDF3PMUFOGPJBUYAC AT4J3B6LI4J5YYAAG6OHHQMZRVL5WUOTL5Q6NBSAX4UX3PBICBBAC BUSA7O6EFBZVAG2RL5T7MD2WTWKOEKKIAAZ2VS4Y3L6ECT4HQR6QC static bool _merge_slimes(monsters *initial_slime, monsters *merge_to)
// Actually merge two slime creature pooling their HP etc.// intial_slime is the one that get's killed off by this process.static bool _do_merge(monsters *initial_slime, monsters *merge_to)
bool slime_split_merge(monsters *thing)
// Slime creatures can split but not merge under these conditionsstatic bool _unoccupied_slime(monsters *thing){return (mons_is_sleeping(thing)|| mons_is_wandering(thing)|| thing->foe == MHITNOT);}// Slime things cannot split or merge if they have any of these// conditions.static bool _disabled_slime(monsters *thing)
// No merging/splitting shapeshifters.if (mons_is_shapeshifter(thing))return (false);
return (!thing|| mons_is_fleeing(thing)|| mons_is_confused(thing)|| mons_is_paralysed(thing));}// See if there are any appropriate adjacent slime creatures for// 'thing' to merge with, if so carry out the merge.static bool _slime_merge(monsters *thing){if(!thing || _disabled_slime(thing) || _unoccupied_slime(thing))return false;
int max_slime_merge = 5;// We can split if in an 'inactive' state (wandering or sleeping for// now).if (mons_is_sleeping(thing) || mons_is_wandering(thing)|| thing->foe == MHITNOT)
// Check for adjacent slime creatures.for(int i=0;i<8;i++)
if (thing->number > 1 && thing->hit_points == thing->max_hit_points)
coord_def target=origin + Compass[compass_idx[i]];monsters * other_thing = monster_at(target);// We found an adjacent monster, is it another slime creature// we can consider merging with?if(other_thing&& other_thing->mons_species() == MONS_SLIME_CREATURE&& other_thing->attitude == thing->attitude&& other_thing->is_summoned() == thing->is_summoned()&& !mons_is_shapeshifter(other_thing)&& !_disabled_slime(other_thing))
// Anywhere we can place am offspring? If so, split.for (int i = 0; i < 8; ++i)
// We can actually merge if doing so won't take us over the// merge cap and the 'movement' would bring us closer to// our target.int new_blob_count = other_thing->number + thing->number;if(new_blob_count <= max_slime_merge&& grid_distance(thing->target, thing->pos()) >grid_distance(thing->target, target))
coord_def target=origin + Compass[compass_idx[i]];
return _do_merge(thing, other_thing);}}}// No adjacent slime creatures we could merge with.return false;}// See if slime creature 'thing' can split, and carry out the split if// we can find a square to place the new slime creature on.static bool _slime_split(monsters *thing){if(!thing|| !_unoccupied_slime(thing)|| _disabled_slime(thing)|| thing->number <= 1)return false;
if (mons_class_can_pass(MONS_SLIME_CREATURE,env.grid(target))&& !actor_at(target)){return (_split_slime(thing, target));}} // end adjacent squares check}// end non singular check}// Otherwise see if a merge is viable.else if (!mons_is_fleeing(thing)){// Check for adjacent slime creatures.for (int i = 0; i < 8; ++i){coord_def target = origin + Compass[compass_idx[i]];monsters *other_thing = monster_at(target);
int compass_idx[] = {0, 1, 2, 3, 4, 5, 6, 7};std::random_shuffle(compass_idx, compass_idx+8);coord_def origin = thing->pos();
// We can merge if we find another adjacent slime which// isn't already at the merge cap and is closer to the// target than our current position.if (other_thing&& other_thing->mons_species() == MONS_SLIME_CREATURE&& other_thing->attitude == thing->attitude&& other_thing->is_summoned() == thing->is_summoned()&& !mons_is_shapeshifter(other_thing)){int new_blob_count = other_thing->number + thing->number;
// Anywhere we can place an offspring?for (int i = 0; i < 8; i++){coord_def target=origin + Compass[compass_idx[i]];
if (new_blob_count <= max_slime_merge&& grid_distance(thing->target, thing->pos()) >grid_distance(thing->target, target)){return (_merge_slimes(thing, other_thing));}}} // end check adjacent}// end merge check
if(mons_class_can_pass(MONS_SLIME_CREATURE,env.grid(target))&& !actor_at(target)){// This can fail if placing a new monster fails. That// probably means we have too many monsters on the level// so just return in that case.return _do_split(thing, target);}}
// Couldn't merge or split.return (false);
// No free squaresreturn false;}// See if a given slime creature can split or merge.bool slime_split_merge(monsters * thing){// No merging/splitting shapeshiftersif(!thing|| mons_is_shapeshifter(thing)|| thing->mons_species() != MONS_SLIME_CREATURE)return false;if (_slime_split(thing))return true;return _slime_merge(thing);