* * * * *
RACTER, generative text and Lisp. Oh my!
It figures.
I make disparaging (So when does 2 not equal 2?) [1] remarks [2] about Lisp
[3], and it turns out to possibly be the best language to use for a project
I'm working on.
Sigh.
The project (or projects—there are a few things I want to work on that can
use this) deals with computer generated text (or “generative text” as it's
called). Textual mashups if you will, like Crow Haiku Generator [4] or my own
Quick and Dirty B-Movie Plot Generator [5]. There are plenty more out there
if you look.
A lot of these are nothing more than arrays of strings and a slew of code to
sling the pieces together. Something like:
> temp = Newsflash[rand(Newsflash.length)] + "\n"
> + Location[rand(Location.length)] + " was attacked at dawn by "
> + Monsters[rand(Monsters.length)] + " "
> + From[rand(From.length)] + " "
> + Lowersheol[rand(Lowersheol.length)] + ". Our hero "
> + Hero[rand(Hero.length)] + " "
> + Fought[rand(Fought.length)] + ".";
>
Which would generate output like:
> ******* FLASH! FLASH! FLASH! *******
>
> Disneyland was attacked at dawn by giant green worms from the lowest levels
> of The IRS (Internal Revenue Service). Our hero Tim Conway told their
> mothers they were naughty.
>
This is probably one reason why so many generative text programs don't
generate all that much different text—they're too tedious to program.
I wanted an easier way to create the data and sling the words around—I wanted
a “program” I could write that could then be processed, much like INRAC, the
compiler used to create RACTER [6] (which supposedly wrote _The Policeman's
Beard is Half Constructed_ [7]), but using INRAC, to generate something like
this:
> Bill Gates bit Winston Churchill, but Winston Churchill just smiled. Bill
> Gates snarled, “Saint Winston Churchill, I presume”. “That's a Bill
> Gatesesque remark” replied Winston Churchill.
>
You write this:
> *story code section
> a %PEOPLE #
> b >HERO*person[&P] >VILLAIN*person[&N] #
> c $VILLAIN #RND3 bit robbed hit $HERO , #
> d but $HERO just #RND3 smiled laughed shrugged . #
> ' new:
> e $VILLAIN snarled >X=Saint,HERO "> $X , I presume <*. #
> f "That's a !Y=VILLAIN;esque remark" replied $HERO .
>
Um … yeah.
Thanks, but no thanks.
Building upon my own Quick-n-Dirty B-Movie Plot Generator, I wrote two
further prototypes, one in Perl and one in C; both can use the same input
files (and are not restricted to just generating B-movie plots). Why a
version in C? Because the one in Perl consumes an insane amount of memory and
takes almost 600 times longer to generate the output (since the C version can
process the input files once into an intermediate format that is quicker to
use whereas the Perl version has to re-read the input files for each
invocation; but even when I include the preprocessing time in the C version
it's still four times faster than Perl). The format I came up with is much
easier to deal with:
> # declare an array of text, which, when
> # referenced, will return one of the lines
> # at random. It ends with a semicolon alone
> # on a line.
>
> :MayYou
> I pray thou shalt
> I hope you will
> ;
>
> :HaveBadThingsHappen
> be plagued with gnats, flies and locusts
> be taunted by the king's concubines
> ;
>
> :OhYou
> thou
> O thou
> O ye
> ;
>
> :OfLittleFaith
> incompetent tax-collector
> lazy Babylonian
> ;
>
> :HearThis
> Listen
> Hear this
> Take heed
> ;
>
> # to reference an array, use %a-arrayname% #
> # one of the following lines will be used
>
> %a-MayYou% %a-HaveBadThingsHappen%, %a-OhYou% %a-OfLittleFaith%!
> %a-HearThis% %a-OhYou% %a-OfLittleFaith%, for you will %a-HaveBadThingsHappen%!
>
(I pulled these from a webpage that generated Biblical taunts, but I've since
lost the link).
So that's the point I am now—I can replicate most of the generative text
programs I've seen on webpages pretty quickly (about as quick as I can copy
the text out and into this format). Star Trek technobabble, fake Nostradamus
quatrains [8], crow haikus, all easy now.
Except I'm still not at the level of INRAC. I have no way of generating
variables and article generation (“a” or “an”) is still a bit problematic.
The syntax I'm currently using, while better than anything else I've seen, is
still clumsy (it's a holdover from the initial Perl version. So I've been
playing around with syntax a bit, making it easier, and adding variables and
functions (say, to generate the appropriate article for a word, or a random
number). So far, I like what I have for the new syntax:
> # assume we're using the Bible Taunts
>
> # declare a variable TheProphet, which
> # is a randomly choosen Bible name
>
> {TheProphet=[biblenames]}
>
> [MayYou] [HaveBadThingsHappen] [OhYou] [OfLittleFaith]!
> [HearThis] [OhYou] [OfLittleFaith], for you will [HaveBadThingsHappen]!
> {TheProphet} had a dream-you will [HaveBadThingsHappen]. So says {TheProphet}.
>
But things are progressing to where I'm reaching for lex and yacc to handle
the parsing and processing of the input files.
I am, in effect, writing a programming language.
Want to know something?
> Any sufficiently complicated C or Fortran program contains an ad-hoc,
> informally-specified bug-ridden slow implementation of half of Common Lisp.
>
> “Greenspun's Tenth Rule of Programming”
>
For all my misgivings about Lisp, I'm finding myself starting to write an ad-
hoc, informally-specified bug-ridden slow implementation of Lisp.
Heh.
[1]
gopher://gopher.conman.org/0Phlog:2006/01/25.1
[2]
gopher://gopher.conman.org/0Phlog:2006/01/26.2
[3]
http://www.apl.jhu.edu/~hall/lisp.html
[4]
http://website.lineone.net/~crowseed/crowcity/studio/haiku.html
[5]
http://boston.conman.org/cgi-bin/plotdriver.cgi
[6]
http://www.robotwisdom.com/ai/racterfaq.html
[7]
http://www.amazon.com/exec/obidos/ASIN/0446380512/conmanlaborat-20
[8]
http://www.sacred-texts.com/nos/
Email author at
[email protected]