Skip to content

Commit

Permalink
Write many new tests for Entity, Player, Monster
Browse files Browse the repository at this point in the history
  • Loading branch information
nskins committed Apr 22, 2017
1 parent 81f448d commit 98278bf
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 39 deletions.
30 changes: 14 additions & 16 deletions lib/Entity/Monster/monster.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require_relative "../entity.rb"

class Monster < Entity

# @param [String] name the name.
# @param [Integer] max_hp the greatest amount of health.
# @param [Integer] hp the current amount of health.
Expand All @@ -21,50 +21,50 @@ def initialize(name: "Monster", max_hp: 1, hp: nil, attack: 1, defense: 1, agili
inventory: inventory, gold: gold, battle_commands: battle_commands, outfit: outfit)
@message = message
@treasures = treasures

# Find the total number of treasures in the distribution.
@total_treasures = 0
@treasures.each do |pair|
@total_treasures += pair.second
end
end

# Choose rewards based on the 'gold' and 'treasures' member variables.
#
# @return [Couple(Integer, Item)] the gold (first) and the treasure (second).
def sample_rewards
# Sample a random amount of gold.
gold = Random.rand(0..@gold)

# Determine which treasure to reward the victor.
treasure = sample_treasures

return Couple.new(gold, treasure)
end

# Provides a deep copy of the monster. This is necessary since
# the monster can use up its items in battle.
#
# @return [Monster] deep copy of the monster.
def clone
# Create a shallow copy for most of the variables.
monster = super

# Reset the copy's inventory.
monster.inventory = []

# Create a deep copy of the inventory.
@inventory.each do |pair|
monster.inventory << Couple.new(pair.first.clone, pair.second)
end

return monster
end

attr_accessor :message, :treasures, :total_treasures

private

# Chooses a treasure based on the sample distribution.
#
# @return [Item] the reward for the victor of the battle (or nil - no treasure).
Expand All @@ -79,10 +79,8 @@ def sample_treasures
total = 0
@treasures.each do |pair|
total += pair.second
if index < total
return pair.first
end
return pair.first if index < total
end
end

end
31 changes: 29 additions & 2 deletions lib/Entity/entity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,25 @@ def add_item(item, amount = 1)
@inventory.push(Couple.new(item, amount))
end

# Adds the specified gold and treasure item to the inventory.
#
# @param [Integer] gold the amount of gold.
# @param [Item] treasure the treasure item.
def add_rewards(gold, treasure)
if ((gold > 0) || treasure)
type("Rewards:\n")
if (gold > 0)
type("* #{gold} gold\n")
add_gold(gold)
end
if (treasure)
type("* #{treasure.name}\n")
add_item(treasure)
end
print "\n"
end
end

# Determines how the entity should select an attack in battle.
# Override this method for control over this functionality.
#
Expand All @@ -99,6 +118,13 @@ def choose_item_and_on_whom(enemy)
return Couple.new(item, whom)
end

# Removes all items from the entity's inventory.
def clear_inventory
while @inventory.size.nonzero?
@inventory.pop
end
end

# Equips the specified item to the entity's outfit.
#
# @param [Item, String] item the item (or its name) to equip.
Expand Down Expand Up @@ -194,7 +220,8 @@ def print_status
print "\n"

unless @battle_commands.empty?
puts "Battle Commands:"; print_battle_commands
puts "Battle Commands:"
print_battle_commands
end
end

Expand Down Expand Up @@ -285,7 +312,7 @@ def ==(rhs)
attr_accessor :defense
attr_accessor :agility

attr_reader :inventory
attr_accessor :inventory
attr_reader :gold

attr_reader :outfit
Expand Down
18 changes: 2 additions & 16 deletions lib/Entity/player.rb
Original file line number Diff line number Diff line change
Expand Up @@ -327,28 +327,14 @@ def battle(monster)
die if hp <= 0

if monster.hp <= 0
type("You defeated the #{monster.name}!\n")
type("You defeated the #{monster.name}!\n\n")

# Determine the rewards for defeating the monster.
rewards = monster.sample_rewards

gold = rewards.first
treasure = rewards.second

# Output some helpful text and give the rewards to the player.
# TODO: print_rewards?
if ((gold > 0) || treasure)
type("Rewards:\n")
if (gold > 0)
type("* #{gold} gold\n")
@gold += gold # TODO: fix: use #add_gold.
end
if (treasure)
type("* #{treasure.name}\n")
add_item(treasure)
end
end
print "\n"
add_rewards(gold, treasure)
end

end
Expand Down
27 changes: 26 additions & 1 deletion spec/Entity/Monster/monster_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
expect(monster.outfit).to eq Hash.new
expect(monster.battle_commands).to eq Array.new
expect(monster.message).to eq "!!!"
expect(monster.treasures).to eq Array.new
end

it "correctly assigns custom parameters" do
Expand All @@ -38,7 +39,9 @@
Attack.new(name: "Scratch"),
Attack.new(name: "Kick")
],
message: "\"Oh, hi.\"")
message: "\"Oh, hi.\"",
treasures: [Couple.new(Item.new, 1),
Couple.new(nil, 3)])
expect(clown.name).to eq "Clown"
expect(clown.max_hp).to eq 20
expect(clown.hp).to eq 15
Expand All @@ -55,6 +58,28 @@
Attack.new(name: "Scratch")
]
expect(clown.message).to eq "\"Oh, hi.\""
expect(clown.treasures).to eq [Couple.new(Item.new, 1),
Couple.new(nil, 3)]
expect(clown.total_treasures).to eq 4
end
end

context "clone" do
before(:each) do
@monster = Monster.new(inventory: [Couple.new(Item.new, 1)])
@clone = @monster.clone
end

it "should leave the original's inventory the same" do
@clone.use_item("Item", @clone)
expect(@monster.inventory.size).to eq 1
expect(@clone.inventory.size).to be_zero
end

it "should leave the clone's inventory the same" do
@monster.use_item("Item", @monster)
expect(@monster.inventory.size).to be_zero
expect(@clone.inventory.size).to eq 1
end
end

Expand Down
50 changes: 50 additions & 0 deletions spec/Entity/entity_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,40 @@
end
end

context "add rewards" do
before(:each) do
@entity = Entity.new
end

it "should give the player the appropriate amount of gold" do
@entity.add_rewards(5, nil)
expect(@entity.gold).to eq 5
expect(@entity.inventory.size).to be_zero
end

it "should give the player the appropriate treasure item" do
@entity.add_rewards(0, Item.new)
expect(@entity.gold).to be_zero
expect(@entity.inventory).to eq [Couple.new(Item.new, 1)]
end

it "should give the player both the gold and the treasure item" do
@entity.add_rewards(5, Item.new)
expect(@entity.gold).to eq 5
expect(@entity.inventory).to eq [Couple.new(Item.new, 1)]
end

it "should not output anything for no rewards" do
expect { @entity.add_rewards(0, nil) }.not_to output.to_stdout
end

it "should output both of the rewards" do
expect { @entity.add_rewards(5, Item.new) }.to output(
"Rewards:\n* 5 gold\n* Item\n\n"
).to_stdout
end
end

context "choose attack" do
it "randomly selects one of the available commands" do
kick = BattleCommand.new(name: "Kick")
Expand All @@ -172,6 +206,22 @@
end
end

context "clear inventory" do
it "has no effect on an empty inventory" do
entity = Entity.new
entity.clear_inventory
expect(entity.inventory.size).to be_zero
end

it "removes all items from a non-empty inventory" do
entity = Entity.new(inventory: [Couple.new(Item.new, 4),
Couple.new(Item.new(name: "Apple"), 3),
Couple.new(Item.new(name: "Orange"), 7)])
entity.clear_inventory
expect(entity.inventory.size).to be_zero
end
end

context "equip item" do
it "correctly equips the weapon and alters the stats" do
entity = Entity.new(inventory: [Couple.new(
Expand Down
17 changes: 13 additions & 4 deletions spec/Entity/player_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
end

before(:each) do
@dude = Player.new(attack: 10, battle_commands: [Attack.new(strength: 20)],
@dude = Player.new(attack: 10, agility: 10000,
battle_commands: [Attack.new(strength: 20), Escape.new, Use.new],
map: @map, location: @center)
@slime = Monster.new(battle_commands: [Attack.new(success_rate: 0)] )
@slime = Monster.new(battle_commands: [Attack.new(success_rate: 0)],
gold: 5000, treasures: [Couple.new(Item.new, 1)])
@newb = Player.new(battle_commands: [Attack.new(success_rate: 0)],
gold: 50, map: @map, location: @center)
@dragon = Monster.new(attack: 50, battle_commands: [Attack.new(strength: 50)] )
Expand Down Expand Up @@ -322,7 +324,15 @@
# TODO: may need to expose more line coverage in these tests.
context "battle" do
it "should allow the player to win in this example" do
__stdin("attack\n") do
__stdin("use\nattack\n") do
@dude.battle(@slime)
end
expect(@dude.inventory.size).to eq 1
end

it "should allow the player to escape in this example" do
# Could theoretically fail, but with very low probability.
__stdin("escape\nescape\nescape\n") do
@dude.battle(@slime)
end
end
Expand All @@ -337,5 +347,4 @@
expect(@newb.location).to eq Couple.new(1,1)
end
end

end

0 comments on commit 98278bf

Please sign in to comment.