# My Longsword is broken

**URL:** <https://www.ruby-forum.com/t/my-longsword-is-broken/134748>\
**Category:** Ruby\
**Created:** [April 14, 2008, 7:08pm UTC](https://www.ruby-forum.com/t/my-longsword-is-broken/134748 "2008-04-14T19:08:39Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![gastrogreen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@gastrogreen](https://www.ruby-forum.com/u/gastrogreen)\
**Post date:** [April 14, 2008, 7:08pm UTC](https://www.ruby-forum.com/t/my-longsword-is-broken/134748/1 "2008-04-14T19:08:39Z")

</div>

Hello all,

Just started my first Ruby prog and hit a snag almost instantly. I  
simply wish to have my selected weapon do it’s prescribed damage as I  
intend (in this case, it’s 1-8 damage). Complete noob here so any help  
at all would be greatly appreciated. The following is a re-creation of  
my problem:

#\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
class Sword  
attr\_accessor(:realDam)

def initialize(aRealDam)  
@realDam = aRealDam  
end  
end

Longsword = Sword.new(rand(8)+1)  
weapon = Longsword

begin

5.times {p weapon.realDam}  
puts  
5.times {p (rand(8)+1)}

end  
#\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

Output looks like this:

#**Current Longsword damage (Picks a number and ‘keeps’ it).**  
6  
6  
6  
6  
6

# **Intended output for the longsword here**  
6  
8  
8  
4  
8

---

<div class="post-metadata">

**Author:** ![gastrogreen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@gastrogreen](https://www.ruby-forum.com/u/gastrogreen)\
**Post date:** [April 14, 2008, 7:28pm UTC](https://www.ruby-forum.com/t/my-longsword-is-broken/134748/2 "2008-04-14T19:28:57Z")

</div>

class Sword  
def initialize(&block)  
@damage = block  
end

def realDam  
@damage.call  
end  
end

Longsword = Sword.new { rand(8)+1 }  
weapon = Longsword

5.times {p weapon.realDam}  
puts  
5.times {p(rand(8)+1)}

------- output --------  
3  
2  
1  
4  
8

1  
5  
4  
1  
5

---

<div class="post-metadata">

**Author:** ![gastrogreen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@gastrogreen](https://www.ruby-forum.com/u/gastrogreen)\
**Post date:** [April 14, 2008, 7:30pm UTC](https://www.ruby-forum.com/t/my-longsword-is-broken/134748/3 "2008-04-14T19:30:07Z")

</div>

On Monday 14 April 2008, Ben G. wrote:

> attr\_accessor(:realDam)
> 
> 6  
> 8  
> When you write:

Longsword = Sword.new(rand(8)+1), you’re setting the @realDam attribute  
to the  
return value of rand(8)+1. To do what you want, you should pass to the  
constructor (that is, initialize) the maximum damage, then call rand in  
the  
realDam method. Of course, this means that you shouldn’t create the  
realDam  
method using attr\_accessor, but write it by hand. For example:

class Sword  
def initialize max\_dam  
@max\_dam = max\_dam  
end

def real\_dam  
rand(@max\_dam)+1  
end  
end

weapon = Sword.new(8)  
5.times{p weapon.real\_dam}

This should produce 5 random values between 1 and 8.

By the way, are you sure it is right to assign to the constant LongSword  
an  
instance of class Sword? Of course, I can’t know how your application is  
structured, but I think that both Sword and LongSword should be classes,  
representing the generic sword or long sword, maybe with LongSword  
inheriting  
from Sword. Your code, in my opinion, can create confusion, since it  
creates  
two constants, each with the name of a weapon, but with very different  
behaviour: one, Sword, represents the ‘abstract’ sword, while the other  
(LongSword) is a ‘concrete’ weapon. This difference has very practical  
consequences, of course: you can’t call the realDam method on Sword, but  
you  
can on LongSword.

Stefano

---

<div class="post-metadata">

**Author:** ![gastrogreen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@gastrogreen](https://www.ruby-forum.com/u/gastrogreen)\
**Post date:** [April 14, 2008, 7:31pm UTC](https://www.ruby-forum.com/t/my-longsword-is-broken/134748/4 "2008-04-14T19:31:54Z")

</div>

Hi Ben,

if I understand it correctly, your program shows completely normal  
behavior: you instantiate your Sword class and assign a number to  
@realDam and then just read this variable 5 times. What you might want  
is this:

class Sword  
def intialize(maxDam)  
@maxDam = maxDam  
end  
def realDam  
return rand(@maxDam) + 1  
end  
end

So everytime you access sword\_instance.realDam you get a freshly  
calculated random number which is never higher than @maxDam. Since  
everything is a method call in ruby (even accessing an instance  
variable), there is no need to declare one (in your special case  
however), the realDam method behaves like a getter.

Hope that helps,  
Martin

---

<div class="post-metadata">

**Author:** ![gastrogreen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@gastrogreen](https://www.ruby-forum.com/u/gastrogreen)\
**Post date:** [April 14, 2008, 7:35pm UTC](https://www.ruby-forum.com/t/my-longsword-is-broken/134748/5 "2008-04-14T19:35:26Z")

</div>

A few ruby basics:  
foo\_bar is a variable name (all lowercase separated by underscores)  
FOO\_BAR is a constant (all caps separated by underscore)  
FooBar is a class or module (starts with cap and is bumpy case)

So:  
Longsword = Sword.new(rand(8)+1)  
is a little funky.

Secondly,  
The …

Apparently, I type too slow and Gerardo has finished my work for me.  
Hope that helps.

/Shawn

On Mon, Apr 14, 2008 at 10:08 AM, Ben G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![gastrogreen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@gastrogreen](https://www.ruby-forum.com/u/gastrogreen)\
**Post date:** [April 14, 2008, 7:37pm UTC](https://www.ruby-forum.com/t/my-longsword-is-broken/134748/6 "2008-04-14T19:37:48Z")

</div>

On Apr 14, 1:08 pm, Ben G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Longsword = Sword.new(rand(8)+1)

Here you generate a value that gets stored  
try:

class Sword  
def initialize(maxDamage, modifier)  
@maxDamage, @modifier = maxDamage, modifier  
end

def hitDamage()  
return rand(@maxDamage)+1 + @modifier  
end  
end

not tested, but should be close

cheers  
Chris

---

<div class="post-metadata">

**Author:** ![gastrogreen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@gastrogreen](https://www.ruby-forum.com/u/gastrogreen)\
**Post date:** [April 15, 2008, 1:43am UTC](https://www.ruby-forum.com/t/my-longsword-is-broken/134748/7 "2008-04-15T01:43:47Z")

</div>

On Tue, Apr 15, 2008 at 02:08:42AM +0900, Ben G. wrote:

> Hello all,
> 
> Just started my first Ruby prog and hit a snag almost instantly. I  
> simply wish to have my selected weapon do it’s prescribed damage as I  
> intend (in this case, it’s 1-8 damage). Complete noob here so any help  
> at all would be greatly appreciated. The following is a re-creation of  
> my problem:

Sometimes to fix your longsword, you must adjust your johnson:

require ‘johnson’

ctx = Johnson::Context.new  
ctx[:ruby\_rand] = lambda { |x| rand(x) }  
ctx.evaluate(\<\<-END  
var LongSword = {  
realDamage: function() {  
return ruby\_rand(this.maxDamage);  
}  
}  
END  
)  
ctx[:LongSword].maxDamage = 8  
puts ctx[:LongSword].realDamage()

> **[GitHub - jbarnette/johnson: Johnson wraps JavaScript in a loving Ruby embrace.](https://github.com/jbarnette/johnson/tree/master)**
>
> master

Though there might be easier solutions…

---

<div class="post-metadata">

**Author:** ![gastrogreen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@gastrogreen](https://www.ruby-forum.com/u/gastrogreen)\
**Post date:** [April 15, 2008, 8:26am UTC](https://www.ruby-forum.com/t/my-longsword-is-broken/134748/8 "2008-04-15T08:26:48Z")

</div>

On Mon, Apr 14, 2008 at 4:43 PM, Aaron P.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Sometimes to fix your longsword, you must adjust your johnson:

require “johnson”  
Johnson.evaluate(“Math.floor(max \* Math.random() + 1)”, :max =\> 8)

~ j.
