Let’s Program A Prisoners Dilemma Part 4: Heaven or Hell, Let’s Rock!

Last time we wrote enough code to actually play the prisoner’s dilemma. Combined with the Saint and Devil prisoners we wrote we now have enough code to run some interesting experiments.

Heaven

Let’s start by putting together a group of nothing but saints and seeing what happens to them after a thousand rounds.

#A group of all saints
prisoners = createPrisoners(10, 0)
playPrisonersDilemma(prisoners, 1000)

Which results in this:

The Group’s Overall Score was -10000 in 1000 rounds with 10 prisoners

ID: 1 Score: -1000 Strategy: Saint

ID: 2 Score: -1000 Strategy: Saint

ID: 3 Score: -1000 Strategy: Saint

ID: 4 Score: -1000 Strategy: Saint

ID: 5 Score: -1000 Strategy: Saint

ID: 6 Score: -1000 Strategy: Saint

ID: 7 Score: -1000 Strategy: Saint

ID: 8 Score: -1000 Strategy: Saint

ID: 9 Score: -1000 Strategy: Saint

ID: 10 Score: -1000 Strategy: Saint

Because the saints always cooperate they all ended up with the same score. What is much more interesting is their group score, which is actually perfect.

Why is -10,000 perfect? In every round every pair can do one of three things: if both prisoners cooperate the pair loses only 2 points, if one prisoner cooperates but the other defects the pair loses 3 points and if both defect the pair loses 4 points. Ten prisoners means five pairs. Five pairs multiplied by the best case scenario of -2 points gives us -10 points per round. Multiply that by the 1000 rounds we played the game and you find out that the best possible score for a group of this size playing a game this long is in fact -10,000 points.

So, unsurprisingly, when you have a group made up of nothing but saints you get a really really good outcome.

Hell

Now let’s try the inverse and put 10 devil’s together.

#A group of all devils
prisoners = createPrisoners(0, 10)
playPrisonersDilemma(prisoners, 1000)

Which turns out like this:

The Group’s Overall Score was -20000 in 1000 rounds with 10 prisoners

ID: 1 Score: -2000 Strategy: Devil

ID: 2 Score: -2000 Strategy: Devil

ID: 3 Score: -2000 Strategy: Devil

ID: 4 Score: -2000 Strategy: Devil

ID: 5 Score: -2000 Strategy: Devil

ID: 6 Score: -2000 Strategy: Devil

ID: 7 Score: -2000 Strategy: Devil

ID: 8 Score: -2000 Strategy: Devil

ID: 9 Score: -2000 Strategy: Devil

ID: 10 Score: -2000 Strategy: Devil

The devils also wound up with a ten-way tie, but the real story is in that group score: -20,000 points is the absolute worst score a group this size can manage! (-4 points for a double defection * 5 pairs * 1000 rounds)

You probably saw that coming. Of course a big group of devils is going to make an absolute mess of things. I didn’t just draw that name out of a hat.

Wolf Among Sheep

So if you have a group of all saints they will all tie for first place while a group of all devils will tie for last place. That’s good to know but doesn’t do much good for those of us living in a world full of both good and bad people.

So let’s mix things up!

#Saints with one devil among them
prisoners = createPrisoners(9, 1)
playPrisonersDilemma(prisoners, 1000)

The Group’s Overall Score was -11000 in 1000 rounds with 10 prisoners

ID: 10 Score: 0 Strategy: Devil

ID: 5 Score: -1188 Strategy: Saint

ID: 6 Score: -1206 Strategy: Saint

ID: 4 Score: -1210 Strategy: Saint

ID: 2 Score: -1212 Strategy: Saint

ID: 1 Score: -1216 Strategy: Saint

ID: 8 Score: -1220 Strategy: Saint

ID: 9 Score: -1232 Strategy: Saint

ID: 3 Score: -1236 Strategy: Saint

ID: 7 Score: -1280 Strategy: Saint

This test is actually a little interesting because it’s the first one we’ve run where the score will be different every time you play the game. Run the program a few times in a row and see for yourself: The scores will move move up and down a bit. The devil always gets a perfect score but the individual saint scores will go up and down based on how often they had the bad luck of getting stuck with the all-betraying devil.

The fact that the devil always get a perfect score is also pretty interesting, although it isn’t hard to figure out how he pulled it off. The devil never accepts the -1 penalty for cooperating and the saints never penalize their partner with the -2 points of betrayal, so there is literally no way for the devil to lose.

Also, look at the group score. The devil may have messed up the saints ten way tie but at least the group is still within 10% of being perfect.

Diabolic Duo

It doesn’t seem fair to have a single devil running around taking advantage of everything, so let’s give him a taste of his own medicine by introducing a second devil to the mix.

#A group of mostly saints
prisoners = createPrisoners(8, 2)
playPrisonersDilemma(prisoners, 1000)

The Group’s Overall Score was -12000 in 1000 rounds with 10 prisoners

ID: 10 Score: -232 Strategy: Devil

ID: 9 Score: -232 Strategy: Devil

ID: 8 Score: -1408 Strategy: Saint

ID: 7 Score: -1438 Strategy: Saint

ID: 1 Score: -1444 Strategy: Saint

ID: 6 Score: -1446 Strategy: Saint

ID: 2 Score: -1448 Strategy: Saint

ID: 3 Score: -1448 Strategy: Saint

ID: 4 Score: -1452 Strategy: Saint

ID: 5 Score: -1452 Strategy: Saint

Once again the scores will move up and down a bit depending on how often the devils get paired up and betray each other versus how often they get paired up with a defenseless saint, but the overwhelming trend here is for the devils to come out ahead. After all, each devil has an 8 out of 9 chance of getting paired with an easy to exploit saint.

(It is technically possible for the devils to lose if they get paired up a lot… but the odds of that happening a thousand times in a row is really really low. Try running shorter games if you want to see what happens when lightning strikes and devils always get stuck together).

Other interesting things to note include the fact that the devils will always have the same score (since they only lose points when they get paired together and then they always both lose two points). It’s also worth noting that our group score is now 20% worse than perfect. If this was a neighborhood it would still be a nice place to live even if a few of your neighbors smell like sulfur and brimstone and tend to park their cars in front of other people’s driveways.

Wheat and Tears

Let’s level the playing field and mix together an even number of saints and devils.

#An even mix of saints and devils
prisoners = createPrisoners(5, 5)
playPrisonersDilemma(prisoners, 1000)

The Group’s Overall Score was -15000 in 1000 rounds with 10 prisoners

ID: 6 Score: -900 Strategy: Devil

ID: 9 Score: -900 Strategy: Devil

ID: 7 Score: -910 Strategy: Devil

ID: 10 Score: -924 Strategy: Devil

ID: 8 Score: -934 Strategy: Devil

ID: 4 Score: -2030 Strategy: Saint

ID: 2 Score: -2080 Strategy: Saint

ID: 1 Score: -2086 Strategy: Saint

ID: 5 Score: -2116 Strategy: Saint

ID: 3 Score: -2120 Strategy: Saint

About what you would expect. The devils still manage to absolutely destroy the saints. Even worse, our group score is starting to get pretty bad and even after exploiting the saints mercilessly the devils are only a little better off than they would have been if they had decided to cooperate.

I guess the lesson here is that crime only pays when you have a small number of criminals exploiting a large population of good productive citizens. If you have too many criminals there just isn’t enough loot to go around.

A Light in the Darkness

For our last experiment let’s see what happens when you have a group made up mostly of devils and throw in a single saint. Doesn’t take a genius to predict this is going to be pretty bad…

#A single saint in a group of devils
prisoners = createPrisoners(1, 9)
playPrisonersDilemma(prisoners, 1000)

The Group’s Overall Score was -19000 in 1000 rounds with 10 prisoners

ID: 6 Score: -1756 Strategy: Devil

ID: 3 Score: -1766 Strategy: Devil

ID: 10 Score: -1766 Strategy: Devil

ID: 7 Score: -1774 Strategy: Devil

ID: 8 Score: -1774 Strategy: Devil

ID: 4 Score: -1780 Strategy: Devil

ID: 9 Score: -1792 Strategy: Devil

ID: 5 Score: -1794 Strategy: Devil

ID: 2 Score: -1798 Strategy: Devil

ID: 1 Score: -3000 Strategy: Saint

Ouch. Our poor saint wound up with the absolute worst possible individual score this time around. In every single round the saint hit himself with a -1 penalty for cooperating and then got with a -2 penalty from his defecting partner. Doesn’t get any worse. How perfectly terrible.

The group score is also pretty horrible and the devils are now significantly worse off than if they had just cooperated. (Fun experiment, mess with the ratio of saints to devils and find the exact point at which being a devil no longer pays).

One Last Observation

Let’s finish this post off with one last interesting trend you may have noticed: Running an experiment multiple times in a row caused individual scores to bounce around a lot but the group score never changed by even a single point. Why is that?

I’ll give you a few moments to think about it.

The answer is simple enough. Saints always cooperate, which causes the group to lose one point per round. Devils always defect, which causes the group to lose two points per round. Doesn’t matter how you mix up the pairs; the group as a whole will always lose one point per saint and two points per devil.

To get a group score that occasionally changes we would have to have a prisoner that sometimes cooperates (losing the group only one point) and sometimes defects (losing the group two points). Then the group score could go up or down based on how that individual prisoner decided to play.

Which is exactly what we’re going to be doing next time!