Skip to content

Commit

Permalink
flood_fill use enhanced/fixed (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
fdocr authored Sep 27, 2023
1 parent a994c66 commit 38ddcec
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 22 deletions.
8 changes: 5 additions & 3 deletions src/battle_snake/context.cr
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,14 @@ class BattleSnake::Context
}
end

# Simulate a move of a snake by id in some direction
def move(snake_id, direction)
# Simulate a move of a snake by id in some `direction`. Optional param
# `pop_body` that defaults as `true`. If false it won't pop the body
# of the snake being moved (sometimes snakes may have been popped already)
def move(snake_id, direction, pop_body = true)
index = board.snakes.index! { |snake| snake.id == snake_id }

# delete last body point
deleted_point = board.snakes[index].body.pop
deleted_point = board.snakes[index].body.pop if pop_body

# Move head
board.snakes[index].head = board.snakes[index].head.move(direction)
Expand Down
42 changes: 23 additions & 19 deletions src/strategy/cautious_carol.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
# most open area of the board to avoid enclosed spaces.
class Strategy::CautiousCarol < Strategy::Base
def move
@context.board.snakes.each { |snake| snake.body.pop }
valid_moves = @context.valid_moves(@context.you.head)
return RandomValid.new(@context).move if valid_moves[:moves].empty?

# Check for head-to-head collision possibilities
dangerous_moves = [] of BattleSnake::Point
enemies = @context.board.snakes.reject { |s| s.id == @context.you.id }
enemies.each do |snake|
next if snake.head <=> @context.you.head > 2
@context.enemies.each do |snake|
next if (snake.head <=> @context.you.head) > 2
next if snake.body.size < @context.you.body.size

# Check if we share valid moves (meeting point for collision)
Expand All @@ -24,29 +24,33 @@ class Strategy::CautiousCarol < Strategy::Base
end
end

# Attempt to chase closest food unless dangerous move is detected
# Calculate chase closest food direction
closest_food = ChaseClosestFood.new(@context).move
target_point = @context.you.head.move(closest_food)
safe_move = dangerous_moves.find { |p| (p <=> target_point).zero? }.nil?
return closest_food if safe_move
closest_food_area = 0

# Leftover valid moves (not chasing closest food anymore) & fallback to
# RandomValid if no other moves are available (likely run into own death)
safe_moves = valid_moves[:moves].reject { |move| move == closest_food }
return RandomValid.new(@context).move if safe_moves.size.zero?

# Use flood fill to pick the valid move with more space to spare as an
# Use flood fill to check the available space to move for valid_moves and
# attempt to avoid small areas
flood_fills = {} of Int32 => String
contexts = [] of BattleSnake::Context
safe_moves.size.times { contexts << @context.dup }
safe_moves.each_with_index do |move, i|
contexts[i].move(@context.you.id, move)
area_size = Utils.flood_fill(@context.you.head, contexts[i]).size
contexts = {} of String => BattleSnake::Context
valid_moves[:moves].each do |move|
contexts[move] = @context.dup
contexts[move].move(@context.you.id, move, false)
area_size = Utils.flood_fill(contexts[move].you.head, contexts[move]).size
flood_fills[area_size] = move
closest_food_area = area_size if move == closest_food
end

# Pick the direction with the largest available area
flood_fills[flood_fills.keys.sort.last]
# Safe move if not considered dangerous (collision) or too small space
safe_move = dangerous_moves.find { |p| (p <=> target_point).zero? }.nil?
safe_area = closest_food_area >= @context.you.body.size
return closest_food if safe_move && safe_area

# Leftover valid moves (not chasing closest food anymore) & fallback to
# RandomValid if no other moves are available (likely run into own death)
return flood_fills[flood_fills.keys.sort.last] if flood_fills.keys.size > 0

# Fallback to RandomValid (likely run into own death)
RandomValid.new(@context).move
end
end

0 comments on commit 38ddcec

Please sign in to comment.