diff --git a/lib/goby/entity/entity.rb b/lib/goby/entity/entity.rb index 9c37f57..4d1b3c1 100644 --- a/lib/goby/entity/entity.rb +++ b/lib/goby/entity/entity.rb @@ -13,13 +13,18 @@ class Entity # @param [String] name the name. # @param [Hash] stats hash of stats + # @option stats [Integer] :max_hp maximum health points. Set to be positive. + # @option stats [Integer] :hp current health points. Set to be nonnegative. + # @option stats [Integer] :attack strength in battle. Set to be positive. + # @option stats [Integer] :defense protection from attacks. Set to be positive. + # @option stats [Integer] :agility speed of commands in battle. Set to be positive. # @param [[Couple(Item, Integer)]] inventory a list of pairs of items and their respective amounts. # @param [Integer] gold the currency used for economical transactions. # @param [[BattleCommand]] battle_commands the commands that can be used in battle. # @param [Hash] outfit the collection of equippable items currently worn. def initialize(name: "Entity", stats: {}, inventory: [], gold: 0, battle_commands: [], outfit: {}) @name = name - @stats = set_stats(stats) + set_stats(stats) @inventory = inventory set_gold(gold) @@ -266,6 +271,43 @@ def set_gold(gold) check_and_set_gold end + # Sets stats + # + # @param [Hash] passed_in_stats value pairs of stats + # @option passed_in_stats [Integer] :max_hp maximum health points. Set to be positive. + # @option passed_in_stats [Integer] :hp current health points. Set to be nonnegative. + # @option passed_in_stats [Integer] :attack strength in battle. Set to be positive. + # @option passed_in_stats [Integer] :defense protection from attacks. Set to be positive. + # @option passed_in_stats [Integer] :agility speed of commands in battle. Set to be positive. + def set_stats(passed_in_stats) + current_stats = @stats || { max_hp: 1, hp: nil, attack: 1, defense: 1, agility: 1 } + constructed_stats = current_stats.merge(passed_in_stats) + + # Set hp to max_hp if hp not specified + constructed_stats[:hp] = constructed_stats[:hp] || constructed_stats[:max_hp] + # hp should not be greater than max_hp + constructed_stats[:hp] = [constructed_stats[:hp], constructed_stats[:max_hp]].min + #ensure hp is at least 0 + constructed_stats[:hp] = constructed_stats[:hp] > 0 ? constructed_stats[:hp] : 0 + #ensure all other stats > 0 + constructed_stats.each do |key,value| + if [:max_hp, :attack, :defense, :agility].include?(key) + constructed_stats[key] = value.nonpositive? ? 1 : value + end + end + + @stats = constructed_stats + end + + # getter for stats + # + # @return [Object] + def stats + # attr_reader makes sure stats cannot be set via stats= + # freeze makes sure that stats []= cannot be used + @stats.freeze + end + # Unequips the specified item from the entity's outfit. # # @param [Item, String] item the item (or its name) to unequip. @@ -302,38 +344,6 @@ def ==(rhs) @name == rhs.name end - # Sets stats - # - # @param [Hash] passed_in_stats value pairs of stats - def set_stats(passed_in_stats) - current_stats = @stats || { max_hp: 1, hp: nil, attack: 1, defense: 1, agility: 1 } - constructed_stats = current_stats.merge(passed_in_stats) - - # Set hp to max_hp if hp not specified - constructed_stats[:hp] = constructed_stats[:hp] || constructed_stats[:max_hp] - # hp should not be greater than max_hp - constructed_stats[:hp] = [constructed_stats[:hp], constructed_stats[:max_hp]].min - #ensure hp is at least 0 - constructed_stats[:hp] = constructed_stats[:hp] > 0 ? constructed_stats[:hp] : 0 - #ensure all other stats > 0 - constructed_stats.each do |key,value| - if [:max_hp, :attack, :defense, :agility].include?(key) - constructed_stats[key] = value.negative? ? 1 : value - end - end - - @stats = constructed_stats - end - - # getter for stats - # - # @return [Object] - def stats - # attr_reader makes sure stats cannot be set via stats= - # freeze makes sure that stats []= cannot be used - @stats.freeze - end - attr_accessor :name attr_accessor :inventory diff --git a/lib/goby/item/equippable.rb b/lib/goby/item/equippable.rb index fbae7e3..8dda44f 100644 --- a/lib/goby/item/equippable.rb +++ b/lib/goby/item/equippable.rb @@ -25,12 +25,8 @@ def type def alter_stats(entity, equipping) stats_to_change = entity.stats.dup affected_stats = [:attack, :defense, :agility, :max_hp] - if equipping - operator = :+ - else - operator = :- - end + operator = equipping ? :+ : :- affected_stats.each do |stat| stats_to_change[stat]= stats_to_change[stat].send(operator, stat_change[stat]) if stat_change[stat] end diff --git a/spec/goby/entity/entity_spec.rb b/spec/goby/entity/entity_spec.rb index 09b7f0f..d66a43c 100644 --- a/spec/goby/entity/entity_spec.rb +++ b/spec/goby/entity/entity_spec.rb @@ -617,12 +617,12 @@ end it "only changes specified stats" do - entity = Entity.new(stats: { max_hp: 2, hp: 2, attack: 1, defense: 4, agility: 4 }) + entity = Entity.new(stats: { max_hp: 4, hp: 2, attack: 1, defense: 4, agility: 4 }) - entity.set_stats({ attack: 2 }) + entity.set_stats({ max_hp: 3, attack: 2 }) stats = entity.stats - expect(stats[:max_hp]).to eq 2 + expect(stats[:max_hp]).to eq 3 expect(stats[:hp]).to eq 2 expect(stats[:attack]).to eq 2 expect(stats[:defense]).to eq 4 @@ -650,9 +650,9 @@ end it "non hp values cannot go below 1" do - entity = Entity.new(stats: { max_hp: 2, attack: 1, defense: 1, agility: 1 }) + entity = Entity.new(stats: { max_hp: 2, attack: 3, defense: 2, agility: 3 }) - entity.set_stats({ max_hp: -1, hp: -1, attack: -1, defense: -1, agility: -1 }) + entity.set_stats({ max_hp: 0, attack: 0, defense: 0, agility: 0 }) stats = entity.stats expect(stats[:max_hp]).to eq 1