---
title: "The prisoner's dilemma in R"
description: "The prisoner's dilemma in R: why defection dominates a single encounter and mutual cooperation collapses, the starting point for the evolution of cooperation."
date: "2026-07-07 13:00"
categories: [evolutionary ecology, evolutionary game theory, social evolution, R, ecology tutorial]
image: thumbnail.png
image-alt: "A two-by-two payoff matrix showing defection paying more than cooperation against either opponent move"
---
Cooperation is a puzzle because cheating pays. Two animals that both help each other do better than two that both cheat, yet whatever the other one does, an individual gains by cheating. That tension has a canonical model: the prisoner's dilemma. It is the foundation of everything in [the evolution of cooperation](../direct-reciprocity-and-tit-for-tat/), and this post builds it in a few lines of base R to show exactly why cooperation is hard.
## The payoffs
Two players each choose to cooperate or defect. The four outcomes have standard names: mutual cooperation pays the reward `R`, mutual defection the punishment `P`, and a defector against a cooperator gets the temptation `T` while the cooperator gets the sucker's payoff `S`. A prisoner's dilemma is any game with `T > R > P > S`.
```{r}
#| label: payoffs
Tt <- 5; R <- 3; P <- 1; S <- 0 # temptation, reward, punishment, sucker
# focal player's payoff given (focal move, opponent move), C = cooperate, D = defect
payoff <- function(me, opp) {
if (me == "C" && opp == "C") R else if (me == "C" && opp == "D") S else
if (me == "D" && opp == "C") Tt else P
}
cat(sprintf("T=%g > R=%g > P=%g > S=%g\n", Tt, R, P, S))
```
## Defection dominates
Ask the only question that matters to a selfish player: whatever my opponent does, am I better off cooperating or defecting?
```{r}
#| label: dominance
cat(sprintf("opponent cooperates: D pays %g vs C pays %g -> defect\n", payoff("D", "C"), payoff("C", "C")))
cat(sprintf("opponent defects: D pays %g vs C pays %g -> defect\n", payoff("D", "D"), payoff("C", "D")))
```
Against a cooperator, defecting pays 5 instead of 3. Against a defector, defecting pays 1 instead of 0. Defection wins in both columns, so it is a dominant strategy: a rational player defects no matter what, and a population of defectors cannot be invaded by a lone cooperator. Defection is the only evolutionarily stable strategy of the one-shot game, the same logic that makes all-defect an equilibrium in any single social encounter.
## The dilemma
Here is the catch that gives the game its name.
```{r}
#| label: dilemma
cat(sprintf("both defect (the ESS): %g each\n", payoff("D", "D")))
cat(sprintf("both cooperate: %g each\n", payoff("C", "C")))
```
Two defectors earn 1 each; two cooperators would earn 3 each. Individual rationality drives everyone to the outcome that is worse for everyone. Nothing is wrong with the reasoning; the trap is real. This is why cooperation in nature demands an explanation, and why so much of social evolution is the search for what changes the payoffs or the structure enough to escape it.
```{r}
#| label: fig-matrix
#| fig-cap: "The focal player's payoff for each move against each opponent move. Defect (top row) beats cooperate (bottom row) in both columns, so defection dominates, even though mutual cooperation (3) beats mutual defection (1)."
#| fig-alt: "A two-by-two grid of payoffs. Reading each row from the cooperate column to the defect column, the top defect row shows 5 then 1 and the bottom cooperate row shows 3 then 0; a tile is darker the higher its payoff, so the 5 is the darkest of the four."
library(ggplot2)
te_canvas <- theme(plot.background = element_rect(fill = "#f5f4ee", colour = NA),
panel.background = element_rect(fill = "#f5f4ee", colour = NA))
d <- expand.grid(me = c("C", "D"), opp = c("C", "D"))
d$pay <- mapply(payoff, d$me, d$opp)
ggplot(d, aes(opp, me, fill = pay)) +
geom_tile(colour = "white", linewidth = 2) +
geom_text(aes(label = pay), colour = "white", size = 7) +
scale_fill_gradient(low = "#93a87f", high = "#275139", guide = "none") +
labs(x = "Opponent move", y = "Focal move") +
theme_minimal(base_size = 13) + te_canvas
```
## An honest limit
The one-shot dilemma is a starting point, not a description of most animal life. Its stark conclusion, always defect, rests on a specific and often false assumption: that the two players will never meet again and that nothing links this encounter to the next. Real interactions repeat, happen among relatives, are watched by others, and play out in space. Each of those changes the game, and each is a route out of the trap. The next posts follow the most studied one, [repeated interaction](../direct-reciprocity-and-tit-for-tat/), where the shadow of future encounters can make cooperation pay after all. The dilemma is worth understanding precisely because it sets the bar every explanation of cooperation has to clear.
## References
Axelrod R, Hamilton WD 1981. Science 211(4489):1390-1396 (10.1126/science.7466396)
Trivers RL 1971. Quarterly Review of Biology 46(1):35-57 (10.1086/406755)
## Related tutorials
- [Direct reciprocity and tit-for-tat](../direct-reciprocity-and-tit-for-tat/)
- [Network reciprocity on a lattice](../network-reciprocity-on-a-lattice/)
- [Checking a reciprocity model](../checking-a-reciprocity-model/)
- [The hawk-dove game and the ESS](../hawk-dove-and-the-ess/)