133 lines
5 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|
|
}
|