Poker-AI.org
http://poker-ai.org/phpbb/

Understanding python script to create Kuhn Poker game tree
http://poker-ai.org/phpbb/viewtopic.php?f=24&t=2884
Page 1 of 1

Author:  James23 [ Fri Feb 27, 2015 1:30 pm ]
Post subject:  Understanding python script to create Kuhn Poker game tree

For a University project I am trying to follow a script I have access to which supposedly creates the game tree structure for two player Kuhn Poker - written using Python's class structure.

When run it comes across problems with the children and parents properties of its decision nodes, and I can't grasp how the code is progressing step by step. I believe this code has been based off the pycfr github library, "pokertrees" script. The error message states the list index is out of range for the children list called under the tree_structure function for each child. I can't follow when it is writing to this list, and feel this may be missing from this 'simplified version' of the pycfr code "pokertrees", available on github. I am inexperienced using parent/children system of moving from node to node, especially in python, using the node classes and the self.root instantiated with the tree.

Can anybody clear this up for me? I have spent days poring over the code and feel knowledgeable opinions will be able to spot the problem.


The code can be run in the shell as follows:

First define specifications.
Call "specs = specifications(deck ,size_of_bet, maximum_allowed_bet, ante)"
e.g. "specs = specifications([A,K,Q] ,1, 1, 1)"
Next create game tree.
Call "tree = tree(specs)"
Next, run start_game_and_deal_card.
Call "tree.start_game_and_deal_card()


Here is the relevant piece of code:

Code:
import random
from copy import deepcopy
from itertools import permutations
from itertools import combinations

J=11
Q=12
K=13
A=14

class specifications(object):
    def __init__(self, deck, size_of_bet, maximum_allowed_bet, ante):
            self.deck = deck
            self.ante = ante
            self.size_of_bet = size_of_bet
            self.maximum_allowed_bet = maximum_allowed_bet

class tree(object):
    def __init__(self, specifications):
            self.specifications = deepcopy(specifications)
            self.info = []
            self.root = None

    def start_game_and_deal_card(self):
        in_the_pot = [True] * 2
        players_contribution = [self.specifications.ante] * 2
        acting_player = 0
        bets = [0] * 2
        minimum_moves = in_the_pot.count(True)
        moves = 0
        game_so_far = ""
        possible_cards = permutations(combinations(self.specifications.deck,1),2)
        for cards in possible_cards:
            dealt_cards = ()
            cards = list(cards)
            for i,card in enumerate(cards):
                if in_the_pot[i]:
                    cards[i] = card + cards[i]
            for card in cards:
                dealt_cards += card
            deal = deal_cards_node(node, players_contribution, player_cards, self.specifications.deck, "")
            self.tree_structure(deal, acting_player, in_the_pot, players_contribution, cards, self.specifications.deck, game_so_far, minimum_moves, moves, bets)
        return deal

    def tree_structure(self, node, acting_player, in_the_pot, players_contribution, player_cards, deck, game_so_far, minimum_moves, moves, bets):
        if in_the_pot.count(True) ==1:
            self.showdown(node, in_the_pot, players_contribution, player_cards, self.specifications.deck, game_so_far)
            return
        if moves>=minimum_moves and bets[node.player]==betlevel:
            self.showdown(node, in_the_pot, players_contribution, player_cards, self.specifications.deck, game_so_far)
            return
        decision = decision_node(node, players_contribution, player_cards, self.specifications.deck, game_so_far, acting_player)
        # update information set
        self.info.append(decision.player)
        acting_player = (acting_player + 1) % 2
        # fold child
        if players_contribution[decision.player] < max(players_contribution):
            game_so_far += 'f'
            in_the_pot[decision.player] = False
            self.tree_structure(node, acting_player, in_the_pot, players_contribution, player_cards, deck, game_so_far, minimum_moves, moves + 1,bets)
            in_the_pot[decision.player] = True
            node.fold_decision = node.children[-1]
        # raise child
        if self.specifications.maximum_allowed_bet > max(bets):
            game_so_far += 'r'
            players_contribution[decision.player]=players_contribution[decision.player]+1
            bets[decision.player]=bets[decision.player]+1
            self.tree_structure(node, acting_player, in_the_pot, players_contribution, player_cards, deck, game_so_far, minimum_moves, moves + 1, bets)
            node.raise_decision = node.children[-1]
        # call child
        game_so_far =+ 'c'
        players_contribution[node.player]=players_contribution[(node.player+1)%2]
        bets[node.player]=bets[(node.player+1)%2]
        self.tree_structure(node, acting_player, in_the_pot, players_contribution, player_cards, deck, game_so_far, minimum_moves, moves + 1, bets)
        node.call_decision = node.children[-1]
        return decision

    def showdown(self, node, in_the_pot, players_contribution, player_cards, deck, game_so_far):
        if in_the_pot.count(True) == 1:
            winners = in_the_pot
        else:
            winners = []
            if player_cards[0] > player_cards[1]:
                winners.append(0)
            if player_cards[0] < player_cards[1]:
                winners.append(1)
        total = sum(players_contribution)
        payoffs = winners.extend([total])
        return terminal_node(node, players_contribution, player_cards, deck, game_so_far, payoffs, in_the_pot)

class node(object):
    def __init__(self, parent, players_contribution, player_cards, deck, game_so_far):
        self.deck = deepcopy(deck)
        self.players_contribution = deepcopy(players_contribution)
        self.player_cards = deepcopy(player_cards)
        self.parent = parent

class terminal_node(node):
    def __init__(self, parent, players_contribution, player_cards, deck, game_so_far, payoffs, in_the_pot):
        node.__init__(self, parent, players_contribution, player_cards, deck, game_so_far)
        self.children = []

class deal_cards_node(node):
    def __init__(self, parent, players_contribution, player_cards, deck, game_so_far):
        node.__init__(self, parent, players_contribution, player_cards, deck, game_so_far)
        self.children = []

class decision_node(node):
    def __init__(self, parent, players_contribution, player_cards, deck, game_so_far, player):
        node.__init__(self, parent, players_contribution, player_cards, deck, game_so_far)
        self.player = player
        self.children = []
        self.raise_decision = None
        self.call_decision = None
        self.fold_decision = None

Author:  spears [ Fri Feb 27, 2015 3:46 pm ]
Post subject:  Re: Understanding python script to create Kuhn Poker game tr

I don't know any python and I've only given this a few minutes.

class specifications isn't very interesting.

There looks to be something wrong with class tree or at least the call to the constructor that you make. If you are supposed to building the tree I would expect to see recursive calls to build it and there aren't any in tree.

I'm guessing that tree_structure builds the tree as it has recursive calls and game_so_far is a label for an action.

start_game_and_deal_card I suspect is badly named. The penultimate line is a call to tree_structure so this must be something to do with building the tree. Also there is no reference to how many iterations to use or anything about calculating cfr so it can't actually be running the calculation.

deal_cards_node constructs the root node of the tree.

Trees are made up of nodes each of which have an array of child nodes. Code that navigates a tree starts at the root node and then moves onto the children in turn. This is usually done through recursive calls. In most languages I would expect to see iteration over the child nodes but I don't see anything like that here. I suppose it is possible that python could use some other mechanism but would be very clever.

If the owner of this code can't help I think I would dump it and start over. If you can read c# you should take a look at amax's nice code at http://poker-ai.org/archive/www.pokerai ... 335#p40335. Maybe http://modelai.gettysburg.edu/2013/cfr/ is worth a look too

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/