Get ruby dungeon to repeat back player name - ruby

I'm trying to expand upon Peter Cooper's dungeon game in Beginning Ruby and I want the game to address the player by name at each room and then ask them where they will go to make the game more interactive. I keep getting this error though:
dungeon.rb:82:in <main>': undefined methodname' for nil:NilClass (NoMethodError)
So the main parts I've added to try to make this work are Dungeon initialize (lines 4-13)
def initialize
player_name = ""
until !player_name.empty?
puts "Enter your name!"
player_name = gets.chomp
end
#player = Player.new(player_name)
#player.name = player_name
#rooms = []
end
The line in question that creates the error is this:
my_dungeon.add_room(:largecave, "Large Cave", "#{#player.name}, you find yourself in a large cavernous cave. To the west is a small aperture", {:west => :smallcave})
Full code is here:
Ruby Dungeon Code
What's going on here?

You probably wanted to use
my_dungeon.player.name
instead of
#player.name
in rooms addition method calls(since player has been defined for Dungeon instance).
So just use these lines instead of ones you currently have:
my_dungeon.add_room(:largecave, "Large Cave", "#{my_dungeon.player.name}, you find yourself in a large cavernous cave. To the west is a small aperture", {:west => :smallcave})
my_dungeon.add_room(:smallcave, "Small Cave", "#{my_dungeon.player.name}, you find yourself in a small, claustrophopic cave. To the east is a small aperture", {:east => :largecave}
By the way, you set name in initialize method, so there is no need for #player.name = player_name. And it is simpler to read while player_name.empty? instead of until !player_name.empty?, consider following refactoring:
def initialize
player_name = ""
while player_name.empty?
puts "Enter your name!"
player_name = gets.chomp
end
#player = Player.new(player_name)
#rooms = []
end

Related

Ruby hash.new error undefined local variable or method ... for main:Object

I'm trying to create a new hash (group) to which I'll pass values for name, groceries, fuel_and_accommodations and recreational_activities. Actually, eventually I'll need a hash nested within the group hash (for each traveler). My issue right now is that I get this message:
undefined local variable or method `group' for main:Object
(repl):5:in `user_name'
(repl):18:in `block in enter_expenses'
(repl):15:in `times'
(repl):15:in `enter_expenses'
(repl):34:in `'
I'm just learning Ruby. Any help would be greatly appreciated!
group = Hash.new
def user_name
puts "What is the name of this traveler?"
group["name"]= gets.chomp.capitalize
end
def enter_expenses
puts "Welcome to the Expense Tracker System!\n".upcase
puts "__________________________________________"
puts "\nUse this system to track your group's expenses when traveling."
print "Ready to get started? Enter yes to continue"
ready_to_expense = gets.chomp.downcase
4.times do
if ready_to_expense == "yes"
puts "Welcome #{user_name}! Enter your expenses below:\n"
puts "Amount spent on groceries:"
group["groceries"]= gets.chomp.to_f
puts "Amount spent on fuel & accommodations:"
group["fuel_and_accommodations"]= gets.chomp.to_f
puts "Amount spent recreational activities:"
group["recreational_activities"] = gets.chomp.to_f
elsif "Please come back when ready to enter your expenses."
end
end
end
enter_expenses
create_travelers
puts "__________________________________________"
puts "Thanks for using the expense tracker system!".upcase
Local variables in Ruby does not get into methods; methods declare their own scope, they don’t act like closures. You might use instance variable instead:
#group = Hash.new # NOTE #
...
def enter_expenses
...
4.times do
if ready_to_expense == "yes"
#group["groceries"]= gets.chomp.to_f # NOTE #
...
end
end
end

ruby program in sublime text 2 throws "undefined method" error in saved .rb files

This is the Dungeon example from Beginning Ruby:
class Dungeon
def add_room(reference, name, description, connections)
#rooms << Room.new(reference, name, description, connections,)
end
class Player
attr_accessor :name, :location
def initialize(player_name)
#name = player_name
end
end
def initialize(player_name)
#player = Player.new(player_name)
#rooms = []
end
end
my_dungeon = Dungeon.add_room(:largecave, "Large Cave", "a large cavernous cave", {:west => :smallcave})
my_dungeon = Dungeon.add_room(:smallcave, "Small Cave", "a small claustrophobic cave", {:east => :largecave})
This code builds without error in Sublim Text 2 until I save it to a file on my HD. Once it's saved to my PC I get this build error from Sublime Text 2
C:/Ruby193/bin/stephon.rb:18:in `<main>': undefined method `add_room' for Dungeon:Class (NoMethodError)
[Finished in 0.0s with exit code 1]
I used the %PATH% command in a comm window to add both the directory that this code is in and the Ruby directory. No change.
Any help would be appreciated.
The add_room method on your Dungeon class is an instance method. That means, you must create a new instance of the class before you can call the method on the instance.
Something like this should work (as long as you define a Room class somewhere):
my_dungeon = Dungeon.new("Player 1")
my_dungeon.add_room(:largecave, "Large Cave", "a large cavernous cave", {:west => :smallcave})
my_dungeon.add_room(:smallcave, "Small Cave", "a small claustrophobic cave", {:east => :largecave})

Assert_equal undefined local variable LRTHW ex52

Hi I made it to the lase exercise os Learn Ruby The Hard Way, and I come at the wall...
Here is the test code:
def test_gothon_map()
assert_equal(START.go('shoot!'), generic_death)
assert_equal(START.go('dodge!'), generic_death)
room = START.go("tell a joke")
assert_equal(room, laser_weapon_armory)
end
And here is the code of the file it should test:
class Room
attr_accessor :name, :description, :paths
def initialize(name, description)
#name = name
#description = description
#paths = {}
end
def ==(other)
self.name==other.name&&self.description==other.description&&self.paths==other.paths
end
def go(direction)
#paths[direction]
end
def add_paths(paths)
#paths.update(paths)
end
end
generic_death = Room.new("death", "You died.")
And when I try to launch the test file I get an error:
generic_death = Room.new("death", "You died.")
I tried to set the "generic_death = Room.new("death", "You died.")" in test_gothon_map method and it worked but the problem is that description of the next object is extremely long, so my questions are:
why assertion doesn't not respond to defined object?
can it be done different way then by putting whole object to testing method, since description of the next object is extremely long...
The nature of local variable is that they are, well, local. This means that they are not available outside the scope they were defined.
That's why ruby does not know what generic_death means in your test.
You can solve this in a couple of ways:
define rooms as constants in the Room class:
class Room
# ...
GENERIC_DEATH = Room.new("death", "You died.")
LASER_WEAPON_ARMORY = Room.new(...)
end
def test_gothon_map()
assert_equal(Room::START.go('shoot!'), Room::GENERIC_DEATH)
assert_equal(Room::START.go('dodge!'), Room::GENERIC_DEATH)
room = Room::START.go("tell a joke")
assert_equal(room, Room::LASER_WEAPON_ARMORY)
end
assert the room by its name, or some other identifier:
def test_gothon_map()
assert_equal(START.go('shoot!').name, "death")
assert_equal(START.go('dodge!').name, "death")
room = START.go("tell a joke")
assert_equal(room.name, "laser weapon armory")
end

Undefined method error using a Proc with ruby, cucumber and rspec

Looks like my use of the proc maybe a bit off. I'm working on a tic-tac-toe game and using cucumber to test it's behavior. I've outlined the scenario that i want to fulfill and the step file that I'm using.
The Scenario,
Scenario: Making Bad Moves
Given I have a started Tic-Tac-Toe game
And it is my turn
And I am playing X
When I enter a position "A1" on the board
And "A1" is taken
Then computer should ask me for another position "B2"
And it is now the computer's turn
The step files say...
Given /^I have a started Tic\-Tac\-Toe game$/ do #
#game = TicTacToe.new(:player)
#game.player = "player" #
end
Given /^it is my turn$/ do #
#game.current_player.should eq "player"
end
Given /^I am playing X$/ do
#game = TicTacToe.new(:computer, :X)
#game.player_symbol.should eq :X
end
When /^"(.*?)" is taken$/ do |arg1|
#game.board[arg1.to_sy m] = :O **- # this is causing me to get a "undefined
method `[]=' for #
Given /^I am playing X$/ do
#game = TicTacToe.new(:computer, :X)
#game.player_symbol.should eq :X
end
My code that is attempting to satisfy the feature is:
def board
Proc.new do |get_player_move = :B2|
board_value = get_player_move
#board_locations[board_value]
end
I get this error: NoMethodError: undefined method[]=' for #`
Am i using the proc properly?
Your problem is that [] and []= are in fact different methods. When you type:
#game.board[arg1.to_sym] = :O
ruby reads it as:
#game.board.[]=(arg1.to_sym, :o)
and what you want is
#game.board.[](arg1.to_sym) = :O
To make sure ruby knows what you want do:
(#game.board[arg1.to_sym]) = :O
NOTE:
To be honest I am not sure why you are using Proc here at all, why not simple:
def board
#board_locations
end

Ruby Name Error - Uninitialized constant

I am doing exercises and am
getting NameError:Unitialized Constant MyUnitTests::Room when running test_ex47.rb.
test_ex47.rb:
require 'test/unit'
require_relative '../lib/ex47'
class MyUnitTests < Test::Unit::TestCase
def test_room()
gold = Room.new("Gold Room", """This room has gold in it you can grab. There's a doo to the north.""")
assert_equal(gold.name, "GoldRoom")
assert_equal(gold.paths, {})
end
def test_room_paths()
center = Room.new("Center", "Test room in the center.")
north = Room.new("North", "Test room in the north.")
south = Room.new("South", "Test room in the south.")
center.add_paths({:north => north, :south => south})
assert_equal(center.go(:north), north)
assert_equal(center.go(:south), south)
end
def test_map()
start = Room.new("Start", "You can go west and down a hole.")
west = Room.new("Trees", "There are trees here, you can go east.")
down = Room.new("Dungeon", "It's dark down here, you can go up.")
start.add_paths({:west => west, :down => down})
west.add_paths({:east => start})
down.add_paths({:up => start})
assert_equal(start.go(:west), west)
assert_equal(start.go(:west).go(:east), start)
assert_equal(start.go(down).go(up), start)
end
end
ex47.rb is located in the lib folder and looks like:
class Room
aatr_accessor :name, :description, :paths
def initialize(name, description)
#name = name
#description = description
#paths = {}
end
def go(direction)
#paths[direction]
end
def add_paths(paths)
#paths.update(paths)
end
end
Error:
Finished tests in 0.000872s, 3440.3670 tests/s, 0.0000 assertions/s.
1) Error:
test_map(MyUnitTests):
NameError: uninitialized constant MyUnitTests::Room
test_ex47.rb:22:in `test_map'
2) Error:
test_room(MyUnitTests):
NameError: uninitialized constant MyUnitTests::Room
test_ex47.rb:6:in `test_room'
3) Error:
test_room_paths(MyUnitTests):
NameError: uninitialized constant MyUnitTests::Room
test_ex47.rb:12:in `test_room_paths'
3 tests, 0 assertions, 0 failures, 3 errors, 0 skips]
The problem here is that you are creating a Room object inside the MyUnitTests class on line 3. Ruby thinks you want to use a class called MyUnitTest::Room, which doesn't exist. You need to use an absolute class reference, like so:
class MyUnitTests < Test::Unit::TestCase
def test_room()
gold = ::Room.new("Gold Room", """This room has gold in it you can grab. There's a doo to the north.""")
assert_equal(gold.name, "GoldRoom")
assert_equal(gold.paths, {})
end
Notice the :: before Room.new on line 3 there? That tells Ruby that you want to create a Room object from the top level name space :)
I hope that answers your question.
EDIT: You'll also need to change your other references to the Room class to ::Room. Sorry, I thought only the top one was a problem because of the indentation. A closer look reveals that the rest need the :: as well.

Resources