900 simulated voters sit on a grid. Each party has a spatial "stronghold" center; a voter's support score for party p is a Gaussian bump around that center plus random noise, and the voter backs whichever party scores highest for them:
score_p(voter) = base_p + exp(-dist(voter,center_p)² / (2σ²)) + noise
σ shrinks as polarization rises → sharper regional strongholds
The same 900 ballots are counted two different ways, side by side:
- First-Past-the-Post (left arc) — the grid is split into districts (rows × cols); whichever party has the plurality of votes in a district wins that district's single seat. Everyone else's vote there elects nobody.
- D'Hondt proportional (right arc) — nationwide, seats are handed out one at a time to whichever party currently has the highest quotient votesp / (seatsp+1), which converges on seat shares close to vote shares.
Wasted votes = Σ over districts [ losing-party votes + (winner's votes − (runner-up + 1)) ]
Gallagher index (least-squares disproportionality):
LSq = √( ½ · Σ_p (voteShare_p − seatShare_p)² ) — 0 is perfectly proportional
Raise polarization to see the classic FPTP effect: once support is geographically clustered, a minority party can sweep its home districts and outperform its national vote share — while a party with support spread evenly everywhere can win nowhere. D'Hondt on the right stays close to the national vote share regardless.