About Ulysses Redux

Quick Links


Ulysses Redux is a blog written by a set of scripts on my laptop. (Usually, one chapter per day is posted, though this can vary, especially if I'm currently working on the scripts.) Each cohesive run consists of eighteen chapters, or individual blog posts; I call each set of eighteen chapters a novel. Each chapter in each iteration is randomly generated by a program that uses Markov chains to represent the textual state of that particular chapter in James Joyce's 1922 novel Ulysses; often, they are also trained based on other texts in addition to Ulysses. (And if you don't already know what an enjoyable and brilliant novel Ulysses is, you should go read it, enjoy it, and love it right now). This project is intended both as an homage to Ulysses and as an ongoing experiment in automatic text generation.

Contents and Links

There is a list of novels written for Ulysses Redux available, which provides access to a detailed table of contents for each novel written by the script. Like the blog itself, and the scripts that write it, it is work in progress.

I occasionally write about Ulysses Redux on my personal blog under the tag #UlyssesRedux. I also maintain intermittent, though sometimes quite detailed, notes about the blog development; you can read these if you'd like to look at recent news, changes, etc.

Technical details


The scripts used to generate the text on the blog run under Python 3.5 (and perhaps earlier versions) . They are available on GitHub; the set of scripts that generates each novel a separate branch in the GitHub repo.

Short version

There is a main script, daily_script.py, that's called by a cron job once a day. It, in turn, checks to see how many stories have been written in the current run and calls a script to write the next story. Each chapter has its own script in the directory chapter_scripts and is called ch01.py, ch02.py, etc. Many of these scripts are basically the same except for the statistics embedded in the script file itself intended to describe the structure of the source chapter in Joyce's Ulysses, which are currently nothing more than the total number of sentences in the chapter and the average number of sentences per paragraph. (Currently, the only scripts that don't fit this pattern are the scripts for Aeolus (ch07.py), Scylla and Charybdis (ch10.py), Circe (ch15.py), and Ithaca (ch17.py). Each of these scripts, in one way or another, calls the main routine in the markov_sentence_generator module, a Python module I abstracted from Harry R. Schwartz's Markov sentence generator and adapted substantially to my own use.

The daily script gradually builds the table of contents for each novel in a file, /UlyssesRedux/current-run/index.html, and keeps track of other information related to the current run in /UlyssesRedux/current-run/, as well. This index.html file is also how the script knows how many chapters have been written so far. Each day, the cron job runs the daily script, which calls the appropriate chapter script to write a chapter, posts it to the UlyssesRedux Tumblr account, and records some basic information in the index.html tracking file. Once the full eighteen chapters have been written, the daily script does nothing except bother me to reset it.

Resetting it involves running one of the scripts in the utility_scripts directory: postprocess_set.py which posts the partial table of contents to my website, syncs the code used to the GitHub repository, and sets up the next run by calling setup_run.py.

There are other helpful scripts in the utility_scripts directory. Perhaps notable: get-chapter-stats.py, which coughts up some basic stats for a given chapter (or any text) file; various get-chapter-[something]-stats.py scripts, which analyze specific text files and produce the kinds of stats file that individual chapter scripts expect; and produce-entire-novel.py, which runs the top-level script eighteen times, then runs the postprocessing script.

About the Coder

Input, feedback, and suggestions are welcome; you can reach me on Twitter or on GNUSocial or on GitHub, or find me elsewhere on the web. Anyone interested in collaborating should make contact through GitHub.

This page is currently a stub, but will hopefully be expanded not too far in the future.