Week 4 – Shahram Chaudhry – Antakshari

This project started with a simple yet poetic idea , visualizing lines from old Urdu poetry on screen, placing the main verse at the center and surrounding it with words from the next line, like floating thoughts. But then I began replacing those with some of my favorite Urdu song lyrics , the kind I really connect with , trying to merge different verses across songs to create something emotionally layered. That’s when I was reminded of Antakshari, a fun game many of us grew up playing. The rules are simple: one person sings a song, and the next person has to sing another song that starts with the last letter of the previous one. I loved the idea of using that structure as the basis for generative text. I initially wanted to build this fully in Urdu, but I realized it would be tricky to detect and match the last letter accurately in the script. So, I switched to English to get the logic working smoothly. Instead of full lyrics, I used individual words and for each word, the next one is chosen randomly from a list of possible options starting with the last letter. That means each run of the program generates a unique chain of words, but with a meaningful constraint just like Antakshari. I also added visual flair: a short delay between words, small random rotations and scaling for different text sizes so it wouldn’t look like a grid structure and feel a little unpredictable.

The two functions placeWord() and pickNextWord() were the heart of my sketch. I was particularly proud of how I used my prior knowledge of dictionaries to implement the words dictionary, which acts as a lookup system. It takes the last letter of the previous word and finds a list of possible next words starting with that letter. Then I randomly select one to create branching possibilities making the output  different every time.

In placeWord(), I figured out how to make each word feel organic and unique by adding randomness to its angle and size using random(-PI/16, PI/16) and a scaling factor. I also calculated the text width dynamically so I could position the next word without overlap between words. These choices made the flow of words appear natural.

function placeWord(word) {
  let fontOriginalSize = 24;
  let wordMargin = 8; 

  let angle = random(-PI / 16, PI / 16);
  let scaleFactor = random(0.9, 1.3);
  //find color from colormap
  let firstLetter = word.charAt(0).toLowerCase();
  let wordColor = colorMap[firstLetter];
  
  
  textSize(fontOriginalSize * scaleFactor);
  let wordWidth = textWidth(word);

  placedWords.push({
    word: word,
    x: gridX,
    y: gridY + random(-3, 3),
    size: fontOriginalSize * scaleFactor,
    angle: angle,
    color: wordColor
  });
  
  //move the horizontal position to right for next word
  gridX += wordWidth + wordMargin;
  
  //starts a new line/row
  if (gridX > width - 100) {
    gridX = 50;
    gridY += gridSpacing;
  }
  //canvas not filled checked by seeing if we reach bottom or not
  if (autoRun && gridY < height - 50) {
    pickNextWord();
    lastPlacedWord = nextWord;
    setTimeout(() => placeWord(nextWord), 150);
  }
}
function pickNextWord() {
  let lastLetter = lastPlacedWord.charAt(lastPlacedWord.length - 1).toLowerCase();
  //find the candidate words using lastletter and choose a random word
  let candidates = words[lastLetter];
  nextWord = random(candidates);
}

Here’s the sketch:

Eventually, I’d love to go back to my original vision and bring Urdu fully into the experience. That would mean figuring out last-letter detection in Urdu script and possibly integrating a calligraphic font to preserve the beauty of the language. If I can pull that off, the result would be a truly generative, Urdu Antakshari as a perfect blend of nostalgia, music, and generative text. 

 



Leave a Reply