void Creature_tracker::swap_positions( monster &first, monster &second )
{
    const int first_mdex = mon_at( first.pos() );
    const int second_mdex = mon_at( second.pos() );
    remove_from_location_map( first );
    remove_from_location_map( second );
    bool ok = true;
    if( first_mdex == -1 || second_mdex == -1 || first_mdex == second_mdex ) {
        debugmsg( "Tried to swap monsters with invalid positions" );
        ok = false;
    }

    tripoint temp = second.pos();
    second.spawn( first.pos() );
    first.spawn( temp );
    if( ok ) {
        monsters_by_location[first.pos()] = first_mdex;
        monsters_by_location[second.pos()] = second_mdex;
    } else {
        // Try to avoid spamming error messages if something weird happens
        rebuild_cache();
    }
}
void Creature_tracker::swap_positions( monster &first, monster &second )
{
    if( first.pos() == second.pos() ) {
        return;
    }

    // Either of them may be invalid!
    const auto first_iter = monsters_by_location.find( first.pos() );
    const auto second_iter = monsters_by_location.find( second.pos() );
    // implied: first_iter != second_iter

    std::shared_ptr<monster> first_ptr;
    if( first_iter != monsters_by_location.end() ) {
        first_ptr = first_iter->second;
        monsters_by_location.erase( first_iter );
    }

    std::shared_ptr<monster> second_ptr;
    if( second_iter != monsters_by_location.end() ) {
        second_ptr = second_iter->second;
        monsters_by_location.erase( second_iter );
    }
    // implied: (first_ptr != second_ptr) or (first_ptr == nullptr && second_ptr == nullptr)

    tripoint temp = second.pos();
    second.spawn( first.pos() );
    first.spawn( temp );

    // If the pointers have been taken out of the list, put them back in.
    if( first_ptr ) {
        monsters_by_location[first.pos()] = first_ptr;
    }
    if( second_ptr ) {
        monsters_by_location[second.pos()] = second_ptr;
    }
}