Don't exit on losing all lemmings (feature development)

Started by Simon, January 10, 2024, 11:42:06 AM

Previous topic - Next topic

0 Members and 5 Guests are viewing this topic.

Simon

Quote from: namida on February 14, 2024, 07:36:00 PM
LemGame refuse to run the update routine if all:
1. 2. 3.

Yes, for the freeze, this is a good approach, and it doesn't need messaging nor extra state tracking.

Quote from: WillLem
That's 38 characters, the panel allows 45.

Sounds doable, yes.

When you overwrite this status panel, you can't display its usual values. Most values have become irrelevant by here (we know that 0 lemmings are in hatch, 0 lemmings are in level), but I like to look at by how many lemmings we fell short of the save requirement. I'd nudge you to still show this (how many more to save) at all times.

Maybe we want the time limit here, too, but I have no experience. The time limit doesn't sound as important to show (i.e., by how much we fell short of the save requirement feels more important). Or ditch half of the message, only show "skip back or restart", or "rewind or restart", or ...

In a pinch, if you don't show a value, we can rewind 1 or more ticks to view the regular panel.

Quote from: WillLemWhich nuances will determine how the re-write looks.
option to unpause the game and continue into the "no lems" state
need more community feedback

Right; others, please join the discussion.

-- Simon

WillLem

Quote from: namida on February 14, 2024, 07:36:00 PM
You could achieve what Simon is talking about by simply having LemGame refuse to run the update routine

Quote from: namida on February 14, 2024, 07:36:00 PM
Specific places I would look for bugs with this implementation

All good shouts, thanks. I'll take a look at it over the weekend.

Quote from: Simon on February 15, 2024, 04:34:31 AM
When you overwrite this status panel, you can't display its usual values ... I'd nudge you to still show this (how many more to save) at all times.

Essentially, the entire display would have be re-written for this particular instance. It's worth it though, because it would be relatively easy to manage and may come in handy for other game features as well. Also, since it's in the area of the screen that the player relies on for information, it keeps things consistent.

If you still want to display level information - OK, the message could be shrunk to something like:

"NO LEMS - BACKSKIP OR RESTART"

That's 29 characters, leaving 16 for any other info we need to display. But, if "how many more need to be saved" is the only crucial piece here, maybe we could have something like:

"NO LEMS LEFT! XXX NEEDED! BACKSKIP OR RESTART"

That uses all 45 characters and accounts for levels with lem counts in 3 digits (since 500 is the official NL limit, we don't need to account for 4 digits - we could also hard-code the display message to allow a maximum of 999 anyway).

WillLem

OK, after some thought, it seems the best way to approach showing a message is to display it in the play area of the screen rather than on the panel.

The panel display is simply not meant to be messed with; a repurposing attempt very quickly gets messy and invites re-writing of some parts of the panel code - not worth it for such an incidental feature, particularly when we take into account that players may want to still have access to some or all of the panel's information.

For this particular feature, it seems best to make a simple .png graphic with the necessary text written in, and then load it and display it when relevant. Directly above the panel seems like the best place, but centre or top of screen could also work. Here's a mockup to show how this might look:



The image will then be displayed for the duration of the "no lems" state, and will disappear if the player backskips/restarts to a playable state.

Using a .png to display the message has the added benefit of being something that the user can customise themselves - we could make multilingual versions of the message available, and if the player doesn't want it then it can just be replaced with a blank image (making it optional is also a possibility).

I'm still working on integrating this into the codebase with a minimum of impact. Ideally, we don't want this feature to piggyback on any other rendering elements (panel, shadows, helpers, etc) where it could cause bugs/issues; a unique procedure within GameWindow seems most appropriate.




Meanwhile, I've figured out how to allow the game to be unpaused into the unplayable state (should the player wish to do this for any reason) whilst retaining the ability to re-pause if the game is backskipped and another (or the same) "no lems" situation arises again.

With this is mind, do we still want to freeze physics and not allow any player input other than backstep or restart?

Feedback needed before I can progress much further with this.

Simon

Thanks for the mockup!

When this message appears, will the main map (where we play the level) jump up by the height of the message? Or do you overlay it onto the main map? Map resizing can be nasty (when to do it, lots of corner cases, violates assumptions in existing code, ...) but we aren't actively playing here, nor aiming the cursor at anything.

I agree that such extra text is better than cramming it into the panel, where it would complicate the code only to hide panel stats.

I still believe that the full freeze is the best, and I accept the inability to view future zombie behavior here. Regarding zombies, you don't worsen in comparison to existing NL, which quits here. Technically, you still accept lots of player input, e.g., skill changes, load savestate, load replays, ..., but you're right that the only useful reactions are rewind, restart, or manual quit.

Still, I, too, am interested in others' opinions. I'm biased: Lix is the only Lemmings-like that doesn't quit, and I designed the freeze for Lix, and I play it often, and I like it, and I've developed playing patterns (aggressive fast-forwarding) that rely on the freeze and take it for granted. I talked with geoo about it, and he understands how NL's quit annoys me, but the quit annoys me more than the quit annoys him. Darkshoxx played NL and was surprised (in a bad way) from the quit. Looks like he didn't expect the powerful NL to still quit here like ancient L1. But that's not an argument for the freeze in particular, only against the quit.

I'll playtest your experimental today.

-- Simon

WillLem

Quote from: Simon on February 18, 2024, 11:58:31 AM
I still believe that the full freeze is the best, and I accept the inability to view future zombie behavior here. Regarding zombies, you don't worsen in comparison to existing NL, which quits here. Technically, you still accept lots of player input, e.g., skill changes, load savestate, load replays, ..., but you're right that the only useful reactions are rewind, restart, or manual quit.

Advantages for freeze: it's impossible to overshoot into the unplayable state

Advantages for pause: it doesn't look like a bug, the player knows what to do when the game is paused so a display message is not necessary, the player can explore the unplayable state if they wish to do so

Physics freeze will require significantly more overhauling of the codebase, including writing a new procedure to display the necessary message (which, as I imagine it, would simply be overlayed onto the play area); we should be absolutely sure it's what we want before we proceed any further with it.

Test put the pause behaviour and see if it's adequate. It may be easier and less problematic to simply disallow fast-forward or forwards skipping once there are no lems left - this would combine all advantages into one feature :)

Simon

Quote from: WillLem on February 18, 2024, 01:21:12 PM
Test put the pause behaviour and see if it's adequate.

The first observation of it: The pause allows stepping into dead state, but turns even a 10-second skip into a 1-tick advance. This limits the overshooting. If I hold the 10-second skip and am 3 real-time seconds late with realizing the dead state, I've stepped ~180 ticks into the dead state, not 3*10*17 ticks. That's reasonably quick to undo with 1-second rewind.

This is solid anti-rage already, nice.

I'll play some contest levels tonight. Will see how it holds on big levels that have worse framestepping performance than the small test level. More feedback tomorrow.

Whether it's good for a release, I can't advise; I don't mind much that the 10-second skip eventually turns into a 1-tick advance, but it obviously breaks the 10-second skip's (unimportant?) promise.

-- Simon

WillLem

#36
Quote from: Simon on February 18, 2024, 02:22:20 PM
This is solid anti-rage already, nice.
...
I don't mind much that the 10-second skip eventually turns into a 1-tick advance, but it obviously breaks the 10-second skip's (unimportant?) promise.

Glad to have your approval. I've uploaded an update to the Exp this evening which prevents forward-skipping into the unplayable state at all (whilst retaining pause behaviour). It works nicely, prevents overshooting and is minimum impact on the existing codebase. Also, we arguably don't need to display a message because it's very clear what's happened.

With that said, I'll still work on getting a message displayed because it'll be good to learn how to do that sort of thing anyway, and I'll also get a version together with a full physics freeze so that we can test that behaviour as well. This will likely take longer though, later in the week I'd expect.




The attachment includes all relevant project files to date.

WillLem

Well, the message alert is proving to be the most difficult element to this feature so far.

I can overlay the panel (no good for reasons already discussed), plonk it somewhere on the playable area (no good, because it might be off-screen) or replace the cursor in a similar fashion to the splat ruler (yikes!).

Anything other than that involves creating a new canvas just for the sake of displaying this message, which seems way over the top, and adds further rendering load, which is generally not a good thing in this program.

The only reasonable place to display the message, using existing logic, is where the minimap would normally be. I didn't want to piggyback like this originally, but it actually seems like quite an elegant solution - it keeps the message completely away from both the playable area and the panel information.

Thoughts?


Simon

Feedback from yesterday's V1 testing on levels from Contest 29: No problems on large maps either. If NL never released again, I could imagine always playing this V1 in the future without raging over surprise quits. My settings are: When no lemmings remain, exit if level is solved; otherwise, pause.

Those small elegance questions remain (does it look like a hack, do people like it, are people confused by lack of fast-forward or held-down skip buttons, etc.). They don't need answers yet because you'll have more testing first, and namida isn't yet going to pull V1 into the mainline.

I'll see when I find time to test the experimental V2.

Quote from: WillLemI can overlay the panel (no good for reasons already discussed), plonk it somewhere on the playable area (no good, because it might be off-screen) or replace the cursor in a similar fashion to the splat ruler (yikes!).

All of these ideas: I agree that printing into the minimap is better than those ideas.

I don't see any big downsides for printing into the minimap. The minimap is always there, regardless of user options. Minor design questions arise, e.g., can you still scroll with it during the message?

To stick the message into a side/corner of the camera where it can't scroll away: This was my hunch, but it sounds like it's too hard to fit on top of existing drawing. In Lix, after Dave4's replay-cancelling confusion, I bit the bullet and invested all the extra work to print occasional text into a corner of the camera.

-- Simon

WillLem

Success!

After much deliberation and failed attempts, I've figured out how to draw a message to the minimap area. The method basically involves replacing the viewport rectangle with a .png image - no hackish shunting of the minimap itself, the message is simply displayed over the top of the existing minimap:



The same logic can also theoretically be used to display other messages in the minimap area. However, I'd probably caution against overuse of this feature, since whenever a message is being displayed, we lose use of the minimap. It should only really be used in very exceptional circumstances (such as unplayable states).

Anyway, I've now uploaded two new versions of the 12.13 experimental, called "PauseVersion" and "FreezeVersion" - both versions make use of the minimap message, but the Pause version pauses the game and the Freeze version performs a Lix-style physics freeze. See the exp topic for more info and to give each version a test-run.

Proxima

Very nice. The only thing I'd like to say at this point is, maybe it's not the best to use a word that's unique to NL like "backskip"? Sure, it's easy for an English speaker to work out what it means, but it is a little bit less friendly to newcomers (not all of whom will be native English speakers), which seems wrong when newcomer-friendliness was the main point of this feature in the first place. Would "rewind" be a better substitute?

WillLem

Quote from: Proxima on February 23, 2024, 04:21:56 PM
Would "rewind" be a better substitute?

Happy to change the wording to whatever people agree on.

"Rewind" is OK, but since NeoLemmix doesn't have an explicit "Rewind" feature (i.e. it's done by performing multiple backwards frame skips), this could be confusing: players may look for a "Rewind" button on the panel (they'd find one in SLX ;P).

For this reason, I ended up preferring "Backskip". But, I can absolutely see how this might be similarly confusing to anyone who isn't yet familiar with this feature, or whose first language isn't English.

Rewind probably is better.

Thoughts? Suggestions?

Simon

Rewind is a good term for this; it doesn't clash with anything in NL. I've started to use "rewind" consistently in Lix, too.

Attempting to shoehorn it for SLX: You'll have one-shot rewinds (during pause) and a continuous rewind mode.

Stepping 1 tick forward is still called "skip" in the Lix code, but it doesn't skip anything; in the English translation, I think I've started to call it a step. The 10-second skip is a skip. Similarly, stepping 1 tick backwards is more a backstep than a backskip. If you call it "backstep" or "backskip", I think it's still easy enough for non-native English speakers to guess that it is the rewind; reason: "back" is elementary vocabulary.

I'll see if I find time tomorrow to test your full freeze. If not, you'll have to wait for next Wednesday. Thanks for putting in all that hard work!

-- Simon

Simon

First test results of your experimental NL 12.13 freeze version:

Out of habit, I placed only the executable in my existing NL dir and forgot the images (for the in-game messages during the freeze). NL works well until it finally wants to show the message. This produces many exceptions as one popup each, and the level continues to run and produce more exception popups even before I close the earlier popups. NL was hard to kill from the command line (impossible to type xkill or killall -s 9) because the popups stole focus (many times per second). Mouse worked, but NL has no X button to close the window. It managed to write a total of 7,000 lines into the log until I managed to close NL.

To close NL, eventually I thought of Alt+F4, and that worked. I believe that another solution would have been: Ctrl+Shift+F2 to switch to non-GUI Linux command line, kill NL from there, Ctrl+Shift+F1 to switch back to desktop.

Okay, in hindsight, the popups are practically unrelated to the freeze feature; if we want to do anything at all about this, we should first file those repeated exception popups (1 popup is enough) as a bug against the general resource loading. By the way, I'm happy that NL loads the things lazily, to start up more quickly. Nice.

I took the lo-res and the hi-res image from the zip into the NL tree, and that fixed the exceptions.




Now back to the freeze.

Yes, it prevents any physics advances consistently.

It appears impossible to bypass the freeze. I tried to fast-forward, to unpause, and to framestep forward. Nothing bypasses, nice. Not even when I rewound ~3 frames to before the freeze, then tapped or held the 10-second skip, NL would ever advance beyond the freeze.

The freeze appears to happen 1 tick too late. Example: I see the lemming in tick n. Then it falls out of the level, dies, and is not visibile anymore in tick n + 1. The lemming count in tick n + 1 is red and shows 0, correct. Nonetheless, I can now still advance to tick n + 2 before your message appears. The late freeze is mostly cosmetical, it doesn't break my play patterns. It merely makes me wonder why it overshoots.

Nuking brings an interesting design problem. The nuke generates 5-second countdowns, and you might run into the freeze (because you lost all normal lemmings and all neutrals), but there are still unnuked zombies (with countdowns from your nuke). This freezes, but it doesn't exit. Is this intended? Do I want this myself? (Haven't made up my mind w.r.t. nuke solutions.) Would others want this?

Ah, a nuked level in general freezes now (when everybody has exploded and even if no zombies exist), and doesn't exit. I believe it should exit, as it did in your pause experimental. Or do you have a new reason to freeze here?

-- Simon

WillLem

Quote from: Simon on March 02, 2024, 04:53:51 PM
Out of habit, I placed only the executable in my existing NL dir and forgot the images (for the in-game messages during the freeze). NL works well until it finally wants to show the message. This produces many exceptions as one popup each

Since the images are loaded when needed, they'll need their own exception handling in the event of an unsuccessful load; I'll get on this.

Quote from: Simon on March 02, 2024, 04:53:51 PM
The freeze appears to happen 1 tick too late ... The late freeze is mostly cosmetical, it doesn't break my play patterns. It merely makes me wonder why it overshoots.

First thought: if it ain't broke, don't fix it ;P

Second thought: OK, I can probably figure out why this is happening. I'll have a look later. Question, though: was anything else happening besides the lemmings falling offscreen? Any trap animations it needed to wait for?

Quote from: Simon on March 02, 2024, 04:53:51 PM
Ah, a nuked level in general freezes now (when everybody has exploded and even if no zombies exist), and doesn't exit. I believe it should exit, as it did in your pause experimental. Or do you have a new reason to freeze here?

No, this is a bug resulting from the more simplistic freeze code (which simply prevents the game updating when stuff returns true); I'll need to add a check for the nuke specifically here. The pause, whilst more complex in that it needs to allow more user input, necessarily makes use of existing checks (including nuke) whilst the game determines if it's finished or not.




EDIT: Please see this poll.