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 ... 250
Dullstar, I haven't heard from anybody else with a Mac. Is it time you dust off yours? >_>

In #431 are my first ideas to start debugging; if you're fine with github, we can continue to post stuff right in that github bug.

-- Simon

The zooming behavior is so aggravating that, several times now, I stopped playing NL before I wanted. And I don't understand how everybody else apparently doesn't care and happily plays on. Either everybody else is so thick not to notice any problem, or, more likely, subconciously avoids the nasty zooming even for precision work and just crawls into the screen really close.

Rule: Zooming must preserve mouse-on-land* and mouse-on-canvas.

This rule should apply even at the cost of not shifting all the land into view, i.e., the canvas should allow some land to remain out of view even when there is still void visible. Both Lix and NL fail this extended requirement. I should improve it in Lix.

Anyway, NL fails the rule even when the canvas is filled with land, and no void is visible. Please fix NL to follow the rule at least for when the canvas is filled entirely with land both before and after the zooming operation.

(*) There is a fun special case for the rule when the mouse points into the void, not onto the land. We should probably clamp the mouse-on-void coordinates then to get mouse-on-land coordinates, and preserve the clamped coordinates. This is hard to describe, and it's not necessary to understand yet because I'm mainly concerned with NL's zooming behavior when the entire canvas is filled with land, i.e., when no void is visible at all.

-- Simon

It's a title bar in the Curve theme from Xfce 4 on Linux. No particular settings for VLC.

Dekstop stuff must be reasonably dark, moderately small, completely static (buttons or scrollbars shall not roll in and out) and overall nonintrusive.

-- Simon

More research: Zooming-in never zooms onto the cursor unless the cursor is exactly in the middle of the canvas. Let's ignore this special case. (Reason for ignoring this: In general, any two linear maps agree at one point.)

Zooming-in seems to look at where the mouse is on the canvas, threating the position as a relative location of a point (mouse) on a rectangle (canvas), finding the corresponding relative location on the land (which doesn't even have the same aspect ratio), and zooming onto that point of the land.

As a result, when you don't move the mouse and repeatedly zoom-in, zoom-out, zoom-in, zoom-out, ..., you'll end up in one of the four corners of the level, depending on the quadrant of the canvas where your mouse was.

-- Simon

Lix Main / Basher Walks into Terrain
« on: February 06, 2023, 06:00:41 AM »
A basher oddity found by Icho during multiplayer in Lix 0.10.5. Thanks! Here's a reduced example level.

Rule 1: Bashers walk forward during some frames in their cycle. This forward movement is allowed to enter terrain, i.e., the basher's foot is allowed to move into and through terrain.

Reasoning behind rule 1: Either the basher's swing removed all terrain here, therefore we won't walk into earth anyway. Or the basher hit steel, immediately stopped bashing, and won't walk forward.

Rule 2: During the walk forward, bashers lower themselves into holes. Bashers never gain height.

Reasoning behind rule 2: We removed all terrain onto which we might step upwards, or cancelled on steel in the way. Either way, there is no need for the basher to ever rise. But the basher may try to walk over holes, and the basher should certainly fall into such holes if they're deep enough. If the holes are shallow, it's okay for the basher to continue; shallow holes shouldn't break mental pathfinding.

As a result of rules 1 and 2 combined, the attached level Basher Walks into Terrain is solvable (saves 1 of 2, using 1 cuber, 1 basher, and a few jumpers to position the cuber and basher). The thin white line is steel.

The most noticeable effect here is that we can clip through a particular arrangement of steel.

The second effect is that a basher falls through an arrangement through which a following crowd would not fall. The non-falling crowd alerted Icho in the first place.

I don't have a good solution.
-- Simon

Contests / Re: Level Design Contest #27 - Playing Phase (Discussion Topic)
« on: February 05, 2023, 02:52:33 PM »
Lemmings are Beans (click to show/hide)
Natural Born v3 (click to show/hide)
Splash or Splat (click to show/hide)
Stop Blowing Up v3 (click to show/hide)
Swim Team Rush v3 (click to show/hide)
Tomb of Doom v2 (click to show/hide)

-- Simon

Contests / Re: Level Design Contest #27 - Playing Phase (Discussion Topic)
« on: February 05, 2023, 07:11:30 AM »
Swim Team Rush v2: Backroute, abusing a finnicky start to save time.

Stop Blowing Up v2: Looks sensible, but still feels too comfortable near the end and loses only 2, not 4.

Natural Born v3 (higher pole), thanks for the hint. I haven't found a solution, but I have new ideas to try later. Interesting things will happen.

Tomato Watcher: No worries!

-- Simon

NL 12.12.5

The land are the physics pixels, i.e., the pixels where Lemmings physics apply. Zooming into the map will draw the land bigger, and we will see less of the land.

The canvas is the bitmap where we paint the land, then paint the lemmings, then paint the mouse cursor, ..., and finally paint the entire bitmap to the screen. After zooming in, we'll draw a land pixel as a square across several canvas pixels. The mouse position on the canvas stays the same throughout zooming in, that is good.

The mouse position on land will ideally remain the same before and after zooming in. When we're in small zoom levels and the land doesn't fill all of the canvas, preserving mouse-on-land won't always be possible. NL wants to fill the canvas with as much land as possible, and that's good.

The bug is now:
  • Zoom in until the land fills all of the canvas. Don't zoom in further yet, i.e., keep available at least one deeper zoom level for later.
  • Scroll to a position at but not directly touching, the boundary of the land. As a result, one edge of the canvas will show pixels from near, but not at, the edge of the land.
  • Look at where the mouse points on the land.
  • Zoom in.
  • Look again at where the mouse points on the land. Now, it's a different pixel than where the mouse pointed on the land during step 3, before you zoomed in during step 4.
Expected instead: In step 5, mouse-on-land agrees with step 3's mouse-on-land.

Surprisingly, the bug doesn't happen when you're near the center of the map. There, NL computes and preserves mouse-on-land correctly when zooming in.

I haven't tested zooming out. That should ideally use the same code to preserve mouse-on-land, and fixing the bug for zooming in should ideally also apply to zooming out.

-- Simon

It's a screenshot of VLC playing the attached video. It's not a direct screenshot of NL.

-- Simon

Contests / Re: Level Design Contest #27 - Playing Phase (Discussion Topic)
« on: February 04, 2023, 01:36:48 AM »
Armani, all of Rhizome, Inside Your Router, Bumper Cave are intended. geoo and I had a hard time solving each other's levels, and you plowed through all of them on the first evening. Congratulations, excellent work!

Re-solved Natural Born v2 with a minimal adaption of my v1 backroute. I use all skills now. Nice!

Solved Clown Fiesta. I'll let geoo applaud. 8-)

Solved both of Kaywhyn's entries (Swim Team Rush, Stop Blowing Up). Of these, Swim Team Rush doesn't feel like it needs the time limit; the limit leads to unnecessary worrying near the end. Swim Team Rush has interesting and different uses of water, nice!

-- Simon

NL 12.5.5.

Have a lemming near the top of the level, almost at the ceiling. Have space in front of the lemming. Select jumper in the panel. Hover over the lemming.

Game draws an arc that goes out of bounds (where nothing is drawn, and this is correct), then returns downwards from the ceiling. But if we assign jumper, the jumper does not follow this arc. Instead, the jumper dies beyond the ceiling and never returns. The arc and the path do not match even though there is no interaction with other lemmings.

Expected: The arc comes back from the ceiling if and only if the jumper survives.

-- Simon

Contests / Re: Level Design Contest #27 - Playing Phase (Discussion Topic)
« on: February 03, 2023, 10:49:17 PM »
Archive has replays for:
Expediency_will_be_ENFORCED v1
Expediency_will_be_ENFORCED v2
Mincemeat (twice, but similar)

As loose files:
Pommes Schranke

-- Simon

Lix Main / Re: Design history of Lix
« on: February 01, 2023, 03:49:38 AM »
Replay Verification

You can run Lix noninteractively on a directory full of replays:
  • lix --verify mydir will tell you, for each replay, whether it passes its pointed-to level. Finally, Lix tallies passes and fails.
  • lix --coverage mydir does everything from --verify mydir, and will also list the uncovered levels, i.e., levels in a level directory into which at least one replay pointed, but that themselves had no passing replay.
It's really a single feature with two forms of invocation. You want --coverage when you expect most levels to be covered by your replay collection and want to find omissions. Otherwise, you want --verify, which also makes sense for individual replay files.

The origin of replay verification: Around 2010-2013, geoo wanted to maintain online highscores for Lix. He considered to write a server based on Django, let people upload replays, then have the server run Lix in the background to verify the replay.

Thus, from day one, I saw a clear need to make replay verification run with as little of Lix as possible. I would still have to initialize graphics to load tiles, but I wouldn't be able to run the graphical user interface on the server. Everything had to work from the command line and print results as text output.

In the end, we never had online highscores. Nowadays, I don't even want them, they're extra stuff to maintain. There are enough other juicy objectives for Lix development in the next few years. But even without online highscores, the replay verification enjoys fast runtimes. It doesn't have to maintain a graphical land, only a physical land.

The biggest use case of replay verification is not competition between level players; it's tooling for level authors to verify pack solvability. I don't remember when exactly we realized this use case. Maybe we always had it in mind and it merely became the main use case over time.

Fully covered packs serve me as physics test cases: Whenever I touch physics code, if all replays pass, then most likely, I haven't changed physics.

I believe we had cross-pollination between Lix and NeoLemmix about replay verification, but I forgot the details. Most directly comes to mind: I'm still worrying how to associate replays to levels. Neither (level path only) nor (NL's level ID only) is perfect. And we eventually must start classifying replays in the proof collections: Intended solutions, accepted alternatives, backroutes, ...

-- Simon

General Discussion / Re: Simon blogs
« on: January 28, 2023, 06:56:07 AM »
Templates in C++

Nice talks on Youtube:

CppCon 2016: Template Normal Programming, part 1/2
CppCon 2016: Template Normal Programming, part 2/2

By Arthur O'Dwyer. A thorough explanation of C++17 templates and their language rules. The examples are straightforward, and it avoids metaprogramming examples wherever possible to keep it accessible, hence the title "Template Normal Programming".

CppCon 2014: Modern Template Metaprogramming: A Compendium, part 1/2
CppCon 2014: Modern Template Metaprogramming: A Compendium, part 2/2

By Walter E. Brown. Many short examples of type manipulation. You'll see the implementation and ideas behind standard library utilities such as  std::is_same<T, U> or std::remove_const<T>. Introduction to SFINAE.


I should revisit one of my toy C++ examples: How nice of a functor can you create, e.g., with C++ template magic, to minimize boilerplate in the usercode. Here, I mean functor in the sense of category theory, not necessarily in the sense of object that overloads operator().

The use case is: You have

template <typename T>
struct ErrorOr {
    int error;
    T value;

... with the unenforced rule that we should use its good value if and only if the error is 0. You have a function func: T -> U. The goal is to lift func into the world of ErrorOr: The lifted function is of type ErrorOr<T> -> ErrorOr<U> and calls func when a good T comes, and merely copies the error code when an error code comes.

The solutions will likely not be beginner-friendly, and I'm sure that other people have already found solutions that make the usercode calls look reasonably straightforward. Nonetheless, I'll keep it in mind as an exercise for myself.

-- Simon

Lix Levels / Re: Simon streamed lemforum/Hopeless, 2023-01-22
« on: January 27, 2023, 10:14:41 PM »
Thanks for the feedback! Yes, that spoiler said exactly what I figured it would probably say.

Next Hopeless stream will be in a few weeks. I'll be busy this weekend. Next week, geoo will visit me for a few days, and there is already a multiplayer session.

-- Simon

Pages: [1] 2 3 ... 250