go_games_collection/poker_bot_test.go
2026-07-10 09:12:06 +03:00

133 lines
5 KiB
Go

package main
import (
"math/rand"
"testing"
)
func TestPokerHandStrengthPocketAcesBeatsRandomMost(t *testing.T) {
rnd := rand.New(rand.NewSource(1))
aces := [2]Card{c(Ace, Spades), c(Ace, Hearts)}
strength := pokerHandStrength(aces, nil, 1, 300, rnd)
if strength < 0.7 {
t.Errorf("пара тузов против одного случайного соперника должна выигрывать заметно чаще, чем в 70%% случаев, получено %.2f", strength)
}
}
func TestPokerHandStrengthWeakHandLowerThanPocketAces(t *testing.T) {
rnd := rand.New(rand.NewSource(1))
aces := [2]Card{c(Ace, Spades), c(Ace, Hearts)}
weak := [2]Card{c(Two, Clubs), c(Seven, Diamonds)}
acesStrength := pokerHandStrength(aces, nil, 1, 300, rnd)
weakStrength := pokerHandStrength(weak, nil, 1, 300, rnd)
if weakStrength >= acesStrength {
t.Errorf("слабая рука 2-7 разномастные не должна оцениваться сильнее пары тузов: слабая=%.2f тузы=%.2f", weakStrength, acesStrength)
}
}
func TestCrudeStrengthPairHigherThanHighCardOnly(t *testing.T) {
pair := crudeStrength([2]Card{c(King, Clubs), c(King, Diamonds)}, nil)
highCard := crudeStrength([2]Card{c(Two, Clubs), c(Seven, Diamonds)}, nil)
if pair <= highCard {
t.Errorf("пара королей должна оцениваться выше, чем непарные 2-7, получено пара=%.2f старшая=%.2f", pair, highCard)
}
}
func TestRemainingDeckExcludesKnownCards(t *testing.T) {
hole := [2]Card{c(Ace, Spades), c(King, Hearts)}
board := []Card{c(Two, Clubs), c(Three, Diamonds), c(Four, Hearts)}
deck := remainingDeck(hole, board)
if len(deck) != 52-5 {
t.Fatalf("ожидалось 47 оставшихся карт, получено %d", len(deck))
}
known := map[Card]bool{hole[0]: true, hole[1]: true}
for _, cc := range board {
known[cc] = true
}
for _, card := range deck {
if known[card] {
t.Errorf("известная карта %v не должна встречаться в оставшейся колоде", card)
}
}
}
func playPokerFullTournament(t *testing.T, g *PokerGameState, bots []PokerBot, rnd *rand.Rand, maxHands int) {
t.Helper()
for hand := 0; hand < maxHands && g.Phase != PokerPhaseTournamentOver; hand++ {
steps := 0
for g.Phase != PokerPhaseShowdown && g.Phase != PokerPhaseTournamentOver && steps < 500 {
steps++
seat := g.CurrentPlayerIdx
if err := bots[seat].PlayFullTurn(g, seat, rnd); err != nil {
t.Fatalf("раздача %d, шаг %d: неожиданная ошибка бота на месте %d: %v", hand, steps, seat, err)
}
}
if g.Phase != PokerPhaseShowdown && g.Phase != PokerPhaseTournamentOver {
t.Fatalf("раздача %d не завершилась за %d шагов — похоже на зависание", hand, steps)
}
if g.Phase == PokerPhaseShowdown {
g.NextHand(rnd)
}
}
if g.Phase != PokerPhaseTournamentOver {
t.Fatalf("турнир не завершился за %d раздач", maxHands)
}
}
func TestPokerBotFullTournamentAllEasy(t *testing.T) {
rnd := rand.New(rand.NewSource(1))
for trial := 0; trial < 3; trial++ {
g := NewPokerGame(4, 500, 10, 20, rnd)
bots := []PokerBot{{Difficulty: PokerDifficultyEasy}, {Difficulty: PokerDifficultyEasy}, {Difficulty: PokerDifficultyEasy}, {Difficulty: PokerDifficultyEasy}}
playPokerFullTournament(t, g, bots, rnd, 300)
}
}
func TestPokerBotFullTournamentMixedDifficulties(t *testing.T) {
rnd := rand.New(rand.NewSource(2))
for trial := 0; trial < 2; trial++ {
g := NewPokerGame(4, 500, 10, 20, rnd)
bots := []PokerBot{
{Difficulty: PokerDifficultyEasy},
{Difficulty: PokerDifficultyMedium},
{Difficulty: PokerDifficultyHard},
{Difficulty: PokerDifficultyMedium},
}
playPokerFullTournament(t, g, bots, rnd, 300)
}
}
func TestPokerBotFullTournamentHeadsUp(t *testing.T) {
rnd := rand.New(rand.NewSource(3))
for trial := 0; trial < 3; trial++ {
g := NewPokerGame(2, 500, 10, 20, rnd)
bots := []PokerBot{{Difficulty: PokerDifficultyHard}, {Difficulty: PokerDifficultyEasy}}
playPokerFullTournament(t, g, bots, rnd, 300)
}
}
func TestPokerBotFullTournamentSixPlayers(t *testing.T) {
rnd := rand.New(rand.NewSource(4))
g := NewPokerGame(6, 500, 10, 20, rnd)
bots := make([]PokerBot, 6)
for i := range bots {
bots[i] = PokerBot{Difficulty: PokerDifficulty(i % 3)}
}
playPokerFullTournament(t, g, bots, rnd, 500)
}
func TestPokerBotNeverActsWithInvalidAmount(t *testing.T) {
rnd := rand.New(rand.NewSource(5))
for trial := 0; trial < 5; trial++ {
g := NewPokerGame(3, 200, 10, 20, rnd)
bots := []PokerBot{{Difficulty: PokerDifficultyHard}, {Difficulty: PokerDifficultyHard}, {Difficulty: PokerDifficultyHard}}
steps := 0
for g.Phase != PokerPhaseShowdown && g.Phase != PokerPhaseTournamentOver && steps < 200 {
steps++
seat := g.CurrentPlayerIdx
if err := bots[seat].PlayFullTurn(g, seat, rnd); err != nil {
t.Fatalf("бот попытался сделать недопустимое действие: %v", err)
}
}
}
}