Infinite skill deducts to 2^31 − 2 during replay

Started by kaywhyn, December 13, 2022, 07:31:22 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

kaywhyn

Edit Simon: Split from Physics differences between SuperLemmini and NeoLemmix




Doesn't exactly belong here, nor in the bugs topic of Lemmings behavior for Superlemmini, but I'll just post it here anyway, just because it kind of fits here even though the best place for this post would be my conversion of Deceit's Lemmings to Superlemmini and it's more of a UI thing rather than anything concerning physics differences between the engines.

Superlemmini

Something I only observed very recently from watching my replay of Mayhem 22 of Deceit's Lemmings. Easily reproducible, and that is play any level that has an infinite amount of skill(s) or edit the .ini file of a level to have an infinite amount of a skill. If you play the level and assign the skill(s) for which you have an infinite amount, it works as usual by not counting down and hence the skill still shows the infinity symbol. However, if you enter replay mode by, say, restarting the level or nuking and then clicking on restart on the post-results screen, once you use the skill(s) for which you have an infinite amount of, it will show that you have 2,147,483,646 (two billion one hundred forty seven million four hundred eighty three thousand six hundred forty six) of that skill left, meaning you essentially start with 2,147,483,647 of that skill which technically is an infinite amount as far as Lemmings levels are concerned as it's very unlikely you'll run out of it. Now, 2,147,483,646 = 2^31 - 2 according to Wolfram Alpha, and so you start with 2^31 - 1 of the infinite skill. Why this amount? I'm guessing it's just due to the amount of memory that can be stored as a 32-bit integer, but I'm not sure.

Video of Mayhem 22 replay of Deceit's Lemmings for Superlemmini: https://www.youtube.com/watch?v=1B3ID5_T2bE Also happens in SuperLemminiToo, as I expect it to.

Neolemmix

No problem here, the skill still shows the infinity symbol regardless of whether you're in replay mode or not.
https://www.youtube.com/channel/UCPMqwuqZ206rBWJrUC6wkrA - My YouTube channel and you can also find my playlists of Lemmings level packs that I have LPed
kaywhyn's blog: https://www.lemmingsforums.net/index.php?topic=5363.0

Simon

#1
Yeah, Java's int is signed 32-bit with two's complement, and has maximum positive value of 2^31 − 1, Integer.MAX_VALUE. Looks like Lemmini uses this max to denote infinity.

More eyebrow-raising than the bug itself (mistakenly deducting from the special value) is that normal play and replay exhibit different behavior here. It might be worthwhile to examine the Lemmini source for possible discrepancies between normal play and replay. Ideally, normal play and replay should share as much code as possible. A good way is to funnel all player input into an internal replay first, and then all the physics ever get to see is replays, and then let the numbers in the UI only depend on these single physics.

The good news is that I haven't heard about desynching of replays for any Lemmini. Most likely, you have a cosmetic bug here.

-- Simon

Charles

Quote from: kaywhyn on December 13, 2022, 07:31:22 AM
if you enter replay mode by, say, restarting the level or nuking and then clicking on restart on the post-results screen, once you use the skill(s) for which you have an infinite amount of, it will show that you have 2,147,483,646 (two billion one hundred forty seven million four hundred eighty three thousand six hundred forty six) of that skill left

That's a great bug find!

I can see exactly what's causing it, too. The code for decrementing the skills is different for during a replay and for when you manually click on a lemming (for no real good reason I can see...)

Manually clicking has a check to make sure the value is not already the highest integer value, and won't decrease if that's the case... the replay decrement code is missing that validation.

You can see the exact code in the GameController.java file:
Good code: https://github.com/Blazingstix/SuperLemminiToo/blob/main/src/lemmini/game/GameController.java#L1371
Bad code: https://github.com/Blazingstix/SuperLemminiToo/blob/main/src/lemmini/game/GameController.java#L1084

I'll try and update that code and publish a new version of SuperLemminiToo before Christmas.

kaywhyn

Quote from: Simon on December 13, 2022, 12:29:31 PM
Yeah, Java's int is signed 32-bit with two's complement, and has maximum positive value of 2^31 − 1, Integer.MAX_VALUE. Looks like Lemmini uses this max to denote infinity.

Thanks for confirming my guess! :thumbsup: I do know about variable declaration and declaration types, though it's been a long time since I've done any coding/programming that perhaps it's time for me to whip up Visual Studios again. Back when I was in university/college, for my math major, I was required to take a programming course. The programming language I studied in the course was C++. Because I haven't worked with it for a very long time, I have since pretty much forgotten a lot of what I learned in the course.

I took a course on Java through Code Academy earlier this year, though once again I haven't done anything with this for a while now, so perhaps it's time for me to pick up where I last left off with it. I only did a very basic program with it.

At times, I have thought about possibly helping out on the coding side of things with NL. Sometime ago, I looked at the NL source code, and it definitely looks quite overwhelming. So, it would definitely take a lot of time to scrutinize. If I'm not mistaken, I believe it's written in Delphi? I might be wrong, but I'm certain that pretty much every programming language shares some common elements, such as if-then statements of some sort. So, perhaps some of my C++ knowledge is transferable to an extent to other programming languages.

Quote from: Charles on December 14, 2022, 12:19:30 AM
Manually clicking has a check to make sure the value is not already the highest integer value, and won't decrease if that's the case... the replay decrement code is missing that validation.

You can see the exact code in the GameController.java file:
Good code: https://github.com/Blazingstix/SuperLemminiToo/blob/main/src/lemmini/game/GameController.java#L1371
Bad code: https://github.com/Blazingstix/SuperLemminiToo/blob/main/src/lemmini/game/GameController.java#L1084

Thanks for the links! :thumbsup: I have taken a look, though I honestly am not certain about what's going on in the code. For example, is the Max-Value implied to be that huge number from my post above or infinity? Or was the value for it declared somewhere in the code and I just didn't see it? Similarly, am I correct to say that -- and ++ mean -1 and +1, respectively? I think I kind of vaguely remember them meaning those from when I studied C++ back when I was in university/college all those years ago, but it's been a long time since I've done any programming/coding that I've forgotten.

Fortunately, many members here are knowledgeable with coding/programming that there's plenty to ask for assistance :thumbsup:
https://www.youtube.com/channel/UCPMqwuqZ206rBWJrUC6wkrA - My YouTube channel and you can also find my playlists of Lemmings level packs that I have LPed
kaywhyn's blog: https://www.lemmingsforums.net/index.php?topic=5363.0

Charles

Quote from: kaywhyn on December 14, 2022, 01:01:24 PM
is the Max-Value implied to be that huge number from my post above or infinity? Or was the value for it declared somewhere in the code and I just didn't see it? Similarly, am I correct to say that -- and ++ mean -1 and +1, respectively?

Yup, you've got the gist. Integer.MAX_VALUE is exactly as Simon mentioned earlier... a named literal that equals the highest value that can be represented by a 32-bit Integer. i.e. 2^32-1.  That name is built-in to Java.  SuperLemminiToo (and SuperLemmini, and presumably Lemmini before it) it coded to interpret a MAX_VALUE as meaning Infinity, and to display the UI as such.

Note, that MAX_VALUE does not inherently mean Infinity. We're just using it that way. We could just as easily check NumClimbers != (2^32-1) or NumClimbers != 2147483647. Using integer.MAX_VALUE is just more convenient, and makes for easier to read code.  There are data types that do allow you to represent actual infinity.  Like Double.NEGATIVE_INFINITY, or Double.POSITIVE_INFINITY, or even Double.NaN (Not a Number, like divide by 0).  But thsoe are only for Float types, and don't make sense for discrete values like the number of skills left.

And yup, -- is -1, and ++ is +1.  Not sure if Java allows this, but in C, x++ is different from ++x. x++ uses the x variable then increments it, whereas ++x increments it first then uses it.

Anyway, that's far enough of a tangent.  i pushed a new release to fix the bug. v1.51. It's on the stickied topic for SuperLemminiToo.