[DISCUSSION] [PLAYER] Let's discuss skill assignments.

Started by namida, March 06, 2016, 08:30:56 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

namida

So - in the interest of getting as much physics changes as possible done in a single hit - I think a good place to start is with  the question:

When should we be able to assign which skills?

Currently, the detection for this is quite a mess, for sure. However, we'll leave it to me on tidying up how it works behind the scenes, and focus more on the end results - what should or shouldn't be possible to do? We also won't worry about what exactly happens when the skill is assigned for now - just whether it can be assigned or not.

Let's look at what current checks are applied to assigning the various skills. Note that everything mentioned here is based off the code with gimmicks (except zombies) removed.

General
In general, the approach when a skill assignment is attempted is:
1. First, find two lemmings (Lemming1 and Lemming2) - this will generally be the highest-priority and second-highest-priority lemming. Which lemmings are eligible (and prioritized or deprioritized) may be modified by things such as directional select; we will leave /that/ for another discussion.
2. If one of the two lemmings is a zombie, change the marked lemmings so that both Lemming1 and Lemming2 point to the non-zombie. (If both are zombies, stop trying to assign the skill.
3. If both lemmings are zombies, the assignment fails altogether.
4. Proceed to the skill-specific assignment code.

Note: Not all skill-specific code does actually check Lemming2. It will be specifically mentioned if it does.

Note: All skills also (obviously) have a check "does the remaining skillset have at least 1 of the skill being assigned". I won't specifically mention this during the steps.

Walker
1. Mark Lemming1 as "SelectedLemming" if it is currently performing one of these actions: Walking, Shrugging, Blocking, Platforming, Building, Stacking, Bashing, Mining, Digging.
2. If Lemming1 was not doing one of those, and Lemming2 is, mark Lemming2 as "SelectedLemming".
3. If we have a SelectedLemming, assigning Walker to it succeeds.

Permanent Skills (Climber, Swimmer, Floater, Glider, Disarmer)
1. Check that Lemming1 doesn't already have the skill in question. If the skill in question is Floater or Glider, check it doesn't have the other one of those two either.
2. Check that Lemming1 is not performing one of these actions: Ohnoing, Exploding, Drowning, Burning, Splatting, Exiting. (Exception: Drowning is not checked for assigning Swimmer)
3. If both of the above checks passed, assigning the permanent skill to Lemming1 succeeds.

Bug noticed when writing topic: The "Exploding" state is only checked for in a Bomber explosion, not a Stoner explosion. The "Ohnoing" state is correctly checked for both skills.

Bomber, Stoner
1. Check that Lemming1 is not performing one of these actions: Ohnoing, Exploding, Drowning, Burning, Splatting, Exiting.
2. If the above check passed, assigning Bomber / Stoner to Lemming1 succeeds.

Bug noticed when writing topic: Like with the permanent skills, the "Exploding" state is only properly checked for with Bomber explosions. This one is more noticable - try assigning a Bomber or another Stoner, to a Stoner, on the exact frame of the explosion (click in the upper-left corner of the explosion graphic when assigning).

Blocker
1. Check that Lemming1 is performing one of these actions: Walking, Shrugging, Platforming, Building, Stacking, Bashing, Mining, Digging.
2. Check that no blocker field already exists at Lemming1's position.
3. If both of the above checks passed, assigning Blocker to Lemming1 succeeds.

Platformer
1. Check that Lemming1 is performing one of these actions: Walking, Shrugging, Building, Stacking, Bashing, Mining, Digging.
2. Check that at least one pixel in the area the first brick would cover is currently non-solid and so are the two pixels immediately above the 2nd and 3rd pixels of the brick (relative to the lemming's position / direction).
3. If these checks fail for Lemming1, perform them for Lemming2.
4. Whichever lemming (if either) they succeeded for first, gets successfully assigned Platformer.

Builder, Stacker
1. Check that Lemming1 is performing one of these actions: Walking, Shrugging, Platforming, Bashing, Mining, Digging, or whichever one out of Building / Stacking is not currently being assigned.
2. If that check fails for Lemming1, perform it for Lemming2.
3. Whichever lemming (if either) passed the check is successfully assigned Builder.

Basher
1. Check that Lemming1 is performing one of these actions: Walking, Shrugging, Platforming, Building, Stacking, Mining, Digging.
2. If that failed, check if Lemming2 is. Whichever lemming it passed for (if any) is now "SelectedLemming".
3. If the pixel at 4 pixels in front of SelectedLemming and 5 pixels above SelectedLemming (by foot position) is steel or an incorrect one way, the assign fails (in the case of steel, a sound is also played).
4. If all of the above passed, SelectedLemming is successfully assigned a basher.

I know the steel check is weird. It's mostly a carry-over from vanilla Lemmix and probably needs improvement. The check during the actual bashing action is, IIRC, much better.

Miner
1. Check that Lemming1 is performing one of these actions: Walking, Shrugging, Platforming, Building, Stacking, Bashing, Digging.
2. If that failed, check if Lemming2 is. Whichever lemming it passed for (if any) is now "SelectedLemming".
3. If the pixel where SelectedLemming is standing is steel, the assign fails (a sound is played).
4. If the pixel 4 pixels in front and 5 above (like with the basher's checks) is an incorrect one way (but NOT if it's steel), the assign fails.
5. If all of the above passed, SelectedLemming is successfully assigned a digger.

And you thought the basher's checks were weird...

Digger
1. If the pixel where Lemming1 is standing is steel, the assignment fails (no sound is played this time).
2. Check if Lemming1 is performing one of these actions: Walking, Shrugging, Platforming, Building, Stacking, Bashing, Mining.
3. If that failed, check if Lemming2 is performing one of those actions and not standing on steel.
4. Whichever lemming the checks succeeded for becomes a digger successfully.

No, you're not interpreting that wrong. If Lemming1 is standing on steel, then the assignment will fail for Lemming2 too, even if Lemming2 isn't standing on steel. However, while these false negatives can occur, false positives cannot (as far as I can tell) - the assignment will never succeed on a lemming that is standing on steel. My only guess as to why is that it's something that slipped through from vanilla Lemmix, and since it's so obscure, never got noticed.

Cloner
1. Check if Lemming1 is performing one of these actions: Walking, Shrugging, Platforming, Building, Stacking, Bashing, Mining, Digging, Jumping, Falling, Floating, Swimming, Gliding, Fixing.
2. If not, check if Lemming2 is.
3. Whichever the checks succeeded for first, the Cloner gets assigned successfully to that lemming.

I could swear I remember making it impossible to assign a Cloner to a Digger too, but the current code - and indeed, the results from testing the latest version - contradict that.

There's some areas where there's obvious room for improvement - the first of course being fixing the bugs with permanent skills / bombers / stoners assigning to in-explosion stoners - but I'd also like to get input from anyone else who has ideas too. Fire away! :)
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

namida

Proposed changes:

General
(None)

Walker
(None)

Permanent Skills
1. Fix the bug which allows assignment to Stoners during the explosion frame.

Bomber, Stoner
1. Fix the bug which allows assignment to Stoners during the explosion frame.

Blocker
(None)

Platformer
(None)

Builder, Stacker
(None)

Basher
(None)

Miner
(None)

Digger
(None)

Cloner
(None)
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

IchoTolot

As weird as the checks may seem sometimes ---- they work and I don't find any of the behaviors problematic.

There is probably a lot of tidying up to do there to make the code more cleaner, but as you said that's your buisness ;)

And as I don't find any of the behaviors problematic, aside from little bugs as the cloner-platformer case and maybe some smaller things with no really big impact (like changing a assign priority): I say leave it as it is. Never change a running system :8():

Also I get really sick if I think about the consequences for already existing content (broken levels + creating new backroutes) and replays if I think about what could change here :sick::sick:

namida

Quotemaybe some smaller things with no really big impact (like changing a assign priority)

Priority should be purely a UI thing. The ideal rule is - whether or not a skill can be assigned to a given lemming should not depend on whether or not (or how many) any other lemmings are near him at the time. Although perhaps sometimes complex, this is already possible in virtually any situation by using highlight.

QuoteAlso I get really sick if I think about the consequences for already existing content (broken levels + creating new backroutes) and replays if I think about what could change here :sick::sick:

Yeah, I know. That's the reasoning behind wanting to do as many changes as possible at the same time, to avoid the situation we had in the early days where every update changed physics somehow. Chances are there are things that need to change, and will only be uncovered by a close look at the code (the Stoner -> permanent skill / Bomber / Stoner bug being a prime example). There's probably the odd case that doesn't make sense too, or is inconsistent.

Some things in particular that stand out are - the basher's check for steel / one-way walls. Although this is one pixel the basher checks during the actual action, it's only one of many - should we not either check all (or at least most, perhaps?) of them, or not check any at all and instead let the skill be assigned then stop on the first stroke? Likewise, the miner checks for steel and one way don't even check the same place as each other; and neither of these positions is actually checked during the miner's action. (The digger on the other hand is pretty consistent with the terrain checks during the actual digging action.)

Another one is the Platformer's extra checks compared to the Builder and Stacker. Should it really have those? I remember the reason I put them there was to avoid platforming in a position where nothing would be placed, thus resulting in turning around, but at the same time - we certianly don't prevent a Builder or Stacker assignment in such a case.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

IchoTolot

Quote from: namida on March 06, 2016, 11:52:03 AM
Another one is the Platformer's extra checks compared to the Builder and Stacker. Should it really have those? I remember the reason I put them there was to avoid platforming in a position where nothing would be placed, thus resulting in turning around, but at the same time - we certianly don't prevent a Builder or Stacker assignment in such a case.

Well the builder always has sth to place, as the Lemming can simply be at this place. The platformer on the other hand places sth under the Lemming, where it often cannot be there.
If we allow a platformer to place a brick where it would not place anything we would have another walker type skill. So giving the player platformers will be extremely more dangerous as it has now a big backroute potential.
There is a big difference between placing builder/platformer bricks! So the "inconsistancy" makes sense here -- to avoid the platformer beeing just another walker. With the builder you cannot easily avoid this + it actually places sth.

Nepster

Quote from: IchoTolot on March 06, 2016, 11:43:19 AM
Also I get really sick if I think about the consequences for already existing content (broken levels + creating new backroutes) and replays if I think about what could change here :sick::sick:
I agree that we should try to keep the current checks if possible.

However there are a few more things we might consider in order to simplify skill assignments:

1) Instead of having only two lemmings, loop through all lemmings under the cursor
The algorithm would be something like: Get list of all lemmings under cursor (ordered by priority; modified by only-right, etc.). Then go through all lemmings and check whether one can give them the skill, until one has found one such lemming or the list runs out.
The reason for this suggestion is, that currently spamming builders, bashers, ... can only be done with priority-invert. The above would make this easier.

2) Ease skill assignment on steep slopes
Problem: On steep slopes the lemmings are most of the time a jumper or a faller, hence cannot be assigned most non-permanent skills.
2a) Downwards slopes
Here the skill assignment would have to be remembered for two frames (or so). If during this time, the lemming hits terrain again, he would start with the skill.
I am not sure how hard it is to implement such a thing with the current code.
2b) Upwards slopes
The algorithm would be somthing like: If a jumper gets assigned a non-permanent skill, he drops instantly back to the bottom and there starts with the work.
Unfortunately this might have some unwanted consequences:
- The skill assignement can be delayed for two more frames.
- Depending on the precise terrain layout, the drop back to the bottom, might find another different bottom and not the original one. Perhaps one can compute the original position from the frame number of the jumper animation?

Proxima

Why the asymmetry? Why not say that if a jumper is assigned a non-permanent, he starts to carry it out at the first opportunity, i.e. at the top of his jump?

IchoTolot

Quote from: Proxima on March 06, 2016, 02:17:43 PM
Why the asymmetry? Why not say that if a jumper is assigned a non-permanent, he starts to carry it out at the first opportunity, i.e. at the top of his jump?

I think this would be the best solution :)   
Assigning at steep slopes was a nightmare in Lemmini without skipping backwards and i often thought: Why couldn't the jumper simply perform the task when he's able to do so again.

namida

Quote1) Instead of having only two lemmings, loop through all lemmings under the cursor
The algorithm would be something like: Get list of all lemmings under cursor (ordered by priority; modified by only-right, etc.). Then go through all lemmings and check whether one can give them the skill, until one has found one such lemming or the list runs out.
The reason for this suggestion is, that currently spamming builders, bashers, ... can only be done with priority-invert. The above would make this easier.

Agreed that this makes sense, although priority invert is not really nessecary for this - if, for example, you're trying to assign builder, any lemmings that are already builders are de-prioritized (as of V1.39n). So it's very unlikely that they'll become Lemming1 or Lemming2, unless there aren't enough lemmings to choose from. Still, this is indeed not an ideal way to handle it, and is mostly a matter of "this is how Lemmix does it, and it hasn't been changed".

Quote2) Ease skill assignment on steep slopes
...

I'm not so sure about this one, especially the instant-drop-and-perform. If anything, I prefer Proxima's suggestion here, but I'm not sure about this as a whole, especially given that we do have frame-by-frame control. It should also be considered that currently (by design), it is impossible to assign more than one skill in a single frame (now whether or not it should stay that way is another matter); the suggestion of delaying the assignment rather than preventing it leads to another situation that has to be examined, and could possibly lead to unexpected behaviour.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

Nepster

Quote from: Proxima on March 06, 2016, 02:17:43 PM
Why the asymmetry? Why not say that if a jumper is assigned a non-permanent, he starts to carry it out at the first opportunity, i.e. at the top of his jump?
Good question. I just thought first about upwards slopes, where the idea was to start the skill as soon as possible. But your suggestion is probably better and easier to understand for new players.

QuoteIt should also be considered that currently (by design), it is impossible to assign more than one skill in a single frame (now whether or not it should stay that way is another matter)
Apply the same algorithm that you already have for the case that the player and the replay want to assign skills during the same frame, i.e. prioritize new assignments.

Edit: Remove incorrect parts. Thanks namida.

namida

QuoteApply the same algorithm that you already have for the case that the player and the replay want to assign skills during the same frame, i.e. prioritize new assignments.

The opposite actually - the already-existing assignment is prioritized. This has been criticized, but won't be changable without some major overhauling. Which is something that's ideal to do after any physics changes have been, at the very least, decided on.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

namida

So, I think the questions that remain at this stage:

1. Should a change be made in regards to assigning skills to jumpers? I'm not sure about the whole thing of delaying it, but a more-radical but perhaps practical idea - should we simply allow most (if not all) skills to be assigned to them just like it would be with walkers (subject to other conditions that are usually required for the skill)?
I think for this one, rather than discuss it theoretically, I should upload a modified version that allows this so it can be tested in practical situations. I'll do this later today.

2. Should the one-assignment-per-frame limitation be kept?
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

Simon

About (1): Queuing skills are executed at what time? Do you want to allow transistions that are impossible right now?

When a jumper finishes jumping, and would become walker, will he start working instead? When (1) is not implemented, the earliest you can click the jumper is after becoming walker. Then he starts working one frame later than what (1) implies.

I don't want to decide whether (1) is good. Framestepping makes queuing less urgent. Queuing can be useful with many skills, it's not jumper-exclusive.

About (2): If you implement (1), we have to redefine what an assignment is before answering (2). Is an assignment the act of queuing, or is it the queued transistion later?

You advance physics when assigning during pause. This is good from a UI standpoint, because the assignment is carried out immediately, giving maximum feedback for the click. When you want to allow multiple assignments, should we advance (then how to assign several skills?), not advance (skimping on great feedback), or have extra UI to choose the behavior during play (feature bloat, undiscoverable keys, etc.)?

-- Simon

ccexplore

Perhaps instead of tackling through queueing assignments, the game could provide some form of "smart frame advance" that advances time until, say, the selected lemming underwent certain kinds of transition like landing or finishing a jump.  Though it does feel like too much effort for something that usually can be achieved manually with a small series of forward and backward steps.

I do want to point out that another compelling case for queueing would be for skills like builders and platformers, specifically being able to tell the lemming to build several times on the outset rather than having to keep watch to assign the next one.  Maybe this already exists in NeoLemmix but if not, it's worth considering.  This is not really about game mechanics though, it's really a UI feature around skill assignments.

Finally, I'm sure Simon knows this already, but advancing physics is not the only way to provide visual feedback about a skill assignment.  I think Lix's "skill assignment bubbles" may have an excellent use case here for multiple assignments per frame.  The discussion around multiple assignments per frame should be more about pros and cons as regards to level solving and designing.

namida

Re 1, my proposal was to no longer disallow assignment to jumpers in the first place. ie. if you click a jumper with Builder selected, he immediately starts building just like a walker would.

Re 2, let's decide whether to allow it at all first. Then we can consider visual feedback etc.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)