# Scoring with 2 values

working with mobile sokoban-style puzzle where player scored with 2 values:

1. time (how many seconds is taken to clear level)
2. move (how many moves is taken to clear level)

scoring with stars is no problem i can evaluate this by:

var record := {"move": 10, "time": 5}
var move := 9
var time := 4
var star := 1

if time < record.time:
star += 1  # beated record time
if move < record.move:
star += 1  # beated record move


scoring with points are problem: how evaluate time and move variables to achieve fair scoring, where skilled player gets more points and unskilled player less points.

i could do this:

var move = 10.0 * 300  # multiplied with score per move
var time = 5.0 * 100   # multiplied with score per sec
var pnts = (move / time * 1000)  # 6000


but scoring points like this makes no sense, you can beat level with more time and move that records and get more points and 1 star (because you didn't beat records)

• Usually stars on a level are specific to that level and either by time or moves, but not both. Time is a poor measure in case you can replay the level. Nothing stops a player from just refilling the level by playing it again and using a fraction of original time. Commented Aug 11, 2023 at 7:57
• You can also just make two leaderboards Commented Aug 11, 2023 at 9:02
• Is the record you're beating fixed? If you update the record each time the player beats it, then players who find a really good solution first are penalized vs players who find a bad solution, then a slightly better one, then a slightly better one, etc. Since low numbers of both moves and points are good, it doesn't make sense to put them on opposite sides of the division: you either want them both on top (where smaller scores are better, like in golf) or both on the bottom (where higher scores are better). Commented Aug 11, 2023 at 13:04
• @DMGregory record are fixed by difficulty of level, basically you need something to compare with (minimum required moves and sec to beat). Stars are always 1,2,3, but points have huge range. less moves and timesec gives more points better for players, so you can challenge with other players. Probably i need refuse either move or time Commented Aug 11, 2023 at 13:31
• That sounds more like a "Par" or "Target Score" than a "Record", then. Commented Aug 11, 2023 at 13:34

Myself, I'd avoid non-linearity in the scoring system. It's hard for a player to do division in their head to understand how they got a particular score or predict how much finishing a little faster would change their score. Division also gives you a steep hyperbolic scoring curve with a long shallow tail, meaning you have to deal with a very wide range of scoring values, even though most scores from not-great to not-good will be very similar. That can be demotivating for a player who gets a meh score, sees astronomical scores in the leaderboard, but makes only modest gains when they re-try the challenge: it seems like they'll never get to those top scores.

Instead, I'd recommend keeping your scoring system linear. Add together a Move Bonus and a Time Bonus. Each one starts at a high value, and you subtract an increment from it for each move taken or each second elapsed. Something like...

moveBonus = max(1000 - 25 * movesTaken, 0)

timeBonus = max(1000 - 1 * secondsTaken, 0)

score = moveBonus + timeBonus


This keeps the scores bounded in a controllable range (here 0-2000), and the rate of score improvement is uniform over that whole range. So a player who shaves 1 move off their solution always gets 25 more points, whether it was their 30th move they eliminated or their 10th. A player who finishes 1 second faster always gets 1 more point. That makes it easy for players to understand, and anticipate how their score can improve, so they're more motivated to keep climbing up the high scores table.

It also makes it easy to reason about the relative value of different kinds of optimization. If shaving off a move earns 25 points and shaving off a second earns 1 point, then it's worth going up to 24 seconds out of your way if it saves you a move, or you'd have to be 26 seconds faster to be worth taking a 1-move-longer route that's easier to speedrun.

This does have a downside though: somewhere, that straight line linear falloff bottoms-out where it hits zero. With the numbers I've chosen above, that's at $$\\frac {1000} {25} = 40\$$ moves and $$\\frac {1000} {1 \cdot 60 \frac s {\text{min}}} = 16:40\$$ minutes. Players who take more moves or more time than this won't earn any bonus points, or see any benefit from improving their solutions by a small amount. To minimize the impact of this, you generally want to choose your max bonus and falloff increment so that this bottoming-out point sits beyond the first attempt results you see from most new players - so most people will only see a zero time bonus if they go AFK mid game or something.