I have been a big fan of Insurgency over the last years. One of my biggest Problems with the game is the complete lack of a rating System in all Modes but firefight. Me myself, I mostly prefer not so overcrowded Push-Servers, meaning something from 5v5 to 8v8, however this creates some problems in regards to balancing that big 16v16 Servers DO suffer from too, but not as badly.
The thing is - obviously - the more people you randomly throw into teams, the more likely it is that thus’ teams will be balanced in the end. In other words: If two people throw a dice 16 times, it’s more likely they will have a similar result compared to throwing their dices only 8 times.
Also this problem is worsened by friends playing together and (usually) performing better, in fact the whole reason I began thinking about a rating system is because on my own 6v6 Push-Server, the enemy team would usually start rage-quitting after a short time when I played with my mate, because the two of us were simply too good together. At this point I also thought it to be nice if you could tell the server that you WANT to play with somebody else, however if I’d be able to just say I always wanna play with my friend it would lead me to have something in the range of a 95% winrate.
There are a few obvious problems that intermediately come to mind when thinking about rating public Push games:
- many players don’t play for a full map, or maybe not even for a full round
- players may change team mid round
- gameplay is asymmetric and some maps favor one side, but best of 5 (which is the default) means that each team will play one side (attacker/defender) twice
- even best case scenario, it’s still teams of 6 or more, it might take a long time for ratings to converge on a meaningful value
- how to get the data in the first place
Today standard for ratingsystems are Bayesian-Networks, one incarnation of this technique is known as TrueSkill, for which there is a python-library which I am going to use. This library (or TrueSkill/Bayesian-Network-Rating in general) have some features which will solve some of my problems:
- weighted playtimes: I’ll be able to assign a percental playtime for a player in order to describe his impact to the game
- naitively rating multi-player or even by-numbers imbalanced teams
So lets tackle the other problems.
The outcome of a Map (of a best 5) is ultimately meaningless, what matters are the results of each round, so we will rate each round by it’s own. Also we can introduce a fake-player to each team, representing attacker/defender on each map. So basically, each side on a Map will be a “player” playing with the respective team and rising and falling in rating just as normal players.
The ultimate solution as soon as the system can balance the games by itself and put friends together in one team, will be to disable teamchanges altogether. There simply is no way to reliably model changes of team without introducing a insane level of complexity. The System cannot deal with a player being in two teams at once. As long as my System isn’t complete I will only count the player in the team he played more time in and subtract the time he player the other team from thus time. This is by no means a good solution thought, because what does it really mean if a player changes after 3⁄4 of game to the other team and the teams he changed to wins? Maybe the other team was winning already and he change cause’ pussy, but maybe he was the best player in his old team, yet decided to change for balance reasons and carried the team he changed to to victory. In the latter case he would still be counted as a “loser” cause he played more time on the first team.
This will be a tricky one. Especially as I will not have access to all matches of players but only the matches they play on my server. I COULD give people different starting points based on for example their playtime or what they initially buy. I have yet to explore if there is any good in doing this. But given that even after months around 70% of the people connecting to my server did never play on it before I will have to introduce some kind of metric sooner or later.
Getting the Data
In order to get the Data I will have to write a Sourcemod-plugin. I hate writing SourcePawn, so I will keep it as basic as possible and send the data to my python backend as soon as possible. Sourcemod allows me to get callbacks on certain Events, in my case:
- EventRoundStart (log all players ingame)
- EventRoundEnd (log winner and players)
- EventTeamchange (initial connect is a teamchange from 0 [NO_TEAM] to X)
- EventPlayerDisconnect (log the player that disconnected)
There are basically two ways I could get the data out of SourcePawn: Via a socket or via a logfile. I decided that the most reliable way would be to write the data to file, only later I noticed that insurgency does not always honor ‘sv_logflush’ and will still write the logs in bulks (be it in smaller ones than without the directive). While this is an annoyance, because you don’t get instant feedback after a round. I will ignore it for now. Eventually I will switch the system to use logfile and sockets in parallel but that means I have to be careful as to not interpret log-lines twice/lose them if my python backend is ever down.
I use a simple format that looks something like this:
I also remove ’ , ‘ and ’ | ‘ from the player names in SourcePawn, this is also not a perfect solution, but people use too much shit-characters in their names anyway.
- A great article from Juho Snellman which inspired me to create the system in the first place
- The Math Behind TrueSkill a detailed paper on the inner workings of TrueSkill
- TrueSkill python-libary
- Cover picture based uppon tommyvideo’s work, licensed CC0
Feel free to send me a mail to share your thoughts or maybe you even want to share data from your server!