Exploring Game Theory: GOPS (Game of Pure Strategy)
When economists and computer scientists talk about “Game Theory,” they aren’t usually referring to modern video games. They’re talking about the mathematical modeling of strategic interaction among rational decision-makers. One of the most fascinating micro-games for exploring this is GOPS (Game of Pure Strategy).
Also known as Goofspiel, it is an incomplete information game played with a standard deck of cards.
The Rules of GOPS
The game is played between two players.
- Suits: Each player gets an entire suit (e.g., all 13 Spades for Player A, all 13 Hearts for Player B).
- Prizes: A third suit (e.g., Diamonds) is shuffled and placed face down as the “Prize Deck”.
- Gameplay: In each round, the top card of the Prize Deck is revealed. Both players simultaneously choose one card from their hand and bid it face down.
- Resolution: The bids are revealed. The highest bidder wins the prize card (which is worth its face value, Jack=11, Queen=12, King=13, Ace=1). If there is a tie, the prize card is discarded (or in some variants, rolled over to the next round).
- Conclusion: The game ends after 13 rounds when all hands are depleted. The winner is the player with the most accumulated prize points.
The Mathematics of Bidding
Because players move simultaneously and must out-guess their opponent, GOPS is an excellent candidate for exploring Nash Equilibria in mixed strategies.
Let the prize card value be . If Player 1 bids and Player 2 bids , the expected payoff for Player 1, , can be modeled as:
However, the game isn’t played in isolation. Playing a high card now means you lack it for a future turn. Your bid incurs an opportunity cost. Our true utility function must account for the state of remaining cards:
This turns out to be a classic Blotto game, and computing the exact equilibrium for the full 13-card game is computationally intensive.
Writing a Basic Simulator
Rather than solving it analytically, we can write a simple Python simulator to test out heuristic strategies against each other.
Here is a naive approach where we just bid the card closest to the prize’s value:
import random
class Player:
def __init__(self, name):
self.name = name
self.hand = list(range(1, 14)) # Cards 1 through 13
self.score = 0
def get_bid(self, prize):
"""Naive strategy: Just bid the exact value of the prize if we have it,
otherwise bid the highest available card."""
if prize in self.hand:
bid = prize
else:
bid = max(self.hand)
self.hand.remove(bid)
return bid
def play_gops():
p1, p2 = Player("Alice"), Player("Bob")
prizes = list(range(1, 14))
random.shuffle(prizes)
for round_num, prize in enumerate(prizes, start=1):
bid1 = p1.get_bid(prize)
bid2 = p2.get_bid(prize)
print(f"Round {round_num}: Prize {prize} | Alice bids {bid1}, Bob bids {bid2}")
if bid1 > bid2:
p1.score += prize
elif bid2 > bid1:
p2.score += prize
print(f"\nFinal Score: Alice {p1.score} - {p2.score} Bob")
if __name__ == "__main__":
play_gops()
If both players play this deterministic strategy, the game is heavily dependent on the shuffled order of the prize deck. To win at GOPS, you must randomize (play a mixed strategy) to avoid being predictable.
Next time you have a deck of cards, deal out the suits and give it a try. It is much deeper than it first appears.