pokercore/examples/montecarlo/main.go

151 lines
3.0 KiB
Go
Raw Permalink Normal View History

package main
import (
"fmt"
"time"
"git.eeqj.de/sneak/pokercore"
"github.com/rcrowley/go-metrics"
"github.com/schollz/progressbar/v3"
)
var gameCount = 50_000
var playerCount = 2
type Player struct {
Hand pokercore.Cards
ScoredHand *pokercore.PokerHand
Position int
}
type Game struct {
Deck *pokercore.Deck
Players []*Player
Community pokercore.Cards
Street int
}
func NewGame() *Game {
g := &Game{}
g.Street = 0
g.Deck = pokercore.NewDeck()
g.Deck.ShuffleRandomly()
return g
}
func (g *Game) StreetAsString() string {
switch g.Street {
case 0:
return "pre-flop"
case 1:
return "flop"
case 2:
return "turn"
case 3:
return "river"
}
return "unknown"
}
func (g *Game) DealPlayersIn() {
for i := 0; i < playerCount; i++ {
p := Player{Hand: g.Deck.Deal(2), Position: i + 1}
g.Players = append(g.Players, &p)
}
}
func (g *Game) DealFlop() {
g.Community = g.Deck.Deal(3)
g.Street = 1
}
func (g *Game) DealTurn() {
g.Community = append(g.Community, g.Deck.Deal(1)...)
g.Street = 2
}
func (g *Game) DealRiver() {
g.Community = append(g.Community, g.Deck.Deal(1)...)
g.Street = 3
}
func (g *Game) ShowWinner() int {
var winner *Player
var winningHand *pokercore.PokerHand
for _, p := range g.Players {
if p != nil {
ac := append(p.Hand, g.Community...)
ph, err := ac.PokerHand()
if err != nil {
panic(err)
}
if winner == nil {
winner = p
winningHand = ph
} else {
if ph.Score > winningHand.Score {
winner = p
winningHand = ph
}
}
}
}
return winner.Position
}
func main() {
oneWins := 0
twoWins := 0
registry := metrics.NewRegistry()
timer := metrics.NewTimer()
registry.Register("pokerGame", timer)
bar := progressbar.NewOptions(gameCount,
progressbar.OptionSetDescription("Gambling..."),
progressbar.OptionShowCount(),
progressbar.OptionShowIts(),
progressbar.OptionSetPredictTime(true),
progressbar.OptionClearOnFinish(),
progressbar.OptionThrottle(100*time.Millisecond), // Update every 100ms
)
for i := 0; i < gameCount; i++ {
start := time.Now()
w := runFlip()
duration := time.Since(start)
timer.Update(duration)
bar.Add(1)
if w == 1 {
oneWins++
} else {
twoWins++
}
}
fmt.Printf("%d games played\n", gameCount)
fmt.Printf("Min: %d ns\n", timer.Min())
fmt.Printf("Max: %d ns\n", timer.Max())
fmt.Printf("Mean: %0.2f ns\n", timer.Mean())
fmt.Printf("StdDev: %0.2f ns\n", timer.StdDev())
fmt.Printf("Percentiles: 50%%: %0.2f ns, 75%%: %0.2f ns, 95%%: %0.2f ns, 99%%: %0.2f ns\n",
timer.Percentile(0.50),
timer.Percentile(0.75),
timer.Percentile(0.95),
timer.Percentile(0.99))
oneWinPercentage := float64(oneWins) / float64(gameCount) * 100
twoWinPercentage := float64(twoWins) / float64(gameCount) * 100
fmt.Printf("Player 1 won: %d (%0.2f%%)\n", oneWins, oneWinPercentage)
fmt.Printf("Player 2 won: %d (%0.2f%%)\n", twoWins, twoWinPercentage)
}
func runFlip() int {
g := NewGame()
g.DealPlayersIn()
g.DealFlop()
g.DealTurn()
g.DealRiver()
winnerPosition := g.ShowWinner()
return winnerPosition
}