| 
 | 1 | +# The guts of life force within Dwemthy's Array  | 
 | 2 | +class Creature  | 
 | 3 | + | 
 | 4 | +  # Get a metaclass for this class  | 
 | 5 | +  def self.metaclass; class << self; self; end; end  | 
 | 6 | + | 
 | 7 | +  # Advanced metaprogramming code for nice, clean traits  | 
 | 8 | +  def self.traits( *arr )  | 
 | 9 | +    return @traits if arr.empty?  | 
 | 10 | + | 
 | 11 | +    # 1. Set up accessors for each variable  | 
 | 12 | +    attr_accessor *arr  | 
 | 13 | + | 
 | 14 | +    # 2. Add a new class method to for each trait.  | 
 | 15 | +    arr.each do |a|  | 
 | 16 | +      metaclass.instance_eval do  | 
 | 17 | +        define_method( a ) do |val|  | 
 | 18 | +          @traits ||= {}  | 
 | 19 | +          @traits[a] = val  | 
 | 20 | +        end  | 
 | 21 | +      end  | 
 | 22 | +    end  | 
 | 23 | + | 
 | 24 | +    # 3. For each monster, the `initialize' method  | 
 | 25 | +    #    should use the default number for each trait.  | 
 | 26 | +    class_eval do  | 
 | 27 | +      define_method( :initialize ) do  | 
 | 28 | +        self.class.traits.each do |k,v|  | 
 | 29 | +          instance_variable_set("@#{k}", v)  | 
 | 30 | +        end  | 
 | 31 | +      end  | 
 | 32 | +    end  | 
 | 33 | + | 
 | 34 | +  end  | 
 | 35 | + | 
 | 36 | +  # Creature attributes are read-only  | 
 | 37 | +  traits :life, :strength, :charisma, :weapon  | 
 | 38 | + | 
 | 39 | +  # This method applies a hit taken during a fight.  | 
 | 40 | +  def hit( damage )  | 
 | 41 | +    p_up = rand( charisma )  | 
 | 42 | +    if p_up % 9 == 7  | 
 | 43 | +      @life += p_up / 4  | 
 | 44 | +      puts "[#{ self.class } magick powers up #{ p_up }!]"  | 
 | 45 | +    end   | 
 | 46 | +    @life -= damage  | 
 | 47 | +    puts "[#{ self.class } has died.]" if @life <= 0  | 
 | 48 | +  end  | 
 | 49 | + | 
 | 50 | +  # This method takes one turn in a fight.  | 
 | 51 | +  def fight( enemy, weapon )  | 
 | 52 | +    if life <= 0  | 
 | 53 | +      puts "[#{ self.class } is too dead to fight!]"  | 
 | 54 | +      return  | 
 | 55 | +    end  | 
 | 56 | + | 
 | 57 | +    # Attack the opponent  | 
 | 58 | +    your_hit = rand( strength + weapon )  | 
 | 59 | +    puts "[You hit with #{ your_hit } points of damage!]"  | 
 | 60 | +    enemy.hit( your_hit )  | 
 | 61 | + | 
 | 62 | +    # Retaliation  | 
 | 63 | +    puts '#'  # replaced by ashbb: p enemy  | 
 | 64 | +    if enemy.life > 0  | 
 | 65 | +      enemy_hit = rand( enemy.strength + enemy.weapon )  | 
 | 66 | +      puts "[Your enemy hit with #{ enemy_hit } points of damage!]"  | 
 | 67 | +      self.hit( enemy_hit )  | 
 | 68 | +    end  | 
 | 69 | +  end  | 
 | 70 | + | 
 | 71 | +end  | 
 | 72 | + | 
 | 73 | +class DwemthysArray < Array  | 
 | 74 | +  alias _inspect inspect  | 
 | 75 | +  def inspect; "#"; end  # replaced by ashbb : def inspect; "#<#{ self.class }#{ _inspect }>"; end  | 
 | 76 | +  def method_missing( meth, *args )  | 
 | 77 | +    return unless first  | 
 | 78 | +    answer = first.send( meth, *args )  | 
 | 79 | +    if first.life <= 0  | 
 | 80 | +      shift  | 
 | 81 | +      if empty?  | 
 | 82 | +        puts "[Whoa.  You decimated Dwemthy's Array!]"  | 
 | 83 | +      else  | 
 | 84 | +        puts "[Get ready. #{ first.class } has emerged.]"  | 
 | 85 | +      end  | 
 | 86 | +    end  | 
 | 87 | +    answer || 0  | 
 | 88 | +  end  | 
 | 89 | +end  | 
0 commit comments