[QUIZ] Story Generator (#96)

you are heading for the Nobel Prize(1), I hate you, even if you are the boss
of that Quiz thingy :wink:

(1) B/c I do not know how to spell Purlitzer :slight_smile:

Robert

···

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

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.

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

I am @ 300 lines, only concept, my wife does not talk to me anymore, and

--
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

Wow, I can't wait to see that generator!

James Edward Gray II

···

On Oct 1, 2006, at 5:08 AM, Leslie Viljoen wrote:

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!

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.

See if this version holds the formatting better and works for you:

http://pastie.caboo.se/15699

James Edward Gray II

···

On Oct 1, 2006, at 12:29 PM, Leslie Viljoen wrote:

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 just get:

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

My submission puts out a "story" that looks more like a transcript from
a turn-based MUD like dwemthy. It's basically just a poor man's markov
chain generator with a fixed model. Some of the turns are pretty funny
though. :slight_smile:

#!/usr/bin/ruby

···

##
## A new Legend...
##

turns = (ARGV.first || 14).to_i

characters = ['Jack', 'Princess Lily', 'Honeythorn Gump',
              'Oona', 'Brown Tom', 'Screwball', 'Blunder',
              'Blix', 'The Lord of Darkness']

actions = ['bites', 'conjugates', 'hits', 'scares', 'oogles',
              'thumps', 'extrapolates', 'undulates', 'pesters',
              'sputters', 'liquifies', 'castigates', 'gesticulates',
              'berates', 'circumscribes', 'burns', 'kicks',
              'punctures', 'disembowels', 'stabs', 'smells',
              'browbeats', 'villifies', 'deflagrates',
              'psychoanalyzes', 'dominates', 'cajoles']

modifiers = ['near', 'under', 'around', 'past', 'next to',
              'about', 'with', 'by', 'above', 'beside',
              'close to', 'in the general vicinity of']

adjectives = ['actually', 'giddly', 'angrily', 'suddenly',
              'fearfully', 'faithfully', 'fiendishly',
              'maniacally', 'gradually', 'manually']

fragments = ['until noon', 'when darkness falls',
              'in the mouth of chaos', 'as the rain falls',
              'all day long', 'while unicorns roam the earth',
              'as the world turns', 'in the belly of the beast',
              'on television', 'in Parliment', 'with gentle hands',
              'like a soccer scanger', 'with a cockney accent',
              'like a malevolent spirit', 'like a wild banshee']

plottwists = ['From out of nowhere..', 'All of a sudden..',
              'Somewhat randomly..', 'Then with utter abandon..',
              'In contempt of life..', 'When he finally realizes..',
              'Meanwhile in the forest..', 'After that..',
              'Back at the office..', 'During normal buisness hours..']

finales = ['decimates destroys and otherwise obliterates',
              'pummels drop-kicks and powerfully suplexes',
              'burns explodes and utterly incinderates',
              'stabs cuts and overall perferates']

actions2 = ['hides', 'sneaks', 'knits sweaters', 'steals cheese',
              'answers the call of nature', 'aggrevates the wildlife',
              'saves the whales', 'clear cuts old-growth forests']

locations = ['pools of bean curd', 'fountains of cheese dip',
              'deciduous forests', "farmer John's chicken coops",
              'Fruit Of The Loom underwear', 'the English Channel',
              'nests of burrowing rodents', 'festering sores',
              'public bathrooms', "Hugh Hefner's mansion",
              'Buddhist temples']

chains = [['characters', 'actions', 'characters', 'fragments'],
          ['characters', 'adjectives', 'actions', 'characters',
'fragments'],
          ['characters', 'actions', 'modifiers', 'characters',
'fragments'],
          ['characters', 'actions', 'modifiers', 'characters',
'adjectives', 'fragments'],
          ['characters', 'actions', 'characters', 'modifiers',
'characters']]

def choose(ary)
  ary[rand(ary.size)]
end

intervals = []
(turns/3).times {
  interval = rand(turns)
  while intervals.include?(interval) or
        intervals.include?(interval+1) or
        intervals.include?(interval-1)
    interval = rand(turns)
  end
  intervals << interval
}

story = []
twists = []
turns.times {
  begin
    events = []
    choose(chains).each { |item|
      item = eval(item)
      event = choose(item)
      while events.include?(event)
        event = choose(item)
      end
      events << event
    }
  end while story.include?(events)
  story << events
}

intervals.each { |i|
  twist = choose(plottwists)
  while twists.include?(twist)
    twist = choose(plottwists)
  end
  story.insert(i, [twist])
}

story.each { |event|
  puts event.join(' ') + '.'
}

print "\n~~~\n\nFinally, after much strife...\n#{choose(characters)} ",
"#{choose(finales)} #{choose(characters)},\nwho #{choose(actions2)} ",
"in or around #{choose(locations)} at night,\nand has thusly rid ",
"the world of the scurrilous bane forever!\n\n~ The End ~\n"

__END__

Regards,
Jordan

Well it's a mailing list and not just a quiz list. So let's see all
the code! What's not part of the quiz can just not go in the quiz,
since the silent period is over, right?

Les

···

On 10/1/06, Morton Goldberg <m_goldberg@ameritech.net> wrote:

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.

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?

Nope. People submit multiple solutions all the time.

We're a low rules kind of crowd.

James Edward Gray II

···

On Oct 1, 2006, at 5:47 PM, Morton Goldberg wrote:

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.

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?

Sure, this is one my favorites:

···

On Sep 30, 2006, at 11:14 AM, M. Edward (Ed) Borasky wrote:

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

+-------------------+

                  >
      . . |
                  >

+-------------------+

Polar Bear in a Snowstorm

Regards, Morton

OK, here's my second solution. It applies the KISS principle with a vengeance. Since I had some C and regex experience before I took up Ruby, I could have written this when I was two weeks into my Ruby life. I had to fall back to such a simple and inelegant style to meet my self-imposed deadline of one hour or less to write the code. Then, of course, I blew it by spending almost three hours working on the story template, word lists, and phrase dictionaries, to make the output read smoothly. But that's not coding, right? :slight_smile:

I really like my first solution a lot better, but this one has some charm if I do say so myself.

<sample story>
The Three Bears Go To Corporate USA

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

Papa Bear wanted to go to Corporate USA. Mama Bear wanted to go to Jurassic Park. But Baby Bear got all exited. "I want to go to Corporate USA! I want to go to Corporate USA! I want to go to Corporate USA!"

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

Although it seemed nearly forever to Baby Bear, next month eventually arrived. The Bears piled into their mini-van and off they went. Along the way they made a wrong turn and got lost.

They stayed two days. While they were there they saw a Venture Capitalist, a Marketing Manager, a Stock Broker, and a Tax Accountant. At the park's restaurants they had pizza, CEO's platter, and outsourced curry. They enjoyed attractions such as the Chamber of Outsourcing Horrors, the Cubicle Maze, and the Golden Parachute Drop. Mama Bear was shocked by the Cubicle Maze. Baby Bear especially liked the Tax Accountant.

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

Papa Bear thought the Venture Capitalist was best. Mama Bear thought the Marketing Manager was best. But Baby Bear was certain that the Tax Accountant was really the best.

The end.
</sample story>

<code>
#! /usr/bin/env ruby -w

···

On Oct 1, 2006, at 10:02 PM, James Edward Gray II wrote:

On Oct 1, 2006, at 5:47 PM, Morton Goldberg wrote:

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?

Nope. People submit multiple solutions all the time.

We're a low rules kind of crowd.

#
# Created by Morton Goldberg on 2006-10-01.
#
# quiz_96.rb -- Story Generator

class Array

    def pick(n=1)
       sample = self.dup
       result =
       until n <= 0 || sample.empty?
          result << sample.delete_at(rand(sample.size))
          n -= 1
       end
       result
    end

    def pick1
       self.pick.first
    end

    def pick!(n=1)
       result =
       until n <= 0 || self.empty?
          result << self.delete_at(rand(self.size))
          n -= 1
       end
       result
    end

end

PARKS = [ 'Jurassic Park', "Dwemthy's Array", 'Corporate USA' ]

FAMILIES = %w[ Armadillo Artichoke Bear Droid ]

EXHIBITS = {
    'Jurassic Park' =>
       %w[
          tyrannosaur
          raptor
          sauropod
          triceratops
          maiasaur
          styracosaur
       ],
    "Dwemthy's Array" =>
       [
          'Rabbit',
          'Bogus Fox',
          'Jabberwocky',
          'Demon Angel',
          'Vicious Green Fungus',
          'Dragon'
       ],
    'Corporate USA' =>
       [
          'Tax Accountant',
          'Commodities Trader',
          'Venture Capitalist',
          'Stock Broker',
          'Chief Executive Officer',
          'Marketing Manager'
       ]
}

FOODS = {
    'Jurassic Park' =>
       [
          'Dinoburgers',
          'sauropod steak',
          'softshell trilobite',
          'Kentucky fried pterodon',
          'Jurassic pizza',
          'dinosaur kebabs'
       ],
    "Dwemthy's Array" =>
       [
          'jabberwocky steak',
          'Green fungus omelet',
          'magick lettuce',
          "Mama Dragnon's roast rabbit",
          "Dwemthy's pizza"
       ],
    'Corporate USA' =>
       [
          "CEO's platter",
          'NGO salad',
          "Venture Capitalist's delight",
          'Board Room Buffet (tm)',
          'outsourced curry',
          'pizza']
}

ATTRACTIONS = {
    'Jurassic Park' =>
       [
          'DinoCoaster (tm)',
          'Dismal Swamp Flatboat',
          'Raptor Rodeo',

       ],
    "Dwemthy's Array" =>
       [
          'Monster-Go-Round',
          'Fungus Garden',
          'Bogus Fox Bowling',
          'Demon Twister',
          "Dragon's Den"
       ],
    'Corporate USA' =>
       [
          'Golden Parachute Drop',
          'Cubicle Maze',
          'Takeover Museum',
          'Chamber of Outsourcing Horrors'
      ]
}

EVENTS = [
    "stopped at an ice cream store where they all had three-scoop sundaes",
    "made a wrong turn and got lost",
    "had to stop twice to let the little one use a rest room",
    "had to swerve violently to avoid a <?> crossing the road"
]

def choose_park(*parks)
    choices = parks.uniq
    return choices.first if choices.size == 1 # unanimous
    return choices.pick1 if choices.size == 3 # all different
    # two out three
    parks.pop == parks.first ? parks.first : parks.last
end

$park = choose_park($p1=PARKS.pick1, $p2=PARKS.pick1, $p3=PARKS.pick1)
$family = FAMILIES.pick1
$do_not = [ $p1, $p2, $p3 ].uniq.size == 1 ? "don't " : ""
$papa = case $family
    when 'Droid'
       'R2P2'
    else
       'Papa ' + $family
    end
$mama = case $family
    when 'Droid'
       'R2M2'
    else
       'Mama ' + $family
    end
$baby = case $family
    when 'Droid'
       'R2B2'
    when 'Artichoke'
       'Sprout ' + $family
    else
       'Baby ' + $family
    end
$time = %w[ week month ].pick1
$duration = %w[ two three four ].pick1
$exhibits = EXHIBITS[$park].pick(4)
$baby_favorite = $exhibits.pick1
$attractions = ATTRACTIONS[$park].pick(3)
$shocker = $attractions.pick1
favorites = $exhibits + $attractions - [ $baby_favorite ]
$papa_favorite = favorites.pick!.first
$mama_favorite = (favorites - [ $shocker ]).pick1
$exhibits = 'a ' + $exhibits.join(', a ')
k = $exhibits.rindex(',')
$exhibits.insert(k + 1, ' and')
$foods = FOODS[$park].pick(3).join(", ")
k = $foods.rindex(',')
$foods.insert(k + 1, ' and')
$attractions = 'the ' + $attractions.join(", the ")
k = $attractions.rindex(',')
$attractions.insert(k + 1, ' and')
$vehicle = [ 'SUV', 'pick-up truck', 'car', 'mini-van' ].pick1
events = EVENTS.dup
$trip_event = events.pick!.first.sub(/<\?>/, EXHIBITS[$park].pick1)
$return_event = events.pick1.sub(/<\?>/, EXHIBITS[$park].pick1)

TEMPLATE = <<TXT
The Three #{$family}s Go To #{$park}

One day #{$papa} asked, "Vacation starts next #{$time}. Where shall we go?"

#{$papa} wanted to go to #{$p1}. #{$mama} wanted to go to #{$p2}. But #{$baby} got all exited. "I #{$do_not}want to go to #{$p3}! I #{$do_not}want to go to #{$p3}! I #{$do_not}want to go to #{$p3}!"

In the end, they agreed to go to #{$park}.

Although it seemed nearly forever to #{$baby}, next #{$time} eventually arrived. The #{$family}s piled into their #{$vehicle} and off they went. Along the way they #{$trip_event}.

They stayed #{$duration} days. While they were there they saw #{$exhibits}. At the park's restaurants they had #{$foods}. They enjoyed attractions such as #{$attractions}. #{$mama} was shocked by the #{$shocker}. #{$baby} especially liked the #{$baby_favorite}.

On the way back they #{$return_event}.

#{$papa} thought the #{$papa_favorite} was best. #{$mama} thought the #{$mama_favorite} was best. But #{$baby} was certain that the #{$baby_favorite} was really the best.

The end.
TXT

puts TEMPLATE
</code>

Regards, Morton

Mine is based on the 80's movie, Legend. My favorite output so far is:

"The Lord of Darkness undulates Princess Lily as the rain falls."

Oh my! Naughty Lord of Darkness! Heh.

Regards,
Jordan

The approach I've taken is to modify my solution to Ruby Quiz #49 (the
Lisp Game) so it plays itself. The output is a random "story" that's
all plot and no characterization.

Jim

···

On 9/30/06, MonkeeSage <MonkeeSage@gmail.com> wrote:

Mine is based on the 80's movie, Legend. My favorite output so far is:

"The Lord of Darkness undulates Princess Lily as the rain falls."

Oh my! Naughty Lord of Darkness! Heh.

Regards,
Jordan

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