From a44bec8d3cfa0c16ad40f45bc1f7c37670c0412a Mon Sep 17 00:00:00 2001 From: Yuval Ben-Hayun Date: Mon, 21 Nov 2022 15:59:54 -0500 Subject: [PATCH] warmle bot & color coded multibots --- index.html | 3 +- js/bot.js | 8 +- js/class.js | 180 +++++++++++++++++++------ js/main.js | 381 +++++++++++++++++++++++++++++++--------------------- js/setup.js | 42 +++++- wordl.css | 49 ++++++- 6 files changed, 465 insertions(+), 198 deletions(-) diff --git a/index.html b/index.html index a4aa444..018dc76 100644 --- a/index.html +++ b/index.html @@ -74,6 +74,7 @@

Choose Your Bot

+ @@ -83,6 +84,7 @@

Choose Your Bot

+

@@ -104,7 +106,6 @@

-
diff --git a/js/bot.js b/js/bot.js index dcdeece..de688a1 100644 --- a/js/bot.js +++ b/js/bot.js @@ -156,7 +156,7 @@ function swapDiv(event, elem) { } function setupTest(word) { - if (bot.isFor(XORDLE) || bot.isFor(FIBBLE)) { + if (bot.isFor(XORDLE) || bot.isFor(FIBBLE) || bot.getCount() > 2) { return; } @@ -319,7 +319,7 @@ function runBot(guess, difficulty) { let iv = setInterval(function() { clearGrids(); let points = wordleBot(guess, testing_sample[count], difficulty); - if (points > bot.guessesAllowed(difficulty)) { + if (points > bot.guessesAllowed()) { missed.push(testing_sample[count]); } @@ -371,7 +371,7 @@ function updateWordData(guess, average, wrong, difficulty) { if (TEST_SIZE < common.length) return; if (!newlist.length) { - if (isDifficulty(HARD, difficulty) && bot.hasHardMode()) newlist = hard; + if (isDifficulty(HARD) && bot.hasHardMode()) newlist = hard; else newlist = easy; } @@ -397,7 +397,7 @@ function wordleBot(guess, answer, difficulty) { let attempts = 1; let correct = 0; - while (attempts <= bot.guessesAllowed(difficulty)) { + while (attempts <= bot.guessesAllowed()) { makeTables(guess, "testing"); let diff; diff --git a/js/class.js b/js/class.js index c948c92..4e275eb 100644 --- a/js/class.js +++ b/js/class.js @@ -10,6 +10,7 @@ const HARDLE = 'Hardle'; const DORDLE = 'Dordle'; const QUORDLE = 'Quordle'; const OCTORDLE = 'Octordle'; +const WARMLE = 'Warmle'; class Bot { @@ -22,14 +23,15 @@ class Bot { } hasHardMode() { - return this.type == WORDLE || this.type == ANTI; + // return this.type == WORDLE || this.type == ANTI; + return true; } hasMax() { return this.type != ANTI; } - guessesAllowed(difficulty) { + guessesAllowed() { if (this.type == ANTI) return INFINITY; return parseInt(document.getElementById('max-guesses').value); } @@ -45,13 +47,21 @@ class Bot { getDifference(word1, word2) { if (this.type == WOODLE) { return differencesWithoutPositions(word1, word2); - } else if (this.type == PEAKS) { + } + + if (this.type == PEAKS) { return getAlphabeticDifferences(word1, word2); - } else if (typeof word2 == 'object') { + } + + if (typeof word2 == 'object') { return getDoubleDifference(word1, word2); - } else { - return differencesWithPositions(word1, word2); + } + + if (this.type == WARMLE) { + return getWarmleDifferences(word1, word2); } + + return differencesWithPositions(word1, word2); } getRowColor(row_number) { @@ -75,11 +85,15 @@ class Bot { } getBestLetters(list) { - if (this.type != PEAKS) { - return mostCommonLetters(list); - } else { + if (this.type == PEAKS) { return lettersClosestToCenter(list); - } + } + + if (this.type == WARMLE) { + return bestWarmleLetters(list); + } + + return mostCommonLetters(list); } reducesListBest(answers, guesses, future_guess) { @@ -138,6 +152,22 @@ class Bot { return list; } + + getAnswerListLength(answers) { + if (bot.getCount() > 1) { + return lengthOfAllLists(answers); + } + + return answers.length; + } + + isLikely(answer) { + if (this.type == XORDLE && typeof answer == 'object') { + return this.isLikely(answer.word1) && this.isLikely(answer.word2); + } + + return common.includes(answer); + } } function isHigher(a, b) { @@ -208,13 +238,11 @@ function differencesWithPositions(word1, word2) { let word1_c = temp1.charAt(j); if (temp2.includes(word1_c)) { - // diff = diff.slice(0, pos) + WRONG_SPOT + diff.slice(pos+1); diff = replaceAt(diff, WRONG_SPOT, pos); let index = temp2.indexOf(word1_c); temp2 = temp2.slice(0, index) + temp2.slice(index+1); } else { - // diff = diff.slice(0, pos) + INCORRECT + diff.slice(pos+1); diff = replaceAt(diff, INCORRECT, pos); } @@ -276,21 +304,6 @@ function rowDifferencesWithPairs(row_number) { } return colors; - - // let row = document.getElementsByClassName("row"); - // let left = row[row_number*2]; - // let right = row[row_number*2+1]; - // let coloring = ""; - - // for (let i = 0; i < word_length; i++) { - // coloring += getTileColor(left.getElementsByClassName('tile')[i]) - // } - - // for (let i = 0; i < word_length; i++) { - // coloring += getTileColor(right.getElementsByClassName('tile')[i]) - // } - - // return coloring; } function getAlphabeticDifferences(word1, word2) { @@ -301,9 +314,28 @@ function getAlphabeticDifferences(word1, word2) { if (a == b) { diff += CORRECT; } else if (a > b) { - diff += 'B'; + diff += INCORRECT; } else if (a < b) { - diff += 'Y'; + diff += WRONG_SPOT; + } + } + + return diff; +} + +function getWarmleDifferences(word1, word2) { + let diff = ""; + let distance = document.getElementsByClassName('warmle-selector')[0].value; + + for (let i = 0; i < word_length; i++) { + let a = word1.charAt(i).charCodeAt(0), b = word2.charAt(i).charCodeAt(0); + + if (a == b) { + diff += CORRECT; + } else if (Math.abs(a-b) <= distance ) { + diff += WRONG_SPOT; + } else { + diff += INCORRECT; } } @@ -413,15 +445,7 @@ function setRowDifferencesWithoutPositions(coloring, row) { function mostCommonLetters(list) { if (!list.length) return []; - let letters = []; - - for (let c = 65; c <= 90; c++) { - letters[String.fromCharCode(c)] = []; - for (let i = 0; i < parseInt(word_length)+1; i++) { - letters[String.fromCharCode(c)].push(0); - } - } - + let letters = makeAlphabetArray(parseInt(word_length)+1); let checked; for (let i = 0; i < list.length; i++) { @@ -454,6 +478,64 @@ function lettersClosestToCenter() { return letters; } +function bestWarmleLetters(list) { + let letters = makeAlphabetArray(parseInt(word_length)+1); + + list.forEach(function(word) { + for (let i = 0; i < word_length; i++) { + let c = word.charAt(i); + letters[c][i]++; + letters[c][word.length]++; + } + }); + + let new_letters = makeAlphabetArray(parseInt(word_length)+1); + + for (let i = 65; i <= 90; i++) { + let pos = intToChar(i); + + for (let j = 0; j < word_length; j++) { + new_letters[pos][j] = letters[pos][j]; + + let distance = document.getElementsByClassName('warmle-selector')[0].value; + for (let k = 1; k <= distance; k++) { + let c = charToInt(pos)+k; + + if (c <= 90) { + c = intToChar(c); + new_letters[pos][j] += letters[c][j]; + } + + c = charToInt(pos)-k; + if (c >= 65) { + c = intToChar(c); + new_letters[pos][j] += letters[c][j]; + } + } + + } + + new_letters[pos][word_length] = letters[pos][word_length]; + } + + return new_letters; +} + +function makeAlphabetArray(size) { + let letters = []; + + for (let i = 65; i <= 90; i++) { + let c = String.fromCharCode(i); + + letters[c] = []; + for (let i = 0; i < size; i++) { + letters[c].push(0); + } + } + + return letters; +} + function reducesListMost(answers, guesses, future_guess) { let best_words = []; let min = answers.length; @@ -465,6 +547,7 @@ function reducesListMost(answers, guesses, future_guess) { let data_per_list = []; for (let j = 0; j < answers.length; j++) { + min = answers[j].length; data_per_list.push(calculateAverageBucketSize(guesses[i], answers[j], min, future_guess)); } @@ -599,6 +682,10 @@ function getHardleDiffs(diff) { let differences = [diff]; let new_diff = ""; + if (diff == WRONG_SPOT.repeat(word_length)) { + return differences; + } + for (let i = 0; i < diff.length; i++) { if (diff.charAt(i) == CORRECT) { new_diff += WRONG_SPOT; @@ -672,7 +759,7 @@ function findWrongSpotLetters(diff, guess) { // find index of every Y character in the differences let wrong_spots = allInstancesOf(WRONG_SPOT, diff); let correct = allInstancesOf(CORRECT, diff); - let indices = wrong_spots.concat(correct); + let indices = combineLists(wrong_spots, correct); let c = []; // indentify all letters marked as Y @@ -683,3 +770,18 @@ function findWrongSpotLetters(diff, guess) { c = [...new Set(c)]; return c; } + +function lengthOfAllLists(lists) { + if (lists.length && typeof lists[0] == 'string') { + return lists.length; + } + + let new_list = []; + + lists.forEach(function(a) { + new_list = combineLists(new_list, a); + }); + + new_list = uniqueWordsFrom(new_list); + return new_list.length; +} \ No newline at end of file diff --git a/js/main.js b/js/main.js index 2b633a3..20552ab 100644 --- a/js/main.js +++ b/js/main.js @@ -43,7 +43,7 @@ function setLength() { clearHTML(document.getElementById('next-previous-buttons')); words = big_list.filter((a) => a.length == word_length); - // words = official_guesses.slice(); // uncomment to use original wordle guess list + words = official_guesses.slice(); // uncomment to use original wordle guess list clearGrids(); setWordbank(); @@ -71,7 +71,7 @@ function setWordbank() { common = common.filter(a => a.length == word_length).sort(); common = [...new Set(common)]; - // common = officical_answers.slice(); // uncomment to use original wordle answer list + common = officical_answers.slice(); // uncomment to use original wordle answer list } function getBestOf(list) { @@ -96,7 +96,7 @@ function update() { let difficulty = NORMAL; if (bot.hasHardMode()) { - difficulty = Number(document.getElementById("mode").checked); + difficulty = getDifficulty(); } let lists = getPotentialGuessesAndAnswers(difficulty); @@ -110,7 +110,7 @@ function update() { best_guesses = best_guesses.filter(function(e) {return e.word !== getWord(i);}); } - updateLists(lists.all, lists.answers, lists.unlikely, best_guesses); + updateLists(lists.all, lists.answers, lists.unlikely, best_guesses, lists.unique); } function uniqueWordsFrom(list) { @@ -119,7 +119,7 @@ function uniqueWordsFrom(list) { if (typeof list[0] == 'object') { let unique = []; for (let i = 0; i < list.length; i++) { - unique = unique.concat(Object.values(list[i])); + unique = combineLists(unique, Object.values(list[i])); } return [... new Set(unique)]; @@ -132,15 +132,37 @@ function dontNeedToCheck(answers, unique_answers) { || numberOfGuessesSoFar(0) } -function getPotentialGuessesAndAnswers(difficulty) { - let answer_list = bot.getAllPossibleAnswersFrom(common.slice()); - let unique_answers = uniqueWordsFrom(answer_list); - let all_possible_words = uniqueWordsFrom(filterList(words.slice(), 0, 0, bot.getCount() > 1)); - let unlikely_answers = all_possible_words.filter(a => !unique_answers.some(b => b == a)); +function separateListByLikelihood(list) { + let likely = []; + let unlikely = []; + + for (let i = 0; i < list.length; i++) { + if (Array.isArray(list[i])) { + let new_lists = separateListByLikelihood(list[i]); + likely.push(new_lists.likely); + unlikely.push(new_lists.unlikely) + } + + else if (bot.isLikely(list[i])) { + likely.push(list[i]); + } + + else { + unlikely.push(list[i]); + } + } - if (dontNeedToCheck(answer_list, unique_answers)) { - if (!bot.isFor(XORDLE)) answer_list = unique_answers; + return {likely: likely, unlikely: unlikely}; +} +function getPotentialGuessesAndAnswers(difficulty) { + let all_possible_words = bot.getAllPossibleAnswersFrom(words.slice()); + let separated_lists = separateListByLikelihood(all_possible_words); + let answer_list = separated_lists.likely; + let unlikely_answers = separated_lists.unlikely; + let unique_answers= uniqueWordsFrom(answer_list); + + if (dontNeedToCheck(answer_list, unique_answers)) { return { guesses: unique_answers, answers: answer_list, @@ -152,13 +174,8 @@ function getPotentialGuessesAndAnswers(difficulty) { let alphabet = bot.getBestLetters(unique_answers); let sorted_answer_list = sortList(unique_answers, alphabet); - let sorted_guess_list = initialGuesses(answer_list, sorted_answer_list, unique_answers, all_possible_words, alphabet, difficulty); + let sorted_guess_list = initialGuesses(answer_list, sorted_answer_list, unique_answers, all_possible_words, alphabet); - if (bot.getCount() > 1) { - sorted_guess_list = answerAlreadyFound(sorted_guess_list, answer_list); - // answer_list = uniqueWordsFrom(answer_list); - } - return { guesses: sorted_guess_list, answers: answer_list, @@ -168,15 +185,17 @@ function getPotentialGuessesAndAnswers(difficulty) { }; } -function initialGuesses(answer_list, sorted_answer_list, unique_answers, all_possible_words, alphabet, difficulty) { +function initialGuesses(answer_list, sorted_answer_list, unique_answers, all_possible_words, alphabet) { let sorted_guess_list = words.slice(); if (bot.isFor(THIRDLE)) sorted_guess_list = allCombinations("", []); if (twoAnswersLeft(answer_list) && !bot.isFor(ANTI)) { - sorted_guess_list = unique_answers; - } else if (isDifficulty(HARD, difficulty)){ - sorted_guess_list = all_possible_words.slice(); + // sorted_guess_list = unique_answers; + sorted_guess_list = sorted_answer_list; + } else if (isDifficulty(HARD)){ + sorted_guess_list = uniqueWordsFrom(all_possible_words.slice()); + // sorted_guess_list = unique_answers.slice(); } else if (bot.isFor(ANTI)) { sorted_guess_list = filterList(sorted_guess_list, 0, true); } @@ -184,11 +203,12 @@ function initialGuesses(answer_list, sorted_answer_list, unique_answers, all_pos sorted_guess_list = sortList(sorted_guess_list, alphabet); if (!bot.isFor(ANTI)) { - sorted_guess_list = [...new Set(unique_answers.concat(sorted_guess_list))]; + sorted_guess_list = combineLists(sorted_answer_list, sorted_guess_list); } - new_lists = reduceListSize(sorted_guess_list, sorted_answer_list, answer_list.length); - sorted_guess_list = new_lists.guesses; + sorted_guess_list = reduceListSize(sorted_guess_list, sorted_answer_list, bot.getAnswerListLength(answer_list)); + // new_lists = reduceListSize(sorted_guess_list, sorted_answer_list, bot.getAnswerListLength(answer_list)); + // sorted_guess_list = new_lists.guesses; return sorted_guess_list; } @@ -201,14 +221,30 @@ function twoAnswersLeft(answers) { return uniqueWordsFrom(answers).length <= 2; } -function answerAlreadyFound(guesses, answer_lists) { +function getUnfoundAnswers(answer_lists) { + unfound_answers = []; + for (let i = 0; i < answer_lists.length; i++) { if (answer_lists[i].length == 1) { - return answer_lists[i]; + unfound_answers.push(answer_lists[i][0]); } } - return guesses; + + for (let i = 0; i < guessesSoFar(); i++) { + let colors = bot.getRowColor(i); + + if (colors.includes(CORRECT.repeat(word_length))) { + let pos = unfound_answers.indexOf(getWord(i)); + + if (pos != -1) { + unfound_answers.splice(pos, 1); + } + } + } + + + return unfound_answers; } function allCombinations(string, list) { @@ -227,19 +263,10 @@ function allCombinations(string, list) { // updates the headers to reflect how many words are left // adds those suggestions to the respective slides // creates a dropdown list showing all possible words -function updateLists(words_left, likely_answers, unlikely_answers, best_guesses) { - if (bot.getCount() > 1) { - likely_answers = uniqueWordsFrom(likely_answers); - } - - let list_length = Math.min(likely_answers.length, TOP_TEN_LENGTH); +function updateLists(words_left, likely_answers, unlikely_answers, best_guesses, unique_answers) { + let list_length = Math.min(bot.getAnswerListLength(likely_answers), TOP_TEN_LENGTH); let guess_list = writeBestGuessList(best_guesses, list_length); - if (bot.isFor(XORDLE)) { - unlikely_answers = xordleFilter(unlikely_answers); - // unlikely_answers = uniqueWordsFrom(unlikely_answers); - } - updateHeaders(words_left, likely_answers, unlikely_answers); addToSlides("Your best possible guesses are:", guess_list); createAnswerDropdown(likely_answers, unlikely_answers); @@ -248,18 +275,24 @@ function updateLists(words_left, likely_answers, unlikely_answers, best_guesses) return addToSlides("", noWordsLeftMessage()); } - if (likely_answers.length <= 2 && !bot.isFor(ANTI)) { + if (bot.getAnswerListLength(likely_answers) <= 2 && !bot.isFor(ANTI)) { // will only show the final two options as suggestions // ie: 'its either 'THIS' or 'THAT' return showFinalOptions(likely_answers, unlikely_answers); } + + let unfound_answers = getUnfoundAnswers(likely_answers); + if (unfound_answers.length) { + addToSlides("", unfoundAnswersMessage(unfound_answers)); + } } // creates and returns the top 10 list of suggestions // suggestions will then be added to the HTLM of either the suggestions // for hard mode or normal mode function writeBestGuessList(guesses, list_length) { - let data, list = ""; + let data = ""; + let list = []; for (let i = 0; i < list_length && i < guesses.length; i++) { let num_guesses = (guesses[i].average - guessesSoFar()).toFixed(3); @@ -273,7 +306,8 @@ function writeBestGuessList(guesses, list_length) { data = num_guesses + " guesses" } else data = num_guesses + " guesses left"; - list += createListItem(guesses[i].word, data, i+1); + let list_item = createListItem(guesses[i].word, data, i+1); + list.push(list_item); } return list; @@ -286,7 +320,7 @@ function createListItem(word, data, rank) { let list_item = createElement('li', word_with_ranking.outerHTML + score.outerHTML); - return list_item.outerHTML; + return list_item; } function enterGuess(word) { @@ -296,13 +330,16 @@ function enterGuess(word) { function updateHeaders(words_left, likely_answers, unlikely_answers) { let heading = document.getElementsByClassName("possibilities total")[0]; let subheading = document.getElementsByClassName("possibilities separated")[0]; + let likely_length = bot.getAnswerListLength(likely_answers); + let unlikely_length = bot.getAnswerListLength(unlikely_answers); + let total_length = unlikely_length + likely_length; let class_name = "class = 'showlist'>
"; - if (words_left.length == words.length) class_name = ">"; + if (total_length == words.length) class_name = ">"; - heading.innerHTML = words_left.length + " possibilit" + ((words_left.length != 1) ? "ies" : "y"); - subheading.innerHTML = ", " - + "."; + heading.innerHTML = total_length + " possibilit" + ((total_length != 1) ? "ies" : "y"); + subheading.innerHTML = ", " + + "."; } // creates a dropdown of all possible words left @@ -314,65 +351,107 @@ function createAnswerDropdown(likely_answers, unlikely_answers) { let word_lists = document.getElementsByClassName("showlist"); let potential_answers = word_lists[0].getElementsByTagName("div")[0]; let technically_words = word_lists[1].getElementsByTagName("div")[0]; - let likely_list = unlikely_list = ""; for (let i = 0; i < likely_answers.length; i++) { - likely_list += printAnswer(likely_answers[i]) + "
"; + addWordsToDiv(likely_answers[i], potential_answers, bot.getCount() > 1 ? COLORS[i] : "black"); } - potential_answers.innerHTML = "

" + likely_list + "

"; for (let i = 0; i < unlikely_answers.length; i++) { - unlikely_list += printAnswer(unlikely_answers[i]) + "
"; + addWordsToDiv(unlikely_answers[i], technically_words, bot.getCount() > 1 ? COLORS[i] : "black"); } - technically_words.innerHTML = "

" + unlikely_list + "

"; - if (likely_answers.length < 1) { - clearHTML(potential_answers); + if (bot.getAnswerListLength(likely_answers) < 1) { + setHTML(potential_answers, "goose egg"); } - if (unlikely_answers.length < 1) { - clearHTML(technically_words); + if (bot.getAnswerListLength(unlikely_answers) < 1) { + setHTML(technically_words, "goose egg") } } +const COLORS = [ + "black", "green", "blue", "red", "purple", "orange", "brown", "gray" +]; + +function addWordsToDiv(words, div, color) { + if (Array.isArray(words)) { + for (let i = 0; i < words.length; i++) { + addWordsToDiv(words[i], div, color); + } + } else { + let answer = createElement('p', printAnswer(words), color); + div.append(answer); + } + +} + const NO_WORDS_LEFT_MESSAGE = "it doesn't look like we have this word. double check to make sure you all the clues you entered are correct."; function noWordsLeftMessage() { let message = createElement('div', NO_WORDS_LEFT_MESSAGE, '', 'nowords') - return message.outerHTML; + return [message]; +} + +function unfoundAnswersMessage(unfound_answers) { + let text = unfound_answers.length + " of the answers " + pluralOrSingle(unfound_answers.length, "is ", "are "); + + for (let i = 0; i < unfound_answers.length; i++) { + let answer = createElement('span', printAnswer(unfound_answers[i]), 'final'); + text += answer.outerHTML; + + if (i == unfound_answers.length-1) { + text += "." + } + + else if (i == unfound_answers.length-2) { + text += ", and "; + } else { + text += ", "; + } + } + + let message = createElement('div', text, 'multi-answer'); + return [message]; } // only called if there are less than two likely answers left // shows: almost certainly 'THIS' or 'THAT' // unlikely but it could be: 'SOMETHING', 'ELSE' function showFinalOptions(sorted, less_likely) { - let final_words = ""; + let all_suggestions = []; - if (sorted.length) { - final_words += "
  • the word is almost certainly "; + if (bot.getCount() > 1) { + sorted = uniqueWordsFrom(sorted); + less_likely = uniqueWordsFrom(less_likely); + } + + if (bot.getAnswerListLength(sorted)) { + let final_words = createElement('li', '', 'likely'); + let first_answer = createElement('span', printAnswer(sorted[0]), 'final'); + final_words.innerHTML = "The word is almost certainly " + first_answer.outerHTML; if (sorted.length == 2) { - final_words += "" + printAnswer(sorted[0]) + " or " + printAnswer(sorted[1]) + "
  • "; - } + let second_answer = createElement('span', printAnswer(sorted[1]), 'final'); + final_words.innerHTML += " or " + second_answer.outerHTML; + } - else { - final_words += "" + printAnswer(sorted[0]) + ""; - } + final_words.innerHTML += "."; + all_suggestions.push(final_words); } - if (less_likely.length) { - final_words += "
  • Unlikely, but it might be "; + if (bot.getAnswerListLength(less_likely)) { + let unlikely = createElement('li', "Unlikely, but it might be ", 'others'); for (let i = 0; i < less_likely.length; i++) { - final_words += "" + printAnswer(less_likely[i]) + ""; + let unlikely_answer = createElement('span', printAnswer(less_likely[i]), 'final'); + unlikely.innerHTML += unlikely_answer.outerHTML; - if (i < less_likely.length - 1) final_words += ", "; - else final_words += "." + (i < less_likely.length - 1) ? unlikely.innerHTML += ", " : unlikely.innerHTML += "."; } - final_words += "
  • "; + all_suggestions.push(unlikely); } - addToSlides("", final_words); + addToSlides("", all_suggestions); } function printAnswer(answer) { @@ -380,35 +459,27 @@ function printAnswer(answer) { return createElement('span', answer, 'click').outerHTML; } - if (Array.isArray(answer)) { - return printAnswer(array[0]); + if (Array.isArray(answer) && answer.length) { + return printAnswer(answer[0]); } - return printAnswer(answer.word1) + "/" + printAnswer(answer.word2); + if (typeof answer == 'object' && bot.isFor(XORDLE)) { + return printAnswer(answer.word1) + "/" + printAnswer(answer.word2); + } } // adds the heading, normal suggestsions, and hard suggestions // to the respective HTML element -function addToSlides(heading, suggestions) { +function addToSlides(heading_html, suggestions) { let header = document.getElementsByClassName("mini-title")[0]; - let list = document.getElementsByClassName('best-guesses')[0]; - - header.innerHTML = heading; - list.getElementsByTagName('ul')[0].innerHTML = suggestions; -} - -function swapSlides(normal_slides, hard_slides, hard_mode) { - let norm_pos = getSlidePosition(normal_slides); - let hard_pos = norm_pos == 'front' ? 'back' : 'front'; - - normal_slides[0].classList.replace(norm_pos, hard_pos); - hard_slides[0].classList.replace(hard_pos, norm_pos); + let list = document.getElementsByClassName('best-guesses')[0].getElementsByTagName('ul')[0]; - hard_mode ? localStorage.setItem('difficulty', true) : localStorage.removeItem('difficulty'); -} + setHTML(header, heading_html); + clearHTML(list); -function getSlidePosition(slide) { - return Array.from(slide[0].classList).filter(a => a == 'back' || a == 'front'); + suggestions.forEach(function(a) { + list.append(a); + }); } // returns the number of guesses made to far @@ -422,10 +493,14 @@ function numberOfGuessesSoFar(number) { } // checks if we're playing on hard mode or normal mode -// mode --> the mode we want to see if we're playing -// check --> the mode we are currently playing on -function isDifficulty(mode, check) { - return mode == check; +function isDifficulty(difficulty) { + return getDifficulty() == difficulty; +} + +function getDifficulty() { + if (document.getElementById('results')) return true; + + return Number(document.getElementById("mode")?.checked); } /* @@ -434,14 +509,14 @@ function isDifficulty(mode, check) { modifies the tiles/buttons when clicked accesses information about the guesses/current state */ - function makeTables(val, c) { if (c == null) c = "normal"; + let grids = document.getElementsByClassName('grid'); if (val) { for (let i = 0; i < bot.getCount(); i++) { let row = createRow(val, c); - document.getElementsByClassName("grid")[i].append(row); + grids[i].append(row); bot.setChangeEvents(row); } } @@ -453,6 +528,7 @@ function makeTables(val, c) { } document.getElementById("word-entered").value = ""; + clearValue(document.getElementById('word-entered')); } function createRow(word, mode) { @@ -482,20 +558,22 @@ function makeWoodleDropdowns() { } function addButtons() { - let buttons = ""; - buttons += ""; + let undo = createElement('button', 'remove last guess', 'undo'); + let filter = createElement('button', 'calculate next guess', 'filter'); + let button_container = document.getElementById('next-previous-buttons'); - document.getElementById('next-previous-buttons').innerHTML += buttons; + button_container.append(undo); + button_container.append(filter); - document.getElementsByClassName('filter')[0].addEventListener('click', function() { + filter.addEventListener('click', function() { let difficulty = NORMAL; if (bot.hasHardMode()) { - difficulty = Number(document.getElementById("mode").checked); + difficulty = getDifficulty(); } update(difficulty); }); - document.getElementsByClassName('undo')[0].addEventListener('click', function() { + undo.addEventListener('click', function() { let grids = document.getElementsByClassName('grid'); for (let i = 0; i < grids.length; i++) { @@ -511,7 +589,7 @@ function addButtons() { let difficulty = NORMAL; if (bot.hasHardMode()) { - difficulty = Number(document.getElementById("mode").checked); + difficulty = getDifficulty(); } update(difficulty); }); @@ -547,7 +625,8 @@ function guessesArePrecomputed(difficulty) { word += getWord(i); } - let hash = makeHash(bot.type, wordbank, difficulty, bot.guessesAllowed(difficulty), diff); + let hash = makeHash(bot.type, wordbank, difficulty, + bot.guessesAllowed(), document.getElementsByClassName('warmle-selector')[0]?.value, diff); if (seconds[word] != null) { if (seconds[word][hash] != null) { @@ -558,8 +637,8 @@ function guessesArePrecomputed(difficulty) { return 0; } -function makeHash(game, list_type, difficulty, guesses, string) { - return game + "/" + list_type + "/" + difficulty + "/" + guesses + "/" + string; +function makeHash(game, list_type, difficulty, guesses, extras, string) { + return game + "/" + list_type + "/" + difficulty + "/" + guesses + "/" + extras + "/" + string; } function setBestGuesses(best_guesses, difficulty) { @@ -570,7 +649,8 @@ function setBestGuesses(best_guesses, difficulty) { word += getWord(i); } - let hash = makeHash(bot.type, wordbank, difficulty, bot.guessesAllowed(difficulty), diff); + let hash = makeHash(bot.type, wordbank, difficulty, bot.guessesAllowed(), + document.getElementsByClassName('warmle-selector')[0]?.value, diff); seconds[word][hash] = JSON.stringify(best_guesses.slice(0, TOP_TEN_LENGTH)); } @@ -582,10 +662,17 @@ function getBestGuesses(answer_list, guess_list, difficulty, unique_answers) { return twoSort(best_guesses); } - if (numberOfGuessesSoFar(0)) return getFirstGuesses(difficulty); - if (answer_list.length > 1000) return getTempList(guess_list, answer_list); + if (numberOfGuessesSoFar(0)) { + return getFirstGuesses(difficulty); + } + + if (answer_list.length > 1000) { + return getTempList(guess_list, answer_list); + } - if (guessesSoFar() == bot.guessesAllowed()-1) guess_list = unique_answers; + if (guessesSoFar() == bot.guessesAllowed()-1) { + guess_list = unique_answers; + } let initial_guesses = bot.reducesListBest(answer_list, guess_list); @@ -607,29 +694,24 @@ function reduceListSize(guesses, answers, answers_size) { } const MAXIMUM = 100000; - let reduced = false; + // let reduced = false; if (answers_size * guesses.length * bot.getCount() > MAXIMUM) { - guesses = combineLists(answers, guesses); + // if (!bot.isFor(ANTI)) { + // guesses = combineLists(answers, guesses); + // } let current = answers_size * guesses.length * bot.getCount(); let ratio = current/MAXIMUM; guesses = guesses.slice(0, guesses.length/ratio); - reduced = true; + // reduced = true; } for (let guess = 0; guess < guessesSoFar(); guess++) { guesses = guesses.filter(a => a != getWord(guess)); } - return {guesses: guesses, answers: answers, reduced: reduced}; -} - -function combineLists(answers, guesses) { - if (!bot.isFor(ANTI)) { - return [...new Set(answers.concat(sortList(guesses, bot.getBestLetters(answers))))]; - } - + // return {guesses: guesses, answers: answers, reduced: reduced}; return guesses; } @@ -655,12 +737,7 @@ function removeUselessGuesses(list, possibilities) { } function getFirstGuesses(difficulty) { - let first_guesses = easy; - - if (isDifficulty(HARD, difficulty)) { - first_guesses = hard; - } - + let first_guesses = isDifficulty(HARD) ? hard : easy; first_guesses = getBestOf(first_guesses).filter(a => a.word.length == word_length); if (!first_guesses.length) { @@ -706,7 +783,8 @@ function calculateGuessList(answers, guesses, best_words, difficulty) { can_finish = true; } - if (performance.now() - start_time > MAX_TIME || (can_finish && i >= CHECK_SIZE)) { + // if (performance.now() - start_time > MAX_TIME || (can_finish && i >= CHECK_SIZE)) { + if (shouldStopTesting(start_time, performance.now(), can_finish, i)) { console.log("only calculated " + (i+1) + " words in " + ((performance.now()-start_time)/1000).toFixed(3) + " seconds"); best_words = best_words.slice(0, i+1); break; @@ -717,25 +795,37 @@ function calculateGuessList(answers, guesses, best_words, difficulty) { return best_words.map(a => Object.assign({}, {word: a.word, average: a.average, wrong: a.wrong})).slice(0, TOP_TEN_LENGTH); } +function shouldStopTesting(start_time, end_time, can_finish, i) { + return end_time - start_time > MAX_TIME || (can_finish && i >= CHECK_SIZE); +} + function getNextGuesses(new_guesses, answers, best, differences, difficulty) { + let list; + if (isDifficulty(HARD, difficulty)) { - return filterList(new_guesses, {word: best.word, colors: differences}); + list = filterList(new_guesses, {word: best.word, colors: differences}); } else if (!bot.isFor(ANTI)) { - return reduceListSize(new_guesses, uniqueWordsFrom(answers), answers.length).guesses; + list = reduceListSize(new_guesses, uniqueWordsFrom(answers), answers.length); } else { - return filterList(new_guesses, {word: best.word, colors: differences}, true); + list = filterList(new_guesses, {word: best.word, colors: differences}, true); } + + if (!bot.isFor(ANTI) && !isDifficulty(HARD)) { + list = combineLists(answers, new_guesses); + } + + return list; } function countResults(best, answers, guesses, results, attempt, difficulty, differences) { - let new_guesses = uniqueWordsFrom(answers).concat(guesses); - new_guesses = getNextGuesses(new_guesses, answers, best, differences, difficulty); + let new_guesses = combineLists(answers, guesses); + new_guesses = getNextGuesses(combineLists(guesses, uniqueWordsFrom(answers)), answers, best, differences, difficulty); if (answers.length <= 2 && (!bot.isFor(ANTI) || new_guesses.length == answers.length || !answers.length)) { - addToResults(results, answers, attempt, best.word, bot.guessesAllowed(difficulty)); + addToResults(results, answers, attempt, best.word, bot.guessesAllowed()); - } else if (attempt < bot.guessesAllowed(difficulty)-1) { - if (attempt == bot.guessesAllowed(difficulty)-2) { + } else if (attempt < bot.guessesAllowed()-1) { + if (attempt == bot.guessesAllowed()-2) { new_guesses = uniqueWordsFrom(answers.slice()); } @@ -749,8 +839,8 @@ function countResults(best, answers, guesses, results, attempt, difficulty, diff }); } - if (attempt >= bot.guessesAllowed(difficulty)-1) { - results['w'] = results['w'].concat(answers); + if (attempt >= bot.guessesAllowed()-1) { + results['w'] = combineLists(results['w'], answers); } calculateAverageGuesses(best, results); @@ -800,7 +890,6 @@ function calculateAverageGuesses(current_word, results) { } /* FILTER FUNCTIONS */ - function filterList(list, letters, reduced_filter, split) { if (numberOfGuessesSoFar(0)) return list; @@ -808,12 +897,10 @@ function filterList(list, letters, reduced_filter, split) { return createFilteredList(list, letters.word, letters.colors, reduced_filter, split); } - for (let guess = 0; guess < guessesSoFar(); guess++) { list = createFilteredList(list, getWord(guess), bot.getRowColor(guess), reduced_filter, split); } - return list; } @@ -838,12 +925,6 @@ function createFilteredList(old_list, guess, difference, reduced_filter, split) } } - for (let i = 0; i < new_list.length; i++) { - if (!bot.isFor(XORDLE)) { - new_list[i] = new_list[i].filter(a => a != guess); - } - } - if (!split) new_list = uniqueWordsFrom(new_list); return new_list; } @@ -920,7 +1001,7 @@ function sortList(list, alphabet) { for (let i = 0; i < newranks.length; i++) { for (let j = 0; j < word_length; j++) { if (checked[i + " " + newranks[i].word.charAt(j)] == true) continue; //no extra credit to letters with doubles - if (alphabet[newranks[i].word.charAt(j)][word_length] == alphabet[newranks[i].word.charAt(j)][j]) continue; + // if (alphabet[newranks[i].word.charAt(j)][word_length] == alphabet[newranks[i].word.charAt(j)][j]) continue; newranks[i].average += alphabet[newranks[i].word.charAt(j)][word_length]; newranks[i].average += alphabet[newranks[i].word.charAt(j)][j]; diff --git a/js/setup.js b/js/setup.js index 7dc895c..56e9537 100644 --- a/js/setup.js +++ b/js/setup.js @@ -9,6 +9,12 @@ $(document).ready(function() { createPage(); }); + $(document).on('input', '.warmle-selector', function() { + let val = $(this).val(); + localStorage.setItem('warmle_dist', val); + update(); + }); + $("#word-length").on('input', function() { localStorage.setItem('word_length' + bot.type, $(this).val()); createPage(); @@ -97,6 +103,11 @@ function getPreferences() { document.getElementById(otherWordbank(bank)).checked = false; setWordbank() } + + // if (bot.isFor(WARMLE) && localStorage.getItem('warmle_dist')) { + // let dist = localStorage.getItem('warmle_dist'); + // document.getElementsByClassName('warmle-selector')[0].value = dist; + // } } function otherWordbank(bank) { @@ -116,6 +127,31 @@ function drawPage() { createGuessInput(container); createAnswerSuggestions(container); + + updateSettings(); +} + +function updateSettings() { + let extra = document.getElementsByClassName('extra-settings')[0]; + + if (bot.isFor(WARMLE)) { + let selector = createElement('select', '', 'warmle-selector'); + + for (let i = 3; i >= 1; i--) { + let option = createElement('option', i); + option.value = i; + selector.append(option); + } + + setHTML(extra, + "Yellows are " + selector.outerHTML + " letters away from the correct letter."); + + if (localStorage.getItem('warmle_dist')) { + document.getElementsByClassName('warmle-selector')[0].value = localStorage.getItem('warmle_dist'); + } + } else { + clearHTML(extra); + } } function addGrid(hints) { @@ -194,7 +230,8 @@ function createExample() { let example_list = createElement('ul', '', 'word-list dummy'); for (let i = 0; i < EXAMPLE_LIST.length; i++) { - example_list.innerHTML += createListItem(EXAMPLE_LIST[i].word, EXAMPLE_LIST[i].score, i+1); + // example_list.innerHTML += createListItem(EXAMPLE_LIST[i].word, EXAMPLE_LIST[i].score, i+1); + example_list.append(createListItem(EXAMPLE_LIST[i].word, EXAMPLE_LIST[i].score, i+1)); } return {row: example_row, list: example_list}; @@ -202,7 +239,8 @@ function createExample() { function createWrongExample() { let example_wrong = createElement('ul', '', 'word-list dummy'); - example_wrong.innerHTML = createListItem(EXAMPLE_LIST[0].word, EXAMPLE_LIST[0].wrong, 1); + // example_wrong.innerHTML = createListItem(EXAMPLE_LIST[0].word, EXAMPLE_LIST[0].wrong, 1); + example_wrong.append(createListItem(EXAMPLE_LIST[0].word, EXAMPLE_LIST[0].wrong, 1)); return example_wrong; } diff --git a/wordl.css b/wordl.css index 00b1cc1..def3b48 100644 --- a/wordl.css +++ b/wordl.css @@ -420,6 +420,8 @@ button:hover, .tile:hover, .increment:hover { overflow-y: scroll; max-height: 350px; color: var(--background); + padding-top: .5rem; + padding-bottom: .5rem; } .showlist div:not(.showlist div.visible) { @@ -436,8 +438,9 @@ button:hover, .tile:hover, .increment:hover { } .visible p { - margin-top: .5rem; - margin-bottom: .5rem; + /* margin-top: .5rem; + margin-bottom: .5rem; */ + margin: 0; } .label { @@ -868,4 +871,46 @@ input:checked + .slider:before { #hints.empty { height: 0; +} + +.multi-answer { + margin-bottom: 1rem; + padding: .5rem; +} + +.black > span { + color: black; +} + +.green > span { + color: green; +} + +.red > span { + color: red; +} + +.orange > span { + color: orange; +} + +.puple > span { + color: purple; +} + +.brown > span { + color: brown; +} + +.gray > span { + color: gray; +} + +.blue > span { + color: blue; +} + +.extra-settings { + margin: 0; + padding: 0; } \ No newline at end of file