Transform the 2d list of poker stacks into list of actions

Question:

All poker stacks are scraped every few seconds during one poker hand on the preflop. Here’s the list of list of stacks in the big blinds(BB). Player 4 makes mandatory bet 0.5 BB, Player 5 makes 1 BB bet at the start, then players act consecutively from 0 to 5. The first sublist is player 0, the last is player 5.
Return list of actions.

Example 1: [[102,102,102,102]
[101,101,99,99]
[103.5,103.5,103.5]
[100.5,100.5,100.5,93,79.5]
[105.5,105.0,105.0,105.0]
[94,93,93,93,93,73]]

Desired output 1: Fold – Raise 2 – Fold – Raise 7.5 – Fold – Raise 21 – Fold – Call.

Explanation:

  • Player 0 folded because there’s no change in his stack.
  • Player 1 raised 2 because the stack decreased 101 – 99 = 2 big blinds (BB).
  • Player 2 folded because there’s no change in his stack.
  • Player 3 raised because the stack decreased 100.5 – 93 = 7.5 big blinds and the decrease is larger than previous bet (2 big blinds).
  • Player 4 folded because there’s no change in his stack after posting small blind (0.5 big blinds or BB).
  • Player 5 raised 21 because the his overall stack decreased 93 – 73 = 20 big blinds, he also posted 1 big blind so his overall raise size is 20 + 1 = 21).
  • Player 1 folded because the stack doesn’t decrease after his bet.
  • Player 3 called 21 because his stack decreased 93 – 79.5 = 13.5 BB and his overall bet in the round is 13.5 + 7.5 = 21 BB which equals maximum raise size in current round.

I correctly wrote transform_stacks function that transfroms list of stacks sizes into list of differences, however get_actions function is completely incorrect.

from more_itertools import pairwise
from itertools import zip_longest
 
stacks = [[102,102,102,102], [101,101,99,99], [103.5,103.5,103.5], [100.5,100.5,100.5,93,79.5], [105.5,105.0,105.0,105.0], [94,93,93,93,93,73]]
 
def transform_stacks(stacks): # finds the difference in stack sizes, the functions is normal
    u = [[float(x) - float(y) for (x, y) in pairwise(stacks[z]) if x != '' and y != '' and abs(float(y) - float(x)) > 0.499] for z in range(len(stacks))]
    #print(u) 
    #will return [[], [2.0], [], [7.5, 13.5], [0.5], [1.0, 20.0]]
    return u
 
transposed = transform_stacks(stacks)
 
def get_actions(stacks):
    actions = []
    for index in range(len(stacks)):
        curr_max = 0
        for k in range(len(stacks[index])):
            if stacks[index][k] and (stacks[index][k] - 0.01 > curr_max):
                actions.append("Raise " + str(stacks[index][k]))
                curr_max = stacks[index][k]
            elif stacks[index][k]:
                actions.append("Call " + str(stacks[index][k]))
 
    return actions
print(get_actions(transposed))  # should print ['Fold','Raise 2','Fold','Raise 7.5,'Fold','Raise 21','Fold','Call']
Asked By: Alice Myers

||

Answers:

I can’t test it right now but try if this works. It might look a bit longer than what you had but I think it’s a very intuitive way of going at this problem:

from itertools import accumulate

def get_actions(stacks):
    
    # this part should probably go in the transform_stacks function
    # what it does is give you the cumulative total rather than the individual raises
    # this makes sense because you want the output to be "raise 21" 
    # for the BB in the example, rather than "raise 20"
    stacks = [list(accumulate(x)) for x in stacks]

    SB = None
    for i, stack in enumerate(stacks):
        try:           
            if stack[0] == 0.5:             
                SB = i
                break      
        except IndexError:
            continue

    # just to make sure
    if SB is None:
        raise ValueError("Small Blind not found")
    
    num_players = len(stacks)
    stacks[SB].pop(0)
    bet = stacks[(SB+1)%num_players].pop(0)
    action_on_player = (SB+2)%num_players

    action_strings, out_of_hand = [], []
    while any(stacks):

        if action_on_player in out_of_hand:
            action_on_player = (action_on_player+1)%num_players
            continue

        if not stacks[action_on_player]:
            action_strings.append("Fold")
            out_of_hand.append(action_on_player)
            action_on_player = (action_on_player+1)%num_players
            continue
        
        action = stacks[action_on_player].pop(0)
        if action == bet:
            action_strings.append("Call")
        else:
            action_strings.append("Raise " + str(action))
            bet = action
        
        action_on_player = (action_on_player+1)%num_players

    return action_strings
Answered By: yagod
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.