Extra Material - Split the dollar with neighbors

The corriculum for evolutionary game theory includes

  • Introduction to Part I: Location, p. 15-16

  • Chapter 2, “Bargaining with Neighbours”, p. 17-29

From Skyrms, Brian. The Stag Hunt and the Evolution of Social Structure. Cambridge: Cambridge University Press, 2004

This excerpt ends with a discussion of the game split the dollar played on a grid with neighbors. Split the dollar is a game where two players each must make a demand of a portion of a dollar, which they receive if the sum of their demands is no more than a dollar. If one player demands 60 cents and the other 70, they both get nothing. But if one player demands 80 cents and the other 10, the first gets 80 cents and the other 10.

We are interested in how different strategies of split the dollar(large demand, fair division, small demand) can spread according to different rules of evolution.

To analyze this we will simulate a population of players on a grid, where each player has a strategy which it plays against its neighbors(players to the N,S,E,W). To simplify the discussion and coding, each pair of players are splitting 10 dollars, and can only demand a whole number of dollars (which cannot total more than 10). After a round, each player has a fitness equal to the number of dollars it got from playing split the dollar with its neighbors. Then, if a player has a neighbor with a higher fitness, it adopts the strategy of the neigbor with the highest fitness.

Below, we have provided code for such a simulation. Skip to the end of the notebook to run the simulation yourself and observe the spread of fair division.

The code for updating and simulating

import numpy as np
from IPython.display import clear_output
def payoff(s1, s2): # The split the dollar rules
    if s1 + s2 <= 10:
        return s1
    else:
        return 0
def findFitness(strategies): # Finding the fitness of all players
    X = strategies.shape[1]
    Y = strategies.shape[0]
    fitness = np.zeros((Y, X))
    
    for row in range(Y):
        for col in range(X):
            s1 = strategies[row, col]
            fit = 0
            if row != 0:
                fit += payoff(s1, strategies[row-1, col]) #Up
            if row != Y-1:
                fit += payoff(s1, strategies[row+1, col]) #Down
            if col != 0:
                fit += payoff(s1, strategies[row, col-1]) #Left
            if col != X-1:
                fit += payoff(s1, strategies[row, col+1]) #Right

            fitness[row, col] = fit
    return fitness
def updateStrats(strategies, fitness): # Updating the strategies of all players
    X = strategies.shape[1]
    Y = strategies.shape[0]
    newStrats = np.zeros((Y, X))
    
    for row in range(Y):
        for col in range(X):
            fit = fitness[row, col] # fitness of this player
            strat = strategies[row, col] # strategy of this player

            if row != 0:
                if fitness[row-1, col] > fit:
                    strat = strategies[row-1, col]
                    fit = fitness[row-1, col]
            if row != Y-1:
                if fitness[row+1, col] > fit:
                    strat = strategies[row+1, col]
                    fit = fitness[row+1, col]
            if col != 0:
                if fitness[row, col-1] > fit:
                    strat = strategies[row, col-1]
                    fit = fitness[row, col-1]
            if col != X-1:
                if fitness[row, col+1] > fit:
                    strat = strategies[row, col+1]
                    fit = fitness[row, col+1]

            newStrats[row, col] = strat
            
    return newStrats
def simulate(strategies): # Updates and prints strategies for each step
    X = strategies.shape[1]
    Y = strategies.shape[0]
    for i in range(200):
        clear_output(wait=True)
        stop = input("Press enter to continue. Any text to stop: ")
        clear_output()
        
        fitness = findFitness(strategies)

        myOutput = ""
        for j in range(Y):
            for k in range(X):
                strat = strategies[j,k]
                if strat == 5:
                    myOutput += "X"
                elif strat == 4:
                    myOutput += "."
                elif strat == 6:
                    myOutput += "/"
                else:
                    myOutput += f"{strategies[j,k]:.0f}"
            myOutput += "\n"
        print(myOutput)
        strategies = updateStrats(strategies, fitness)

        if stop != "":
            break

Setup of initial strategies

X = 50
Y = 25
strategies = np.random.randint(10, size=(Y, X))
strategies[strategies == 5] = 6
strategies[5, 5] = 5
strategies[5, 6] = 5
strategies[6, 5] = 5
strategies[6, 6] = 5

Simulating split the dollar

Run the two cells above to reset the strategies. Run the cell below to start the simulation.

Press enter in the input field to continue the simulation. Enter any text to the input field to stop the simulation. If you run the cell below over again without stopping the simulation, the program will get stuck and you will need to interrupt the kernel.

simulate(strategies)
XXXXXXXXXXXXXXXXXXXXX./...//..//////../...././././
XXXXXXXXXXXXXXXXXXXXXX//.///././/////./.../.....//
XXXXXXXXXXXXXXXXXXXXX./././..././///././././././..
XXXXXXXXXXXXXXXXXXXXXX.../././//./../..././//././.
XXXXXXXXXXXXXXXXXXXXX././././////.////.///////////
XXXXXXXXXXXXXXXXXXXXXXX/...///.//////./////./././.
XXXXXXXXXXXXXXXXXXXXXX/././//////.//////./////////
XXXXXXXXXXXXXXXXXXXXXX//./////./././///////././//.
XXXXXXXXXXXXXXXXXXXXXX/////.///////.//////././//..
XXXXXXXXXXXXXXXXXXXXXX//////./././..../././..././/
XXXXXXXXXXXXXXXXXXXXX//./././////././///.../././//
XXXXXXXXXXXXXXXXXXXX//././././////...//./.../././/
XXXXXXXXXXXXXXXXXXX///....../////.../.././...///..
XXXXXXXXXXXXXXXXXXX//.//././//.///./..///./././...
XXXXXXXXXXXXXXXX.X././////../////.//.///....../...
XXXXXXXXXXXXXXXX///.///////..///.////./././..///..
XXXXXXXXXXXXXXX..///././././.././/////.////.///./.
XXXXXXXXXXXXXX...///..////..////.////././.././//..
XXXXXXXXXXXXXXX./////./////././.../../////../////.
XXXXXXXXXXXXX../////////////..././..///.////////..
XXXXXXXXX//././././//////./././.../../////.//././/
..XX./X/////.///////.///./....././//.////.///.../.
.//////////////.///.///./..././././/////./////....
///../././//././//////./././//.///./././/////././.
.//////////././//./././../../.../../..//././../../