Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve coverage, add some bots #43

Merged
merged 1 commit into from
May 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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