├── .env ├── .prettierrc ├── src ├── react-app-env.d.ts ├── lib │ ├── keyboard.ts │ ├── words.ts │ ├── share.ts │ ├── localStorage.ts │ ├── stats.ts │ └── statuses.ts ├── setupTests.ts ├── App.test.tsx ├── components │ ├── grid │ │ ├── EmptyRow.tsx │ │ ├── CompletedRow.tsx │ │ ├── CurrentRow.tsx │ │ ├── Grid.tsx │ │ └── Cell.tsx │ ├── mini-grid │ │ ├── MiniGrid.tsx │ │ ├── MiniCompletedRow.tsx │ │ └── MiniCell.tsx │ ├── stats │ │ ├── Histogram.tsx │ │ ├── Progress.tsx │ │ └── StatBar.tsx │ ├── modals │ │ ├── StatsModal.tsx │ │ ├── AboutModal.tsx │ │ ├── InfoModal.tsx │ │ ├── WinModal.tsx │ │ └── BaseModal.tsx │ ├── alerts │ │ └── Alert.tsx │ └── keyboard │ │ ├── Key.tsx │ │ └── Keyboard.tsx ├── index.css ├── reportWebVitals.ts ├── index.tsx ├── App.css ├── logo.svg ├── App.tsx └── constants │ └── wordlist.ts ├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── Dockerfile ├── .vscode └── settings.json ├── postcss.config.js ├── tailwind.config.js ├── .gitignore ├── tsconfig.json ├── README.md ├── LICENSE └── package.json /.env: -------------------------------------------------------------------------------- 1 | CI= npm run build -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | singleQuote: true 2 | semi: false 3 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeRoantree4815162342/wordle/main/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeRoantree4815162342/wordle/main/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeRoantree4815162342/wordle/main/public/logo512.png -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node 2 | 3 | COPY . . 4 | RUN npm install 5 | 6 | EXPOSE 3000 7 | CMD npm run start 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "editor.defaultFormatter": "esbenp.prettier-vscode" 4 | } -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/lib/keyboard.ts: -------------------------------------------------------------------------------- 1 | import { CharValue } from './statuses' 2 | 3 | export type KeyValue = CharValue | 'ENTER' | 'DELETE' 4 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: ['./src/**/*.{js,jsx,ts,tsx}'], 3 | theme: { 4 | extend: {}, 5 | }, 6 | plugins: [], 7 | } 8 | -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom' 6 | -------------------------------------------------------------------------------- /src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { render, screen } from '@testing-library/react' 3 | import App from './App' 4 | 5 | test('renders learn react link', () => { 6 | render() 7 | const linkElement = screen.getByText(/learn react/i) 8 | expect(linkElement).toBeInTheDocument() 9 | }) 10 | -------------------------------------------------------------------------------- /src/components/grid/EmptyRow.tsx: -------------------------------------------------------------------------------- 1 | import { Cell } from './Cell' 2 | 3 | export const EmptyRow = () => { 4 | const emptyCells = Array.from(Array(5)) 5 | 6 | return ( 7 |
8 | {emptyCells.map((_, i) => ( 9 | 10 | ))} 11 |
12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /src/components/mini-grid/MiniGrid.tsx: -------------------------------------------------------------------------------- 1 | import { MiniCompletedRow } from './MiniCompletedRow' 2 | 3 | type Props = { 4 | guesses: string[] 5 | } 6 | 7 | export const MiniGrid = ({ guesses }: Props) => { 8 | return ( 9 |
10 | {guesses.map((guess, i) => ( 11 | 12 | ))} 13 |
14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | .cell-animation { 6 | animation: revealCharCell linear; 7 | animation-duration: 0.15s; 8 | } 9 | 10 | @keyframes revealCharCell { 11 | 0% { 12 | transform: scale(1); 13 | } 14 | 15 | 50% { 16 | transform: scale(1.1); 17 | } 18 | 19 | 100% { 20 | transform: scale(1); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals' 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry) 7 | getFID(onPerfEntry) 8 | getFCP(onPerfEntry) 9 | getLCP(onPerfEntry) 10 | getTTFB(onPerfEntry) 11 | }) 12 | } 13 | } 14 | 15 | export default reportWebVitals 16 | -------------------------------------------------------------------------------- /src/components/grid/CompletedRow.tsx: -------------------------------------------------------------------------------- 1 | import { getGuessStatuses } from '../../lib/statuses' 2 | import { Cell } from './Cell' 3 | 4 | type Props = { 5 | guess: string 6 | } 7 | 8 | export const CompletedRow = ({ guess }: Props) => { 9 | const statuses = getGuessStatuses(guess) 10 | 11 | return ( 12 |
13 | {guess.split('').map((letter, i) => ( 14 | 15 | ))} 16 |
17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /src/components/mini-grid/MiniCompletedRow.tsx: -------------------------------------------------------------------------------- 1 | import { getGuessStatuses } from '../../lib/statuses' 2 | import { MiniCell } from './MiniCell' 3 | 4 | type Props = { 5 | guess: string 6 | } 7 | 8 | export const MiniCompletedRow = ({ guess }: Props) => { 9 | const statuses = getGuessStatuses(guess) 10 | 11 | return ( 12 |
13 | {guess.split('').map((letter, i) => ( 14 | 15 | ))} 16 |
17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /src/components/grid/CurrentRow.tsx: -------------------------------------------------------------------------------- 1 | import { Cell } from './Cell' 2 | 3 | type Props = { 4 | guess: string 5 | } 6 | 7 | export const CurrentRow = ({ guess }: Props) => { 8 | const splitGuess = guess.split('') 9 | const emptyCells = Array.from(Array(5 - splitGuess.length)) 10 | 11 | return ( 12 |
13 | {splitGuess.map((letter, i) => ( 14 | 15 | ))} 16 | {emptyCells.map((_, i) => ( 17 | 18 | ))} 19 |
20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import './index.css' 4 | import App from './App' 5 | import reportWebVitals from './reportWebVitals' 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ) 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals() 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"] 20 | } 21 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/components/stats/Histogram.tsx: -------------------------------------------------------------------------------- 1 | import { GameStats } from '../../lib/localStorage' 2 | import { Progress } from './Progress' 3 | 4 | type Props = { 5 | gameStats: GameStats 6 | } 7 | 8 | export const Histogram = ({ gameStats }: Props) => { 9 | const { totalGames, winDistribution } = gameStats 10 | 11 | return ( 12 |
13 | {winDistribution.map((value, i) => ( 14 | 20 | ))} 21 |
22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /src/components/stats/Progress.tsx: -------------------------------------------------------------------------------- 1 | type Props = { 2 | index: number 3 | size: number 4 | label: string 5 | } 6 | 7 | export const Progress = ({ index, size, label }: Props) => { 8 | return ( 9 |
10 |
{index + 1}
11 |
12 |
16 | {label} 17 |
18 |
19 |
20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /src/components/mini-grid/MiniCell.tsx: -------------------------------------------------------------------------------- 1 | import { CharStatus } from '../../lib/statuses' 2 | import classnames from 'classnames' 3 | 4 | type Props = { 5 | status: CharStatus 6 | } 7 | 8 | export const MiniCell = ({ status }: Props) => { 9 | const classes = classnames( 10 | 'w-10 h-10 border-solid border-2 border-slate-200 flex items-center justify-center mx-0.5 text-lg font-bold rounded', 11 | { 12 | 'bg-white': status === 'absent', 13 | 'bg-green-500': status === 'correct', 14 | 'bg-yellow-500': status === 'present', 15 | } 16 | ) 17 | 18 | return ( 19 | <> 20 |
21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/components/grid/Grid.tsx: -------------------------------------------------------------------------------- 1 | import { CompletedRow } from './CompletedRow' 2 | import { CurrentRow } from './CurrentRow' 3 | import { EmptyRow } from './EmptyRow' 4 | 5 | type Props = { 6 | guesses: string[] 7 | currentGuess: string 8 | } 9 | 10 | export const Grid = ({ guesses, currentGuess }: Props) => { 11 | const empties = 12 | guesses.length < 5 ? Array.from(Array(5 - guesses.length)) : [] 13 | 14 | return ( 15 |
16 | {guesses.map((guess, i) => ( 17 | 18 | ))} 19 | {guesses.length < 6 && } 20 | {empties.map((_, i) => ( 21 | 22 | ))} 23 |
24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /src/components/modals/StatsModal.tsx: -------------------------------------------------------------------------------- 1 | import { StatBar } from '../stats/StatBar' 2 | import { Histogram } from '../stats/Histogram' 3 | import { GameStats } from '../../lib/localStorage' 4 | import { BaseModal } from './BaseModal' 5 | 6 | type Props = { 7 | isOpen: boolean 8 | handleClose: () => void 9 | gameStats: GameStats 10 | } 11 | 12 | export const StatsModal = ({ isOpen, handleClose, gameStats }: Props) => { 13 | return ( 14 | 15 | 16 |

17 | Guess Distribution 18 |

19 | 20 |
21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /src/lib/words.ts: -------------------------------------------------------------------------------- 1 | import { WORDS } from '../constants/wordlist' 2 | import { VALIDGUESSES } from '../constants/validGuesses' 3 | 4 | export const isWordInWordList = (word: string) => { 5 | return ( 6 | WORDS.includes(word.toLowerCase()) || 7 | VALIDGUESSES.includes(word.toLowerCase()) 8 | ) 9 | } 10 | 11 | export const isWinningWord = (word: string) => { 12 | return solution === word 13 | } 14 | 15 | export const getWordOfDay = () => { 16 | // January 1, 2022 Game Epoch 17 | const epochMs = 1641013200000 18 | const now = Date.now() 19 | const msInDay = 86400000 20 | const index = Math.floor((now - epochMs) / msInDay) 21 | 22 | return { 23 | solution: WORDS[index].toUpperCase(), 24 | solutionIndex: index, 25 | } 26 | } 27 | 28 | export const { solution, solutionIndex } = getWordOfDay() 29 | -------------------------------------------------------------------------------- /src/components/grid/Cell.tsx: -------------------------------------------------------------------------------- 1 | import { CharStatus } from '../../lib/statuses' 2 | import classnames from 'classnames' 3 | 4 | type Props = { 5 | value?: string 6 | status?: CharStatus 7 | } 8 | 9 | export const Cell = ({ value, status }: Props) => { 10 | const classes = classnames( 11 | 'w-14 h-14 border-solid border-2 flex items-center justify-center mx-0.5 text-lg font-bold rounded', 12 | { 13 | 'bg-white border-slate-200': !status, 14 | 'border-black': value && !status, 15 | 'bg-slate-400 text-white border-slate-400': status === 'absent', 16 | 'bg-green-500 text-white border-green-500': status === 'correct', 17 | 'bg-yellow-500 text-white border-yellow-500': status === 'present', 18 | 'cell-animation': !!value, 19 | } 20 | ) 21 | 22 | return
{value}
23 | } 24 | -------------------------------------------------------------------------------- /src/lib/share.ts: -------------------------------------------------------------------------------- 1 | import { getGuessStatuses } from './statuses' 2 | import { solutionIndex } from './words' 3 | 4 | export const shareStatus = (guesses: string[]) => { 5 | navigator.clipboard.writeText( 6 | `Not Wordle ${solutionIndex} ${guesses.length}/6\n\n` + 7 | generateEmojiGrid(guesses) 8 | ) 9 | } 10 | 11 | export const generateEmojiGrid = (guesses: string[]) => { 12 | return guesses 13 | .map((guess) => { 14 | const status = getGuessStatuses(guess) 15 | return guess 16 | .split('') 17 | .map((letter, i) => { 18 | switch (status[i]) { 19 | case 'correct': 20 | return '🟩' 21 | case 'present': 22 | return '🟨' 23 | default: 24 | return '⬜' 25 | } 26 | }) 27 | .join('') 28 | }) 29 | .join('\n') 30 | } 31 | -------------------------------------------------------------------------------- /src/components/modals/AboutModal.tsx: -------------------------------------------------------------------------------- 1 | import { BaseModal } from './BaseModal' 2 | 3 | type Props = { 4 | isOpen: boolean 5 | handleClose: () => void 6 | } 7 | 8 | export const AboutModal = ({ isOpen, handleClose }: Props) => { 9 | return ( 10 | 11 |

12 | This is an open source clone of the game Wordle -{' '} 13 | 17 | check out the code here 18 | {' '} 19 | and{' '} 20 | 24 | play the original here 25 | 26 |

27 |
28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /src/components/stats/StatBar.tsx: -------------------------------------------------------------------------------- 1 | import { GameStats } from '../../lib/localStorage' 2 | 3 | type Props = { 4 | gameStats: GameStats 5 | } 6 | 7 | const StatItem = ({ 8 | label, 9 | value, 10 | }: { 11 | label: string 12 | value: string | number 13 | }) => { 14 | return ( 15 |
16 |
{value}
17 |
{label}
18 |
19 | ) 20 | } 21 | 22 | export const StatBar = ({ gameStats }: Props) => { 23 | return ( 24 |
25 | 26 | 27 | 28 | 29 |
30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wordle Clone - In Irish / As Gaeilge 2 | 3 | ## STATUS: Work In Progress 4 | 5 | --- 6 | ### The majority of this clone was written by [hannahcode](https://github.com/hannahcode/wordle) for her Wordle Clone, my only contributions are in tweaking that code base to use an Irish corpus. 7 | --- 8 | 9 | - Try it [here](TODO) 10 | - Go play the real Wordle [here](https://www.powerlanguage.co.uk/wordle/) 11 | - Read the story behind it [here](https://www.nytimes.com/2022/01/03/technology/wordle-word-game-creator.html) 12 | - Try a demo of hannahcode's Wordle clone project [here](https://wordle.hannahmariepark.com) 13 | 14 | _To Run Locally:_ 15 | Clone the repository and perform the following command line actions: 16 | ```bash 17 | $ cd wordle 18 | $ npm install 19 | $ npm run start 20 | ``` 21 | 22 | _To build/run docker container:_ 23 | ```bash 24 | $ docker build -t focale . 25 | $ docker run -d -p 3000:3000 focale 26 | ``` 27 | open http://localhost:3000 in browser. 28 | 29 | -------------------------------------------------------------------------------- /src/lib/localStorage.ts: -------------------------------------------------------------------------------- 1 | const gameStateKey = 'gameState' 2 | 3 | type StoredGameState = { 4 | guesses: string[] 5 | solution: string 6 | } 7 | 8 | export const saveGameStateToLocalStorage = (gameState: StoredGameState) => { 9 | localStorage.setItem(gameStateKey, JSON.stringify(gameState)) 10 | } 11 | 12 | export const loadGameStateFromLocalStorage = () => { 13 | const state = localStorage.getItem(gameStateKey) 14 | return state ? (JSON.parse(state) as StoredGameState) : null 15 | } 16 | 17 | const gameStatKey = 'gameStats' 18 | 19 | export type GameStats = { 20 | winDistribution: number[] 21 | gamesFailed: number 22 | currentStreak: number 23 | bestStreak: number 24 | totalGames: number 25 | successRate: number 26 | } 27 | 28 | export const saveStatsToLocalStorage = (gameStats: GameStats) => { 29 | localStorage.setItem(gameStatKey, JSON.stringify(gameStats)) 30 | } 31 | 32 | export const loadStatsFromLocalStorage = () => { 33 | const stats = localStorage.getItem(gameStatKey) 34 | return stats ? (JSON.parse(stats) as GameStats) : null 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Hannah Park 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/alerts/Alert.tsx: -------------------------------------------------------------------------------- 1 | import { Fragment } from 'react' 2 | import { Transition } from '@headlessui/react' 3 | import classNames from 'classnames' 4 | 5 | type Props = { 6 | isOpen: boolean 7 | message: string 8 | variant?: 'success' | 'warning' 9 | } 10 | 11 | export const Alert = ({ isOpen, message, variant = 'warning' }: Props) => { 12 | const classes = classNames( 13 | 'fixed top-20 left-1/2 transform -translate-x-1/2 max-w-sm w-full shadow-lg rounded-lg pointer-events-auto ring-1 ring-black ring-opacity-5 overflow-hidden', 14 | { 15 | 'bg-rose-200': variant === 'warning', 16 | 'bg-green-200': variant === 'success', 17 | } 18 | ) 19 | 20 | return ( 21 | 31 |
32 |
33 |

34 | {message} 35 |

36 |
37 |
38 |
39 | ) 40 | } 41 | -------------------------------------------------------------------------------- /src/components/keyboard/Key.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react' 2 | import classnames from 'classnames' 3 | import { KeyValue } from '../../lib/keyboard' 4 | import { CharStatus } from '../../lib/statuses' 5 | 6 | type Props = { 7 | children?: ReactNode 8 | value: KeyValue 9 | width?: number 10 | status?: CharStatus 11 | onClick: (value: KeyValue) => void 12 | } 13 | 14 | export const Key = ({ 15 | children, 16 | status, 17 | width = 40, 18 | value, 19 | onClick, 20 | }: Props) => { 21 | const classes = classnames( 22 | 'flex items-center justify-center rounded mx-0.5 text-xs font-bold cursor-pointer select-none', 23 | { 24 | 'bg-slate-200 hover:bg-slate-300 active:bg-slate-400': !status, 25 | 'bg-slate-400 text-white': status === 'absent', 26 | 'bg-green-500 hover:bg-green-600 active:bg-green-700 text-white': 27 | status === 'correct', 28 | 'bg-yellow-500 hover:bg-yellow-600 active:bg-yellow-700 text-white': 29 | status === 'present', 30 | } 31 | ) 32 | 33 | const handleClick: React.MouseEventHandler = (event) => { 34 | onClick(value) 35 | event.currentTarget.blur() 36 | } 37 | 38 | return ( 39 | 46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wordle", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@headlessui/react": "^1.4.2", 7 | "@heroicons/react": "^1.0.5", 8 | "@testing-library/jest-dom": "^5.16.1", 9 | "@testing-library/react": "^12.1.2", 10 | "@testing-library/user-event": "^13.5.0", 11 | "@types/jest": "^27.4.0", 12 | "@types/node": "^16.11.19", 13 | "@types/react": "^17.0.38", 14 | "@types/react-dom": "^17.0.11", 15 | "classnames": "^2.3.1", 16 | "react": "^17.0.2", 17 | "react-dom": "^17.0.2", 18 | "react-scripts": "5.0.0", 19 | "typescript": "^4.5.4", 20 | "web-vitals": "^2.1.3" 21 | }, 22 | "scripts": { 23 | "start": "react-scripts start", 24 | "build": "react-scripts build", 25 | "test": "react-scripts test", 26 | "eject": "react-scripts eject" 27 | }, 28 | "eslintConfig": { 29 | "extends": [ 30 | "react-app", 31 | "react-app/jest" 32 | ] 33 | }, 34 | "browserslist": { 35 | "production": [ 36 | ">0.2%", 37 | "not dead", 38 | "not op_mini all" 39 | ], 40 | "development": [ 41 | "last 1 chrome version", 42 | "last 1 firefox version", 43 | "last 1 safari version" 44 | ] 45 | }, 46 | "devDependencies": { 47 | "autoprefixer": "^10.4.2", 48 | "postcss": "^8.4.5", 49 | "tailwindcss": "^3.0.12", 50 | "prettier": "^2.5.1" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/lib/stats.ts: -------------------------------------------------------------------------------- 1 | import { 2 | GameStats, 3 | loadStatsFromLocalStorage, 4 | saveStatsToLocalStorage, 5 | } from './localStorage' 6 | 7 | // In stats array elements 0-5 are successes in 1-6 trys 8 | 9 | export const addStatsForCompletedGame = ( 10 | gameStats: GameStats, 11 | count: number 12 | ) => { 13 | // Count is number of incorrect guesses before end. 14 | const stats = { ...gameStats } 15 | 16 | stats.totalGames += 1 17 | 18 | if (count > 5) { 19 | // A fail situation 20 | stats.currentStreak = 0 21 | stats.gamesFailed += 1 22 | } else { 23 | stats.winDistribution[count] += 1 24 | stats.currentStreak += 1 25 | 26 | if (stats.bestStreak < stats.currentStreak) { 27 | stats.bestStreak = stats.currentStreak 28 | } 29 | } 30 | 31 | stats.successRate = getSuccessRate(stats) 32 | 33 | saveStatsToLocalStorage(stats) 34 | return stats 35 | } 36 | 37 | const defaultStats: GameStats = { 38 | winDistribution: [0, 0, 0, 0, 0, 0], 39 | gamesFailed: 0, 40 | currentStreak: 0, 41 | bestStreak: 0, 42 | totalGames: 0, 43 | successRate: 0, 44 | } 45 | 46 | export const loadStats = () => { 47 | return loadStatsFromLocalStorage() || defaultStats 48 | } 49 | 50 | const getSuccessRate = (gameStats: GameStats) => { 51 | const { totalGames, gamesFailed } = gameStats 52 | 53 | return Math.round( 54 | (100 * (totalGames - gamesFailed)) / Math.max(totalGames, 1) 55 | ) 56 | } 57 | -------------------------------------------------------------------------------- /src/components/modals/InfoModal.tsx: -------------------------------------------------------------------------------- 1 | import { Cell } from '../grid/Cell' 2 | import { BaseModal } from './BaseModal' 3 | 4 | type Props = { 5 | isOpen: boolean 6 | handleClose: () => void 7 | } 8 | 9 | export const InfoModal = ({ isOpen, handleClose }: Props) => { 10 | return ( 11 | 12 |

13 | Guess the WORDLE in 6 tries. After each guess, the color of the tiles 14 | will change to show how close your guess was to the word. 15 |

16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 |
24 |

25 | The letter W is in the word and in the correct spot. 26 |

27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 |
35 |

36 | The letter L is in the word but in the wrong spot. 37 |

38 | 39 |
40 | 41 | 42 | 43 | 44 | 45 |
46 |

47 | The letter U is not in the word in any spot. 48 |

49 |
50 | ) 51 | } 52 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Wordle Clone 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/components/modals/WinModal.tsx: -------------------------------------------------------------------------------- 1 | import { Dialog } from '@headlessui/react' 2 | import { CheckIcon } from '@heroicons/react/outline' 3 | import { MiniGrid } from '../mini-grid/MiniGrid' 4 | import { shareStatus } from '../../lib/share' 5 | import { BaseModal } from './BaseModal' 6 | 7 | type Props = { 8 | isOpen: boolean 9 | handleClose: () => void 10 | guesses: string[] 11 | handleShare: () => void 12 | } 13 | 14 | export const WinModal = ({ 15 | isOpen, 16 | handleClose, 17 | guesses, 18 | handleShare, 19 | }: Props) => { 20 | return ( 21 | 22 |
23 |
24 |
26 |
27 | 31 | You won! 32 | 33 |
34 | 35 |

Great job.

36 |
37 |
38 |
39 |
40 | 50 |
51 |
52 | ) 53 | } 54 | -------------------------------------------------------------------------------- /src/lib/statuses.ts: -------------------------------------------------------------------------------- 1 | import { solution } from './words' 2 | 3 | export type CharStatus = 'absent' | 'present' | 'correct' 4 | 5 | export type CharValue = 6 | | 'Q' 7 | | 'W' 8 | | 'E' 9 | | 'R' 10 | | 'T' 11 | | 'Y' 12 | | 'U' 13 | | 'I' 14 | | 'O' 15 | | 'P' 16 | | 'A' 17 | | 'S' 18 | | 'D' 19 | | 'F' 20 | | 'G' 21 | | 'H' 22 | | 'J' 23 | | 'K' 24 | | 'L' 25 | | 'Z' 26 | | 'X' 27 | | 'C' 28 | | 'V' 29 | | 'B' 30 | | 'N' 31 | | 'M' 32 | 33 | export const getStatuses = ( 34 | guesses: string[] 35 | ): { [key: string]: CharStatus } => { 36 | const charObj: { [key: string]: CharStatus } = {} 37 | 38 | guesses.forEach((word) => { 39 | word.split('').forEach((letter, i) => { 40 | if (!solution.includes(letter)) { 41 | // make status absent 42 | return (charObj[letter] = 'absent') 43 | } 44 | 45 | if (letter === solution[i]) { 46 | //make status correct 47 | return (charObj[letter] = 'correct') 48 | } 49 | 50 | if (charObj[letter] !== 'correct') { 51 | //make status present 52 | return (charObj[letter] = 'present') 53 | } 54 | }) 55 | }) 56 | 57 | return charObj 58 | } 59 | 60 | export const getGuessStatuses = (guess: string): CharStatus[] => { 61 | const splitSolution = solution.split('') 62 | const splitGuess = guess.split('') 63 | 64 | const solutionCharsTaken = splitSolution.map((_) => false) 65 | 66 | const statuses: CharStatus[] = Array.from(Array(guess.length)) 67 | 68 | // handle all correct cases first 69 | splitGuess.forEach((letter, i) => { 70 | if (letter === splitSolution[i]) { 71 | statuses[i] = 'correct' 72 | solutionCharsTaken[i] = true 73 | return 74 | } 75 | }) 76 | 77 | splitGuess.forEach((letter, i) => { 78 | if (statuses[i]) return 79 | 80 | if (!splitSolution.includes(letter)) { 81 | // handles the absent case 82 | statuses[i] = 'absent' 83 | return 84 | } 85 | 86 | // now we are left with "present"s 87 | const indexOfPresentChar = splitSolution.findIndex( 88 | (x, index) => x === letter && !solutionCharsTaken[index] 89 | ) 90 | 91 | if (indexOfPresentChar > -1) { 92 | statuses[i] = 'present' 93 | solutionCharsTaken[indexOfPresentChar] = true 94 | return 95 | } else { 96 | statuses[i] = 'absent' 97 | return 98 | } 99 | }) 100 | 101 | return statuses 102 | } 103 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/modals/BaseModal.tsx: -------------------------------------------------------------------------------- 1 | import { Fragment } from 'react' 2 | import { Dialog, Transition } from '@headlessui/react' 3 | import { XCircleIcon } from '@heroicons/react/outline' 4 | 5 | type Props = { 6 | title: string 7 | children: React.ReactNode 8 | isOpen: boolean 9 | handleClose: () => void 10 | } 11 | 12 | export const BaseModal = ({ title, children, isOpen, handleClose }: Props) => { 13 | return ( 14 | 15 | 20 |
21 | 30 | 31 | 32 | 33 | {/* This element is to trick the browser into centering the modal contents. */} 34 | 40 | 49 |
50 |
51 | handleClose()} 54 | /> 55 |
56 |
57 |
58 | 62 | {title} 63 | 64 |
65 | {children} 66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | ) 75 | } 76 | -------------------------------------------------------------------------------- /src/components/keyboard/Keyboard.tsx: -------------------------------------------------------------------------------- 1 | import { KeyValue } from '../../lib/keyboard' 2 | import { getStatuses } from '../../lib/statuses' 3 | import { Key } from './Key' 4 | import { useEffect } from 'react' 5 | 6 | type Props = { 7 | onChar: (value: string) => void 8 | onDelete: () => void 9 | onEnter: () => void 10 | guesses: string[] 11 | } 12 | 13 | export const Keyboard = ({ onChar, onDelete, onEnter, guesses }: Props) => { 14 | const charStatuses = getStatuses(guesses) 15 | 16 | const onClick = (value: KeyValue) => { 17 | if (value === 'ENTER') { 18 | onEnter() 19 | } else if (value === 'DELETE') { 20 | onDelete() 21 | } else { 22 | onChar(value) 23 | } 24 | } 25 | 26 | useEffect(() => { 27 | const listener = (e: KeyboardEvent) => { 28 | if (e.code === 'Enter') { 29 | onEnter() 30 | } else if (e.code === 'Backspace') { 31 | onDelete() 32 | } else { 33 | const key = e.key.toUpperCase() 34 | if (key.length === 1 && key >= 'A' && key <= 'Z') { 35 | onChar(key) 36 | } 37 | } 38 | } 39 | window.addEventListener('keyup', listener) 40 | return () => { 41 | window.removeEventListener('keyup', listener) 42 | } 43 | }, [onEnter, onDelete, onChar]) 44 | 45 | return ( 46 |
47 |
48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
70 |
71 | 72 | Enter 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | Delete 83 | 84 |
85 |
86 | ) 87 | } 88 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { InformationCircleIcon } from '@heroicons/react/outline' 2 | import { ChartBarIcon } from '@heroicons/react/outline' 3 | import { useState, useEffect } from 'react' 4 | import { Alert } from './components/alerts/Alert' 5 | import { Grid } from './components/grid/Grid' 6 | import { Keyboard } from './components/keyboard/Keyboard' 7 | import { AboutModal } from './components/modals/AboutModal' 8 | import { InfoModal } from './components/modals/InfoModal' 9 | import { WinModal } from './components/modals/WinModal' 10 | import { StatsModal } from './components/modals/StatsModal' 11 | import { isWordInWordList, isWinningWord, solution } from './lib/words' 12 | import { addStatsForCompletedGame, loadStats } from './lib/stats' 13 | import { 14 | loadGameStateFromLocalStorage, 15 | saveGameStateToLocalStorage, 16 | } from './lib/localStorage' 17 | 18 | function App() { 19 | const [currentGuess, setCurrentGuess] = useState('') 20 | const [isGameWon, setIsGameWon] = useState(false) 21 | const [isWinModalOpen, setIsWinModalOpen] = useState(false) 22 | const [isInfoModalOpen, setIsInfoModalOpen] = useState(false) 23 | const [isAboutModalOpen, setIsAboutModalOpen] = useState(false) 24 | const [isNotEnoughLetters, setIsNotEnoughLetters] = useState(false) 25 | const [isStatsModalOpen, setIsStatsModalOpen] = useState(false) 26 | const [isWordNotFoundAlertOpen, setIsWordNotFoundAlertOpen] = useState(false) 27 | const [isGameLost, setIsGameLost] = useState(false) 28 | const [shareComplete, setShareComplete] = useState(false) 29 | const [guesses, setGuesses] = useState(() => { 30 | const loaded = loadGameStateFromLocalStorage() 31 | if (loaded?.solution !== solution) { 32 | return [] 33 | } 34 | const gameWasWon = loaded.guesses.includes(solution) 35 | if (gameWasWon) { 36 | setIsGameWon(true) 37 | } 38 | if (loaded.guesses.length === 6 && !gameWasWon) { 39 | setIsGameLost(true) 40 | } 41 | return loaded.guesses 42 | }) 43 | 44 | const [stats, setStats] = useState(() => loadStats()) 45 | 46 | useEffect(() => { 47 | saveGameStateToLocalStorage({ guesses, solution }) 48 | }, [guesses]) 49 | 50 | useEffect(() => { 51 | if (isGameWon) { 52 | setIsWinModalOpen(true) 53 | } 54 | }, [isGameWon]) 55 | 56 | const onChar = (value: string) => { 57 | if (currentGuess.length < 5 && guesses.length < 6 && !isGameWon) { 58 | setCurrentGuess(`${currentGuess}${value}`) 59 | } 60 | } 61 | 62 | const onDelete = () => { 63 | setCurrentGuess(currentGuess.slice(0, -1)) 64 | } 65 | 66 | const onEnter = () => { 67 | if (!(currentGuess.length === 5) && !isGameLost) { 68 | setIsNotEnoughLetters(true) 69 | return setTimeout(() => { 70 | setIsNotEnoughLetters(false) 71 | }, 2000) 72 | } 73 | 74 | if (!isWordInWordList(currentGuess)) { 75 | setIsWordNotFoundAlertOpen(true) 76 | return setTimeout(() => { 77 | setIsWordNotFoundAlertOpen(false) 78 | }, 2000) 79 | } 80 | 81 | const winningWord = isWinningWord(currentGuess) 82 | 83 | if (currentGuess.length === 5 && guesses.length < 6 && !isGameWon) { 84 | setGuesses([...guesses, currentGuess]) 85 | setCurrentGuess('') 86 | 87 | if (winningWord) { 88 | setStats(addStatsForCompletedGame(stats, guesses.length)) 89 | return setIsGameWon(true) 90 | } 91 | 92 | if (guesses.length === 5) { 93 | setStats(addStatsForCompletedGame(stats, guesses.length + 1)) 94 | setIsGameLost(true) 95 | } 96 | } 97 | } 98 | 99 | return ( 100 |
101 |
102 |

Not Wordle

103 | setIsInfoModalOpen(true)} 106 | /> 107 | setIsStatsModalOpen(true)} 110 | /> 111 |
112 | 113 | 119 | setIsWinModalOpen(false)} 122 | guesses={guesses} 123 | handleShare={() => { 124 | setIsWinModalOpen(false) 125 | setShareComplete(true) 126 | return setTimeout(() => { 127 | setShareComplete(false) 128 | }, 2000) 129 | }} 130 | /> 131 | setIsInfoModalOpen(false)} 134 | /> 135 | setIsStatsModalOpen(false)} 138 | gameStats={stats} 139 | /> 140 | setIsAboutModalOpen(false)} 143 | /> 144 | 145 | 152 | 153 | 154 | 155 | 159 | 164 |
165 | ) 166 | } 167 | 168 | export default App 169 | -------------------------------------------------------------------------------- /src/constants/wordlist.ts: -------------------------------------------------------------------------------- 1 | export const WORDS = [ 2 | 'cigar', 3 | 'rebut', 4 | 'sissy', 5 | 'humph', 6 | 'awake', 7 | 'blush', 8 | 'focal', 9 | 'evade', 10 | 'naval', 11 | 'serve', 12 | 'heath', 13 | 'dwarf', 14 | 'model', 15 | 'karma', 16 | 'stink', 17 | 'grade', 18 | 'quiet', 19 | 'bench', 20 | 'abate', 21 | 'feign', 22 | 'major', 23 | 'death', 24 | 'fresh', 25 | 'crust', 26 | 'stool', 27 | 'colon', 28 | 'abase', 29 | 'marry', 30 | 'react', 31 | 'batty', 32 | 'pride', 33 | 'floss', 34 | 'helix', 35 | 'croak', 36 | 'staff', 37 | 'paper', 38 | 'unfed', 39 | 'whelp', 40 | 'trawl', 41 | 'outdo', 42 | 'adobe', 43 | 'crazy', 44 | 'sower', 45 | 'repay', 46 | 'digit', 47 | 'crate', 48 | 'cluck', 49 | 'spike', 50 | 'mimic', 51 | 'pound', 52 | 'maxim', 53 | 'linen', 54 | 'unmet', 55 | 'flesh', 56 | 'booby', 57 | 'forth', 58 | 'first', 59 | 'stand', 60 | 'belly', 61 | 'ivory', 62 | 'seedy', 63 | 'print', 64 | 'yearn', 65 | 'drain', 66 | 'bribe', 67 | 'stout', 68 | 'panel', 69 | 'crass', 70 | 'flume', 71 | 'offal', 72 | 'agree', 73 | 'error', 74 | 'swirl', 75 | 'argue', 76 | 'bleed', 77 | 'delta', 78 | 'flick', 79 | 'totem', 80 | 'wooer', 81 | 'front', 82 | 'shrub', 83 | 'parry', 84 | 'biome', 85 | 'lapel', 86 | 'start', 87 | 'greet', 88 | 'goner', 89 | 'golem', 90 | 'lusty', 91 | 'loopy', 92 | 'round', 93 | 'audit', 94 | 'lying', 95 | 'gamma', 96 | 'labor', 97 | 'islet', 98 | 'civic', 99 | 'forge', 100 | 'corny', 101 | 'moult', 102 | 'basic', 103 | 'salad', 104 | 'agate', 105 | 'spicy', 106 | 'spray', 107 | 'essay', 108 | 'fjord', 109 | 'spend', 110 | 'kebab', 111 | 'guild', 112 | 'aback', 113 | 'motor', 114 | 'alone', 115 | 'hatch', 116 | 'hyper', 117 | 'thumb', 118 | 'dowry', 119 | 'ought', 120 | 'belch', 121 | 'dutch', 122 | 'pilot', 123 | 'tweed', 124 | 'comet', 125 | 'jaunt', 126 | 'enema', 127 | 'steed', 128 | 'abyss', 129 | 'growl', 130 | 'fling', 131 | 'dozen', 132 | 'boozy', 133 | 'erode', 134 | 'world', 135 | 'gouge', 136 | 'click', 137 | 'briar', 138 | 'great', 139 | 'altar', 140 | 'pulpy', 141 | 'blurt', 142 | 'coast', 143 | 'duchy', 144 | 'groin', 145 | 'fixer', 146 | 'group', 147 | 'rogue', 148 | 'badly', 149 | 'smart', 150 | 'pithy', 151 | 'gaudy', 152 | 'chill', 153 | 'heron', 154 | 'vodka', 155 | 'finer', 156 | 'surer', 157 | 'radio', 158 | 'rouge', 159 | 'perch', 160 | 'retch', 161 | 'wrote', 162 | 'clock', 163 | 'tilde', 164 | 'store', 165 | 'prove', 166 | 'bring', 167 | 'solve', 168 | 'cheat', 169 | 'grime', 170 | 'exult', 171 | 'usher', 172 | 'epoch', 173 | 'triad', 174 | 'break', 175 | 'rhino', 176 | 'viral', 177 | 'conic', 178 | 'masse', 179 | 'sonic', 180 | 'vital', 181 | 'trace', 182 | 'using', 183 | 'peach', 184 | 'champ', 185 | 'baton', 186 | 'brake', 187 | 'pluck', 188 | 'craze', 189 | 'gripe', 190 | 'weary', 191 | 'picky', 192 | 'acute', 193 | 'ferry', 194 | 'aside', 195 | 'tapir', 196 | 'troll', 197 | 'unify', 198 | 'rebus', 199 | 'boost', 200 | 'truss', 201 | 'siege', 202 | 'tiger', 203 | 'banal', 204 | 'slump', 205 | 'crank', 206 | 'gorge', 207 | 'query', 208 | 'drink', 209 | 'favor', 210 | 'abbey', 211 | 'tangy', 212 | 'panic', 213 | 'solar', 214 | 'shire', 215 | 'proxy', 216 | 'point', 217 | 'robot', 218 | 'prick', 219 | 'wince', 220 | 'crimp', 221 | 'knoll', 222 | 'sugar', 223 | 'whack', 224 | 'mount', 225 | 'perky', 226 | 'could', 227 | 'wrung', 228 | 'light', 229 | 'those', 230 | 'moist', 231 | 'shard', 232 | 'pleat', 233 | 'aloft', 234 | 'skill', 235 | 'elder', 236 | 'frame', 237 | 'humor', 238 | 'pause', 239 | 'ulcer', 240 | 'ultra', 241 | 'robin', 242 | 'cynic', 243 | 'agora', 244 | 'aroma', 245 | 'caulk', 246 | 'shake', 247 | 'pupal', 248 | 'dodge', 249 | 'swill', 250 | 'tacit', 251 | 'other', 252 | 'thorn', 253 | 'trove', 254 | 'bloke', 255 | 'vivid', 256 | 'spill', 257 | 'chant', 258 | 'choke', 259 | 'rupee', 260 | 'nasty', 261 | 'mourn', 262 | 'ahead', 263 | 'brine', 264 | 'cloth', 265 | 'hoard', 266 | 'sweet', 267 | 'month', 268 | 'lapse', 269 | 'watch', 270 | 'today', 271 | 'focus', 272 | 'smelt', 273 | 'tease', 274 | 'cater', 275 | 'movie', 276 | 'lynch', 277 | 'saute', 278 | 'allow', 279 | 'renew', 280 | 'their', 281 | 'slosh', 282 | 'purge', 283 | 'chest', 284 | 'depot', 285 | 'epoxy', 286 | 'nymph', 287 | 'found', 288 | 'shall', 289 | 'harry', 290 | 'stove', 291 | 'lowly', 292 | 'snout', 293 | 'trope', 294 | 'fewer', 295 | 'shawl', 296 | 'natal', 297 | 'fibre', 298 | 'comma', 299 | 'foray', 300 | 'scare', 301 | 'stair', 302 | 'black', 303 | 'squad', 304 | 'royal', 305 | 'chunk', 306 | 'mince', 307 | 'slave', 308 | 'shame', 309 | 'cheek', 310 | 'ample', 311 | 'flair', 312 | 'foyer', 313 | 'cargo', 314 | 'oxide', 315 | 'plant', 316 | 'olive', 317 | 'inert', 318 | 'askew', 319 | 'heist', 320 | 'shown', 321 | 'zesty', 322 | 'hasty', 323 | 'trash', 324 | 'fella', 325 | 'larva', 326 | 'forgo', 327 | 'story', 328 | 'hairy', 329 | 'train', 330 | 'homer', 331 | 'badge', 332 | 'midst', 333 | 'canny', 334 | 'fetus', 335 | 'butch', 336 | 'farce', 337 | 'slung', 338 | 'tipsy', 339 | 'metal', 340 | 'yield', 341 | 'delve', 342 | 'being', 343 | 'scour', 344 | 'glass', 345 | 'gamer', 346 | 'scrap', 347 | 'money', 348 | 'hinge', 349 | 'album', 350 | 'vouch', 351 | 'asset', 352 | 'tiara', 353 | 'crept', 354 | 'bayou', 355 | 'atoll', 356 | 'manor', 357 | 'creak', 358 | 'showy', 359 | 'phase', 360 | 'froth', 361 | 'depth', 362 | 'gloom', 363 | 'flood', 364 | 'trait', 365 | 'girth', 366 | 'piety', 367 | 'payer', 368 | 'goose', 369 | 'float', 370 | 'donor', 371 | 'atone', 372 | 'primo', 373 | 'apron', 374 | 'blown', 375 | 'cacao', 376 | 'loser', 377 | 'input', 378 | 'gloat', 379 | 'awful', 380 | 'brink', 381 | 'smite', 382 | 'beady', 383 | 'rusty', 384 | 'retro', 385 | 'droll', 386 | 'gawky', 387 | 'hutch', 388 | 'pinto', 389 | 'gaily', 390 | 'egret', 391 | 'lilac', 392 | 'sever', 393 | 'field', 394 | 'fluff', 395 | 'hydro', 396 | 'flack', 397 | 'agape', 398 | 'wench', 399 | 'voice', 400 | 'stead', 401 | 'stalk', 402 | 'berth', 403 | 'madam', 404 | 'night', 405 | 'bland', 406 | 'liver', 407 | 'wedge', 408 | 'augur', 409 | 'roomy', 410 | 'wacky', 411 | 'flock', 412 | 'angry', 413 | 'bobby', 414 | 'trite', 415 | 'aphid', 416 | 'tryst', 417 | 'midge', 418 | 'power', 419 | 'elope', 420 | 'cinch', 421 | 'motto', 422 | 'stomp', 423 | 'upset', 424 | 'bluff', 425 | 'cramp', 426 | 'quart', 427 | 'coyly', 428 | 'youth', 429 | 'rhyme', 430 | 'buggy', 431 | 'alien', 432 | 'smear', 433 | 'unfit', 434 | 'patty', 435 | 'cling', 436 | 'glean', 437 | 'label', 438 | 'hunky', 439 | 'khaki', 440 | 'poker', 441 | 'gruel', 442 | 'twice', 443 | 'twang', 444 | 'shrug', 445 | 'treat', 446 | 'unlit', 447 | 'waste', 448 | 'merit', 449 | 'woven', 450 | 'octal', 451 | 'needy', 452 | 'clown', 453 | 'widow', 454 | 'irony', 455 | 'ruder', 456 | 'gauze', 457 | 'chief', 458 | 'onset', 459 | 'prize', 460 | 'fungi', 461 | 'charm', 462 | 'gully', 463 | 'inter', 464 | 'whoop', 465 | 'taunt', 466 | 'leery', 467 | 'class', 468 | 'theme', 469 | 'lofty', 470 | 'tibia', 471 | 'booze', 472 | 'alpha', 473 | 'thyme', 474 | 'eclat', 475 | 'doubt', 476 | 'parer', 477 | 'chute', 478 | 'stick', 479 | 'trice', 480 | 'alike', 481 | 'sooth', 482 | 'recap', 483 | 'saint', 484 | 'liege', 485 | 'glory', 486 | 'grate', 487 | 'admit', 488 | 'brisk', 489 | 'soggy', 490 | 'usurp', 491 | 'scald', 492 | 'scorn', 493 | 'leave', 494 | 'twine', 495 | 'sting', 496 | 'bough', 497 | 'marsh', 498 | 'sloth', 499 | 'dandy', 500 | 'vigor', 501 | 'howdy', 502 | 'enjoy', 503 | 'valid', 504 | 'ionic', 505 | 'equal', 506 | 'unset', 507 | 'floor', 508 | 'catch', 509 | 'spade', 510 | 'stein', 511 | 'exist', 512 | 'quirk', 513 | 'denim', 514 | 'grove', 515 | 'spiel', 516 | 'mummy', 517 | 'fault', 518 | 'foggy', 519 | 'flout', 520 | 'carry', 521 | 'sneak', 522 | 'libel', 523 | 'waltz', 524 | 'aptly', 525 | 'piney', 526 | 'inept', 527 | 'aloud', 528 | 'photo', 529 | 'dream', 530 | 'stale', 531 | 'vomit', 532 | 'ombre', 533 | 'fanny', 534 | 'unite', 535 | 'snarl', 536 | 'baker', 537 | 'there', 538 | 'glyph', 539 | 'pooch', 540 | 'hippy', 541 | 'spell', 542 | 'folly', 543 | 'louse', 544 | 'gulch', 545 | 'vault', 546 | 'godly', 547 | 'threw', 548 | 'fleet', 549 | 'grave', 550 | 'inane', 551 | 'shock', 552 | 'crave', 553 | 'spite', 554 | 'valve', 555 | 'skimp', 556 | 'claim', 557 | 'rainy', 558 | 'musty', 559 | 'pique', 560 | 'daddy', 561 | 'quasi', 562 | 'arise', 563 | 'aging', 564 | 'valet', 565 | 'opium', 566 | 'avert', 567 | 'stuck', 568 | 'recut', 569 | 'mulch', 570 | 'genre', 571 | 'plume', 572 | 'rifle', 573 | 'count', 574 | 'incur', 575 | 'total', 576 | 'wrest', 577 | 'mocha', 578 | 'deter', 579 | 'study', 580 | 'lover', 581 | 'safer', 582 | 'rivet', 583 | 'funny', 584 | 'smoke', 585 | 'mound', 586 | 'undue', 587 | 'sedan', 588 | 'pagan', 589 | 'swine', 590 | 'guile', 591 | 'gusty', 592 | 'equip', 593 | 'tough', 594 | 'canoe', 595 | 'chaos', 596 | 'covet', 597 | 'human', 598 | 'udder', 599 | 'lunch', 600 | 'blast', 601 | 'stray', 602 | 'manga', 603 | 'melee', 604 | 'lefty', 605 | 'quick', 606 | 'paste', 607 | 'given', 608 | 'octet', 609 | 'risen', 610 | 'groan', 611 | 'leaky', 612 | 'grind', 613 | 'carve', 614 | 'loose', 615 | 'sadly', 616 | 'spilt', 617 | 'apple', 618 | 'slack', 619 | 'honey', 620 | 'final', 621 | 'sheen', 622 | 'eerie', 623 | 'minty', 624 | 'slick', 625 | 'derby', 626 | 'wharf', 627 | 'spelt', 628 | 'coach', 629 | 'erupt', 630 | 'singe', 631 | 'price', 632 | 'spawn', 633 | 'fairy', 634 | 'jiffy', 635 | 'filmy', 636 | 'stack', 637 | 'chose', 638 | 'sleep', 639 | 'ardor', 640 | 'nanny', 641 | 'niece', 642 | 'woozy', 643 | 'handy', 644 | 'grace', 645 | 'ditto', 646 | 'stank', 647 | 'cream', 648 | 'usual', 649 | 'diode', 650 | 'valor', 651 | 'angle', 652 | 'ninja', 653 | 'muddy', 654 | 'chase', 655 | 'reply', 656 | 'prone', 657 | 'spoil', 658 | 'heart', 659 | 'shade', 660 | 'diner', 661 | 'arson', 662 | 'onion', 663 | 'sleet', 664 | 'dowel', 665 | 'couch', 666 | 'palsy', 667 | 'bowel', 668 | 'smile', 669 | 'evoke', 670 | 'creek', 671 | 'lance', 672 | 'eagle', 673 | 'idiot', 674 | 'siren', 675 | 'built', 676 | 'embed', 677 | 'award', 678 | 'dross', 679 | 'annul', 680 | 'goody', 681 | 'frown', 682 | 'patio', 683 | 'laden', 684 | 'humid', 685 | 'elite', 686 | 'lymph', 687 | 'edify', 688 | 'might', 689 | 'reset', 690 | 'visit', 691 | 'gusto', 692 | 'purse', 693 | 'vapor', 694 | 'crock', 695 | 'write', 696 | 'sunny', 697 | 'loath', 698 | 'chaff', 699 | 'slide', 700 | 'queer', 701 | 'venom', 702 | 'stamp', 703 | 'sorry', 704 | 'still', 705 | 'acorn', 706 | 'aping', 707 | 'pushy', 708 | 'tamer', 709 | 'hater', 710 | 'mania', 711 | 'awoke', 712 | 'brawn', 713 | 'swift', 714 | 'exile', 715 | 'birch', 716 | 'lucky', 717 | 'freer', 718 | 'risky', 719 | 'ghost', 720 | 'plier', 721 | 'lunar', 722 | 'winch', 723 | 'snare', 724 | 'nurse', 725 | 'house', 726 | 'borax', 727 | 'nicer', 728 | 'lurch', 729 | 'exalt', 730 | 'about', 731 | 'savvy', 732 | 'toxin', 733 | 'tunic', 734 | 'pried', 735 | 'inlay', 736 | 'chump', 737 | 'lanky', 738 | 'cress', 739 | 'eater', 740 | 'elude', 741 | 'cycle', 742 | 'kitty', 743 | 'boule', 744 | 'moron', 745 | 'tenet', 746 | 'place', 747 | 'lobby', 748 | 'plush', 749 | 'vigil', 750 | 'index', 751 | 'blink', 752 | 'clung', 753 | 'qualm', 754 | 'croup', 755 | 'clink', 756 | 'juicy', 757 | 'stage', 758 | 'decay', 759 | 'nerve', 760 | 'flier', 761 | 'shaft', 762 | 'crook', 763 | 'clean', 764 | 'china', 765 | 'ridge', 766 | 'vowel', 767 | 'gnome', 768 | 'snuck', 769 | 'icing', 770 | 'spiny', 771 | 'rigor', 772 | 'snail', 773 | 'flown', 774 | 'rabid', 775 | 'prose', 776 | 'thank', 777 | 'poppy', 778 | 'budge', 779 | 'fiber', 780 | 'moldy', 781 | 'dowdy', 782 | 'kneel', 783 | 'track', 784 | 'caddy', 785 | 'quell', 786 | 'dumpy', 787 | 'paler', 788 | 'swore', 789 | 'rebar', 790 | 'scuba', 791 | 'splat', 792 | 'flyer', 793 | 'horny', 794 | 'mason', 795 | 'doing', 796 | 'ozone', 797 | 'amply', 798 | 'molar', 799 | 'ovary', 800 | 'beset', 801 | 'queue', 802 | 'cliff', 803 | 'magic', 804 | 'truce', 805 | 'sport', 806 | 'fritz', 807 | 'edict', 808 | 'twirl', 809 | 'verse', 810 | 'llama', 811 | 'eaten', 812 | 'range', 813 | 'whisk', 814 | 'hovel', 815 | 'rehab', 816 | 'macaw', 817 | 'sigma', 818 | 'spout', 819 | 'verve', 820 | 'sushi', 821 | 'dying', 822 | 'fetid', 823 | 'brain', 824 | 'buddy', 825 | 'thump', 826 | 'scion', 827 | 'candy', 828 | 'chord', 829 | 'basin', 830 | 'march', 831 | 'crowd', 832 | 'arbor', 833 | 'gayly', 834 | 'musky', 835 | 'stain', 836 | 'dally', 837 | 'bless', 838 | 'bravo', 839 | 'stung', 840 | 'title', 841 | 'ruler', 842 | 'kiosk', 843 | 'blond', 844 | 'ennui', 845 | 'layer', 846 | 'fluid', 847 | 'tatty', 848 | 'score', 849 | 'cutie', 850 | 'zebra', 851 | 'barge', 852 | 'matey', 853 | 'bluer', 854 | 'aider', 855 | 'shook', 856 | 'river', 857 | 'privy', 858 | 'betel', 859 | 'frisk', 860 | 'bongo', 861 | 'begun', 862 | 'azure', 863 | 'weave', 864 | 'genie', 865 | 'sound', 866 | 'glove', 867 | 'braid', 868 | 'scope', 869 | 'wryly', 870 | 'rover', 871 | 'assay', 872 | 'ocean', 873 | 'bloom', 874 | 'irate', 875 | 'later', 876 | 'woken', 877 | 'silky', 878 | 'wreck', 879 | 'dwelt', 880 | 'slate', 881 | 'smack', 882 | 'solid', 883 | 'amaze', 884 | 'hazel', 885 | 'wrist', 886 | 'jolly', 887 | 'globe', 888 | 'flint', 889 | 'rouse', 890 | 'civil', 891 | 'vista', 892 | 'relax', 893 | 'cover', 894 | 'alive', 895 | 'beech', 896 | 'jetty', 897 | 'bliss', 898 | 'vocal', 899 | 'often', 900 | 'dolly', 901 | 'eight', 902 | 'joker', 903 | 'since', 904 | 'event', 905 | 'ensue', 906 | 'shunt', 907 | 'diver', 908 | 'poser', 909 | 'worst', 910 | 'sweep', 911 | 'alley', 912 | 'creed', 913 | 'anime', 914 | 'leafy', 915 | 'bosom', 916 | 'dunce', 917 | 'stare', 918 | 'pudgy', 919 | 'waive', 920 | 'choir', 921 | 'stood', 922 | 'spoke', 923 | 'outgo', 924 | 'delay', 925 | 'bilge', 926 | 'ideal', 927 | 'clasp', 928 | 'seize', 929 | 'hotly', 930 | 'laugh', 931 | 'sieve', 932 | 'block', 933 | 'meant', 934 | 'grape', 935 | 'noose', 936 | 'hardy', 937 | 'shied', 938 | 'drawl', 939 | 'daisy', 940 | 'putty', 941 | 'strut', 942 | 'burnt', 943 | 'tulip', 944 | 'crick', 945 | 'idyll', 946 | 'vixen', 947 | 'furor', 948 | 'geeky', 949 | 'cough', 950 | 'naive', 951 | 'shoal', 952 | 'stork', 953 | 'bathe', 954 | 'aunty', 955 | 'check', 956 | 'prime', 957 | 'brass', 958 | 'outer', 959 | 'furry', 960 | 'razor', 961 | 'elect', 962 | 'evict', 963 | 'imply', 964 | 'demur', 965 | 'quota', 966 | 'haven', 967 | 'cavil', 968 | 'swear', 969 | 'crump', 970 | 'dough', 971 | 'gavel', 972 | 'wagon', 973 | 'salon', 974 | 'nudge', 975 | 'harem', 976 | 'pitch', 977 | 'sworn', 978 | 'pupil', 979 | 'excel', 980 | 'stony', 981 | 'cabin', 982 | 'unzip', 983 | 'queen', 984 | 'trout', 985 | 'polyp', 986 | 'earth', 987 | 'storm', 988 | 'until', 989 | 'taper', 990 | 'enter', 991 | 'child', 992 | 'adopt', 993 | 'minor', 994 | 'fatty', 995 | 'husky', 996 | 'brave', 997 | 'filet', 998 | 'slime', 999 | 'glint', 1000 | 'tread', 1001 | 'steal', 1002 | 'regal', 1003 | 'guest', 1004 | 'every', 1005 | 'murky', 1006 | 'share', 1007 | 'spore', 1008 | 'hoist', 1009 | 'buxom', 1010 | 'inner', 1011 | 'otter', 1012 | 'dimly', 1013 | 'level', 1014 | 'sumac', 1015 | 'donut', 1016 | 'stilt', 1017 | 'arena', 1018 | 'sheet', 1019 | 'scrub', 1020 | 'fancy', 1021 | 'slimy', 1022 | 'pearl', 1023 | 'silly', 1024 | 'porch', 1025 | 'dingo', 1026 | 'sepia', 1027 | 'amble', 1028 | 'shady', 1029 | 'bread', 1030 | 'friar', 1031 | 'reign', 1032 | 'dairy', 1033 | 'quill', 1034 | 'cross', 1035 | 'brood', 1036 | 'tuber', 1037 | 'shear', 1038 | 'posit', 1039 | 'blank', 1040 | 'villa', 1041 | 'shank', 1042 | 'piggy', 1043 | 'freak', 1044 | 'which', 1045 | 'among', 1046 | 'fecal', 1047 | 'shell', 1048 | 'would', 1049 | 'algae', 1050 | 'large', 1051 | 'rabbi', 1052 | 'agony', 1053 | 'amuse', 1054 | 'bushy', 1055 | 'copse', 1056 | 'swoon', 1057 | 'knife', 1058 | 'pouch', 1059 | 'ascot', 1060 | 'plane', 1061 | 'crown', 1062 | 'urban', 1063 | 'snide', 1064 | 'relay', 1065 | 'abide', 1066 | 'viola', 1067 | 'rajah', 1068 | 'straw', 1069 | 'dilly', 1070 | 'crash', 1071 | 'amass', 1072 | 'third', 1073 | 'trick', 1074 | 'tutor', 1075 | 'woody', 1076 | 'blurb', 1077 | 'grief', 1078 | 'disco', 1079 | 'where', 1080 | 'sassy', 1081 | 'beach', 1082 | 'sauna', 1083 | 'comic', 1084 | 'clued', 1085 | 'creep', 1086 | 'caste', 1087 | 'graze', 1088 | 'snuff', 1089 | 'frock', 1090 | 'gonad', 1091 | 'drunk', 1092 | 'prong', 1093 | 'lurid', 1094 | 'steel', 1095 | 'halve', 1096 | 'buyer', 1097 | 'vinyl', 1098 | 'utile', 1099 | 'smell', 1100 | 'adage', 1101 | 'worry', 1102 | 'tasty', 1103 | 'local', 1104 | 'trade', 1105 | 'finch', 1106 | 'ashen', 1107 | 'modal', 1108 | 'gaunt', 1109 | 'clove', 1110 | 'enact', 1111 | 'adorn', 1112 | 'roast', 1113 | 'speck', 1114 | 'sheik', 1115 | 'missy', 1116 | 'grunt', 1117 | 'snoop', 1118 | 'party', 1119 | 'touch', 1120 | 'mafia', 1121 | 'emcee', 1122 | 'array', 1123 | 'south', 1124 | 'vapid', 1125 | 'jelly', 1126 | 'skulk', 1127 | 'angst', 1128 | 'tubal', 1129 | 'lower', 1130 | 'crest', 1131 | 'sweat', 1132 | 'cyber', 1133 | 'adore', 1134 | 'tardy', 1135 | 'swami', 1136 | 'notch', 1137 | 'groom', 1138 | 'roach', 1139 | 'hitch', 1140 | 'young', 1141 | 'align', 1142 | 'ready', 1143 | 'frond', 1144 | 'strap', 1145 | 'puree', 1146 | 'realm', 1147 | 'venue', 1148 | 'swarm', 1149 | 'offer', 1150 | 'seven', 1151 | 'dryer', 1152 | 'diary', 1153 | 'dryly', 1154 | 'drank', 1155 | 'acrid', 1156 | 'heady', 1157 | 'theta', 1158 | 'junto', 1159 | 'pixie', 1160 | 'quoth', 1161 | 'bonus', 1162 | 'shalt', 1163 | 'penne', 1164 | 'amend', 1165 | 'datum', 1166 | 'build', 1167 | 'piano', 1168 | 'shelf', 1169 | 'lodge', 1170 | 'suing', 1171 | 'rearm', 1172 | 'coral', 1173 | 'ramen', 1174 | 'worth', 1175 | 'psalm', 1176 | 'infer', 1177 | 'overt', 1178 | 'mayor', 1179 | 'ovoid', 1180 | 'glide', 1181 | 'usage', 1182 | 'poise', 1183 | 'randy', 1184 | 'chuck', 1185 | 'prank', 1186 | 'fishy', 1187 | 'tooth', 1188 | 'ether', 1189 | 'drove', 1190 | 'idler', 1191 | 'swath', 1192 | 'stint', 1193 | 'while', 1194 | 'begat', 1195 | 'apply', 1196 | 'slang', 1197 | 'tarot', 1198 | 'radar', 1199 | 'credo', 1200 | 'aware', 1201 | 'canon', 1202 | 'shift', 1203 | 'timer', 1204 | 'bylaw', 1205 | 'serum', 1206 | 'three', 1207 | 'steak', 1208 | 'iliac', 1209 | 'shirk', 1210 | 'blunt', 1211 | 'puppy', 1212 | 'penal', 1213 | 'joist', 1214 | 'bunny', 1215 | 'shape', 1216 | 'beget', 1217 | 'wheel', 1218 | 'adept', 1219 | 'stunt', 1220 | 'stole', 1221 | 'topaz', 1222 | 'chore', 1223 | 'fluke', 1224 | 'afoot', 1225 | 'bloat', 1226 | 'bully', 1227 | 'dense', 1228 | 'caper', 1229 | 'sneer', 1230 | 'boxer', 1231 | 'jumbo', 1232 | 'lunge', 1233 | 'space', 1234 | 'avail', 1235 | 'short', 1236 | 'slurp', 1237 | 'loyal', 1238 | 'flirt', 1239 | 'pizza', 1240 | 'conch', 1241 | 'tempo', 1242 | 'droop', 1243 | 'plate', 1244 | 'bible', 1245 | 'plunk', 1246 | 'afoul', 1247 | 'savoy', 1248 | 'steep', 1249 | 'agile', 1250 | 'stake', 1251 | 'dwell', 1252 | 'knave', 1253 | 'beard', 1254 | 'arose', 1255 | 'motif', 1256 | 'smash', 1257 | 'broil', 1258 | 'glare', 1259 | 'shove', 1260 | 'baggy', 1261 | 'mammy', 1262 | 'swamp', 1263 | 'along', 1264 | 'rugby', 1265 | 'wager', 1266 | 'quack', 1267 | 'squat', 1268 | 'snaky', 1269 | 'debit', 1270 | 'mange', 1271 | 'skate', 1272 | 'ninth', 1273 | 'joust', 1274 | 'tramp', 1275 | 'spurn', 1276 | 'medal', 1277 | 'micro', 1278 | 'rebel', 1279 | 'flank', 1280 | 'learn', 1281 | 'nadir', 1282 | 'maple', 1283 | 'comfy', 1284 | 'remit', 1285 | 'gruff', 1286 | 'ester', 1287 | 'least', 1288 | 'mogul', 1289 | 'fetch', 1290 | 'cause', 1291 | 'oaken', 1292 | 'aglow', 1293 | 'meaty', 1294 | 'gaffe', 1295 | 'shyly', 1296 | 'racer', 1297 | 'prowl', 1298 | 'thief', 1299 | 'stern', 1300 | 'poesy', 1301 | 'rocky', 1302 | 'tweet', 1303 | 'waist', 1304 | 'spire', 1305 | 'grope', 1306 | 'havoc', 1307 | 'patsy', 1308 | 'truly', 1309 | 'forty', 1310 | 'deity', 1311 | 'uncle', 1312 | 'swish', 1313 | 'giver', 1314 | 'preen', 1315 | 'bevel', 1316 | 'lemur', 1317 | 'draft', 1318 | 'slope', 1319 | 'annoy', 1320 | 'lingo', 1321 | 'bleak', 1322 | 'ditty', 1323 | 'curly', 1324 | 'cedar', 1325 | 'dirge', 1326 | 'grown', 1327 | 'horde', 1328 | 'drool', 1329 | 'shuck', 1330 | 'crypt', 1331 | 'cumin', 1332 | 'stock', 1333 | 'gravy', 1334 | 'locus', 1335 | 'wider', 1336 | 'breed', 1337 | 'quite', 1338 | 'chafe', 1339 | 'cache', 1340 | 'blimp', 1341 | 'deign', 1342 | 'fiend', 1343 | 'logic', 1344 | 'cheap', 1345 | 'elide', 1346 | 'rigid', 1347 | 'false', 1348 | 'renal', 1349 | 'pence', 1350 | 'rowdy', 1351 | 'shoot', 1352 | 'blaze', 1353 | 'envoy', 1354 | 'posse', 1355 | 'brief', 1356 | 'never', 1357 | 'abort', 1358 | 'mouse', 1359 | 'mucky', 1360 | 'sulky', 1361 | 'fiery', 1362 | 'media', 1363 | 'trunk', 1364 | 'yeast', 1365 | 'clear', 1366 | 'skunk', 1367 | 'scalp', 1368 | 'bitty', 1369 | 'cider', 1370 | 'koala', 1371 | 'duvet', 1372 | 'segue', 1373 | 'creme', 1374 | 'super', 1375 | 'grill', 1376 | 'after', 1377 | 'owner', 1378 | 'ember', 1379 | 'reach', 1380 | 'nobly', 1381 | 'empty', 1382 | 'speed', 1383 | 'gipsy', 1384 | 'recur', 1385 | 'smock', 1386 | 'dread', 1387 | 'merge', 1388 | 'burst', 1389 | 'kappa', 1390 | 'amity', 1391 | 'shaky', 1392 | 'hover', 1393 | 'carol', 1394 | 'snort', 1395 | 'synod', 1396 | 'faint', 1397 | 'haunt', 1398 | 'flour', 1399 | 'chair', 1400 | 'detox', 1401 | 'shrew', 1402 | 'tense', 1403 | 'plied', 1404 | 'quark', 1405 | 'burly', 1406 | 'novel', 1407 | 'waxen', 1408 | 'stoic', 1409 | 'jerky', 1410 | 'blitz', 1411 | 'beefy', 1412 | 'lyric', 1413 | 'hussy', 1414 | 'towel', 1415 | 'quilt', 1416 | 'below', 1417 | 'bingo', 1418 | 'wispy', 1419 | 'brash', 1420 | 'scone', 1421 | 'toast', 1422 | 'easel', 1423 | 'saucy', 1424 | 'value', 1425 | 'spice', 1426 | 'honor', 1427 | 'route', 1428 | 'sharp', 1429 | 'bawdy', 1430 | 'radii', 1431 | 'skull', 1432 | 'phony', 1433 | 'issue', 1434 | 'lager', 1435 | 'swell', 1436 | 'urine', 1437 | 'gassy', 1438 | 'trial', 1439 | 'flora', 1440 | 'upper', 1441 | 'latch', 1442 | 'wight', 1443 | 'brick', 1444 | 'retry', 1445 | 'holly', 1446 | 'decal', 1447 | 'grass', 1448 | 'shack', 1449 | 'dogma', 1450 | 'mover', 1451 | 'defer', 1452 | 'sober', 1453 | 'optic', 1454 | 'crier', 1455 | 'vying', 1456 | 'nomad', 1457 | 'flute', 1458 | 'hippo', 1459 | 'shark', 1460 | 'drier', 1461 | 'obese', 1462 | 'bugle', 1463 | 'tawny', 1464 | 'chalk', 1465 | 'feast', 1466 | 'ruddy', 1467 | 'pedal', 1468 | 'scarf', 1469 | 'cruel', 1470 | 'bleat', 1471 | 'tidal', 1472 | 'slush', 1473 | 'semen', 1474 | 'windy', 1475 | 'dusty', 1476 | 'sally', 1477 | 'igloo', 1478 | 'nerdy', 1479 | 'jewel', 1480 | 'shone', 1481 | 'whale', 1482 | 'hymen', 1483 | 'abuse', 1484 | 'fugue', 1485 | 'elbow', 1486 | 'crumb', 1487 | 'pansy', 1488 | 'welsh', 1489 | 'syrup', 1490 | 'terse', 1491 | 'suave', 1492 | 'gamut', 1493 | 'swung', 1494 | 'drake', 1495 | 'freed', 1496 | 'afire', 1497 | 'shirt', 1498 | 'grout', 1499 | 'oddly', 1500 | 'tithe', 1501 | 'plaid', 1502 | 'dummy', 1503 | 'broom', 1504 | 'blind', 1505 | 'torch', 1506 | 'enemy', 1507 | 'again', 1508 | 'tying', 1509 | 'pesky', 1510 | 'alter', 1511 | 'gazer', 1512 | 'noble', 1513 | 'ethos', 1514 | 'bride', 1515 | 'extol', 1516 | 'decor', 1517 | 'hobby', 1518 | 'beast', 1519 | 'idiom', 1520 | 'utter', 1521 | 'these', 1522 | 'sixth', 1523 | 'alarm', 1524 | 'erase', 1525 | 'elegy', 1526 | 'spunk', 1527 | 'piper', 1528 | 'scaly', 1529 | 'scold', 1530 | 'hefty', 1531 | 'chick', 1532 | 'sooty', 1533 | 'canal', 1534 | 'whiny', 1535 | 'slash', 1536 | 'quake', 1537 | 'joint', 1538 | 'swept', 1539 | 'prude', 1540 | 'heavy', 1541 | 'wield', 1542 | 'femme', 1543 | 'lasso', 1544 | 'maize', 1545 | 'shale', 1546 | 'screw', 1547 | 'spree', 1548 | 'smoky', 1549 | 'whiff', 1550 | 'scent', 1551 | 'glade', 1552 | 'spent', 1553 | 'prism', 1554 | 'stoke', 1555 | 'riper', 1556 | 'orbit', 1557 | 'cocoa', 1558 | 'guilt', 1559 | 'humus', 1560 | 'shush', 1561 | 'table', 1562 | 'smirk', 1563 | 'wrong', 1564 | 'noisy', 1565 | 'alert', 1566 | 'shiny', 1567 | 'elate', 1568 | 'resin', 1569 | 'whole', 1570 | 'hunch', 1571 | 'pixel', 1572 | 'polar', 1573 | 'hotel', 1574 | 'sword', 1575 | 'cleat', 1576 | 'mango', 1577 | 'rumba', 1578 | 'puffy', 1579 | 'filly', 1580 | 'billy', 1581 | 'leash', 1582 | 'clout', 1583 | 'dance', 1584 | 'ovate', 1585 | 'facet', 1586 | 'chili', 1587 | 'paint', 1588 | 'liner', 1589 | 'curio', 1590 | 'salty', 1591 | 'audio', 1592 | 'snake', 1593 | 'fable', 1594 | 'cloak', 1595 | 'navel', 1596 | 'spurt', 1597 | 'pesto', 1598 | 'balmy', 1599 | 'flash', 1600 | 'unwed', 1601 | 'early', 1602 | 'churn', 1603 | 'weedy', 1604 | 'stump', 1605 | 'lease', 1606 | 'witty', 1607 | 'wimpy', 1608 | 'spoof', 1609 | 'saner', 1610 | 'blend', 1611 | 'salsa', 1612 | 'thick', 1613 | 'warty', 1614 | 'manic', 1615 | 'blare', 1616 | 'squib', 1617 | 'spoon', 1618 | 'probe', 1619 | 'crepe', 1620 | 'knack', 1621 | 'force', 1622 | 'debut', 1623 | 'order', 1624 | 'haste', 1625 | 'teeth', 1626 | 'agent', 1627 | 'widen', 1628 | 'icily', 1629 | 'slice', 1630 | 'ingot', 1631 | 'clash', 1632 | 'juror', 1633 | 'blood', 1634 | 'abode', 1635 | 'throw', 1636 | 'unity', 1637 | 'pivot', 1638 | 'slept', 1639 | 'troop', 1640 | 'spare', 1641 | 'sewer', 1642 | 'parse', 1643 | 'morph', 1644 | 'cacti', 1645 | 'tacky', 1646 | 'spool', 1647 | 'demon', 1648 | 'moody', 1649 | 'annex', 1650 | 'begin', 1651 | 'fuzzy', 1652 | 'patch', 1653 | 'water', 1654 | 'lumpy', 1655 | 'admin', 1656 | 'omega', 1657 | 'limit', 1658 | 'tabby', 1659 | 'macho', 1660 | 'aisle', 1661 | 'skiff', 1662 | 'basis', 1663 | 'plank', 1664 | 'verge', 1665 | 'botch', 1666 | 'crawl', 1667 | 'lousy', 1668 | 'slain', 1669 | 'cubic', 1670 | 'raise', 1671 | 'wrack', 1672 | 'guide', 1673 | 'foist', 1674 | 'cameo', 1675 | 'under', 1676 | 'actor', 1677 | 'revue', 1678 | 'fraud', 1679 | 'harpy', 1680 | 'scoop', 1681 | 'climb', 1682 | 'refer', 1683 | 'olden', 1684 | 'clerk', 1685 | 'debar', 1686 | 'tally', 1687 | 'ethic', 1688 | 'cairn', 1689 | 'tulle', 1690 | 'ghoul', 1691 | 'hilly', 1692 | 'crude', 1693 | 'apart', 1694 | 'scale', 1695 | 'older', 1696 | 'plain', 1697 | 'sperm', 1698 | 'briny', 1699 | 'abbot', 1700 | 'rerun', 1701 | 'quest', 1702 | 'crisp', 1703 | 'bound', 1704 | 'befit', 1705 | 'drawn', 1706 | 'suite', 1707 | 'itchy', 1708 | 'cheer', 1709 | 'bagel', 1710 | 'guess', 1711 | 'broad', 1712 | 'axiom', 1713 | 'chard', 1714 | 'caput', 1715 | 'leant', 1716 | 'harsh', 1717 | 'curse', 1718 | 'proud', 1719 | 'swing', 1720 | 'opine', 1721 | 'taste', 1722 | 'lupus', 1723 | 'gumbo', 1724 | 'miner', 1725 | 'green', 1726 | 'chasm', 1727 | 'lipid', 1728 | 'topic', 1729 | 'armor', 1730 | 'brush', 1731 | 'crane', 1732 | 'mural', 1733 | 'abled', 1734 | 'habit', 1735 | 'bossy', 1736 | 'maker', 1737 | 'dusky', 1738 | 'dizzy', 1739 | 'lithe', 1740 | 'brook', 1741 | 'jazzy', 1742 | 'fifty', 1743 | 'sense', 1744 | 'giant', 1745 | 'surly', 1746 | 'legal', 1747 | 'fatal', 1748 | 'flunk', 1749 | 'began', 1750 | 'prune', 1751 | 'small', 1752 | 'slant', 1753 | 'scoff', 1754 | 'torus', 1755 | 'ninny', 1756 | 'covey', 1757 | 'viper', 1758 | 'taken', 1759 | 'moral', 1760 | 'vogue', 1761 | 'owing', 1762 | 'token', 1763 | 'entry', 1764 | 'booth', 1765 | 'voter', 1766 | 'chide', 1767 | 'elfin', 1768 | 'ebony', 1769 | 'neigh', 1770 | 'minim', 1771 | 'melon', 1772 | 'kneed', 1773 | 'decoy', 1774 | 'voila', 1775 | 'ankle', 1776 | 'arrow', 1777 | 'mushy', 1778 | 'tribe', 1779 | 'cease', 1780 | 'eager', 1781 | 'birth', 1782 | 'graph', 1783 | 'odder', 1784 | 'terra', 1785 | 'weird', 1786 | 'tried', 1787 | 'clack', 1788 | 'color', 1789 | 'rough', 1790 | 'weigh', 1791 | 'uncut', 1792 | 'ladle', 1793 | 'strip', 1794 | 'craft', 1795 | 'minus', 1796 | 'dicey', 1797 | 'titan', 1798 | 'lucid', 1799 | 'vicar', 1800 | 'dress', 1801 | 'ditch', 1802 | 'gypsy', 1803 | 'pasta', 1804 | 'taffy', 1805 | 'flame', 1806 | 'swoop', 1807 | 'aloof', 1808 | 'sight', 1809 | 'broke', 1810 | 'teary', 1811 | 'chart', 1812 | 'sixty', 1813 | 'wordy', 1814 | 'sheer', 1815 | 'leper', 1816 | 'nosey', 1817 | 'bulge', 1818 | 'savor', 1819 | 'clamp', 1820 | 'funky', 1821 | 'foamy', 1822 | 'toxic', 1823 | 'brand', 1824 | 'plumb', 1825 | 'dingy', 1826 | 'butte', 1827 | 'drill', 1828 | 'tripe', 1829 | 'bicep', 1830 | 'tenor', 1831 | 'krill', 1832 | 'worse', 1833 | 'drama', 1834 | 'hyena', 1835 | 'think', 1836 | 'ratio', 1837 | 'cobra', 1838 | 'basil', 1839 | 'scrum', 1840 | 'bused', 1841 | 'phone', 1842 | 'court', 1843 | 'camel', 1844 | 'proof', 1845 | 'heard', 1846 | 'angel', 1847 | 'petal', 1848 | 'pouty', 1849 | 'throb', 1850 | 'maybe', 1851 | 'fetal', 1852 | 'sprig', 1853 | 'spine', 1854 | 'shout', 1855 | 'cadet', 1856 | 'macro', 1857 | 'dodgy', 1858 | 'satyr', 1859 | 'rarer', 1860 | 'binge', 1861 | 'trend', 1862 | 'nutty', 1863 | 'leapt', 1864 | 'amiss', 1865 | 'split', 1866 | 'myrrh', 1867 | 'width', 1868 | 'sonar', 1869 | 'tower', 1870 | 'baron', 1871 | 'fever', 1872 | 'waver', 1873 | 'spark', 1874 | 'belie', 1875 | 'sloop', 1876 | 'expel', 1877 | 'smote', 1878 | 'baler', 1879 | 'above', 1880 | 'north', 1881 | 'wafer', 1882 | 'scant', 1883 | 'frill', 1884 | 'awash', 1885 | 'snack', 1886 | 'scowl', 1887 | 'frail', 1888 | 'drift', 1889 | 'limbo', 1890 | 'fence', 1891 | 'motel', 1892 | 'ounce', 1893 | 'wreak', 1894 | 'revel', 1895 | 'talon', 1896 | 'prior', 1897 | 'knelt', 1898 | 'cello', 1899 | 'flake', 1900 | 'debug', 1901 | 'anode', 1902 | 'crime', 1903 | 'salve', 1904 | 'scout', 1905 | 'imbue', 1906 | 'pinky', 1907 | 'stave', 1908 | 'vague', 1909 | 'chock', 1910 | 'fight', 1911 | 'video', 1912 | 'stone', 1913 | 'teach', 1914 | 'cleft', 1915 | 'frost', 1916 | 'prawn', 1917 | 'booty', 1918 | 'twist', 1919 | 'apnea', 1920 | 'stiff', 1921 | 'plaza', 1922 | 'ledge', 1923 | 'tweak', 1924 | 'board', 1925 | 'grant', 1926 | 'medic', 1927 | 'bacon', 1928 | 'cable', 1929 | 'brawl', 1930 | 'slunk', 1931 | 'raspy', 1932 | 'forum', 1933 | 'drone', 1934 | 'women', 1935 | 'mucus', 1936 | 'boast', 1937 | 'toddy', 1938 | 'coven', 1939 | 'tumor', 1940 | 'truer', 1941 | 'wrath', 1942 | 'stall', 1943 | 'steam', 1944 | 'axial', 1945 | 'purer', 1946 | 'daily', 1947 | 'trail', 1948 | 'niche', 1949 | 'mealy', 1950 | 'juice', 1951 | 'nylon', 1952 | 'plump', 1953 | 'merry', 1954 | 'flail', 1955 | 'papal', 1956 | 'wheat', 1957 | 'berry', 1958 | 'cower', 1959 | 'erect', 1960 | 'brute', 1961 | 'leggy', 1962 | 'snipe', 1963 | 'sinew', 1964 | 'skier', 1965 | 'penny', 1966 | 'jumpy', 1967 | 'rally', 1968 | 'umbra', 1969 | 'scary', 1970 | 'modem', 1971 | 'gross', 1972 | 'avian', 1973 | 'greed', 1974 | 'satin', 1975 | 'tonic', 1976 | 'parka', 1977 | 'sniff', 1978 | 'livid', 1979 | 'stark', 1980 | 'trump', 1981 | 'giddy', 1982 | 'reuse', 1983 | 'taboo', 1984 | 'avoid', 1985 | 'quote', 1986 | 'devil', 1987 | 'liken', 1988 | 'gloss', 1989 | 'gayer', 1990 | 'beret', 1991 | 'noise', 1992 | 'gland', 1993 | 'dealt', 1994 | 'sling', 1995 | 'rumor', 1996 | 'opera', 1997 | 'thigh', 1998 | 'tonga', 1999 | 'flare', 2000 | 'wound', 2001 | 'white', 2002 | 'bulky', 2003 | 'etude', 2004 | 'horse', 2005 | 'circa', 2006 | 'paddy', 2007 | 'inbox', 2008 | 'fizzy', 2009 | 'grain', 2010 | 'exert', 2011 | 'surge', 2012 | 'gleam', 2013 | 'belle', 2014 | 'salvo', 2015 | 'crush', 2016 | 'fruit', 2017 | 'sappy', 2018 | 'taker', 2019 | 'tract', 2020 | 'ovine', 2021 | 'spiky', 2022 | 'frank', 2023 | 'reedy', 2024 | 'filth', 2025 | 'spasm', 2026 | 'heave', 2027 | 'mambo', 2028 | 'right', 2029 | 'clank', 2030 | 'trust', 2031 | 'lumen', 2032 | 'borne', 2033 | 'spook', 2034 | 'sauce', 2035 | 'amber', 2036 | 'lathe', 2037 | 'carat', 2038 | 'corer', 2039 | 'dirty', 2040 | 'slyly', 2041 | 'affix', 2042 | 'alloy', 2043 | 'taint', 2044 | 'sheep', 2045 | 'kinky', 2046 | 'wooly', 2047 | 'mauve', 2048 | 'flung', 2049 | 'yacht', 2050 | 'fried', 2051 | 'quail', 2052 | 'brunt', 2053 | 'grimy', 2054 | 'curvy', 2055 | 'cagey', 2056 | 'rinse', 2057 | 'deuce', 2058 | 'state', 2059 | 'grasp', 2060 | 'milky', 2061 | 'bison', 2062 | 'graft', 2063 | 'sandy', 2064 | 'baste', 2065 | 'flask', 2066 | 'hedge', 2067 | 'girly', 2068 | 'swash', 2069 | 'boney', 2070 | 'coupe', 2071 | 'endow', 2072 | 'abhor', 2073 | 'welch', 2074 | 'blade', 2075 | 'tight', 2076 | 'geese', 2077 | 'miser', 2078 | 'mirth', 2079 | 'cloud', 2080 | 'cabal', 2081 | 'leech', 2082 | 'close', 2083 | 'tenth', 2084 | 'pecan', 2085 | 'droit', 2086 | 'grail', 2087 | 'clone', 2088 | 'guise', 2089 | 'ralph', 2090 | 'tango', 2091 | 'biddy', 2092 | 'smith', 2093 | 'mower', 2094 | 'payee', 2095 | 'serif', 2096 | 'drape', 2097 | 'fifth', 2098 | 'spank', 2099 | 'glaze', 2100 | 'allot', 2101 | 'truck', 2102 | 'kayak', 2103 | 'virus', 2104 | 'testy', 2105 | 'tepee', 2106 | 'fully', 2107 | 'zonal', 2108 | 'metro', 2109 | 'curry', 2110 | 'grand', 2111 | 'banjo', 2112 | 'axion', 2113 | 'bezel', 2114 | 'occur', 2115 | 'chain', 2116 | 'nasal', 2117 | 'gooey', 2118 | 'filer', 2119 | 'brace', 2120 | 'allay', 2121 | 'pubic', 2122 | 'raven', 2123 | 'plead', 2124 | 'gnash', 2125 | 'flaky', 2126 | 'munch', 2127 | 'dully', 2128 | 'eking', 2129 | 'thing', 2130 | 'slink', 2131 | 'hurry', 2132 | 'theft', 2133 | 'shorn', 2134 | 'pygmy', 2135 | 'ranch', 2136 | 'wring', 2137 | 'lemon', 2138 | 'shore', 2139 | 'mamma', 2140 | 'froze', 2141 | 'newer', 2142 | 'style', 2143 | 'moose', 2144 | 'antic', 2145 | 'drown', 2146 | 'vegan', 2147 | 'chess', 2148 | 'guppy', 2149 | 'union', 2150 | 'lever', 2151 | 'lorry', 2152 | 'image', 2153 | 'cabby', 2154 | 'druid', 2155 | 'exact', 2156 | 'truth', 2157 | 'dopey', 2158 | 'spear', 2159 | 'cried', 2160 | 'chime', 2161 | 'crony', 2162 | 'stunk', 2163 | 'timid', 2164 | 'batch', 2165 | 'gauge', 2166 | 'rotor', 2167 | 'crack', 2168 | 'curve', 2169 | 'latte', 2170 | 'witch', 2171 | 'bunch', 2172 | 'repel', 2173 | 'anvil', 2174 | 'soapy', 2175 | 'meter', 2176 | 'broth', 2177 | 'madly', 2178 | 'dried', 2179 | 'scene', 2180 | 'known', 2181 | 'magma', 2182 | 'roost', 2183 | 'woman', 2184 | 'thong', 2185 | 'punch', 2186 | 'pasty', 2187 | 'downy', 2188 | 'knead', 2189 | 'whirl', 2190 | 'rapid', 2191 | 'clang', 2192 | 'anger', 2193 | 'drive', 2194 | 'goofy', 2195 | 'email', 2196 | 'music', 2197 | 'stuff', 2198 | 'bleep', 2199 | 'rider', 2200 | 'mecca', 2201 | 'folio', 2202 | 'setup', 2203 | 'verso', 2204 | 'quash', 2205 | 'fauna', 2206 | 'gummy', 2207 | 'happy', 2208 | 'newly', 2209 | 'fussy', 2210 | 'relic', 2211 | 'guava', 2212 | 'ratty', 2213 | 'fudge', 2214 | 'femur', 2215 | 'chirp', 2216 | 'forte', 2217 | 'alibi', 2218 | 'whine', 2219 | 'petty', 2220 | 'golly', 2221 | 'plait', 2222 | 'fleck', 2223 | 'felon', 2224 | 'gourd', 2225 | 'brown', 2226 | 'thrum', 2227 | 'ficus', 2228 | 'stash', 2229 | 'decry', 2230 | 'wiser', 2231 | 'junta', 2232 | 'visor', 2233 | 'daunt', 2234 | 'scree', 2235 | 'impel', 2236 | 'await', 2237 | 'press', 2238 | 'whose', 2239 | 'turbo', 2240 | 'stoop', 2241 | 'speak', 2242 | 'mangy', 2243 | 'eying', 2244 | 'inlet', 2245 | 'crone', 2246 | 'pulse', 2247 | 'mossy', 2248 | 'staid', 2249 | 'hence', 2250 | 'pinch', 2251 | 'teddy', 2252 | 'sully', 2253 | 'snore', 2254 | 'ripen', 2255 | 'snowy', 2256 | 'attic', 2257 | 'going', 2258 | 'leach', 2259 | 'mouth', 2260 | 'hound', 2261 | 'clump', 2262 | 'tonal', 2263 | 'bigot', 2264 | 'peril', 2265 | 'piece', 2266 | 'blame', 2267 | 'haute', 2268 | 'spied', 2269 | 'undid', 2270 | 'intro', 2271 | 'basal', 2272 | 'shine', 2273 | 'gecko', 2274 | 'rodeo', 2275 | 'guard', 2276 | 'steer', 2277 | 'loamy', 2278 | 'scamp', 2279 | 'scram', 2280 | 'manly', 2281 | 'hello', 2282 | 'vaunt', 2283 | 'organ', 2284 | 'feral', 2285 | 'knock', 2286 | 'extra', 2287 | 'condo', 2288 | 'adapt', 2289 | 'willy', 2290 | 'polka', 2291 | 'rayon', 2292 | 'skirt', 2293 | 'faith', 2294 | 'torso', 2295 | 'match', 2296 | 'mercy', 2297 | 'tepid', 2298 | 'sleek', 2299 | 'riser', 2300 | 'twixt', 2301 | 'peace', 2302 | 'flush', 2303 | 'catty', 2304 | 'login', 2305 | 'eject', 2306 | 'roger', 2307 | 'rival', 2308 | 'untie', 2309 | 'refit', 2310 | 'aorta', 2311 | 'adult', 2312 | 'judge', 2313 | 'rower', 2314 | 'artsy', 2315 | 'rural', 2316 | 'shave', 2317 | ] 2318 | --------------------------------------------------------------------------------