in source/BattlesnakeGym/battlesnake_gym/snake_gym.py [0:0]
def _did_snake_collide(self, snake, snakes_to_be_killed):
'''
Helper function to check if a snake has collided into something else. Checks the following:
1) If the snake's head hit a wall (i.e., if the head is outside of the map)
2) Check if the snake collided with another snake's head (entering the same tile and adjacent)
3) Check if the snake ran into another snake's body (itself and other snakes)
4) Check if the snake's body hit another snake's head
Parameter:
----------
snake: Snake
snakes_to_be_killed: a list of snakes that will be killed in the end of the turn.
Returns:
----------
should_kill_snake: Bool
Boolean to indicate if the snake is dead or not
collision_outcome: options = ["Snake hit wall",
"Snake was eaten - same tile",
"Snake was eaten - adjacent tile",
"Snake hit body - hit itself",
"Snake hit body - hit other",
"Did not collide",
"Ate another snake",
"Other snake hit body"]
'''
snake_head_location = snake.get_head()
ate_another_snake = False
snakes_eaten_this_turn = []
# 1) Check if the snake ran into a wall
outcome = "Snake hit wall"
if snake.is_head_outside_map():
if self.verbose: print(outcome)
should_kill_snake = True
return should_kill_snake, outcome
# 2.1) Check if snake's head collided with another snake's head when they both entered the same tile
# e.g.,:
#
# | |< S1
# ^
# S2
for other_snake in self.snakes.get_snakes():
if other_snake == snake:
continue
if other_snake.is_alive():
other_snake_head = other_snake.get_head()
if np.array_equal(snake_head_location, other_snake_head):
if other_snake.get_size() >= snake.get_size():
outcome = "Snake was eaten - same tile"
if self.verbose: print(outcome)
return True, outcome
else:
ate_another_snake = True
snakes_eaten_this_turn.append(other_snake)
# 2.2) Check if snake's head collided with another snakes head when they were adjacent to one another
# (i.e., that the heads swapped positions)
#
# S1 S1
# | |> <| |
#
for other_snake in self.snakes.get_snakes():
if other_snake == snake:
continue
# Check if snake swapped places with the other_snake.
# 1) check if heads are adjacent
# 2) check if heads swapped places
if other_snake.is_alive():
other_snake_head = other_snake.get_head()
if get_distance(snake_head_location, other_snake_head) == 1:
if np.array_equal(snake_head_location, other_snake.get_previous_snake_head())\
and np.array_equal(other_snake_head, snake.get_previous_snake_head()):
if other_snake.get_size() >= snake.get_size():
outcome = "Snake was eaten - adjacent tile"
if self.verbose: print(outcome)
return True, outcome
else:
ate_another_snake = True
snakes_eaten_this_turn.append(other_snake)
# 3.1) Check if snake ran into it's own body
outcome = "Snake hit body - hit itself"
for self_body_locations in snake.get_body():
if np.array_equal(snake_head_location, self_body_locations):
if self.verbose: print("Snake hit itself")
return True, outcome
# 3.2) Check if snake ran into another snake's body
outcome = "Snake hit body - hit other"
snake_binary_map = self.snakes.get_snake_51_map(excluded_snakes=[snake]+snakes_eaten_this_turn)
if snake_binary_map[snake_head_location[0], snake_head_location[1]] == 1:
if self.verbose: print("Snake hit another snake")
return True, outcome
# 4) Check if another snake ran into this snake
for other_snake in self.snakes.get_snakes():
if other_snake == snake:
continue
if other_snake.is_alive():
if other_snake not in snakes_to_be_killed:
other_snake_head = other_snake.get_head()
for location in snake.get_body():
if np.array_equal(location, other_snake_head):
return False, "Other snake hit body"
if ate_another_snake:
return False, "Ate another snake"
return False, "Did not collide"