diff --git a/board.go b/board.go index 8d15ea7..675ebc6 100644 --- a/board.go +++ b/board.go @@ -160,7 +160,7 @@ func PlaceFoodAutomatically(b *BoardState) error { func PlaceFoodFixed(b *BoardState) error { centerCoord := Point{(b.Width - 1) / 2, (b.Height - 1) / 2} - // Place 1 food within exactly 2 moves of each snake, but never towards the center + // Place 1 food within exactly 2 moves of each snake, but never towards the center or in a corner for i := 0; i < len(b.Snakes); i++ { snakeHead := b.Snakes[i].Body[0] possibleFoodLocations := []Point{ @@ -170,9 +170,11 @@ func PlaceFoodFixed(b *BoardState) error { {snakeHead.X + 1, snakeHead.Y + 1}, } - // Remove any positions already occupied by food or closer to center + // Remove any invalid/unwanted positions availableFoodLocations := []Point{} for _, p := range possibleFoodLocations { + + // Ignore points already occupied by food isOccupiedAlready := false for _, food := range b.Food { if food.X == p.X && food.Y == p.Y { @@ -184,20 +186,27 @@ func PlaceFoodFixed(b *BoardState) error { continue } - // Food must be away from center on at least one axis - isFarFromCenter := false + // Food must be further than snake from center on at least one axis + isAwayFromCenter := false if p.X < snakeHead.X && snakeHead.X < centerCoord.X { - isFarFromCenter = true + isAwayFromCenter = true } else if centerCoord.X < snakeHead.X && snakeHead.X < p.X { - isFarFromCenter = true + isAwayFromCenter = true } else if p.Y < snakeHead.Y && snakeHead.Y < centerCoord.Y { - isFarFromCenter = true + isAwayFromCenter = true } else if centerCoord.Y < snakeHead.Y && snakeHead.Y < p.Y { - isFarFromCenter = true + isAwayFromCenter = true } - if isFarFromCenter { - availableFoodLocations = append(availableFoodLocations, p) + if !isAwayFromCenter { + continue } + + // Don't spawn food in corners + if (p.X == 0 || p.X == (b.Width-1)) && (p.Y == 0 || p.Y == (b.Height-1)) { + continue + } + + availableFoodLocations = append(availableFoodLocations, p) } if len(availableFoodLocations) <= 0 { diff --git a/board_test.go b/board_test.go index feec3e1..9e58536 100644 --- a/board_test.go +++ b/board_test.go @@ -461,8 +461,8 @@ func TestPlaceFoodFixedNoRoom_Corners(t *testing.T) { Food: []Point{}, } - // There are only three possible spawn locations for each snake, - // so repeat calls to place food should fail after 3 successes + // There are only two possible food spawn locations for each snake, + // so repeat calls to place food should fail after 2 successes err := PlaceFoodFixed(boardState) require.NoError(t, err) boardState.Food = boardState.Food[:len(boardState.Food)-1] // Center food @@ -473,20 +473,15 @@ func TestPlaceFoodFixedNoRoom_Corners(t *testing.T) { boardState.Food = boardState.Food[:len(boardState.Food)-1] // Center food require.Equal(t, 8, len(boardState.Food)) - err = PlaceFoodFixed(boardState) - require.NoError(t, err) - boardState.Food = boardState.Food[:len(boardState.Food)-1] // Center food - require.Equal(t, 12, len(boardState.Food)) - // And now there should be no more room. err = PlaceFoodFixed(boardState) require.Error(t, err) expectedFood := []Point{ - {0, 0}, {0, 2}, {2, 0}, // Snake @ {1, 1} - {0, 4}, {0, 6}, {2, 6}, // Snake @ {1, 5} - {4, 0}, {6, 0}, {6, 2}, // Snake @ {5, 1} - {4, 6}, {6, 4}, {6, 6}, // Snake @ {5, 5} + {0, 2}, {2, 0}, // Snake @ {1, 1} + {0, 4}, {2, 6}, // Snake @ {1, 5} + {4, 0}, {6, 2}, // Snake @ {5, 1} + {4, 6}, {6, 4}, // Snake @ {5, 5} } sortPoints(expectedFood) sortPoints(boardState.Food)