In another question, you helped me to build a simulation algorithm for soccer. I got some very good answers there. Thanks again!
Now I’ve coded this algorithm. I would like to improve it and find little mistakes which could be in it. I don’t want to discuss how to solve it – as we did in the last question. Now I only want to improve it. Can you help me again please?
- Are there any mistakes?
- Is the structure of the nested if-clauses ok? Could it be improved?
- Are the tactics integrated correctly according to my description?
Tactical settings which should have an influence on the randomness:
- $tactics[x] adjustment (1=defensive, 2=neutral, 3=offensive): the higher the value is the weaker is the defense and the stronger is the offense
- $tacticsx speed of play (1=slow, 2=medium, 3=fast): the higher the value is the better are the opportunities but the higher is the risk of getting a quick counter attack
- $tacticsx distance of passes (1=short, 2=medium, 3=long): the higher the value is the less but better opportunities you get and the more often you are offside
- $tacticsx creation of changes (1=safe, 2=medium, 3=risky): the higher the value is the better are your opportunities but the higher is the risk of getting a quick counter attack
- $tactics[x] pressure in defense (1=low, 2=medium, 3=high): the higher the value is the more quick counter attacks you will have
- $tactics[x] aggressivity (1=low, 2=medium, 3=high): the higher the value is the more attacks you will stop by fouls
Tactic 0 and tactic 4 are partly integrated in the rest of the engine, not needed in this function.
The current algorithm:
Update (2014): A few years later, I have now released the full code base of the game as open-source on GitHub. You’ll find the specific implementation of this simulation in this file, if anyone is interested.
In general, it looks like this is a fairly complicated problem, and I’m not sure how efficient you’ll get it.
That said, I have seen some things which would decidedly help you.
First I would type the variables in the parameters. This may not necessarily make your code faster, but it would make it easier to read and debug. Next, I would remove the $teamname_att, $teamname_def parameters and simply have those as values in the associative $strength_att, $strength_def arrays. Since this data is always paired up anyway, this will reduce the risk of accidentally using one team’s name as a reference to the other team.
This will make it so you will not have to continually look up values in arrays:
You have three helper functions which all have the pattern:
Since this means that you have to create an extra variable (something which can be costly) each time you run the function, use these instead:
I couldn’t help but notice this pattern coming up consistently:
My general experience is that if you move the concatenation of $matchReport into comment_action, then it will be just slightly faster (Generally less than a dozen milliseconds, but since you’re calling that function a half-dozen times inside of a recursive function, this could shave a couple tenths of a second per running).
I think that this would flow much better (both from a reader’s perspective, and from
Finally, there are several times where you will use the same call to the same function with the same parameter. Make that call up front:
Hope this helps.
I (quickly) read through it and I noticed a couple of things:
The percentage a red / yellow card is handed out is the same in all thirds of the field, is this intentional? I’m not a soccer guy, but I’d say that offences are more likely to happen on the last third of the field, than on the first. (Because if you’re on the first, you’re likely defending)
The percentage to determine that a penalty is scored is the same for each team, however some teams, or rather players, are more likely to score a penalty than others.
You’re not taking into account corner kicks, possible injuries after a foul, or goals scored using the head (which might be worth mentioning in the report).
Apart from that, you’ll just need to run this simulation a lot of times and see if the values you chose are correct; tweak the algorithm. The best thing to do is hand tweak it (eg. read all the constants from a file and run a couple of hundred simulations with different values and different teams), the easiest thing to do is probably to implement a Genetic Algorithm to try and find better values.
Basically what you have here is genuine gameplay / ai code, so you might want to read up on techniques used by game studios to manage this type of code. (One thing is to put the variables in a google spreadsheet which you can then share / tweak more easily, for example).
Also, even though you’re missing some things that a real soccer match has, there’s no point trying to be as realistic as possible because generally in these cases it’s more important to provide nice gameplay than it is to provide an accurate simulation.
Yous seem to be missing:-
How often are these values going to be checked? If it’s going to be in use by a lot of people and constantly recursing over those if/else statements, I can see you eating up a lot of memory and running quite slowly.
Perhaps you could but a few switches in there to replace some of the if’s?
That’s all I can see for speed improvement. As for the algorithm itself, I’ll have to peruse over that a bit later if no one else does.