Isolate and improve logic to determine default move.
This commit is contained in:
parent
a1ee890dde
commit
020303a8dd
2 changed files with 107 additions and 19 deletions
60
standard.go
60
standard.go
|
|
@ -98,8 +98,20 @@ func (r *StandardRuleset) moveSnakes(b *BoardState, moves []SnakeMove) error {
|
|||
|
||||
for _, move := range moves {
|
||||
if move.ID == snake.ID {
|
||||
var newHead = Point{}
|
||||
appliedMove := move.Move
|
||||
switch move.Move {
|
||||
case MoveUp, MoveDown, MoveRight, MoveLeft:
|
||||
break
|
||||
default:
|
||||
appliedMove = r.getDefaultMove(snake.Body)
|
||||
}
|
||||
|
||||
newHead := Point{}
|
||||
switch appliedMove {
|
||||
// Guaranteed to be one of these options given the clause above
|
||||
case MoveUp:
|
||||
newHead.X = snake.Body[0].X
|
||||
newHead.Y = snake.Body[0].Y + 1
|
||||
case MoveDown:
|
||||
newHead.X = snake.Body[0].X
|
||||
newHead.Y = snake.Body[0].Y - 1
|
||||
|
|
@ -109,24 +121,6 @@ func (r *StandardRuleset) moveSnakes(b *BoardState, moves []SnakeMove) error {
|
|||
case MoveRight:
|
||||
newHead.X = snake.Body[0].X + 1
|
||||
newHead.Y = snake.Body[0].Y
|
||||
case MoveUp:
|
||||
newHead.X = snake.Body[0].X
|
||||
newHead.Y = snake.Body[0].Y + 1
|
||||
default:
|
||||
// Default to UP
|
||||
var dX int32 = 0
|
||||
var dY int32 = 1
|
||||
// If neck is available, use neck to determine last direction
|
||||
if len(snake.Body) >= 2 {
|
||||
dX = snake.Body[0].X - snake.Body[1].X
|
||||
dY = snake.Body[0].Y - snake.Body[1].Y
|
||||
if dX == 0 && dY == 0 {
|
||||
dY = 1 // Move up if no last move was made
|
||||
}
|
||||
}
|
||||
// Apply
|
||||
newHead.X = snake.Body[0].X + dX
|
||||
newHead.Y = snake.Body[0].Y + dY
|
||||
}
|
||||
|
||||
// Append new head, pop old tail
|
||||
|
|
@ -137,6 +131,34 @@ func (r *StandardRuleset) moveSnakes(b *BoardState, moves []SnakeMove) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *StandardRuleset) getDefaultMove(snakeBody []Point) string {
|
||||
if len(snakeBody) >= 2 {
|
||||
// Use neck to determine last move made
|
||||
head, neck := snakeBody[0], snakeBody[1]
|
||||
// Situations where neck is next to head
|
||||
if head.X == neck.X+1 {
|
||||
return MoveRight
|
||||
} else if head.X == neck.X-1 {
|
||||
return MoveLeft
|
||||
} else if head.Y == neck.Y+1 {
|
||||
return MoveUp
|
||||
} else if head.Y == neck.Y-1 {
|
||||
return MoveDown
|
||||
}
|
||||
// Consider the wrapped cases using zero axis to anchor
|
||||
if head.X == 0 && neck.X > 0 {
|
||||
return MoveRight
|
||||
} else if neck.X == 0 && head.X > 0 {
|
||||
return MoveLeft
|
||||
} else if head.Y == 0 && neck.Y > 0 {
|
||||
return MoveUp
|
||||
} else if neck.Y == 0 && head.Y > 0 {
|
||||
return MoveDown
|
||||
}
|
||||
}
|
||||
return MoveUp
|
||||
}
|
||||
|
||||
func (r *StandardRuleset) reduceSnakeHealth(b *BoardState) error {
|
||||
for i := 0; i < len(b.Snakes); i++ {
|
||||
if b.Snakes[i].EliminatedCause == NotEliminated {
|
||||
|
|
|
|||
|
|
@ -658,6 +658,72 @@ func TestMoveSnakesDefault(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetDefaultMove(t *testing.T) {
|
||||
tests := []struct {
|
||||
SnakeBody []Point
|
||||
ExpectedMove string
|
||||
}{
|
||||
// Default is always up
|
||||
{
|
||||
SnakeBody: []Point{},
|
||||
ExpectedMove: MoveUp,
|
||||
},
|
||||
{
|
||||
SnakeBody: []Point{{0, 0}},
|
||||
ExpectedMove: MoveUp,
|
||||
},
|
||||
{
|
||||
SnakeBody: []Point{{-1, -1}},
|
||||
ExpectedMove: MoveUp,
|
||||
},
|
||||
// Stacked (fallback to default)
|
||||
{
|
||||
SnakeBody: []Point{{2, 2}, {2, 2}},
|
||||
ExpectedMove: MoveUp,
|
||||
},
|
||||
// Neck next to head
|
||||
{
|
||||
SnakeBody: []Point{{2, 2}, {2, 1}},
|
||||
ExpectedMove: MoveUp,
|
||||
},
|
||||
{
|
||||
SnakeBody: []Point{{2, 2}, {2, 3}},
|
||||
ExpectedMove: MoveDown,
|
||||
},
|
||||
{
|
||||
SnakeBody: []Point{{2, 2}, {1, 2}},
|
||||
ExpectedMove: MoveRight,
|
||||
},
|
||||
{
|
||||
SnakeBody: []Point{{2, 2}, {3, 2}},
|
||||
ExpectedMove: MoveLeft,
|
||||
},
|
||||
// Board wrap cases
|
||||
{
|
||||
SnakeBody: []Point{{0, 0}, {0, 2}},
|
||||
ExpectedMove: MoveUp,
|
||||
},
|
||||
{
|
||||
SnakeBody: []Point{{0, 0}, {2, 0}},
|
||||
ExpectedMove: MoveRight,
|
||||
},
|
||||
{
|
||||
SnakeBody: []Point{{0, 2}, {0, 0}},
|
||||
ExpectedMove: MoveDown,
|
||||
},
|
||||
{
|
||||
SnakeBody: []Point{{2, 0}, {0, 0}},
|
||||
ExpectedMove: MoveLeft,
|
||||
},
|
||||
}
|
||||
|
||||
r := StandardRuleset{}
|
||||
for _, test := range tests {
|
||||
actualMove := r.getDefaultMove(test.SnakeBody)
|
||||
require.Equal(t, test.ExpectedMove, actualMove)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReduceSnakeHealth(t *testing.T) {
|
||||
b := &BoardState{
|
||||
Snakes: []Snake{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue