|
Player Rating: Quick View of the Algorithm
Due to the fact that the final algorithm appears overly complicated at first (and maybe second) glance, a simplified view of the core equations is given here. These equations deal with a competition between two players (playerA and playerB). In designing this algorithm, the following assumptions were made. - the player with the higher rating is the better player
- a player should earn more points for defeating a player that is better than him or her
- if two equal players tie, the rating of neither player should change
- since winning is the important thing, a decisive win is just as valuable as a narrow victory
- as a player competes in more games, his or her rating will approach his or her true rating
delta = playerA_rating - playerB_rating
predicted_outcome = 1.0 / (1.0 + exp(-delta/T))
if( playerA wins ) rating_adjustment = 1.0 - predicted_outcome
if( playerB wins ) rating_adjustment = 0.0 - predicted_outcome
if( tie score ) rating_adjustment = 0.5 - predicted_outcome
playerA_rating_adjustment = rating_adjustment
playerB_rating_adjustment = -rating_adjustment
The "predicted_outcome" equation will yield a number between 0 and 1. A value of one predicts that playerA will always win; a value of zero predicts that playerA will always lose, and a value of 0.5 predicts that the players will always tie. The rating points that a player earns in a game (1 for a win, 0 for a loss, and 0.5 for a tie) can then be offset by the predicted value to give a final adjustment to the player's overall rating. Thus, if playerA is supposed to defeat playerB, and that happens, then the ratings for both players were correct and no change will be made. However, if playerA is supposed to defeat playerB, and playerB wins, then playerB will gain the maximum rating points possible (and playerA will lose the maximum rating points). As you can see, this is just a feedback system that tries to zero in on a player's "true" rating by making small adjustments as more "measurements" are taken (i.e., more games are played).
In order to allow this system to converge rapidly to the correct rating for each player, a correct value of "T" must be chosen, as well as an appropriate multiplier for the final rating adjustment. See Tuning the Algorithm for details on the numbers that were chosen.
Detail Equations
The following is a step-by-step explanation of how a player's rating is adjusted after playing in a game. Note that the ELO system (which this is based off of) is a "zero sum" algorithm. This means that if playerA gains 5 rating points in a game vs. playerB, then playerB must lose 5 points in the same game (5?5 = 0). The result of this is that in step 7 (where a player's rating adjustment is scaled if it is too large), if one player's rating adjustment is scaled, then all players' rating adjustments must be scaled. Also, "Score Per Hour" is used instead of "Score" to account for the fact that in games such as MechWarrior 4, players can join and leave at any time during the game, and using raw scores would give a distinct advantage to the player that was in the game the longest. - Get the Score Per Hour (SPH) for each ZoneStats enabled player in the game (players who have a password only). Players are only compared against enabled players on opposing teams in team games. SPH = Score / Hours_In_Game.
- Acquire the current ratings for all enabled players from the ZoneStats database. If a player doesn't have a rating, give the player a rating of 500.
- Compute the predicted outcome of each 1 on 1 contest that occurred in this game based on each player's previous rating (see equation 1).
- Compare the SPH for each pair of players to determine their individual baseline rating adjustments (see equation 2).
- Get the actual individual rating adjustment by scaling based on the time the two players were in the game (see equation 3).
- Get each player's overall ranking adjustment by summing together all of that player's individual adjustments vs. other enabled players (see equation 4).
- Scale each player's rating adjustment if any of the player's gained/lost more than 2 rating points per minute in the game (see equations 5 and 6). This is done to prevent any single player from gaining too many rating points in one game.
- Adjust each player's overall rating based on the result of step 7 and adjust his or her rankings appropriately.
Equation 1:
Predicted_outcome = 1.0 / (1.0 + exp( [opponent's_rating ? my_rating] / T ) )
Equation 2:
If(my_score_vs_opp > opp_score_vs_me) indiv_result = 1.0 ? predicted_outcome
If(my_score_vs_opp < opp_score_vs_me) indiv_result = 0.0 ? predicted_outcome
If(my_score_vs_opp == opp_score_vs_me) indiv_result = 0.5 ? predicted_outcome
Equation 3:
time = MAX_GAME_LENGTH => time is in minutes
if ( my_time_in_game < time ) time = my_time_in_game
if ( opp_time_in_game < time ) time = opp_time_in_game
indiv_result = indiv_result * GAME_MULT * time
Equation 4:
Rating_offset = SUM { indiv_result } vs. all opponents
Equation 5:
Highest_rating_offset = this is the absolute value of the rating offset for the player that is most distant from 0.0
Time_in_game = the amount of time that the player with the highest_rating_offset was in the game
Scale = time_in_game * GAME_MULT / highest_rating_offset
If ( scale > 1.0 ) scale = 1.0 (we only want to scale scores down if they are too large, we don't want to increase them)
Equation 6:
Final_rating_offset = rating_offset * scale
Variables:
T = 120.0 (this variable determines the "spread" in this rating system. The larger T is, the greater the amount of points that the "best" players will have.
GAME_MULT = 2.0 (this variable, along with MAX_GAME_LENGTH, determines the maximum amount of points that a player can gain in one game)
MAX_GAME_LENGTH = 20.0 (minutes)
|