Byte-snake-engine/maps/standard_test.go

326 lines
7.8 KiB
Go
Raw Normal View History

package maps_test
import (
"fmt"
"testing"
"github.com/BattlesnakeOfficial/rules"
"github.com/BattlesnakeOfficial/rules/maps"
"github.com/stretchr/testify/require"
)
func TestStandardMapInterface(t *testing.T) {
var _ maps.GameMap = maps.StandardMap{}
}
func TestStandardMapSetupBoard(t *testing.T) {
m := maps.StandardMap{}
settings := rules.Settings{}
tests := []struct {
name string
initialBoardState *rules.BoardState
rand rules.Rand
expected *rules.BoardState
err error
}{
{
"empty 7x7",
rules.NewBoardState(7, 7),
rules.MinRand,
&rules.BoardState{
Width: 7,
Height: 7,
Snakes: []rules.Snake{},
Food: []rules.Point{{X: 3, Y: 3}},
Hazards: []rules.Point{},
},
nil,
},
{
"not enough room for snakes 7x7",
&rules.BoardState{
Width: 7,
Height: 7,
Snakes: generateSnakes(9),
Food: []rules.Point{},
Hazards: []rules.Point{},
},
rules.MinRand,
nil,
rules.ErrorTooManySnakes,
},
{
"not enough room for snakes 5x5",
&rules.BoardState{
Width: 5,
Height: 5,
Snakes: generateSnakes(14),
Food: []rules.Point{},
Hazards: []rules.Point{},
},
rules.MinRand,
nil,
rules.ErrorNoRoomForSnake,
},
{
"full 11x11 min",
&rules.BoardState{
Width: 11,
Height: 11,
Snakes: generateSnakes(8),
Food: []rules.Point{},
Hazards: []rules.Point{},
},
rules.MinRand,
&rules.BoardState{
Width: 11,
Height: 11,
Snakes: []rules.Snake{
{ID: "1", Body: []rules.Point{{X: 1, Y: 1}, {X: 1, Y: 1}, {X: 1, Y: 1}}, Health: 100},
{ID: "2", Body: []rules.Point{{X: 1, Y: 9}, {X: 1, Y: 9}, {X: 1, Y: 9}}, Health: 100},
{ID: "3", Body: []rules.Point{{X: 9, Y: 1}, {X: 9, Y: 1}, {X: 9, Y: 1}}, Health: 100},
{ID: "4", Body: []rules.Point{{X: 9, Y: 9}, {X: 9, Y: 9}, {X: 9, Y: 9}}, Health: 100},
{ID: "5", Body: []rules.Point{{X: 1, Y: 5}, {X: 1, Y: 5}, {X: 1, Y: 5}}, Health: 100},
{ID: "6", Body: []rules.Point{{X: 5, Y: 1}, {X: 5, Y: 1}, {X: 5, Y: 1}}, Health: 100},
{ID: "7", Body: []rules.Point{{X: 5, Y: 9}, {X: 5, Y: 9}, {X: 5, Y: 9}}, Health: 100},
{ID: "8", Body: []rules.Point{{X: 9, Y: 5}, {X: 9, Y: 5}, {X: 9, Y: 5}}, Health: 100},
},
Food: []rules.Point{
{X: 0, Y: 2},
{X: 0, Y: 8},
{X: 8, Y: 0},
{X: 8, Y: 10},
{X: 0, Y: 4},
{X: 4, Y: 0},
{X: 4, Y: 10},
{X: 10, Y: 4},
{X: 5, Y: 5},
},
Hazards: []rules.Point{},
},
nil,
},
{
"full 11x11 max",
&rules.BoardState{
Width: 11,
Height: 11,
Snakes: generateSnakes(8),
Food: []rules.Point{},
Hazards: []rules.Point{},
},
rules.MaxRand,
&rules.BoardState{
Width: 11,
Height: 11,
Snakes: []rules.Snake{
{ID: "1", Body: []rules.Point{{X: 5, Y: 1}, {X: 5, Y: 1}, {X: 5, Y: 1}}, Health: 100},
{ID: "2", Body: []rules.Point{{X: 5, Y: 9}, {X: 5, Y: 9}, {X: 5, Y: 9}}, Health: 100},
{ID: "3", Body: []rules.Point{{X: 9, Y: 5}, {X: 9, Y: 5}, {X: 9, Y: 5}}, Health: 100},
{ID: "4", Body: []rules.Point{{X: 1, Y: 5}, {X: 1, Y: 5}, {X: 1, Y: 5}}, Health: 100},
{ID: "5", Body: []rules.Point{{X: 1, Y: 9}, {X: 1, Y: 9}, {X: 1, Y: 9}}, Health: 100},
{ID: "6", Body: []rules.Point{{X: 9, Y: 1}, {X: 9, Y: 1}, {X: 9, Y: 1}}, Health: 100},
{ID: "7", Body: []rules.Point{{X: 9, Y: 9}, {X: 9, Y: 9}, {X: 9, Y: 9}}, Health: 100},
{ID: "8", Body: []rules.Point{{X: 1, Y: 1}, {X: 1, Y: 1}, {X: 1, Y: 1}}, Health: 100},
},
Food: []rules.Point{
{X: 6, Y: 0},
{X: 6, Y: 10},
{X: 10, Y: 6},
{X: 0, Y: 6},
{X: 2, Y: 10},
{X: 10, Y: 2},
{X: 10, Y: 8},
{X: 2, Y: 0},
{X: 5, Y: 5},
},
Hazards: []rules.Point{},
},
nil,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
nextBoardState := rules.NewBoardState(test.initialBoardState.Width, test.initialBoardState.Height)
editor := maps.NewBoardStateEditor(nextBoardState)
settings := settings.WithRand(test.rand)
err := m.SetupBoard(test.initialBoardState, settings, editor)
if test.err != nil {
require.Equal(t, test.err, err)
} else {
require.Equalf(t, test.expected, nextBoardState, "%#v", nextBoardState.Food)
}
})
}
}
func TestStandardMapUpdateBoard(t *testing.T) {
m := maps.StandardMap{}
tests := []struct {
name string
initialBoardState *rules.BoardState
settings rules.Settings
rand rules.Rand
expected *rules.BoardState
}{
{
"empty no food",
rules.NewBoardState(2, 2),
rules.Settings{
FoodSpawnChance: 0,
MinimumFood: 0,
},
rules.MinRand,
&rules.BoardState{
Width: 2,
Height: 2,
Snakes: []rules.Snake{},
Food: []rules.Point{},
Hazards: []rules.Point{},
},
},
{
"empty MinimumFood",
rules.NewBoardState(2, 2),
rules.Settings{
FoodSpawnChance: 0,
MinimumFood: 2,
},
rules.MinRand,
&rules.BoardState{
Width: 2,
Height: 2,
Snakes: []rules.Snake{},
Food: []rules.Point{{X: 0, Y: 0}, {X: 0, Y: 1}},
Hazards: []rules.Point{},
},
},
{
"not empty MinimumFood",
&rules.BoardState{
Width: 2,
Height: 2,
Snakes: []rules.Snake{},
Food: []rules.Point{{X: 0, Y: 1}},
Hazards: []rules.Point{},
},
rules.Settings{
FoodSpawnChance: 0,
MinimumFood: 2,
},
rules.MinRand,
&rules.BoardState{
Width: 2,
Height: 2,
Snakes: []rules.Snake{},
Food: []rules.Point{{X: 0, Y: 1}, {X: 0, Y: 0}},
Hazards: []rules.Point{},
},
},
{
"empty FoodSpawnChance inactive",
rules.NewBoardState(2, 2),
rules.Settings{
FoodSpawnChance: 50,
MinimumFood: 0,
},
rules.MinRand,
&rules.BoardState{
Width: 2,
Height: 2,
Snakes: []rules.Snake{},
Food: []rules.Point{},
Hazards: []rules.Point{},
},
},
{
"empty FoodSpawnChance active",
rules.NewBoardState(2, 2),
rules.Settings{
FoodSpawnChance: 50,
MinimumFood: 0,
},
rules.MaxRand,
&rules.BoardState{
Width: 2,
Height: 2,
Snakes: []rules.Snake{},
Food: []rules.Point{{X: 0, Y: 1}},
Hazards: []rules.Point{},
},
},
{
"not empty FoodSpawnChance active",
&rules.BoardState{
Width: 2,
Height: 2,
Snakes: []rules.Snake{},
Food: []rules.Point{{X: 0, Y: 0}},
Hazards: []rules.Point{},
},
rules.Settings{
FoodSpawnChance: 50,
MinimumFood: 0,
},
rules.MaxRand,
&rules.BoardState{
Width: 2,
Height: 2,
Snakes: []rules.Snake{},
Food: []rules.Point{{X: 0, Y: 0}, {X: 1, Y: 0}},
Hazards: []rules.Point{},
},
},
{
"not empty FoodSpawnChance no room",
&rules.BoardState{
Width: 2,
Height: 2,
Snakes: []rules.Snake{},
Food: []rules.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 0}, {X: 1, Y: 1}},
Hazards: []rules.Point{},
},
rules.Settings{
FoodSpawnChance: 50,
MinimumFood: 0,
},
rules.MaxRand,
&rules.BoardState{
Width: 2,
Height: 2,
Snakes: []rules.Snake{},
Food: []rules.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 0}, {X: 1, Y: 1}},
Hazards: []rules.Point{},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
nextBoardState := test.initialBoardState.Clone()
settings := test.settings.WithRand(test.rand)
editor := maps.NewBoardStateEditor(nextBoardState)
err := m.UpdateBoard(test.initialBoardState.Clone(), settings, editor)
require.NoError(t, err)
require.Equal(t, test.expected, nextBoardState)
})
}
}
func generateSnakes(n int) []rules.Snake {
var snakes []rules.Snake
for i := 0; i < n; i++ {
snakes = append(snakes, rules.Snake{
ID: fmt.Sprint(i + 1),
})
}
return snakes
}