forked from BattlesnakeOfficial/rules
-
Notifications
You must be signed in to change notification settings - Fork 0
/
solo_test.go
138 lines (123 loc) · 3.45 KB
/
solo_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package rules
import (
"testing"
"github.com/stretchr/testify/require"
)
func getSoloRuleset(settings Settings) Ruleset {
return NewRulesetBuilder().WithSettings(settings).NamedRuleset(GameTypeSolo)
}
func TestSoloName(t *testing.T) {
r := getSoloRuleset(Settings{})
require.Equal(t, "solo", r.Name())
}
func TestSoloCreateNextBoardStateSanity(t *testing.T) {
boardState := &BoardState{}
r := getSoloRuleset(Settings{})
gameOver, _, err := r.Execute(boardState, []SnakeMove{})
require.NoError(t, err)
require.True(t, gameOver)
}
func TestSoloIsGameOver(t *testing.T) {
tests := []struct {
Snakes []Snake
Expected bool
}{
{[]Snake{}, true},
{[]Snake{{}}, false},
{[]Snake{{}, {}, {}}, false},
{[]Snake{{EliminatedCause: EliminatedByOutOfBounds}}, true},
{
[]Snake{
{EliminatedCause: EliminatedByOutOfBounds},
{EliminatedCause: EliminatedByOutOfBounds},
{EliminatedCause: EliminatedByOutOfBounds},
},
true,
},
}
r := getSoloRuleset(Settings{})
for _, test := range tests {
b := &BoardState{
Height: 11,
Width: 11,
Snakes: test.Snakes,
Food: []Point{},
}
actual, _, err := r.Execute(b, nil)
require.NoError(t, err)
require.Equal(t, test.Expected, actual)
}
}
// Checks that a single snake doesn't end the game
// also that:
// - snake moves okay
// - food gets consumed
// - snake grows and gets health from food
var soloCaseNotOver = gameTestCase{
"Solo Case Game Not Over",
&BoardState{
Width: 10,
Height: 10,
Snakes: []Snake{
{
ID: "one",
Body: []Point{{X: 1, Y: 1}, {X: 1, Y: 2}},
Health: 100,
},
},
Food: []Point{{X: 0, Y: 0}, {X: 1, Y: 0}},
Hazards: []Point{},
},
[]SnakeMove{
{ID: "one", Move: MoveDown},
},
nil,
&BoardState{
Width: 10,
Height: 10,
Snakes: []Snake{
{
ID: "one",
Body: []Point{{X: 1, Y: 0}, {X: 1, Y: 1}, {X: 1, Y: 1}},
Health: 100,
},
},
Food: []Point{{X: 0, Y: 0}},
Hazards: []Point{},
},
}
func TestSoloCreateNextBoardState(t *testing.T) {
cases := []gameTestCase{
// inherits these test cases from standard
standardCaseErrNoMoveFound,
standardCaseErrZeroLengthSnake,
standardCaseMoveEatAndGrow,
standardMoveAndCollideMAD,
soloCaseNotOver,
}
r := getSoloRuleset(Settings{})
for _, gc := range cases {
// test a RulesBuilder constructed instance
gc.requireValidNextState(t, r)
// also test a pipeline with the same settings
gc.requireValidNextState(t, NewRulesetBuilder().PipelineRuleset(GameTypeSolo, NewPipeline(soloRulesetStages...)))
}
}
// Test a snake running right into the wall is properly eliminated
func TestSoloEliminationOutOfBounds(t *testing.T) {
r := getSoloRuleset(Settings{})
// Using MaxRand is important because it ensures that the snakes are consistently placed in a way this test will work.
// Actually random placement could result in the assumptions made by this test being incorrect.
initialState, err := CreateDefaultBoardState(MaxRand, 2, 2, []string{"one"})
require.NoError(t, err)
_, next, err := r.Execute(initialState, []SnakeMove{{ID: "one", Move: "right"}})
require.NoError(t, err)
require.NotNil(t, initialState)
ended, next, err := r.Execute(next, []SnakeMove{{ID: "one", Move: "right"}})
require.NoError(t, err)
require.NotNil(t, initialState)
require.True(t, ended)
require.Equal(t, EliminatedByOutOfBounds, next.Snakes[0].EliminatedCause)
require.Equal(t, "", next.Snakes[0].EliminatedBy)
require.Equal(t, 1, next.Snakes[0].EliminatedOnTurn)
}