Skip to content

Instantly share code, notes, and snippets.

@kmayer
Created August 25, 2013 18:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kmayer/6335552 to your computer and use it in GitHub Desktop.
Save kmayer/6335552 to your computer and use it in GitHub Desktop.
RubyWarrior beginner Total Score: 525 + 101 = 626 Your average grade for this tower is: S Level 1: S Level 2: A Level 3: S Level 4: S Level 5: A Level 6: S Level 7: S Level 8: S Level 9: S
module Heuristics
TARGET_PRIORITY = {
RubyWarrior::Units::Archer => 1,
RubyWarrior::Units::Wizard => 2,
RubyWarrior::Units::ThickSludge => 3,
RubyWarrior::Units::Sludge => 4,
RubyWarrior::Units::Captive => 999,
RubyWarrior::Units::Warrior => 999,
}
def targets(targeter)
[:forward, :backward].map{ |direction| self.send(targeter, direction) }.compact.sort_by{|target| priority(target)}
end
def priority(target)
TARGET_PRIORITY.detect(->{[RubyWarrior::Units::Base, 9]}) {|enemy, _| target.unit.is_a?(enemy)}[1]
end
def sick?
warrior.health < 8
end
def attacked?
warrior.health < health
end
def should_rest?
warrior.health < 20 && ((look(:forward) && look(:forward).enemy?) || (look(:backward) && look(:backward).enemy?))
end
def safe_to_rest?
!ahead.enemy? && !behind.enemy?
end
def safe_to_retreat?(direction)
return false if !warrior.feel(direction).empty?
return false if look(direction) && look(direction).enemy?
distance_to_enemy = warrior.look(opposite(direction)).find_index{|space| space.enemy? }
return true if distance_to_enemy.nil?
farthest_safe_space = 3 - warrior.look(direction).reverse.find_index{|space| space.empty? }
distance_to_enemy + farthest_safe_space > 2
end
end
require "sensing"
require "heuristics"
class Player
attr_reader :warrior, :health
include Sensing
include Heuristics
def initialize
@health = 20
end
def play_turn(warrior)
@warrior = warrior
tactics.detect { |action| try(action) }
@health = warrior.health
end
private
def tactics
[:retreat, :attack, :shoot, :reengage, :search_and_rescue, :rest, :pivot, :walk]
end
def try(action)
self.send(action) && log(action)
end
def log(action)
$stdout.puts "ACTION => #{action}"
true
end
def retreat
retreat_to(:backward) || retreat_to(:forward)
end
def retreat_to(direction)
warrior.walk!(direction) if attacked? && sick? && safe_to_retreat?(direction)
end
def shoot
target = targets(:target_toward).first
return warrior.shoot!(target.direction) if target
end
def reengage
warrior.walk!(:forward) if attacked? && ahead.empty?
end
def search_and_rescue
rescue_captive(:forward) || rescue_captive(:backward) || search_for_captive(:backward)
end
def rescue_captive(direction)
warrior.rescue!(direction) if warrior.feel(direction).captive?
end
def search_for_captive(direction)
warrior.walk!(direction) if look(direction) && look(direction).captive?
end
def rest
warrior.rest! if ((should_rest? || sick?) && safe_to_rest?)
end
def attack
target = targets(:target_at).first
warrior.attack!(target.direction) if target
end
def pivot
warrior.pivot!(:backward) if ahead.wall?
end
def walk
warrior.walk!(:forward)
end
end
module Sensing
Target = Struct.new(:unit, :direction)
def look(direction)
warrior.look(direction).detect{|space| !space.empty?}
end
def target_toward(direction)
lookyloo = look(direction)
Target.new(lookyloo.unit, direction) if lookyloo && lookyloo.enemy?
end
def target_at(direction)
unit = warrior.feel(direction)
Target.new(unit, direction) if unit.enemy?
end
def ahead
warrior.feel(:forward)
end
def behind
warrior.feel(:backward)
end
def opposite(direction)
{:forward => :backward, :backward => :forward}[direction]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment