Class and inheritance

A

August0866

Hi All,

I am not a programmer, yet. I am trying ruby on for size, most things
fit ok, but Classes are puzzling me.

<code>
class Roll
def Roll(base,range)
@base=base
@range=range
@roll = base+random(range)
end
end

class Stats
def power
@power=Roll.new(10,8)
end
def speed
@speed=Roll.new(10,8)
end
def smarts
@smarts=Roll.new(10,8)
end
end

class Attribs < Stats
def acc
@acc=0.75*self.power+(self.speed/self.smarts)
end
def health
@health = self.power*(self.smarts/self.speed)
end
end
class Npc < Attribs
def name(name)
@name=name
end
end

joe=Npc.new
joe.name('Joe')
#puts joe.name.to_s+' = name'
puts joe.power.to_s+' = power'
puts joe.smarts.to_s+' = smarts'
puts joe.speed.to_s+' = speed'
puts joe.health.to_s+' = health'
puts joe.acc+' = acc'
puts joe
puts '======================='
puts 'Calculations'
puts 0.75*joe.power+(joe.speed/joe.smarts)
</code>

OK, so why is this broken?
 
F

F. Senault

Le 03 mars à 16:03, August0866 a écrit :

Hi.
I am not a programmer, yet. I am trying ruby on for size, most things
fit ok, but Classes are puzzling me.

<code>
class Roll
def Roll(base,range)

OK, so why is this broken?

The constructor in ruby is named initialize, not the name of the class
like in Java. Try :

class Roll
def initialize(base, range)
...
end
...
end

Fred
 
A

August0866

Le 03 mars à 16:03, August0866 a écrit :

Hi.



The constructor in ruby is named initialize, not the name of the class
like in Java. Try :

class Roll
def initialize(base, range)
...
end
...
end

Fred

ok, new attempt

class Roll
def initialize(base, range)
@roll = base+rand(range)
return @roll
end
end

class Stats
def power
@power=Roll.new(10,8)
end

def speed
@speed=Roll.new(10,8)
end

def smarts
@smarts=Roll.new(10,8)
end
end

class Attribs < Stats
def acc
@acc=self.power+(self.speed / self.smarts)# doesnt want to do
the math ?Why?
end

def health
@health = 0.00+self.power*(self.smarts/self.speed)# doesnt want
to do the math ?Why?
end
end
class Npc < Attribs
def initialize(name)
@name=name
end
def job
puts 'stuff'
end
end


class Test
def test
a=Roll.new(10,8)
b=Stats.new
c=Attribs.new
d=Npc.new('Joe')

puts '++++++++++++++++A+++++++++++++++++++'
puts 'a object is '+a.to_s
puts 'a\'s method is called roll '+a.inspect
puts '++++++++++++++++A+++++++++++++++++++'
puts '================B==================='
puts 'b is object '+b.inspect.to_s
puts 'b methods are power = '+b.power.to_s
puts ', speed ='+b.speed.to_s
puts ', and finaly smarts = '+b.smarts.to_s
puts '================B=================='
puts '________________C__________________'
puts 'now on to c'
puts c.to_s+' is the object name for c'
puts 'c has all the methods of a and b plus its own'
puts ' c has a power of '+c.power.inspect.to_s
puts ' c has a speed of '+c.speed.inspect.to_s
puts ' c has a smarts of '+c.smarts.inspect.to_s
puts ' plus c has an Accuracy of '+c.acc.to_s
puts ' plus c has a health of '+c.health.to_s
puts '________________C____________________'
puts '||||||||||||||||D||||||||||||||||||||'

puts 'D is the goal'
puts d.inspect

end
end
s=Test.new
puts s.test
 
A

August0866

My intent is when i call class Npc(str) i want to get back
3 random values power,speed,smarts 2 derived values => accuracy and =>
health and a derived string => job

like this
joe=Npc.new('Joe')
puts joe

output like "Joe" 11 12 15 10.15 8.8 "smithy"
 
F

F. Senault

Le 03 mars à 17:53, August0866 a écrit :
My intent is when i call class Npc(str) i want to get back
3 random values power,speed,smarts 2 derived values => accuracy and =>
health and a derived string => job

like this
joe=Npc.new('Joe')
puts joe

output like "Joe" 11 12 15 10.15 8.8 "smithy"

Ok. Here's an adapted version of your code.

- I gave you the way to create a "Roll" objetct, but you don't really
need it ; what you need is an "helper function" that returns a
number. So, I made a module to contain it.
- Constructors in Ruby _always_ return the new object, regardless of the
explicit return clause.
- Rolling dice every time you access one of your base characteristics is
not the way to go ; here, I assign them at constructing time, and
give them an accessor.
- Using the #{} interpolation mechanism is way more legible than the
concatenation with xxx.to_s (BTW, inspect returns a string, no need
for to_s).
- Puts returns nil, not the string passed ; puts test where your test
method itself is writing on the screen is useless.
- If you want to convert your object to a string (for instance for
puts), all you need to do is define a to_s method.

Oh, and last : you should _really_ pay attention to the formatting of
your code...

class Roll
def Roll.roll(base, range)
base+rand(range)
end
end

class Stats
attr_reader :power, :speed, :smarts
def initialize()
@power = Roll.roll(10,8)
@speed = Roll.roll(10,8)
@smarts = Roll.roll(10,8)
end
end

class Attribs < Stats
def acc
(@power.to_f + (@speed.to_f / @smarts.to_f)).round
end

def health
(@power.to_f * (@smarts.to_f / @speed.to_f)).round
end
end

class Npc < Attribs
def initialize(name)
@name = name
super()
end
def job
'stuff'
end
def to_s
"#{@name} - pw#{power}, sp#{speed}, sm#{smarts}, ac#{acc}, "\
"he#{health} - #{job}"
end
end

class Test
def test
a = Roll.roll(10,8)
b = Stats.new
c = Attribs.new
d = Npc.new('Joe')

puts "++++++++++++++++A+++++++++++++++++++"
puts "a object is #{a.to_s}"
puts "a's method is called roll #{a.inspect}"
puts "++++++++++++++++A+++++++++++++++++++"
puts "================B==================="
puts "b is object #{b.inspect}"
puts "b methods are power = #{b.power}, "
puts "speed = #{b.speed}, "
puts "and finaly smarts = #{b.smarts.to_s}"
puts "================B=================="
puts "________________C__________________"
puts "now on to c"
puts "#{c.to_s} is the object name for c"
puts "c has all the methods of a and b plus its own"
puts " c has a power of #{c.power}"
puts " c has a speed of #{c.speed}"
puts " c has a smarts of #{c.smarts}"
puts " plus c has an Accuracy of #{c.acc}"
puts " plus c has a health of #{c.health}"
puts "________________C____________________"
puts "||||||||||||||||D||||||||||||||||||||"

puts 'D is the goal'
puts d.inspect
puts d

end
end
s=Test.new
s.test

Fred
 
A

August0866

Le 03 mars à 17:53, August0866 a écrit :

Thank you for taking time i appreciate the help,
Oh, and last : you should _really_ pay attention to the formatting of
your code...

being painfully new at this i don't know what you mean, what can i do
better format wise next time
 
F

F. Senault

Le 03 mars à 20:39, August0866 a écrit :
being painfully new at this i don't know what you mean, what can i do
better format wise next time

First and before all, indentation. Try to indent your statements by two
spaces, and to keep the code aligned (the end keyword should be at the
same column than the corresponding def or class keyword, etc).

After that, try to add some space around operators and such.

It makes code much more legible, which is important when you write code
that you'll have to understand later, and doubly so if you post it to a
public forum where _other_ people have to understand it...

CYA,

Fred
 
A

Arlen Cuss

[Note: parts of this message were removed to make it a legal post.]

Hi,

- I gave you the way to create a "Roll" objetct, but you don't really
need it ; what you need is an "helper function" that returns a
number. So, I made a module to contain it.

class Roll
def Roll.roll(base, range)
base+rand(range)
end
end

You could use a regular ol'module for that:

module Roll
def self.roll(base, range)
base + rand(range)
end
end

Arlen
 
F

F. Senault

Le 04 mars à 06:52, Arlen Cuss a écrit :
You could use a regular ol'module for that:

module Roll
def self.roll(base, range)
base + rand(range)
end
end

Indeed. I wanted to make that modification, but it seems I forgot it...
Thanks.

Fred
 
A

August0866

OK, 2 dumb questions What is the difference between a class and a
module and

What is wrong here, the logic or the syntax

<stub location =( class => Npc, def => job)>

def job
if
@power.to_f > 12 && @smarts.to_f > 14 && @speed.to_f > 14
@job = 'Adventurer'
elsif
@power.to_f > 14 and (@smarts.to_f <14 or @speed.to_f < 14)
@job = 'laborer'
elsif
@power.to_f < 14 and (@smarts.to_f > 14 and @speed.to_f > 14)
@job = 'coureror'
elsif
@power.to_f < 14 and (@smarts.to_f > 14 and @speed.to_f < 14)
@job='teacher'
else
@job = 'commoner'
end
end
</stub>

the result is sometimes joe is an adventurer otherwise nothing is
output
 
G

Gary Wright

OK, 2 dumb questions What is the difference between a class and a
module and

A module is a container for methods and a namespace
for constants.

A class is a module (Class inherits from Module) that
provides a framework for instantiating and initializing
instances as well as organizing method lookup through
the inheritance hierarchy.

If you think of classes as blueprints for creating
instances, then modules are like common sub-systems
that are reused in the blueprints of one or more
classes.

Gary Wright
 
T

Todd Benson

OK, 2 dumb questions What is the difference between a class and a
module and

What is wrong here, the logic or the syntax

<stub location =( class => Npc, def => job)>

def job
if
@power.to_f > 12 && @smarts.to_f > 14 && @speed.to_f > 14
@job = 'Adventurer'
elsif
@power.to_f > 14 and (@smarts.to_f <14 or @speed.to_f < 14)
@job = 'laborer'
elsif
@power.to_f < 14 and (@smarts.to_f > 14 and @speed.to_f > 14)
@job = 'coureror'
elsif
@power.to_f < 14 and (@smarts.to_f > 14 and @speed.to_f < 14)
@job='teacher'
else
@job = 'commoner'
end
end
</stub>

the result is sometimes joe is an adventurer otherwise nothing is
output

Not sure, but I think the logic. (@smarts.to_f < 14 or @speed.to_f <
14) will be true the same time (@smarts.to_f > 14 and @speed.to_f <
14) is true. Your decision set is not mutually exclusive because of
that first 12 (What if your 13?). Just a guess...

Todd
 
A

August0866

Not sure, but I think the logic. (@smarts.to_f < 14 or @speed.to_f <
14) will be true the same time (@smarts.to_f > 14 and @speed.to_f <
14) is true. Your decision set is not mutually exclusive because of
that first 12 (What if your 13?). Just a guess...

Todd

Ok, i'm looking for a true false answer to choose a job. For example
Joe - smarts = 15 power = 9 speed = 17

<pseudo code>

adventurer job needs power >= 12 and speed >=14 and smarts
= 14 ?joe an adventurer = false
laborer job needs power >= 12 but smarts and speed <=
12 ?joe laborer = false
mailman job needs power >=12 speed >=12 but smarts
=9 ?joe mailman = false
teacher job needs power <=14 speed <=14 but smarts
=14 ?joe teacher =
</pseudo code>

D'oh i see the problem..... i need to rethink the jobs
 
T

Todd Benson

Not sure, but I think the logic. (@smarts.to_f < 14 or @speed.to_f <
14) will be true the same time (@smarts.to_f > 14 and @speed.to_f <
14) is true. Your decision set is not mutually exclusive because of
that first 12 (What if your 13?). Just a guess...

One other thing, though. Maybe you want your code to cascade the
decision like that. In any case, your code works just fine on my
system, as long as I properly #rand my power, smarts, and speed :)
On 1.8.6, the if/elsif construct seems to correctly jump out. In
other words, if my power is 13, then it will will leave the loop with
the second result and never get to the fourth.

My distribution for 10_000 people for one run using rand(20 for each
attribute turns out to be...

adventurer: 211
laborer: 2260
courier: 416
teacher: 1261
commoner: 5852

...which doesn't look too bad.

Todd
 
A

August0866

One other thing, though. Maybe you want your code to cascade the
decision like that. In any case, your code works just fine on my
system, as long as I properly #rand my power, smarts, and speed :)
On 1.8.6, the if/elsif construct seems to correctly jump out. In
other words, if my power is 13, then it will will leave the loop with
the second result and never get to the fourth.

My distribution for 10_000 people for one run using rand(20 for each
attribute turns out to be...

adventurer: 211
laborer: 2260
courier: 416
teacher: 1261
commoner: 5852

..which doesn't look too bad.

Todd

Thanks Todd,

how would i go about defining a job and its requirements and then
match the npc to the job

<pseudo>
job[[Adventurer,14,14,14],[Courier,14,10,14] .... ]

the numbers are the minimum stats for the job these jobs are actually
categories i am going to break them down to specific occupations
next


</pseudo>
 
T

Todd Benson

One other thing, though. Maybe you want your code to cascade the
decision like that. In any case, your code works just fine on my
system, as long as I properly #rand my power, smarts, and speed :)
On 1.8.6, the if/elsif construct seems to correctly jump out. In
other words, if my power is 13, then it will will leave the loop with
the second result and never get to the fourth.

My distribution for 10_000 people for one run using rand(20 for each
attribute turns out to be...

adventurer: 211
laborer: 2260
courier: 416
teacher: 1261
commoner: 5852

..which doesn't look too bad.

Todd

Thanks Todd,

how would i go about defining a job and its requirements and then
match the npc to the job

<pseudo>
job[[Adventurer,14,14,14],[Courier,14,10,14] .... ]

the numbers are the minimum stats for the job these jobs are actually
categories i am going to break them down to specific occupations
next

I'll make a couple assumptions here. I think you want to have minimum
requirements, and then have the job assignment go to the least
requirement. In other words, in your above pseudo, if I had stats
like [14,15,14], I would be an adventurer, and if I had stats
[10,14,14] I would fail to be either (but maybe something else).
Least common denominator?

I would approach it probably in an eccentric way. Most people would
suggest side by side iteration of Arrays (which, IIRC, was added as a
feature to Ruby 1.9). That is probably the best way to do it. I'm
kind of a set theory guy, though, so tend towards slower but
conceptually more sound (to me) methods.

I'd probably build a matrix of the person's stats and use that...


require 'matrix'
joblist = ['adventurer', 'courier']
attributes = ['power', 'smarts', 'speed']
n, j = attributes.length, joblist.length
a = [[14, 14, 14], [14, 10, 14]]
some_poor_guys_stats_copies = Array.new(j, Array.new(n) {rand(20) + 1})
s = Matrix[*some_poor_guys_stats_copies]
e = Matrix[*a]
poss = []
(s - e).to_a.each_with_index do |v, i|
poss << i if (v.select {|j| j >= 0}).length == n
end
p joblist[poss.min] rescue p "Commoner"

It's not even close to clean, but I like using Matrix for this kind of
thing instead of the side by side iterating.

I suppose it's way better to use a Hash, too, like so...

requirements = {
:adventurer => {
:power => 14,
:smarts => 14.
:speed => 14
}
:courier => {
:power => 14,
:smarts => 10,
:speed => 14
}

person = {
:power => rand(die_number),
:smarts => rand(die_number),
:speed => rand(die_number)
}

I'm pretty sure you can use the Hash.new block form to build these if
you wanted to.

I should mention also that many people frown upon using the rescue
word for conditional use (in other words, my code above is not good
for application use, but probably ok for a script).

Todd
 
T

Todd Benson

Least common denominator?

I should point out, too, that my use of #min only works if you want to
pick the first on the list that fits. Maybe what you really want are
_all_ the jobs that apply for a person.

Todd
 
A

August0866

I should point out, too, that my use of #min only works if you want to
pick the first on the list that fits. Maybe what you really want are
_all_ the jobs that apply for a person.

Todd

Wow Crunchy code. it will take ma awhile to decipher all the things
going on up there.

originally the idea was first match out. I think that approach may
not be where i end up in the end.

thanks again for the help
 
T

Todd Benson

Wow Crunchy code. it will take ma awhile to decipher all the things
going on up there.

originally the idea was first match out. I think that approach may
not be where i end up in the end.

thanks again for the help

With comments...

require 'matrix'
#need this for Matrix class
joblist = ['adventurer', 'courier']
attributes = ['power', 'smarts', 'speed']
n, j = attributes.length, joblist.length
a = [[14, 14, 14], [14, 10, 14]]
#cheating here, need Hash really
some_poor_guys_stats_copies = Array.new(j, Array.new(n) {rand(20) + 1})
#an array of arrays to be a matrix
s = Matrix[*some_poor_guys_stats_copies]
#make the requirements Matrix
#using e for "employment", bad choice
e = Matrix[*a]
poss = []
#using poss for possibilities, bad choice
(s - e).to_a.each_with_index do |v, i|
poss << i if (v.select {|j| j >= 0}).length == n
end
p joblist[poss.min] rescue p "Commoner"


Okay, the key here is:

I have two matrices of same dimensions. I take the guys stats,
subtract the requirements, and remove anything that is negative in
each ability check.

I'm not certain at the moment how I would clean that up for production
use, but I have a few ideas. The only dodgy part of the code
(discounting the variable names), IMHO, is the a = [[14, 14, 14], [14,
10, 14]] part. Not because of the logic, but because of the fact
we're depending on the order of the array called "a". Like, what if
somebody changes the attributes array? A Hash object would fit better
here even if it requires more code.

hth,
Todd
 
M

Marc Heiler

it will take me awhile to decipher all the things going on up there.

I recommend using

require 'pp'


and then

pp your_object

like

pp joe


Also, my recommendation would be to stay as simple as possible, and from
this
point onwards (if things work) add complexity/more features.
I once wrote a game where I added features and features, but eventually
it
all became kinda big and complicated and I stopped continuing on it. :(

(And I still have a very flexible MUD engine on my todo list, but this
takes looong :D )
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,285
Messages
2,571,416
Members
48,107
Latest member
AmeliaAmad

Latest Threads

Top