change map support for large #'s of snakes (#92)
* change map support for large #'s of snakes * test square board fn * format comment * add whitespace * better support large #'s of snakes on small boards * include an intermediate xlarge size
This commit is contained in:
parent
08cb7ae61d
commit
663c377cc4
10 changed files with 174 additions and 101 deletions
65
board.go
65
board.go
|
|
@ -84,14 +84,25 @@ func CreateDefaultBoardState(rand Rand, width int, height int, snakeIDs []string
|
||||||
|
|
||||||
// PlaceSnakesAutomatically initializes the array of snakes based on the provided snake IDs and the size of the board.
|
// PlaceSnakesAutomatically initializes the array of snakes based on the provided snake IDs and the size of the board.
|
||||||
func PlaceSnakesAutomatically(rand Rand, b *BoardState, snakeIDs []string) error {
|
func PlaceSnakesAutomatically(rand Rand, b *BoardState, snakeIDs []string) error {
|
||||||
if isFixedBoardSize(b) {
|
|
||||||
return PlaceSnakesFixed(rand, b, snakeIDs)
|
if isSquareBoard(b) {
|
||||||
}
|
// we don't allow > 8 snakes on very small boards
|
||||||
|
if len(snakeIDs) > 8 && b.Width < BoardSizeSmall {
|
||||||
if isExtraLargeBoardSize(b) {
|
return ErrorTooManySnakes
|
||||||
return PlaceManySnakesDistributed(rand, b, snakeIDs)
|
}
|
||||||
|
|
||||||
|
// we can do fixed placement for up to 8 snakes on minimum sized boards
|
||||||
|
if len(snakeIDs) <= 8 && b.Width >= BoardSizeSmall {
|
||||||
|
return PlaceSnakesFixed(rand, b, snakeIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// for > 8 snakes, we can do distributed placement
|
||||||
|
if b.Width >= BoardSizeMedium {
|
||||||
|
return PlaceManySnakesDistributed(rand, b, snakeIDs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// last resort for unexpected board sizes we'll just randomly place snakes
|
||||||
return PlaceSnakesRandomly(rand, b, snakeIDs)
|
return PlaceSnakesRandomly(rand, b, snakeIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -294,7 +305,7 @@ func PlaceSnakesRandomly(rand Rand, b *BoardState, snakeIDs []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(b.Snakes); i++ {
|
for i := 0; i < len(b.Snakes); i++ {
|
||||||
unoccupiedPoints := GetEvenUnoccupiedPoints(b)
|
unoccupiedPoints := removeCenterCoord(b, GetEvenUnoccupiedPoints(b))
|
||||||
if len(unoccupiedPoints) <= 0 {
|
if len(unoccupiedPoints) <= 0 {
|
||||||
return ErrorNoRoomForSnake
|
return ErrorNoRoomForSnake
|
||||||
}
|
}
|
||||||
|
|
@ -340,7 +351,7 @@ func PlaceSnake(b *BoardState, snakeID string, body []Point) error {
|
||||||
|
|
||||||
// PlaceFoodAutomatically initializes the array of food based on the size of the board and the number of snakes.
|
// PlaceFoodAutomatically initializes the array of food based on the size of the board and the number of snakes.
|
||||||
func PlaceFoodAutomatically(rand Rand, b *BoardState) error {
|
func PlaceFoodAutomatically(rand Rand, b *BoardState) error {
|
||||||
if isFixedBoardSize(b) || isExtraLargeBoardSize(b) {
|
if isSquareBoard(b) && b.Width >= BoardSizeSmall {
|
||||||
return PlaceFoodFixed(rand, b)
|
return PlaceFoodFixed(rand, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -350,7 +361,7 @@ func PlaceFoodAutomatically(rand Rand, b *BoardState) error {
|
||||||
func PlaceFoodFixed(rand Rand, b *BoardState) error {
|
func PlaceFoodFixed(rand Rand, b *BoardState) error {
|
||||||
centerCoord := Point{(b.Width - 1) / 2, (b.Height - 1) / 2}
|
centerCoord := Point{(b.Width - 1) / 2, (b.Height - 1) / 2}
|
||||||
|
|
||||||
isSmallBoard := b.Width*b.Height <= BoardSizeSmall*BoardSizeSmall
|
isSmallBoard := b.Width*b.Height < BoardSizeMedium*BoardSizeMedium
|
||||||
// Up to 4 snakes can be placed such that food is nearby on small boards.
|
// Up to 4 snakes can be placed such that food is nearby on small boards.
|
||||||
// Otherwise, we skip this and only try to place food in the center.
|
// Otherwise, we skip this and only try to place food in the center.
|
||||||
if len(b.Snakes) <= 4 || !isSmallBoard {
|
if len(b.Snakes) <= 4 || !isSmallBoard {
|
||||||
|
|
@ -368,6 +379,11 @@ func PlaceFoodFixed(rand Rand, b *BoardState) error {
|
||||||
availableFoodLocations := []Point{}
|
availableFoodLocations := []Point{}
|
||||||
for _, p := range possibleFoodLocations {
|
for _, p := range possibleFoodLocations {
|
||||||
|
|
||||||
|
// Don't place in the center
|
||||||
|
if centerCoord == p {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore points already occupied by food
|
// Ignore points already occupied by food
|
||||||
isOccupiedAlready := false
|
isOccupiedAlready := false
|
||||||
for _, food := range b.Food {
|
for _, food := range b.Food {
|
||||||
|
|
@ -464,6 +480,19 @@ func GetEvenUnoccupiedPoints(b *BoardState) []Point {
|
||||||
return evenUnoccupiedPoints
|
return evenUnoccupiedPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removeCenterCoord filters out the board's center point from a list of points.
|
||||||
|
func removeCenterCoord(b *BoardState, points []Point) []Point {
|
||||||
|
centerCoord := Point{(b.Width - 1) / 2, (b.Height - 1) / 2}
|
||||||
|
var noCenterPoints []Point
|
||||||
|
for _, p := range points {
|
||||||
|
if p != centerCoord {
|
||||||
|
noCenterPoints = append(noCenterPoints, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return noCenterPoints
|
||||||
|
}
|
||||||
|
|
||||||
func GetUnoccupiedPoints(b *BoardState, includePossibleMoves bool) []Point {
|
func GetUnoccupiedPoints(b *BoardState, includePossibleMoves bool) []Point {
|
||||||
pointIsOccupied := map[int]map[int]bool{}
|
pointIsOccupied := map[int]map[int]bool{}
|
||||||
for _, p := range b.Food {
|
for _, p := range b.Food {
|
||||||
|
|
@ -519,20 +548,6 @@ func getDistanceBetweenPoints(a, b Point) int {
|
||||||
return absInt(a.X-b.X) + absInt(a.Y-b.Y)
|
return absInt(a.X-b.X) + absInt(a.Y-b.Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isExtraLargeBoardSize(b *BoardState) bool {
|
func isSquareBoard(b *BoardState) bool {
|
||||||
// We can do placement for any square, large board using the distributed placement algorithm
|
return b.Width == b.Height
|
||||||
return b.Width == b.Height && b.Width >= 21
|
|
||||||
}
|
|
||||||
|
|
||||||
func isFixedBoardSize(b *BoardState) bool {
|
|
||||||
if b.Height == BoardSizeSmall && b.Width == BoardSizeSmall {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if b.Height == BoardSizeMedium && b.Width == BoardSizeMedium {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if b.Height == BoardSizeLarge && b.Width == BoardSizeLarge {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
107
board_test.go
107
board_test.go
|
|
@ -53,18 +53,47 @@ func TestCreateDefaultBoardState(t *testing.T) {
|
||||||
ExpectedNumFood int
|
ExpectedNumFood int
|
||||||
Err error
|
Err error
|
||||||
}{
|
}{
|
||||||
{1, 1, []string{"one"}, 0, nil},
|
{1, 1, []string{"one"}, 0, ErrorNoRoomForSnake},
|
||||||
{1, 2, []string{"one"}, 0, nil},
|
{1, 2, []string{"one"}, 0, ErrorNoRoomForSnake},
|
||||||
{1, 4, []string{"one"}, 1, nil},
|
{1, 4, []string{"one"}, 1, nil},
|
||||||
{2, 2, []string{"one"}, 1, nil},
|
{2, 2, []string{"one"}, 1, nil},
|
||||||
{9, 8, []string{"one"}, 1, nil},
|
{9, 8, []string{"one"}, 1, nil},
|
||||||
{2, 2, []string{"one", "two"}, 0, nil},
|
{2, 2, []string{"one", "two"}, 0, ErrorNoRoomForSnake},
|
||||||
{1, 1, []string{"one", "two"}, 2, ErrorNoRoomForSnake},
|
{1, 1, []string{"one", "two"}, 2, ErrorNoRoomForSnake},
|
||||||
{1, 2, []string{"one", "two"}, 2, ErrorNoRoomForSnake},
|
{1, 2, []string{"one", "two"}, 2, ErrorNoRoomForSnake},
|
||||||
{BoardSizeSmall, BoardSizeSmall, []string{"one", "two"}, 3, nil},
|
{BoardSizeSmall, BoardSizeSmall, []string{"one", "two"}, 3, nil},
|
||||||
|
{
|
||||||
|
BoardSizeSmall,
|
||||||
|
BoardSizeSmall,
|
||||||
|
[]string{"1", "2", "3", "4"},
|
||||||
|
5, // <= 4 snakes on a small board we get more than just center food
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BoardSizeSmall,
|
||||||
|
BoardSizeSmall,
|
||||||
|
[]string{"1", "2", "3", "4", "5"},
|
||||||
|
1, // for this size and this many snakes, food is only placed in the center
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BoardSizeSmall,
|
||||||
|
BoardSizeSmall,
|
||||||
|
[]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"},
|
||||||
|
1, // for this size and this many snakes, food is only placed in the center
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BoardSizeMedium,
|
||||||
|
BoardSizeMedium,
|
||||||
|
[]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"},
|
||||||
|
17, // > small boards and we get non-center food
|
||||||
|
nil,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for testNum, test := range tests {
|
for testNum, test := range tests {
|
||||||
|
t.Logf("test case %d", testNum)
|
||||||
state, err := CreateDefaultBoardState(MaxRand, test.Width, test.Height, test.IDs)
|
state, err := CreateDefaultBoardState(MaxRand, test.Width, test.Height, test.IDs)
|
||||||
require.Equal(t, test.Err, err)
|
require.Equal(t, test.Err, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -87,6 +116,7 @@ func TestPlaceSnakesDefault(t *testing.T) {
|
||||||
// Because placement is random, we only test to ensure
|
// Because placement is random, we only test to ensure
|
||||||
// that snake bodies are populated correctly
|
// that snake bodies are populated correctly
|
||||||
// Note: because snakes are randomly spawned on even diagonal points, the board can accomodate number of snakes equal to: width*height/2
|
// Note: because snakes are randomly spawned on even diagonal points, the board can accomodate number of snakes equal to: width*height/2
|
||||||
|
// Update: because we exclude the center point now, we can accommodate 1 less snake now (width*height/2 - 1)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
BoardState *BoardState
|
BoardState *BoardState
|
||||||
SnakeIDs []string
|
SnakeIDs []string
|
||||||
|
|
@ -98,7 +128,7 @@ func TestPlaceSnakesDefault(t *testing.T) {
|
||||||
Height: 1,
|
Height: 1,
|
||||||
},
|
},
|
||||||
make([]string, 1),
|
make([]string, 1),
|
||||||
nil,
|
ErrorNoRoomForSnake, // we avoid placing snakes in the center, so a board size of 1 will error
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
&BoardState{
|
&BoardState{
|
||||||
|
|
@ -137,9 +167,17 @@ func TestPlaceSnakesDefault(t *testing.T) {
|
||||||
Width: 5,
|
Width: 5,
|
||||||
Height: 10,
|
Height: 10,
|
||||||
},
|
},
|
||||||
make([]string, 25),
|
make([]string, 24),
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
&BoardState{
|
||||||
|
Width: 5,
|
||||||
|
Height: 10,
|
||||||
|
},
|
||||||
|
make([]string, 25),
|
||||||
|
ErrorNoRoomForSnake,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
&BoardState{
|
&BoardState{
|
||||||
Width: 10,
|
Width: 10,
|
||||||
|
|
@ -180,14 +218,6 @@ func TestPlaceSnakesDefault(t *testing.T) {
|
||||||
make([]string, 8),
|
make([]string, 8),
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
&BoardState{
|
|
||||||
Width: BoardSizeSmall,
|
|
||||||
Height: BoardSizeSmall,
|
|
||||||
},
|
|
||||||
make([]string, 9),
|
|
||||||
ErrorTooManySnakes,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
&BoardState{
|
&BoardState{
|
||||||
Width: BoardSizeMedium,
|
Width: BoardSizeMedium,
|
||||||
|
|
@ -201,7 +231,7 @@ func TestPlaceSnakesDefault(t *testing.T) {
|
||||||
Width: BoardSizeMedium,
|
Width: BoardSizeMedium,
|
||||||
Height: BoardSizeMedium,
|
Height: BoardSizeMedium,
|
||||||
},
|
},
|
||||||
make([]string, 9),
|
make([]string, 17),
|
||||||
ErrorTooManySnakes,
|
ErrorTooManySnakes,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -217,7 +247,7 @@ func TestPlaceSnakesDefault(t *testing.T) {
|
||||||
Width: BoardSizeLarge,
|
Width: BoardSizeLarge,
|
||||||
Height: BoardSizeLarge,
|
Height: BoardSizeLarge,
|
||||||
},
|
},
|
||||||
make([]string, 9),
|
make([]string, 17),
|
||||||
ErrorTooManySnakes,
|
ErrorTooManySnakes,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -422,17 +452,20 @@ func TestPlaceFood(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for i, test := range tests {
|
||||||
require.Len(t, test.BoardState.Food, 0)
|
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
|
||||||
err := PlaceFoodAutomatically(MaxRand, test.BoardState)
|
|
||||||
require.NoError(t, err)
|
require.Len(t, test.BoardState.Food, 0)
|
||||||
require.Equal(t, test.ExpectedFood, len(test.BoardState.Food))
|
err := PlaceFoodAutomatically(MaxRand, test.BoardState)
|
||||||
for _, point := range test.BoardState.Food {
|
require.NoError(t, err)
|
||||||
require.GreaterOrEqual(t, point.X, 0)
|
require.Equal(t, test.ExpectedFood, len(test.BoardState.Food))
|
||||||
require.GreaterOrEqual(t, point.Y, 0)
|
for _, point := range test.BoardState.Food {
|
||||||
require.Less(t, point.X, test.BoardState.Width)
|
require.GreaterOrEqual(t, point.X, 0)
|
||||||
require.Less(t, point.Y, test.BoardState.Height)
|
require.GreaterOrEqual(t, point.Y, 0)
|
||||||
}
|
require.Less(t, point.X, test.BoardState.Width)
|
||||||
|
require.Less(t, point.Y, test.BoardState.Height)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -637,14 +670,14 @@ func TestGetDistanceBetweenPoints(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsKnownBoardSize(t *testing.T) {
|
func TestIsSquareBoard(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Width int
|
Width int
|
||||||
Height int
|
Height int
|
||||||
Expected bool
|
Expected bool
|
||||||
}{
|
}{
|
||||||
{1, 1, false},
|
{1, 1, true},
|
||||||
{0, 0, false},
|
{0, 0, true},
|
||||||
{0, 45, false},
|
{0, 45, false},
|
||||||
{45, 1, false},
|
{45, 1, false},
|
||||||
{7, 7, true},
|
{7, 7, true},
|
||||||
|
|
@ -656,7 +689,7 @@ func TestIsKnownBoardSize(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
result := isFixedBoardSize(&BoardState{Width: test.Width, Height: test.Height})
|
result := isSquareBoard(&BoardState{Width: test.Width, Height: test.Height})
|
||||||
require.Equal(t, test.Expected, result)
|
require.Equal(t, test.Expected, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -824,12 +857,14 @@ func TestGetEvenUnoccupiedPoints(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for i, test := range tests {
|
||||||
evenUnoccupiedPoints := GetEvenUnoccupiedPoints(test.Board)
|
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
|
||||||
require.Equal(t, len(test.Expected), len(evenUnoccupiedPoints))
|
evenUnoccupiedPoints := GetEvenUnoccupiedPoints(test.Board)
|
||||||
for i, e := range test.Expected {
|
require.Equal(t, len(test.Expected), len(evenUnoccupiedPoints))
|
||||||
require.Equal(t, e, evenUnoccupiedPoints[i])
|
for i, e := range test.Expected {
|
||||||
}
|
require.Equal(t, e, evenUnoccupiedPoints[i])
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,11 @@ const (
|
||||||
MoveRight = "right"
|
MoveRight = "right"
|
||||||
MoveLeft = "left"
|
MoveLeft = "left"
|
||||||
|
|
||||||
BoardSizeSmall = 7
|
BoardSizeSmall = 7
|
||||||
BoardSizeMedium = 11
|
BoardSizeMedium = 11
|
||||||
BoardSizeLarge = 19
|
BoardSizeLarge = 19
|
||||||
|
BoardSizeXLarge = 21
|
||||||
|
BoardSizeXXLarge = 25
|
||||||
|
|
||||||
SnakeMaxHealth = 100
|
SnakeMaxHealth = 100
|
||||||
SnakeStartSize = 3
|
SnakeStartSize = 3
|
||||||
|
|
|
||||||
|
|
@ -19,16 +19,20 @@ func (m EmptyMap) Meta() Metadata {
|
||||||
Name: "Empty",
|
Name: "Empty",
|
||||||
Description: "Default snake placement with no food",
|
Description: "Default snake placement with no food",
|
||||||
Author: "Battlesnake",
|
Author: "Battlesnake",
|
||||||
Version: 1,
|
Version: 2,
|
||||||
MinPlayers: 1,
|
MinPlayers: 1,
|
||||||
MaxPlayers: 8,
|
MaxPlayers: 16,
|
||||||
BoardSizes: AnySize(),
|
BoardSizes: OddSizes(rules.BoardSizeSmall, rules.BoardSizeXXLarge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m EmptyMap) SetupBoard(initialBoardState *rules.BoardState, settings rules.Settings, editor Editor) error {
|
func (m EmptyMap) SetupBoard(initialBoardState *rules.BoardState, settings rules.Settings, editor Editor) error {
|
||||||
rand := settings.GetRand(0)
|
rand := settings.GetRand(0)
|
||||||
|
|
||||||
|
if len(initialBoardState.Snakes) > int(m.Meta().MaxPlayers) {
|
||||||
|
return rules.ErrorTooManySnakes
|
||||||
|
}
|
||||||
|
|
||||||
snakeIDs := make([]string, 0, len(initialBoardState.Snakes))
|
snakeIDs := make([]string, 0, len(initialBoardState.Snakes))
|
||||||
for _, snake := range initialBoardState.Snakes {
|
for _, snake := range initialBoardState.Snakes {
|
||||||
snakeIDs = append(snakeIDs, snake.ID)
|
snakeIDs = append(snakeIDs, snake.ID)
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ func TestEmptyMapSetupBoard(t *testing.T) {
|
||||||
&rules.BoardState{
|
&rules.BoardState{
|
||||||
Width: 7,
|
Width: 7,
|
||||||
Height: 7,
|
Height: 7,
|
||||||
Snakes: generateSnakes(9),
|
Snakes: generateSnakes(17),
|
||||||
Food: []rules.Point{},
|
Food: []rules.Point{},
|
||||||
Hazards: []rules.Point{},
|
Hazards: []rules.Point{},
|
||||||
},
|
},
|
||||||
|
|
@ -61,7 +61,7 @@ func TestEmptyMapSetupBoard(t *testing.T) {
|
||||||
},
|
},
|
||||||
rules.MinRand,
|
rules.MinRand,
|
||||||
nil,
|
nil,
|
||||||
rules.ErrorNoRoomForSnake,
|
rules.ErrorTooManySnakes,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full 11x11 min",
|
"full 11x11 min",
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,19 @@ func AnySize() sizes {
|
||||||
return sizes{Dimensions{Width: 0, Height: 0}}
|
return sizes{Dimensions{Width: 0, Height: 0}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OddSizes generates square (width = height) board sizes with an odd number of positions
|
||||||
|
// in the vertical and horizontal directions.
|
||||||
|
// Examples:
|
||||||
|
// - OddSizes(11,21) produces [(11,11), (13,13), (15,15), (17,17), (19,19), (21,21)]
|
||||||
|
func OddSizes(min, max uint) sizes {
|
||||||
|
var s sizes
|
||||||
|
for i := min; i <= max; i += 2 {
|
||||||
|
s = append(s, Dimensions{Width: i, Height: i})
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
// FixedSizes creates dimensions for a board that has 1 or more fixed sizes.
|
// FixedSizes creates dimensions for a board that has 1 or more fixed sizes.
|
||||||
// Examples:
|
// Examples:
|
||||||
// - FixedSizes(Dimension{9,11}) supports only a width of 9 and a height of 11.
|
// - FixedSizes(Dimension{9,11}) supports only a width of 9 and a height of 11.
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,10 @@ func (m InnerBorderHazardsMap) Meta() Metadata {
|
||||||
Name: "hz_inner_wall",
|
Name: "hz_inner_wall",
|
||||||
Description: "Creates a static map on turn 0 that is a 1-square wall of hazard that is inset 2 squares from the edge of the board",
|
Description: "Creates a static map on turn 0 that is a 1-square wall of hazard that is inset 2 squares from the edge of the board",
|
||||||
Author: "Battlesnake",
|
Author: "Battlesnake",
|
||||||
Version: 1,
|
Version: 2,
|
||||||
MinPlayers: 1,
|
MinPlayers: 1,
|
||||||
MaxPlayers: 8,
|
MaxPlayers: 16,
|
||||||
BoardSizes: AnySize(),
|
BoardSizes: OddSizes(rules.BoardSizeSmall, rules.BoardSizeXXLarge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,10 +69,10 @@ func (m ConcentricRingsHazardsMap) Meta() Metadata {
|
||||||
Name: "hz_rings",
|
Name: "hz_rings",
|
||||||
Description: "Creates a static map where there are rings of hazard sauce starting from the center with a 1 square space between the rings that has no sauce",
|
Description: "Creates a static map where there are rings of hazard sauce starting from the center with a 1 square space between the rings that has no sauce",
|
||||||
Author: "Battlesnake",
|
Author: "Battlesnake",
|
||||||
Version: 1,
|
Version: 2,
|
||||||
MinPlayers: 1,
|
MinPlayers: 1,
|
||||||
MaxPlayers: 8,
|
MaxPlayers: 16,
|
||||||
BoardSizes: AnySize(),
|
BoardSizes: OddSizes(rules.BoardSizeSmall, rules.BoardSizeXXLarge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,10 +110,10 @@ func (m ColumnsHazardsMap) Meta() Metadata {
|
||||||
Name: "hz_columns",
|
Name: "hz_columns",
|
||||||
Description: "Creates a static map on turn 0 that fills in odd squares, i.e. (1,1), (1,3), (3,3) ... with hazard sauce",
|
Description: "Creates a static map on turn 0 that fills in odd squares, i.e. (1,1), (1,3), (3,3) ... with hazard sauce",
|
||||||
Author: "Battlesnake",
|
Author: "Battlesnake",
|
||||||
Version: 1,
|
Version: 2,
|
||||||
MinPlayers: 1,
|
MinPlayers: 1,
|
||||||
MaxPlayers: 8,
|
MaxPlayers: 16,
|
||||||
BoardSizes: AnySize(),
|
BoardSizes: OddSizes(rules.BoardSizeSmall, rules.BoardSizeXXLarge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,10 +149,10 @@ func (m SpiralHazardsMap) Meta() Metadata {
|
||||||
Description: `Generates a dynamic hazard map that grows in a spiral pattern clockwise from a random point on
|
Description: `Generates a dynamic hazard map that grows in a spiral pattern clockwise from a random point on
|
||||||
the map. Each 2 turns a new hazard square is added to the map`,
|
the map. Each 2 turns a new hazard square is added to the map`,
|
||||||
Author: "altersaddle",
|
Author: "altersaddle",
|
||||||
Version: 1,
|
Version: 2,
|
||||||
MinPlayers: 1,
|
MinPlayers: 1,
|
||||||
MaxPlayers: 8,
|
MaxPlayers: 16,
|
||||||
BoardSizes: AnySize(),
|
BoardSizes: OddSizes(rules.BoardSizeSmall, rules.BoardSizeXXLarge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -241,10 +241,10 @@ func (m ScatterFillMap) Meta() Metadata {
|
||||||
return Metadata{
|
return Metadata{
|
||||||
Name: "hz_scatter",
|
Name: "hz_scatter",
|
||||||
Description: `Fills the entire board with hazard squares that are set to appear on regular turn schedule. Each square is picked at random.`,
|
Description: `Fills the entire board with hazard squares that are set to appear on regular turn schedule. Each square is picked at random.`,
|
||||||
Version: 1,
|
Version: 2,
|
||||||
MinPlayers: 1,
|
MinPlayers: 1,
|
||||||
MaxPlayers: 8,
|
MaxPlayers: 16,
|
||||||
BoardSizes: AnySize(),
|
BoardSizes: OddSizes(rules.BoardSizeSmall, rules.BoardSizeXXLarge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -292,10 +292,10 @@ func (m DirectionalExpandingBoxMap) Meta() Metadata {
|
||||||
return Metadata{
|
return Metadata{
|
||||||
Name: "hz_grow_box",
|
Name: "hz_grow_box",
|
||||||
Description: `Creates an area of hazard that expands from a point with one random side growing on a turn schedule.`,
|
Description: `Creates an area of hazard that expands from a point with one random side growing on a turn schedule.`,
|
||||||
Version: 1,
|
Version: 2,
|
||||||
MinPlayers: 1,
|
MinPlayers: 1,
|
||||||
MaxPlayers: 8,
|
MaxPlayers: 16,
|
||||||
BoardSizes: AnySize(),
|
BoardSizes: OddSizes(rules.BoardSizeSmall, rules.BoardSizeXXLarge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -406,10 +406,10 @@ func (m ExpandingBoxMap) Meta() Metadata {
|
||||||
return Metadata{
|
return Metadata{
|
||||||
Name: "hz_expand_box",
|
Name: "hz_expand_box",
|
||||||
Description: `Generates an area of hazard that expands from a random point on the board outward in concentric rings on a periodic turn schedule.`,
|
Description: `Generates an area of hazard that expands from a random point on the board outward in concentric rings on a periodic turn schedule.`,
|
||||||
Version: 1,
|
Version: 2,
|
||||||
MinPlayers: 1,
|
MinPlayers: 1,
|
||||||
MaxPlayers: 8,
|
MaxPlayers: 16,
|
||||||
BoardSizes: AnySize(),
|
BoardSizes: OddSizes(rules.BoardSizeSmall, rules.BoardSizeXXLarge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -481,10 +481,10 @@ func (m ExpandingScatterMap) Meta() Metadata {
|
||||||
return Metadata{
|
return Metadata{
|
||||||
Name: "hz_expand_scatter",
|
Name: "hz_expand_scatter",
|
||||||
Description: `Builds an expanding hazard area that grows from a central point in rings that are randomly filled in on a regular turn schedule.`,
|
Description: `Builds an expanding hazard area that grows from a central point in rings that are randomly filled in on a regular turn schedule.`,
|
||||||
Version: 1,
|
Version: 2,
|
||||||
MinPlayers: 1,
|
MinPlayers: 1,
|
||||||
MaxPlayers: 8,
|
MaxPlayers: 16,
|
||||||
BoardSizes: AnySize(),
|
BoardSizes: OddSizes(rules.BoardSizeSmall, rules.BoardSizeXXLarge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,10 @@ func (m RoyaleHazardsMap) Meta() Metadata {
|
||||||
Name: "Royale",
|
Name: "Royale",
|
||||||
Description: "A map where hazards are generated every N turns",
|
Description: "A map where hazards are generated every N turns",
|
||||||
Author: "Battlesnake",
|
Author: "Battlesnake",
|
||||||
Version: 1,
|
Version: 2,
|
||||||
MinPlayers: 1,
|
MinPlayers: 1,
|
||||||
MaxPlayers: 8,
|
MaxPlayers: 16,
|
||||||
BoardSizes: AnySize(),
|
BoardSizes: OddSizes(rules.BoardSizeSmall, rules.BoardSizeXXLarge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,16 +19,20 @@ func (m StandardMap) Meta() Metadata {
|
||||||
Name: "Standard",
|
Name: "Standard",
|
||||||
Description: "Standard snake placement and food spawning",
|
Description: "Standard snake placement and food spawning",
|
||||||
Author: "Battlesnake",
|
Author: "Battlesnake",
|
||||||
Version: 1,
|
Version: 2,
|
||||||
MinPlayers: 1,
|
MinPlayers: 1,
|
||||||
MaxPlayers: 8,
|
MaxPlayers: 16,
|
||||||
BoardSizes: AnySize(),
|
BoardSizes: OddSizes(rules.BoardSizeSmall, rules.BoardSizeXXLarge),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m StandardMap) SetupBoard(initialBoardState *rules.BoardState, settings rules.Settings, editor Editor) error {
|
func (m StandardMap) SetupBoard(initialBoardState *rules.BoardState, settings rules.Settings, editor Editor) error {
|
||||||
rand := settings.GetRand(0)
|
rand := settings.GetRand(0)
|
||||||
|
|
||||||
|
if len(initialBoardState.Snakes) > int(m.Meta().MaxPlayers) {
|
||||||
|
return rules.ErrorTooManySnakes
|
||||||
|
}
|
||||||
|
|
||||||
snakeIDs := make([]string, 0, len(initialBoardState.Snakes))
|
snakeIDs := make([]string, 0, len(initialBoardState.Snakes))
|
||||||
for _, snake := range initialBoardState.Snakes {
|
for _, snake := range initialBoardState.Snakes {
|
||||||
snakeIDs = append(snakeIDs, snake.ID)
|
snakeIDs = append(snakeIDs, snake.ID)
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ func TestStandardMapSetupBoard(t *testing.T) {
|
||||||
&rules.BoardState{
|
&rules.BoardState{
|
||||||
Width: 7,
|
Width: 7,
|
||||||
Height: 7,
|
Height: 7,
|
||||||
Snakes: generateSnakes(9),
|
Snakes: generateSnakes(17),
|
||||||
Food: []rules.Point{},
|
Food: []rules.Point{},
|
||||||
Hazards: []rules.Point{},
|
Hazards: []rules.Point{},
|
||||||
},
|
},
|
||||||
|
|
@ -62,7 +62,7 @@ func TestStandardMapSetupBoard(t *testing.T) {
|
||||||
},
|
},
|
||||||
rules.MinRand,
|
rules.MinRand,
|
||||||
nil,
|
nil,
|
||||||
rules.ErrorNoRoomForSnake,
|
rules.ErrorTooManySnakes,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"full 11x11 min",
|
"full 11x11 min",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue