Menu

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.

Show posts Menu

Messages - Simon

#46
Yes, I hear both the successful old assignment and the short click for the failed assignment. I didn't notice that yesterday.

I agree that you shouldn't play a successful sound here.

On a click that will not assign, don't advance physics in the first place? Play only the failed assignment. Then you won't have to introduce inconsistencies. On air clicks, you probably want to advance physics, but air clicks are safe, can't mistake air clicks for a wanted assignment.

Wondering if you want to tell people before the click that the assignment will not go through.

-- Simon
#47
Quote from: WillLem on February 11, 2025, 01:42:52 AM
Quote from: Simon on February 10, 2025, 10:54:43 PMabsolute overwrite prevention into the next release.
It should already be in the RC...?

Ah, yes, RC1 prevents all overwrites. It behaves as follows. Situation:

  • Replay contains old assignment for the next tick.
  • Activate insert mode.
  • Point to a lemming that would normally (= if nothing were in the replay) eligible to be assigned.
  • Click.

The game then does:

  • You hear an assign sound.
  • The replay stays as before the click. You didn't cut, you didn't insert.
  • Physics advance once.
  • The old assignment replays.

This UX is problematic. You hear the expected assignment sound exactly as after a successful click, and the physics advance, too. But the click didn't produce what we wanted. It feels like a bug.

It's outright misleading when we assign permanents that will do nothing on the immediate next frame. The potential assignee does exactly what he would do if the click's assignment went through: Walk forward once.

-- Simon
#48
Then put absolute overwrite prevention into the next release. It's already better than NL 12.14, which accidentally overwrites different lemming.

The problem with your hotkey remains that it overwrites different lemming, which nobody wants. We have seen that different-lemming prevention is amenable code-wise. I'll help you until it's done.

-- Simon
#49
Lemmini / Re: Lemmini bit handling
February 10, 2025, 02:12:00 PM
All right, Tue, 19:00 UTC in Mumble. See you!

-- Simon
#50
WillLem and I know where to attack in the source, but source discussion has a separate topic.

Back to the design of insert mode.

Will uses NL's insert mode often, or rather the SLX mode that is NL's mode with absolute overwrite prevention. For this post, I'll define it as:

  • In cut mode, on new assignment, cut all lemmings' future, then add the new assignment.
  • In insert mode, on new assignment, look at the next physics update; if no assignment sits there, add the new assignment. (Never remove or overwrite.)
  • Air clicks cut all lemmings' future only if you're in cut mode.

For reference, Lix's insert mode:

  • In cut mode, on new assignment, cut all lix' future, then add the new assignment.
  • In insert mode, on new assignment, cut the same lix's future, then add the new assignment.
  • Air clicks cut all lix's future regardless of mode.

Will cares about integrity of the replay as a whole. This guarantees that you can revert your change. Any map click in insert mode either does nothing, or it inserts exactly one assignment, which you can revert by erasing.

I care about integrity of unaffected timelines. When lemmings A and B will not interact, assignments to A in insert mode should not affect what B will do. This is weaker than Will's goal of preserving the entire replay. I welcome cutting A's future because junk assignments are annoying. I accept that this has no easy reversal.

QuoteConsider a player accidentally deleting 20 carefully configured future assignments with a single click; we should guard against this, however unlikely it may seem.

For air clicks, I haven't made up my mind about how much value the easy reversal has. In today's stream of NepsterLix, I played Lots of Small Tasks, a 20-fold disjoint union. I was in insert mode throughout. I took care not to click air by accident. I explicitly say so in my twitch stream at 57:50 -- this is again the lingering fear that I'd like to design away.

On the other hand, when air clicks in Lix's insert mode didn't cut the global future, I got annoyed in 2022/2023.

When I'm sure that my click goes to the desired lix, I haven't experienced such fear recently. I suppose that misassigning to wrong lemming, and accidentally cutting his 20 assignments, is rare enough. But I can't prove that either.

In Lix, sometimes, I cut the same lix's future explicitly. Maybe I do this when I really care about the replay as a whole? I haven't paid attention to that yet. Sometimes I'll implicitly cut by assignment in insert mode. One big idea behind Lix's insert mode is that I wanted to solve disjoint unions and have each sublevel feel like it has its own replay.

I have no good answer for the design yet. A complete undo stack of replay changes feels like travelling in a new fifth dimension (x, y, physics updates, replay, undo), but it's not out of the question. I'll sleep over it more.

-- Simon
#51
Lemmini / Re: Lemmini bit handling
February 10, 2025, 12:30:39 AM
Bitwise operations treat a byte (e.g., -128 through 127) as an array of 8 bools.

Decimal 31 is binary 00011111.
Decimal 85 is binary 01010101.
Then 31 & 85 is 21 because decimal 21 is binary 00010101, this has a 1 only where both of the sources had a 1. And 31 | 85 is 95 because decimal 95 is 01011111, this has a 1 wherever one (or both) of the sources had a 1.

Search the internet for: bitwise operators, Java bitwise operations.

https://www.w3schools.in/java/operators/bitwise

Or do you want to investigate the Java source together? I have little time this week, but we can schedule Tuesday night or Wednesday night. Tuesday 19:00 UTC in Mumble?

-- Simon
#52
Stream is over!

-- Simon
#53
Thanks for the quick reply! The Delphi reference site will be useful.

-- Simon
#54
Help & Guides / Delphi, understanding the NL/CE codebase
February 08, 2025, 07:12:16 PM
Here are questions from Tuesday, 2025-02-04 when I looked with WillLem at the NL-CE source.

Downcasting in Delphi happens with as, e.g., myDerived := myBase as Derived. This is the equivalent of Java's instanceof or C++'s dynamic_cast<Derived*>(myBase), where I get null if the runtime type isn't Derived. In OO design, it's hackish to force usercode to downcast. Thus:

Does Delphi allow to type-parametrize my own types? Or: What is the closest Delphi equivalent to C++ templates/Java generics? If we have two lists of replay entries (one for assignments, one for RR changes), I want one to be a list of Assignment and the other a list of RrChange, not two lists of Base (the base class of both Assignment and RrChange). Then my callers don't have to downcast.

What is the closest Delphi equivalent to std::span (a slice, a pointer-with-length)? E.g., my object contains the array [0, 1, 2, 3, 4, 5], I would like to return the view [2, 3, 4] to my caller without making a copy of the entries.

I expected the search function (find the assignment for a given physics update) in the list class, not in the replay manager class. The search works purely with that list and it's a natural operation for that list.

The search has at least one near-duplicate.

When your list (of assignments, of ...) is always ordered, you can find elements by binary search instead of by linear search. But this doesn't matter when you have 30 elements in the list and you search it only a few times per second. And this (5 to 100 assignments and RR changes) is the extent of most Lemmings solutions. Don't prioritize rewriting the searches to binary search.

-- Simon
#55
The next stream was on Sunday, Feburary 9th:

I'm back in Lix development, with singleplayer features to playtest during this stream:

  • Scissors mouse cursor when you can click air to cancel the replay. Will it be annoying?
  • Small scissors next to the cursor, or a small "+" sign in insert mode, when the cursor opens over a lix during the replay.
  • Explain the gadget in the infobar whenever the mouse hovers over a gadget. E.g.: "Goal. Save 10/20 to win." Or: "Catapult. Flings +4, ↑16 in 8 ticks." These texts appear where "Lix #7 is bashing" would also appear.

I'll play NepsterLix, and I'll start at its very beginning.

Over the years, I have looked only sporadically at NepsterLix, ClamLix, and Rubix's pack. I want to try them properly. Last year, I've played geoo's pack on stream, and I can still warmly recommend that.

-- Simon
#56
Cool, thanks for clarifying that the workaround works (copying Allegro DLLs from Lix 0.10.28 into current Lix). I'll have to investigate what exactly changed on Windows with this recent jump from Allegro 5.2.9 to 5.2.10.

I'll come back to you when I have new ideas.

-- Simon
#57
I assume this is from the Allegro DLL upgrade from 5.2.9 to 5.2.10. Reason: Nothing related in the Lix code should have changed between Lix 0.10.28 and 0.10.29.

As a workaround, put the 5.2.9 DLLs (from Lix 0.10.28 or earlier) into Lix 0.10.29. Does that help?

-- Simon
#58
All right, Tuesday (today) at 18:00 UTC. See you!

-- Simon
#59
No strong opinion on the steel sound for a disallowed miner. If I assign during pause and the failed assignment doesn't advance physics, I know that it's not physically striking steel. If I assign unpaused, you risk misinterpretation.

-- Simon
#60
Quote from: WillLem on January 30, 2025, 04:11:02 PMunknowingly overwrite the Climber assignment.

Permanent ability assignments are odd in modern Lemmings.

For the physical motion, there is no difference between

  • queuing the climber for the next wall (let the engine assign it for you when lemming reaches wall) and
  • assigning climber earlier than the next wall (assign at arbitrary time between two reachings of wall, but you still must choose a tick).

From the view of the replay, it's a difference because NL refuses to accept two assignments for a single physics update. The intuitive fix for insert mode, when the clashing assignment comes, is to shift the old climber assignment earlier/later by 1 tick, in hope that it doesn't produce different physical motion. This is nasty. It's not guaranteed to produce equal motion, and the climber can clash with another old assignment.

I recommend: Don't worry about permanents. Solve the other skills first, then think about permanent abilities. I have worried about this in Lix, too, and it's too rare a case to design the entire feature around it.

Quoteassign a Platformer to Lemming A instead of a Builder
now all assignments following frame Y are out of sync
solved by using the Replay Editor

... or by cutting the same lix's future.

By your point, we should either never overwrite (not even same lemming), or first cut that lemming's future and then insert (what I suggest).

I agree that it's odd to allow overwrite same lemming, but keep the lemming's future.

In 2022/2023, I've played Lix with insert mode always-on, as a playtest. The first result was that same-lix-overwriting sucks when you preserve the same lix's future.

Quote from: namida on January 23, 2025, 08:37:46 PMiffy about the idea of erasing all future assignments for the same reasons. Additionally, it might be useful for the player to refer to the future assignments when correcting them

This is vague, what exactly are you doing? Do you look at the listing (as if you loaded the replay in a text editor) to see what the original replay was? When I fix a replay, I know enough of the solution, I've never needed a mixed list of old and new assignments.

Or do you need this when you move assignments by only a few ticks earlier/later? You have a chance then that the old assignments stay meaningful.

Quote from: WillLem on January 30, 2025, 04:11:02 PMYes, because the player is in Replay insert mode, which never allows overwriting:
reinforcing the player's choice to be in Replay Insert mode

This is backwards. It's okay to look at what the existing mode does (to not confuse existing users), but it's irrelevant what either of us supposes for the existing mode's design.

In your design, there are two modes: Always cut, or never overwrite. If your never-overwriting mode comes closer than always-cutting to what the player really wants/needs, he chooses to use never-overwrite mode (regardless of any design ideas behind that mode) and can still be unhappy.

Indeed, the natural next idea is to consider three modes.

Quote from: WillLem on January 30, 2025, 04:11:02 PM1) hotkey to allow overwriting
accept that this will also allow overwriting to a different lemming
Quote from: WillLem on January 30, 2025, 04:11:02 PM3) third mode:
preserves everything it can, but does allow overwriting
accepts the potential for accidental overwrites

Here's how these will behave in practice:

  • Lemming becomes builder at tick 100.
  • We want to assign him basher at tick 100.
  • We go to the always-preserving insert mode because that protects against overwriting a different lemming.
  • Assignment fails (because of old same-tick assignment).
  • We framestep forward and back to see which lemming has the old assignment.
  • Ah, it's the same lemming, therefore the overwrite is safe.
  • Hold hotkey, or enter third mode (essentially the same idea).
  • Assign to overwrite.

Two annoyances:

With 1) or 3), you still require the player to back-and-forth manually in step 4, to see who gets the clashing assignment. You've already identified that this is a problem, and you're looking into other solutions, I'll get to it later.

With 1) or 3), you still don't cut the lemming's future in step 8. I recommend to either forbid the overwriting, or to overwrite by cutting the same lemming's future.

Quote from: WillLem on January 30, 2025, 04:11:02 PM2) make it optional
doesn't allow on-the-fly switching

At first, this sounded like 1) or 3), but with a user option instead of a third mode during play. But I won't dissect it yet, because then you write:

QuoteIt also means figuring out the how when it comes to implementing same-frame same-lemming overwrite, which (full disclosure) isn't trivial!

This is getting to the heart of the matter.

What we really want is freedom to design the mode around clearly visible system status. You want to see ahead of time who/what exactly will be assigned, so we know what exactly will be overwritten/why the click will fail. You'll give the player the best information before he clicks at all. (You can still give feedback after the fact.)

And the important starting point is to ferry information from replay to the UI ahead of time about who will be overwritten.

I'm happy to dissect the NL code with you.

Tomorrow (Tuesday, Feb 4th), I have a day off work, and I can offer you any time of the day for a Mumble session. Do you have time around 18:00 UTC?

-- Simon