151 lines
3.0 KiB
Go
151 lines
3.0 KiB
Go
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
|
|
}
|