Skip to content

Commit

Permalink
Merge #232
Browse files Browse the repository at this point in the history
232: Bot5050 -> FuzzBot, add sane Bot5050 r=charleskawczynski a=charleskawczynski

This PR renames `Bot5050` to `FuzzBot`, and adds `Bot5050` which is the same before but it doesn't fold when it can check. The FuzzBot is still used in the tests, since it's technically a valid action.

Co-authored-by: Charles Kawczynski <kawczynski.charles@gmail.com>
  • Loading branch information
bors[bot] and charleskawczynski authored Sep 30, 2023
2 parents e209337 + b8e8418 commit c727256
Show file tree
Hide file tree
Showing 19 changed files with 156 additions and 123 deletions.
2 changes: 1 addition & 1 deletion docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Chips
```@docs
AbstractStrategy
Human
Bot5050
FuzzBot
Player
bank_roll
bank_roll_chips
Expand Down
2 changes: 1 addition & 1 deletion docs/src/perf.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Logging
import Random
Random.seed!(1234)
players() = ntuple(i->(Player(Bot5050(), i)), 4)
players() = ntuple(i->(Player(FuzzBot(), i)), 4)
function do_work!()
play!(Game(players();logger=TH.ByPassLogger()))
Expand Down
2 changes: 1 addition & 1 deletion perf/benchmark.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Logging
import Random
Random.seed!(1234)

players() = ntuple(i->(Player(Bot5050(), i)), 4)
players() = ntuple(i->(Player(FuzzBot(), i)), 4)

# It's not easy to benchmark games without
# also benchmarking the creation/allocation
Expand Down
2 changes: 1 addition & 1 deletion perf/flame.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Logging
import Random
Random.seed!(1234)

players() = ntuple(i->(Player(Bot5050(), i)), 4)
players() = ntuple(i->(Player(FuzzBot(), i)), 4)

function do_work!(games)
for game in games
Expand Down
2 changes: 1 addition & 1 deletion perf/jet.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const TH = TexasHoldem
using TexasHoldem
using BenchmarkTools

players() = ntuple(i->(Player(Bot5050(), i)), 4)
players() = ntuple(i->(Player(FuzzBot(), i)), 4)

function do_work!(game)
play!(game)
Expand Down
25 changes: 23 additions & 2 deletions src/player_options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -305,15 +305,36 @@ player_option(game::Game, player::Player, option) =
##### AbstractStrategy
#####

##### Bot5050
##### FuzzBot

function player_option(game::Game, player::Player{Bot5050}, ::CheckRaiseFold)
function player_option(game::Game, player::Player{FuzzBot}, ::CheckRaiseFold)
rand() < 0.5 && return Check()
rand() < 0.5 && return Raise(rand(valid_raise_range(game.table, player)))
# while we can check for free, this bot is used for fuzzing,
# so we want to explore the most diverse set of possible cases.
return Fold()
end
function player_option(game::Game, player::Player{FuzzBot}, ::CallRaiseFold)
rand() < 0.5 && return Call(game.table, player)
rand() < 0.5 && return Raise(rand(valid_raise_range(game.table, player))) # re-raise
return Fold()
end
function player_option(game::Game, player::Player{FuzzBot}, ::CallAllInFold)
rand() < 0.5 && return Call(game.table, player)
rand() < 0.5 && return AllIn(game.table, player) # re-raise
return Fold()
end
function player_option(game::Game, player::Player{FuzzBot}, ::CallFold)
rand() < 0.5 && return Call(game.table, player)
return Fold()
end

##### Bot5050

function player_option(game::Game, player::Player{Bot5050}, ::CheckRaiseFold)
rand() < 0.5 && return Check()
return Raise(rand(valid_raise_range(game.table, player)))
end
function player_option(game::Game, player::Player{Bot5050}, ::CallRaiseFold)
rand() < 0.5 && return Call(game.table, player)
rand() < 0.5 && return Raise(rand(valid_raise_range(game.table, player))) # re-raise
Expand Down
16 changes: 14 additions & 2 deletions src/player_type.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,28 @@ and not for simulating games.
struct Human <: AbstractStrategy end

"""
Bot5050
FuzzBot
`Bot5050` is a stochastic strategy that
`FuzzBot` is a stochastic strategy that
chooses all of its actions based on a
coin flip.
This bot is used for fuzzing in the test
suite and for quick-start game configurations
for users.
"""
struct FuzzBot <: AbstractStrategy end

"""
Bot5050
`Bot5050` is a stochastic strategy that
chooses all of its actions based on a
coin flip.
This bot is used for quick-start game
configurations for users.
"""
struct Bot5050 <: AbstractStrategy end

"""
Expand Down
42 changes: 21 additions & 21 deletions test/call_raise_validation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,56 +49,56 @@ end

@testset "valid_raise_range" begin
# Case 1
table = QuietGame((Player(Bot5050(), 1; bank_roll=1), Player(Bot5050(), 2));blinds = TH.Blinds(2,4)).table
table = QuietGame((Player(FuzzBot(), 1; bank_roll=1), Player(FuzzBot(), 2));blinds = TH.Blinds(2,4)).table
players = TH.players_at_table(table)
table.current_raise_amt = 0
@test valid_raise_range_simple(table, players[1]) == (TH.valid_raise_range(table, players[1]), 1)

# Case 2
table = QuietGame((Player(Bot5050(), 1), Player(Bot5050(), 2; bank_roll = 300))).table
table = QuietGame((Player(FuzzBot(), 1), Player(FuzzBot(), 2; bank_roll = 300))).table
players = TH.players_at_table(table)
table.current_raise_amt = 0
@test valid_raise_range_simple(table, players[1]) == (TH.valid_raise_range(table, players[1]), 2)

# Case 3
table = QuietGame((Player(Bot5050(), 1; bank_roll=2), Player(Bot5050(), 2; bank_roll = 1)); blinds=TH.Blinds(2,4)).table
table = QuietGame((Player(FuzzBot(), 1; bank_roll=2), Player(FuzzBot(), 2; bank_roll = 1)); blinds=TH.Blinds(2,4)).table
players = TH.players_at_table(table)
table.current_raise_amt = 0
@test valid_raise_range_simple(table, players[1]) == (TH.valid_raise_range(table, players[1]), 3)

# Case 4
table = QuietGame((Player(Bot5050(), 1), Player(Bot5050(), 2; bank_roll = 50))).table
table = QuietGame((Player(FuzzBot(), 1), Player(FuzzBot(), 2; bank_roll = 50))).table
players = TH.players_at_table(table)
table.current_raise_amt = 0
@test valid_raise_range_simple(table, players[1]) == (TH.valid_raise_range(table, players[1]), 4)

# Case 5
table = QuietGame((Player(Bot5050(), 1; bank_roll=1), Player(Bot5050(), 2))).table
table = QuietGame((Player(FuzzBot(), 1; bank_roll=1), Player(FuzzBot(), 2))).table
players = TH.players_at_table(table)
table.current_raise_amt = 1
@test valid_raise_range_simple(table, players[1]) == (TH.valid_raise_range(table, players[1]), 5)

# Case 6
table = QuietGame((Player(Bot5050(), 1), Player(Bot5050(), 2; bank_roll = 300))).table
table = QuietGame((Player(FuzzBot(), 1), Player(FuzzBot(), 2; bank_roll = 300))).table
players = TH.players_at_table(table)
table.current_raise_amt = 1
@test valid_raise_range_simple(table, players[1]) == (TH.valid_raise_range(table, players[1]), 6)

# Case 7
table = QuietGame((Player(Bot5050(), 1; bank_roll=2), Player(Bot5050(), 2; bank_roll = 1));blinds=TH.Blinds(2,4)).table
table = QuietGame((Player(FuzzBot(), 1; bank_roll=2), Player(FuzzBot(), 2; bank_roll = 1));blinds=TH.Blinds(2,4)).table
players = TH.players_at_table(table)
table.current_raise_amt = 1
@test valid_raise_range_simple(table, players[1]) == (TH.valid_raise_range(table, players[1]), 7)

# Case 8
table = QuietGame((Player(Bot5050(), 1), Player(Bot5050(), 2; bank_roll = 50))).table
table = QuietGame((Player(FuzzBot(), 1), Player(FuzzBot(), 2; bank_roll = 50))).table
players = TH.players_at_table(table)
table.current_raise_amt = 1
@test valid_raise_range_simple(table, players[1]) == (TH.valid_raise_range(table, players[1]), 8)
end

@testset "is_valid_raise_amount" begin
players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
mra = TH.minimum_raise_amt(table)
@assert mra == TH.blinds(table).small
Expand All @@ -111,36 +111,36 @@ end
@test TH.is_valid_raise_amount(table, players[1], TH.blinds(table).big) == (true, "")
@test TH.is_valid_raise_amount(table, players[1], TH.bank_roll(players[1])) == (true, "")

players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.initial_round_raise_amt = 20
table.current_raise_amt = 20
players[1].round_contribution = 200
players[1].round_bank_roll = Chips(500) # oops
@test TH.is_valid_raise_amount(table, players[1], 200) == (false, "Cannot contribute 0 to the pot.")

players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.initial_round_raise_amt = 10
table.current_raise_amt = 10
players[1].round_bank_roll = Chips(20)
@test TH.is_valid_raise_amount(table, players[1], 10) == (false, "Only allowable raise is 20 (all-in)")

players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.initial_round_raise_amt = 10
table.current_raise_amt = 10
players[1].round_bank_roll = Chips(20)
@test TH.is_valid_raise_amount(table, players[1], 20) == (true, "")

players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.initial_round_raise_amt = 5
table.current_raise_amt = 20
players[1].round_bank_roll = Chips(30)
@test TH.is_valid_raise_amount(table, players[1], 25) == (true, "")

players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.initial_round_raise_amt = 5
table.current_raise_amt = 20
Expand All @@ -149,45 +149,45 @@ end
end

@testset "call_amount" begin
players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.current_raise_amt = 20
players[1].round_contribution = 10
@test call_amount(table, players[1]) == 10

players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.current_raise_amt = 10
players[1].round_contribution = 0
@test call_amount(table, players[1]) == 10

players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.current_raise_amt = 0
players[1].round_contribution = 10
@test_throws AssertionError("Round contribution must be zero if current raise is zero.") call_amount(table, players[1])

players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.round = Flop()
table.current_raise_amt = 10
players[1].round_contribution = 10
@test call_amount(table, players[1]) == 0

players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.round = Flop()
table.current_raise_amt = 10
players[1].round_contribution = 20
@test_throws AssertionError("Call amount cannot be negative") call_amount(table, players[1])

players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.current_raise_amt = TH.blinds(table).big
players[1].round_contribution = TH.blinds(table).big
@test call_amount(table, players[1]) == 0 # action is back to big-blind pre-flop

players = (Player(Human(), 1), Player(Bot5050(), 2))
players = (Player(Human(), 1), Player(FuzzBot(), 2))
table = QuietGame(players).table
table.current_raise_amt = TH.blinds(table).big
players[1].round_contribution = TH.blinds(table).big
Expand Down
30 changes: 15 additions & 15 deletions test/fuzz_play.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ where `3788` was found from
fuzz(;fun=tournament!,n_players=10,bank_roll=30,n_games=10000)
players = (
Player(Bot5050(), 1; bank_roll=9),
Player(Bot5050(), 2; bank_roll=5),
Player(Bot5050(), 3; bank_roll=4),
Player(FuzzBot(), 1; bank_roll=9),
Player(FuzzBot(), 2; bank_roll=5),
Player(FuzzBot(), 3; bank_roll=4),
)
fuzz_given_players_debug(;fun=play!, players, n_games=138)
fuzz_debug(; fun = tournament!, n_players = 10, bank_roll = 30, n_games = 1310)
Expand All @@ -21,39 +21,39 @@ fuzz_debug(; fun = play!, n_players = 3, bank_roll = 200, n_games = 2373)
=#
include("fuzz_utils.jl")

@testset "Game: play! (3 Bot5050's)" begin
@testset "Game: play! (3 FuzzBot's)" begin
@test isempty(fuzz(;fun=play!,n_players=3, bank_roll=200, n_games=100_000))
end

@testset "Game: play! (10 Bot5050's)" begin
@testset "Game: play! (10 FuzzBot's)" begin
@test isempty(fuzz(;fun=play!,n_players=10, bank_roll=200, n_games=10_000))
end

@testset "Game: play! (3 Bot5050's)" begin
@testset "Game: play! (3 FuzzBot's)" begin
players = (
Player(Bot5050(), 1; bank_roll=9),
Player(Bot5050(), 2; bank_roll=5),
Player(Bot5050(), 3; bank_roll=4),
Player(FuzzBot(), 1; bank_roll=9),
Player(FuzzBot(), 2; bank_roll=5),
Player(FuzzBot(), 3; bank_roll=4),
)
@test isempty(fuzz_given_players(;fun=play!, players, n_games=10_000))
end

@testset "Game: tournament! (2 Bot5050's)" begin
@testset "Game: tournament! (2 FuzzBot's)" begin
@test isempty(fuzz(;fun=tournament!,n_players=2, bank_roll=6, n_games=10_000))
@test isempty(fuzz(;fun=tournament!,n_players=2, bank_roll=30,n_games=100_000))
end

@testset "Game: tournament! (3 Bot5050's)" begin
@testset "Game: tournament! (3 FuzzBot's)" begin
@test isempty(fuzz(;fun=tournament!,n_players=3, bank_roll=6, n_games=10_000))
@test isempty(fuzz(;fun=tournament!,n_players=3, bank_roll=30, n_games=100_000))
end

@testset "Game: tournament! (10 Bot5050's)" begin
@testset "Game: tournament! (10 FuzzBot's)" begin
# https://github.com/charleskawczynski/TexasHoldem.jl/issues/151
@test isempty(fuzz(;fun=tournament!,n_players=10,bank_roll=30,n_games=3788))
end

@testset "Game: tournament! (10 Bot5050's)" begin
@testset "Game: tournament! (10 FuzzBot's)" begin
# https://github.com/charleskawczynski/TexasHoldem.jl/issues/151
@test isempty(fuzz(;fun=tournament!,n_players=10,bank_roll=30,n_games=3788))
end
Expand All @@ -66,9 +66,9 @@ end
br = 30
rperm = Random.randperm(n_players)
games1 = seeded_game(;fun=play!, n_games, players =
ntuple(i->Player(Bot5050(), i; bank_roll=br), n_players))
ntuple(i->Player(FuzzBot(), i; bank_roll=br), n_players))
games2 = seeded_game(;fun=play!, n_games, players =
ntuple(i->Player(Bot5050(), rperm[i]; bank_roll=br), n_players))
ntuple(i->Player(FuzzBot(), rperm[i]; bank_roll=br), n_players))

for (g1, g2) in zip(games1, games2)
for (p1, p2) in zip(g1.table.players, g2.table.players)
Expand Down
4 changes: 2 additions & 2 deletions test/fuzz_utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ to enforce tests that work.
=#
function fuzz(;fun, n_players, n_games, bank_roll=200)
Random.seed!(1234)
players = ntuple(i->Player(Bot5050(), i; bank_roll=bank_roll), n_players)
players = ntuple(i->Player(FuzzBot(), i; bank_roll=bank_roll), n_players)
return fuzz_given_players(;fun, n_games, players)
end

Expand Down Expand Up @@ -57,7 +57,7 @@ swap the logger to debug level for the
indices that fail.
=#
function fuzz_debug(;fun,n_players, n_games, bank_roll=200)
players = ntuple(i->Player(Bot5050(), i; bank_roll=bank_roll), n_players)
players = ntuple(i->Player(FuzzBot(), i; bank_roll=bank_roll), n_players)
fuzz_given_players_debug(;fun,n_games, players)
end

Expand Down
Loading

0 comments on commit c727256

Please sign in to comment.