Skip to content

Commit

Permalink
Improve coverage, add some bots
Browse files Browse the repository at this point in the history
  • Loading branch information
charleskawczynski committed May 6, 2021
1 parent f5a13bd commit 8de54ea
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 29 deletions.
9 changes: 3 additions & 6 deletions src/game.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ end

function Game(players::Tuple;
deck = ordered_deck(),
table_in = nothing,
table = nothing,
button_id::Int = button_id(),
blinds::Blinds = Blinds(1,2),
)
Expand All @@ -32,10 +32,9 @@ function Game(players::Tuple;

# If the user is specifying the player cards, then the
# user should probably also handle the table cards too.
@assert table_in nothing
table = table_in
@assert table nothing
@assert cards(table) isa Tuple{Card,Card,Card,Card,Card}
@assert legnth(cards(table)) == 5
@assert length(cards(table)) == 5
@assert length(deck) + n_player_cards + length(cards(table)) == 52
else # nobody has been dealt yet
table = Table(;
Expand All @@ -54,8 +53,6 @@ function Game(players::Tuple;
end

players_at_table(game::Game) = players_at_table(game.table)
small_blind(game::Game) = small_blind(players_at_table(game), game.table)
big_blind(game::Game) = big_blind(players_at_table(game), game.table)
blinds(game::Game) = blinds(game.table)
any_actions_required(game::Game) = any_actions_required(game.table)

Expand Down
41 changes: 31 additions & 10 deletions src/player_options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,28 @@ end
##### AbstractAI
#####

##### BotSitOut

player_option(player::Player{BotSitOut}, ::PayBlindSitOut) = SitOut() # no other options needed

##### BotCheckFold

player_option(player::Player{BotCheckFold}, ::PayBlindSitOut) = PayBlind()
player_option!(game::Game, player::Player{BotCheckFold}, ::CheckRaiseFold) = check!(game, player)
player_option!(game::Game, player::Player{BotCheckFold}, ::CallRaiseFold) = fold!(game, player)

##### BotCheckCall

player_option(player::Player{BotCheckCall}, ::PayBlindSitOut) = PayBlind()
player_option!(game::Game, player::Player{BotCheckCall}, ::CheckRaiseFold) = check!(game, player)
function player_option!(game::Game, player::Player{BotCheckCall}, ::CallRaiseFold)
if game.table.current_raise_amt bank_roll(player)
call!(game, player, game.table.current_raise_amt)
else
call!(game, player, bank_roll(player))
end
end

##### BotRandom

player_option(player::Player{BotRandom}, ::PayBlindSitOut) = PayBlind()
Expand All @@ -77,16 +99,15 @@ function player_option!(game::Game, player::Player{BotRandom}, ::CheckRaiseFold)
end
function player_option!(game::Game, player::Player{BotRandom}, ::CallRaiseFold)
if rand() < 0.5
if rand() < 0.5 # TODO: broken: if false: no action is taken. Need raise_to! add validate_raise to properly fix
if game.table.current_raise_amt bank_roll(player)
call!(game, player, game.table.current_raise_amt)
else
call!(game, player, bank_roll(player))
end
if rand() < 0.5
amt = Int(round(rand()*bank_roll(player), digits=0))
raise_to!(game, player, min(amt, blinds(game).small))
end
# Call
if game.table.current_raise_amt bank_roll(player)
call!(game, player, game.table.current_raise_amt)
else
call!(game, player, bank_roll(player))
end
if rand() < 0.5
amt = Int(round(rand()*bank_roll(player), digits=0))
raise_to!(game, player, min(amt, blinds(game).small))
end
else
fold!(game, player)
Expand Down
6 changes: 5 additions & 1 deletion src/player_types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@
##### Player types
#####

export bank_roll
export Human
export BotRandom, bank_roll
export BotRandom, BotSitOut, BotCheckFold, BotCheckCall

abstract type AbstractLifeForm end

struct Human <: AbstractLifeForm end

abstract type AbstractAI <: AbstractLifeForm end
struct BotRandom <: AbstractAI end
struct BotSitOut <: AbstractAI end
struct BotCheckFold <: AbstractAI end
struct BotCheckCall <: AbstractAI end

ai_to_use() = BotRandom()

Expand Down
16 changes: 6 additions & 10 deletions src/table.jl
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,11 @@ circle_table(n_players, button_id, state) =
circle_table(table::Table, state) =
circle_table(length(table.players), table.button_id, state)

button(players::Tuple, table::Table) = players[circle_table(table, 1)]
small_blind(players::Tuple, table::Table) = players[circle_table(table, 2)]
big_blind(players::Tuple, table::Table) = players[circle_table(table, 3)]
small_blind(table::Table) = players_at_table(table)[circle_table(table, 2)]
big_blind(table::Table) = players_at_table(table)[circle_table(table, 3)]

any_actions_required(table::Table) = any(action_required.(players_at_table(table)))

player_button_star(table::Table, player::Player) =
table.button_id == player.id ? "*" : ""

abstract type TablePosition end
struct Button <: TablePosition end
struct SmallBlind <: TablePosition end
Expand Down Expand Up @@ -195,22 +191,22 @@ function deal!(table::Table, blinds::Blinds)
@info "$(name(player)) sat out a hand."
check_for_winner!(table)
elseif po isa PayBlind
if player.id == small_blind(players, table).id && bank_roll(player) blinds.small
if player.id == small_blind(table).id && bank_roll(player) blinds.small
player.cards = pop!(table.deck, 2)
player.all_in = true
@info "$(name(player)) paid the small blind (all-in) and dealt cards: $(player.cards)"
contribute!(table, player, bank_roll(player))
elseif player.id == big_blind(players, table).id && bank_roll(player) blinds.big
elseif player.id == big_blind(table).id && bank_roll(player) blinds.big
player.cards = pop!(table.deck, 2)
player.all_in = true
@info "$(name(player)) paid the big blind (all-in) and dealt cards: $(player.cards)"
contribute!(table, player, bank_roll(player))
else
player.cards = pop!(table.deck, 2)
if player.id == small_blind(players, table).id
if player.id == small_blind(table).id
@info "$(name(player)) paid the small blind and dealt cards: $(player.cards)"
contribute!(table, player, blinds.small)
elseif player.id == big_blind(players, table).id
elseif player.id == big_blind(table).id
@info "$(name(player)) paid the big blind and dealt cards: $(player.cards)"
contribute!(table, player, blinds.big)
else
Expand Down
6 changes: 4 additions & 2 deletions src/transactions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ function contribute!(table, player, amt, call=false)
for i in 1:length(tm.side_pots)
@assert 0 amt_remaining
side_pot_full(tm, i) && continue
cap_i = tm.side_pots[i].cap
cap_i = cap(tm.side_pots[i])
@assert 0 amt_remaining
cond = amt_remaining < cap_i
amt_contrib = cond ? amt_remaining : cap_i
Expand Down Expand Up @@ -179,7 +179,9 @@ function distribute_winnings!(players, tm::TransactionManager, table_cards)
end
all_valid_min_hrs = min(map(x->hand_rank(x.fhe), filter(x->x.eligible, hand_evals_sorted))...)

winner_ids = findall(x->hand_rank(x.fhe)==all_valid_min_hrs && x.eligible, hand_evals_sorted)
winner_ids = findall(hand_evals_sorted) do x
x.eligible ? hand_rank(x.fhe)==all_valid_min_hrs : false
end
n_winners = length(winner_ids)
@debug "winner_ids = $(winner_ids)"
for winner_id in winner_ids
Expand Down
10 changes: 10 additions & 0 deletions test/game.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ NLH = NoLimitHoldem
sprint(show, game)
end

@testset "Game: pre-dealt deck" begin
deck = ordered_deck()
shuffle!(deck)
players = ntuple(3) do i
NLH.Player(BotRandom(), i, pop!(deck, 2))
end
table = Table(;players=players,deck=deck,cards=pop!(deck, 5))
game = Game(players;deck=deck,table=table)
end

@testset "Game: contrived game" begin
players = ntuple(3) do i
NLH.Player(BotRandom(), i)
Expand Down
20 changes: 20 additions & 0 deletions test/play.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,23 @@ NLH = NoLimitHoldem

play(game)
end

@testset "Game: Play (BotSitOut)" begin
players = (
NLH.Player(BotSitOut(), 1),
NLH.Player(BotRandom(), 2),
NLH.Player(BotRandom(), 3),
)
game = Game(players)
play(game)
end

@testset "Game: Play (BotCheckFold)" begin
players = (
NLH.Player(BotCheckFold(), 1),
NLH.Player(BotCheckFold(), 2),
NLH.Player(BotCheckFold(), 3),
)
game = Game(players)
play(game)
end

0 comments on commit 8de54ea

Please sign in to comment.