Go in hard or pull out? Hawks, doves and the 50/50 challenge
Two players chase a loose ball. Go in hard and you might win it, or collide. Pull out and you're safe, but beaten. Game theory says there's no best choice, only a best mix, and a simple rule about who got there first beats both.
Intermediate Part 7 of Game Theory Through Football
New to the notation? The symbols explained
Contents
The football question
The ball breaks loose between two players. Both can go in hard, or pull out. If one goes in hard and the other pulls out, the one who went in wins the ball. If both pull out, it's anyone's. If both go in hard, someone might win it, but both risk a clash, an injury or a card.
So what should a player do: go in hard every time, or pick his moments?
The concept
This is the hawk-dove game, from a 1973 paper by John Maynard Smith and George Price, "The Logic of Animal Conflict". They wanted to know why animals fighting over food or territory so rarely fight to the death. Hawks always fight; doves back off.
It's different from the games earlier in this series. In the prisoner's dilemma one choice is best whatever the other side does. In hawk-dove the best choice is the opposite of what the other player does: if he's going in hard, pull out; if he's pulling out, go in hard. Nobody can settle on one choice for ever, so, as with penalties, the answer is a mix.
The 50/50 in numbers
The numbers here are made up, to show the idea. Say winning the ball is worth 4 and a collision costs each player 10: a knock, a booking, a free kick given away. When both go in hard, each wins the ball half the time but both pay for the collision.
| Me \ them | Them hard | Them pull out |
|---|---|---|
| Me hard | −3 | 4 |
| Me pull out | 0 | 2 |
Read along a row: going in hard wins 4 against a player who pulls out, but loses 3 on average against one who doesn't. Pulling out gets nothing against a hard challenge, and half the ball, 2, against another player who pulls out.
What each choice earns depends on how often the opposition goes in hard:
If nobody goes in hard, going in hard earns 4 a challenge against 2 for pulling out, so players start going in. If everyone goes in hard, going in hard earns −3 against 0 for pulling out, so players start pulling out. The two lines cross where opponents go in hard 40% of the time: there, both choices earn the same, 1.20 a challenge, and nobody gains by changing. That's the stable mix.
$$p = \frac{V}{C}$$
In plain football
- V is what winning the ball is worth, here 4.
- C is what a collision costs each player, here 10.
- p is how often to go in hard: 4 out of 10, so 40% of 50/50s.
- When the ball is worth as much as the collision, or more, p reaches 100%: always go in hard.
Maynard Smith called this an evolutionarily stable strategy. Think of a whole league of players. If fewer than 40% of challenges are hard ones, the players who go in hard do better, and more copy them. If more than 40% are, the ones who pull out do better. Either way the league drifts back to 40%. Nobody has to work it out; the arithmetic pushes them there.
When the numbers change
The stable mix moves with the stakes, and the formula says which way:
- Stricter referees. If a collision costs 16 instead of 10, the mix falls to 4 out of 16, 25%. Fewer hard challenges, without anyone being told to stop.
- A ball worth more. If winning it is worth 8, say a loose ball in your own box late in a tight game, the mix rises to 8 out of 10, 80%.
- Worth more than the risk. At 12 against 10, going in hard always pays: 100%. That's when you see both players fly in.
The rule that beats them both
At the stable mix, players still collide: two hard challenges meet 16% of the time (40% of 40%). There's a better way, and football already has it: whoever gets there first goes in hard; the other pulls out.
Two players who both follow that rule never collide. Each is first half the time and wins the ball, so each averages 2.00 a challenge, against 1.20 at the stable mix. And nobody gains by breaking the rule:
| Among players who follow the rule | Earns a challenge |
|---|---|
| Follow it too | 2.00 |
| Always go in hard | 0.50 |
| Always pull out | 1.00 |
Always going in hard means colliding every time you arrive second. Always pulling out means giving away the balls you got to first. Biologists call this the bourgeois strategy, after animals where the owner of a territory fights and the intruder backs off; Maynard Smith and Geoff Parker studied contests like it in 1976. The deciding difference doesn't have to matter in itself. Size, age or who arrived first will do, so long as both players can see it.
Does the league behave like this?
It's worth asking whether real football shows the pattern. The Scottish Premiership has records of every side's fouls and yellow cards since 2000/01: 5,877 matches and 310 team-seasons. Measure each side against its own season and call it physical if it fouls and gets booked more than that season's average side, and clean if less. Three tests:
- Do physical sides earn more? No. Holding fixed how much each side dominated, a step up in physical play goes with −0.05 points a game (± 0.03), slightly fewer. Among sides that were outshot, −0.02 (± 0.04): nothing. Part 18 of the machine learning series found the same, that fouling buys no points.
- Does a hawk do better against a dove? The theory's sharpest prediction. Allowing for each side's strength that season, a physical side earned −0.00 points (± 0.04) beyond what its strength predicted against clean opponents, and −0.00 (± 0.05) against physical ones. The opponent's style made no difference.
- Do two hawks pay a price? A physical side picked up 2.08 cards a match against physical opponents and 2.15 against clean ones, a difference within luck. No sign of a costlier collision.
The league as a whole doesn't sit at a steady mix either. Fouls fell from 14.4 a side a game in 2002/03 to 10.5 in 2012/13, then rose to 12.1 by 2025/26, while yellow cards rose from 1.62 to 1.97.
So the season records can't see the hawk-dove pattern. That doesn't sink the theory: it's about single challenges, and a whole season of fouls and cards is far too blunt to see who pulled out of which 50/50. It's a reminder that a theory that explains a moment on the pitch needs data from those moments to be tested, as in do football stats mislead?
Why it matters
- Sometimes there's no best choice, only a best mix. When the right move is the opposite of your opponent's, any fixed habit gets exploited.
- The mix follows the stakes. Raise the cost of a collision and hard challenges fall; raise the prize and they rise, with nobody issuing orders.
- Conventions beat bravado. A shared rule about who gets there first is worth more to both players than the cleverest mix.
- Test a theory with data from the right level. A good story about single challenges says little about season averages, and the averages can't confirm it.
Limitations
- The numbers are made up. Nobody has measured what a 50/50 is worth or what a collision costs; only the shape of the answer matters here.
- Players aren't identical. A bigger, stronger player wins more of the hard challenges, which changes the payoffs for both.
- One challenge at a time. Real players remember who went in hard last time, which turns it into a repeated game.
- The data test is blunt. Physical and clean are season-long labels from fouls and yellows; the data has no record of 50/50s.
Try it yourself
Change the two numbers in the snippet: make the ball worth 6 and the collision cost 8, and see the stable mix move to 75%. Or watch the next match you go to: count the 50/50s, and how often both players go in hard. If it's often, the theory says the ball is worth more to them than the risk.
Reproduce the analysis
The game needs nothing but Python. For the last section, download the Scottish Premiership files (SC0) for 2000/01 to 2025/26 from football-data.co.uk, saved as SC0_0001.csv and so on; they aren't rehosted on this site. Then:
Show the Python104 lines, ready to copy and run.
# From Football Data Science by Bryan McGuire. Free to use with credit.
# https://www.footballdatascience.co.uk/learn/hawk-dove-fifty-fifty
import csv
from collections import defaultdict
from math import sqrt
from statistics import mean, pstdev
# 1. The 50/50 as hawk and dove, made-up numbers: winning the ball is worth V, a collision costs each player C
def game(V, C):
"""Payoffs to me for (my choice, their choice): both go in hard, each wins half the time but pays C."""
return {("hard", "hard"): (V - C) / 2, ("hard", "pull"): V, ("pull", "hard"): 0, ("pull", "pull"): V / 2}
def against(pay, p):
"""What going in hard and pulling out each earn against opponents who go in hard a share p of the time."""
return {me: p * pay[me, "hard"] + (1 - p) * pay[me, "pull"] for me in ("hard", "pull")}
V, C = 4, 10
pay = game(V, C)
print("payoffs to me (them hard, them pull):", {me: (pay[me, "hard"], pay[me, "pull"]) for me in ("hard", "pull")})
for p in (0.0, 0.2, 0.4, 0.6, 1.0):
e = against(pay, p)
print(f"opponents hard {p:.0%}: hard earns {e['hard']:+.2f}, pull out {e['pull']:+.2f}")
p_star = V / C # where the two are equal
print(f"stable mix: go in hard {p_star:.0%} of the time, each challenge worth {against(pay, p_star)['hard']:.2f}")
for v, c, why in ((4, 16, "stricter referees"), (8, 10, "the ball is worth more"), (12, 10, "worth more than the risk")):
print(f"{why} (V {v}, C {c}): go in hard {min(1, v / c):.0%}")
# the convention: whoever gets there first goes in hard, the other pulls out
def first_rule(me_first, me, opp): # payoff to `me` (a rule: hard if first else pull) against `opp`, me first or not
my, their = me(me_first), opp(not me_first)
return pay[my, their]
rule = lambda first: "hard" if first else "pull"
always_hard, always_pull = (lambda first: "hard"), (lambda first: "pull")
for name, me in (("follow the rule", rule), ("always go in hard", always_hard), ("always pull out", always_pull)):
print(f"{name:18} among rule-followers: {mean(first_rule(f, me, rule) for f in (True, False)):+.2f}")
# 2. Does the league behave like it? Scottish Premiership 2000/01-2025/26 from football-data.co.uk
NEED = ("FTHG", "FTAG", "HS", "AS", "HST", "AST", "HC", "AC", "HF", "AF", "HY", "AY", "HR", "AR")
matches, tot = [], defaultdict(lambda: defaultdict(float))
for s in [f"{y % 100:02d}{(y + 1) % 100:02d}" for y in range(2000, 2026)]:
with open(f"SC0_{s}.csv", encoding="latin-1") as f:
for r in csv.DictReader(f):
if not all(r.get(c) for c in NEED):
continue
v = {c: int(r[c]) for c in NEED}
matches.append((s, r["HomeTeam"], r["AwayTeam"], v))
for team, us, them in ((r["HomeTeam"], "H", "A"), (r["AwayTeam"], "A", "H")):
gf, ga, t = v[f"FT{us}G"], v[f"FT{them}G"], tot[s, team]
t["n"] += 1
t["pts"] += 3 if gf > ga else 1 if gf == ga else 0
t["fouls"] += v[us + "F"]
t["yel"] += v[us + "Y"]
t["dom"] += sum(v[us + k] - v[them + k] for k in ("S", "ST", "C")) # shots, on target, corners
ts = {k: {c: t[c] / t["n"] for c in ("pts", "fouls", "yel", "dom")} for k, t in tot.items() if t["n"] >= 30}
seasons = defaultdict(list)
for (s, _), t in ts.items():
seasons[s].append(t)
for s, g in seasons.items(): # each side against its own season: how physical (fouls and yellows) and how dominant
for c in ("fouls", "yel", "dom"):
m, sd = mean(t[c] for t in g), pstdev([t[c] for t in g])
for t in g:
t["z_" + c] = (t[c] - m) / sd
for t in g:
t["physical"] = (t["z_fouls"] + t["z_yel"]) / 2
print(f"\n{len(matches)} matches, {len(ts)} team-seasons")
for s in ("0203", "1213", "2526"):
print(f"20{s[:2]}/{s[2:]}: {mean(t['fouls'] for t in seasons[s]):.1f} fouls and {mean(t['yel'] for t in seasons[s]):.2f} yellows a side a game")
def luck(xs): # average and its luck margin, about two standard errors
return mean(xs), 2 * pstdev(xs) / sqrt(len(xs))
# do more physical sides earn more or fewer points, holding dominance fixed? (least squares on the two)
def slope_physical(rows):
xs = [(t["z_dom"], t["physical"], t["pts"]) for t in rows]
m = [mean(x[i] for x in xs) for i in range(3)]
s = lambda i, j: sum((x[i] - m[i]) * (x[j] - m[j]) for x in xs)
det = s(0, 0) * s(1, 1) - s(0, 1) ** 2
b1, b2 = (s(1, 1) * s(0, 2) - s(0, 1) * s(1, 2)) / det, (s(0, 0) * s(1, 2) - s(0, 1) * s(0, 2)) / det
res = [x[2] - m[2] - b1 * (x[0] - m[0]) - b2 * (x[1] - m[1]) for x in xs]
return b2, 2 * sqrt(sum(e * e for e in res) / (len(xs) - 3) * s(0, 0) / det)
print("points a game per step up in physical play, like for like: %+.2f (± %.2f); outshot sides only %+.2f (± %.2f)"
% (*slope_physical(ts.values()), *slope_physical([t for t in ts.values() if t["z_dom"] < 0])))
# hawk against dove: points above or below what the two sides' season strength predicts, by style pairing
rows = []
for s, h, a, v in matches:
th, ta = ts.get((s, h)), ts.get((s, a))
if th and ta:
hp = 3 if v["FTHG"] > v["FTAG"] else 1 if v["FTHG"] == v["FTAG"] else 0
ap = 3 if v["FTAG"] > v["FTHG"] else 1 if v["FTHG"] == v["FTAG"] else 0
rows.append((th, ta, th["pts"] - ta["pts"], hp, ap, v["HY"] + 2 * v["HR"], v["AY"] + 2 * v["AR"]))
def line(i): # points (home or away) as a straight line in the season-strength gap
gx, gy = mean(r[2] for r in rows), mean(r[i] for r in rows)
b = sum((r[2] - gx) * (r[i] - gy) for r in rows) / sum((r[2] - gx) ** 2 for r in rows)
return lambda r: r[i] - gy - b * (r[2] - gx)
home_left, away_left = line(3), line(4)
style = lambda t: "physical" if t["physical"] > 0 else "clean"
left, cards = defaultdict(list), defaultdict(list)
for r in rows:
for me, opp, extra, card in ((r[0], r[1], home_left(r), r[5]), (r[1], r[0], away_left(r), r[6])):
left[style(me), style(opp)].append(extra)
cards[style(me), style(opp)].append(card)
for me in ("physical", "clean"):
for opp in ("physical", "clean"):
print(f"{me:8} side v {opp:8} ({len(left[me, opp])}): points beyond strength %+.2f (± %.2f), "
f"own cards %.2f (± %.2f)" % (*luck(left[me, opp]), *luck(cards[me, opp])))
Further reading
- Evolutionary Game Theory, Stanford Encyclopedia of Philosophy: a thorough introduction, including the hawk-dove game as Maynard Smith and Price set it out in 1973.
- Evolutionarily stable strategy, Wikipedia: the idea behind the stable mix, with the hawk-dove game as its standard example.
- Chicken (game), Wikipedia: the same game under its other name, two drivers heading for each other, with sections on hawk-dove and on how a visible difference between the players settles it.
- Uncorrelated asymmetry, Wikipedia: why a difference that changes nothing in itself, such as who arrived first, can still decide who backs down, and where the bourgeois strategy comes from.