[QUIZ] Story Generator (#96)

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.rubyquiz.com/

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone
on Ruby Talk follow the discussion. Please reply to the original quiz message,
if you can.

···

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

by Morton Goldberg

[ Editor's Note:

I realize we've done a similar quiz in the past, but read on and give this one a
chance. It has a pretty different spin than Markov Chains.

--JEG2 ]

The Dwemthy's Array RPG example in Why's (Poignant) Guide to Ruby[1] was my
introduction to Ruby metaprogramming. While it's an excellent introduction to
metaprogramming, it's not much of an RPG, so I thought I'd have a go at
improving it. But a funny thing happened when I started coding: the RPG turned
in a story generator. Here are a couple of stories generated by my current
version.

The first story is fairly typical of the shorter ones. The rabbit gets past the
BogusFox only to fall to the Jabberwocky.

  A BogusFox emerges from the gloom and cries out,"Hail, Rabbit,
  prepare to die!"
  "I fear you not, BogusFox!"
  Rabbit [25] and BogusFox [50] fight.
  Rabbit attacks BogusFox with magick sword.
  Fighting lowers BogusFox life force by 9.
  BogusFox suffered a minor wound.
  BogusFox swings his axe.
  Fighting lowers Rabbit life force by 7.
  Rabbit was wounded.
  Rabbit [18] and BogusFox [41] fight.
  Rabbit attacks BogusFox with magick sword.
  Fighting lowers BogusFox life force by 43.
  BogusFox dies.
  Eating magick lettuce adds 7 to Rabbit life force.
  A Jabberwocky emerges from the gloom and cries out,"Ah, a tasty Rabbit!"
  "I fear you not, Jabberwocky!"
  Rabbit [25] and Jabberwocky [100] fight.
  Rabbit attacks Jabberwocky with magick sword.
  Fighting lowers Jabberwocky life force by 63.
  Jabberwocky was seriously wounded but carries on.
  Jabberwocky attacks Rabbit with teeth and claws.
  Fighting lowers Rabbit life force by 33.
  Rabbit dies.
  It's over. It's all over.

The second story is an example proving that low probability events do occur. The
rabbit actually wins! And what's truly amazing is that he kills every monster
with a single stroke of his magick sword. Talk about luck!

  A BogusFox emerges from the gloom and cries out,"Hail, Rabbit,
  prepare to die!"
  "I fear you not, BogusFox!"
  Rabbit [25] and BogusFox [50] fight.
  Rabbit attacks BogusFox with magick sword.
  Fighting lowers BogusFox life force by 59.
  BogusFox dies.
  Eating magick lettuce adds 37 to Rabbit life force.
  A Jabberwocky emerges from the gloom and cries out,"Ah, a tasty Rabbit!"
  "I fear you not, Jabberwocky!"
  Rabbit [62] and Jabberwocky [100] fight.
  Rabbit attacks Jabberwocky with magick sword.
  Fighting lowers Jabberwocky life force by 155.
  Jabberwocky dies.
  Eating magick lettuce adds 46 to Rabbit life force.
  A DemonAngel emerges from the gloom and cries out,"Rabbit, I will
  eat your soul!"
  "I fear you not, DemonAngel!"
  Rabbit [108] and DemonAngel [540] fight.
  Rabbit attacks DemonAngel with magick sword.
  Fighting lowers DemonAngel life force by 600.
  DemonAngel dies.
  Eating magick lettuce adds 20 to Rabbit life force.
  A ViciousGreenFungus emerges from the gloom and cries out,"No Rabbit
  has ever left my presence alive."
  "I fear you not, ViciousGreenFungus!"
  Rabbit [128] and ViciousGreenFungus [320] fight.
  Rabbit attacks ViciousGreenFungus with magick sword.
  Fighting lowers ViciousGreenFungus life force by 390.
  ViciousGreenFungus dies.
  Eating magick lettuce adds 35 to Rabbit life force.
  A Dragon emerges from the gloom and cries out,"A brave Rabbit burns
  just as well as a timid one."
  "I fear you not, Dragon!"
  Rabbit [163] and Dragon [1340] fight.
  Rabbit attacks Dragon with magick sword.
  Fighting lowers Dragon life force by 1436.
  Dragon dies.
  Eating magick lettuce adds 44 to Rabbit life force.
  It's over. It's all over.

The secret of the rabbit's magick sword will be revealed when my story generated
is posted.

"It's hardly literature," you say. I agree. "It's needs more work," you say.
Again, I agree. But it does tell a story. Don't you root for the rabbit? Don't
you feel just a little sad when he's killed (as he almost always is)? And isn't
it wonderful when, once in a hundred runs or so, he actually kills the dragon
and completes his quest?

Story generators can be a lot of fun. Even addictive. It's fascinating to create
your own world. And they are completely open-ended. You can always find ways to
tweak them, either to improve the readability of the output or to improve the
plot.

In this quiz, I ask you to write your own story generator. You can start with
Dwemthy's Array, as I did, or invent your own characters and plot. The only
requirement is that the generator must produce a different story each time it is
run.

  1: http://qa.poignantguide.net/chapter-6.html#section3

The Quiz ittself might be too much work to do for me, but reading it was
already an enourmous pleasure.
What a Funny, Great Idea!

Robert

···

On 9/29/06, Ruby Quiz <james@grayproductions.net> wrote:

The three rules of Ruby Quiz:

<snip>

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

I believe the 48 hours are up, so here's my solution:
http://www.io.com/~jimm/rubyquiz/quiz96/

I decided to modify my solution to the Lisp Game quiz so it plays
itself. The output is a random "story" that's all plot and no
characterization.

Aside from a small tweak to one method in game.rb, all the
"story-telling" code can be found in rads.rb. The general approach I
took was to, for each turn, find all legal verbs and construct correct
game input. Look for the comment "new game-playing methods". The one
tweak to game.rb suppresses error messages when checking for the
legality of certain moves.

The game plays itself to a conclusion in approximately five to ten
seconds on my laptop. If I pipe all output to a file instead of the
terminal, it completes in under a second.

  * rads.rb the engine, with modified "story-telling" code
  * game.rb the game description and custom verbs

To run this game, download both files and execute game.rb. See the
notes for my original game solution for details.

Jim

···

--
Jim Menard, jimm@io.com, jim.menard@gmail.com
http://www.io.com/~jimm

Little Red-Cap revisited

Once upon a time little red-cap opened the stomach of the huntsman. The huntsman
thought to himself "what a tender young creature". Soon he gave a pair of
scissors to grandmother. Little red-cap went into the wood. And so the huntsman
swallowed up the wolf. Grandmother gave a piece of cake to the wolf. Mother ran
straight to grandmother's house. And so grandmother was on her guard although
the wolf was not afraid of grandmother until mother swallowed up the wolf.
Grandmother was not afraid of herself. The wolf gave a pair of scissors to the
huntsman. Little red-cap fell asleep. She said: "oh, the huntsman, what big ears
you have".
The End.

### stories.rb

require 'enumerator'

class Base
   def self.constructor *args
     attr_accessor(*args)
     define_method :initialize do |*values|
       (0...args.size).each do |i|
         self.instance_variable_set("@#{args[i]}", values[i])
       end
     end
   end
   def to_s
     @name
   end
end

class Character < Base
   constructor :name, :gender
end

class Action < Base
   constructor :name, :objects_or_types
end

class Item < Base
   constructor :name
end

class Place < Base
   constructor :name
end

class PronounBase < Base
   constructor :gender
   class << self
     attr_accessor :cases
   end
   def to_s
     cases = self.class.cases
     @gender == :female ? cases[0] : cases[1]
   end
end

class PossessiveAdjective < PronounBase
   self.cases = ['her', 'his']
end

class Pronoun < PronounBase
   self.cases = ['she', 'he']
end

class ReflexivePronoun < PronounBase
   self.cases = ['herself', 'himself']
end

class Bridge < Base
   constructor :name
end

class Entities
   def initialize klass
     @entities = []
     @klass = klass
     yield(self)
   end
   def create *args
     @entities << @klass.new(*args)
   end
   def pick
     @entities[rand(@entities.size)]
   end
end

CAST = Entities.new(Character) do |c|
   c.create 'little red-cap', :female
   c.create 'mother', :female
   c.create 'grandmother', :female
   c.create 'the wolf', :male
   c.create 'the huntsman', :male
end

ACTIONS = Entities.new(Action) do |a|
   a.create 'met', [Character]
   a.create 'gave', [Item, 'to', Character]
   a.create 'took', [Item]
   a.create 'ate', [Item]
   a.create 'saw', [Item]
   a.create 'told', [Character, 'to be careful']
   a.create 'lived in', [Place]
   a.create 'lied in', [Place]
   a.create 'went into', [Place]
   a.create 'ran straight to', [Place]
   a.create 'raised', [PossessiveAdjective, 'eyes']
   a.create 'was on', [PossessiveAdjective, 'guard']
   a.create 'thought to', [ReflexivePronoun, '"what a tender young creature"']
   a.create 'swallowed up', [Character]
   a.create 'opened the stomach of', [Character]
   a.create 'looked very strange', []
   a.create 'was delighted', []
   a.create 'fell asleep', []
   a.create 'snored very loud', []
   a.create 'said: "oh,', [Character, ', what big ears you have"']
   a.create 'was not afraid of', [Character]
   a.create 'walked for a short time by the side of', [Character]
   a.create 'got deeper and deeper into', [Place]
end

ITEMS = Entities.new(Item) do |i|
   i.create 'a piece of cake'
   i.create 'a bottle of wine'
   i.create 'pretty flowers'
   i.create 'a pair of scissors'
end

PLACES = Entities.new(Place) do |p|
   p.create 'the wood'
   p.create 'the village'
   p.create 'bed'
   p.create "grandmother's house"
   p.create 'the room'
end

BRIDGES = Entities.new(Bridge) do |b|
   5.times{b.create '.'}
   b.create ', because'
   b.create ', while'
   b.create '. Later'
   b.create '. Then'
   b.create '. The next day'
   b.create '. And so'
   b.create ', but'
   b.create '. Soon'
   b.create ', and'
   b.create ' until'
   b.create ' although'
end

ALL = { Character => CAST, Action => ACTIONS, Place => PLACES, Item => ITEMS }

class Sentence
   attr_accessor :subject
   def initialize
     @subject = CAST.pick
     @verb = ACTIONS.pick
     @objects = []
     @verb.objects_or_types.each do |obj_or_type|
       if String === obj_or_type
         @objects << obj_or_type
       else
         if obj_or_type == PossessiveAdjective or obj_or_type == ReflexivePronoun
           @objects << obj_or_type.new(@subject.gender)
         else
           thingy = ALL[obj_or_type].pick
           thingy = ReflexivePronoun.new(thingy.gender) if thingy == @subject
           @objects << thingy
         end
       end
     end
   end

   def to_s
     [@subject, @verb, @objects].flatten.map{|e| e.to_s}.join(' ')
   end
end

class Story
   def initialize
     @sentences = []
     1.upto(rand(10)+10) do
       @sentences << Sentence.new
     end
     combine_subjects
   end

   # When the last sentence had the same subject, replace subject with 'he' or 'she':
   def combine_subjects
     @sentences.each_cons(2) do |s1, s2|
       if s1.subject == s2.subject
         s2.subject = Pronoun.new(s1.subject.gender)
       end
     end
   end

   # Combine sentences to a story:
   def to_s
     text = 'Once upon a time ' + @sentences[0].to_s
     @sentences[1..-1].each do |sentence|
       bridge = BRIDGES.pick.to_s
       text += bridge + ' ' + (bridge[-1,1] == '.' ? sentence.to_s.capitalize : sentence.to_s)
     end
     text.gsub!(/ ,/, ',') # a little clean-up
     text.gsub!(/(.{70,80}) /, "\\1\n")
     text + ".\nThe End.\n"
   end
end

puts Story.new.to_s

There's one problem, as the perpetrator of this quiz, I'm not sure if I should post my solution. But if I don't, the secret will be forever lost :slight_smile: What to do?

Also, I've built another story generator using very simple code. I did this because JEG II pointed out that my original solution was a bit complex and took me more time than one should spend on a Ruby Quiz. So I set myself the task of seeing what I could do with code that I wrote in less than an hour. The results are much more rigid than what the original story generator produces. Although the code didn't take long to write, I have to admit I've been working for three hours on the story template and the phase dictionaries and still haven't finished. To give an idea of the flavor of this new generator I include two (incomplete) stories it generated:

1. The Three Bears Go To Dwemthy's Array

One day Papa Bear asked, "Vacation starts next month. Where shall we go?"

Papa Bear wanted to go to Dwemthy's Array. Mama Bear wanted to go to Corporate USA. But Baby Bear got all exited. "I want to go to Dwemthy's Array! I want to go to Dwemthy's Array! I want to go to Dwemthy's Array!"

In the end, they agreed to go to Dwemthy's Array.

Although it seemed nearly forever to Baby Bear, next month eventually arrived. The Bears piled into their pick-up truck and off they went. Along the way they stop twice to let the little one use a rest room.

They stayed four days. While they were there they saw a Jabberwocky, a Vicious Green Fungus, a Bogus Fox, a Rabbit. At the park's restaurants they had Dwemthy's pizza, Mama Dragnon's roast rabbit, jabberwocky steak. They enjoyed attractions such as Demon Twister, Monster-Go-Round, Dragon's Den. Mama Bear was shocked by the Demon Twister. Baby Bear especially liked the Bogus Fox.

On the way back they stopped at a ice cream store where they all had three-scoop sundaes.

Papa Bear thought <park_feature> was best. Mama Bear thought <park_feature> was best. But Baby Bear was certain that the Bogus Fox was really the best.

The end.

2. The Three Droids Go To Corporate USA

One day R2P2 asked, "Vacation starts next week. Where shall we go?"

R2P2 wanted to go to Corporate USA. R2M2 wanted to go to Corporate USA. But R2B2 got all exited. "I don't want to go to Corporate USA! I don't want to go to Corporate USA! I don't want to go to Corporate USA!"

In the end, they agreed to go to Corporate USA.

Although it seemed nearly forever to R2B2, next week eventually arrived. The Droids piled into their SUV and off they went. Along the way they stopped at a ice cream store where they all had three-scoop sundaes.

They stayed three days. While they were there they saw a Tax Accountant, a Marketing Manager, a Chief Executive Officer, a Stock Broker. At the park's restaurants they had Board Room Buffet (tm), outsourced curry, pizza. They enjoyed attractions such as Golden Parachute Drop, Chamber of Outsourcing Horrors, Takeover Museum. R2M2 was shocked by the Chamber of Outsourcing Horrors. R2B2 especially liked the Marketing Manager.

On the way back they made a wrong turn and got lost.

R2P2 thought <park_feature> was best. R2M2 thought <park_feature> was best. But R2B2 was certain that the Marketing Manager was really the best.

The end.

My second question: should I post the new generator?

Regards, Morton

···

On Sep 29, 2006, at 9:02 AM, Ruby Quiz wrote:

The secret of the rabbit's magick sword will be revealed when my story generated
is posted.

Here is my solution, which is based on Dwemthy's Array.

<code>
#! /usr/bin/ruby
# Author: Morton Goldberg

···

#
# Date: 2006-09-23
#
# Based on the Dwemthy's Array example in Chapter 6 of "why's (poignant)
# guide to ruby".

# This is the story of a rabbit that went on a quest to slay a dragon.
# But before he got to face the dragon, he had to kill a whole bunch
# of other montsters, each much stronger than he. How could a tiny, weak
# rabbit survive against this terrible arary of monsters? Well, he had
# a magick sword, magick lettuce, a few bombs, and -- most importantly --
# incredible good luck.

# Abstract class providing the basic behavior of all the creatures in the
# story.
class Creature

    # Get a metaclass for this class.
    def self.metaclass
       class << self; self; end
    end

    # Advanced metaprogramming code for nice, clean traits.
    def self.traits(*arr)
       return @traits if arr.empty?
       # Set up accessors for each variable
       attr_accessor(*arr)
       # Add a new class method to for each trait.
       arr.each do |a|
          metaclass.instance_eval do
             define_method(a) do |val|
                @traits ||= {}
                @traits[a] = val
             end
          end
       end
       # For each monster, the `initialize' method should use the default
       # number for each trait.
       class_eval do
          define_method(:initialize) do
             self.class.traits.each do |k,v|
                instance_variable_set("@#{k}", v)
             end
          end
       end
    end

    # Damage assessment after taking a hit during fight.
    def hit(damage)
       bonus = rand(magick)
       if bonus % 9 == 7
          @life += bonus
          puts "Protective spell adds #{bonus} to #{self} life force."
       end
       puts "Fighting lowers #{self} life force by #{damage}."
       case
       when damage < 1
          puts "#{self} wasn't touched!"
       when damage < 0.25 * life
          puts "#{self} suffered a minor wound."
       when damage < 0.5 * life
          puts "#{self} was wounded."
       when damage < 0.75 * life
          puts "#{self} was seriously wounded but carries on."
       when damage < life
          puts "#{self} was gravely wounded but survives."
       else
          puts "#{self} dies."
       end
       @life -= damage
    end

    # One participant's attack during one fight turn.
    def attack
       puts attack_description
       damage = rand(strength * life + weapon_force)
       foe.hit(damage)
    end

    # One fight (attack + counter-attack) in a battle.
    def fight
       if life <= 0
          puts "#{self} is too dead to fight."
       else
          puts "#{self} [#{life}] and #{foe} [#{foe.life}] fight."
          # Attack opponent.
          attack if foe.life > 0
          # Opponent's counter-attack.
          foe.attack if life > 0 && foe.life > 0
       end
       self
    end

    def to_s
       self.class.name
    end

    # Description of how an attack was made. Subclasses will often override
    # this.
    def attack_description
       "#{self} attacks #{foe} with #{weapon}."
    end

    # Creature default attributes are read-only.
    traits :life, :strength, :magick, :challenge, :weapon, :weapon_force
    # This trait is dynaminc -- don't give it a default value.
    traits :foe
end

# The monsters.

class BogusFox < Creature

    life 50
    strength 0.6
    magick 100
    weapon 'axe'
    weapon_force 20
    challenge "Hail, %s, prepare to die!"

    def attack_description
       "BogusFox " + ["swings", "strikes with"][rand(2)] + " his axe."
    end

end

class Jabberwocky < Creature

    life 100
    strength 0.8
    magick 100
    weapon 'teeth and claws'
    weapon_force 20
    challenge "Ah, a tasty %s!"

end

class DemonAngel < Creature

    life 540
    strength 0.2
    magick 200
    weapon 'black sword'
    weapon_force 20
    challenge "%s, I will eat your soul!"

    def attack_description
       "DemonAngel thrusts " + ["high", "low"][rand(2)] +
       " with her black sword."
    end

end

class ViciousGreenFungus < Creature

    life 320
    strength 0.8
    magick 300
    weapon 'acid spray'
    weapon_force 100
    challenge "No %s has ever left my presence alive."

end

class Dragon < Creature

    life 1340 # really tough hide
    strength 1.0 # big muscles
    magick 1066 # studied with Merlin
    weapon 'blast of flame' # fiery breath
    weapon_force 940
    challenge "A brave %s burns just as well as a timid one."

end

MONSTERS = [
    BogusFox.new,
    Jabberwocky.new,
    DemonAngel.new,
    ViciousGreenFungus.new,
    Dragon.new
].freeze

# The hero.
class Rabbit < Creature

    traits :bombs

    life 25 # no armor or shield
    strength 0.4 # not in great shape
    magick 50 # more than you might expect
    weapon 'boomerang'
    weapon_force 4 # can't handle heavy stuff
    challenge "I fear you not, %s!"
    bombs 3 # quantity

    # Little boomerang. Nearly useless.
    def ^
       self.weapon = Rabbit.weapon
       self.weapon_force = Rabbit.weapon_force
       fight
    end

    # Potent magick sword. Rabbit's Vorpal blade is powered by opponent's
    # life force -- a healthier opponent suffers more damage. The rabbit's
    # only chance? Well, he has some bombs.
    def /
       self.weapon = 'magick sword'
       self.weapon_force = magick + foe.life
       fight
    end

    # Bombs. Powerful, but rabbits don't have very many.
    def *
       if @bombs.zero?
          puts "Rabbit is out of bombs!"
          return
       end
       @bombs -= 1
       self.weapon = 'bomb'
       self.weapon_force = 1600
       fight
    end

    # Eating magick lettuce casts a spell that improves health.
    def %
       gain = 5 + rand(magick)
       puts "Eating magick lettuce adds #{gain} to Rabbit life force."
       @life += gain
    end

end

QUOTE = '"'

# The quest.
if $0 == __FILE__
    hero = Rabbit.new
    MONSTERS.each do |a_foe|
       hero.foe = a_foe
       a_foe.foe = hero
       cry = a_foe.challenge % hero
       puts %Q[A #{a_foe} emerges from the gloom and cries out,"#{cry}"]
       puts QUOTE + (hero.challenge % a_foe) + QUOTE
       # Combat! Hero attacks, foe retaliates. Over and over to the death,
       # but whose death?
       while hero.life > 0
          if a_foe.life <= 0
             # Victory -- hero munches on magic lettuce.
             hero.%
             break
          end
          # Strike foe with magick sword.
          hero./
          # Throw bomb if foe still major treat.
          hero.* if a_foe.life > 250
       end
       break if hero.life <= 0
    end
    puts "It's over. It's all over."
end
</code>

Regards, Morton

I too was worried it was too much effort before I ran it, but Morton sent me his solution and it's not out-of-line with past quizzes.

We're not going for Pulitzer Prize winning publications here. Keep it simple and see what you can get with a moderate effort.

Morton gives a great suggestion for where to steal code that will get you started, but even without that you have a lot of options. Remember grade school English? A subject, verb, and object is all you really need.

Think outside the box. If your stories turn out comical, list that as a feature in the quiz submission message, not a bug. :wink:

James Edward Gray II

P.S. For those of you that try this, posting generated stories is not a spoiler!

···

On Sep 29, 2006, at 8:18 AM, Robert Dober wrote:

On 9/29/06, Ruby Quiz <james@grayproductions.net> wrote:

The three rules of Ruby Quiz:

<snip>

The Quiz ittself might be too much work to do for me, but reading it was
already an enourmous pleasure.

I glad you like the idea. Please give it a try. It doesn't require complex code, and it is even more fun to code this up than it is to read the results.

Here is a surefire recipe for success :slight_smile:

1. To a handful of goofy characters, add a list of silly things for them to do
2. Season with your favorite cliches -- cliches are a key ingredient
3. Stir in a text editor until a suitably turgid consistency is reached
4. Run in a Ruby interpreter until done

Regards, Morton

···

On Sep 29, 2006, at 9:18 AM, Robert Dober wrote:

The Quiz ittself might be too much work to do for me, but reading it was
already an enourmous pleasure.
What a Funny, Great Idea!

Dang that's clever Jim!

Here's the tragedy.rb file I was taunting the list with yesterday:

#!/usr/bin/env ruby -w

class Array
   def rand
     fetch(Kernel.rand(size))
   end
end

characters = %w[James Ruby]
sentence_structure = [ "S falls in love with O.",
                        "S (slays|kills) O(.|.|.|!)",
                        "S cries." ]

output = String.new
(ARGV.shift || 5).to_i.times do
   sentence = sentence_structure.rand.gsub(/\b[SO]\b/) { characters.rand }
   output << " " << sentence.gsub(/\([^()|]+(?:\|[^()|]+)+\)/) do |choices>
     choices[1..-2].split("|").rand
   end
end

puts output.strip.gsub(/(.{1,80}|\S{81,})(?: +|$\n?)/, "\\1\n")

__END__

James Edward Gray II

···

On Oct 1, 2006, at 9:45 AM, Jim Menard wrote:

I believe the 48 hours are up, so here's my solution:
http://www.io.com/~jimm/rubyquiz/quiz96/

Boris Prinz wrote:

Little Red-Cap revisited

Nice one Boris!

Regards,
Jordan

I can't think of any good reason not to show the code. The whole point of Ruby Quiz is to share and learn.

James Edward Gray II

···

On Oct 1, 2006, at 4:37 PM, Morton Goldberg wrote:

On Sep 29, 2006, at 9:02 AM, Ruby Quiz wrote:

The secret of the rabbit's magick sword will be revealed when my story generated
is posted.

There's one problem, as the perpetrator of this quiz, I'm not sure if I should post my solution. But if I don't, the secret will be forever lost :slight_smile: What to do?

Gruesome I got a couple of really strange situations with my generator too!

Les

···

On 10/1/06, Boris Prinz <boris.prinz@gmail.com> wrote:

Little Red-Cap revisited

Once upon a time little red-cap opened the stomach of the huntsman.

;)?
I cannot promise, I have to spend some time with my wife - what an excuse,
but probably not the best idea, because I have never noticed any female
names in the ML :frowning: , and I do not have the slightes idea how to attack
this.

Cheers
Robert

···

On 9/30/06, Morton Goldberg <m_goldberg@ameritech.net> wrote:

On Sep 29, 2006, at 9:18 AM, Robert Dober wrote:

> The Quiz ittself might be too much work to do for me, but reading
> it was
> already an enourmous pleasure.
> What a Funny, Great Idea!

I glad you like the idea. Please give it a try. It doesn't require
complex code, and it is even more fun to code this up than it is to
read the results.

Here is a surefire recipe for success :slight_smile:

1. To a handful of goofy characters, add a list of silly things for
them to do
2. Season with your favorite cliches -- cliches are a key ingredient
3. Stir in a text editor until a suitably turgid consistency is reached
4. Run in a Ruby interpreter until done

Regards, Morton

Please clarify, the text above is it your advice or just some more output

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

Anyone else here old enough to remember MadLibs?

···

On 9/30/06, Morton Goldberg <m_goldberg@ameritech.net> wrote:

Here is a surefire recipe for success :slight_smile:

1. To a handful of goofy characters, add a list of silly things for
them to do
2. Season with your favorite cliches -- cliches are a key ingredient

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

I agree. I'm at 22 lines of code and I'm already laughing:

   James kills Ruby. Ruby falls in love with James. James falls in love
   with James. Ruby slays James! James cries.

Shakespeare would be jealous for sure.

James Edward Gray II

···

On Sep 29, 2006, at 11:15 PM, Morton Goldberg wrote:

It doesn't require complex code, and it is even more fun to code this up than it is to read the results.

In a parallel universe in the land of Atlantis there was a tireless
Botanist named
Goldilocks. Goldilocks lived there with her loyal Armadillo Barbara,
and the two were never apart.

The land of Atlantis was in meyhem because of the repulsive
influence of a evil witch named Argonagas.

Goldilocks and Barbara came up with a daring plan - Barbara would
distract the witch, giving Goldilocks the opportinuty to attack unseen.

They rode bravely into battle and Goldilocks sliced the evil witch in
strips with her portable angle-grinder while Barbara created a
diversion by screaming synonyms!
Goldilocks and Barbara became the heroes of Atlantis and lived happily
ever after.

THE END.

···

On 9/29/06, James Edward Gray II <james@grayproductions.net> wrote:

P.S. For those of you that try this, posting generated stories is
not a spoiler!

I just get:

jim.rb:17: odd number list for Hash
something to do with the email formatting? I'll have to look later.

Les

···

On 10/1/06, James Edward Gray II <james@grayproductions.net> wrote:

On Oct 1, 2006, at 9:45 AM, Jim Menard wrote:

> I believe the 48 hours are up, so here's my solution:
> http://www.io.com/~jimm/rubyquiz/quiz96/

Dang that's clever Jim!

Here's the tragedy.rb file I was taunting the list with yesterday:

#!/usr/bin/env ruby -w

class Array
   def rand
     fetch(Kernel.rand(size))
   end
end

characters = %w[James Ruby]
sentence_structure = [ "S falls in love with O.",
                        "S (slays|kills) O(.|.|.|!)",
                        "S cries." ]

output = String.new
(ARGV.shift || 5).to_i.times do
   sentence = sentence_structure.rand.gsub(/\b[SO]\b/)
{ characters.rand }
   output << " " << sentence.gsub(/\([^()|]+(?:\|[^()|]+)+\)/) do |
choices>
     choices[1..-2].split("|").rand
   end
end

puts output.strip.gsub(/(.{1,80}|\S{81,})(?: +|$\n?)/, "\\1\n")

__END__

I take it from your answer that one is only allowed to submit one solution and that I should submit the first solution but not the second. Am I reading you right?

Regards, Morton

···

On Oct 1, 2006, at 6:37 PM, James Edward Gray II wrote:

On Oct 1, 2006, at 4:37 PM, Morton Goldberg wrote:

On Sep 29, 2006, at 9:02 AM, Ruby Quiz wrote:

The secret of the rabbit's magick sword will be revealed when my story generated
is posted.

There's one problem, as the perpetrator of this quiz, I'm not sure if I should post my solution. But if I don't, the secret will be forever lost :slight_smile: What to do?

I can't think of any good reason not to show the code. The whole point of Ruby Quiz is to share and learn.

Rick DeNatale wrote:

···

On 9/30/06, Morton Goldberg <m_goldberg@ameritech.net> wrote:

Here is a surefire recipe for success :slight_smile:

1. To a handful of goofy characters, add a list of silly things for
them to do
2. Season with your favorite cliches -- cliches are a key ingredient

Anyone else here old enough to remember MadLibs?

Roger Price ... of course. Do you remember Droodles?

Sure:

http://www.rubyquiz.com/quiz28.html

James Edward Gray II

···

On Sep 30, 2006, at 9:08 AM, Rick DeNatale wrote:

On 9/30/06, Morton Goldberg <m_goldberg@ameritech.net> wrote:

Here is a surefire recipe for success :slight_smile:

1. To a handful of goofy characters, add a list of silly things for
them to do
2. Season with your favorite cliches -- cliches are a key ingredient

Anyone else here old enough to remember MadLibs?