DEV-1313: Add additional map types (#76)

* add helper to draw a ring of hazards

* refactor tests to not be internal tests

* add "hz_inner_wall" map

* add "hz_rings" map

* fix map registry

* fix: edge case bugs in drawRing

* remove println

* add "hz_columns"

* add "hz_rivers_bridges" map

* WIP: implementing spiral hazards map

* finish basic testing of 'hz_spiral'

* include first turn

* add "hz_hazards" map

* remove incorrect author

* add "hz_grow_box" map

* add "hz_expand_box" map

* add "hz_expand_scatter" map

* remove debug

* document the new "Range" method

* - use rules.RulesetError instead of generic error
- use a rules.Point for map rivers and bridgets map key

* use rules.RulesetError instead of errors.New

* provide more detail about boundar conditions

* fix documentation (max can be == min)

* add unit tests
This commit is contained in:
Torben 2022-06-01 11:39:31 -07:00 committed by GitHub
parent aa38bcd0eb
commit f0dc0bcb38
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 1129 additions and 24 deletions

View file

@ -1,6 +1,8 @@
package maps
import "github.com/BattlesnakeOfficial/rules"
import (
"github.com/BattlesnakeOfficial/rules"
)
// SetupBoard is a shortcut for looking up a map by ID and initializing a new board state with it.
func SetupBoard(mapID string, settings rules.Settings, width, height int, snakeIDs []string) (*rules.BoardState, error) {
@ -87,3 +89,91 @@ func (m StubMap) UpdateBoard(previousBoardState *rules.BoardState, settings rule
}
return nil
}
// drawRing draws a ring of hazard points offset from the outer edge of the board
func drawRing(bw, bh, hOffset, vOffset int) ([]rules.Point, error) {
if bw < 1 {
return nil, rules.RulesetError("board width too small")
}
if bh < 1 {
return nil, rules.RulesetError("board height too small")
}
if hOffset >= bw-1 {
return nil, rules.RulesetError("horizontal offset too large")
}
if vOffset >= bh-1 {
return nil, rules.RulesetError("vertical offset too large")
}
if hOffset < 1 {
return nil, rules.RulesetError("horizontal offset too small")
}
if vOffset < 1 {
return nil, rules.RulesetError("vertical offset too small")
}
// calculate the start/end point of the horizontal borders
xStart := hOffset - 1
xEnd := bw - hOffset
// calculate start/end point of the vertical borders
yStart := vOffset - 1
yEnd := bh - vOffset
// we can pre-determine how many points will be in the ring and allocate a slice of exactly that size
numPoints := 2 * (xEnd - xStart + 1) // horizontal hazard points
// Add vertical walls, if there are any.
// Sometimes there are no vertical walls when the ring height is only 2.
// In that case, the vertical walls are handled by the horizontal walls
if yEnd >= yStart {
numPoints += 2*(yEnd-yStart+1) - 4
}
hazards := make([]rules.Point, 0, numPoints)
// draw horizontal walls
for x := xStart; x <= xEnd; x++ {
hazards = append(hazards,
rules.Point{X: x, Y: yStart},
rules.Point{X: x, Y: yEnd},
)
}
// draw vertical walls, but don't include corners that the horizontal walls already included
for y := yStart + 1; y <= yEnd-1; y++ {
hazards = append(hazards,
rules.Point{X: xStart, Y: y},
rules.Point{X: xEnd, Y: y},
)
}
return hazards, nil
}
func maxInt(n1 int, n ...int) int {
max := n1
for _, v := range n {
if v > max {
max = v
}
}
return max
}
func isOnBoard(w, h, x, y int) bool {
if x >= w || x < 0 {
return false
}
if y >= h || y < 0 {
return false
}
return true
}