Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Simon

Pages: 1 [2] 3 4 ... 281
16
SuperLemmix / Re: [FEAT] Rewind button / hotkey
« on: July 08, 2024, 04:06:35 PM »
Short answer because busy; prod me for details later.

Making saving/loading of the world faster was only 3.5 % for me woth an unclear amount, possibly more, possibly less than 3.5 % during graphical play. But I'm not sure if it's your best bet to start here. You're aiming for 1.5x or 2x, not 3.5 %.

NL creates savestates every 10 seconds. That doesn't sound frequent enough to me. Create another savestate (either one, or a leapfrogging pair) every 10 physics updates (even faster than 1 second) and replace frequently. Reason: With 10 seconds, I had noticeable lag during rewinding on larger NL maps in Wine on 2016 Intel i5-6600. The lag got better whenever timer was barely past a multiple of 10 seconds, and the lag was worst whenever timer was almost at the next multiple of 10 seconds.

NL takes longer for mass-replay verification than Lix. This suggests that you should investigate forward calculation (a.k.a. advancing physics) in NL/SuperLemmix. Reduce the amount of forward calculation (savestate more frequently) or make forward calculation itself better (unsure if that's good idea, or where to start in NL for that). Speedy rewinding requires speedy forward computation from a savestate behind the scenes unless you savestate every physics update, which you are not.

Compression improves space (RAM) but costs time (during compression and uncompression), I doubt that space is your biggest worry. I'd recommend to try something else first. You can look into compression when your strategy is to keep a truckload of savestates.

-- Simon

17
Tech & Research / Re: The Direct Drop Topic
« on: July 06, 2024, 09:13:26 PM »
The compelling factor is contact with the trigger, then, rather than lem state or exit position.

Floaters enter the exit trigger from above, too. ;P Anyway, you wrote that floaters are special and we shouldn't care about them here, that's good with me.

You also wrote that you're interested in fallers and splatters only. That's good enough for the research: When a faller can enter without splatting, you get midair direct drop. When a faller-to-splatter or a splatter outright can exit, you get grounded direct drop.

Thanks for showing the Amiga floaters.

-- Simon

18
Tech & Research / Re: The Direct Drop Topic
« on: July 06, 2024, 11:40:14 AM »
they solved a level using a text editor! :forehead:

I solved it in my head, then wrote a script to generate an NL replay for it, then verified in NL that the replay was a solution, then submitted the replay and the script.

DOS Lemmings 1
unintentionally, as a bi-product of incorrectly handled physics.
I unfortunately wasn't around for a lot of the early Forum discussion

I'm investigating engine behavior, not classifying it as bug. You started a nice table, and I'd be happy to see more entries filled. I'm criticizing your table for distinguishing the wrong things.



This is from DOS Lemmings 1, and clearly we can enter midair exits. Your table says that we cannot directly drop into midair exits in DOS Lemmings 1. I recommend that you distinguish by activity of the lemming, not by groundedness of the exit nor of the lemming.

It may help you to define direct drop in the first place. You've said "it's basically this" and posted an example gif. Fallers don't exit in DOS L1 even when the exit is grounded, they must start splatting first, yet you say that DOS L1 has direct drop for grounded exits. Floaters enter midair exits, yet you say that DOS L1 has no midair direct drop. What is direct drop?

Do you have an Amiga or emulator ready to run Amiga Lemmings 1? What happens when floaters pass a midair exit on Amiga L1?

-- Simon

19
Today, I've improved replay verification runtime once more by 13 percent. This is unexpectedly good, I didn't want to believe it, and I spent 2 hours to isolate the reason.

The culprit was the code that tests whether lix should exit. This code runs for every lix alive, during every physics update. The old code was:

if the outside world generally allows lix to exit because we aren't nuking
    and this lix has encountered an exit during movement
    and this lix' activity allows to become exiter
    then loop through all exits, give points ...

The new code changes the order of the questions to:
  • Have we encountered exits earlier during this physics update?
  • Does our activity allow us to become exiter?
  • Is it generally allowed to exit because we aren't nuking?
Asking for encountered exits first has two desirable qualities:
  • It's usually false. The logic can short-circuit, i.e., we can skip the remainig questions.
  • It's fast. The lix stores her encounters in a small bitfield. We test one bit inside the lix.
Asking the outside world for general exit allowance is the complete opposite: We're usually allowed to exit (rarely are we nuking) and asking the outside world is expensive here. This code runs once per lix per physics update, thus the hot memory is the lix's own memory. Asking the outside world follows a pointer to not-so-hot memory, and we compute the answer (are we nuking) from several properties of the player teams.

Reordering three lines brought a whopping 13 percent speed improvement during mass replay verification. This means 13 percent of the entire workload -- which includes file loading, terrain rendering, ... I'm sure it will be useful during graphical play, too, especially when we compute several physics updates behind the scenes during networking games or during singleplayer framestepping.



There is treasure everywhere!

Nonetheless, I don't want to believe it still. 13 percent sounds too good. I'll have to playtest this experimental build in a networking session first.

-- Simon

20
Tech & Research / Re: The Direct Drop Topic
« on: July 04, 2024, 06:57:33 AM »
This is really 3 topics rolled into one: Physics research across engines, interpretation across engines, and design of SuperLemmix. I'll focus on the research here.

The distinction between mid-air exiting and grounded exiting isn't perfect. It's better to distinguish
  • by lemming activity first,
  • possibly by activity transition if research points us to it,
  • and only by lemming groundedness if we can't explain it purely by activity.
Reason: In DOS Lemmings 1, the knowledge is that fallers don't exit, splatters don't exit, but fallers-turning-into-splatters may exit during this exact physics update. The groundedness is irrelevant for exiting; it merely prompted the faller to splat. Strictly, this irrelevance of groundedness is unverifiable by experiment; Occham's razor tells us to consider it irrelevant until we know better. At the very least, the groundedness wouldn't allow splatters to exit either after the splatter has missed his one-frame chance to exit.

More activities of interest:
  • Floating. IIRC, floaters in DOS Lemmings 1 exit in mid-air outright. The devs prevented fallers from exiting, but not floaters. NL behaves the same, floaters exit mid-air, but fallers don't. What do floaters in Amiga L1 do?
  • Climbing. DOS Lemmings 1 climbers are inside the wall, thus grounded (which I claim irrelevant), but otherwise similar to floaters (can't assign most skills). Can they exit mid-climb? I expect that climbers can indeed exit in DOS Lemmings 1.
  • Drowning lemmings after they have started to drown. In DOS, they don't exit. But they move. On which engines can you drift horizontally into an exit as you drown?
  • Drowning lemmings exactly during transition from falling to drowning. This will be interesting in DOS Lemmings 1: Like faller-to-splatter, it's a transition between two un-exitable activities, and we already know that faller-to-splatter may exit.
  • Burning lemmings, exactly during transition.
  • Theoretically, one can investigate hoisters, blockers, ..., but I feel that that these provide bonus knowledge only. They're not as crucial when you want to apply the knowledge later to interpretation or design. They're also harder to test, e.g., in DOS Lemmings 1, you'll have to move an exit trigger area onto a blocker via a falling oh-noer.
-- Simon

21
Lix Main / Performance of Rewinding and of Mass Replay Verification
« on: July 03, 2024, 01:24:28 AM »
Hi,

after Mindless released Golems on the forums here, he posted his ideas about what to include in a savestate, what to compress, ... I got inspired to investigate Lix rewinding performance. Over several evenings, I've finished the following three improvements:
  • Savestate only the mutable half of the world
  • Choose graphical frames of hatches/exits/... only when drawing
  • Refactor away from overuse of shared pointer to world
1. Mutable Half: The world in Lix consists of terrain, players, their lix, hatches, exits, traps, ..., and I used to keep everything in savestates. But some parts of the world never change: Water never changes. Fire hazards never change. An exit has some state (e.g., ownership, the red player gets points) but this state never changes during play. The initial value of the overtime never changes.

I've separated the world into a mutable half (land, lix, triggered traps, ...) and an immutable half (hatches, exits, water, ...). I copy only the mutable half into savestates. When I load a savestate, I attach the loaded mutable half to the existing immutable half, and that's the new world. This makes the savestates smaller in memory and reduces allocations. Each gadget (hatch, exit, trap, ...) is a heap-allocated class object. To track one in a savestate, we must deep-copy it, and it helps when we only have to save some of the gadgets, not all.

The name "half" is euphemistic. The mutable half is still the lion's share with the uncompressed land bitmap, the physics map, ..., and I didn't look into compression.

2. Graphical Frames: Ostensibly, exits still change over time because they animate. This animation has no bearing on physics, which is a strong argument to keep the exit in the immutable half of the world. But if the exit never changes, it can't keep track of its current animation frame.

The solution: During drawing, I tell the exit the current tick (physics update number) and the exit computes its animation frame from first principles. The drawing method ferries the arguments the to the exit.

Instead of incrementing the frame each tick and resetting the frame after reaching the end, we compute the modulus tick % animationLength. Naively, taking the modulus of integers is slower than adding and comparing integers. But there are performance benefits: We track less state in the exit now, which makes the exit smaller in memory by itself, and it makes all savestates smaller because exits can now be in the immutable half of the world.

Most importantly, non-drawing physics updates don't have to compute animation frames for exits anymore. When we aren't going to draw the results of some physics updates, we've saved many virtual method calls: One virtual call per gadget per update.

After all, we have our direst need for performance during singleplayer rewinding, during networked games with many players, and during mass replay verification. All three cases compute several (or all) physics updates behind the scenes. E.g., rewinding loads a savestate that is older than the target tick, then updates physics forward from the savestate until we're at the target tick.

3. Ditch Shared Pointer: A shared pointer to the world means two levels of indirection:
  • Usercode holds a shared pointer by value.
  • Each shared pointer points to the single reference-counting storage.
  • The reference-counting storage points points to the payload.
Compare this with unique resource handling (one indirection) or putting the world struct by value inside your world-handling code (direct access for the holder, and still one indirection for other parts of the physics).

In 2016, when I wrote D Lix, I chose the shared pointer for all holdings of worlds (the current world and for the savestated worlds) because I wanted easy savestating. The same world could appear several times in the savestating cache. I used the same type (shared pointer to world struct) everywhere. The problem was in the current world, which was also a shared pointer to a world struct. All physics that referenced the world (instead of, e.g., only the lix at hand) had to dereference the shared world pointer many times over.

Solution: Now, I hold the current world by value. After all, the world struct is less than 300 bytes; there is a lot of indirection in the world by itself already.

Sidetracking: I've also removed the shared pointers from the savestating cache. That wasn't necessary to change; it wouldn't have mattered for performance here. For now, I've resorted to manual management of copying/disposing between the current world and the savestates. To do what I really wanted, I need move semantics. D supports C++03-style RAII, but not yet the value-type-based rule-of-five resource handling that became popular with C++11. I want to write my program in the mathematical union of all the programming languages.



Overall Benefit

Mass replay verification is 3.5 percent faster. The 1077 replays from the replay collection take 18.9 seconds on my Intel i5-6600 3.30 GHz. Before, in the stable Lix 0.10.24, they took 19.6 seconds.

It can't be from the smaller savestates because mass replay verification doesn't generate savestates. It must be either from holding the current world by value or from from skipping graphical frame calculations and avoiding their virtual calls. I can't tell which of the two improvements it is, I have only measured all three optimizations together.

During singleplayer, I've kept the full 60 fps more often during hard rewinds when Lix 0.10.24 would dent to 55 or 50 fps. This is hard to quantify because it depends on the level. It's also hard to guess which of the three optimizations played the biggest role here. The bottom line is: The benefit is at least measurable during graphical play.

We'll see if and how much it helps in practice, after I release this in Lix 0.10.25. :lix-smile:

-- Simon

22
In that light, ditch the belly check.

Ditching the belly check is better, in at least 3 ways, than reintroducing direct drop.
  • It's way more popular.
  • It breaks fewer levels. Direct drop lures designers into offering backroutes.
  • It's not an outright bug in the first place, unlike exits accepting dying* lemmings.
*: At least splatters. I don't know DOS Lemmings 1 exiting behavior of drowners, or of burners, or of already-exploded lemmings. (These already-exploded lemmings are invisible and offset diagonally from their exploding position. They go away after the debris has finished raining. We know about their existence because the cursor opens over them. Their purpose seems to be to prevent the game from exiting to postview after losing all lemmings).

<SimonN> Mindless: In DOS Lemmings 1, exits accept splatters ("direct drop"). Do they accept drowners? Do they accept already-exploded lemmings (they're offset diagonally)?
<SimonN> I can test the exploded lemmings myself in L1. I don't have a test level for drowners.
<Mindless> Drowners and exploders do not exit.
<Mindless> *Technically* splatters do not exit either.  The faller becomes a splatter and then becomes an exiter in the same frame.  Once it has started splatting, it would not exit if the exit suddenly came into existence behind it.


-- Simon

23

^^^Much more arbitrary - why did the lem stop building here*??

I call this the belly check. This came early in NL. Prod namida for the full rationale.

I've never liked the belly check, either. I haven't argued much about it. Icho would defend it for content preservation: When you remove the belly check, you potentially open backroutes, and, nastily, this backroute potential affects practically every NL pack because NL gained the belly check so early. It wouldn't matter then that the backroute potential is weak per level.

I don't have a good argument against the belly check other than how nasty the belly check feels, and that feeling may well come from early conditioning from playing L1.

Quote from: ericderkovits
I remember also discussing this with Simon about Genesis' Lemmings Ark.

Right, the possible solutions to Lemmings Ark differ between NL physics and Genesis physics. The solutions differed enough that I decided to solve Lemmings Ark twice, once in NL, once in vanilla Lemmix.

Spoiler to Lemmings Ark (click to show/hide)

24
Lix Main / Re: Lix 0.10.24 released
« on: June 24, 2024, 09:50:43 AM »
Lix 0.10.24 released.
  • Shorten and easen Pipe Dream. It's now a better second introductory level.
  • Change the author in Proxima's levels to Proxima. Existing checkmarks convert automatically whenever Proxima is the only author. Existing checkmarks become "?!" for Proxima's co-authored levels.
  • Remove pack descriptions (_english.X.txt and _german.X.txt) from the level tree. Lix has never displayed them since 2016.
  • Draw cyan trigger area rectangles one pixel lower. They now look like they match the lix's lowermost foot pixel. As before, cyan trigger area rectangles appear in the editor and during play when you activate the splat ruler.
  • Many internal refactorings, e.g., to prepare multiple spritesheets for future physics changes.


-- Simon

25
Session is over! Thanks for playing.

Recording will remain for 14 days at:
https://www.twitch.tv/simonnaar

-- Simon

26
In hindsight, this is such a natural feature. Well done implementing it first!

In August 2023, I wrote about such a feature in Implement Rewind to Last Assignment Like NL. I haven't gotten around to do it. Did you have new insights in the meantime?

What's your opinion about the exact physics update to which to jump? There are three candidates:
  • two updates before we see the assignment's effect, i.e., what kaywhyn wants and NL does.
  • the update before we see the assignment's effect, i.e., what Lix 0.10.23 and Loap do.
  • the update on which we see the assignment's effect.
Hard to say what's good. #1 feels unnatural during design, but kaywhyn likes it best. #2 feels logical during design, but it isn't necessarily the best. #3 has the advantage that we can use regular assignment highlighting to show what's going on, but we can't airclick anymore to erase the assignment.

-- Simon

27
Lix Levels / Re: Newbie feedback about early Lix singleplayer
« on: June 17, 2024, 08:25:30 PM »
Thanks to both of you for watching that part of my stream and giving your feedback. We now give 25 builders, 0 platformers, 25 bashers. We need 3 to pass. That current Pipe Dream on Github, I'll merge it into Lix 0.10.24.

We have tutorial puzzles, but I don't advertize those.

geoo is envisioning the mixed approach where a game teaches itself without calling it a tutorial outright, and without making it feel like a dedicated tutorial. Lovely has several facets of that, but isn't designed from the ground up as that. I can't tell how far off it is, I'll continue to let you know about the rough edges as I find them.

Other than sanding the rough edges, I'm open to redesigns, radical or minor. I merely won't spearhead such a modern tutorial rank (self-teaching puzzles, implicit tutorial) myself this year.

-- Simon

28
Lix Levels / Re: Simon streamed Lix puzzles, Sun, 2024-06-16
« on: June 16, 2024, 09:10:35 PM »
Stream is over! Recording will remain for 14 days at: https://www.twitch.tv/simonnaar

Played geoo's Crafty rank.

Full Circle: Not solved yet. Progress on all fronts, but no unifying theory of the universe.

Day Care Center: Funky idea, with some difficult-to-find timings. Solution feels intended, and I can't see how to improve the fickle execution. I like it, but one has to be in the mood for pixel pushing and for haggling over timings on the level of individual physics updates.

Undercut: Lovely! Feels completely intended. Armani found one of the core ingredients in chat.

Cellar Dwellers: Cute. I believe I solved this before, when it was in the Wrappy rank, and you re-sorted it.

Construction Site Conuntrum: Looked easier than it was. I had a precise solution that feels like a backroute, but it wasn't annoying to find.

29
Lix Levels / Re: Newbie feedback about early Lix singleplayer
« on: June 15, 2024, 06:14:04 PM »
Thanks for taking this seriously and choosing to fix it from the ground up. I'll look at your level in detail tonight.

Yes, I'll mass-change the author field in your levels to "Proxima" without quotes.

Also, I'll write some code in Lix itself such that, whenever Lix loads existing checkmarks from user/trophies.sdl, the checkmarks of your levels change their author to "Proxima", too. Reason: Lix saves the three following fields per checkmark, and later, to match a checkmark to a level, requires that all three of the following are identical:
  • The basename of the level file, i.e., the part of the level filename that comes after the directories and slashes,
  • the level title,
  • the level author.
When I auto-adapt the checkmarks according to this author change, we can rename the author in your levels and people still keep the checkmarks.

The directory isn't in the above list. You can always move levels between directories and the checkmarks will come with them.

-- Simon

30
Lemmings Main / Re: How to play Lemmings (1991) on a modern PC
« on: June 15, 2024, 02:35:23 PM »
Thanks.

I agree that it's good to keep everything on one page. If it's too long, we should shorten the entries instead of splitting the post.

How-to-install shouldn't be hidden behind spoiler tags. Instead, for every engine, how-to-install should become a numbered list. Reason: Picking the easiest-to-install is an excellent heuristic for the newbie. We're onboarding new people; getting the L1 levels to run ASAP is the goal.

The other nice things are secondary to ease of installation. All of the following are interesting and should appear unhidden, but should be succinct: Convenience tools, how close the physics are to DOS/Amiga L1, how popular the engine is, what custom culture it supports.

-- Simon

Pages: 1 [2] 3 4 ... 281