# Optimizing for Newbies

Since I've gotten the go-ahead from Christer, here's a little newbie app
I just wrote and am looking for advice on how to better write:

=begin
=Author & Maintainer
=Description
arschar.rb guides the user through the process of rolling attributes
for
an Ars Magica character using v4 rules.
reserved.
Do as you like with it, as long as you don't claim to have written it.
And, there is certainly no warranty hereabout, express or implied.
=Version
arschar.rb 0.1 2005/Nov/30
=end
system("clear")
#BEGINCLASSDEFS
#Classname: Die
#Purpose: Provide arbitrarily-sided die functionality
#Notes: Only 6-sided dice display from 1, all others from 0
class Die
def initialize(sides)
@sides = sides
roll
if @sides == 6
@currentFace += 1
end
@currentFace
end
def roll
@currentFace = rand(@sides)
@currentFace
end
def showing
@currentFace
end
end
#ENDCLASSDEFS
#BEGINMETHODDEFS
#Roll 2 10-sided die and subtract 2nd from 1st to determine pair total
def rollAttributePair
rolls = Array.new
rolls.push(Die.new(10).roll)
rolls.push(Die.new(10).roll)
if (rolls[0] == 0) or (rolls[1] == 0)
total = 0
else
total = (rolls[0] - rolls[1])
end
end
#Obtain user allocation of scores and validate against AM rules
def getScore(total,attr)
print " Enter score for " + attr + ": "
userInput = gets.chomp.strip.to_i
if (userInput < 0) and (total > 0)
puts " You rolled positively; no negatives for this pair."
elsif (userInput > 0) and (total < 0)
puts " You rolled negatively; no positives for this pair."
elsif userInput > 4
puts " Rolled scores cannot be higher than 4."
elsif userInput < -4
puts " Rolled scores cannot be lower than 4."
else
end
end
return userInput
end
#ENDMETHODDEFS
#BEGINVARIABLEDEFS
#Init Array to hold shortnames of the 8 Attributes
attributeShortNames = Array.new
attributeShortNames[0,7]=["Int", "Per", "Str", "Sta", "Pre", "Com",
"Dex", "Qik"]
#Init Array to hold fullnames of the 8 Attributes
attributeFullNames = Array.new
attributeFullNames[0,7]=["Intelligence","Perception","Strength","Stamina","Presence","Communication","Dexterity","Quickness"]
#Init Hash to hold shortname/fullname pairs for the 8 Attributes
attributeNameMap = Hash.new
count = 0
attributeShortNames.each do |name|
attributeNameMap[name]= attributeFullNames[count]
count += 1
end
#Init Hash to hold name/value pairs for character Attributes
#charAttributes = {'Int' => 0, 'Per' => 0, 'Str' => 0, 'Sta' => 0, 'Pre'
=> 0, 'Com' => 0, 'Dex' => 0, 'Qik' => 0}
charAttributes = Hash.new(0)
attributeShortNames.each do |name|
charAttributes[name]= 0
end
#ENDVARIABLEDEFS
#BEGINMAIN
x = 0
y = 1
while (x <= 6) and (y <= 7)
attr0 = attributeShortNames[x]
attr1 = attributeShortNames[y]
full0 = attributeNameMap[attr0]
full1 = attributeNameMap[attr1]
puts "Now rolling for the " + full0 + " and " + full1 + " pair..."
total = rollAttributePair
if total == 0
puts " You rolled a zero for this pair. Both " + attr0 + " and " +
attr1 + " will be set to zero."
charAttributes[attr0]= 0
charAttributes[attr1]= 0
elsif total > 0
puts " You rolled a +" + total.to_s + " for this pair."
puts " Please choose scores which are >= 0, <= 4, and which add up
to " + total.to_s + "."
temp = Array.new
val0 = getScore(total,attr0)
val1 = getScore(total,attr1)
if (val0 + val1) == total
charAttributes[attr0]= val0
charAttributes[attr1]= val1
else
puts " Your scores add up to more than " + total.to_s + ".
end
end
else
puts " You rolled a " + total.to_s + " for this pair."
puts " Please, choose scores which are <= 0, >= -4, and which add
up to " + total.to_s + "."
temp = Array.new
val0 = getScore(total,attr0)
val1 = getScore(total,attr1)
if (val0 + val1) == total
charAttributes[attr0]= val0
charAttributes[attr1]= val1
else
puts " Your scores add up to more than " + total.to_s + ".
end
end
end
x += 2
y += 2
puts
end
#Print charAttributes
attributeShortNames.each do |attr|
puts attr.to_s + ": " + charAttributes[attr].to_s
end
#Pause for user input before exit
puts
print "Press Enter to exit..."
gets
#ENDMAIN

-Matthew

···

--
Posted via http://www.ruby-forum.com/.

[snip]

def rollAttributePair
rolls = Array.new
rolls.push(Die.new(10).roll)
rolls.push(Die.new(10).roll)
if (rolls[0] == 0) or (rolls[1] == 0)
total = 0
else
total = (rolls[0] - rolls[1])
end
end

maybe write it like this (untested)

def roll_attribute_pair
r1 = Die.new(10).roll
r2 = Die.new(10).roll
return 0 if (r1 == 0) or (r2 == 0)
(r1 - r2)
end

···

Since I've gotten the go-ahead from Christer, here's a little newbie app
I just wrote and am looking for advice on how to better write:

--
Simon Strandgaard

Since I've gotten the go-ahead from Christer, here's a little newbie
app I just wrote and am looking for advice on how to better write:

=begin =Author & Maintainer Matthew A. Feadler http://matthew.feadler.com =Description arschar.rb guides the user
through the process of rolling attributes for an Ars Magica character
using v4 rules.

Jeeez, I haven't seen Ars Magica in a long, long while. Will probably
look at the code, but I just had to admire the fact that it still exists
(I've got almost all of 3rd Eds).
I always loved it (a lot more than D&D a bit less then CoC )
This brings back memories.
V.-

···

____________________________________________________________________
http://www.freemail.gr - äùñåÜí õðçñåóßá çëåêôñïíéêïý ôá÷õäñïìåßïõ.
http://www.freemail.gr - free email service for the Greek-speaking.

#Init Array to hold shortnames of the 8 Attributes
attributeShortNames = Array.new
attributeShortNames[0,7]=["Int", "Per", "Str", "Sta", "Pre", "Com",
"Dex", "Qik"]

can simplified:

attributeShortNames=["Int", "Per", "Str", "Sta", "Pre", "Com", "Dex", "Qik"]

which again can be even more simpified:

attributeShortNames=%w(Int Per Str Sta Pre Com Dex Qik)

#Init Hash to hold shortname/fullname pairs for the 8 Attributes
attributeNameMap = Hash.new
count = 0
attributeShortNames.each do |name|
attributeNameMap[name]= attributeFullNames[count]
count += 1
end

can be simplified:

attributeNameMap = Hash[*(attributeShortNames.zip(attributeFullNames).flatten)]

···

On 12/1/05, Simon Strandgaard <neoneye@gmail.com> wrote:

> Since I've gotten the go-ahead from Christer, here's a little newbie app
> I just wrote and am looking for advice on how to better write:
[snip]

--
Simon Strandgaard

Simon Strandgaard wrote:

Since I've gotten the go-ahead from Christer, here's a little newbie app
I just wrote and am looking for advice on how to better write:

[snip]

def rollAttributePair
rolls = Array.new
rolls.push(Die.new(10).roll)
if (rolls[0] == 0) or (rolls[1] == 0)
total = 0
else
total = (rolls[0] - rolls[1])
end
end

maybe write it like this (untested)

def roll_attribute_pair
r1 = Die.new(10).roll
r2 = Die.new(10).roll
return 0 if (r1 == 0) or (r2 == 0)
(r1 - r2)
end

--
Simon Strandgaard

or if you like your Array:

def rollAttributePair
rolls = Array.new(2){Die.new(10).roll}
return 0 if rolls.any?{|r|r.zero?}
rolls[0] - rolls[1]
end

you may also look at 'Struct' for the charAttributes
(may just be better suited than a hash)

cheers

Simon

···

damphyr wrote:

Jeeez, I haven't seen Ars Magica in a long, long while. Will probably
look at the code, but I just had to admire the fact that it still exists
(I've got almost all of 3rd Eds).
I always loved it (a lot more than D&D a bit less then CoC )
This brings back memories.

In reverse order:

<chuckles> Glad I could spark the recollection, Damphyr. It certainly
is my favorite system.

Simon, I was unfamiliar with 'Struct' before your mention. Loking
briefly here: http://www.rubycentral.com/book/ref_c_struct.html, it
doesn't seem there's a way to establish relationships between the
elements of the 'Struct', which I think defeats my purpose. Please
enlighten me if I've misunderstood. Also, these

rolls = Array.new(2){Die.new(10).roll}
return 0 if rolls.any?{|r|r.zero?}

are very cool. I was originally under the impression that the first
line would create a two-element array *with the same Die instance in
each element*, which would, of course, always result in a 0 total
further down the code. I've tested it now, and realize that each
element contains a seperate Die instance. VERY handy knowledge. The
second line is an example of Ruby's lovely ? notation, which I've
noticed all over, but have yet to really grasp/master. Thanks for this
example.

Neoneye, I had never seen the %w in this

attributeShortNames=%w(Int Per Str Sta Pre Com Dex Qik)

before, but looking here: http://www.rubycentral.com/book/intro.html I
found it. Exactly the sort of Ruby shorthand I'm looking for. Now this

Hash[*(attributeShortNames.zip(attributeFullNames).flatten)]

doesn't give much for the zip method, so it's still a bit magical to me.
Any references to recommend? As for the flatten method, looking here:
http://www.rubycentral.com/book/ref_c_array.html, I see how it works.
Very lovely.

Thanks tremendously, all. You've given me much food for thought and
practice. But don't stop advising on my account.

-Matthew

···

--
Posted via http://www.ruby-forum.com/.

Also, these

rolls = Array.new(2){Die.new(10).roll}
return 0 if rolls.any?{|r|r.zero?}

are very cool. I was originally under the impression that the first
line would create a two-element array *with the same Die instance in
each element*, which would, of course, always result in a 0 total
further down the code.

Nope. The block is executed to create each element.

The second line is an example of Ruby's lovely ? notation, which I've
noticed all over, but have yet to really grasp/master. Thanks for this
example.

By convention, a method ending in a ? returns a true/false answer to the question implied by the call.

doesn't give much for the zip method, so it's still a bit magical to me.
Any references to recommend?

If you have Ruby's documentation installed just feed your command-line:

ri Array.zip

Or you can look it up here:

James Edward Gray II

···

On Dec 2, 2005, at 12:24 PM, Matthew Feadler wrote:

This isn't meant as 'the' solution of your problem,
its just a bit more like it would look like if i had
to write the same program (i was bored, obviously):

···

---------------------------------------------------------------------
require 'enumerator'

\$stdout.sync = true
system("clear")

#Roll 2 10-sided die and subtract 2nd from 1st to determine pair total
def rollAttributePair
rolls = Array.new(2){rand(10)}
return 0 if rolls.any?{|r|r.zero?}
rolls[0] - rolls[1]
end

#Obtain user allocation of scores and validate against AM rules
def getScore(total,attr)
loop do
print " Enter score for " + attr + ": "
userInput = gets.chomp.strip.to_i
if (userInput < 0) && (total > 0)
puts " You rolled positively; no negatives for this pair."
elsif (userInput > 0) && (total < 0)
puts " You rolled negatively; no positives for this pair."
elsif userInput > 4
puts " Rolled scores cannot be higher than 4."
elsif userInput < -4
puts " Rolled scores cannot be lower than 4."
else
return userInput
end
end
end

Attribute = Struct.new(:long, :short)
long = %w(Intelligence Perception Strength Stamina Presence Communication Dexterity Quickness)
short = %w(Int Per Str Sta Pre Com Dex Qik)
attributes = long.zip(short).map{|a| Attribute.new *a}

#Init Hash to hold name/value pairs for character Attributes
charAttributes = Hash.new(0)

attributes.each_slice(2) do |attr|
puts "Now rolling for the #{attr[0].long} and #{attr[1].long} pair..."
total = rollAttributePair
if total == 0
puts " You rolled a zero for this pair. Both #{attr[0].short} and #{attr[1].short} will be set to zero."
attr.each{|a| charAttributes[a] = 0}
else
puts " You rolled a #{total} for this pair."
if total > 0
puts " Please choose scores which are >= 0, <= 4, and which add up to #{total}."
else
puts " Please, choose scores which are <= 0, >= -4, and which add up to #{total}."
end

loop do
attr.each{|a| charAttributes[a] = getScore(total, a.short)}
break if (charAttributes[attr[0]] + charAttributes[attr[1]]) == total
end
end
puts
end

#Print charAttributes
attributes.each{|attr| puts attr.long + ": #{charAttributes[attr]}"}

#Pause for user input before exit
print "\nPress Enter to exit..."
gets
---------------------------------------------------------------------

cheers

Simon

bbazzarrakk wrote:

rolls = Array.new(2){Die.new(10).roll}

Nope. The block is executed to create each element.

This highlights exactly what I wasn't grasping about that line
previously: the {} delimits a block. I was (wrongly, of course)
equating it to

rolls = Array.new(2,Die.new)

Now I get it. Thanks!

If you have Ruby's documentation installed just feed your command-line:

ri Array.zip

Or you can look it up here:

Both excellent reference sources of which I was not aware. Much
appreciated. Now the zip method makes perfect sense.

-Matthew

···

--
Posted via http://www.ruby-forum.com/.