Anapest Generator: a JavaScript Poem Maker

My JavaScript iambic pentameter generator is among the most popular articles on this blog. If you liked that, you’re gonna love today’s article. I decided to make an anapest generator with a rhyme! It’s a JavaScript poetry generator using an anapest, that is, a poem with anapestic meter.

anapest generator
Could the pen really write with the might of the sword?
(see what I did there?) 😉

An anapest, or anapestic meter, is a metrical foot consisting of two unstressed syllables followed by a stressed one. Perhaps the most famous example of an anapestic poem (also mentioned in my article on poetry) is Lord Byron’s “The Destruction of Sennacherib”.

The Assyrian came down like the wolf on the fold,
And his cohorts were gleaming in purple and gold;
And the sheen of their spears was like stars on the sea,
When the blue wave rolls nightly on deep Galilee.

Like the leaves of the forest when Summer is green,
That host with their banners at sunset were seen:
Like the leaves of the forest when Autumn hath blown,
That host on the morrow lay withered and strown.

A Simple Anapest Generator in Javascript

Without further delay, here’s what I came up with:

Perceptive observers will notice that the anapest generator is running in an iframe. As I didn’t want to mess with running JavaScript code in the blog post, the code originates from a sandbox page on the main website.

Looking for the code? Here it is, you’re welcome: 😉

<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rita/1.3.11/rita-full.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<input type="button" value="Generate New" onclick="window.location.reload();">
<br>
</header>
<div id="out1"></div><br>
<script>
var i=0;
var rhymedWord, rhymedWord2;
var preRhyme, preRhymeB;
var advS, advSB;
var det = " they ";
//creating rhymes
var w1 = wordChoice("vbn", 2);
var w1b = wordChoice("vb", 2);
var w2 = rhymeGen('https://api.datamuse.com/words?rel_rhy=', w1) //wordChoice("vb", 3)
var w2b = rhymeGen('https://api.datamuse.com/words?rel_rhy=', w1b) // wordChoice("vb", 2)
var syllNum = new_count(w2);
var syllNumB = new_count(w2b);
// first & second lines
if (w2 != undefined) {
rhymedWord = w2;
if (syllNum == 1) {
advS = 3;
det = " some ";
preRhyme = wordChoice("nns", advS)
}
else if (syllNum == 2) {
advS = 2;
preRhyme = RiTa.randomWord("rb", advS)
}
else if (syllNum == 3) {
advS = 1;
preRhyme = RiTa.randomWord("rb", advS);
}
else if (syllNum == 4) {
preRhyme = "";
}
else {
advS = 1;
preRhyme = RiTa.randomWord("rb", advS);
}
}
else {
rhymedWord = wordChoice("vb", 3);
advS = 1;
preRhyme = RiTa.randomWord("rb", advS);
}
// third and fourth lines
if (w2b != undefined) {
rhymedWord2 = w2b;
if (syllNumB == 1) {
advSB = 2;
preRhymeB = wordChoice("rb", advSB)
}
else if (syllNumB == 2) {
advSB = 1;
preRhymeB = RiTa.randomWord("md", advSB)
}
else if (syllNumB == 3) {
advSB = 1;
preRhymeB = "";
}
else {
advSB = 1;
preRhymeB = RiTa.randomWord("md", advSB);
}
}
else {
rhymedWord2 = wordChoice("vb", 2);
advSB = 1;
preRhymeB = RiTa.randomWord("md",advSB);
}
// structuring lines
var line1 = capitalizeFirstLetter(RiTa.randomWord("prp$",1)) + " " + wordChoice("jj",2) + " " + wordChoice("nn",3) + " " + retConjunction() + " " + wordChoice("nns",2) + " has " + w1 + ",";
var line2 = RiTa.randomWord("jj",1) + " " + wordChoice2("jj",3) + " " + wordChoice("nns",2) + " " + retConjunction2() + det + preRhyme + " " + rhymedWord + ".";
var line3 = capitalizeFirstLetter(wordChoice("jj",3)) + " " + RiTa.randomWord("jj",1) + " " + wordChoice("nn",2) + " " + retConjunction() + " " + wordChoice("nns",2) + " " + RiTa.randomWord ("md", 1) + " " + w1b + ",";
var line4 = RiTa.randomWord("prp$",1) + " " + wordChoice("jj",2) + " " + RiTa.randomWord("jj", 1) + " " + wordChoice("nn",2) + " " + retConjunction2() + " " + wordChoice("nns",2) + " " + preRhymeB + " " + rhymedWord2 + ".";
$('#out1').append(line1+"<br/>"+line2+"<br/>"+line3+"<br/>"+line4+"<br/>"+"<br/>");
// word picking functions for stress detection
function wordChoice(pos, syl) {
var word = RiTa.randomWord(pos, syl);
if ((RiTa.getStresses(word) == "0/1") || (RiTa.getStresses(word) == "0/0/1")) {
return (word);
}
else {
return (wordChoice(pos, syl));
}
}
function wordChoice2(pos, syl) {
var word = RiTa.randomWord(pos, syl);
if (RiTa.getStresses(word) == "0/1/0") {
return (word);
}
else {
return (wordChoice2(pos, syl));
}
}
function wordChoice3(pos, syl) {
var word = RiTa.randomWord(pos, syl);
if (RiTa.getStresses(word) == "1/0/0") {
return (word);
}
else {
return (wordChoice3(pos, syl));
}
}
//capitalize first letter
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
// counts syllables
function new_count(word) {
word = word.toLowerCase(); //word.downcase!
if(word.length <= 3) { return 1; } //return 1 if word.length <= 3
word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, ''); //word.sub!(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '')
word = word.replace(/^y/, ''); //word.sub!(/^y/, '')
return word.match(/[aeiouy]{1,2}/g).length; //word.scan(/[aeiouy]{1,2}/).size
}
function rhymeGen(urlAdd2, sWord){
var dmuseQuery2 = dataMUSE(urlAdd2 + sWord);
var aIndex2 = dmuseQuery2.length;
var rnd2 = Math.floor((Math.random() * aIndex2) + 1);
var dmuseWord2 = dmuseQuery2[rnd2];
return dmuseWord2;
}
function dataMUSE (myURL) {
var json = (function () {
var json = null;
$.ajax({
'async': false,
'global': false,
'url': myURL,
'dataType': "json",
'success': function (data) {
json = data;
}
});
return json;
})();
var amb2_proto = JSON.stringify(json);
var amb2_proto2 = amb2_proto.replace(/[.,\/#!?'"$%\^&\*;:{}\[\]=\-_`~()]/g,"");
var amb2_proto3 = amb2_proto2.replace(/word/g , " ");
var amb2_proto4 = amb2_proto3.replace(/score/g, " ");
var amb2_proto5 = amb2_proto4.replace(/[0-9]/g, " ");
var amb2_proto5b = amb2_proto5.replace(/numSyllables/g, " ");
var amb2_proto6 = amb2_proto5b.replace(/\s+/g,' ').trim();
var amb2 = amb2_proto6.split(" ");
return amb2;
}
function retConjunction() {
var conjs = ["with", "near", "for"];
var inde = Math.floor(Math.random() * (2 - 0 + 1) ) + 0;
return conjs[inde];
}
function retConjunction2() {
var conjs = ["as", "while", "soon", "then", "which", "how"];
var inde = Math.floor(Math.random() * (5 - 0 + 1) ) + 0;
return conjs[inde];
}
</script>
</body>
</html>
view raw anapest.html hosted with ❤ by GitHub


You will need the RiTa library for this to work. It also implements the Datamuse API (which means, if the Datamuse server is slow, this page will be slow as well; it’s out of my control). You will also need a bit of patience to get through my ridiculously redundant, ugly code (I got too bored to clean it up; finding the rhymes could be done with a function returning a string array).

Anapestic Poetry Generator: Next Steps

As with my iambic pentameter maker, this is really, really “alpha”. I’d like to work on it some more, if I only find the time. My main focus would be an attempt to improve semantic coherence.

I’ve also noticed that sometimes the generator draws a blank (not verse!). If that happens, pressing “Generate New” should resolve the issue.

home for fictionMansion Escape – a Text Adventure App for Android

There’s also the same issue as with the iambic pentameter generator, namely, that the library I’m using to detect syllable stress isn’t 100% correct. If you came up with an improved version, feel free to share it!

Before you Go…

Some blog posts come and go, and they vanish from sight.
And what then would you do, if you just lost the one?
Just subscribe to the list, and your job here is done,
Find some knowledge, some truth; discover
another source of light.

Where Are the Social Buttons?

There aren't any, because I don't want to advertise companies which I loathe. Besides, I consider my readers smart enough to know how to copy the link and share it anywhere they'd like.

Share your Thoughts on this Article