22 Jul, 2009, Igabod wrote in the 1st comment:
Votes: 0
I'm trying to make a sample program from the tutorial I'm using into an interactive game. It's successful so far but I'm trying to turn it into a more in-depth game. To do this I need a prompt that displays the name and various stats of the character. Similar to a prompt for muds. The problem I keep coming across is that the various numbers and whatnot aren't showing. Here's what I'm trying.

[edit to add] The problem area starts at line 161.

class Dragon

def initialize name
@name = name
@asleep = false
@stuffInBelly = 10 # He's full.
@stuffInIntestine = 1 # He doesn't need to go.
@energy = 10 # He's full of energy.

puts @name + ' is born.'
end

def feed
puts 'You feed ' + @name + '.'
@stuffInBelly = 10
passageOfTime
end

def walk
puts 'You walk ' + @name + '.'
@stuffInIntestine = 0
@energy -= 1
passageOfTime
end

def putToBed
puts 'You put ' + @name + ' to bed.'
@asleep = true
3.times do
if @asleep
passageOfTime
end
if @asleep
puts @name + ' snores, filling the room with smoke.'
end
end
if @asleep
@asleep = false
@energy = 10
puts @name + ' wakes up slowly.'
end
end

def passOut
puts @name + ' wobbles unsteadily on his feet then comes crashing down in a big heap.'
@asleep = true
3.times do
if @asleep
passageOfTime
end
if @asleep
puts @name + ' growls in his sleep and thrashes about as if in a nightmare.'
end
end
if @asleep
@asleep = false
@energy = 6
puts @name + ' wakes up in a bad mood… looks like he needs more sleep.'
end
end

def toss
puts 'You toss ' + @name + ' up into the air.'
puts 'He giggles, which singes your eyebrows.'
@energy -= 1
passageOfTime
end

def rock
puts 'You rock ' + @name + ' gently.'
@asleep = true
puts 'He briefly dozes off…'
@energy += 1
passageOfTime
if @asleep
@asleep = false
puts '…but wakes when you stop.'
end
end

private

# "private" means that the methods defined here are
# methods internal to the object. (You can feed
# your dragon, but you can't ask him if he's hungry.)

def tired?
# only mildly tired
@energy == 5
end

def exhausted?
# passing out
@energy == 0
end

def hungry?
# Method names can end with "?".
# Usually, we only do this if the method
# returns true or false, like this:
@stuffInBelly <= 2
end

def poopy?
@stuffInIntestine >= 8
end

def passageOfTime
if @stuffInBelly > 0
# Move food from belly to intestine.
@stuffInBelly -= 1
@stuffInIntestine += 1
else # Our dragon is starving!
if @asleep
@asleep = false
puts 'He wakes up suddenly!'
end
puts @name + ' is starving! In desperation, he ate YOU!'
sleep 4
exit # This quits the program.
end

if @stuffInIntestine >= 10
@stuffInIntestine = 0
puts 'Whoops! ' + @name + ' had an accident…'
end

if tired?
puts @name + ' yawns a big toothy yawn and puffs smoke in your face.'
end

if exhausted?
puts @name + ' wobbles unsteadily on his feet then crashes down in a big heap.'
@asleep = true
end

if hungry?
if @asleep
@asleep = false
puts 'He wakes up suddenly!'
end
puts @name + '\'s stomach grumbles…'
end

if poopy?
if @asleep
@asleep = false
puts 'He wakes up suddenly!'
end
puts @name + ' does the potty dance…'
end
end

end

print 'Please enter your dragon\'s name: '
dname = gets.chomp
pet = Dragon.new dname.capitalize
command = ' '

#HERE IS THE PROBLEM AREA
def prompt
puts 'Name: ' +@name+ ' Energy: ' +@energy+ ' Food: ' +@stuffInBelly+ ' Potty: ' +@stuffInIntestine
print 'Enter your command here: '
end

while command.downcase != 'quit'
puts "Commands are: Feed, Toss, Rock, Sleep, Walk and Quit\r\n\r\n"
prompt
command = gets.chomp
if command.downcase == 'feed'
pet.feed
end
if command.downcase == 'toss'
pet.toss
end
if command.downcase == 'walk'
pet.walk
end
if command.downcase == 'sleep'
pet.putToBed
end
if command.downcase == 'rock'
pet.rock
end
end


and here's what shows up:

Quote
Name: Energy: Food: Potty:
Enter your command here:


notice the Name: Energy: Food: Potty: all show up but the values don't. any help with this would be very much appreciated.
22 Jul, 2009, Ssolvarain wrote in the 2nd comment:
Votes: 0
22 Jul, 2009, Igabod wrote in the 3rd comment:
Votes: 0
great response there… so helpful… thanks so much.
22 Jul, 2009, kiasyn wrote in the 4th comment:
Votes: 0
This needs to be like:

dname = gets.chomp
pet = Dragon.new dname.capitalize
command = ' '

def prompt
puts 'Name: ' + pet.name+ ' Energy: ' + pet.energy+ ' Food: ' +pet.stuffInBelly+ ' Potty: ' +pet.stuffInIntestine
print 'Enter your command here: '
end
22 Jul, 2009, Igabod wrote in the 5th comment:
Votes: 0
dragon_interactive.rb:157:in `prompt': undefined local variable or method `pet' for main:Object (NameError)
from dragon_interactive.rb:169

That's the error I get from that method.
22 Jul, 2009, Ssolvarain wrote in the 6th comment:
Votes: 0
Sorry, you can see it was edited. I decided not to waste space, like now.
22 Jul, 2009, bbailey wrote in the 7th comment:
Votes: 0
kiasyn said:
This needs to be like:

dname = gets.chomp
pet = Dragon.new dname.capitalize
command = ' '

def prompt
puts 'Name: ' + pet.name+ ' Energy: ' + pet.energy+ ' Food: ' +pet.stuffInBelly+ ' Potty: ' +pet.stuffInIntestine
print 'Enter your command here: '
end


The above is close to what you want. "Global" variables in ruby need to be defined and accessed with a $.

dname = gets.chomp
$pet = Dragon.new dname.capitalize
command = ' '

def prompt
puts 'Name: ' + $pet.name+ ' Energy: ' + $pet.energy+ ' Food: ' +$pet.stuffInBelly+ ' Potty: ' +$pet.stuffInIntestine
print 'Enter your command here: '
end


As a hint for your next set of problems, check out attr_reader/attr_writer/attr_accessor, and the to_s method.
22 Jul, 2009, Chris Bailey wrote in the 8th comment:
Votes: 0
Just came across your post Igabod, did you get it all worked out? I see no need for a gobal variable here, as long as you keep a reference to the Dragon object around, you can use it without a hitch. You can only access @instance_variables from within the instance of the class in question. That is why you need to expose them externally using a reference to the object. You can either expose those variables manually by writing getter/setter methods, ex:

class Foo
@bar = 'foo'
def bar
@bar
end

def bar=(val)
@bar = val
end
end


Or you can use attr_accessor/reader/writer, which are actually methods that write those above methods for you. To use them, simply insert a call to the attr_* method, passing whichever variables you would like the methods to be created for as arguments, in the form of symbols like so.

class Foo
attr_reader :one
attr_writer :two
attr_accessor :three, :four

def initialize
@one,@two,@three,@four = 50
end
end

You will now have the following methods, one, two=, three, three=, four, four= defined for you! =)
22 Jul, 2009, bbailey wrote in the 9th comment:
Votes: 0
Chris Bailey said:
Just came across your post Igabod, did you get it all worked out? I see no need for a gobal variable here, as long as you keep a reference to the Dragon object around, you can use it without a hitch.


If only that were so.

./drag2.rb:165:in `prompt': undefined local variable or method `pet' for main:Object (NameError)
from ./drag2.rb:171


pet, unless made a global variable with $, will remain local in scope, which works fine for the top-level code in the while loop at the end of the program, but the prompt function has no access to the pet variable. Pet either needs to be made global, or made accessible to prompt in another way. Such are the pitfalls of using the global (really, Object's local) scope.
22 Jul, 2009, Chris Bailey wrote in the 10th comment:
Votes: 0
bbailey said:
Chris Bailey said:
Just came across your post Igabod, did you get it all worked out? I see no need for a gobal variable here, as long as you keep a reference to the Dragon object around, you can use it without a hitch.


If only that were so.

./drag2.rb:165:in `prompt': undefined local variable or method `pet' for main:Object (NameError)
from ./drag2.rb:171


pet, unless made a global variable with $, will remain local in scope, which works fine for the top-level code in the while loop at the end of the program, but the prompt function has no access to the pet variable. Pet either needs to be made global, or made accessible to prompt in another way. Such are the pitfalls of using the global (really, Object's local) scope.


You are correct Mr. Bailey, the prompt function has no access to the pet variable. That is exactly why I said "as long as you keep a reference to the Dragon object around". By which I meant, you don't need a global, you just need make sure that your reference is within the scope of your function. =)
22 Jul, 2009, bbailey wrote in the 11th comment:
Votes: 0
Chris Bailey said:
bbailey said:
pet, unless made a global variable with $, will remain local in scope, which works fine for the top-level code in the while loop at the end of the program, but the prompt function has no access to the pet variable. Pet either needs to be made global, or made accessible to prompt in another way. Such are the pitfalls of using the global (really, Object's local) scope.


You are correct Mr. Bailey, the prompt function has no access to the pet variable. That is exactly why I said "as long as you keep a reference to the Dragon object around". By which I meant, you don't need a global, you just need make sure that your reference is within the scope of your function. =)


Right, but from the perspective of a ruby newcomer (e.g., the OP), it likely appeared as though a reference to the Dragon object -was- being kept around. Making it explicitly clear that scope issues is why the code did not work seemed prudent, especially when a variable used in such a way as the OP attempted is in fact treated as a global variable in many other languages (e.g., C), but not in Ruby. I (and, I'm sure, anyone familiar with scope in Ruby) understood what you meant and I did not mean to imply you were incorrect – only to make it clearer for those who aren't as familiar with it.
22 Jul, 2009, Chris Bailey wrote in the 12th comment:
Votes: 0
Oh ok I get it now =P
22 Jul, 2009, Runter wrote in the 13th comment:
Votes: 0
I disagree with all Bailey.
23 Jul, 2009, bbailey wrote in the 14th comment:
Votes: 0
Runter said:
I disagree with all Bailey.


I agree with your disagreement, unless we can agree to disagree with your disagreement. Narf!
Random Picks
0.0/14