[N/A] Not all lemmings are nuked [PLAYER] [BUG]

Started by Nepster, March 28, 2016, 05:46:29 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Nepster

If you watch the official solution to Insane 16 of LP IV (attached for convenience), there is one climber coming from the left, who is not nuked together with all the other lemmings.
If one turns him into a blocker (to prevent him from exiting), his nuke countdown starts once all other lemmings are dead.

namida

#1
There isn't a bug here; at worst, there's a mechanic that should maybe be changed (but I'm not entirely sure if it should).

How the nuking works is, immediately after the nuke is activated, lemming #0 starts counting down. The next frame, lemming #1 starts counting down, and so on. If, for example, lemming #1 no longer exists (due to, in this case, exiting), it doens't immediately proceed to lemming #2, but rather, does nothing on that frame (and on the next frame, lemming #2 starts counting down). Note that this behaviour is unchanged from vanilla Lemmix.

In Insane 16, the climber you mention is lemming #191, so almost the last lemming to start counting down. Because he's isolated from the crowd at this point, it's very noticable, but there's actually nothing unusual happening here. Since a countdown for nuking lasts 85 frames, plus the 16 frames of ohnoing, this means that by the time he even starts counting down, 90 lemmings (give or take one) will have already exploded if they didn't exit before this; and likely, many more will have exited mid-countdown or even mid-ohno.

Even if the behaviour was changed to skip removed lemmings rather than having a do-nothing frame, it's likely that you'd still get a similar effect on this level due to that many more would have started counting down, but exited before they explode.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

ccexplore

Quote from: namida on March 28, 2016, 05:55:49 PMHow the nuking works is, immediately after the nuke is activated, lemming #0 starts counting down. The next frame, lemming #1 starts counting down, and so on. If, for example, lemming #1 no longer exists (due to, in this case, exiting), it doens't immediately proceed to lemming #2, but rather, does nothing on that frame (and on the next frame, lemming #2 starts counting down). Note that this behaviour is unchanged from vanilla Lemmix.

Really? :lem-shocked: If that's true then vanilla Lemmix is not emulating DOS behavior correctly.  For reference, this is what I have for the annotated disassembly of the relevant code in DOS Lemmings:

  // process nuking
  cs:2005 A04C00         mov    al,[004C]                   
  cs:2008 3A064300       cmp    al,[0043]                   
  cs:200C 742E           je     203C          // no more lemmings to nuke!
  cs:200E B92D00         mov    cx,002D                     
  cs:2011 32E4           xor    ah,ah                       
  cs:2013 F7E1           mul    cx                           
  cs:2015 058800         add    ax,0088                     
  cs:2018 8BF0           mov    si,ax                       
  // go to the n-th Lemming, where n (0 based) = [004C]
  cs:201A 807C2000       cmp    byte ptr [si+20],00         
  cs:201E 7517           jne    2037                 // don't change explosion count if already set to countdown
  cs:2020 807C26FF       cmp    byte ptr [si+26],FF  // if lemming removed already, skip to next one       
  cs:2024 7506           jne    202C                         
  cs:2026 FE064C00       inc    byte ptr [004C]             
  cs:202A EBD9           jmp    2005                         
  cs:202C F744080300     test   word ptr [si+08],0003   // if lemming is a splatterer or about to explode, don't do anything do them
  cs:2031 7504           jne    2037                         
  cs:2033 C644204F       mov    byte ptr [si+20],4F     // initialize explosion count
  cs:2037 FE064C00       inc    byte ptr [004C]             
  cs:203B C3             ret                                 
  // nuking assigns complete
  cs:203C C6064B0000     mov    byte ptr [004B],00           
  cs:2041 C606500000     mov    byte ptr [0050],00           
  cs:2046 C3             ret     


I realize not too many people can read this without consulting an x86 instruction set reference, but "skip to next one" will end up reaching the instruction at cs:202A which jumps back to the top of the code snippet.  So it should immediately proceed to the next alive one, not wait for next frame.

I'll have to dig into old emails and see if something was miscommunicated to Eric, though I find it fairly hard to believe that happened.  It's rather easy to test this behavior in DOS Lemmings and see that it doesn't just do nothing on the frames where nuke processing gets to a lemming no longer alive.

namida

Crap, looks like (in the interest of keeping the "Lemmix emulates DOS as close to perfectly as possible") I'll have to dig out the vanilla Lemmix code again and fix that up. We'll let further discussion / thinking occur on how NeoLemmix should handle such a case, but given that the current behaviour is pretty much on the "copy what Lemmix does" standard, perhaps that's a valid argument for changing NL's behaviour too.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

ccexplore

I just did a quick test in the Lemmix editor and I got the expected DOS behavior, and not the behavior described by namida.  Here's a replay for Fun 8.  First and last lemming out are made blockers, then we wait for everyone else to exit before nuking.  It clearly does not take 79 frames after the first lemming gets the explosion countdown for the other lemming to get its countdown.

ccexplore

Regardless of how Lemmix and NeoLemmix currently behaves, I think it's an easy argument that nuke should generally avoid doing nothing on a frame, especially with respect to lemmings that have already exited or died--as you pointed out, if it does nothing then you can easily wound end up with many frames where nothing seem to happen nuke-wise.  And since the final explosion is more or less a constant time offset from when the countdown starts, you'll also get a very uneven firework at the end.  Basically, it seems to clear to me that the way they handled nuking is to maximize the fireworks display at the end--it would be too brief if everyone explodes all at the same instance, but you also don't want to avoid grossly uneven rate for starting the countdowns lest there be noticeable gaps in the fireworks at the end.

namida

Okay, it appears I was understanding how it works incorrectly. After a quick look at the source code, NL too behaves as you described. So even without the oddity, the effect described in the first post still happens, as predicted:

QuoteEven if the behaviour was changed to skip removed lemmings rather than having a do-nothing frame, it's likely that you'd still get a similar effect on this level due to that many more would have started counting down, but exited before they explode.

Code (LemGame.pas 6688 (latest version in "master" branch on my repo)) Select
    while (Index_LemmingToBeNuked <{=} LemmingsReleased + LemmingsCloned)
    and (LemmingList[Index_LemmingToBeNuked].LemRemoved) do
      Inc(Index_LemmingToBeNuked);


Short of accelerating the countdowns if a mid-countdown lemming exits (very bad idea IMO), I don't think there's too much we can do about this. There's no bug here, just an expected (but easily-mistaken-for-a-bug) side effect of a large number of lemmings exiting during the countdown, combined with a nearly-last-to-spawn lemming being isolated enough that his nuke timing stands out.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

ccexplore

Since I don't have any of this set up to actually see on my computer, I'll trust that what Nepster's reporting is nothing more than what you mentioned.  It would seem to me though that if one only focuses on when each lemming starts their explosion countdown rather than when the eventual explosion may or may not happen, the start of each lemming's countdown should basically happen frame by frame.  Except as noted below there shouldn't be any long gaps where no lemming starts their explosion countdown, even if there may be stretches of time where no explosions happen.

Minor technical sidenote:  the disassembly shows there are only 3 cases (as far as vanilla Lemmix, and most likely NeoLemmix as well since there had been no reason to mess with the nuke code) where nuke explosion countdown does not start for a lemming but the game doesn't immediately look for the next lemming:
  - if the lemming already has an explosion countdown (due to assigning a bomber skill) before the one granted by nuke
  - if the lemming is splatting from a fatal fall
  - if the lemming already finishes its explosion countdown and explosion is imminent or in progress (ie. so not even for "oh-no", but past that).

Lemmings already in the middle of exiting or dying from water/hazards will still start their countdown, though of course they'll be saved/dead long before the countdown actually finish.  If they finished being saved or killed before the nuke countdown reaches them, then the "skip rule" (ie. immediately go for the next one rather than wait for next frame) applies.  And obviously lemmings who started their countdown without doing any of that, may still be saved or killed before their countdown finishes.

namida

An easy way to see a similar effect in action is using Sneaky 8 of Lemmings Plus II. Set the release rate to 99, and nuke as soon as the last lemming comes out. Here too, you'll notice the same effect - some lemmings have fully exploded at a point where some others have yet to even start counting down. The two levels have a similar number of total lemmings (Insane 16 has 200, Sneaky 8 has 250), but Sneaky 8 illustrates it much more clearly due to the very long flat beam at the start - if you RR99 right away, it's possible to have the entire crowd of 250 lemmings neatly standing in a row on it.

I confirmed the climber mentioned in the OP was lemming #191 by using the replay text file. So, I'm certian that the "bug" here is just an illusion created by the combination of the huge number of lemmings on that level, many lemmings exiting (or in some cases, splatting) mid-countdown, and the fact that a lemming near the end of the list happens to be isolated from the crowd during the start of the countdowns.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

Nepster

Yes, it seems that I just got confused due to the large number of lemmings.

On the other hand, I am no longer sure, whether it should ever take longer than 5 seconds (85 frames) for all lemmings to start their countdown? I see nuking as a colorful way to exit the level, and not as a skill to explode the lemmings in a specific order.

Consider for example a level with 500 lemmings and a save requirement of 1. Then separate the correct lemmings from the crowd and you end up with timed bombers spaced in proper intervals. Who wants to play all the bomber timing levels again, but now with nuke instead of bombers and having to select the correct lemming instead of assigning bombers at the correct places?

namida

QuoteConsider for example a level with 500 lemmings and a save requirement of 1. Then separate the correct lemmings from the crowd and you end up with timed bombers spaced in proper intervals. Who wants to play all the bomber timing levels again, but now with nuke instead of bombers and having to select the correct lemming instead of assigning bombers at the correct places?

What alternative would you propose? If we start all countdowns at once, much of the visual effect (and all practical use - which could be argued should not be there in the first place) of the nuke is lost. Trying to compress all countdown starts into 85 frames (in cases where more than 85 lemmings are present) may be tidy and quick for the user, but that's going to be complicating the code without really achieving anything useful.

The way I see it - culling a feature because it's only useful for bad level design (which could be argued for the Only On Terrain / Fake / Invisible object options, although I personally would still argue they can be used for cosmetic effect, and at any rate the latter two can be reproduced easily with customized versions of graphic sets) is one thing, but making the code more complex - and at the same time, changing a well-established feature that doesn't really have any problems, despite working the same way it did in L1 - solely for the purpose of preventing a hypothetical bad level design, really doesn't sound worthwhile.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)