go_games_collection/senet_tui_test.go

147 lines
4.2 KiB
Go

package main
import (
"fmt"
"testing"
)
func TestSenetModelRollViaKey(t *testing.T) {
m := NewSenetModel(SenetDifficultyEasy)
m.game = NewSenetGame(SenetPlayerA)
m.humanColor = SenetPlayerA
next, _ := m.Update(key("r"))
m = next.(SenetModel)
if m.game.DiceValue == 0 {
t.Errorf("после броска значение кости не должно оставаться нулевым")
}
}
func TestSenetModelApplyMoveViaDigitKey(t *testing.T) {
m := NewSenetModel(SenetDifficultyEasy)
m.game = NewSenetGame(SenetPlayerA)
m.humanColor = SenetPlayerA
m.game.Roll(2)
if m.game.CurrentPlayer != SenetPlayerA {
t.Fatalf("тест предполагает ход человека")
}
moves := m.game.LegalMoves()
if len(moves) == 0 {
t.Fatalf("ожидался хотя бы один легальный ход")
}
next, _ := m.Update(key("1"))
m = next.(SenetModel)
if m.isError {
t.Fatalf("неожиданная ошибка: %s", m.message)
}
}
func TestSenetModelRejectsMoveKeyBeforeRoll(t *testing.T) {
m := NewSenetModel(SenetDifficultyEasy)
m.game = NewSenetGame(SenetPlayerA)
m.humanColor = SenetPlayerA
next, _ := m.Update(key("1"))
m = next.(SenetModel)
if m.game.BorneOff[SenetPlayerA] != 0 || m.game.Rolled {
t.Errorf("ход не должен был приняться до броска костей")
}
}
func TestSenetModelBotPlaysWhenNotHumanTurn(t *testing.T) {
m := NewSenetModel(SenetDifficultyEasy)
m.game = NewSenetGame(SenetPlayerB)
m.humanColor = SenetPlayerA
next, _ := m.Update(botMoveMsg{})
m = next.(SenetModel)
if m.game.CurrentPlayer != SenetPlayerA && m.game.Result == nil {
t.Errorf("после хода бота (без доп.бросков) очередь должна была перейти к человеку")
}
}
func TestSenetModelIgnoresBotMoveMsgOnHumanTurn(t *testing.T) {
m := NewSenetModel(SenetDifficultyEasy)
m.game = NewSenetGame(SenetPlayerA)
m.humanColor = SenetPlayerA
next, _ := m.Update(botMoveMsg{})
m = next.(SenetModel)
if m.game.Rolled {
t.Errorf("botMoveMsg не должно было ничего менять, пока сейчас ход человека")
}
}
func TestSenetModelQReturnsToMenuNotQuitsApp(t *testing.T) {
m := NewSenetModel(SenetDifficultyEasy)
next, _ := m.Update(key("q"))
m = next.(SenetModel)
if !m.backToMenu {
t.Errorf("ожидался флаг backToMenu после 'q'")
}
if m.quitting {
t.Errorf("'q' не должно завершать приложение целиком")
}
}
func TestSenetModelActionsIgnoredAfterGameOver(t *testing.T) {
m := NewSenetModel(SenetDifficultyEasy)
m.game = NewSenetGame(SenetPlayerA)
m.humanColor = SenetPlayerA
m.game.Result = &SenetResult{Winner: SenetPlayerA}
next, _ := m.Update(key("r"))
m = next.(SenetModel)
if m.game.Rolled {
t.Errorf("действия после завершения партии не должны приниматься")
}
}
func TestSenetModelFullAutoPlaythrough(t *testing.T) {
m := NewSenetModel(SenetDifficultyMedium)
m.game = NewSenetGame(SenetPlayerA)
m.humanColor = SenetPlayerA
humanBot := SenetBot{Difficulty: SenetDifficultyMedium}
steps := 0
for m.game.Result == nil && steps < 30000 {
steps++
if m.game.CurrentPlayer != m.humanColor {
next, _ := m.Update(botMoveMsg{})
m = next.(SenetModel)
continue
}
if !m.game.Rolled {
next, _ := m.Update(key("r"))
m = next.(SenetModel)
continue
}
moves := m.game.LegalMoves()
if len(moves) == 0 {
t.Fatalf("LegalMoves пуст при Rolled=true для хода человека — не должно происходить")
}
if len(moves) > 9 {
t.Fatalf("число легальных ходов превысило 9: %d", len(moves))
}
chosen := humanBot.DecideMove(m.game, m.rng)
idx := -1
for i, mv := range moves {
if mv.From == chosen {
idx = i
break
}
}
if idx < 0 {
idx = 0
}
next, _ := m.Update(key(fmt.Sprintf("%d", idx+1)))
m = next.(SenetModel)
if m.isError {
t.Fatalf("неожиданная ошибка при ходе: %s", m.message)
}
}
if m.game.Result == nil {
t.Fatalf("партия не завершилась за %d шагов", steps)
}
}