Text Twist Bot

written in bots, java, postmortem, project

source code
source game

Text Twist Bot is a bot made to play the anagram solving game Text Twist. Once ran, the bot will auto detect the location of the window, parse the current letters on the board, and automatically input all anagrams that can be found from those six letters. Of course solving anagrams is not new in the field of programming but whatever, revel in its glory!

In its most basic form, the Text Twist Bot is simply an anagram solver wrapped in a robot that detects the game board and inputs the letters. Upon execution, the program reads in an extensive list of english words. These words are placed as a value into a HashMap where their keys are the letters of the word but alphabetically ordered. This means that words like ‘eat’ and ‘tea’ will both have the keys of ‘aet’. You might then ask “But Jason, doesn’t HashMaps only accept unique key values?” then I’ll answer back “Why yes, that’s correct, that’s why I extended the base HashMap class with a MultiValueMap that automatically creates a Collection as a value when new values are added to the same key”. This means that no value with the same key will be overwritten but rather added onto in the collection. Initially I used a MultiValueMap from the apache commons collection library, but after being asked to implement it in an interview (that I bombed) I felt compelled to go back and re-implement it by extending the base HashMap class. Hashing and adding a word to the MultiValueMap takes constant time O(1) for each english word in the list meaning the whole process of adding all the words in the list runs in linear time O(n) where n is the number of words in the list. Now that all the words are processed in the map, I can now lookup anagrams of each groupings of letters at constant speed! Amazing!

Finding the location of the game board and the letters to use was another challenge. The Java class Robot definitely comes in handy when doing these kinds of screen reading actions. To determine the location of the board, I take a full screen picture of the primary monitor where I then go pixel by pixel looking for two specific origin pixels. Once these pixels are found, then I would know the origin of the game board as well as the location of the letters since the letter location is positioned relatively to the origin. I’m still not sure if doing these pixel by pixel searches to find something is the best way to go about it but after seeing how fast it goes about the search, I felt that it was a good enough solution for the problem at hand.

Now that I had the location of the game board I needed to find out the letters to solve an anagram for. Since I didn’t use any OCR technologies for this project, I needed a way to determine which letters were currently on the board. In Text Twist, the letters are represented by spheres. These spheres initially appear on the base row. When pressed, the letter then shifts up to the input row leaving behind an empty yellow sphere. Knowing this, I had the Robot type the alphabet multiple times for each letter in order then press enter. This would sort the letters and bring them back to the base row. I would then slowly type the alphabet in sequence and determine whether a letter was shifted to the input row by using pixel detection. If a letter had shifted, then we know the letter that was just typed is in play. This would continue until all letters were found. The letters would then be alphabetically sorted then passed into a Powerset generator where each set represents a key in the MultiValueMap. Once the values were found, it was game time and the Robot will feverishly type in the letters as fast as the game would take them, only stopping once it finished with inputting all words found.

Issues and Improvements

Of course everything isn’t all sunshine and rainbows. If the robot inputs the text too quickly, the game can’t process it and will ignore it often mucking up an answer and causing the game to stall. Delays were implemented to make the Robot delay each keypress by 15ms. Also, the word list that I found sometimes doesn’t have pluralized versions of the word meaning it usually will find a word but not its plural form. I had a create a cheap word pluraliser that doesn’t cover every instance. Also a word just may be missing from the word list which means I add it in manually after the game lets me know which words I missed. In short the bot isn’t perfect. More work can be put into it to make it have 100% word coverage but I think it does the job pretty well for now.