package main import "testing" func TestUrNewGameAllPiecesInHand(t *testing.T) { g := NewUrGame(UrPlayerA) for _, p := range [2]UrPlayer{UrPlayerA, UrPlayerB} { for i, pos := range g.Path[p] { if pos != 0 { t.Errorf("шашка %d игрока %v должна начинать в руке (0), получено %d", i, p, pos) } } } } func TestUrRollZeroEndsTurnImmediately(t *testing.T) { g := NewUrGame(UrPlayerA) if err := g.Roll(0); err != nil { t.Fatalf("неожиданная ошибка: %v", err) } if g.CurrentPlayer != UrPlayerB { t.Errorf("бросок 0 должен был сразу передать ход сопернику") } } func TestUrCannotRollTwiceInOneTurn(t *testing.T) { g := NewUrGame(UrPlayerA) g.Roll(3) if err := g.Roll(2); err != ErrUrAlreadyRolled { t.Errorf("ожидалась ошибка повторного броска, получено: %v", err) } } func TestUrMoveRequiresRollFirst(t *testing.T) { g := NewUrGame(UrPlayerA) if err := g.Move(0); err != ErrUrMustRollFirst { t.Errorf("ожидалась ошибка отсутствия броска, получено: %v", err) } } func TestUrEnterFromHand(t *testing.T) { g := NewUrGame(UrPlayerA) g.Roll(3) if err := g.Move(0); err != nil { t.Fatalf("неожиданная ошибка: %v", err) } if g.Path[UrPlayerA][0] != 3 { t.Errorf("ожидалась позиция 3 после входа с броском 3, получено %d", g.Path[UrPlayerA][0]) } } func TestUrCaptureOnSharedSquareSendsToHand(t *testing.T) { g := NewUrGame(UrPlayerA) g.Path[UrPlayerA][0] = 4 g.Path[UrPlayerB][0] = 7 // общая клетка (sharedIdx=2, не розетка) g.CurrentPlayer = UrPlayerA g.Rolled = true g.DiceValue = 3 // 4+3=7 — встаёт на шашку соперника if err := g.Move(0); err != nil { t.Fatalf("неожиданная ошибка: %v", err) } if g.Path[UrPlayerB][0] != 0 { t.Errorf("шашка соперника должна была вернуться в руку, получено %d", g.Path[UrPlayerB][0]) } if g.Path[UrPlayerA][0] != 7 { t.Errorf("своя шашка должна была встать на клетку 7, получено %d", g.Path[UrPlayerA][0]) } } func TestUrRosetteSquareBlocksCapture(t *testing.T) { g := NewUrGame(UrPlayerA) g.Path[UrPlayerA][0] = 4 g.Path[UrPlayerB][0] = 8 // общая клетка sharedIdx=3 — это розетка (pathIndex 8) g.CurrentPlayer = UrPlayerA g.Rolled = true g.DiceValue = 4 // 4+4=8 moves := g.LegalMoves() for _, mv := range moves { if mv.PieceIdx == 0 { t.Errorf("нельзя вставать на клетку с розеткой, занятую соперником") } } } func TestUrRosetteGrantsExtraTurn(t *testing.T) { g := NewUrGame(UrPlayerA) g.Path[UrPlayerA][0] = 4 g.CurrentPlayer = UrPlayerA g.Rolled = true g.DiceValue = 4 // 4+4=8, розетка if err := g.Move(0); err != nil { t.Fatalf("неожиданная ошибка: %v", err) } if g.CurrentPlayer != UrPlayerA { t.Errorf("розетка должна была дать дополнительный ход тому же игроку") } if g.Rolled { t.Errorf("после хода, давшего доп.бросок, Rolled должен был сброситься для нового броска") } } func TestUrNonRosetteEndsTurn(t *testing.T) { g := NewUrGame(UrPlayerA) g.Path[UrPlayerA][0] = 4 g.CurrentPlayer = UrPlayerA g.Rolled = true g.DiceValue = 2 // 4+2=6 — не розетка if err := g.Move(0); err != nil { t.Fatalf("неожиданная ошибка: %v", err) } if g.CurrentPlayer != UrPlayerB { t.Errorf("обычный (не розетка) ход должен был передать очередь сопернику") } } func TestUrExactRollRequiredToBearOff(t *testing.T) { g := NewUrGame(UrPlayerA) g.Path[UrPlayerA][0] = 13 g.CurrentPlayer = UrPlayerA g.Rolled = true g.DiceValue = 3 // 13+3=16 > 15 — перелёт, недопустимо moves := g.LegalMoves() for _, mv := range moves { if mv.PieceIdx == 0 { t.Errorf("перелёт при снятии с доски не должен быть разрешён") } } } func TestUrExactRollBearsOff(t *testing.T) { g := NewUrGame(UrPlayerA) g.Path[UrPlayerA][0] = 13 g.CurrentPlayer = UrPlayerA g.Rolled = true g.DiceValue = 2 // 13+2=15 — точное снятие if err := g.Move(0); err != nil { t.Fatalf("неожиданная ошибка: %v", err) } if g.Path[UrPlayerA][0] != UrPathLength+1 { t.Errorf("шашка должна была быть снята с доски (15), получено %d", g.Path[UrPlayerA][0]) } } func TestUrWinWhenAllSevenBorneOff(t *testing.T) { g := NewUrGame(UrPlayerA) for i := 0; i < UrPieceCount-1; i++ { g.Path[UrPlayerA][i] = UrPathLength + 1 } g.Path[UrPlayerA][UrPieceCount-1] = 13 g.CurrentPlayer = UrPlayerA g.Rolled = true g.DiceValue = 2 if err := g.Move(UrPieceCount - 1); err != nil { t.Fatalf("неожиданная ошибка: %v", err) } if g.Result == nil || g.Result.Winner != UrPlayerA { t.Fatalf("ожидалась победа игрока A, получено Result=%+v", g.Result) } } func TestUrNoLegalMovesEndsTurnAfterRoll(t *testing.T) { g := NewUrGame(UrPlayerA) for i := 0; i < UrPieceCount-1; i++ { g.Path[UrPlayerA][i] = UrPathLength + 1 } g.Path[UrPlayerA][UrPieceCount-1] = 14 g.CurrentPlayer = UrPlayerA if err := g.Roll(3); err != nil { // 14+3=17 — перелёт, нет легальных ходов t.Fatalf("неожиданная ошибка: %v", err) } if g.CurrentPlayer != UrPlayerB { t.Errorf("при отсутствии легальных ходов очередь должна была перейти к сопернику") } } func TestUrPrivateSquaresNeverConflictBetweenPlayers(t *testing.T) { g := NewUrGame(UrPlayerA) g.Path[UrPlayerB][0] = 2 // частная клетка B — не должна мешать A g.Path[UrPlayerA][0] = 0 g.CurrentPlayer = UrPlayerA g.Rolled = true g.DiceValue = 2 moves := g.LegalMoves() found := false for _, mv := range moves { if mv.PieceIdx == 0 { found = true } } if !found { t.Errorf("частная клетка соперника не должна мешать входу своей шашки на такую же по номеру собственную клетку") } }