-
Notifications
You must be signed in to change notification settings - Fork 838
k776's Beginner Code
Daniel Hug edited this page Apr 8, 2015
·
2 revisions
class Player
DEBUG = false
LONG_RANGE_ENEMIES = %{ a w } # the map chars for long range enemies
MAX_HEALTH = 20
LOW_HEALTH = 5
def play_turn(warrior)
@warrior = warrior
@health ||= warrior_health
@walk_direction ||= :forward
@retreating ||= false
# bunch of actions
retreating || rest || shoot || attack || rescue_captive || turn_around || walk
@health = warrior_health
end
private
# Check if warrior can respond to various methods
# (adds clutter, but allows this script to run 1-9 seperatly and in epic mode)
def warrior_can?(method)
@warrior.respond_to?(method)
end
# What is the warriors current health?
# Rescue the method and return max health incase health is not available
def warrior_health
warrior_can?(:health) ? @warrior.health : MAX_HEALTH
end
# Have we lost health since last turn?
# Compare the current health with the health at the end of last turn
# If current health is lower, we know we've taken some damage
def lost_health_since_last_turn?
lost_health = (warrior_health < @health)
puts "Player has lost health since the last turn." if lost_health && DEBUG
lost_health
end
def each_direction(&block)
[:forward, :backward, :left, :right].each do |dir|
yield(dir)
end
end
#
# Level methods
# Various methods for checking objects and such in our path
#
def objects_in_direction(direction)
warrior_can?(:look) <br> ? @warrior.look(direction).select { |o| !o.empty? } <br> : Array.new
end
def first_object_in_direction_long_range_enemy?(direction)
objects_in_direction(direction).first &&
objects_in_direction(direction).first.enemy? &&
LONG_RANGE_ENEMIES.include?(objects_in_direction(direction).first.to_map)
end
def within_distance_of_long_range_enemy?
each_direction do |dir|
return true if first_object_in_direction_long_range_enemy?(dir)
end
false
end
# is the first object in our walking path the stairs? (can we see it?)
# not always correct (since we can only see three spaces ahead)
def can_see_stairs?
return false unless warrior_can?(:look)
@warrior.look(@walk_direction).each do |space|
if !space.empty? && !space.captive?
puts "Player can't see stairs, enemy in direction: #{@walk_direction}" if DEBUG
return false
end
if space.stairs?
puts "Player can see stairs from current location in direction: #{@walk_direction}" if DEBUG
return true
end
end
false
end
def only_wall_in_walk_direction?
only_walls = objects_in_direction(@walk_direction).first &&
objects_in_direction(@walk_direction).first.wall?
puts "Only walls in direction: #{@walk_direction}" if only_walls && DEBUG
only_walls
end
# are we ok to heal? to find out, we have to have less than perfect health,
# have not been attacked since last turn, not within distance of a long
# range fighter, and not heading directly into stairs (the last one helps
# boost points scored in the level)
def is_ok_to_rest?
warrior_health < MAX_HEALTH &&
!lost_health_since_last_turn? &&
!within_distance_of_long_range_enemy? &&
!can_see_stairs?
end
#
# Actions
# Return true if the player has moved (bang methods)
# Return false if the player has not moved
#
def retreating
if @retreating && !lost_health_since_last_turn?
puts "Have not been attacked so can stop retreating." if DEBUG
@retreating = false
return turn_around(true) if only_wall_in_walk_direction?
elsif lost_health_since_last_turn? && warrior_health <= LOW_HEALTH
puts "Health is low and still being attacked. Turning around and retreating." if DEBUG
result = turn_around(true)
@retreating = true
return result # turn_around returns a boolean
end
false
end
def rest
return false unless warrior_can?(:rest!)
if is_ok_to_rest?
puts "Haven't been hurt since last turn, and not within reach of attacker, so healing." if DEBUG
@warrior.rest!
return true
end
false
end
def shoot
return false unless warrior_can?(:shoot!)
each_direction do |dir|
if first_object_in_direction_long_range_enemy?(dir)
puts "Shooting enemy in direction: #{dir.to_s}" if DEBUG
@warrior.shoot!(dir)
return true
end
end
false
end
def attack
return false unless warrior_can?(:attack!)
each_direction do |dir|
if @warrior.feel(dir).enemy?
puts "Attacking enemy in direction: #{dir.to_s}" if DEBUG
@warrior.attack!(dir)
return true
end
end
false
end
def rescue_captive
return false unless warrior_can?(:rescue!)
each_direction do |dir|
if @warrior.feel(dir).captive?
puts "Rescuing captive in direction: #{dir.to_s}" if DEBUG
@warrior.rescue!(dir)
return true
end
end
false
end
def turn_around(quick_turn=false)
return false unless warrior_can?(:feel)
if @retreating
puts "Player already retreating so not turning around." if DEBUG
return false
end
reverse_dirs = {
:forward => :backward,
:backward => :forward,
:left => :right,
:right => :left
}
direction = reverse_dirs[@walk_direction]
if quick_turn # won't pivot
puts "Walking direction to direction: #{direction.to_s}" if DEBUG
@walk_direction = direction
elsif @warrior.feel(@walk_direction).wall?
puts "Pivoting direction to direction: #{direction.to_s}" if DEBUG
@walk_direction = direction
@warrior.pivot!(direction) if warrior_can?(:pivot!)
return true
end
false
end
def walk
if !warrior_can?(:feel) || @warrior.feel(@walk_direction).empty?
puts "Walking to empty space in direction: #{@walk_direction.to_s}" if DEBUG
@warrior.walk!(@walk_direction)
end
end
end