On Monday 03 March 2008, August0866 wrote:
@roll = base+random(range)
def smarts
end
puts joe.power.to_s+’ = power’
OK, so why is this broken?
There are many reasons your code doesn’t work. Let’s see what happens
running
it in ruby (by the way, when asking for help about a piece of code which
produces an error, it’s better to also show the error message):
- FIRST TRY:
./prova.rb:13:in `initialize’: wrong number of arguments (2 for 0)
(ArgumentError)
This means that some initialize method is called with 2 arguments, when
it
should receive no argument on line 11. The line in question is:
@power = Roll.new(10, 8)
Apparently, there’s no call to initialize here. What you’re trying to do
in
this line, is to create an instance of class Roll, calling Roll.new. For
most
classes, the ‘new’ method first creates a new object, then calls its
‘initialize’ method, which, as the name implies, is used to perform
initialization on the object (for example, giving starting values to
instance
variables). Since you didn’t define an initialize method for class Roll,
it
uses the one defined for the parent class, which is Object.
The initialize method defined for class Object takes no argument, so you
get
an error.
Looking at the definition of class Roll, i see you defined a method
called
Roll, which takes two arguments and sets instance variables, just like
initialize should do. I guess you thought that method would have been
called
by new. Let’s rename it to initialize and see if it solves the problem.
- SECOND TRY:
./prova.rb:5:in initialize': undefined method
random’ for
#<Roll:0xb7c10c70
@range=8, @base=10> (NoMethodError)
This is easy: you’re calling a method named ‘random’, which doesn’t
exist.
The method which generates a random number in ruby is called rand, so
we’ll
replace random with rand
- THIRD TRY:
./prova.rb:26:in health': undefined method
/’ for #<Roll:0xb7beeb34
@range=8, @base=10, @roll=15> (NoMethodError)
from ./prova.rb:41
Now, ruby hits an error while calling the health method: in particular,
in
line 26 there’s a call to a method ‘/’ which is undefined. Line 26 is:
@health = self.power*(self.smarts/self.speed)
In ruby, operators such as +, -, * and / are simply methods, so that
when you
write, for example 2 + 3, ruby calls the ‘+’ method of the object 2
passing
it the object 3 as argument. In your code, you’re dividing self.smarts
by
self.speed, which are both of class Roll. Class Roll doesn’t have a
method
called ‘/’, so you get the error.
This problem could be solved defining a sensible / method for class
Roll, or,
more simply, by defining a method which allows to get the value of the
variable @roll of an instance of roll (which is a number), and use that
instead of the instance of Roll itself. It may be worth asking whether
class
Roll really needs to exist. If you won’t require the @base and @range
values
somewhere else, then it would be much easier to replace the whole class
with
a method such as this:
def roll(base, range)
base + rand(range)
end
At any rate, let’s assume that Roll needs to be a class and add a method
which allows to extract the @roll instance variable. We could define it
by
hand, but ruby does it automatically if we add this line inside class
Roll:
attr_reader :roll
This generates a method called roll which returns @roll.
Then, we need to replace speed and smarts and power with speed.roll,
smarts.roll and power.roll in lines 24, 26 and 47 (we would get an
analogous
problem with the acc method if we leaved it as it is).
Before looking at the error, there are two things to notice: first,
power,
smarts and speed aren’t numbers but instances of class Roll. If this
isn’t
what you expected, then most likely you should replace class Roll with
the
method roll as I mentioned above. Second, health is 0 (of course, this
will
depend on the random number which have been generated). Since both
smarts.roll and speed.roll are integers, the division will return 0 if
the
divider is greater than the divisor. To avoid this, add a call to to_f
to one
of the operands. to_f will convert the integer to a float, so the
division
will use decimals.
Looking at the error, it simply means that, in line 43, we’re trying to
add a
number with a string. The reason is simply that you forget to call the
to_s
method on joe.acc as you did for the other ones.
Now, it works.
Attached, you’ll find a copy of the code with all the modifications I
spoke
about.
I hope this helps
Stefano