Skip to content

Instantly share code, notes, and snippets.

@quimcalpe
Last active December 20, 2015 10:09
Show Gist options
  • Save quimcalpe/6113558 to your computer and use it in GitHub Desktop.
Save quimcalpe/6113558 to your computer and use it in GitHub Desktop.
RubyWarrior intermediate epic mode
##
# No custom level tricks
#
# Total Score: 804 + 181 = 985
# Your average grade for this tower is: S
#
# Level 1: S
# Level 2: A
# Level 3: S
# Level 4: S
# Level 5: S
# Level 6: S
# Level 7: S
class Player
def initialize
# init vars
@max_health = 20
@last_health = @max_health
@optimal_health = 10
@panic_health = 5
end
def play_turn(warrior)
# check surroundings
spy = look_around(warrior)
#debug
puts "Current health: #{warrior.health}, Optimal health: #{@optimal_health}, Enemies: #{enemies_left(warrior).length}"
# main decision tree, ordered by priority
if spy[:bomb]
warrior.rescue! spy[:direction]
elsif bombs_left?(warrior) && bombs_reachable?(warrior) && warrior.health > @panic_health
route = find_route(warrior, bombs_left(warrior)[0])
warrior.walk! route
elsif spy[:action] == :detonate
warrior.detonate! spy[:direction]
elsif spy[:action] == :bind
warrior.bind! spy[:direction]
elsif spy[:action] == :attack
warrior.attack! spy[:direction]
elsif spy[:action] == :rescue
warrior.rescue! spy[:direction]
elsif warrior.health < @optimal_health && enemies_left?(warrior)
warrior.rest!
elsif enemies_left?(warrior)
entity = closer_enemy(warrior)
warrior.walk! find_route(warrior, entity)
elsif captives_left?(warrior)
entity = closer_captive(warrior)
warrior.walk! find_route(warrior, entity)
else
warrior.walk! spy[:direction]
end
# save health to check if we are under attack
@last_health = warrior.health
end
def captives_left(warrior)
return warrior.listen.select{ |cell| cell.unit.character=="C" }
end
def captives_left?(warrior)
return captives_left(warrior).length > 0
end
def closer_captive(warrior)
closer = nil
captives_left(warrior).each do |captive|
if !closer || warrior.distance_of(closer) > warrior.distance_of(captive)
closer = captive
end
end
return closer
end
def enemies_left(warrior)
return warrior.listen.select{ |cell| cell.unit.character!="C" }
end
def enemies_left?(warrior)
return enemies_left(warrior).length > 0
end
def closer_enemy(warrior)
closer = nil
enemies_left(warrior).each do |enemy|
if !closer || warrior.distance_of(closer) > warrior.distance_of(enemy)
closer = enemy
end
end
return closer
end
def bombs_left(warrior)
return warrior.listen.select{ |cell| cell.ticking? }
end
def bombs_left?(warrior)
return bombs_left(warrior).length > 0
end
def update_optimal_health(warrior)
optimal = 1
enemies_left(warrior).each do |enemy|
optimal += enemy_threat(enemy)
end
optimal = @max_health if optimal > @max_health
@optimal_health = optimal
end
def enemy_threat(enemy)
threat = {
"Thick Sludge" => 12,
"Sludge" => 9
}
return threat[enemy.to_s]
end
def reverse_route(direction)
return :forward if direction==:backward
return :backward if direction==:forward
return :left if direction==:right
return :right if direction==:left
raise "Unable to find reverse of #{direction}"
end
def find_route(warrior, entity)
direction = warrior.direction_of(entity)
if warrior.feel(direction).empty? && !warrior.feel(direction).stairs?
return direction
else
[:forward, :left, :right, :backward].each do |dir|
return dir if warrior.feel(dir).empty? && !warrior.feel(dir).stairs? && dir!=reverse_route(direction)
end
end
return nil
end
def bombs_reachable?(warrior)
reachable = false
bombs_left(warrior).each do |bomb|
reachable = find_route(warrior, bomb) != nil
end
return reachable
end
def look_around(warrior)
update_optimal_health(warrior)
# search enemies next to me
close_enemies = 0
enemy_direction = :forward
[:forward, :backward, :left, :right].each do |direction|
if warrior.feel(direction).enemy?
close_enemies+=1
enemy_direction = direction
end
end
return {:action=>:bind, :direction=>enemy_direction, :bomb=>false} if close_enemies>1
# detonation chance?
if warrior.health >= @panic_health
[:forward, :left, :right, :backward].each do |direction|
enemies = 0
[0, 1, 2].each do |step|
cell = warrior.look(direction)[step]
# real enemies
if cell.enemy? || (cell.captive? && cell.character != "C")
enemies += 1
end
# discard if captive in range
enemies = -10 if cell.character == "C"
end
if enemies > 1 || warrior.look(direction)[1].enemy?
return {:action=>:detonate, :direction=>direction, :bomb=>false}
end
end
end
# scan near first
[0, 1, 2].each do |step|
[:forward, :left, :right, :backward].each do |direction|
cell = warrior.look(direction)[step]
if cell.ticking?
step == 0 ? action = :rescue : action = :walk
return {:action=>action, :direction=>direction, :bomb=>(step==0)}
end
if cell.enemy?
step == 0 ? action = :attack : action = :walk
return {:action=>action, :direction=>direction, :bomb=>false}
end
if cell.character == "C"
step == 0 ? action = :rescue : action = :walk
return {:action=>action, :direction=>direction, :bomb=>false}
end
if cell.captive? && cell.character != "C" && warrior.health >= @optimal_health
step == 0 ? action = :attack : action = :walk
return {:action=>action, :direction=>direction, :bomb=>false}
end
end
end
# nothing close
return {:action=>:walk, :direction=>warrior.direction_of_stairs, :bomb=>false}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment