Skip to content

Commit

Permalink
Merge #221
Browse files Browse the repository at this point in the history
221: Make sidepot amounts vectors r=charleskawczynski a=charleskawczynski

A step towards #220.

Co-authored-by: Charles Kawczynski <[email protected]>
  • Loading branch information
bors[bot] and charleskawczynski authored Aug 27, 2023
2 parents b5fc332 + cae8f57 commit bb388b9
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 61 deletions.
4 changes: 2 additions & 2 deletions src/game.jl
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ function _deal_and_play!(game::Game, sf::StartFrom)
distribute_winnings!(players, table.transactions, cards(table), logger)
winners.declared = true

@cdebug logger "amount.(table.transactions.side_pots) = $(amount.(table.transactions.side_pots))"
@cdebug logger "amounts.(table.transactions.side_pots) = $(amounts.(table.transactions.side_pots))"
@cdebug logger "initial_∑brs = $(initial_∑brs)"
@cdebug logger "sum(bank_roll.(players)) = $(sum(bank_roll.(players)))"
@cdebug logger "initial_brs = $(initial_brs)"
Expand All @@ -340,7 +340,7 @@ function _deal_and_play!(game::Game, sf::StartFrom)
end
@assert initial_∑brs == ∑bank_rolls(players) "initial_∑brs = $(initial_∑brs), ∑bank_rolls = $(∑bank_rolls(players))"
end
@assert sum(sp->amount(sp), table.transactions.side_pots) == 0
@assert sum(sp->sum(amounts(sp)), table.transactions.side_pots) == 0
for (player, initial_br) in zip(players, initial_brs)
mpp = max_possible_profit(player, players, initial_brs)
prof = bank_roll_chips(player) - initial_br
Expand Down
28 changes: 12 additions & 16 deletions src/transactions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@ const PHE = PokerHandEvaluator
"""
SidePot
A side-pot for player `seat_number`,
who has gone all-in with amount `amt`.
A side-pot for each player.
"""
mutable struct SidePot
seat_number::Int
amt::Int
amts::Vector{Int} # amount contributed per player
cap::Int # total amount any individual player can contribute to this side-pot
end
seat_number(sp::SidePot) = sp.seat_number
amount(sp::SidePot) = sp.amt
amounts(sp::SidePot) = sp.amts
cap(sp::SidePot) = sp.cap

const joker = Card(0, 1)
Expand Down Expand Up @@ -68,7 +65,8 @@ function TransactionManager(players::Players, logger)
unsorted_to_sorted_map = collect(map(players) do player
findfirst(p -> seat_number(players[p]) == seat_number(player), perm)
end)
side_pots = [SidePot(seat_number(players[p]), 0, cap_i) for (cap_i, p) in zip(cap, perm)]
amts = zeros(Int, length(players))
side_pots = [SidePot(deepcopy(amts), cap_i) for cap_i in cap]
@cdebug logger "initial caps = $(cap.(side_pots))"

initial_brs = deepcopy(collect(bank_roll_chips.(players)))
Expand Down Expand Up @@ -100,9 +98,7 @@ function reset!(tm::TransactionManager, players::Players)
player = players[i]
br = bank_roll(sp)
cap_i = i == 1 ? br : br - bank_roll(players[perm[i-1]])
ssn = seat_number(sp)::Int
tm.side_pots[i].seat_number = ssn
tm.side_pots[i].amt = 0
tm.side_pots[i].amts .= 0
tm.side_pots[i].cap = cap_i
for k in 1:length(players)
tm.side_pot_winnings[i][k] = Chips(0)
Expand Down Expand Up @@ -188,7 +184,7 @@ function contribute!(table, player, amt, call=false)
@cdebug logger "contributing, amt_contrib = $contributing, $amt_contrib"
contributing || continue
@assert !(amt_contrib == 0)
tm.side_pots[i].amt += amt_contrib
tm.side_pots[i].amts[seat_number(player)] += amt_contrib
player.bank_roll -= amt_contrib
amt_remaining -= amt_contrib
amt_remaining == 0 && break
Expand All @@ -201,7 +197,7 @@ function contribute!(table, player, amt, call=false)
end

if is_side_pot_full(tm, table, player, call)
set_side_pot_full!(tm)
increment_pot_id!(tm)
end
@cdebug logger "$(name(player))'s bank roll (post-contribute) = $(bank_roll(player))"
@cdebug logger "all_in($(name(player))) = $(all_in(player))"
Expand All @@ -216,11 +212,11 @@ function is_side_pot_full(tm::TransactionManager, table, player, call)
return @inbounds count(x->all_in(x), players) == tm.pot_id[1] && last_action_of_round(table, player, call)
end

set_side_pot_full!(tm::TransactionManager) = (tm.pot_id[1]+=1)
increment_pot_id!(tm::TransactionManager) = (tm.pot_id[1]+=1)
side_pot_full(tm::TransactionManager, i) = i < tm.pot_id[1]

Base.@propagate_inbounds function sidepot_winnings(tm::TransactionManager, id::Int)
mapreduce(i->tm.side_pots[i].amt, +, 1:id; init=0)
mapreduce(i->sum(tm.side_pots[i].amts), +, 1:id; init=0)
end

function profit(player, tm)
Expand Down Expand Up @@ -255,7 +251,7 @@ is_largest_pot_investment(player, players) =

function distribute_winnings!(players, tm::TransactionManager, table_cards, logger=InfoLogger())
@cdebug logger "--- Distributing winnings..."
@cdebug logger "Pot amounts = $(amount.(tm.side_pots))"
@cdebug logger "Pot amounts = $(amounts.(tm.side_pots))"
perm = tm.perm
sorted_hand_evals = tm.sorted_hand_evals
@inbounds for (ssn, p) in enumerate(perm)
Expand Down Expand Up @@ -330,7 +326,7 @@ function distribute_winnings!(players, tm::TransactionManager, table_cards, logg
tm.side_pot_winnings[win_seat][i] = amt_chips
end
for j in 1:i
tm.side_pots[j].amt = 0 # empty out distributed winnings
tm.side_pots[j].amts .= 0 # empty out distributed winnings
end
end

Expand Down
90 changes: 47 additions & 43 deletions test/transactions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ using PlayingCards
using TexasHoldem
using TexasHoldem: Player, Bot5050, TransactionManager, dealer_pidx, Table
const TH = TexasHoldem
all_zero(side_pots) = all(x-> all(y->y==0, x), side_pots)

include("tester_bots.jl")
#=
Expand All @@ -25,15 +26,14 @@ check!(t, p) = TH.update_given_valid_action!(t, p, Check())
)
tm = TH.TransactionManager(players, logger)
table = Table(players;cards=table_cards,transactions=tm, logger=TH.ByPassLogger())
@test TH.seat_number.(tm.side_pots) == [1,2,3]

raise_to!(table, players[1], 100) # raise all-in
call!(table, players[2]) # call
call!(table, players[3]) # call

@test TH.amount.(tm.side_pots) == [300, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100], [0, 0, 0], [0, 0, 0]]
TH.distribute_winnings!(players, tm, table_cards, TH.ByPassLogger())
@test TH.amount.(tm.side_pots) == [0, 0, 0]
@test all_zero(TH.amounts.(tm.side_pots))

@test bank_roll(players[1]) == 300
@test bank_roll(players[2]) == 100
Expand All @@ -55,9 +55,9 @@ end
call!(table, players[2]) # call
call!(table, players[3]) # all-in

@test TH.amount.(tm.side_pots) == [300, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100], [0, 0, 0], [0, 0, 0]]
TH.distribute_winnings!(players, tm, table_cards, TH.ByPassLogger())
@test TH.amount.(tm.side_pots) == [0, 0, 0]
@test all_zero(TH.amounts.(tm.side_pots))

@test bank_roll(players[1]) == 500
@test bank_roll(players[2]) == 100
Expand All @@ -79,7 +79,7 @@ end
call!(table, players[2]) # call
call!(table, players[3]) # call

@test TH.amount.(tm.side_pots) == [300, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100], [0, 0, 0], [0, 0, 0]]

@test_throws AssertionError call!(table, players[1]) # already all-in!

Expand All @@ -88,9 +88,9 @@ end
raise_to!(table, players[2], 100) # Raise all-in
call!(table, players[3]) # call

@test TH.amount.(tm.side_pots) == [300, 200, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100], [0, 100, 100], [0, 0, 0]]
TH.distribute_winnings!(players, tm, table_cards, TH.ByPassLogger())
@test TH.amount.(tm.side_pots) == [0, 0, 0]
@test all_zero(TH.amounts.(tm.side_pots))

@test bank_roll(players[1]) == 300
@test bank_roll(players[2]) == 200
Expand All @@ -112,18 +112,18 @@ end
call!(table, players[2]) # call
call!(table, players[3]) # all-in

@test TH.amount.(tm.side_pots) == [300, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100], [0, 0, 0], [0, 0, 0]]

TH.reset_round!(table)

raise_to!(table, players[1], 100) # call
call!(table, players[2]) # all-in
@test_throws AssertionError call!(table, players[3]) # already all-in!

@test TH.amount.(tm.side_pots) == [300, 200, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100], [100, 100, 0], [0, 0, 0]]

TH.distribute_winnings!(players, tm, table_cards, TH.ByPassLogger())
@test TH.amount.(tm.side_pots) == [0, 0, 0]
@test all_zero(TH.amounts.(tm.side_pots))

@test bank_roll(players[1]) == 600
@test bank_roll(players[2]) == 0
Expand All @@ -150,7 +150,8 @@ end
call!(table, players[4]) # call
call!(table, players[5]) # call
call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [600, 0, 0, 0, 0, 0]
z = [0, 0, 0, 0, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 100, 100, 100], z, z, z, z, z]

TH.reset_round!(table)

Expand All @@ -159,31 +160,31 @@ end
call!(table, players[4]) # call
call!(table, players[5]) # call
call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [600, 500, 0, 0, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 100, 100, 100], [0, 100, 100, 100, 100, 100], z, z, z, z]

TH.reset_round!(table)

raise_to!(table, players[3], 100) # raise all-in
call!(table, players[4]) # call
call!(table, players[5]) # call
call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [600, 500, 400, 0, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 100, 100, 100], [0, 100, 100, 100, 100, 100], [0, 0, 100, 100, 100, 100], z, z, z]

TH.reset_round!(table)

raise_to!(table, players[4], 100) # raise all-in
call!(table, players[5]) # call
call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [600, 500, 400, 300, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 100, 100, 100], [0, 100, 100, 100, 100, 100], [0, 0, 100, 100, 100, 100], [0, 0, 0, 100, 100, 100], z, z]

TH.reset_round!(table)

raise_to!(table, players[5], 100) # raise all-in
call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [600, 500, 400, 300, 200, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 100, 100, 100], [0, 100, 100, 100, 100, 100], [0, 0, 100, 100, 100, 100], [0, 0, 0, 100, 100, 100], [0, 0, 0, 0, 100, 100], z]

TH.distribute_winnings!(players, tm, table_cards, TH.ByPassLogger())
@test TH.amount.(tm.side_pots) == [0, 0, 0, 0, 0, 0]
@test all_zero(TH.amounts.(tm.side_pots))

@test bank_roll(players[1]) == 0 # bust
@test bank_roll(players[2]) == 550 # = 600/2+500/2
Expand Down Expand Up @@ -214,7 +215,8 @@ end
call!(table, players[4]) # call
call!(table, players[5]) # call
call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [42, 0, 0, 0, 0, 0]
z = [0, 0, 0, 0, 0, 0]
@test TH.amounts.(tm.side_pots) == [[7, 7, 7, 7, 7, 7], z, z, z, z, z]

TH.reset_round!(table)

Expand All @@ -223,31 +225,31 @@ end
call!(table, players[4]) # call
call!(table, players[5]) # call
call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [42, 35, 0, 0, 0, 0]
@test TH.amounts.(tm.side_pots) == [[7, 7, 7, 7, 7, 7], [0, 7, 7, 7, 7, 7], z, z, z, z]

TH.reset_round!(table)

raise_to!(table, players[3], 7) # raise all-in
call!(table, players[4]) # call
call!(table, players[5]) # call
call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [42, 35, 28, 0, 0, 0]
@test TH.amounts.(tm.side_pots) == [[7, 7, 7, 7, 7, 7], [0, 7, 7, 7, 7, 7], [0, 0, 7, 7, 7, 7], z, z, z]

TH.reset_round!(table)

raise_to!(table, players[4], 7) # raise all-in
call!(table, players[5]) # call
call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [42, 35, 28, 21, 0, 0]
@test TH.amounts.(tm.side_pots) == [[7, 7, 7, 7, 7, 7], [0, 7, 7, 7, 7, 7], [0, 0, 7, 7, 7, 7], [0, 0, 0, 7, 7, 7], z, z]

TH.reset_round!(table)

raise_to!(table, players[5], 7) # raise all-in
call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [42, 35, 28, 21, 14, 0]
@test TH.amounts.(tm.side_pots) == [[7, 7, 7, 7, 7, 7], [0, 7, 7, 7, 7, 7], [0, 0, 7, 7, 7, 7], [0, 0, 0, 7, 7, 7], [0, 0, 0, 0, 7, 7], z]

TH.distribute_winnings!(players, tm, table_cards, TH.ByPassLogger())
@test TH.amount.(tm.side_pots) == [0, 0, 0, 0, 0, 0]
@test all_zero(TH.amounts.(tm.side_pots))

@test bank_roll_chips(players[1]) == Chips(0) # bust
@test bank_roll_chips(players[2]) == Chips(38, SimpleRatio(1,2)) # = 42/2+35/2 = 38.5
Expand All @@ -271,28 +273,29 @@ end
)
tm = TH.TransactionManager(players, logger)
table = Table(players;cards=table_cards,transactions=tm, logger=TH.ByPassLogger())
@test TH.amount.(tm.side_pots) == [0, 0, 0, 0, 0, 0]
@test all_zero(TH.amounts.(tm.side_pots))
z = [0, 0, 0, 0, 0, 0]

raise_to!(table, players[1], 100) # raise all-in
@test TH.amount.(tm.side_pots) == [100, 0, 0, 0, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 0, 0, 0, 0, 0], z, z, z, z, z]

raise_to!(table, players[2], 200) # raise all-in
@test TH.amount.(tm.side_pots) == [200, 100, 0, 0, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 0, 0, 0, 0], [0, 100, 0, 0, 0, 0], z, z, z, z]

raise_to!(table, players[3], 300) # raise all-in
@test TH.amount.(tm.side_pots) == [300, 200, 100, 0, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 0, 0, 0], [0, 100, 100, 0, 0, 0], [0, 0, 100, 0, 0, 0], z, z, z]

raise_to!(table, players[4], 400) # raise all-in
@test TH.amount.(tm.side_pots) == [400, 300, 200, 100, 0, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 100, 0, 0], [0, 100, 100, 100, 0, 0], [0, 0, 100, 100, 0, 0], [0, 0, 0, 100, 0, 0], z, z]

raise_to!(table, players[5], 500) # raise all-in
@test TH.amount.(tm.side_pots) == [500, 400, 300, 200, 100, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 100, 100, 0], [0, 100, 100, 100, 100, 0], [0, 0, 100, 100, 100, 0], [0, 0, 0, 100, 100, 0], [0, 0, 0, 0, 100, 0], z]

call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [600, 500, 400, 300, 200, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 100, 100, 100], [0, 100, 100, 100, 100, 100], [0, 0, 100, 100, 100, 100], [0, 0, 0, 100, 100, 100], [0, 0, 0, 0, 100, 100], z]

TH.distribute_winnings!(players, tm, table_cards, TH.ByPassLogger())
@test TH.amount.(tm.side_pots) == [0, 0, 0, 0, 0, 0]
@test all_zero(TH.amounts.(tm.side_pots))

@test bank_roll(players[1]) == 0 # bust
@test bank_roll(players[2]) == 550 # = 600/2+500/2
Expand All @@ -316,28 +319,29 @@ end
)
tm = TH.TransactionManager(players, logger)
table = Table(players;cards=table_cards,transactions=tm, logger=TH.ByPassLogger())
@test TH.amount.(tm.side_pots) == [0, 0, 0, 0, 0, 0]
@test all_zero(TH.amounts.(tm.side_pots))
z = [0, 0, 0, 0, 0, 0]

raise_to!(table, players[1], 500) # raise to 500
@test TH.amount.(tm.side_pots) == [100, 100, 100, 100, 100, 0]
@test TH.amounts.(tm.side_pots) == [[100, 0, 0, 0, 0, 0], [100, 0, 0, 0, 0, 0], [100, 0, 0, 0, 0, 0], [100, 0, 0, 0, 0, 0], [100, 0, 0, 0, 0, 0], z]

call!(table, players[2]) # call
@test TH.amount.(tm.side_pots) == [200, 200, 200, 200, 200, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 0, 0, 0, 0], [100, 100, 0, 0, 0, 0], [100, 100, 0, 0, 0, 0], [100, 100, 0, 0, 0, 0], [100, 100, 0, 0, 0, 0], z]

call!(table, players[3]) # call
@test TH.amount.(tm.side_pots) == [300, 300, 300, 300, 200, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 0, 0, 0], [100, 100, 100, 0, 0, 0], [100, 100, 100, 0, 0, 0], [100, 100, 100, 0, 0, 0], [100, 100, 0, 0, 0, 0], z]

call!(table, players[4]) # call
@test TH.amount.(tm.side_pots) == [400, 400, 400, 300, 200, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 100, 0, 0], [100, 100, 100, 100, 0, 0], [100, 100, 100, 100, 0, 0], [100, 100, 100, 0, 0, 0], [100, 100, 0, 0, 0, 0], z]

call!(table, players[5]) # call
@test TH.amount.(tm.side_pots) == [500, 500, 400, 300, 200, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 100, 100, 0], [100, 100, 100, 100, 100, 0], [100, 100, 100, 100, 0, 0], [100, 100, 100, 0, 0, 0], [100, 100, 0, 0, 0, 0], z]

call!(table, players[6]) # call
@test TH.amount.(tm.side_pots) == [600, 500, 400, 300, 200, 0]
@test TH.amounts.(tm.side_pots) == [[100, 100, 100, 100, 100, 100], [100, 100, 100, 100, 100, 0], [100, 100, 100, 100, 0, 0], [100, 100, 100, 0, 0, 0], [100, 100, 0, 0, 0, 0], z]

TH.distribute_winnings!(players, tm, table_cards, TH.ByPassLogger())
@test TH.amount.(tm.side_pots) == [0, 0, 0, 0, 0, 0]
@test all_zero(TH.amounts.(tm.side_pots))

@test bank_roll(players[1]) == 100 # lost (but not all-in)
@test bank_roll(players[2]) == 500 # all contributions after 3rd all-in (3*100+2*100)
Expand All @@ -360,15 +364,15 @@ end
table = Table(players;cards=table_cards,transactions=tm, logger=TH.ByPassLogger())
TH.contribute!(table, players[2], 1, true) # small blind
TH.contribute!(table, players[3], 2, true) # big blind
@test TH.amount.(tm.side_pots) == [3, 0, 0]
@test TH.amounts.(tm.side_pots) == [[0, 1, 2], [0, 0, 0], [0, 0, 0]]

raise_to!(table, players[1], 5) # raise to 5
@test TH.amount.(tm.side_pots) == [7, 1, 0]
@test TH.amounts.(tm.side_pots) == [[4, 1, 2], [1, 0, 0], [0, 0, 0]]

call!(table, players[2]) # call
@test_broken TH.amount.(tm.side_pots) == [10, 2, 0]
@test_broken TH.amounts.(tm.side_pots) == [10, 2, 0]

call!(table, players[3]) # call
@test_broken TH.amount.(tm.side_pots) == [12, 2, 0]
@test_broken TH.amounts.(tm.side_pots) == [12, 2, 0]
@test_broken TH.side_pot_full(tm, 1) == true
end

0 comments on commit bb388b9

Please sign in to comment.