Wordles, Centaur and Code: Building a Game

Written by mcsee | Published 2022/10/16
Tech Story Tags: artificial-intelligence | tdd | test-driven-development | javascript | programming | machine-learning | code-generator | pixel-face | web-monetization

TLDRThe Conquest and Conquer is an analogy for serious software development. I will combine the TDD solution with an automated code generated using Artificial Intelligence. I have written several articles on software development using Wordle as an analogy. We have two repositories: The one with the Javascript Wordle made with TDD and the one with machine-generated code. We are re-building our valid game before building our UI. We create a text field to show status/errors to show users to end users. We replace the algorithmic error counts and count counts with our more robust ones. We re-create the state of our game with our new Wordle state.via the TL;DR App

Why you should use modern AI programming tools

I've been using Wordle as an analogy for serious software development.

In this article, I will combine the TDD solution that created a good model with an automated code generated using Artificial Intelligence.

TL;DR: Use the best available tools wisely

Divide and Conquer

The Division

I have written several articles on software development.

I will talk about Worlde to represent serious software.

I created a backend Wordle using TDD and PHP in the first one.

How to Develop a Wordle Game using TDD in 25 Minutes

Next, I watched a video on how to develop a Wordle using Automatic Code Generation fully.

Step by Step Wordle Creation With Codex AI

Since Wordle is another Kata, I keep practicing it with TDD using Javascript

How to Create a Wordle with TDD in Javascript

Now we have an amazing Wordle with a great domain model AND an incredible machine-learning user interface for it.

Let's combine them.

The Conquest

We have two repositories:

1 - The one with the Javascript Wordle made with TDD

https://replit.com/@mcsee/Wordle-TDD

https://github.com/mcsee/wordle/tree/main/How to Create a Wordle with TDD in Javascript

2 - The one with the machine-generated code

https://github.com/mcsee/wordle/tree/main/Open AI Codex from DotCSV

Playable Version (Live) With Defects

https://mcsee.github.io/wordle/DotCSV/index.html?embedable=true

Making it work together

We need to inject the changes into our main file.

Remember the scripted UI version was not modular.

We set up our valid game before building our UI

 const response = await fetch("dictionary.txt");
 const dictionary = await response.text();
 const words = dictionary.split(/\r?\n/).map((string) => new Word(string));

 var randomIndex = Math.floor(Math.random() * words.length);
 var winnerWord = words[randomIndex];

 var game = new Game(words, winnerWord);   

// Before we setup our UI.
// We want to create our valid working Game

We create a text field to show status/errors to end users

// Step 14 bis
/* add an input text field under the table */

var status = document.createElement('input');
status.setAttribute('type','text');
status.setAttribute('placeholder','');
status.id = 'status';
status.readOnly = true;
document.body.appendChild(status);
status.style.margin = '10px';
status.style.width = '300px';

This is not strictly necessary but it helps keep the UI as simple as possible.

// Step 17
/* create variable named 'rowindex' starting at 0 */

var rowIndex = game.wordsAttempted().length;

rowIndex variable is no longer global. We compute it tied to the attempts tried on the game.

We are reifing the state into our Game object

And this is when all magic happens.

We replace the algorithmic and error prune letter counts computations with our more robust ones

// Step 24
	  
/* when clicking validate button we add an attempt */

document.getElementById('validate').addEventListener('click', function(event) {
  var cells = document.querySelectorAll('td');
  var currentLetters = '';
  for (var i = 0; i < cells.length; i++) {
    if (i >= rowIndex * 5 && i < (rowIndex + 1) * 5) {
        currentLetters += cells[i].innerHTML ;
    }
  }  
  var status = document.getElementById('status');
  status.value = '';
  try { 
    var attempt = new Word(currentLetters);
    game.addAttempt(attempt);  
  }
  catch (error) { 
    status.value = error.message; 
    return;
  }  

  var correctMatches = attempt.matchesPositionWith(winnerWord); 
  var incorrectMatches = attempt.matchesIncorrectPositionWith(winnerWord); 
  
  for (var i = rowIndex * 5; i < (rowIndex + 1) * 5; i++) { 
    if (correctMatches.includes(i-(rowIndex * 5)+1)) { 
        cells[i].style.backgroundColor = '#aedb95'; 
    }
    if (incorrectMatches.includes(i-(rowIndex * 5)+1)) { 
        cells[i].style.backgroundColor = '#edc953'; 
    }
  }
  if (game.hasWon()){
     status.value = 'Congratulations. You won!';
  }
  if (game.hasLost()){
     status.value = 'Sorry. You have lost! Correct word was ' + winnerWord.word();
  }
  document.getElementById('input').value = '';
  rowIndex = game.wordsAttempted().length;
});

We put it as a very long function in the same event for clarification.

The model now raises exceptions following the fail-fast principle and we can show them to the final user.

This method requires heavy refactorization in a future article.

Finally, we reset the game.

This was one of the many mistakes corrected from the first version.

// Step 27

/* when pressing remove, chose randomly the secret word from the words collection */ 

document.getElementById('remove').addEventListener('click', function(event) {
  var randomIndex = Math.floor(Math.random() * words.length);
  winnerWord = words[randomIndex];
  game = new Game(words, winnerWord);   
});

There are repeated code at the start of the script.

You can play with the final version here

The source code is here

And a working repl.it here

The Disclaimer

The final code is full of refactoring opportunities and several code smells.

It is a proof of concept, not an elegant and final solution.

Credits

Image credit: A funny Twitter thread asking AIs to draw a Centaur

Also Published here


Written by mcsee | I’m senior software engineer specialized in declarative designs and S.O.L.I.D. and Agile lover.
Published by HackerNoon on 2022/10/16