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?
Quote:
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 :
PHP Code:
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.
Quote:
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 :
PHP Code:
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 :
PHP Code:
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 :
PHP Code:
#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 :
PHP Code:
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 :
PHP Code:
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.
PHP Code:
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.
You may also use my
Calculator to generate test results.
__________________