Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPC head exploded from infinite loop #30047

Closed
drhead opened this issue Apr 29, 2019 · 4 comments · Fixed by #30150
Closed

NPC head exploded from infinite loop #30047

drhead opened this issue Apr 29, 2019 · 4 comments · Fixed by #30150
Labels
<Bug> This needs to be fixed NPC / Factions NPCs, AI, Speech, Factions, Ownership

Comments

@drhead
Copy link
Contributor

drhead commented Apr 29, 2019

Describe the bug
An NPC's head exploded in my save from attempting to move.

To Reproduce
Steps to reproduce the behavior:

  1. Load save
  2. Sleep until you wake up (may or may not be important though it would be nice to recreate conditions)
  3. Move to the road in front of the southeastern most house in the nearby necropolis. You should get a head exploding message.

Expected behavior
I expect her head to not explode.

Based on the debug message, it is possible the function doesn't have proper handling for move orders which end on the same tile they start and thus don't use moves. This particular NPC does not actually move, she's a necropolis soldier and just stands there forever really.

Screenshots

Versions and configuration:

  • OS: Windows 10
  • Game Version: 0.D-2341-g1c62c69
  • Graphics version: Tiles
  • Mods loaded: dda, aftershock, vehicle additions

Additional context
Savegame:
Hesler.zip

@ifreund ifreund added <Bug> This needs to be fixed NPC / Factions NPCs, AI, Speech, Factions, Ownership labels Apr 29, 2019
@chaoticidealism
Copy link

I observed this as well. The bug I just reported, with NPCs causing extreme lag, came complete with a couple of their heads exploding--both guards at the refugee center. Didn't remember that part until I saw your report. I bet they're connected.

@ghost
Copy link

ghost commented Apr 30, 2019

hmmm. I got this
image
Seems they can handle going to a destination that is already where they are.
Not sure under what conditions your NPCs head exploded, maybe it's the z-level?? can anyone else reproduce?

@neitsa
Copy link
Contributor

neitsa commented May 2, 2019

If a NPC spends 10 moves turns without moving, then the NPC is programmed to have its brain explode 😭 . I think this was made so a NPC is not stuck forever:

Cataclysm-DDA/src/game.cpp

Lines 4229 to 4257 in 33a049e

// Now, do active NPCs.
for( npc &guy : g->all_npcs() ) {
int turns = 0;
m.creature_in_field( guy );
guy.process_turn();
while( !guy.is_dead() && !guy.in_sleep_state() && guy.moves > 0 && turns < 10 ) {
int moves = guy.moves;
guy.move();
if( moves == guy.moves ) {
// Count every time we exit npc::move() without spending any moves.
turns++;
}
// Turn on debug mode when in infinite loop
// It has to be done before the last turn, otherwise
// there will be no meaningful debug output.
if( turns == 9 ) {
debugmsg( "NPC %s entered infinite loop. Turning on debug mode",
guy.name );
debug_mode = true;
}
}
// If we spun too long trying to decide what to do (without spending moves),
// Invoke cranial detonation to prevent an infinite loop.
if( turns == 10 ) {
add_msg( _( "%s's brain explodes!" ), guy.name );
guy.die( nullptr );
}

Maybe we could check if the NPC was ordered to move to the same tile (I mean, it was ordered to move, but the destination was the same tile), which is in this case would simply state that the NPC isn't stuck at all.

At least we need a way to discriminate between "NPC is stuck" and "NPC moved in place".

@mlangsdorf
Copy link
Contributor

mlangsdorf commented May 3, 2019

I think this is the bug:

    const tripoint omt_pos = global_omt_location();
    int sx = sgn( goal.x - omt_pos.x );
    int sy = sgn( goal.y - omt_pos.y );
    const int minz = std::min( goal.z, posz() );
    const int maxz = std::max( goal.z, posz() );
    add_msg( m_debug, "%s going (%d,%d,%d)->(%d,%d,%d)", name,
             omt_pos.x, omt_pos.y, omt_pos.z, goal.x, goal.y, goal.z );
    if( goal == omt_pos ) {
        // We're at our desired map square!
        reach_omt_destination();
        return;
    }

There should be a move_pause() after reach_omt_destination() to zero out the NPC's moves and skip the infinite loop detection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
<Bug> This needs to be fixed NPC / Factions NPCs, AI, Speech, Factions, Ownership
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants