As I mentioned in my last post, I was working on a more generic version of the generator which was driven by XML. This version is written in Python. I wrote in for Python 2.7 using the py-dom-xpath library. I have included the python code here as well as three example XML files: Cave Johnson’s Lemon rant, a quote from model Caprice, and my take on the old Steve Jackson Games “Message form the Illuminated Master” generator.
Here is the code and the XML. Enjoy and let me know what you thing. (I am working on a Powershell version and I am looking at creating a widget for WordPress, by the way.)
generator.py
# Message Generator # Written by Taylor Kent # Copyright 2012 by Michael Taylor Kent # Get the libraries we need import argparse import random import xml.dom.minidom import xpath import re # Setup commandline argument Parser parser = argparse.ArgumentParser(description="Open an XML file, generate a random messgae based on the contents of the XML file, and display it") parser.add_argument('msgdatafile', metavar='InputXmlFile', nargs='?', type=argparse.FileType('r'), help='The XML file containing the message generation details') parser.add_argument('count', metavar='Integer', nargs='?', type=int, help='The Number of random messages to generate (Optional)', default=1) parser.add_argument('outfile', metavar='OutputFile', nargs='?', type=argparse.FileType('w'), help='The file to put the generated messages into (Optional)') # Parse Commandline arguements args = parser.parse_args() # Open XML data file msgdata = xml.dom.minidom.parse(args.msgdatafile) i = 1 for i in range(args.count): # Get a list of all the message patterns in the xml file xpathqry = '//messagedata/patterns/pattern' msgpatterns = xpath.find(xpathqry, msgdata) # Pick a message pattern msgpattern = msgpatterns[random.randint(0,(len(msgpatterns) - 1))] # Create message # Gather all the parts msgpatternname = str(msgpattern.getAttribute('name')) msgpatternvalue = str(msgpattern.getAttribute('value')) # Create Message # Create list of replacements msgparts = [] # Check for Shared lists being used (if any) xpathqry = '//messagedata/patterns/pattern[@name=\'' + msgpatternname + '\']/sharedlistsused/list' msgsharedlists = xpath.find(xpathqry, msgdata) if len(msgsharedlists) > 0: for msglist in msgsharedlists: msglistname = str(msglist.getAttribute('name')) msglistregex = str(msglist.getAttribute('replacepattern')) # Get the shared list xpathqry = '//messagedata/sharedlists/list[@name=\'' + msglistname + '\']/items/item' msgitems = xpath.find(xpathqry, msgdata) msgitemchoice = msgitems[random.randint(0,(len(msgitems) - 1))] msgitemvalue = str(msgitemchoice.getAttribute('value')) msgparts.append([msglistregex, msgitemvalue]) # Check for Specific lists (if any) xpathqry = '//messagedata/patterns/pattern[@name=\'' + msgpatternname + '\']/specificlists/list' msgspecificlists = xpath.find(xpathqry, msgdata) if len(msgspecificlists) > 0: for msglist in msgspecificlists: msglistname = str(msglist.getAttribute('name')) msglistregex = str(msglist.getAttribute('replacepattern')) # Get list items xpathqry = '//messagedata/patterns/pattern[@name=\'' + msgpatternname + '\']/specificlists/list[@name=\'' + msglistname + '\']/items/item' msgitems = xpath.find(xpathqry, msgdata) msgitemchoice = msgitems[random.randint(0,(len(msgitems) - 1))] msgitemvalue = str(msgitemchoice.getAttribute('value')) msgparts.append([msglistregex, msgitemvalue]) # Get linked items (if any) msgcleanedvalue = re.sub("\'", "\\\\\'", msgitemvalue) xpathqry = '//messagedata/patterns/pattern[@name=\'' + msgpatternname + '\']/specificlists/list[@name=\'' + msglistname + '\']/items/item[@value=\"' + msgitemvalue + '\"]/linkeditem' msglinkeditems = xpath.find(xpathqry, msgdata) if len(msglinkeditems) > 0: for msglinkeditem in msglinkeditems: msglinkeditemvalue = str(msglinkeditem.getAttribute("value")) msglinkeditemregex = str(msglinkeditem.getAttribute("replacepattern")) msgparts.append([msglinkeditemregex, msglinkeditemvalue]) # Actuall generate the message (stupid immutable strings in Python makes this harder than it needs to be) msg = [] if len(msgparts) > 0: for msgpart in msgparts: if len(msg) == 0: msg.append(re.sub(msgpart[0],msgpart[1],msgpatternvalue)) else: msg.append(re.sub(msgpart[0],msgpart[1],msg[len(msg) - 1])) else: msg.append(msgpatternvalue) # Get the complete message and display it msgfinal = msg[len(msg) - 1] print (msgfinal) print # write messages to the specified file, if it was supplied if args.outfile != None: args.outfile.write(msgfinal) args.outfile.write('\r\n\r\n')
lemons.xml
Original Quote:
“Alright, I’ve been thinking. When life gives you lemons, don’t make lemonade – make life take the lemons back! Get mad! I don’t want your damn lemons, what am I supposed to do with these? Demand to see life’s manager. Make life rue the day it thought it could give Cave Johnson lemons. Do you know who I am? I’m the man who’s gonna burn your house down! With the lemons. I’m going to to get my engineers to invent a combustible lemon that burns your house down!”
<messagedata> <sharedlists> </sharedlists> <patterns> <pattern name="lemons" value="Alright, I've been thinking. When rp1thing1rp1 gives you rp1thing2rp1, rp1thing3rp1. Make rp1thing1rp1 take the rp1thing2rp1 back! Get mad! I don't want your damn rp1thing2rp1! What am I supposed to do with these?! Demand to see rp1thing1rp1 manager! Make rp1thing1rp1 rue the day rp1pronoun1rp1 though it could give rp1namerp1 rp1thing2rp1! Do you know who I am? I'm rp1pronoun2rp1 who's gonna burn your rp1thing4rp1 down! With rp1thing2rp1! I'm going to get rp1thing5rp1 a combustible rp1thing6rp1 that burns your rp1thing4rp1 down!"> <sharedlistsused> </sharedlistsused> <specificlists> <list name="thing4" replacepattern="rp1thing4rp1"> <items> <item value="house"/> <item value="refrigerator"/> <item value="capitol building"/> <item value="studio"/> <item value="restaurant"/> <item value="candy factory"/> <item value="warehouse"/> <item value="computer"/> </items> </list> <list name="thing5" replacepattern="rp1thing5rp1"> <items> <item value="my engineers to invent"/> <item value="my friends to cook up"/> <item value="some rebel scum to steal"/> <item value="a dark mage to conjure up"/> <item value="some wombats to sniff out"/> <item value="an army of cockroaches to carry"/> <item value="a genius to think up"/> <item value="Lex Luthor to invert"/> <item value="a gang of Mad Scientists to build a time machine and go the future to find"/> </items> </list> <list name="thing1" replacepattern="rp1thing1rp1"> <items> <item value="life"> <linkeditem value="it" replacepattern="rp1pronoun1rp1"/> </item> <item value="John"> <linkeditem value="he" replacepattern="rp1pronoun1rp1"/> </item> <item value="the government"> <linkeditem value="it" replacepattern="rp1pronoun1rp1"/> </item> <item value="the King"> <linkeditem value="he" replacepattern="rp1pronoun1rp1"/> </item> <item value="the Chruch"> <linkeditem value="it" replacepattern="rp1pronoun1rp1"/> </item> <item value="the dark mage"> <linkeditem value="he" replacepattern="rp1pronoun1rp1"/> </item> <item value="the system"> <linkeditem value="it" replacepattern="rp1pronoun1rp1"/> </item> <item value="Russia"> <linkeditem value="Russia" replacepattern="rp1pronoun1rp1"/> </item> <item value="Cthulhu"> <linkeditem value="the great dark lord" replacepattern="rp1pronoun1rp1"/> </item> <item value="that supid dog"> <linkeditem value="it" replacepattern="rp1pronoun1rp1"/> </item> <item value="the devil"> <linkeditem value="it" replacepattern="rp1pronoun1rp1"/> </item> <item value="Darth Vader"> <linkeditem value="he" replacepattern="rp1pronoun1rp1"/> </item> </items> </list> <list name="thing2" replacepattern="rp1thing2rp1"> <items> <item value="lemons"> <linkeditem value="don't make lemonade" replacepattern="rp1thing3rp1"/> <linkeditem value="lemon" replacepattern="rp1thing6rp1"/> </item> <item value="ice cubes"> <linkeditem value="don't make a Tom Collins" replacepattern="rp1thing3rp1"/> <linkeditem value="ice cube" replacepattern="rp1thing6rp1"/> </item> <item value="taxes"> <linkeditem value="don't file a tax return" replacepattern="rp1thing3rp1"/> <linkeditem value="tax" replacepattern="rp1thing6rp1"/> </item> <item value="bad music"> <linkeditem value="don't just listen to it" replacepattern="rp1thing3rp1"/> <linkeditem value="song" replacepattern="rp1thing6rp1"/> </item> <item value="undercooked pizza"> <linkeditem value="don't send it back" replacepattern="rp1thing3rp1"/> <linkeditem value="pizza" replacepattern="rp1thing6rp1"/> </item> <item value="mexican candy"> <linkeditem value="don't eat it and puke" replacepattern="rp1thing3rp1"/> <linkeditem value="candy" replacepattern="rp1thing6rp1"/> </item> <item value="crappy software"> <linkeditem value="don't just install it and post bitter forum post online about how it sucks" replacepattern="rp1thing3rp1"/> <linkeditem value="software" replacepattern="rp1thing6rp1"/> </item> <item value="a Yugo"> <linkeditem value="don't drive it" replacepattern="rp1thing3rp1"/> <linkeditem value="Yugo" replacepattern="rp1thing6rp1"/> </item> </items> </list> <list name="name" replacepattern="rp1namerp1"> <items> <item value="Cave Johnson"> <linkeditem value="the man" replacepattern="rp1pronoun2rp1"/> </item> <item value="Billy"> <linkeditem value="the boy" replacepattern="rp1pronoun2rp1"/> </item> <item value="Sheela"> <linkeditem value="the woman" replacepattern="rp1pronoun2rp1"/> </item> <item value="Merlin"> <linkeditem value="the wizard" replacepattern="rp1pronoun2rp1"/> </item> <item value="Robin Hood"> <linkeditem value="the hood" replacepattern="rp1pronoun2rp1"/> </item> <item value="that guy"> <linkeditem value="the guy" replacepattern="rp1pronoun2rp1"/> </item> <item value="Richard Nixon"> <linkeditem value="the zombie (and former president)" replacepattern="rp1pronoun2rp1"/> </item> <item value="JFK"> <linkeditem value="the gunslinger" replacepattern="rp1pronoun2rp1"/> </item> </items> </list> </specificlists> </pattern> </patterns> </messagedata>
mombasa.xml
Original Quote:
“I knocked someone over in Mombasa and he broke his leg. But I gave him 10 Pounds and he seemed really pleased.”
<messagedata> <sharedlists> </sharedlists> <patterns> <pattern name="mombasa" value="I knocked someone over in rp1placerp1 and rp1pronoun1rp1 broke rp1pronoun2rp1 rp1bodypartrp1. But I gave rp1pronoun3rp1 rp1compensationrp1 and rp1pronoun1rp1 rpt1endingrpt1."> <sharedlistsused> </sharedlistsused> <specificlists> <list name="place" replacepattern="rp1placerp1"> <items> <item value="Mombasa"/> <item value="Washington State"/> <item value="Walmart"/> <item value="Hell"/> <item value="Detroit"/> <item value="Las Vegas"/> <item value="line for concert tickets"/> <item value="my dream"/> <item value="the robot factory"/> <item value="Moombase Alpha"/> <item value="the Dungeon of Dreadmore"/> </items> </list> <list name="bodypart" replacepattern="rp1bodypartrp1"> <items> <item value="leg"/> <item value="arm"/> <item value="jaw"/> <item value="finger"/> <item value="foot"/> <item value="head"/> <item value="ankle"/> <item value="wrist"/> <item value="shoulder"/> <item value="back"/> <item value="tooth"/> </items> </list> <list name="compensation" replacepattern="rp1compensationrp1"> <items> <item value="10 pounds"/> <item value="37 cents"/> <item value="a lemon"/> <item value="someone elses business card"/> <item value="a hall pass"/> <item value="an apple"/> <item value="a 30 dollar bill"/> <item value="a happy meal"/> <item value="a ticket to Disney"/> <item value="a dime bag"/> <item value="3 pennies"/> <item value="a Alien artifact"/> <item value="a bible"/> <item value="my sweaty socks"/> <item value="a Lady Gaga CD"/> <item value="a radioactive bolt"/> <item value="an electric shock"/> <item value="a punch in the face"/> <item value="drug"/> <item value="a red plastic dinosaur"/> <item value="some pocket lint"/> <item value="a pizza"/> <item value="a jar of pickles"/> <item value="a ticket to last years superbowl"/> <item value="my car keys"/> <item value="a dress"/> <item value="some pants"/> <item value="a toy truck"/> <item value="a bowl of ice-cream"/> <item value="some mexican candy"/> <item value="a boot to the head"/> </items> </list> <list name="ending" replacepattern="rpt1endingrpt1"> <items> <item value="sued me"/> <item value="pulled out a shotgun"/> <item value="gave me a Tickle Me Elmo"/> <item value="stole my wallet"/> <item value="ran off screaming"/> <item value="hit me in the face with a pie"/> <item value="threw a rock at me"/> <item value="shot me in the leg"/> <item value="seemed really please"/> <item value="returned the favor"/> <item value="put a curse on me"/> <item value="gave it back"/> <item value="smoked a dubie"/> <item value="had a heart attack"/> <item value="discovered the meaning of life (and didn't share it with me)"/> <item value="bought a roast-beef hoagie"/> <item value="whent to Taco Bell"/> <item value="ate a bug"/> <item value="told me about a great investment opportunity"/> </items> </list> <list name="pronoun" replacepattern="rp1pronoun1rp1"> <items> <item value="he"> <linkeditem value="his" replacepattern="rp1pronoun2rp1"/> <linkeditem value="him" replacepattern="rp1pronoun3rp1"/> </item> <item value="she"> <linkeditem value="her" replacepattern="rp1pronoun2rp1"/> <linkeditem value="her" replacepattern="rp1pronoun3rp1"/> </item> </items> </list> </specificlists> </pattern> </patterns> </messagedata>
illuminator.xml
Examples:
“The President writes Internal Security and the tasty woman
Cthulhu will be the house
George W. Bush smacks Robin Hood and the cold FNORD
Batman hates Captain Kirk, and The President smacks the pen”
<messagedata> <sharedlists> <list name="adjective"> <items> <item value="blue"/> <item value="hot"/> <item value="alien"/> <item value="magical"/> <item value="fast"/> <item value="hot"/> <item value="cold"/> <item value="cool"/> <item value="ferocious"/> <item value="frightening"/> <item value="small"/> <item value="huge"/> <item value="Japanese"/> <item value="old"/> <item value="smelly"/> <item value="fat"/> <item value="phat"/> <item value="angry"/> <item value="irate"/> <item value="mellow"/> <item value="blue-green"/> <item value="hyper"/> <item value="paranormal"/> <item value="super"/> <item value="supernatural"/> <item value="happy"/> <item value="scary"/> <item value="cute"/> <item value="watery"/> <item value="Y2K-ready"/> <item value="ready"/> <item value="tasty"/> </items> </list> <list name="thing"> <items> <item value="MP3"/> <item value="alien"/> <item value="car"/> <item value="book"/> <item value="(CENSORED)"/> <item value="(REDACTED)"/> <item value="calendar"/> <item value="helicoper"/> <item value="briefcase"/> <item value="phone"/> <item value="dinosaur"/> <item value="robot"/> <item value="android"/> <item value="lizard"/> <item value="ball"/> <item value="hat"/> <item value="submarine"/> <item value="computer"/> <item value="man"/> <item value="woman"/> <item value="spaceship"/> <item value="tank"/> <item value="pen"/> <item value="fluid"/> <item value="lake"/> <item value="house"/> <item value="TV"/> <item value="radio"/> <item value="warbot"/> <item value="crate"/> <item value="dog"/> <item value="cat"/> <item value="CEO"/> <item value="CTO"/> <item value="Yugo"/> <item value="horse"/> <item value="FNORD"/> <item value="button"/> </items> </list> <list name="action"> <items> <item value="writes"/> <item value="discovers"/> <item value="torments"/> <item value="fights"/> <item value="smokes"/> <item value="drives"/> <item value="pilots"/> <item value="runs from"/> <item value="is"/> <item value="was"/> <item value="will be"/> <item value="hates"/> <item value="jumps on"/> <item value="infiltrates"/> <item value="adapts to"/> <item value="fills"/> <item value="live in"/> <item value="live on"/> <item value="swims in"/> <item value="runs from"/> <item value="bounces"/> <item value="cooks"/> <item value="kills"/> <item value="smacks"/> </items> </list> <list name="person"> <items> <item value="Dick Cheney"/> <item value="Luke Skywalker"/> <item value="Cave Johnson"/> <item value="Merlin"/> <item value="King Arthur"/> <item value="Robin Hood"/> <item value="Bill Clinton"/> <item value="Bob"/> <item value="Killer Kane"/> <item value="Superman"/> <item value="Lex Luthor"/> <item value="Batman"/> <item value="George W. Bush"/> <item value="The President"/> <item value="Some guy"/> <item value="(CENSORED)"/> <item value="(REDACTED)"/> <item value="The Quarterback"/> <item value="Zeus"/> <item value="Mr Fixit"/> <item value="Conan"/> <item value="Cthulhu"/> <item value="GLaDOS"/> <item value="The Master Computer"/> <item value="HAL 9000"/> <item value="KGB"/> <item value="Internal Security"/> <item value="General Hagenkraut"/> <item value="Captain Kirk"/> </items> </list> </sharedlists> <patterns> <pattern name="illumination1" value="The rp1adj1rp1 rp1thingrp1 is rp1adj2rp1"> <sharedlistsused> <list name="adjective" replacepattern="rp1adj1rp1"/> <list name="thing" replacepattern="rp1thingrp1"/> <list name="adjective" replacepattern="rp1adj2rp1"/> </sharedlistsused> <specificlists> </specificlists> </pattern> <pattern name="illumination2" value="The rp1adj1rp1 rp1thingrp1 is rp1adj1rp1"> <sharedlistsused> <list name="adjective" replacepattern="rp1adj1rp1"/> <list name="thing" replacepattern="rp1thingrp1"/> </sharedlistsused> <specificlists> </specificlists> </pattern> <pattern name="illumination3" value="rp1personrp1 rp1actionrp1 the rp1thingrp1"> <sharedlistsused> <list name="person" replacepattern="rp1personrp1"/> <list name="action" replacepattern="rp1actionrp1"/> <list name="thing" replacepattern="rp1thingrp1"/> </sharedlistsused> <specificlists> </specificlists> </pattern> <pattern name="illumination4" value="rp1person1rp1 rp1actionrp1 rp1person2rp1 and the rp1adjrp1 rp1thingrp1"> <sharedlistsused> <list name="person" replacepattern="rp1person1rp1"/> <list name="action" replacepattern="rp1actionrp1"/> <list name="person" replacepattern="rp1person2rp1"/> <list name="adjective" replacepattern="rp1adjrp1"/> <list name="thing" replacepattern="rp1thingrp1"/> </sharedlistsused> <specificlists> </specificlists> </pattern>--> <pattern name="illumination5" value="rp1person1rp1 rp1actionrp1 rp1person2rp1 and the rp1thingrp1"> <sharedlistsused> <list name="person" replacepattern="rp1person1rp1"/> <list name="action" replacepattern="rp1actionrp1"/> <list name="person" replacepattern="rp1person2rp1"/> <list name="thing" replacepattern="rp1thingrp1"/> </sharedlistsused> <specificlists> </specificlists> </pattern> <pattern name="illumination6" value="rp1person1rp1 rp1actionrp1 rp1person2rp1 and rp1person2rp1's rp1thingrp1"> <sharedlistsused> <list name="person" replacepattern="rp1person1rp1"/> <list name="action" replacepattern="rp1actionrp1"/> <list name="person" replacepattern="rp1person2rp1"/> <list name="thing" replacepattern="rp1thingrp1"/> </sharedlistsused> <specificlists> </specificlists> </pattern> <pattern name="illumination7" value="rp1person1rp1 rp1action1rp1 rp1person2rp1, and rp1person3rp1 rp1action2rp1 the rp1thingrp1"> <sharedlistsused> <list name="person" replacepattern="rp1person1rp1"/> <list name="action" replacepattern="rp1action1rp1"/> <list name="person" replacepattern="rp1person2rp1"/> <list name="person" replacepattern="rp1person3rp1"/> <list name="action" replacepattern="rp1action2rp1"/> <list name="thing" replacepattern="rp1thingrp1"/> </sharedlistsused> <specificlists> </specificlists> </pattern> <pattern name="illumination8" value="FNORD"> <sharedlistsused> </sharedlistsused> <specificlists> </specificlists> </pattern> </patterns> </messagedata>
Enjoy. Please give credit where credit is due if you use the code. I would also be interested in seeing any patterns you come up with.