146 lines
4 KiB
Go
146 lines
4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
func TestUrModelRollViaKey(t *testing.T) {
|
|
m := NewUrModel(UrDifficultyEasy)
|
|
m.game = NewUrGame(UrPlayerA)
|
|
m.humanColor = UrPlayerA
|
|
|
|
next, _ := m.Update(key("r"))
|
|
m = next.(UrModel)
|
|
if !m.game.Rolled && m.game.CurrentPlayer == UrPlayerA {
|
|
t.Errorf("после броска Rolled должен был выставиться (или очередь смениться, если ходов нет)")
|
|
}
|
|
}
|
|
|
|
func TestUrModelApplyMoveViaDigitKey(t *testing.T) {
|
|
m := NewUrModel(UrDifficultyEasy)
|
|
m.game = NewUrGame(UrPlayerA)
|
|
m.humanColor = UrPlayerA
|
|
m.game.Roll(3)
|
|
if m.game.CurrentPlayer != UrPlayerA {
|
|
t.Fatalf("тест предполагает ход человека")
|
|
}
|
|
|
|
next, _ := m.Update(key("1"))
|
|
m = next.(UrModel)
|
|
if m.isError {
|
|
t.Fatalf("неожиданная ошибка: %s", m.message)
|
|
}
|
|
if m.game.Path[UrPlayerA][0] != 3 {
|
|
t.Errorf("ожидалась позиция 3 после хода, получено %d", m.game.Path[UrPlayerA][0])
|
|
}
|
|
}
|
|
|
|
func TestUrModelRejectsMoveKeyBeforeRoll(t *testing.T) {
|
|
m := NewUrModel(UrDifficultyEasy)
|
|
m.game = NewUrGame(UrPlayerA)
|
|
m.humanColor = UrPlayerA
|
|
|
|
next, _ := m.Update(key("1"))
|
|
m = next.(UrModel)
|
|
if m.game.Path[UrPlayerA][0] != 0 {
|
|
t.Errorf("ход не должен был приняться до броска костей")
|
|
}
|
|
}
|
|
|
|
func TestUrModelBotPlaysWhenNotHumanTurn(t *testing.T) {
|
|
m := NewUrModel(UrDifficultyEasy)
|
|
m.game = NewUrGame(UrPlayerB)
|
|
m.humanColor = UrPlayerA
|
|
|
|
next, _ := m.Update(botMoveMsg{})
|
|
m = next.(UrModel)
|
|
if m.game.CurrentPlayer != UrPlayerA {
|
|
t.Errorf("после полного хода бота (без розеток) очередь должна была перейти к человеку")
|
|
}
|
|
}
|
|
|
|
func TestUrModelIgnoresBotMoveMsgOnHumanTurn(t *testing.T) {
|
|
m := NewUrModel(UrDifficultyEasy)
|
|
m.game = NewUrGame(UrPlayerA)
|
|
m.humanColor = UrPlayerA
|
|
|
|
next, _ := m.Update(botMoveMsg{})
|
|
m = next.(UrModel)
|
|
if m.game.Rolled {
|
|
t.Errorf("botMoveMsg не должно было ничего менять, пока сейчас ход человека")
|
|
}
|
|
}
|
|
|
|
func TestUrModelQReturnsToMenuNotQuitsApp(t *testing.T) {
|
|
m := NewUrModel(UrDifficultyEasy)
|
|
next, _ := m.Update(key("q"))
|
|
m = next.(UrModel)
|
|
if !m.backToMenu {
|
|
t.Errorf("ожидался флаг backToMenu после 'q'")
|
|
}
|
|
if m.quitting {
|
|
t.Errorf("'q' не должно завершать приложение целиком")
|
|
}
|
|
}
|
|
|
|
func TestUrModelActionsIgnoredAfterGameOver(t *testing.T) {
|
|
m := NewUrModel(UrDifficultyEasy)
|
|
m.game = NewUrGame(UrPlayerA)
|
|
m.humanColor = UrPlayerA
|
|
m.game.Result = &UrResult{Winner: UrPlayerA}
|
|
|
|
next, _ := m.Update(key("r"))
|
|
m = next.(UrModel)
|
|
if m.game.Rolled {
|
|
t.Errorf("действия после завершения партии не должны приниматься")
|
|
}
|
|
}
|
|
|
|
func TestUrModelFullAutoPlaythrough(t *testing.T) {
|
|
m := NewUrModel(UrDifficultyMedium)
|
|
m.game = NewUrGame(UrPlayerA)
|
|
m.humanColor = UrPlayerA
|
|
humanBot := UrBot{Difficulty: UrDifficultyMedium}
|
|
|
|
steps := 0
|
|
for m.game.Result == nil && steps < 20000 {
|
|
steps++
|
|
if m.game.CurrentPlayer != m.humanColor {
|
|
next, _ := m.Update(botMoveMsg{})
|
|
m = next.(UrModel)
|
|
continue
|
|
}
|
|
if !m.game.Rolled {
|
|
next, _ := m.Update(key("r"))
|
|
m = next.(UrModel)
|
|
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.PieceIdx == chosen {
|
|
idx = i
|
|
break
|
|
}
|
|
}
|
|
if idx < 0 {
|
|
idx = 0
|
|
}
|
|
next, _ := m.Update(key(fmt.Sprintf("%d", idx+1)))
|
|
m = next.(UrModel)
|
|
if m.isError {
|
|
t.Fatalf("неожиданная ошибка при ходе: %s", m.message)
|
|
}
|
|
}
|
|
if m.game.Result == nil {
|
|
t.Fatalf("партия не завершилась за %d шагов", steps)
|
|
}
|
|
}
|