# Help with timebased scoring algorithm

Im trying to devise an appropriate scoring system for my game. The game in essense has a finite number of tasks to complete (say 20) and the quicker you complete these task, the more points you get. I had devised a basic way of doing this using bands of time multiplied by a score for that band multiplied by the number of tasks solved within that time band i.e.

(Time Band) = (Points) 1-5 sec = 15, 5-10 secs = 10, 10-20 secs = 5, 20-30 secs = 3, 40 secs onwards = 1,

So for example if I did 3 tasks in the 1-5sec band i'd get 15*3=45points, if i found 10 in the 20-30sec band i'd get 3*10=30 points.

Im sure there is a more mathematical way of doing this using powers of some kind but I just can't think how and hoping someone has already done something smilar..

• In what way do you want it to be improved? Oct 31, 2013 at 1:33
• Hi, at the moment I am defining the points bands but there must be a forumla that can be used to do that for me. The points / times are examples but basically the points are weighted as more when the time is closest to zero. Kind of like an exponential curve so once the time gets to a certain point, the points flatten out to be 1.
– Dave
Oct 31, 2013 at 2:08

MickLH's suggestion of fitting a smooth function to your chosen point values is a good one. However, you do need to exercise some care in choosing the kind of function you want to fit.

For example, if, as I presume, you want the player's base score to remain above 1 (or at least above 0) no matter how much time he takes, then using a function of the form a - b * log(x) may be a poor choice, since the logarithm will eventually grow larger than a/b: you'd at least have to modify the calculation to always clamp the result above zero.

A better choice might be a function that naturally tends towards a limit, such as a + b / (x + c) or a + b * exp(-x / c). Both of these tend towards the value a as x increases, so it may actually be best to fix a at the limit value we want (e.g. a = 1) and only vary b and c to achieve the best fit.

For example, I tried the following code in gnuplot (which has a nice non-linear fitting feature):

f(x) = a + b * exp(-x / c)           # define the function
a = 1; b = 15; c = 10                # initial guesses
fit f(x) '/tmp/data.dat' via b, c    # adjust b and c to fit the data


where the /tmp/data.dat file just contained the following values:

1   15
5   15
5   10
10  10
10  5
20  5
20  3
30  3
30  1
40  1
50  1
60  1
70  1
80  1
90  1
100 1


After a few milliseconds, gnuplot spat out the following adjusted values (which were pretty close to my initial guesses anyway, since I'd eyeballed it in advance):

b = 16.2064
c = 11.7286


Rounding these to b = 16 and c = 12, here's what the final fit looks like, plotted with:

plot '/tmp/data.dat' with linespoints, f(x) with lines Honestly, though, the initial guesses of b = 15 and c = 10 don't look bad either, they just tend to hug the lower corners of the data graph, whereas the fitted version runs closer to the middle of the range. In fact, if we drop the upper points from the data, f(x) = 1 + 15 * exp(-x / 10) starts to look like an excellent fit, at least at x = 1, x = 5 and x = 20 (the x = 10 and x = 30 points are a bit off, but in a pretty consistent fashion): Just pick whichever one seems more reasonable to you, or tweak them yourself.

• Thanks Ilmari and Mick for both of your fantastic answers! I really appreciate your time and effort in answering this question for me.. As mick suggested, I think this solution is the closest to what i need so i'll accept this as the 'answer' . Thanks again :)
– Dave
Oct 31, 2013 at 21:57

Fitting is the tool for the job. You can research least squares fitting for a more in-depth explanation. is only a simplified example.

I plotted your input on Maxima with this command:

plot2d([discrete,[ [1,15],[5,15],[5,10],[10,10],[10,5],[20,5],[20,3],[30,3],[40,1] ]]);


It looked logarithmic to me so I went ahead and fitted the natural logarithm to your points, then plotted to verify (and adjust coefficients).

plot2d([[discrete,[ [1,15],[5,15],[5,10],[10,10],[10,5],[20,5],[20,3],[30,3],[40,1] ]],20-log(x)*5.2],[x,1,40]);


And the plot itself for fun and pleasure: With all this said, you can just ask Wolfram Alpha to do it for you ;) http://www.wolframalpha.com/input/?i=fit+%5B1%2C15%5D%2C%5B5%2C15%5D%2C%5B5%2C10%5D%2C%5B10%2C10%5D%2C%5B10%2C5%5D%2C%5B20%2C5%5D%2C%5B20%2C3%5D%2C%5B30%2C3%5D%2C%5B40%2C1%5D

• Hey Mick,Thats exactly what I needed! thanks so much :) Now i can just call that equation passing in the time in seconds and get the score out.. I just didnt know how to work out what that equation should be. the wolfram alfa thing is great too and I'll be using that in the future for this kind of thing. Thanks again!
– Dave
Oct 31, 2013 at 3:17
• when i try to get this to work in excel it doesnt look right: =20 - (5.2*LOG( A1)) where column A has seconds from 1 to 240. also if i google the formula (20 - 5.2 * log(x)) the curve doesnt look right either..
– Dave
Oct 31, 2013 at 3:26
• If you want to google it you need to use the natural log properly. google would expect (20 - 5.2 * ln(x)) Oct 31, 2013 at 3:33
• ah, perfect! thanks again :) (its the same in excel too for those interested)
– Dave
Oct 31, 2013 at 3:37
• @Dave : I'd use Ilmari Karonen' algorithm, they've done your job for you :P Oct 31, 2013 at 7:52