6
\$\begingroup\$

I wrote a small simulator to understand the Elo rating system. I can create players, matches and tournaments, and I want to be able to predict the match ending depending on the rating of each player and some randomness. At the beginning the ratings are all around the same values (say 600) and it appears to stay between 400 and 1600. This is what I've tried :

p1 and p2 are instances of Player, rating is an integer attribute.

def random_win(self):
    q = float(self.p2.rating)/float(self.p1.rating)
    if q>2:
        self.win_2()
    elif q<0.5:
        self.win_1()
    else:
        d = float(self.p2.rating)-float(self.p1.rating)
        lim = max(self.p1.rating, self.p2.rating)/2
        r = random.randint(-lim, lim)
        if r > d:
            self.win_1()
        else:
            self.win_2()

I'd like to know if there are some "official" ways of doing this, this custom one works quite fine but I think it can be improved or at least simplified. Any ideas ? The best would be to get something closer the World Chess Ratings.


Once the wins and losses calculated and stored into the Player as a list attribute, I calculate the new rating for each player using this algorithm.

\$\endgroup\$
5
\$\begingroup\$

World Chess Ratings are going to be skewed: people that lose are less likely to play than people who win, so it's quite possible that everyone who went to a single tournament and got wrecked is not going to play in tournaments anymore. And Elo is a measurement of skill, not skill itself, so of course it won't go past a certain value. A good chess player who played 1 competitive match has a lower rating than his playing strength. So even though his rating is lower, he'll win more than his rating suggests, that's why his rating goes up.

As such, your simulation is going to keep giving skewed results until you give each player a "skill" attribute which determines their real playing strength. That means each player would have a rating (which starts at 1000) and a skill (which starts at a randomized value between 0 and 2500 or so, where the distribution is, say, Gaussian), and where you used to compare rating, you compare skill instead. This should give you a more realistic simulation of Elo rating, but you'll still be assuming that players all play equally as much (which is not the case in real life).

\$\endgroup\$
  • \$\begingroup\$ Fair enough. I was going to reply to your comment but you made a more complete answer, so... Do you suggest to change the whole rating system ? How could I differentiate skill and rating ? \$\endgroup\$ – BusyAnt Jul 7 '16 at 13:19
  • \$\begingroup\$ @BusyAnt slightly updated answer - you just gotta add an attribute and use that \$\endgroup\$ – Pimgd Jul 7 '16 at 13:28
  • \$\begingroup\$ Then the skill would be (for example) the mean of the other players ratings that you've beaten, or something like this ? \$\endgroup\$ – BusyAnt Jul 7 '16 at 13:31
  • 3
    \$\begingroup\$ @BusyAnt skill doesn't change - ratings change. The rating is supposed to match the skill after enough games - imagine that skill is a variable which you cannot access but have to determine within several points... \$\endgroup\$ – Pimgd Jul 7 '16 at 13:41
  • \$\begingroup\$ "A good chess player who played 1 competitive match has a lower rating than his playing strength." This is very common in online games and is often called "smurfing" - someone who crushes at the high levels starts a new account and demolishes low level players. Imagine if Magnus Carlsen made a new persona and went to a low level chess tournament - those players probably wouldn't even recognize him! \$\endgroup\$ – corsiKa Jul 7 '16 at 20:55
3
\$\begingroup\$

Is your goal to calculate rating changes for the winner and loser in a match given their difference original ratings? If yes, you should look into an error function (integral of Gaussian function).

Update:
These values don't fit well in Gaussian function. This applet http://statpages.info/nonlin.html suggests 0.5*exp(-(x/217)^2), but the results are off: (0, 0.5); (100, 0.41); (200, 0.22)

A simple exponent 0.5*exp(-(x/(100*e))) seems to predict loser's chances correctly (0, 0.5); (100, 0.346); (200, 0.24)

Winners chances should then be 1-loser's_chances.

\$\endgroup\$
  • \$\begingroup\$ "Winners chances should be 1-loser chance" assuming no ties. \$\endgroup\$ – corsiKa Jul 7 '16 at 20:59
  • 1
    \$\begingroup\$ You can normalize it both ways. It can be "Bayesian probability in a game with no ties" or "the expected payoff -1 for losing, 0 for draw and +1 for winning". Both systems allow rating, but ratings will be different. \$\endgroup\$ – sixtytrees Jul 7 '16 at 22:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.