[Tutorial] ELO Ranking System in Pawn

For scripting examples for learning how to use AMXX.
User avatar
Archive-Poster
Posts: 1367
Gender:
United States of America

[Tutorial] ELO Ranking System in Pawn

Post by Archive-Poster »

ELO Ranking System in Pawn

Hello,
In this post I'll explain how to use the ELO Ranking System in Pawn.

So first, what's ELO?
Originally Posted by Wikipedia
The Elo rating system is a method for calculating the relative skill levels of players in competitor-versus-competitor games such as chess.
It is named after its creator Arpad Elo, a Hungarian-born American physics professor.
So ELO is used to determine a players skill, this can be simply done using this formula :

Code: Select all

New ELO = ELO + ELO_K * ( ELO_SCORE_WIN / LOSE - E(XPECTATION)) 
ELO_K is maximum increase / decrease of Skill. You should use 15 for Beginner Matches and 25 for normal / professional matches. If you want more significant changes use about 50.
Originally Posted by Christopher Allen & Shannon Appelcline
It's a good model because, using the two formulas, it means that a great player gains little from beating an average player, but an average player gains a lot from beating a great player.
To calculate E(xpectation), so what the system is expecting from the player based of his skill, we use this formula :

Code: Select all

E formula : 1 / [ 1 + 10 ^ ( [ELO ENEMY - ELO OWN] / 400 ) ]
Well, it's not very hard to transfer this formular into Pawn, it would look like this :

Code: Select all

E_P1 = 1 / ( 1 + 10 ^ (( g_iELO[P2] - g_iELO[P1] ) / 400 )) 
E_P2 = 1 / ( 1 + 10 ^ (( g_iELO[P1] - g_iELO[P2] ) / 400 )) 

g_iELO[P1] = floatround(g_iELO[P1] + ELO_K * ( ELO_SCORE_1ST - E_P1), floatround_floor) 
g_iELO[P2] = floatround(g_iELO[P2] + ELO_K * ( ELO_SCORE_2ND - E_P2), floatround_floor) 
But what is "ELO_SCORE_1ST"?

ELO_SCORE_1ST is the multiplier for the winner, with descending places the number gets smaller, here the numbers I use :

Code: Select all

#define ELO_SCORE_1ST     1.0 
#define ELO_SCORE_2ND     0.85 
#define ELO_SCORE_3RD     0.425 
#define ELO_SCORE_4TH     0.2125 
#define ELO_SCORE_5TH     0.10625 
#define ELO_SCORE_6TH     0.053125 
#define ELO_SCORE_7TH     0.0265625 
#define ELO_SCORE_8TH     0.01328125 
This code is for two players and would work fine, but what happens if we have more than two players?
The code wouldn't work with more than two players, because ELO is made for duels. So we have to find another way.
And finding this way isn't so hard. If you just get the base Idea of ELO, that it is made for duels, it's easy to add more players.

So, if we have three players, we have to think like this :

Code: Select all

A wins vs. B 
B wins vs. C 
So basically we add another duel between B and C in our code which would look like this :

Code: Select all

E_P1 = 1 / ( 1 + 10 ^ (( g_iELO[P2] - g_iELO[P1] ) / 400 )) 
E_P2 = 1 / ( 1 + 10 ^ (( g_iELO[P1] - g_iELO[P2] ) / 400 )) 
E_P3 = 1 / ( 1 + 10 ^ (( g_iELO[P2] - g_iELO[P3] ) / 400 )) 

g_iELO[P1] = floatround(g_iELO[P1] + ELO_K * ( ELO_SCORE_1ST - E_P1), floatround_floor) 
g_iELO[P2] = floatround(g_iELO[P2] + ELO_K * ( ELO_SCORE_2ND - E_P2), floatround_floor) 
g_iELO[P3] = floatround(g_iELO[P3] + ELO_K * ( ELO_SCORE_3RD - E_P3), floatround_floor)
You can advance it however you like, for my Bunnyhop Racers Plugin I use it for up to eight players.

Code: Select all

new szHUD1[64], szHUD2[64], szHUD3[64], szHUD4[64], szHUD5[64], szHUD6[64], szHUD7[64], szHUD8[64]

new Pri = g_PartyData[id2][FIRST]
new Sec = g_PartyData[id2][SECOND]
new Tri = g_PartyData[id2][THIRD]
new Qua = g_PartyData[id2][FOURTH]
new Qui = g_PartyData[id2][FIFTH]
new Sen = g_PartyData[id2][SIXTH]
new Sep = g_PartyData[id2][SEVENTH]
new Oct = g_PartyData[id2][EIGHTH]
    
new E_P1, E_P2, E_P3, E_P4, E_P5, E_P6, E_P7, E_P8

static iOELO1, iOELO2, iOELO3, iOELO4, iOELO5, iOELO6, iOELO7, iOELO8
static szName1[33], szName2[33], szName3[33], szName4[33], szName5[33], szName6[33], szName7[33], szName8[33]
    
E_P1 = 1 / ( 1 + 10 ^ (( g_iELO[Sec] - g_iELO[Pri] ) / 400 ))
E_P2 = 1 / ( 1 + 10 ^ (( g_iELO[Pri] - g_iELO[Sec] ) / 400 ))
E_P3 = 1 / ( 1 + 10 ^ (( g_iELO[Sec] - g_iELO[Tri] ) / 400 ))
E_P4 = 1 / ( 1 + 10 ^ (( g_iELO[Tri] - g_iELO[Qua] ) / 400 ))
E_P5 = 1 / ( 1 + 10 ^ (( g_iELO[Qua] - g_iELO[Qui] ) / 400 ))
E_P6 = 1 / ( 1 + 10 ^ (( g_iELO[Qui] - g_iELO[Sen] ) / 400 ))
E_P7 = 1 / ( 1 + 10 ^ (( g_iELO[Sen] - g_iELO[Sep] ) / 400 ))
E_P8 = 1 / ( 1 + 10 ^ (( g_iELO[Sep] - g_iELO[Oct] ) / 400 ))

get_user_name(Pri, szName1, charsmax(szName1))
get_user_name(Sec, szName2, charsmax(szName2))
get_user_name(Tri, szName3, charsmax(szName3))
get_user_name(Qua, szName4, charsmax(szName4))
get_user_name(Qui, szName5, charsmax(szName5))
get_user_name(Sen, szName6, charsmax(szName6))
get_user_name(Sep, szName7, charsmax(szName7))
get_user_name(Oct, szName8, charsmax(szName8))
    
g_iELO[Pri] = floatround(g_iELO[Pri] + ELO_K * ( ELO_SCORE_1ST - E_P1), floatround_floor)
g_iELO[Sec] = floatround(g_iELO[Sec] + ELO_K * ( ELO_SCORE_2ND - E_P2), floatround_floor)
g_iELO[Tri] = floatround(g_iELO[Tri] + ELO_K * ( ELO_SCORE_3RD - E_P3), floatround_floor)
g_iELO[Qua] = floatround(g_iELO[Qua] + ELO_K * ( ELO_SCORE_4TH - E_P4), floatround_floor)
g_iELO[Qui] = floatround(g_iELO[Qui] + ELO_K * ( ELO_SCORE_5TH - E_P5), floatround_floor)
g_iELO[Sen] = floatround(g_iELO[Sen] + ELO_K * ( ELO_SCORE_6TH - E_P6), floatround_floor)
g_iELO[Sep] = floatround(g_iELO[Sep] + ELO_K * ( ELO_SCORE_7TH - E_P7), floatround_floor)
g_iELO[Oct] = floatround(g_iELO[Oct] + ELO_K * ( ELO_SCORE_8TH - E_P8), floatround_floor)

formatex(szHUD1, charsmax(szHUD1), "%s --- %i --- %s%i --- %i ^n",szName1, iOELO1, iOELO1 - g_iELO[Pri] < 0 ? "-" : "+", iOELO1 - g_iELO[Pri], g_iELO[Pri])
formatex(szHUD2, charsmax(szHUD2), "%s --- %i --- %s%i --- %i ^n",szName2, iOELO2, iOELO2 - g_iELO[Sec] < 0 ? "-" : "+", iOELO2 - g_iELO[Sec], g_iELO[Sec])
formatex(szHUD3, charsmax(szHUD3), "%s --- %i --- %s%i --- %i ^n",szName3, iOELO3, iOELO3 - g_iELO[Tri] < 0 ? "-" : "+", iOELO3 - g_iELO[Tri], g_iELO[Tri])
formatex(szHUD4, charsmax(szHUD4), "%s --- %i --- %s%i --- %i ^n",szName4, iOELO4, iOELO4 - g_iELO[Qua] < 0 ? "-" : "+", iOELO4 - g_iELO[Qua], g_iELO[Qua])
formatex(szHUD5, charsmax(szHUD5), "%s --- %i --- %s%i --- %i ^n",szName5, iOELO5, iOELO5 - g_iELO[Qui] < 0 ? "-" : "+", iOELO5 - g_iELO[Qui], g_iELO[Qui])
formatex(szHUD6, charsmax(szHUD6), "%s --- %i --- %s%i --- %i ^n",szName6, iOELO6, iOELO6 - g_iELO[Sen] < 0 ? "-" : "+", iOELO6 - g_iELO[Sen], g_iELO[Sen])
formatex(szHUD7, charsmax(szHUD7), "%s --- %i --- %s%i --- %i ^n",szName7, iOELO7, iOELO7 - g_iELO[Sep] < 0 ? "-" : "+", iOELO7 - g_iELO[Sep], g_iELO[Sep])
formatex(szHUD8, charsmax(szHUD8), "%s --- %i --- %s%i --- %i ^n",szName8, iOELO8, iOELO8 - g_iELO[Oct] < 0 ? "-" : "+", iOELO8 - g_iELO[Oct], g_iELO[Oct])

add(szELOHUD, charsmax(szELOHUD), szHUD1)
add(szELOHUD, charsmax(szELOHUD), szHUD2)
add(szELOHUD, charsmax(szELOHUD), szHUD3)
add(szELOHUD, charsmax(szELOHUD), szHUD4)
add(szELOHUD, charsmax(szELOHUD), szHUD5)
add(szELOHUD, charsmax(szELOHUD), szHUD6)
add(szELOHUD, charsmax(szELOHUD), szHUD7)
add(szELOHUD, charsmax(szELOHUD), szHUD8) 
I hope some people can use this. :D

Who is online

Users browsing this forum: No registered users and 1 guest