Skip to content

Commit 62bf493

Browse files
committed
Avoid colliding with stronger snakes
1 parent 77dc043 commit 62bf493

File tree

3 files changed

+153
-2
lines changed

3 files changed

+153
-2
lines changed

internal/battle/simple/simple.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,20 @@ func (s *Snake) Move(state internal.GameState) (internal.Action, error) {
4343
// Avoid hazards if possible
4444
avoidHazards := util.AvoidHazards(state.Board, state.You.Head)
4545
avoidHazardsPriorityMap := map[string]int{}
46-
4746
for _, dir := range avoidHazards {
4847
avoidHazardsPriorityMap[dir] = 2
4948
}
5049

50+
// avoid collisions with stronk snakes
51+
avoidCollisions := util.AvoidCollisions(state.You, state.Board.Snakes)
52+
avoidCollisionsPriorityMap := map[string]int{}
53+
for _, dir := range avoidCollisions {
54+
avoidCollisionsPriorityMap[dir] = 3
55+
}
56+
5157
avoidSelfPriorityMap := util.MoveAwayFromSelf(state.You)
5258

53-
return internal.Action{Move: findOptimal(possibleDirections, foodPriorityMap, avoidSelfPriorityMap, avoidHazardsPriorityMap)}, nil
59+
return internal.Action{Move: findOptimal(possibleDirections, foodPriorityMap, avoidSelfPriorityMap, avoidHazardsPriorityMap, avoidCollisionsPriorityMap)}, nil
5460
}
5561

5662
// Info returns the style info for a simple snake

internal/battle/util/util.go

+30
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package util
22

33
import (
4+
"fmt"
45
"math"
56

67
"github.com/bethanyj28/battlesnek/internal"
@@ -105,6 +106,26 @@ func MoveAwayFromSelf(self internal.Battlesnake) map[string]int {
105106
return distMap
106107
}
107108

109+
// AvoidCollisions returns moves that avoid collisions with stronger snakes
110+
func AvoidCollisions(self internal.Battlesnake, others []internal.Battlesnake) []string {
111+
otherPosCoords := []internal.Coord{}
112+
for _, snake := range others {
113+
if snake.ID == self.ID {
114+
continue
115+
}
116+
117+
if snake.Length < self.Length {
118+
continue
119+
}
120+
121+
otherPosCoords = append(otherPosCoords, potentialPositionsSlice(snake.Head)...)
122+
}
123+
124+
fmt.Println(otherPosCoords)
125+
126+
return decideDir(potentialPositions(self.Head), convertCoordsToGrid(otherPosCoords))
127+
}
128+
108129
func averagePositions(coords []internal.Coord) internal.Coord {
109130
sumX := 0
110131
sumY := 0
@@ -142,6 +163,15 @@ func convertCoordsToGrid(coords []internal.Coord) matrix {
142163
return grid
143164
}
144165

166+
func potentialPositionsSlice(head internal.Coord) []internal.Coord {
167+
positions := []internal.Coord{}
168+
for _, pos := range potentialPositions(head) {
169+
positions = append(positions, pos)
170+
}
171+
172+
return positions
173+
}
174+
145175
func decideDir(potential choices, avoid matrix) []string {
146176
options := []string{}
147177

internal/battle/util/util_test.go

+115
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,118 @@ func TestFindFood(t *testing.T) {
213213
})
214214
}
215215
}
216+
217+
// 30 31 32 33 34
218+
// 20 21 22 23 24
219+
// 10 11 12 13 14
220+
// 00 01 02 03 04
221+
222+
func TestAvoidCollisions(t *testing.T) {
223+
type testcase struct {
224+
name string
225+
inputSelf internal.Battlesnake
226+
inputOthers []internal.Battlesnake
227+
expected []string
228+
}
229+
230+
testcases := []testcase{
231+
{
232+
name: "other snake longer",
233+
inputSelf: internal.Battlesnake{
234+
ID: "me",
235+
Head: internal.Coord{X: 0, Y: 1},
236+
Body: []internal.Coord{
237+
{X: 0, Y: 1},
238+
{X: 0, Y: 2},
239+
{X: 0, Y: 3},
240+
},
241+
Length: 3,
242+
},
243+
inputOthers: []internal.Battlesnake{
244+
{
245+
ID: "other1",
246+
Head: internal.Coord{X: 1, Y: 0},
247+
Body: []internal.Coord{
248+
{X: 1, Y: 0},
249+
{X: 2, Y: 0},
250+
{X: 3, Y: 0},
251+
{X: 4, Y: 0},
252+
{X: 5, Y: 0},
253+
},
254+
Length: 5,
255+
},
256+
},
257+
expected: []string{"left", "up"},
258+
},
259+
{
260+
name: "other snake shorter",
261+
inputSelf: internal.Battlesnake{
262+
ID: "me",
263+
Head: internal.Coord{X: 0, Y: 1},
264+
Body: []internal.Coord{
265+
{X: 0, Y: 0},
266+
{X: 0, Y: 1},
267+
{X: 0, Y: 2},
268+
},
269+
Length: 3,
270+
},
271+
inputOthers: []internal.Battlesnake{
272+
{
273+
ID: "other1",
274+
Head: internal.Coord{X: 1, Y: 0},
275+
Body: []internal.Coord{
276+
{X: 1, Y: 0},
277+
{X: 2, Y: 0},
278+
},
279+
Length: 2,
280+
},
281+
},
282+
expected: []string{"down", "left", "right", "up"},
283+
},
284+
{
285+
name: "multiple snakes",
286+
inputSelf: internal.Battlesnake{
287+
ID: "me",
288+
Head: internal.Coord{X: 3, Y: 1},
289+
Body: []internal.Coord{
290+
{X: 3, Y: 3},
291+
{X: 3, Y: 2},
292+
{X: 3, Y: 1},
293+
},
294+
Length: 3,
295+
},
296+
inputOthers: []internal.Battlesnake{
297+
{
298+
ID: "other1",
299+
Head: internal.Coord{X: 2, Y: 0},
300+
Body: []internal.Coord{
301+
{X: 2, Y: 0},
302+
{X: 1, Y: 0},
303+
{X: 0, Y: 0},
304+
},
305+
Length: 3,
306+
},
307+
{
308+
ID: "other2",
309+
Head: internal.Coord{X: 5, Y: 1},
310+
Body: []internal.Coord{
311+
{X: 5, Y: 1},
312+
{X: 6, Y: 1},
313+
{X: 7, Y: 1},
314+
},
315+
Length: 3,
316+
},
317+
},
318+
expected: []string{"up"},
319+
},
320+
}
321+
322+
for _, tc := range testcases {
323+
t.Run(tc.name, func(t *testing.T) {
324+
is := is.New(t)
325+
actual := AvoidCollisions(tc.inputSelf, tc.inputOthers)
326+
sort.Strings(actual)
327+
is.Equal(actual, tc.expected)
328+
})
329+
}
330+
}

0 commit comments

Comments
 (0)