Unfair racing with horses

Started by
7 comments, last by Xai 16 years, 10 months ago
I wanted to make a horse racing game. Not a game with good graphics and so where you really see 3D horses race. Only a game where you have some images move from one side to the other side, and the first image to move to the right side is the horse winner. But of course, no game without problemes. The main problem for this game is to find a good algorithm for moving the horses. Each horse has some properties, the main properties are minmove, maxmove, totalmove (I am willing to change these properties, adding new ones or deleting some if I find a better algorithm). The first movesystem I had was that each horse moved between 1-10 steps each "turn" and that totalmove was 100. So each horse had to move 100 steps. That was the 'default' properties. The problem with this is that if you just increase the movement of the horse so it can move 2-10 steps each turn then that horse gets a big advantage. Instead of a 50/50 result with 2 horses and 100 races, it's about 75/35 result (there is a possibility that both horses win, hence the reason why it doesn't sum to 100) with 100 races and one horse has that little extra property bonus. So I thought that "Ok, I have to change this somehow. What about this alternative?" and I came up with this movement system: At the start of a race, each horse randomises a value (x) between minmove and maxmove. Then after x turns, this horse moves and then randomises a new value x, and then this repeats until the end of the race (when one or more horses has reached their goal). But then I noticed that this alternative was even worse than the earlier one, mainly because of two reasons: 1. The probability that two horses finish at the same time is close to zero. (Only happens in about 2 of 100 races for me) 2. The advantage of a horse with a 11-20 movement instead of 10-20 is way to big. A result of about 85/15 wins instead of about 50/50. And so, I come to you here and ask for asisstance. I'd like a movement system where the advantages of a small increase in a horse property aren't so high so the result of 100 races is 85/15 or 75/35, but about 55/45 maybe. When increasing a property more than 1, then of course the advantage should grow a little more. Any suggestions how I can modify my algorithms? Or any suggestion about an alternative one? Or any other questions or suggestions? Greetings, Simon from Sweden
Advertisement
The obvious solution would be to use floating-point values, so that you have an arbitrary resolution within which to define the bounds - maybe 10.1f-20 would produce fairer races.

Provided you are producing the random values correctly (i.e. uniformly) within their range, the expected displacement of each horse per frame would be (speedmin + speedmax) / 2. Assuming a long track, the same quantity scales up to be the expected average speed. Hence, if horse (i) has range
[speed(i)min, speed(i)max] and we define:

v(i) = (speed(i)min + speed(i)max) / 2

for each horse (1...n) then the probability of horse (j) winning the race would be:

P(j) = v(j) / ∑ni=1 v(i)

It's possible to invert this equation so that you can define speed(i)min to fit predetermined odds, but it would probably be easier to rewrite the system in a more appropriate goal. Of course, we could go on and make the simulation as complicated as we wanted, perhaps with statistics for fatigue, pace anticipation, competitiveness and so forth, which would lead to a whole range of strategies, but let's keep things simple for the moment.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Quote:Original post by TheAdmiral
The obvious solution would be to use floating-point values, so that you have an arbitrary resolution within which to define the bounds - maybe 10.1f-20 would produce fairer races.
Yeah, I also thought about something like that after a while, I multiplied all properties (speedmin, speedmax and steps) with 10 on the first movement style, and then increased speedmin by 1 on one of the horses, the advantage result was much more satisfying. But what you mean with 10.1f-20, I'm not sure of..
And do you suggest on using floating-point values on the first or second style? (x steps per turn, or 1 step per x turns)

Quote:Provided you are producing the random values correctly (i.e. uniformly) within their range, the expected displacement of each horse per frame would be (speedmin + speedmax) / 2. Assuming a long track, the same quantity scales up to be the expected average speed. Hence, if horse (i) has range
[speed(i)min, speed(i)max] and we define:
Yes, the random values are produced uniformly, of course. I don't see any reason why they shouldn't be that.
The problem with long tracks is that the longer the track is, the advantage for a "faster" horse grows - as the horse has more time to extend it's track advancement compared to the other horse. So the factor "steps" should be taken in notice in some formula, right? Probably steps/(speedmin+speedmax)/2

Quote:v(i) = (speed(i)min + speed(i)max) / 2

for each horse (1...n) then the probability of horse (j) winning the race would be:

P(j) = v(j) / ∑ni=1 v(i)
Let's see if I have got the meaning of this equation:
The probability of a horse to win the race (P(j)) is equal to the earlier equation divided with the sum of all the earlier equations (for each horse). But what does i=1 indicate in the above equation?
(I'm planning on studying more Mathematics on university later, but I'm already now eager to learn more :))

Quote:It's possible to invert this equation so that you can define speed(i)min to fit predetermined odds, but it would probably be easier to rewrite the system in a more appropriate goal. Of course, we could go on and make the simulation as complicated as we wanted, perhaps with statistics for fatigue, pace anticipation, competitiveness and so forth, which would lead to a whole range of strategies, but let's keep things simple for the moment.

Admiral
Good that you mentioned that it can be inverted, that's really something that I need to think of when balancing my game(s).
Indeed it can get complicated, but that's definetly something for the future. The main project now is to make a decent, stable, balanced horse movement style.

Thank you very much for your ideas so far, I hope you're able to respond to my thoughts above.
What about picking the ending order *before* the race, and then simply showing visuals that approximate that theoretical race?

You could then, for instance, speecify that for some proportion of races 1st and 2nd place are involved in a 'photo finish' and then approximate that outcome visualy.
Quote:Original post by Zomis
Quote:Original post by TheAdmiral
The obvious solution would be to use floating-point values, so that you have an arbitrary resolution within which to define the bounds - maybe 10.1f-20 would produce fairer races.
Yeah, I also thought about something like that after a while, I multiplied all properties (speedmin, speedmax and steps) with 10 on the first movement style, and then increased speedmin by 1 on one of the horses, the advantage result was much more satisfying. But what you mean with 10.1f-20, I'm not sure of..
And do you suggest on using floating-point values on the first or second style? (x steps per turn, or 1 step per x turns)
Sorry - I was using C++ notation for the floating values. By 10.1f-20 I just meant values continuously in the range [10.1, 20] (which is incidentally, almost equivalent to what you just described). My intention was to have the horse move x steps per turn where x could be fractional.

Quote:The problem with long tracks is that the longer the track is, the advantage for a "faster" horse grows - as the horse has more time to extend it's track advancement compared to the other horse.
Again, we have crossed wires. By 'long track' I just meant a sufficiently large sample-space to produce a reasonable probability. As it turns out, I got this wrong anyway [dead] - as you say, the longer the track, the shorter the odds.

Quote:Let's see if I have got the meaning of this equation:
The probability of a horse to win the race (P(j)) is equal to the earlier equation divided with the sum of all the earlier equations (for each horse). But what does i=1 indicate in the above equation?
You have the right idea. The i=1 sticks out because I couldn't line it up properly in the HTML, but it's just sigma notation. '∑ni=1' simply means 'the sum from i=1 to i=n of...', as you worked out.

Edit: I've had a think, but I'm still a little stuck.

We've established that P(j) is the expected distance that horse (j) will travel each turn. We also need to take into account the length of the track, L, say.

As I see it, the probability that horse (j) is the first one to the finish line is:

P(j)win = P(j) has travelled L or more . PNo other horse has travelled L or more

The notation is getting a little unwieldy, but I'll persevere. Both factors are sums-to-infinity of Bernoulli random variables. I can get the first one into a closed form, but not the second.

P(j) has travelled L or more = P(j) has travelled exactly L + P(j) has travelled exactly L+1 + P(j) has travelled exactly L+2 + ...
P(j) has travelled L or more = (P(j))L + (P(j))L+1 + (P(j))L+2...
P(j) has travelled L or more = ∑∞i=L(P(j))i
P(j) has travelled L or more = (P(j))L / (1 - (P(j)))

I'm in no hurry to type that out again. That last step is closure of a geometric series. I'm not so sure that the second factor generalises past the two-horse case, though:

PNo other horse has travelled L or more = PNo other has travelled exactly L + PNo other has travelled L+1 + P has travelled L+2 units + ...
PNo other horse has travelled L or more = ∑∞i=L 1 - (1 - P(j))i

I feel I should step aside and let someone more qualified take over before my fingers drop off... Any takers?

Admiral

[Edited by - TheAdmiral on May 21, 2007 7:00:48 PM]
Ring3 Circus - Diary of a programmer, journal of a hacker.
Quote:Original post by Rockoon1
What about picking the ending order *before* the race, and then simply showing visuals that approximate that theoretical race?

You could then, for instance, speecify that for some proportion of races 1st and 2nd place are involved in a 'photo finish' and then approximate that outcome visualy.

Unfortunately, that is an approach I don't want to take. I don't want to randomize a random order based on n values (where n is the horse count in a race)

I want to do a real race with real (or, err...computeristic) horses.
Quote:Original post by TheAdmiral
Sorry - I was using C++ notation for the floating values. By 10.1f-20 I just meant values continuously in the range [10.1, 20] (which is incidentally, almost equivalent to what you just described). My intention was to have the horse move x steps per turn where x could be fractional.
Ok, then I understand. I think that would be the best solution, yes. I'm having a few more ideas in mind though, but as you said earlier "Let's keep it simple for now" ;)
Anyways, my new idea was that each horse had a deltamove value, so that their next move is randomized based on their last move + a randomized delta value. So the deltamove value defines how much faster/slower the horse will go this turn compared to the last turn. Deltamove has a min and a max value of course.
I'm not sure at all if that would be a good thing to add, I'm afraid it'd only make the racing be even more unfair.

Quote:
Quote:The problem with long tracks is that the longer the track is, the advantage for a "faster" horse grows - as the horse has more time to extend it's track advancement compared to the other horse.
Again, we have crossed wires. By 'long track' I just meant a sufficiently large sample-space to produce a reasonable probability. As it turns out, I got this wrong anyway [dead] - as you say, the longer the track, the shorter the odds.
Yes, so it seems like a track shouldn't be too long and not too short. But I think a value of 100 is quite good, at least for now. I've made it so that horses can have longer or shorter tracks (something like inner or outer track, or the track length can define which races they are allowed to compete in, and so on. So the track length will remain a variable - unless someone convinces me to make it constant.)

Quote:Edit: I've had a think, but I'm still a little stuck.
So am I, I'm afraid. I've also tried working with the probabilities lately.

Quote:We've established that P(j) is the expected distance that horse (j) will travel each turn. We also need to take into account the length of the track, L, say.

As I see it, the probability that horse (j) is the first one to the finish line is:

P(j)win = P(j) has travelled L or more . PNo other horse has travelled L or more

Is the "." notation in that equation a Dot product?

Quote:The notation is getting a little unwieldy, but I'll persevere. Both factors are sums-to-infinity of Bernoulli random variables. I can get the first one into a closed form, but not the second.

P(j) has travelled L or more = P(j) has travelled exactly L + P(j) has travelled exactly L+1 + P(j) has travelled exactly L+2 + ...
P(j) has travelled L or more = (P(j))L + (P(j))L+1 + (P(j))L+2...
P(j) has travelled L or more = ∑∞i=L(P(j))i
P(j) has travelled L or more = (P(j))L / (1 - (P(j)))

I'm in no hurry to type that out again. That last step is closure of a geometric series. I'm not so sure that the second factor generalises past the two-horse case, though:

PNo other horse has travelled L or more = PNo other has travelled exactly L + PNo other has travelled L+1 + P has travelled L+2 units + ...
PNo other horse has travelled L or more = ∑∞i=L 1 - (1 - P(j))i

I feel I should step aside and let someone more qualified take over before my fingers drop off... Any takers?

Admiral
The probability part is indeed complicated, I'll continue to check wikipedia topics about this part. If anyone knows a good probability article that can be useful to me, please post it. My approach towards the probability problem is more like
For horse i to win, horse i must have moved >= all other horses. And if H1 has a property (min-max/length) of 1-3/5 and H2 has 2-3/5. Then at turn 1 there's 6 probabilities:
H1 1 H2 2 - H1 has 4 steps left, H2 has 3 steps left.
H1 1 H2 3 - H2 will win no matter what.
H1 2 H2 2 - H1 3 left, H2 3 left = Game equal
H1 2 H2 3 - H1 3 left, H2 2 left = H2 has advantage
H1 3 H2 2 - H1 2 left, H2 3 left = H1 has advantage (this is the only occation where H1 will gain a small advantage on the turn)
H1 3 H2 3 - Both has 2 left, game equal.
And then do a descision tree or something like that based on these values. I'm not sure if this is a realistic way, but since I'm not an advanced probability mathematician, I hoped that this approach could make me find a faster algorithm. None found yet though :/

I've found some other values that might be interesting in this problem, I don't know how they could be used to find a probability chance though...

(L = track length, min = minspeed, max = maxspeed)
Average turns to finish race = L / ((Max + Min) / 2)
Min turns to finish race = L / Max
Max turns to finish race = L / Min
"TurnRange" (I don't really know what to call it, and I don't know what to use it for either... I almost don't even know what it actually calcs.) = (L / Min) - (L / Max)
"TurnRatio" (same as with "TurnRange") = (L / Min) / (L / Max)

(By the way, of course I want an algorithm that will work with more than 2 horses as well... but 2 horses is easiest to start with).

I hope someone can continue to discuss this probability with me (TheAdmiral is very welcome!), 2 brains think better than one. Now I'm off to wikipedia to study some more so that I can understand those formulas to 100 percent... or at least 99...
I confess you lost me with some of the maths, so this may have already been suggested... but, instead of horse A moving 10-20 per turn and horse B moving 11-20, couldn't horse B move 11-19 instead?

I'm sure you've probably already thought of it so I'll duck my head down now...
Truethfully you can model the horses in many ways, and then run them through testing for like 1000 races each computing there slowest, average, and fastest finish times ... to determine what "class" the are in competition wise.

So for instance you write a horse algorithm for simple random speed 10-20, and simple random speed 11-19. And compare them. Then you write code for a horse that is strong starter, weak finisher, and try it with different numbers. Then code for a horse that is "highly competitive" (runs faster for short while when near another horse), etc. Each of the horse personalities will use a set of static configuration inputs to be a particluar horse (my money is on "Dynamite Yonkers" to place), and then of course each horses code needs to use a random number generator during racing to make it any fun.

All told, you would be able to spend as much (or as little) time as you want making personality code. As long as you can save the personality selection / inputs to a file, you can test different sets any way you want, and select any given set for any given race.

And of course all horses have good days and bad days ... so you could give little 0.1 bonuses and minuses to random horses each different race also.

As for using the floating point. Floating point or microgrid is about the only good way to go, to get the level of fine variation you want.

Simply keep ALL nubmers in floating point, and then round the distance for diplay purposes only. Which is great also for photo finishes, you can have 2 horses which finish at the same time on screen (same pixel), but don't have exactly same floating point number ... so it is a "photofinish", where you show them which horse won "by a nose" (also known as a partial pixel).

:) good luck.

This topic is closed to new replies.

Advertisement