Simulating the Golden Balls game show

In this eposide of Golden Balls, an inspired event takes place:

I retold the event at DIKU APL lunch (nice to have a job where game theory is a valid conversation topic), and we had a conversation about it. At first I thought this was prisoners dilemma, but it was quickly revealed that it is a different game. What is cool about it is, that Nick basically forces Abraham to pick split. I don’t think the same approach would work again though. The person in Abrahams position might be tempted to try a counter-steal. The person in Nicks position might be tempted to actually steal the money, which would be a dirty thing to do, but not completely unlikely.

Someone remarked that if each player was a random variable, stealing would be twice as successful as splitting, as on average you get half the money by stealing, while splitting only gets you one quarter of the money on average.

Clearly players are not random variables, so we talked a bit about what a genetic algorithm simulation would reveal. Obviously, if all people were stealers, everyone would loose all the time, so that might inspire people to try splitting. If most people were splitters, stealers would have a field day, which might inspire people to become stealers. Someone speculated that running a simulation would reveal some kind of oscillating pattern. I decided to build a model and implement a simulation in Python.

The way the simulation works is this: A population is initialized, with a certain ratio between stealers and splitters (I use a 50/50 split). A game of golden balls is played, by drawing two participants randomly from the population. If the outcome is a steal, it will have an propability of converting splitters in the population into stealers. If the outcome is a split, it will conversely have a propability of converting stealers into splitters. If the outcome is a mutual steal, and hence loss, it will have a (slightly bigger) propability of converting stealers into splitters.

golden_balls.py:

import random
 
def main():
    # constants
    POP_SIZE = 1000
    INITIAL_STEALERS = 0.5
    population = int(POP_SIZE*INITIAL_STEALERS)*[1]
    population.extend(int(POP_SIZE*(1-INITIAL_STEALERS))*[0])
    GAMES = 100
    CONVERT_TO_STEALER = 0.1
    CONVERT_TO_SPLITTER = 0.05
    CONVERT_TO_SPLITTER_ON_LOOSE = 0.1
 
    ts = [['Generation', 'Percent stealers in population']]
 
    # generations
    for game in range(GAMES):
 
        # calc stealer percent
        stealers = round(reduce(lambda x,y: x+y, population) / float( len(population) ), 5)
 
        # record last generation
        ts.append([game, stealers])
 
        # play game
        p1 = random.random() <= stealers
        p2 = random.random() <= stealers
        new_pop = []
        for person in population:
 
            if (p1 or p2) and not (p1 and p2):
                # steal
                if random.random() <= CONVERT_TO_STEALER:
                    # converted
                    new_pop.append(1)
                else:
                    new_pop.append(person)
 
            elif (not p1) and (not p2):
                # split
                if random.random() <= CONVERT_TO_SPLITTER:
                    new_pop.append(0)
                else:
                    new_pop.append(person)
 
            else:
                # loose
                if random.random() <= CONVERT_TO_SPLITTER_ON_LOOSE:
                    new_pop.append(0)
                else:
                    new_pop.append(person)
 
        population = new_pop
 
 
    print ts
 
if __name__ == '__main__':
    main()

The outcome of the simulation:

Leave a Reply