Last active
December 20, 2015 10:09
-
-
Save quimcalpe/6113558 to your computer and use it in GitHub Desktop.
RubyWarrior intermediate epic mode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
# 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