Handicap in Multiplayer

Started by Simon, May 16, 2022, 06:48:08 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Simon

Hi,

(This has github issue #391: Handicaps in Multiplayer.)



If you're a brand-new player at golf, go, or chess, it's already an achievement when you beat a strong opponent at queen odds, or at nine stones, or at three more strokes per hole. Next time, can you do it at rook odds? You can easily see your personal progress in how the handicap shrinks over time. I'd like to have this in Lix.

Per game: In Lix's networking lobby, I'd like to offer handicap options next to the color picker. Between games, you can adjust the handicap. The default is no handicap for either side.

Choosing a handicap puts you at a disadvantage. The stronger side should handicap itself and thus start with a weaker position. I'd like the new player to start with the level's normal, unhandicapped-but-also-unimproved position; this makes it easier for him to learn how the map usually plays. Also, as I wrote in 2017: A strong player with 50 lix can beat a novice with 500, but a strong player with 5 lix must play enourmously well to beat a novice with 50 on a map with batters.




In IRC, geoo and I have considered some types of handicap.

Divisor handicap: You pick a number ≥ 1. Your initial number of lix is divided by it, and every skill count in your panel is divided by it. Options for divisor handicap could be 1 (= no handicap), 1.2, 1.5, 2, 3.3, 5, 7, and 10.

We'll always round up non-integer results. If the map gives 2 builders, you'll start with 2 builders at handicap 1.2 or 1.5, and you'll start with 1 builder at any bigger handicap.

Previously, I've expressed this as a multiplier handicap, and values were 100% (= no handicap), 70%, 50%, ..., but this design has a downside: Lower numbers mean stronger handicaps. It's nice when higher numbers mean stronger handicaps, to avoid confusion when people say "high handicap" or "you can lower it".

If you're in a team, the team's total divisor handicap can be the average of the team's players. Should "average" be the arithmetic mean or the harmonic mean? I'll have to ponder, and Proxima will be happy. Harmonic makes sense because it's a divisor handicap.



Delay handicap. You pick a number of seconds ≥ 0. Your first lix spawns later than other players' first lix, at this delay. Afterwards, your remaining lix continue to spawn at the normal spawn interval after each previous lix. Options for delay handicap could be 0, 5, 10, 20, 30 seconds. Anything more than 30 seconds is probably too boring for the experienced player.

Again, if you're in a team, the team's total delay is the average of the individual player's delay.

Asymmetric levels. If you choose a divisor and/or delay handicap, you always start in the first seat, and other players are randomly distributed amongst the remaining seats. This doesn't matter in a symmetric level, but if the author wants to build an asymmetric map, the author can put the seat-to-be-disadvantaged always in the first position. As long as we have any kind of handicap option, or even just a checkbox, we can add this seating rule at little exta UI cost in the lobby dialog -- it needs an explanation, but no extra pickers.

Level-specific handicap. Instead of offering concrete values to pick, you merely have a checkbox: Do you want to be handicapped or not? Or you have a choice of handicap strengths; which handicap strength do you want? It's the task of the level author to define the handicap in terms of delays or divisors or seats.

The downside of such level-specific handicap is that most authors won't bother to define handicaps for their levels. The few levels that have author-defined handicaps won't be consistent, e.g., you can play at strength 1 on this map, but it's hard to win against strength 3 on that other map. If it's not consistent anyway, I feel it's better to just offer concrete values, and let the players pick.

Ideas?

-- Simon

Flopsy

I'm not sure if you're considering all these handicaps or just one of these but I'll discuss them anyway :)

Divisor Handicap

I read this as a handicap on both the Lix number and the number of skills at the same time, it feels like limiting skills doesn't really achieve much if the Lixes are already limited anyway, so having less say Walkers, Runners, Climbers, Floaters or Jumpers would not be that bad.
In fact if the same formula is used, if there was one walker for each Lix, it should still be one walker for each Lix.

The team formula is an interesting case however, because it feels like even the new players will be handicapped in this scenario which is not really something which should be encouraged.

Delay Handicap

I quite like the sound of this one but at the same time, I think level knowledge is required to make a decent handicap for this, some levels are over after 10 seconds pretty much.
Sometimes having delayed spawn could help the player rather than hinder them as well (eg. my Krypton Factor race map) so this can be very situational.

Asymmetric Levels

We don't have many of these levels and it's sometimes hard to know which is the hardest start position without play testing first. Otherwise this one is a good idea personally.

Level Specific

This one seems vague in description, are you saying the level author sets a single parameter which would occur if one says "yes" to being handicapped? If so, I don't see this getting much use also.

geoo

I've given this a bit of thought after the games with Rampoina. For the record, we played 3 maps:

  • Uphill battle. Rampoina was too strong for this map, and I didn't stand a chance. So we moved to
  • Ivory Tower: We played quite a few rounds, Rampoina won one and came very close to winning 3-4 times.
  • Stepping Stones: I handicapped myself by trapping my crowd and waiting for 1 minute before acting. Within 1 minute, building from the bottom middle block can almost reach to the opponent's starting platform, so this made it quite intense when my crowd was trapped there. If the spawn was simply delayed, the stakes would be lower, and even a delay of more than 1 minute could be considered. Rampoina almost won one round via the top route, but the crowd splatted right in front of the exit x_x
I believe handicap is extremely map specific. Quite often a delay and the reduction of the number of lix can serve the purpose. But many other maps will have specific skills which are rare, and adjusting their number might be a better means of handicap (e.g. floaters in Rescue Rangers, or diggers in Pancake Compression). The problem is, finding a good handicap needs knowledge of the map, and presumably the person who knows the map best is the level author.

I don't think putting the burden on the players via some complicated UI allowing to adjust delays, skills, number of lix etc is necessarily the best idea (it might be useful for experimenting though).

I would argue the best way would be to introduce handicap levels (both positive and negative), and the level author can specify various handicap levels in terms of delay, number of lix, spawn interval, skill numbers, etc.
Intermediate levels of handicap that are not specified would be done via linear interpolation (or maybe logarithmic for skills and/or lix amount, not sure). Of course, getting these levels consistent across different maps is difficult (and also subjective), but easy to tweak by changing the specific handicap level that is associated to a specific skill/lix parameter tweak.

I'm advocating for both positive and negative handicap because for some maps, it might be easier to provide positive handicap (e.g. add blockers, or add floaters to Rescue Rangers, while you wouldn't want to make these adjustments to the level itself). The aim would be that the handicap difference indicates the advantage, so +10 and 0 would be similar to 0 and -10.

Another advantage is that you can assign handicap values to spawns in asymmetric maps (and then possibly adjust them further via lix/skill parameter tweaks, to allow for a range of handicaps), incorporating these maps straightforwardly into the system.

From a player perspective, one would then simply adjust one's handicap level in the multiplayer UI, without needing knowledge of the specific map. Not every map would offer handicap levels, or some might only offer a limited range; the levels might not be 100% consistent across maps but one could make reasonable efforts towards that. I'd argue that all of this is fine, for example, the level browser could filter to only show maps where the min/max handicap is larger than a user provided value.

Dullstar

#3
With the Divisor Handicap, I think it would be important for skills and Lix to be two separate settings, with Lix being the most important.

Limiting the number of Lix available to a player forces them to go after other players in order to win, as the handicapped player will always lose a passive game. This is fine, because the players who we might handicap this way are the ones who are going to play like this anyway (because getting other players' Lix to come to your exit is generally how you win, but doing this requires a lot of skill because of keeping track of everything), so a reduction in the number of Lix offsets the advantage that players who are able to do this effectively have.

Limiting the number of skills could maybe make sense sometimes, but it's less fine-grained: if you observe a matchup is imbalanced, you can continually adjust the number of Lix handicap for quite a while before it reaches a point where it's unreasonable for the experienced player to overcome. But if you cut the number of skills, depending on what the limiting skill is, you can potentially reach a point where it's no longer possible to complete a path to the exit, and in levels with comparable amounts of constructive/destructive skills, the handicapped player will always lose any wars of attrition, which can happen a lot e.g. when there's a fragile builder/platformer staircase right next to an exit. I think for this reason, you'd want to handicap the number of Lix before the number of skills, and combining the two would place a hard limit on the amount by which you can divide before the matchup swings wildly in the other direction of imbalanced.

Since in a team game, all players share the same Lix and the same skills, I think it's sufficient to simply to assign the handicap to the team as a whole.




Assymetric levels, I think, would benefit from being able to choose arbitrary positions, though you may want some sort of mechanism to handle disputes in the event that talking to the other players fails to resolve it - a simple solution could be to try assigning everyone to their chosen hatch, and randomly select one of the people if multiple people chose it, then allowing remaining players to select from the remaining hatches until either all hatches are assigned, or there is only one hatch left to assign. Players could also choose to be assigned a random hatch, which would be applied after everyone who wants a specific hatch has chosen. Another solution could be to randomize the order of players (perhaps a handicap option to move certain players up or down the list?) and then go down the list and have people pick hatches, perhaps keeping the option to select a random hatch from the remaining hatches after all players have chosen.




The delay handicap is an interesting option, but I'd probably only consider it if we're okay with having multiple choices for handicaps.




A major weakness of level-specific handicaps is that there's not much room to adjust them on the fly. But one major use case could be defining the minimum amount of skills allowed. If a skill divisor handicap brings someone below that amount, they receive the minimum amount instead. This could be used to make sure that a player will always have at least the minimum number of skills required to reach their exit regardless of the skill divisor.

Simon

Thanks for the great replies! I'll come back to everything in 0-3 days.

-- Simon

Simon

Gist: Anything that touches the level format will wait until at least next year. 0.10 will have identical level format as 0.9, even if 0.10 has physics changes.

Anything that I can meaningfully implement as a player field is good for taking into 0.10's networking protocol. Lix 0.10 will already track client version per player, it's easy to add fields for handicap. Especially just adding some ints are are very easy these weeks during the design of 0.10, that's why I've made this thread.

I agree that no single handicap is the best on every map. If we offer handicap in the lobby, we may as well offer several types. This gives flexibility and is important for playtesting; then we'll be wiser in case we add something to the level format in the future.

Clones offered fully asymmetric starting positions for a still-balanced match. You were able to specify seat-dependent initial lemmings and seat-dependent skillsets. This goes in the same direction as handicap, might be worthwhile to keep in mind. Problem: It might also end orthogoal to handicap, forcing us to define all spots in a two-dimensional grid -- one axis handicap, second axis seat. I'd rather avoid too deep of such nesting. We'll see.

-- Simon

Simon

#6
Hard to strike the balance between too many and too few options.

Benefits of many options:
  • You can fine-tune more. You can raise handicap of type X and lower type Y. Allows you to find something closer to 50:50 balancing.
  • As a community, we can experiment quicker and see what pulls its weight: which handicap types, which amounts.
Downsides:
  • Multi-valued handicap won't double as a ranking system. You're not 3 stones stronger than your opponent. You're hard-to-name-long-bla-bla stronger than your opponent.
  • Hard or impossible to squeeze the entire handicap selection into the player line in the lobby. Easy with one value, but hard with 3 or even more values. I don't want to reserve a huge space either for 3 values that will be empty in 90 % of the games.
  • Slightly more overwhelming UI, but this isn't a big downside with the following plan: I'll put all the details for handicap choice to a separate dialog anyway, where I can put ample explanation.
I'll heed Dullstar's warning (unplayability with too few skills), even though I don't believe it will manifest on too many maps. For 0.10, I'm thus aiming at:
  • Lix divisor handicap,
  • Skill divisor handicap (separate from the lix divisor),
  • Spawn delay handicap.
The underlying code will support geoo's beneficial handicap as well as the originally planned disadvantageous handicap, but I don't know if I want to expose beneficial handicap in the UI. I have written UI text that handicap will always put you at a disadvantage. I can revise the text if you feel strongly that Lix should offer beneficial handicap. But even with beneficial handicap, I'd still like to call the feature handicap -- and not mod or something similar unprecise.

In 0.10, I don't yet plan to put handicapped players on certain start positions. E.g., geoo's Uphill Battle will still require you to reset. If such deliberately imbalanced maps get popular, we can still add something in 0.11, 0.12, ...

-- Simon

Simon

Another possibility of beneficial handicap: Absolute +n for every skill.

This would affect even those skills that the map author set to 0. If you set +5 for the absolute +skill handicap, you'll get 5 blockers on maps that don't have any blockers, and you'll get 7 blockers on maps that give 2.

Downsides:
  • Muddles the flavor of the map.
  • Doesn't teach much about normal (unhandicapped) play. Downward Reduction with diggers, blockers, runners, ... distracts from recognizing crowd management principles with miners, the main point of normal Downward Reduction.
The second point dovetails into an argument against positive handicap in general: We want to teach the newbie how to play the map. For this objective, it's best to start the newbie with a normal position.

-- Simon

geoo

If you're implementing multiple handicap options rather than a single score, and you're planning to implement a separate menu anyway, what is the purpose of using divisors rather than simply specifying the exact number of lix/skills/spawn delay in that menu? That seems much cleaner as you know exactly what you'll get, and the UI is the same.

Also, I hope "skill handicap" is configurable per skill and not a blanket handicap, as I think adjusting all skills with the same factor/addition is going to be pretty useless 99% of the time.

If you do implement such a dialog, I think it could actually be integrated quite nicely with the single-score handicap that is determined by the level author as I proposed above:
In the special menu, you can select a handicap level (say via a slider, and all the options that you see adjust accordingly), but you can also manually modify the individual handicap stats (then the slider displays '?').
The aggregated handicap level (or '?') could then be shown in the lobby. This offers the advantages from both approaches: Full customizability of all stats, but also level-author handicap levels which will be more convenient for players that are less familiar with a given map.

I've also thought about how Ultimate Chicken Horse does handicap: Players can only nerf themselves (i.e. no positive handicap), and the handicap is essentially a score multiplier. I'm not sure the former limitation is necessary in lix, but I think a score multiplier might even be more powerful than e.g. adjusting the number of lix or any of the other options individually, and probably the only one that could somewhat stand on its own in most maps.


One other remark: So are you prioritizing handicap over neutral/pre-placed lix? While I certainly think the former is useful, I think it's only relevant to some sessions, and there are various temporary workarounds, while I think the latter opens up a lot of new gameplay potential for any kind of session.

Simon

Quote from: geoo on July 02, 2022, 01:19:38 PM
are you prioritizing handicap over neutral/pre-placed lix?

Yes. Reason: I touch the networking anyway for 0.10, I may as well get the ideas for handicap now and implement what is easy, as changing the structs in the networking is cheap before I release. And originally, handicap was a single divisor, it felt obvious to include that, to also ship the new networking with a visible improvement.

Neutral lix, I'll add them later in 2022 in an experimental build.

I want rapid physics development, testing, and updating, all on the same server. Neutral lix are one of the first target features for that fast iteration. And the networking changes for 0.10 are necessary for that iteration.

Neutral lix need no server-side support.

Quote
what is the purpose of using divisors rather than simply specifying the exact number of lix/skills/spawn delay in that menu?

It's certainly possible that good handicap needs more than a few ints.

If it gets too complicated, I might as well not include it in 0.10. E.g., it's conceivable to send arbitrary handicap information per lobby player, information that the server doesn't even need to parse. That's incompatible with both the 0.9 and 0.10 protocol; both assume that all player information fits in n bytes. This kind of change is expensive, and I would ditch that for 0.10 and add it some years down the road only.

Cementing the constant of 14 skills into the networking format wouldn't smell nice in 0.10.

Please continue to drill into the design!

Quoteadjusting all skills with the same factor/addition is going to be pretty useless 99% of the time.

I probably wouldn't have thought about it either. Then you mentioned that you wanted positive handicap and add blockers.

If you can live without blanket +n of every skill, I'll leave it out.

Blanket skill divisor, I separated this from the initial-lix divisor based on Dullstar's suggestion. My feeling is that initial lix is more important than the skills divisor. Unsure if I should keep blanket skill divisor; I kept it because it was cheap to keep one extra single value for experimentation.

Quotedialog, I think it could actually be integrated quite nicely with the single-score handicap that is determined by the level author as I proposed above:

Yes, that would be really nice. Especially because this works both with author-suggested handicap and without.

Quotescore multiplier might even be more powerful than e.g. adjusting the number of lix or any of the other options individually

Hmm. Score divisor, even more than handicap that changes initial lix, keeps intact the feeling of normal play.

It might be the easiest to substitue, e.g., we agree that A wins if A saves at least half as many lix as B saves. But still, it's nice though to have this straightforward computation in the physics, especially at more than two players.

Is the score divisor more fun than initial lix divisor? My hunch is that changing initial lix is more exciting, but I wouldn't bet on it. I can implement both, then we can experiment.

-- Simon

Simon

#10
There are 4 months left in 2022. The two big unfinished items on the 2022 roadmap are:
  • Release 0.10 with some safe physics changes, and with handicap.
  • Offer a hackish/experimental version to start playtesting neutral lix.
I want to commit December 2022 to the development towards the experimental neutral lix. That means that 0.10.0 will release in later October or in November 2022. That has implications to what parts of handicap play are a must for 0.10.0, and what accessories might have to wait for later:

Must be in 0.10.0:

  • Networking server accepts different minor Lix versions -- practically done, needs field-testing.
  • Handicapping in the networking protocol -- done.
  • Handicapping in the lobby UI -- mostly done, I'll tie up some loose ends tonight.
  • Handicapping in the game physics -- not started, but I'll focus on this in September 2022.
Acceptable omissions in 0.10.0:

  • Handicapping in the replay files. It's okay if handicapped games don't save or load properly in the early stable 0.10.x releases. If I do nothing at all here, then the replay will look as if the game had been unhandicapped.
Won't happen in 0.10.x:

  • Assigning handicapped players to disadvantageous seats on unbalanced maps. This would require a linear order of handicaps, and it would require unbalanced maps to adhere to standards like: Always put the disadvantageous seat first/last. Neither will be satisfied in 0.10.
  • Level-specific handicapping that the level author sets, as geoo suggests. No level format changes.
  • Per-skill customizable handicap in the lobby. Needs a solid concept first and doesn't fit into the 0.10 networking protocol.
I want to support lix divisor handicap, skill divisor handicap, spawn delay handicap, and score divisor handicap.

The lobby UI won't offer fractions > 1 (i.e., the lobby won't offer to multiply your value to make you stronger) even though the internal representation understands fractions > 1. My reason is still the same as I wrote in OP: I'd like the newbie to start with the level's normal, unhandicapped-but-also-unimproved position; this makes it easier for him to learn how the map usually plays.

Looking forward to playtesting all this in November 2022, and see which of the hunches hold up.

-- Simon

Simon

News from the battlefront.

Lix divisor, skill divisor, and spawn delay are all working well in my experimental physics.

Spawn delay can get bells and whistles in a future non-physics upgrade, by printing a countdown timer on your hatches. But that's for the future. All that matters in 0.10 is that lix spawn later by the amount that we specify.

Score divisor handicap is by far the most complex to implement nicely. In 99 % of cases, the score will be integer, and I want the computation to be exact in that case. I don't want to convert everything in scoring logic to floating point; singleplayer save counts would then be floating point, which would be madness. Thus, I'm busy these days converting the logic to rational arithmetic. The rational type will track both the raw save count as integer and the fraction from the handicap. Singleplayer can then extract the raw save count, and multiplayer stats, bars, ..., can compute the (possibly non-integer) score when they need to. Non-integral scores, I'll print them with one decimal place after a decimal dot.

I have a weak hunch that score multiplier will be the least fun handicap because it's so indirect. But that's a problem to be solved during playtesting. It's okay to work hard now and cut it in future versions if really turns out no fun.

-- Simon

geoo

Interesting, my intuition is that score divisor is going to be the single most applicable kind of handicap (unless you're playing all-or-nothing maps), while I feel that the blanket skill divisor is going to be un-fun and rather useless. The rationale is that you want to limit/cut the strong skills for the stronger player, while keeping the utility skills unaffected. The blanket skill divisor does the opposite: Your utility skills get cut in half (so the strong player runs out and gets frustrated), while the skills allowing to wreak havoc with in small amounts (e.g. digger, blocker) will remain available to some extent. So I don't think skill divisor is going to be all too useful unless you can set it for each skill individually.

Also curious to see you're trying to implement fractional scores. I would have thought in practice it'd be fair to just round up to the next integer (and call it a tie if the scores match). The "divisor" is a somewhat arbitrary number anyway, and changing it in small ways will affect your score by more than an integer, so it doesn't seem like precision is really needed (but happy to be proven wrong with some case scenario).

I'll try to make it to the fireside chat tomorrow night, curious to discuss, not sure I'll be able to make it though.


Simon

Yeah, the score divisor is probably the most widely applicable.

The skill divisor will be rarely useful, yes, even if we disregard the fun: Usually, we have many skills left over. Still, I imagine that the skill divisor will be the most appropriate handicap (of 0.10's four types of handicap) on Downward Reduction. On Downward Reduction, reducing lix might even be an advantage, and reducing score won't pull its weight as long as the outcome remains largely all-or-nothing, but reducing miners to match the new player's learning curve sounds promising.

The lix divisor has the small advantage (over the score divisor) that all local situations will still feel exactly like in unhandicapped play, and it's easier to add in your head if all lix are worth 1 point to everybody.

All this would support your idea (that we won't have in 0.10) to let the level designer choose the exact types of handicap and expose a one-dimensional scale to the players.

-- Simon

Simon

#14
The plan is still to release 0.10 sometime in October.

Must-haves for 0.10.0 that I still have to do:
  • Test what happens when some team members have handicap. Does handicap merge properly?
  • Icho will visit me this weekend. Test handicapped multiplayer together. Write down the issues from that testing, and fix any blocking issues.
  • Server should tell 0.9 players that they can't see or can't enter 0.10 rooms.
  • Batter's forward range vs. blockers should be exactly as it has always been in 0.9 and also way back in C++ Lix.
Reason for this odd-looking point about batters: I toyed with improving the backward range vs. blockers for 0.10, and that's likely a good idea. Then I noticed that, for forward range, the bat doesn't overlap the batted blocker, and shortened forward range vs. blockers by 2 hi-res pixels to fit the sprite.

It turned out a batd idea, not fun, will revert forward range to 0.9. As geoo thought during campfire: Nobody ever complaned in 13 years that the batter's forward range vs. blockers was too long.

In later 0.10.x:
  • Client-side, add lobby console text for when somebody changes his handicap. But get some UI feedback first in October/November, anyway.
  • Add replay support for handicap.
-- Simon