tanderson11
tanderson11

Reputation: 127

Simple Python Issue With Dictionaries and Iteration

I was writing an implementation of the iterated prisoner's dilemma in Python, and am having the following problem.

for p in players:
    for o in players:
        if p.name != o.name:
            try:
                p.history[o.name]
            except KeyError:
                p.history[o.name] = []
                o.history[p.name] = []
                for i in xrange(0,2):
                    result = play(p.logic(p.history[o.name]),
                                  o.logic(o.history[p.name]))
                    p.history[o.name].append(result[0])
                    o.history[p.name].append(result[1])

This is the code I have. The 'players' list is a list of Strategy objects which have 'name' a string, and 'logic' a function. The trouble I am having occurs at the lines

p.history[o.name].append(result[0])

I am attempting to create the following dictionaries:

Player 1.history = {"Player 2 Name": [result, result, result]}
Player 2.history = {"Player 1 Name": [result, result, result]}

But I get this instead:

Player 1.history = {"Player 1 Name": [wrong results], 
                    "Player 2 Name": [wrong results]}

The results aren't all wrong, but some are. Does anyone know why either the results aren't all right or why I have the key "Player 1 Name" in Player 1's dictionary and "Player 2 Name" in Player 2's dictionary?

EDIT: Some more code on request

class Strategy:
    """Basic class for all strategies to use. The 'logic' function is defined oustide and governs behavior"""
    def __init__(self, logic, name):
        self.logic = logic
        self.name = name
    history = {}

def makePlayer(name):
    if name == "Defects":
        def logic(hist):
            return 1
    if name == "Tit for Tat":
        def logic(hist):
            for i in xrange(1,3):
                try:
                    if hist[len(hist) -  i][1] == 1:
                        return 1
                except IndexError:
                    pass
            return 0
    return Strategy(logic, name)

payoff = [[100, 0], [101, 1]]

def play(choice1, choice2): #choiceFoo = 0 => cooperate; 1 => defect
    return [[choice1, choice2, payoff[choice1][choice2]], [choice2, choice1, payoff[choice2][choice1]]]

Upvotes: 0

Views: 150

Answers (1)

msw
msw

Reputation: 43497

This isn't a complete answer, but doing "real work" in an exception block is bound to cause confusion. If you want to see if there is a key in a dictionary, do so explicitly with the in operation.

You can drop the try/except block by changing the conditional to

if p.name != o.name and o.name not in p.history:

Then again, part of the iterated prisoners dilemma is that a strategy should play against itself so that might be better as:

if o.name not in p.history:

Without more of the troublesome code (e.g. play) it is hard to give more advice on this problem.

Upvotes: 1

Related Questions