Skip to content

Instantly share code, notes, and snippets.

@shubanker
Last active March 7, 2022 12:49
Show Gist options
  • Save shubanker/afd98af53dab59e0966091ba42766004 to your computer and use it in GitHub Desktop.
Save shubanker/afd98af53dab59e0966091ba42766004 to your computer and use it in GitHub Desktop.
wordleunlimited AutoSolver
// ==UserScript==
// @name wordleunlimited autoMate
// @namespace https://www.wordleunlimited.com/
// @version 0.4
// @description Auto Solve Wordle Unlimited
// @author Shubanker Chourasia
// @match https://www.wordleunlimited.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=wordleunlimited.com
// @grant none
// @require https://cdn.jsdelivr.net/gh/pieroxy/lz-string/libs/lz-string.min.js
// ==/UserScript==
const sleep = (ms = 500) => new Promise((resolve) => setTimeout(resolve, ms));
class WordleSolver {
static wordsList = [];
static fetchWords = async () => {
const localJSON = localStorage.getItem("wordsList.min");
if (localJSON) {
try {
WordleSolver.wordsList = LZString.decompressFromBase64(localJSON).split(',');
return;
} catch (error) {}
}
const response = await fetch("https://api.npoint.io/3338e6baccc78823690d");
const words = await response.json();
WordleSolver.wordsList = words;
localStorage.setItem("wordsList.min", LZString.compressToBase64(words.join(',')));
//clearing older storages:
['wordsList2','wordsList'].forEach(k=>localStorage.removeItem(k));
};
static initialised = false;
/** @type Record<string,HTMLElement> */
static buttonMap = {};
/** @type String[] */
filteredList = [];
length = document.querySelector(".RowL").childNodes.length;
blackListChars = new Set();
/** @type Map<string,Set<Number> */
incorrectPositionsList = new Map();
identifiedPositionsMap = new Map();
identifiedIndexes = new Set();
checkedWords = new Set();
filledRowsCount = 0;
solveWordle = async () => {
await WordleSolver.initialise();
this.filteredList = WordleSolver.wordsList;
this.nextStep();
};
processEnteredRows = (startIndex = this.filledRowsCount) => {
const filledRows = document.querySelectorAll(".RowL-locked-in");
for (let i = startIndex; i < filledRows.length; i++) {
this.processesEnteredWordResults(filledRows[i].childNodes);
}
this.filterWordsList();
this.filledRowsCount = filledRows.length;
};
nextStep = async () => {
this.processEnteredRows();
const word =
this.filteredList[Math.floor(Math.random() * this.filteredList.length)];
WordleSolver.inputWord(word);
this.checkedWords.add(word);
await sleep();
if (
this.identifiedIndexes.size === this.length ||
document.querySelectorAll(".RowL-locked-in").length > 5 ||
this.filteredList.length === 0
) {
return this.done();
}
};
static inputWord = (word, pressEnter = true) => {
if (word) {
for (let i = 0; i < word.length; i++) {
WordleSolver.buttonMap[word[i]].click();
}
}
pressEnter && WordleSolver.buttonMap["enter"].click();
};
static async initialise() {
if (!WordleSolver.initialised) {
nextButton.disabled = true;
await WordleSolver.fetchWords();
WordleSolver.initialised = true;
nextButton.disabled = false;
}
}
/**
*
* @param {NodeListOf<ChildNode>} enteredChars
*/
processesEnteredWordResults(enteredChars) {
enteredChars.forEach((charNode, i) => {
const classes = [...charNode.classList];
const char = charNode.innerText.toLowerCase();
if (classes.includes("letter-elsewhere")) {
if (!this.incorrectPositionsList.has(char)) {
this.incorrectPositionsList.set(char, new Set());
}
this.incorrectPositionsList.get(char).add(i);
}
if (classes.includes("letter-correct")) {
if (!this.identifiedPositionsMap.has(char)) {
this.identifiedPositionsMap.set(char, new Set());
}
this.identifiedPositionsMap.get(char).add(i);
this.identifiedIndexes.add(i);
}
if (classes.includes("letter-absent")) {
this.blackListChars.add(char);
}
});
// for repeting chars, 2nd char is marked as absent.
for (const char of [
...this.incorrectPositionsList.keys(),
...this.identifiedPositionsMap.keys(),
]) {
this.blackListChars.delete(char);
}
}
filterWordsList() {
this.filteredList = this.filteredList.filter((word) => {
if (word.length !== this.length || this.checkedWords.has(word)) {
return false;
}
for (let i = 0; i < word.length; i++) {
const char = word[i];
if (this.blackListChars.has(char)) {
return false;
}
if (
this.identifiedIndexes.has(i) &&
!this.identifiedPositionsMap.get(char)?.has(i)
) {
return false;
}
if (
this.incorrectPositionsList.has(char) &&
this.incorrectPositionsList.get(char)?.has(i)
) {
return false;
}
}
const charSet = new Set(word);
for (const char of this.incorrectPositionsList.keys()) {
if (!charSet.has(char)) {
return false;
}
}
return true;
});
}
done() {
solveButton.hidden = false;
nextButton.hidden = true;
}
}
var solveButton = document.createElement("button");
var nextButton = document.createElement("button");
var revealAnswer = document.createElement("button");
(function () {
"use strict";
solveButton.innerHTML = "Auto Solve";
nextButton.innerHTML = "Next Step";
revealAnswer.innerHTML = "Reveal Answer";
nextButton.hidden = true;
document.querySelector(".game-icons.right-icons").appendChild(solveButton);
document.querySelector(".game-icons.right-icons").appendChild(nextButton);
document.querySelector(".Game").appendChild(revealAnswer);
var currentSolverObj = null;
solveButton.addEventListener("click", () => {
currentSolverObj = new WordleSolver();
nextButton.hidden = false;
solveButton.hidden = true;
currentSolverObj.solveWordle();
});
nextButton.addEventListener("click", () => {
currentSolverObj.nextStep();
});
revealAnswer.addEventListener("click", () => {
WordleSolver.inputWord(
atob(document.querySelector(".game-id").childNodes[1].textContent),
false
);
});
document.querySelectorAll(".Game-keyboard-button").forEach((button) => {
WordleSolver.buttonMap[button.textContent.toLowerCase()] = button;
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment