Skip to content

dannyfreeman's intermediate code

dannyfreeman edited this page May 17, 2014 · 1 revision
class Player
  DIRECTIONS = [:forward, :backward, :left, :right,]
  MAX_HEALTH = 20

  def play_turn(warrior)
    @warrior = warrior
    @units_array = warrior.listen
    @units_in_front = warrior.look

    @units_array.each do |unit|
      if (unit.ticking?)
        @min_health = 13
        break
      elsif @units_array.length < 2
        @min_health = 15
        break
      else
        @min_health = MAX_HEALTH
      end
    end

    if @units_array.any?
      # only do these actions if there are units still in the dungeon
      if rest
      elsif move_to_ticking
      elsif bind_enemy
      elsif throw_bomb
      elsif exterminate
      elsif rescuce_captive
      elsif avoid_stairs
      else
        go_to_next_unit
      end
    else 
      to_victory!
    end
    record_health
  end # play_turn

  def rest
    if need_to_rest?
      puts "Low on health"
      if safe_to_rest?
        puts "No enemies to worry about"
        @warrior.rest!
      else
        feel_for_empty
        @warrior.walk! (@direction)
        puts "retreat!"
      end
      return true
    end
    return false
  end

  def move_to_ticking
    @units_array.each do |space|
      if (space.ticking?)
        @direction = @warrior.direction_of(space)
        if (next_space.captive? and next_space.ticking?)
          if next_space.character.eql?("C") # ain't got time to recuse those slime guys!
            puts "Time to diffuse this bomb"
            @warrior.rescue!(@direction)
            return true
          end
        elsif next_space.empty? #and not next_space.stairs?)
          puts "Walking towards ticking captive"
          @warrior.walk!(@direction)
          return true
        else
          return false
          # space is occupied by another unit, let the next function handle it
        end
      end
    end
    return false
  end

  def throw_bomb
    if safe_to_detonate?
      if current_health < 5
        @warrior.rest!
      elsif (@units_in_front[0].enemy? and @units_in_front[1].enemy?) or good_time_to_bomb?
        puts "EXTERMINATE!"
        @warrior.detonate!
      else
        return false
      end
      return true
    end
    return false
  end

  def bind_enemy
    if feel_for_enemy
      if @enemy_count >= 2
        @warrior.bind! @direction
        return true
      end
    end
    return false
  end

  def exterminate
    if feel_for_enemy
      unless next_space.eql? "C"
        puts "EXTERMINATE!"
        @warrior.attack! @direction
      end
      return true
    end
    return false
  end

  def rescuce_captive
    if feel_for_captive
      #@warrior.rescue! @direction
      #return true
      if (@warrior.feel(@direction).captive? and @warrior.feel(@direction).unit.character == "C")
        @warrior.rescue! @direction
        return true
      else #unit is captive enemy
        puts "Exterminate captive enemy"
        @warrior.attack! @direction
        return true
      end
    end
    return false
  end
  
  def avoid_stairs
    if feel_for_stairs
      @warrior.walk! @direction
      puts "avoiding stairs"
      return true
    end
    return false
  end

  def go_to_next_unit
    if feel_for_empty
      puts "Going to next unit"
      direction_of_next_unit = @warrior.direction_of(@units_array[0])
      if @warrior.feel(direction_of_next_unit).stairs?
        DIRECTIONS.each do |direction|
          if direction != direction_of_next_unit
            @direction = direction if @warrior.feel(direction).empty?
          end
        end
        @warrior.walk!(@direction) 
      else
        @warrior.walk!(direction_of_next_unit)
      end
      return true
    end
    return false
  end

  def to_victory!
    @warrior.walk! @warrior.direction_of_stairs
    puts "To Victory!"
  end

  def next_space
    @warrior.feel(@direction)
  end

  def feel_for_captive_enemy
    DIRECTIONS.each do |direction|
      if @warrior.feel(direction).captive?
      end
    end
  end
    
  def feel_for_enemy
    @enemy_count = 0
    DIRECTIONS.each do |direction|
      if @warrior.feel(direction).enemy?
        @direction = direction
        @enemy_count += 1
      end
    end
    return true if @enemy_count >= 1
    return false if @enemy_count == 0
  end

  def feel_for_captive
    DIRECTIONS.each do |direction|
      if @warrior.feel(direction).captive?
        @direction = direction
        return true
      end
    end
    return false
  end

  def feel_for_empty
    DIRECTIONS.each do |direction|
      if @warrior.feel(direction).empty?
        @direction = direction
        return true
      end
    end
    return false
  end

  def feel_for_stairs
    DIRECTIONS.each do |direction|
      if (@warrior.look(direction)[0].stairs? or @warrior.look(direction)[1].stairs?)
        DIRECTIONS.each do |other_direction|
          if other_direction != direction
            # don't check the direction stairs are in
            # staris unit returns true for .empty?
            @empty_units = 0
            @warrior.look(other_direction).each do |unit|
              if unit.wall? or unit.empty?
                @empty_units += 1
                # Avoid getting stuck in situations like
                # |   s|
                # |  @>|
                #  ----
                # where warrior would keep walking backwards
                # to avoid stairs, and then forwards to get
                # to enemy. Forces warrior up into open area
              end
            end
            unless @empty_units == 3
              @direction = other_direction
              return true
            end
          end
        end
      else #don't feel stairs
        return false
      end
    end
  end

  def enemies_to_murder
    enemies = 0
    @units_array.each do |unit|
      enemies += 1 if unit.enemy?
    end
    return enemies
  end

  def good_time_to_bomb?
    nearby_enemy = 0
    @units_array.each do |unit|
      if unit.enemy?
        nearby_enemy += 1 if @warrior.distance_of(unit) < 2
      end
    end
    return true if nearby_enemy >= 2
    return false
  end

  def safe_to_detonate?
    @units_array.each do |unit|
      # it's okay to blow up captive enemies
      if (unit.captive? and unit.character == "C")
        if @warrior.distance_of(unit) < 3
          return false
        end
      end
    end
    return true
  end

  def taking_damage?
    return false if @previous_health.nil? or @previous_health == current_health
    return true if @previous_health > current_health
  end

  def need_to_rest?
    if enemies_to_murder > 0
      return true if resting_not_complete? or current_health < 5
    else
      return false
    end
  end

  def safe_to_rest?
    true unless feel_for_enemy or taking_damage?
  end

  def resting_not_complete?
    current_health < @min_health and current_health > @previous_health
  end

  def record_health
    unless @previous_health
      @previous_health = MAX_HEALTH
    end
    @previous_health = current_health
  end

  def current_health
    @warrior.health
  end
end # Player