You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+30-4Lines changed: 30 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,15 +21,41 @@ I then filtered out all the words with 3 or less characters since in Ghost we on
21
21
22
22
In order for the AI to make decisions on which letter to select I needed each word in the dictionary to have a "frequency" value which represents how frequently the word is used in daily life. The [wordfreq](https://pypi.org/project/wordfreq/) python library has a "word_frequency(word, lang, wordlist='best', minimum=0.0)" funtion which gives a spoken-frequency rating from 0.0 to 1.0 to the passed word.
23
23
24
-
Using the [wordfreq](https://pypi.org/project/wordfreq/) I wrote a short Python script that iterates through the dictionary, giving it a value from 0-1 which, when graphed, resulted in the following:
24
+
Using the [wordfreq](https://pypi.org/project/wordfreq/) I wrote a short Python script that iterates through the dictionary, giving it a value from 0-1 which, when graphed, resulted in the following data:
After graphing the results of my word-frequecy dictionary I noticed that the majority of words where given incredably small values in comparison to a small subset with very large ones. After some debugging I found that this was due to the heavy hitters like "the" or "is" being given frequencies hundreds of times larger than most other words (which makes sense). To fix this I used a Python's log() function to smooth out the range of frequency values giving this:
After tweaking the script a little more to adjust for the log results I endded up with a much more readable range of frequencies from 13.81 to 0 with an average of 10.73:
29
+
30
+
After tweaking the script a little more to adjust for the log results I endded up with a much more processable range of frequencies with values from 13.81 to 0 with and an average of 10.73:
All versions of the dictionary can be found under [data-prep](https://github.com/reedbryan/ghost-webapp/tree/main/data-prep):
33
+
The final dictionary.json would allow the AI to evaluate words in a more human manor. Weighing the each letter by of all the possible words that it could create and the frequency in which those words appear in the english language. The data is also alphabetized which allows the AI to more quickly evaluate possible branchs of words that can be derived from a new letter.
34
+
35
+
All plots and versions of the dictionary can be found under [data-prep](https://github.com/reedbryan/ghost-webapp/tree/main/data-prep)
32
36
33
37
34
38
# The AI
35
-
AI's logic is to search the wordbank for all possible words created from the user's first letter. It then selects a word from that list based on frequency and an element of random an sends the next letter to be reviewed by the user. The user will then either challange the AI to spell a possible word from the current sequence of letter or will input another letter. On that input the AI will again find all possible words that can be spelled from the current sequence, if none are found it will challange the user, if there are it select another word based on frequency/randomness and send back the next letter. The process repeats as such until a word it spelled or a challange is issued.
39
+
AI's logic is to search the wordbank for all possible words created from the current sequence of letters. It then weighs each letter by the combine weight of all word from that list based on the following logic.
40
+
- if the word would end with the user choosing the final letter (the user loses the game) then that word's weight is its _positive_ frequency
41
+
- if the word would end with the AI choosing the final letter (the AI loses the game) then that word's weight is its _negative_ frequency
42
+
Since the data is alphabetized, in the code the AI groups collections of words that share the same prefix to compare the first few letters. It does this to avoid giving high weight to letters which look great based on the total weight of words it could create but have certain, high-frequency words that the player could chose to put the AI in a corner. An example of this is as follows
const current_word = 'inter'; // The current sequence of letters
46
+
47
+
letter_group = [
48
+
'international',
49
+
'interference',
50
+
'intermediate',
51
+
'interview',
52
+
'internal',
53
+
'interpretation'
54
+
];
55
+
56
+
IDK IF THIS EXPLANATION IS GONNA WORK
57
+
TRY RUNNING THE APP AND USING THE CONSOLE TO LOOK AT SOME REAL CASES
58
+
59
+
60
+
If the word group ends in a "player win" (baseEndsWell is true), the frequency of the next_word is added to the group_weight, which represents the importance of that letter in forming the optimal word.
61
+
This way a letter is evaluated by how often the user will select their letter with the goal of spelling a word that would eventually lose them the game.
0 commit comments