A Diet of Bones

Screen Shot 2014-09-22 at 17.49.58

This is an experiment in generated grammar and poetics. the display is a blank black screen, and clicking generates a phrase that will slowly rise on the page.  The type of phrase is based off of this, and are delineated into 3 types:

Left: A grammatically correct english phrase

Middle: a semi-random phrase in disyllabic trimeter (each line has 6 syllables).

Right: a randomised set of words that are in iambic pentameter (each line consists of 4 sets of iambs, which consist of one weak-stress syllable, and one strong-stress syllable).

Screen Shot 2014-09-22 at 19.14.30

//class containgng pertinent information abot a word
class Word {
  String sing;
  String plur;
  int syllables;
  int[] metre;
  
  Word(String tempSing, String tempPlur, 
       int tempSyl, int[] tempMet) {
    sing = tempSing;
    plur = tempPlur;
    syllables = tempSyl;
    metre = tempMet;
  }
}

// word tupole class - needed for a function return
class WordTuple {
  Word x;
  Word y;
  WordTuple(Word tempX, Word tempY) {
    x = tempX;
    y = tempY;
  }
}

// class that contains the phrases (built from Words) that appear
// on the display
class Phrase {
  String contents;
  int x;
  int y;
  Phrase(String tempConts, int tempX, int tempY){
    contents = tempConts;
    x = tempX;
    y = tempY;
  }
  //phrases rise after generation
  void update(){
    y = y-1;
  }
  void display(){
    fill(250,250,250);
    textAlign(CENTER);
    text(contents,x,y);
  }
  Boolean finished(){
    return y < -50;
  }
}

//word declaration - I have to hard-code the words right now,
//but processing automitically seems possible, if difficult
Word confessional;
Word studio;
Word Lebanon;
Word diet;
Word timber;
Word along;
Word bee;
Word bone;
Word of;
Word forWord;
Word a;
Word redouble;


Word[] nouns;
Word[] allWords;

//rythm patterns for iambic tetrameter and trimeter - 0 is a soft
//stress, 1 a hard stress. tetram is the only one currently in use
//since makeTrimet only follows the syllable restriuction
//Note: this is oversimplified - actually 4 levels of stress in
//english.
int[] tetramPattern = {0,1,0,1,0,1,0,1};
int[] trimetPattern = {0,1,0,1,0,1};

ArrayList<Phrase> phrases;

//makes a gramatically correct english phrase of one of a set of 
//structures and randomly selected nouns
String makePhrase(){
  float chooser = random(0,360);
  int word1 = floor(random(nouns.length));
  int word2 = floor(random(nouns.length));
  String result; 
  if (chooser < 120) {
    // a noun for noun
    result = "a " + nouns[word1].sing + " for " 
              + nouns[word2].plur;
  } else if (chooser < 240) {
    // the noun noun
    result = "the " + nouns[word1].sing + " " + nouns[word2].sing;
  } else {
    // noun for noun
    if (chooser < 300) {
      result = nouns[word1].sing + " for " + nouns[word2].plur;
    } else {
      result = nouns[word1].plur + " for " + nouns[word2].plur;
    }
  }
  return result;
}

//adds a word's metre to the main pattern
int[] addWord( int[] pattern, Word newWord, int patternLen){
  /*println("adding" + newWord.sing + 
            "from " + patternLen + "to:");
  printArray(pattern);*/
  for(int i = 0; i < newWord.syllables; i++) {
    pattern[patternLen + i] = newWord.metre[i]; 
  }
  /*println("result:");
  printArray(pattern);*/
  return pattern;
}

//test wether a metre pattern follows the main pattern up to 
//the given size
Boolean followsMetre(int[] pattern, int[] testPattern, int size){
  for(int i = 0; i < size; i++){
    if (pattern[i] != testPattern[i]) {
      return false;
    }
  } 
  return true;
}


//maked a nonsense iambic tetrameter
String makeTetram(){
  int[] testPattern = new int[tetramPattern.length];
  int[] resultPattern = new int[tetramPattern.length];
  int currentLen = 0;
  int tryI = 0;
  int counter = 0;
  String result = ""; 
  Word tryWord;
  
  while (currentLen < tetramPattern.length) {
    tryI = floor(random(allWords.length));
    tryWord = allWords[(tryI + counter) % allWords.length];
    if ((currentLen + tryWord.syllables) <= tetramPattern.length){
      testPattern = addWord(resultPattern, tryWord, currentLen);
      if (followsMetre(tetramPattern, testPattern,
          currentLen + tryWord.syllables)) {
        resultPattern = testPattern;
        currentLen += tryWord.syllables;
        result = result + tryWord.sing + " ";
        counter = 0;
      } else { 
        testPattern = resultPattern;
      }
    }
    counter += 1;
    if (counter >= allWords.length) {
      /*println(currentLen);
      printArray(resultPattern);*/
      return result + "pain "; //code failure
    }
  }
  return result;
}

//chooses 2 words with total syllable cound of sylSum
WordTuple getWords(int sylSum){
  Word word1 = allWords[floor(random(allWords.length))];
  int[] nul = {};
  Word word2 = new Word("","",0,nul);
  int goalSyl = sylSum - word1.syllables;
  if(goalSyl == 0){
    return new WordTuple(word1, word2);
  }
  int tryI = floor(random(allWords.length));
  
  for(int i=0; i < allWords.length; i++){
    word2 = allWords[(tryI + i) % allWords.length];
    if(word2.syllables == goalSyl){
      return new WordTuple(word1, word2);
    }
  }
  return new WordTuple(word1, word2);
}

// makes a disyllabic trimeter loosely based off of the 
// phrase patterns
String makeTrimet(){
  float chooser = random(0,360);
  WordTuple choices;
  String result; 
  if (chooser < 120) {
    choices = getWords(4);
    result = "a " + choices.x.sing + " for " 
              + choices.y.plur;
  } else if (chooser < 240) {
    choices = getWords(5);
    result = "the " + choices.x.sing + " " + choices.y.sing;
  } else {
    choices = getWords(5);
    if (chooser < 300) {
      result = choices.x.sing + " for " + choices.y.plur;
    } else {
      result = choices.x.plur + " for " + choices.y.plur;
    }
  }
  return result;
}

void setup() {
  //sets up words - hard coding
  int[] feed4 = {0,1,0,1};
  confessional = new Word("confessional", 
                          "confessionals", 4, feed4);
  
  int[] feed3 = {1,0,1};
  studio = new Word("studio", "studios", 3, feed3); 
  Lebanon = new Word("Lebanon", "Lebanon", 3, feed3);
  int[] feed3a = {0,1,0};
  redouble = new Word("redouble", "redoubles", 3, feed3a);
  
  int[] feed2 = {1,0};
  diet = new Word("diet", "diets", 2, feed2); 
  timber = new Word("timber", "timber", 2, feed2); 
  int[] feed2a = {0,1};
  along = new Word("along", "along", 2, feed2a); 

  int[] feed1 = {1};  
  bee = new Word("bee", "bees", 1, feed1); 
  bone = new Word("bone", "bones", 1, feed1); 
  int[] feed1a = {0};
  of = new Word("of", "ofs", 1, feed1a); 
  forWord = new Word("for", "fors", 1, feed1a); 
  a = new Word("a", "a", 1, feed1a); 
  
  nouns = new Word[7];
  nouns[0] = studio;
  nouns[1] = bee;
  nouns[2] = Lebanon;
  nouns[3] = diet;
  nouns[4] = bone;
  nouns[5] = timber;
  nouns[6] = confessional;
  //nouns = {studio, bee, Lebanon, diet, bone, timber};
  allWords = new Word[12];
  allWords[0] = bee;
  allWords[1] = redouble;
  allWords[2] = Lebanon;
  allWords[3] = of;
  allWords[4] = diet;
  allWords[5] = confessional;
  allWords[6] = bone;
  allWords[7] = forWord;
  allWords[8] = studio;
  allWords[9] = timber;
  allWords[10] = along;
  allWords[11] = a;

  phrases = new ArrayList<Phrase>();

  size(800,500);
  frameRate(24);
  
  /*println(makePhrase());
  println("");
  println(makeTetram());
  println("");
  println(makeTrimet());*/
}

void draw() {
  background(0);
  Phrase phrase;
  for (int i = phrases.size()-1; i >= 0; i--) {
    phrase = phrases.get(i);
    phrase.update();
    phrase.display();
    if (phrase.finished()) {
      phrases.remove(i);
    }
  }
}

//what kind of phrase is selected based off of the mouse position
//when clicked3
void mousePressed() {
  println("mouse press:" + mouseX + "in" + width);
  if(mouseX < (width/3)){
    phrases.add(new Phrase(makePhrase(),mouseX, mouseY));
    println("phrase added");
  } else if(mouseX < 2*(width/3)){
    phrases.add(new Phrase(makeTrimet(),mouseX, mouseY));
    println("trimet added");
  } else {
    phrases.add(new Phrase(makeTetram(),mouseX, mouseY));
    println("tetram added");
  }
}

 

Comments are closed.