Alternate to case; generating a list of sub-classes

The below uses pseudo-random number generation to populate an array
with various monsters, all inherit from Creature. Can a list of
classes which inherit from Creature be generated automagically? There
must be a better technique to fill the array then the case
statement…

C:\code>
C:\code>
C:\code>type Driver.rb
require ‘ArrayOfCreatures’

require ‘Creature’
require ‘AssistantViceTentacleAndOmbudsman’
require ‘Dragon’
require ‘DwarvenAngel’
require ‘TeethDeer’

puts “\nquantity of creatures:”
numOfCreatures = gets.chomp.to_i

someCreatures = ArrayOfCreatures.new

0.upto(numOfCreatures) do |i|

    creatureType = Kernel.rand(4)

    case creatureType
    when 0
            someCreatures[i]=AssistantViceTentacleAndOmbudsman.new
    when 1
            someCreatures[i]=Dragon.new
    when 2
            someCreatures[i]=DwarvenAngel.new
    when 3
            someCreatures[i]=TeethDeer.new
    end

end

someCreatures.toString

C:\code>
C:\code>

thanks,

Thufir

Hi –

On Thu, 8 Nov 2007, Thufir wrote:

require ‘ArrayOfCreatures’
numOfCreatures = gets.chomp.to_i
when 0
someCreatures.toString
Here’s one possibility (untested):

creatures = ArrayOfCreatures.new
creature_classes = [AssistantViceTentacleAndOmbudsman, Dragon,
DwarvenAngel, TeethDeer]

puts “\nquantity of creatures:”
num_of_creatures = gets.to_i

num_of_creatures.times do |i|
creatures[i] = creature_classes[rand(4)].new
end

David

Thufir wrote:

The below uses pseudo-random number generation to populate an array
with various monsters, all inherit from Creature. Can a list of
classes which inherit from Creature be generated automagically?

Perhaps:

class Creature
@creature_classes = []

hook to note when a class inherits

def self.inherited(klass)
@creature_classes << klass
end

generate a random creature from among known subclasses

def self.random_creature
@creature_classes[ rand(@creature_classes.length) ].new
end
end

hth
alex

On Nov 7, 2007, at 4:57 PM, Thufir wrote:

The below uses pseudo-random number generation to populate an array
with various monsters, all inherit from Creature. Can a list of
classes which inherit from Creature be generated automagically? There
must be a better technique to fill the array then the case
statement…

cfp: ~> cat a.rb

class Creature
Children = []

def self.inherited other
super
ensure
Children << other
end
end

Creature::List.sort_by{ rand }

a @ http://codeforpeople.com/

On Nov 7, 4:15 pm, Alex F. [email protected] wrote:

def self.inherited(klass)
@creature_classes << klass
end
[…]

Aha, I’ve been trying to figure out what a “hook” meant! :slight_smile:

thanks,

Thufir

On Nov 7, 5:16 pm, “ara.t.howard” [email protected] wrote:

cfp: ~> cat a.rb

class Creature
Children = []

[snip]

end

As an off-topic aside, I really like what you’ve done here. Normally I
do things like this:

class Foo
@all = []
class << self
attr_reader :all
end
def initialize
self.class.all << self
end
end

…but I’ve now seen the light how a constant scoped to the class can
make life far simpler.

class Foo
ALL = []
def initialize
ALL << self
end
end

There’s even some interesting benefits to the scoping, like:

By inheriting the superclass’s initialize,

Bar1 instances get put into Foo::ALL

class Bar1 < Foo; end

But I can totally branch on my own without worrying about

any class variable sort of nonsense

class Bar2 < Foo
ALL = [] # separate from Foo::ALL
def initialize
ALL << self
end
end

Thanks for that, Ara!

Phrogz wrote:

Bar1 instances get put into Foo::ALL

Thanks for that, Ara!

Careful though, constant scoping is not dynamic:

class Foo
def self.show_all
p ALL
end
end

3.times {Foo.new}
Foo.show_all # [#Foo:0x2ae5e8c, #Foo:0x2ae5e78, #Foo:0x2ae5e64]

3.times {Bar2.new}
Bar2.show_all # [#Foo:0x2ae5e8c, #Foo:0x2ae5e78, #Foo:0x2ae5e64]

Of course, you can get dynamic scoping, it’s just easy to forget:

class Foo
def self.show_all
p self::ALL
end
end

On Nov 8, 2007, at 6:08 AM, Robert K. wrote:

class Dice < Bar
use.inject do |as, often| as.you_can - without end

http://drawohara.tumblr.com/post/18708641

:wink:

a @ http://codeforpeople.com/

2007/11/8, Thufir [email protected]:

The below uses pseudo-random number generation to populate an array
with various monsters, all inherit from Creature. Can a list of
classes which inherit from Creature be generated automagically? There
must be a better technique to fill the array then the case
statement…

I usually do this when I want to also recursively track subclasses:

module Hierarchy
def inherited(cl)
superclass.instance_eval { inherited cl }
(@children ||= []) << cl
cl.extend Hierarchy
end

attr_reader :children
end

class Foo
extend Hierarchy
end

class Bar < Foo
end

class Dice < Bar
end

p Bar.children
p Foo.children

Cheers

robert

On Nov 8, 10:13 am, Sebastian H.
[…]

Assuming that ArrayOfCreatures.new works like Array.new this can be simplified
to:
creatures = ArrayOfCreatures.new(num_of_creatures) do |i|
creature_classes[rand(4)].new
end

It took me a few reads to appreciate, but I like that alot :slight_smile:

-Thufir

David A. Black wrote:

creatures = ArrayOfCreatures.new
[…]
num_of_creatures.times do |i|
creatures[i] = creature_classes[rand(4)].new
end

Assuming that ArrayOfCreatures.new works like Array.new this can be
simplified
to:
creatures = ArrayOfCreatures.new(num_of_creatures) do |i|
creature_classes[rand(4)].new
end