Class: Goby::Entity

Inherits:
Object
  • Object
show all
Defined in:
lib/goby/entity/entity.rb

Overview

Provides the ability to fight, equip/unequip weapons & armor, and carry items & gold.

Direct Known Subclasses

Monster, Player

Constant Summary collapse

NO_SUCH_ITEM_ERROR =

Error when the entity specifies a non-existent item.

"What?! You don't have THAT!\n\n"
NOT_EQUIPPED_ERROR =

Error when the entity specifies an item not equipped.

"You are not equipping THAT!\n\n"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name: "Entity", stats: {}, inventory: [], gold: 0, outfit: {}) ⇒ Entity

Returns a new instance of Entity.

Parameters:

  • name (String) (defaults to: "Entity")

    the name.

  • stats (Hash) (defaults to: {})

    hash of stats

  • inventory ([C(Item, Integer)]) (defaults to: [])

    a list of pairs of items and their respective amounts.

  • gold (Integer) (defaults to: 0)

    the currency used for economical transactions.

  • outfit (Hash) (defaults to: {})

    the collection of equippable items currently worn.

Options Hash (stats:):

  • :max_hp (Integer)

    maximum health points. Set to be positive.

  • :hp (Integer)

    current health points. Set to be nonnegative.

  • :attack (Integer)

    strength in battle. Set to be positive.

  • :defense (Integer)

    protection from attacks. Set to be positive.

  • :agility (Integer)

    speed of commands in battle. Set to be positive.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/goby/entity/entity.rb', line 24

def initialize(name: "Entity", stats: {}, inventory: [], gold: 0, outfit: {})
  @name = name
  set_stats(stats)
  @inventory = inventory
  set_gold(gold)

  # See its attr_accessor below.
  @outfit = {}
  outfit.each do |type,value|
    value.equip(self)
  end

  # This should only be switched to true during battle.
  @escaped = false
end

Instance Attribute Details

#escapedObject

Returns the value of attribute escaped.



288
289
290
# File 'lib/goby/entity/entity.rb', line 288

def escaped
  @escaped
end

#goldObject (readonly)

Returns the value of attribute gold.



289
290
291
# File 'lib/goby/entity/entity.rb', line 289

def gold
  @gold
end

#inventoryObject

Returns the value of attribute inventory.



288
289
290
# File 'lib/goby/entity/entity.rb', line 288

def inventory
  @inventory
end

#nameObject

Returns the value of attribute name.



288
289
290
# File 'lib/goby/entity/entity.rb', line 288

def name
  @name
end

#outfitObject (readonly)

Returns the value of attribute outfit.



289
290
291
# File 'lib/goby/entity/entity.rb', line 289

def outfit
  @outfit
end

Instance Method Details

#==(rhs) ⇒ Object

Parameters:

  • rhs (Entity)

    the entity on the right.



284
285
286
# File 'lib/goby/entity/entity.rb', line 284

def ==(rhs)
  @name == rhs.name
end

#add_gold(gold) ⇒ Object

Adds the given amount of gold.

Parameters:

  • gold (Integer)

    the amount of gold to add.



43
44
45
46
# File 'lib/goby/entity/entity.rb', line 43

def add_gold(gold)
  @gold += gold
  check_and_set_gold
end

#add_item(item, amount = 1) ⇒ Object

Adds the item and the given amount to the inventory.

Parameters:

  • item (Item)

    the item being added.

  • amount (Integer) (defaults to: 1)

    the amount of the item to add.



52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/goby/entity/entity.rb', line 52

def add_item(item, amount = 1)

  # Increase the amount if the item already exists in the inventory.
  @inventory.each do |couple|
    if (couple.first == item)
      couple.second += amount
      return
    end
  end

  # If not already in the inventory, push a couple.
  @inventory.push(C[item, amount])
end

#add_loot(gold, treasures) ⇒ Object

Adds the specified gold and treasures to the inventory.

Parameters:

  • gold (Integer)

    the amount of gold.

  • treasures ([Item])

    the list of treasures.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/goby/entity/entity.rb', line 70

def add_loot(gold, treasures)
  type("Loot: ")
  if ((gold.positive?) || (treasures && treasures.any?))
    print "\n"
    if gold.positive?
      type("* #{gold} gold\n")
      add_gold(gold)
    end
    if treasures && treasures.any?
      treasures.each do |treasure|
        unless treasure.nil?
          type("* #{treasure.name}\n")
          add_item(treasure)
        end
      end
    end
    print "\n"
  else
    type("nothing!\n\n")
  end
end

#clear_inventoryObject

Removes all items from the entity’s inventory.



93
94
95
96
97
# File 'lib/goby/entity/entity.rb', line 93

def clear_inventory
  while @inventory.size.nonzero?
    @inventory.pop
  end
end

#equip_item(item) ⇒ Object

Equips the specified item to the entity’s outfit.

Parameters:

  • item (Item, String)

    the item (or its name) to equip.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/goby/entity/entity.rb', line 102

def equip_item(item)

  index = has_item(item)
  if index
    actual_item = inventory[index].first

    # Checks for Equippable without importing the file.
    if (defined? actual_item.equip)
      actual_item.equip(self)

      # Equipping the item will always remove it from the entity's inventory.
      remove_item(actual_item)
    else
      print "#{actual_item.name} cannot be equipped!\n\n"
    end
  else
    print NO_SUCH_ITEM_ERROR
  end
end

#has_item(item) ⇒ Integer

Returns the index of the specified item, if it exists.

Parameters:

Returns:

  • (Integer)

    the index of an existing item. Otherwise nil.



126
127
128
129
130
131
# File 'lib/goby/entity/entity.rb', line 126

def has_item(item)
  inventory.each_with_index do |couple, index|
    return index if couple.first.name.casecmp(item.to_s).zero?
  end
  return
end

Prints the inventory in a nice format.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/goby/entity/entity.rb', line 134

def print_inventory
  print "Current gold in pouch: #{@gold}.\n\n"

  if @inventory.empty?
    print "#{@name}'s inventory is empty!\n\n"
    return
  end

  puts "#{@name}'s inventory:"
  @inventory.each do |couple|
    puts "* #{couple.first.name} (#{couple.second})"
  end
  print "\n"
end

Prints the status in a nice format. TODO: encapsulate print_stats and print_equipment in own functions.



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/goby/entity/entity.rb', line 151

def print_status
  puts "Stats:"
  puts "* HP: #{@stats[:hp]}/#{@stats[:max_hp]}"
  puts "* Attack: #{@stats[:attack]}"
  puts "* Defense: #{@stats[:defense]}"
  puts "* Agility: #{@stats[:agility]}"
  print "\n"

  puts "Equipment:"
  print "* Weapon: "
  puts @outfit[:weapon] ? "#{@outfit[:weapon].name}" : "none"

  print "* Shield: "
  puts @outfit[:shield] ? "#{@outfit[:shield].name}" : "none"

  print "* Helmet: "
  puts @outfit[:helmet] ? "#{@outfit[:helmet].name}" : "none"

  print "* Torso: "
  puts @outfit[:torso] ? "#{@outfit[:torso].name}" : "none"

  print "* Legs: "
  puts @outfit[:legs] ? "#{@outfit[:legs].name}" : "none"

  print "\n"
end

#remove_gold(gold) ⇒ Object

Removes up to the amount of gold given in the argument. Entity’s gold will not be less than zero.

Parameters:

  • gold (Integer)

    the amount of gold to remove.



182
183
184
185
# File 'lib/goby/entity/entity.rb', line 182

def remove_gold(gold)
  @gold -= gold
  check_and_set_gold
end

#remove_item(item, amount = 1) ⇒ Object

Removes the item, if it exists, and, at most, the given amount from the inventory.

Parameters:

  • item (Item)

    the item being removed.

  • amount (Integer) (defaults to: 1)

    the amount of the item to remove.



191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/goby/entity/entity.rb', line 191

def remove_item(item, amount = 1)

  # Decrease the amount if the item already exists in the inventory.
  @inventory.each_with_index do |couple, index|
    if (couple.first == item)
      couple.second -= amount

      # Delete the item if the amount becomes non-positive.
      @inventory.delete_at(index) if couple.second.nonpositive?

      return
    end
  end
end

#set_gold(gold) ⇒ Object

Sets the Entity’s gold to the number in the argument. Only nonnegative numbers are accepted.

Parameters:

  • gold (Integer)

    the amount of gold to set.



210
211
212
213
# File 'lib/goby/entity/entity.rb', line 210

def set_gold(gold)
  @gold = gold
  check_and_set_gold
end

#set_stats(passed_in_stats) ⇒ Object

Sets stats

Parameters:

  • passed_in_stats (Hash)

    value pairs of stats

Options Hash (passed_in_stats):

  • :max_hp (Integer)

    maximum health points. Set to be positive.

  • :hp (Integer)

    current health points. Set to be nonnegative.

  • :attack (Integer)

    strength in battle. Set to be positive.

  • :defense (Integer)

    protection from attacks. Set to be positive.

  • :agility (Integer)

    speed of commands in battle. Set to be positive.



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/goby/entity/entity.rb', line 223

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

#statsObject

getter for stats

Returns:

  • (Object)


246
247
248
249
250
# File 'lib/goby/entity/entity.rb', line 246

def stats
  # attr_reader makes sure stats cannot be set via stats=
  # freeze makes sure that stats []= cannot be used
  @stats.freeze
end

#unequip_item(item) ⇒ Object

Unequips the specified item from the entity’s outfit.

Parameters:

  • item (Item, String)

    the item (or its name) to unequip.



255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/goby/entity/entity.rb', line 255

def unequip_item(item)
  pair = @outfit.detect { |type, value| value.name.casecmp(item.to_s).zero? }
  if pair
    # On a successful find, the "detect" method always returns
    # an array of length 2; thus, the following line should not fail.
    item = pair[1]
    item.unequip(self)
    add_item(item)
  else
    print NOT_EQUIPPED_ERROR
  end
end

#use_item(item, entity) ⇒ Object

Uses the item, if it exists, on the specified entity.

Parameters:

  • item (Item, String)

    the item (or its name) to use.

  • entity (Entity)

    the entity on which to use the item.



272
273
274
275
276
277
278
279
280
281
# File 'lib/goby/entity/entity.rb', line 272

def use_item(item, entity)
  index = has_item(item)
  if index
    actual_item = inventory[index].first
    actual_item.use(self, entity)
    remove_item(actual_item) if actual_item.consumable
  else
    print NO_SUCH_ITEM_ERROR
  end
end