Привет. Я пытаюсь создать калькулятор Poker ICM, который определяет ожидаемое значение для каждого игрока на основе размеров стеков и структуры выплат. Это работает, когда я подключаю 3 игроков за столом, но как только я пытаюсь 4, это выдает неправильные значения, и я вырываю свои волосы, пытаясь выяснить, почему. Вот мой код:
# starting vars
players_remaining = [ "p1", "p2", "p3" ]
players_remaining_stacks = [ 4500, 2700, 1800 ]
# first place pays $84, second $36
payouts = [ 84, 36, 0 ]
# calculate total chips among all players
total_chips = 0
for stack in players_remaining_stacks:
total_chips += stack
# STEP 1:
# create a list of all possible finish positions, each possibility has
# the remaining players finishing in a different order
possible_finish_positions = list(itertools.permutations(players_remaining, len(players_remaining)))
# STEP 2:
# Build matching list of possible_finish_probabilities
# to match possible_finish_positions, probability for each
# position in each scenario
possible_finish_probabilities = []
# loop through every permutation
for finish_positions in possible_finish_positions:
# % chance of each player finishing where they finish in this permutation
# this will get tacked onto possible_finish_probabilities when finished
perm_probabilities = []
# total amount of chips we've deducted for this permutation
perm_chips_deducted = 0
# loop through each finish position
for x in range(len(finish_positions)):
player_name = finish_positions[x]
index = players_remaining.index(player_name)
player_stack = players_remaining_stacks[index]
# the odds of this player finishing in this position is
# their chips divided by remaining chips
probability = player_stack / ( total_chips - perm_chips_deducted )
# add to the probabilities for this permutation
perm_probabilities.append(probability)
# deduct this player's chips from remaining chips
perm_chips_deducted += player_stack
possible_finish_probabilities.append(perm_probabilities)
# now we have two matching lists,
# possible_finish_positions and a matching possible_finish_probabilities
# STEP 3:
# we can now create the probabilities of finishing in each position for
# each player by looping through all of the scenarios for each player
finish_probabilities = []
# loop through each player
for player_name in players_remaining:
# initialize probability as 0 for this player
# finishing in each position
this_p_probabilities = []
for x in range(len(players_remaining)):
this_p_probabilities.append(0)
# loop through scenarios
for x in range(len(possible_finish_positions)):
# this permutation is one possible scenario
permutation = possible_finish_positions[x]
# determine where the player finishes in this scenario
position = permutation.index(player_name)
# initialize the probability as the probability
# for the player who finished first in this scenario
probability = possible_finish_probabilities[x][0]
# now if this player is not the player who finished first,
# need to adjust the probability by mutliplying it by
# the probability for every player in the scenario ahead of this
# player
if position != 0:
print("position not 0, adjusting")
# loop through everyone in front of this player
# in the scenario
for y in range(0, position):
# adjust the probability
probability *= possible_finish_probabilities[x][y + 1]
# if player is 1st in this scenario, their probability
# is set to this probability of finishing first.
# otherwise we add it to any other probabilities of the
# player finishing in this position
if position == 0:
this_p_probabilities[position] = probability
else:
this_p_probabilities[position] += probability
# finished probability for this player
finish_probabilities.append( this_p_probabilities )
print("finish_probabilities=")
for x in range(len(finish_probabilities)):
print(str(finish_probabilities[x]))
# now I can calculate the EV of each player
# multiply the probability of each position times the
# payout for that position
player_EVs = []
for x in range(len(finish_probabilities)):
# get the probability of player finishing
# in each position
probabilities = finish_probabilities[x]
EV = 0
# multiply probability of each position by the payout
# for that position
for y in range(len(probabilities)):
EV += probabilities[y] * payouts[y]
# store
player_EVs.append( EV )
print("player_EVs")
print(str(player_EVs))
Что сводит меня с ума, так это то, что этот код генерирует правильные значения EV ICM для этих 3 игроков согласно калькулятору ICM на https://www.icmpoker.com/icmcalculator/#RXui. Однако, если я изменю 3 переменные в верхней части на:
players_remaining = [ "p1", "p2", "p3", "p4" ]
players_remaining_stacks = [ 4500, 2700, 1800, 1000 ]
payouts = [ 84, 36, 0, 0 ]
Это добавит 4-го игрока в сценарий, и здесь значения EV будут далеко. В частности, когда я вывожу finish_probabilities ближе к концу кода, вероятности для каждого игрока выглядят правильными для их вероятности завершения первым, но остальные 3 выключены, и вероятности каждой позиции складываются более чем в 1 для каждого игрока.
Я перебирал этот код построчно и, насколько я знаю, он делает то, что, как я думаю, должен делать. Я не понимаю, почему это правильно для 3 игроков, но когда я добавляю 4-го, это не работает. Спасибо за любую помощь, спасибо.