From 89712083cc4705a8d9e66e25d2cbd1e0a09b9a06 Mon Sep 17 00:00:00 2001 From: Charles Gould Date: Fri, 30 Dec 2016 04:16:06 -0500 Subject: [PATCH] Initial commit --- .gitignore | 11 + client-api/pom.xml | 22 + .../java/lingo/client/api/StompTopics.java | 17 + client/LingoClient.launch | 24 + client/pom.xml | 43 + client/src/main/config/application.yaml | 7 + .../lingo/client/bootstrap/LingoClient.java | 63 + .../client/bootstrap/LingoPresenter.java | 102 + .../client/multiplayer/MultiplayerConfig.java | 39 + .../multiplayer/MultiplayerPresenter.java | 322 + .../client/multiplayer/StompTemplate.java | 133 + .../singleplayer/SinglePlayerPresenter.java | 158 + .../lingo/client/util/FxmlController.java | 25 + .../main/java/lingo/client/view/Board.java | 35 + .../java/lingo/client/view/GameBoard.java | 80 + .../java/lingo/client/view/OpponentBoard.java | 18 + .../java/lingo/client/view/PlayerBoard.java | 120 + client/src/main/resources/cube-grid.css | 195 + client/src/main/resources/cube-grid.html | 39 + client/src/main/resources/fxml/Lingo.fxml | 38 + .../main/resources/fxml/LingoMultiplayer.fxml | 27 + client/src/main/resources/style.css | 12 + common/pom.xml | 31 + common/src/main/java/lingo/common/Game.java | 91 + common/src/main/java/lingo/common/Report.java | 47 + .../main/java/lingo/common/WordReader.java | 38 + common/src/main/resources/guesses.txt | 9168 +++++++++++++++++ common/src/main/resources/words.txt | 4651 +++++++++ pom.xml | 30 + server/LingoServer.launch | 24 + server/pom.xml | 53 + server/src/main/config/application.yaml | 5 + .../java/lingo/server/LingoController.java | 179 + .../main/java/lingo/server/LingoServer.java | 13 + .../java/lingo/server/WebSocketConfig.java | 24 + .../java/lingo/server/WordRepository.java | 39 + 36 files changed, 15923 insertions(+) create mode 100644 .gitignore create mode 100644 client-api/pom.xml create mode 100644 client-api/src/main/java/lingo/client/api/StompTopics.java create mode 100644 client/LingoClient.launch create mode 100644 client/pom.xml create mode 100644 client/src/main/config/application.yaml create mode 100644 client/src/main/java/lingo/client/bootstrap/LingoClient.java create mode 100644 client/src/main/java/lingo/client/bootstrap/LingoPresenter.java create mode 100644 client/src/main/java/lingo/client/multiplayer/MultiplayerConfig.java create mode 100644 client/src/main/java/lingo/client/multiplayer/MultiplayerPresenter.java create mode 100644 client/src/main/java/lingo/client/multiplayer/StompTemplate.java create mode 100644 client/src/main/java/lingo/client/singleplayer/SinglePlayerPresenter.java create mode 100644 client/src/main/java/lingo/client/util/FxmlController.java create mode 100644 client/src/main/java/lingo/client/view/Board.java create mode 100644 client/src/main/java/lingo/client/view/GameBoard.java create mode 100644 client/src/main/java/lingo/client/view/OpponentBoard.java create mode 100644 client/src/main/java/lingo/client/view/PlayerBoard.java create mode 100644 client/src/main/resources/cube-grid.css create mode 100644 client/src/main/resources/cube-grid.html create mode 100644 client/src/main/resources/fxml/Lingo.fxml create mode 100644 client/src/main/resources/fxml/LingoMultiplayer.fxml create mode 100644 client/src/main/resources/style.css create mode 100644 common/pom.xml create mode 100644 common/src/main/java/lingo/common/Game.java create mode 100644 common/src/main/java/lingo/common/Report.java create mode 100644 common/src/main/java/lingo/common/WordReader.java create mode 100644 common/src/main/resources/guesses.txt create mode 100644 common/src/main/resources/words.txt create mode 100644 pom.xml create mode 100644 server/LingoServer.launch create mode 100644 server/pom.xml create mode 100644 server/src/main/config/application.yaml create mode 100644 server/src/main/java/lingo/server/LingoController.java create mode 100644 server/src/main/java/lingo/server/LingoServer.java create mode 100644 server/src/main/java/lingo/server/WebSocketConfig.java create mode 100644 server/src/main/java/lingo/server/WordRepository.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..880acdb --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Maven +target/ + +# Eclipse +.settings/ +*.project +*.classpath + +# IntelliJ IDEA +.idea/ +*.iml diff --git a/client-api/pom.xml b/client-api/pom.xml new file mode 100644 index 0000000..dd043f0 --- /dev/null +++ b/client-api/pom.xml @@ -0,0 +1,22 @@ + + 4.0.0 + + + com.charego + lingo-websocket + 1.0 + + + lingo-websocket-client-api + Lingo WebSocket :: Client API + + + + ${project.groupId} + ${project.version} + lingo-websocket-common + + + + diff --git a/client-api/src/main/java/lingo/client/api/StompTopics.java b/client-api/src/main/java/lingo/client/api/StompTopics.java new file mode 100644 index 0000000..2831daf --- /dev/null +++ b/client-api/src/main/java/lingo/client/api/StompTopics.java @@ -0,0 +1,17 @@ +package lingo.client.api; + +public class StompTopics { + + public static final String OPPONENT_JOINED = createTopicName("opponentJoined"); + + public static final String OPPONENT_LEFT = createTopicName("opponentLeft"); + + public static final String OPPONENT_REPORTS = createTopicName("opponentReports"); + + public static final String PLAYER_REPORTS = createTopicName("playerReports"); + + private static String createTopicName(String suffix) { + return "/topic/lingo/" + suffix; + } + +} diff --git a/client/LingoClient.launch b/client/LingoClient.launch new file mode 100644 index 0000000..53c9bce --- /dev/null +++ b/client/LingoClient.launch @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/pom.xml b/client/pom.xml new file mode 100644 index 0000000..0fc280d --- /dev/null +++ b/client/pom.xml @@ -0,0 +1,43 @@ + + 4.0.0 + + + com.charego + lingo-websocket + 1.0 + + + lingo-websocket-client + Lingo WebSocket :: Client + + + + ${project.groupId} + ${project.version} + lingo-websocket-client-api + + + + + org.springframework.boot + spring-boot-starter-websocket + + + + + + + com.zenjava + javafx-maven-plugin + 8.7.0 + + lingo.client.bootstrap.LingoClient + src/main/config + true + + + + + + diff --git a/client/src/main/config/application.yaml b/client/src/main/config/application.yaml new file mode 100644 index 0000000..eeb2579 --- /dev/null +++ b/client/src/main/config/application.yaml @@ -0,0 +1,7 @@ +# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html + +server: + host: localhost + port: 8080 + stomp: + endpoint: stomp diff --git a/client/src/main/java/lingo/client/bootstrap/LingoClient.java b/client/src/main/java/lingo/client/bootstrap/LingoClient.java new file mode 100644 index 0000000..b3a9742 --- /dev/null +++ b/client/src/main/java/lingo/client/bootstrap/LingoClient.java @@ -0,0 +1,63 @@ +package lingo.client.bootstrap; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.concurrent.CustomizableThreadFactory; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.stage.Stage; + +@SpringBootApplication +public class LingoClient extends Application { + + private Parent root; + + public static void main(final String[] args) { + Application.launch(args); + } + + @Override + public void init() throws Exception { + ConfigurableApplicationContext context = startSpringApplication(); + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Lingo.fxml")); + loader.setControllerFactory(clazz -> context.getBean(clazz)); + root = loader.load(); + } + + @Override + public void start(Stage stage) throws Exception { + // Close the Spring context when the client is closed. + stage.setOnCloseRequest(e -> { + stage.close(); + System.exit(0); + }); + Scene scene = new Scene(root); + scene.getStylesheets().add("/style.css"); + stage.setResizable(false); + stage.setScene(scene); + stage.setTitle("Lingo"); + stage.show(); + } + + private ConfigurableApplicationContext startSpringApplication() { + SpringApplication application = new SpringApplication(LingoClient.class); + String[] args = getParameters().getRaw().stream().toArray(String[]::new); + application.setHeadless(false); + application.setWebEnvironment(false); + return application.run(args); + } + + @Bean + public ExecutorService executorService() { + return Executors.newFixedThreadPool(5, new CustomizableThreadFactory("ClientThread-")); + } + +} diff --git a/client/src/main/java/lingo/client/bootstrap/LingoPresenter.java b/client/src/main/java/lingo/client/bootstrap/LingoPresenter.java new file mode 100644 index 0000000..19c4e9c --- /dev/null +++ b/client/src/main/java/lingo/client/bootstrap/LingoPresenter.java @@ -0,0 +1,102 @@ +package lingo.client.bootstrap; + +import java.io.IOException; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutorService; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.stereotype.Component; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; +import lingo.client.multiplayer.MultiplayerConfig; +import lingo.client.multiplayer.MultiplayerPresenter; +import lingo.client.singleplayer.SinglePlayerPresenter; +import lingo.client.util.FxmlController; +import lingo.common.WordReader; + +@Component +public class LingoPresenter implements FxmlController { + + private static final Logger log = LoggerFactory.getLogger(LingoPresenter.class); + + @Autowired + private ApplicationContext bootstrapContext; + + @Autowired + private ExecutorService executorService; + + @FXML + private BorderPane content; + + @FXML + private BorderPane gameModeChooser; + + @FXML + private void exit(ActionEvent event) { + Stage stage = (Stage) content.getScene().getWindow(); + stage.close(); + System.exit(0); + } + + @Override + public void initialize() { + // No initialization needed + } + + @FXML + private void showMultiplayer(ActionEvent event) { + log.info("Launching multiplayer..."); + + executorService.execute(() -> { + AnnotationConfigApplicationContext multiplayerContext = new AnnotationConfigApplicationContext(); + multiplayerContext.setParent(bootstrapContext); + multiplayerContext.scan(MultiplayerConfig.class.getPackage().getName()); + multiplayerContext.refresh(); + + MultiplayerPresenter presenter = multiplayerContext.getBean(MultiplayerPresenter.class); + presenter.setOnBackButtonPressed(e -> { + multiplayerContext.close(); + content.setCenter(gameModeChooser); + }); + + Platform.runLater(() -> { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/LingoMultiplayer.fxml")); + loader.setControllerFactory(clazz -> multiplayerContext.getBean(clazz)); + try { + content.setCenter(loader.load()); + } catch (IOException e) { + log.error("Failed to load multiplayer", e); + } + }); + }); + } + + @FXML + private void showSinglePlayer(ActionEvent event) { + log.info("Launching single player..."); + + // TODO: Is there a memory leak here? + try { + Set guesses = WordReader.readFileToSet("/guesses.txt"); + List words = WordReader.readFileToList("/words.txt"); + SinglePlayerPresenter presenter = new SinglePlayerPresenter(words, guesses, e -> { + content.setCenter(gameModeChooser); + }); + content.setCenter(presenter.getNode()); + presenter.startGame(); + } catch (IOException e) { + log.error("Failed to load single player", e); + } + } + +} diff --git a/client/src/main/java/lingo/client/multiplayer/MultiplayerConfig.java b/client/src/main/java/lingo/client/multiplayer/MultiplayerConfig.java new file mode 100644 index 0000000..aadf93b --- /dev/null +++ b/client/src/main/java/lingo/client/multiplayer/MultiplayerConfig.java @@ -0,0 +1,39 @@ +package lingo.client.multiplayer; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.converter.ByteArrayMessageConverter; +import org.springframework.messaging.converter.CompositeMessageConverter; +import org.springframework.messaging.converter.MappingJackson2MessageConverter; +import org.springframework.messaging.converter.MessageConverter; +import org.springframework.messaging.converter.StringMessageConverter; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.web.socket.client.WebSocketClient; +import org.springframework.web.socket.client.standard.StandardWebSocketClient; +import org.springframework.web.socket.messaging.WebSocketStompClient; + +@Configuration +public class MultiplayerConfig { + + @Bean + public WebSocketStompClient stompClient(MessageConverter messageConverter) { + WebSocketClient webSocketClient = new StandardWebSocketClient(); + WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient); + stompClient.setMessageConverter(messageConverter); + stompClient.setTaskScheduler(new ThreadPoolTaskScheduler()); + return stompClient; + } + + @Bean + public MessageConverter messageConverter() { + List converters = new ArrayList<>(); + converters.add(new StringMessageConverter()); + converters.add(new ByteArrayMessageConverter()); + converters.add(new MappingJackson2MessageConverter()); + return new CompositeMessageConverter(converters); + } + +} diff --git a/client/src/main/java/lingo/client/multiplayer/MultiplayerPresenter.java b/client/src/main/java/lingo/client/multiplayer/MultiplayerPresenter.java new file mode 100644 index 0000000..8b3ba64 --- /dev/null +++ b/client/src/main/java/lingo/client/multiplayer/MultiplayerPresenter.java @@ -0,0 +1,322 @@ +package lingo.client.multiplayer; + +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; + +import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.simp.stomp.StompFrameHandler; +import org.springframework.messaging.simp.stomp.StompHeaders; +import org.springframework.stereotype.Component; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.fxml.FXML; +import javafx.geometry.VPos; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.Button; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; +import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; +import javafx.scene.text.Font; +import javafx.scene.text.TextAlignment; +import javafx.scene.web.WebView; +import lingo.client.api.StompTopics; +import lingo.client.util.FxmlController; +import lingo.client.view.Board; +import lingo.client.view.OpponentBoard; +import lingo.client.view.PlayerBoard; +import lingo.common.Game; +import lingo.common.Report; + +@Component +public class MultiplayerPresenter implements FxmlController { + + private static final Logger log = LoggerFactory.getLogger(MultiplayerPresenter.class); + + private static final double MARGIN_BOTTOM = 75; + + @FXML + private Button backButton; + + @FXML + private Canvas canvas; + + @FXML + private StackPane contentPane; + + @FXML + private WebView webView; + + @Autowired + private ExecutorService executorService; + + @Autowired + private StompTemplate stompTemplate; + + private EventHandler backButtonHandler; + + private GraphicsContext gc; + + private String lastWord; + + private PlayerBoard playerBoard; + + private OpponentBoard opponentBoard; + + private final CountDownLatch subscriptionsLatch = new CountDownLatch(4); + + private void clearBoards(boolean clearScore) { + playerBoard.clearBoard(); + opponentBoard.clearBoard(); + if (clearScore) { + playerBoard.clearScore(); + opponentBoard.clearScore(); + } + } + + private void drawLastWord() { + if (lastWord != null) { + double x = canvas.getWidth() / 2; + double y = canvas.getHeight() - MARGIN_BOTTOM / 2; + gc.setFill(Color.BLACK); + gc.fillText("Previous word: " + lastWord.toUpperCase(), x, y); + } + } + + @Override + public void initialize() { + // Needed for key event handling + canvas.setFocusTraversable(true); + + gc = canvas.getGraphicsContext2D(); + gc.setFont(Font.font(24)); + gc.setTextAlign(TextAlignment.CENTER); + gc.setTextBaseline(VPos.CENTER); + playerBoard = new PlayerBoard(canvas, 50, 50); + opponentBoard = new OpponentBoard(canvas, 50 + Board.WIDTH + 50, 50); + + Platform.runLater(() -> { + String html = getClass().getResource("/cube-grid.html").toExternalForm(); + String css = getClass().getResource("/cube-grid.css").toExternalForm(); + webView.getEngine().load(html); + webView.getEngine().setUserStyleSheetLocation(css); + webView.setContextMenuEnabled(false); + repaint(); + }); + + backButton.setOnAction(backButtonHandler); + + executorService.execute(() -> { + while (subscriptionsLatch.getCount() != 0) { + try { + subscriptionsLatch.await(); + } catch (InterruptedException ok) { + ok.printStackTrace(); + } + } + stompTemplate.getSession().send("/app/lingo/join", null); + }); + } + + @FXML + private void keyPressed(KeyEvent e) { + final KeyCode keyCode = e.getCode(); + if (keyCode == KeyCode.BACK_SPACE) { + if (playerBoard.handleBackspace()) { + repaint(); + } + } else if (keyCode == KeyCode.ENTER) { + final String guess = playerBoard.handleEnter(); + if (guess != null) { + executorService.execute(() -> stompTemplate.getSession().send("/app/lingo/guess", guess)); + repaint(); + } + } else if (keyCode.isLetterKey()) { + if (playerBoard.handleLetter(keyCode.getName())) { + repaint(); + } + } + } + + private void newWord(String firstLetter) { + playerBoard.setProgress(0, firstLetter.charAt(0)); + } + + @PostConstruct + private void postConstruct() { + executorService.execute(() -> { + stompTemplate.subscribe("/user" + StompTopics.OPPONENT_JOINED, new OpponentJoinedHandler(), + subscription -> subscriptionsLatch.countDown()); + stompTemplate.subscribe("/user" + StompTopics.OPPONENT_LEFT, new OpponentLeftHandler(), + subscription -> subscriptionsLatch.countDown()); + stompTemplate.subscribe("/user" + StompTopics.OPPONENT_REPORTS, new OpponentReportHandler(), + subscription -> subscriptionsLatch.countDown()); + stompTemplate.subscribe("/user" + StompTopics.PLAYER_REPORTS, new PlayerReportHandler(), + subscription -> subscriptionsLatch.countDown()); + }); + } + + private void repaint() { + gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); + playerBoard.drawBoard(); + opponentBoard.drawBoard(); + drawLastWord(); + } + + public void setOnBackButtonPressed(EventHandler handler) { + backButtonHandler = handler; + } + + private void showWaitingAnimation(boolean show) { + if (show) { + contentPane.getChildren().add(webView); + backButton.toFront(); + } else { + contentPane.getChildren().remove(webView); + } + } + + private class OpponentJoinedHandler implements StompFrameHandler { + + @Override + public Type getPayloadType(StompHeaders headers) { + return String.class; + } + + @Override + public void handleFrame(StompHeaders headers, Object payload) { + final String firstLetter = payload.toString(); + Platform.runLater(() -> { + clearBoards(true); + newWord(firstLetter); + showWaitingAnimation(false); + repaint(); + }); + } + } + + private class OpponentLeftHandler implements StompFrameHandler { + + @Override + public Type getPayloadType(StompHeaders headers) { + return String.class; + } + + @Override + public void handleFrame(StompHeaders headers, Object payload) { + Platform.runLater(() -> { + clearBoards(true); + showWaitingAnimation(true); + lastWord = null; + repaint(); + }); + } + } + + private class OpponentReportHandler implements StompFrameHandler { + + @Override + public Type getPayloadType(StompHeaders headers) { + return Report.class; + } + + @Override + public void handleFrame(StompHeaders headers, Object payload) { + handleMessage((Report) payload); + } + + private void handleMessage(Report report) { + if (report.isCorrect()) { + onCorrectGuess(report); + } else { + onIncorrectGuess(report); + } + } + + private void onCorrectGuess(Report report) { + final String guess = report.getGuess(); + final String firstLetter = report.getFirstLetter(); + log.info("Opponent guessed correctly: " + guess); + Platform.runLater(() -> { + opponentBoard.addToScore(100); + lastWord = guess; + clearBoards(false); + newWord(firstLetter); + repaint(); + }); + } + + private void onIncorrectGuess(Report report) { + final int[] result = report.getResult(); + log.info("Opponent result: " + Arrays.toString(result)); + Platform.runLater(() -> { + opponentBoard.addResult(result); + repaint(); + }); + } + } + + private class PlayerReportHandler implements StompFrameHandler { + + @Override + public Type getPayloadType(StompHeaders headers) { + return Report.class; + } + + @Override + public void handleFrame(StompHeaders headers, Object payload) { + handleMessage((Report) payload); + } + + private void handleMessage(Report report) { + if (report.isCorrect()) { + onCorrectGuess(report); + } else { + onIncorrectGuess(report); + } + } + + private void onCorrectGuess(Report report) { + final String guess = report.getGuess(); + final String firstLetter = report.getFirstLetter(); + log.info("I guessed correctly!"); + Platform.runLater(() -> { + playerBoard.addToScore(100); + lastWord = guess; + clearBoards(false); + newWord(firstLetter); + repaint(); + }); + } + + private void onIncorrectGuess(Report report) { + final String guess = report.getGuess(); + final int[] result = report.getResult(); + log.info("My result: " + Arrays.toString(result)); + Platform.runLater(() -> { + if (Arrays.equals(result, Game.INVALID_GUESS)) { + playerBoard.addGuess("-----"); + } else { + for (int i = 0; i < Game.WORD_LENGTH; i++) { + if (result[i] == Game.CORRECT_CHARACTER) { + playerBoard.setProgress(i, guess.charAt(i)); + } + } + playerBoard.addGuess(guess); + } + playerBoard.addResult(result); + repaint(); + }); + } + } + +} diff --git a/client/src/main/java/lingo/client/multiplayer/StompTemplate.java b/client/src/main/java/lingo/client/multiplayer/StompTemplate.java new file mode 100644 index 0000000..b5c0faf --- /dev/null +++ b/client/src/main/java/lingo/client/multiplayer/StompTemplate.java @@ -0,0 +1,133 @@ +package lingo.client.multiplayer; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.function.Consumer; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.messaging.simp.stomp.StompFrameHandler; +import org.springframework.messaging.simp.stomp.StompHeaders; +import org.springframework.messaging.simp.stomp.StompSession; +import org.springframework.messaging.simp.stomp.StompSession.Subscription; +import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.messaging.WebSocketStompClient; + +@Component +public class StompTemplate { + + private static final Logger log = LoggerFactory.getLogger(StompTemplate.class); + + @Value("${server.host}") + private String host; + + @Value("${server.port}") + private int port; + + @Value("${server.stomp.endpoint}") + private String stompEndpoint; + + @Autowired + private ExecutorService executorService; + + @Autowired + private WebSocketStompClient stompClient; + + private StompSession stompSession; + + private final BlockingQueue subscriptionRequests = new LinkedBlockingQueue<>(); + + public StompSession getSession() { + /* + * TODO: If STOMP session is null or disconnected, create a new + * connection before returning this field. + */ + return stompSession; + } + + @PostConstruct + private void postConstruct() { + final String url = String.format("ws://%s:%d/%s", host, port, stompEndpoint); + executorService.execute(() -> stompClient.connect(url, new WebSocketSessionHandler())); + new Thread(new WebSocketSessionListener()).start(); + } + + @PreDestroy + private void preDestroy() { + if (stompSession != null) { + log.info("Disconnecting from STOMP endpoint..."); + stompSession.disconnect(); + } + stompClient.stop(); + } + + public void subscribe(String destination, StompFrameHandler handler) { + subscribe(destination, handler, null); + } + + public void subscribe(String destination, StompFrameHandler handler, Consumer callback) { + try { + subscriptionRequests.put(new SubscriptionRequest(destination, handler, callback)); + } catch (InterruptedException e) { + log.error("Failed to subscribe to destination: {}", destination, e); + } + } + + private class SubscriptionRequest { + public final String destination; + public final StompFrameHandler handler; + public final Consumer callback; + + public SubscriptionRequest(String destination, StompFrameHandler handler, Consumer callback) { + this.destination = destination; + this.handler = handler; + this.callback = callback; + } + + public void onSubscribed(Subscription subscription) { + if (callback != null) { + callback.accept(subscription); + } + } + } + + private class WebSocketSessionHandler extends StompSessionHandlerAdapter { + @Override + public void afterConnected(StompSession session, StompHeaders connectedHeaders) { + log.info("Connected to STOMP endpoint"); + stompSession = session; + } + } + + private class WebSocketSessionListener implements Runnable { + + @Override + public void run() { + while (true) { + if (stompSession == null) { + try { + Thread.sleep(1000L); + } catch (InterruptedException ok) { + ok.printStackTrace(); + } + continue; + } + try { + final SubscriptionRequest request = subscriptionRequests.take(); + final Subscription subscription = stompSession.subscribe(request.destination, request.handler); + request.onSubscribed(subscription); + } catch (InterruptedException e) { + log.error("Failed to subscribe", e); + } + } + } + } + +} diff --git a/client/src/main/java/lingo/client/singleplayer/SinglePlayerPresenter.java b/client/src/main/java/lingo/client/singleplayer/SinglePlayerPresenter.java new file mode 100644 index 0000000..0c514c6 --- /dev/null +++ b/client/src/main/java/lingo/client/singleplayer/SinglePlayerPresenter.java @@ -0,0 +1,158 @@ +package lingo.client.singleplayer; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.geometry.VPos; +import javafx.scene.Node; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.Button; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; +import javafx.scene.layout.StackPane; +import javafx.scene.text.Font; +import javafx.scene.text.TextAlignment; +import lingo.client.view.PlayerBoard; +import lingo.common.Game; +import lingo.common.Report; + +public class SinglePlayerPresenter { + + private static final Logger log = LoggerFactory.getLogger(SinglePlayerPresenter.class); + + private final Button backButton; + + private final Canvas canvas; + + private final StackPane contentPane; + + private final GraphicsContext gc; + + private final PlayerBoard gameBoard; + + private final Game game; + + public SinglePlayerPresenter(List words, Set guesses, EventHandler backButtonHandler) { + backButton = new Button("Back"); + backButton.getStyleClass().add("game-nav"); + StackPane.setAlignment(backButton, Pos.BOTTOM_LEFT); + StackPane.setMargin(backButton, new Insets(0, 0, 10, 10)); + backButton.setOnAction(backButtonHandler); + backButton.setPrefWidth(50); + + canvas = new Canvas(650, 420); + canvas.setFocusTraversable(true); + canvas.setOnKeyPressed(e -> keyPressed(e)); + gc = canvas.getGraphicsContext2D(); + gc.setFont(Font.font(24)); + gc.setTextAlign(TextAlignment.CENTER); + gc.setTextBaseline(VPos.CENTER); + + contentPane = new StackPane(); + contentPane.getChildren().add(canvas); + contentPane.getChildren().add(backButton); + + gameBoard = new PlayerBoard(canvas, 200, 60); + game = new Game(null, null, words, guesses); + } + + private void clearBoards(boolean clearScore) { + gameBoard.clearBoard(); + if (clearScore) { + gameBoard.clearScore(); + } + } + + public Node getNode() { + return contentPane; + } + + private void keyPressed(KeyEvent e) { + final KeyCode keyCode = e.getCode(); + if (keyCode == KeyCode.BACK_SPACE) { + if (gameBoard.handleBackspace()) { + repaint(); + } + } else if (keyCode == KeyCode.ENTER) { + final String guess = gameBoard.handleEnter(); + if (guess != null) { + final int[] result = game.evaluate(guess); + Report report = new Report(); + report.setGuess(guess); + report.setResult(result); + if (Game.isCorrect(result)) { + final String newWord = game.newWord(); + final String firstLetter = String.valueOf(newWord.charAt(0)); + report.setCorrect(true); + report.setFirstLetter(firstLetter); + report.setResult(result); + onCorrectGuess(report); + } else { + onIncorrectGuess(report); + } + } + } else if (keyCode.isLetterKey()) { + if (gameBoard.handleLetter(keyCode.getName())) { + repaint(); + } + } + } + + private void newWord(String firstLetter) { + gameBoard.setProgress(0, firstLetter.charAt(0)); + } + + private void onCorrectGuess(Report report) { + final String firstLetter = report.getFirstLetter(); + log.info("I guessed correctly!"); + Platform.runLater(() -> { + gameBoard.addToScore(100); + clearBoards(false); + newWord(firstLetter); + repaint(); + }); + } + + private void onIncorrectGuess(Report report) { + final String guess = report.getGuess(); + final int[] result = report.getResult(); + log.info("My result: " + Arrays.toString(result)); + Platform.runLater(() -> { + if (Arrays.equals(result, Game.INVALID_GUESS)) { + gameBoard.addGuess("-----"); + } else { + for (int i = 0; i < Game.WORD_LENGTH; i++) { + if (result[i] == Game.CORRECT_CHARACTER) { + gameBoard.setProgress(i, guess.charAt(i)); + } + } + gameBoard.addGuess(guess); + } + gameBoard.addResult(result); + repaint(); + }); + } + + private void repaint() { + gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); + gameBoard.drawBoard(); + } + + public void startGame() { + final String firstWord = game.newGame(); + final String firstLetter = String.valueOf(firstWord.charAt(0)); + newWord(firstLetter); + repaint(); + } + +} diff --git a/client/src/main/java/lingo/client/util/FxmlController.java b/client/src/main/java/lingo/client/util/FxmlController.java new file mode 100644 index 0000000..6aa1d42 --- /dev/null +++ b/client/src/main/java/lingo/client/util/FxmlController.java @@ -0,0 +1,25 @@ +package lingo.client.util; + +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; + +/** + * Identifies a controller that will be created by an {@link FXMLLoader}. The + * {@code FXMLLoader} will automatically inject {@code location} and + * {@code resources} properties into the controller, and then it will call the + * no-arg {@link #initialize()} method. This is the recommended approach: don't + * use the {@link Initializable} interface. + */ +public interface FxmlController { + + /** + * Called by the {@link FXMLLoader} to initialize a controller after its + * root element has been completely processed. This means all of the + * controller's {@link FXML} elements will be injected, and they can be used + * to wire up the GUI in ways that couldn't be accomplished using pure FXML, + * e.g. attaching property listeners. + */ + void initialize(); + +} diff --git a/client/src/main/java/lingo/client/view/Board.java b/client/src/main/java/lingo/client/view/Board.java new file mode 100644 index 0000000..fab7387 --- /dev/null +++ b/client/src/main/java/lingo/client/view/Board.java @@ -0,0 +1,35 @@ +package lingo.client.view; + +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; + +public abstract class Board { + + public static final double HEIGHT = 300; + public static final double WIDTH = 250; + public static final double SIDE = 50; + + protected final Canvas canvas; + + protected final GraphicsContext gc; + + /** The leftmost x-coordinate */ + protected final double xInit; + + /** The topmost y-coordinate */ + protected final double yInit; + + public Board(Canvas canvas, double xInit, double yInit) { + this.canvas = canvas; + this.gc = canvas.getGraphicsContext2D(); + this.xInit = xInit; + this.yInit = yInit; + } + + public void clearBoard() { + gc.clearRect(xInit, yInit, WIDTH, HEIGHT); + } + + public abstract void drawBoard(); + +} diff --git a/client/src/main/java/lingo/client/view/GameBoard.java b/client/src/main/java/lingo/client/view/GameBoard.java new file mode 100644 index 0000000..c66a214 --- /dev/null +++ b/client/src/main/java/lingo/client/view/GameBoard.java @@ -0,0 +1,80 @@ +package lingo.client.view; + +import java.util.ArrayList; +import java.util.List; + +import javafx.scene.canvas.Canvas; +import javafx.scene.paint.Color; + +public abstract class GameBoard extends Board { + + /** Tracks the player's previous guess evaluations */ + protected final List results = new ArrayList<>(); + + /** Tracks the player's score */ + protected int score; + + public GameBoard(Canvas canvas, double xInit, double yInit) { + super(canvas, xInit, yInit); + } + + @Override + public void clearBoard() { + super.clearBoard(); + results.clear(); + } + + protected void drawScore() { + double scoreX = xInit + WIDTH / 2; + double scoreY = yInit / 2; + gc.setFill(Color.BLACK); + gc.fillText(String.valueOf(score), scoreX, scoreY); + } + + protected void drawGrid() { + gc.beginPath(); + for (int x = 0; x <= WIDTH; x += SIDE) { + gc.moveTo(xInit + x, yInit); + gc.lineTo(xInit + x, yInit + HEIGHT); + } + for (int y = 0; y <= HEIGHT; y += SIDE) { + gc.moveTo(xInit, yInit + y); + gc.lineTo(xInit + WIDTH, yInit + y); + } + gc.setFill(Color.BLACK); + gc.stroke(); + } + + protected void drawResults() { + double y = yInit + SIDE * 1.5; + int numResults = Math.min(4, results.size()); + for (int i = 0; i < numResults; i++) { + double x = xInit + SIDE * 0.5; + int[] result = results.get(results.size() - numResults + i); + for (int j = 0; j < 5; j++) { + if (result[j] == 1) { + gc.setFill(Color.YELLOW); + gc.fillRect(x - SIDE * 0.5, y - SIDE * 0.5, SIDE, SIDE); + } else if (result[j] == 2) { + gc.setFill(Color.ORANGE); + gc.fillRect(x - SIDE * 0.5, y - SIDE * 0.5, SIDE, SIDE); + } + x += SIDE; + } + y += SIDE; + } + } + + public void addResult(int[] value) { + results.add(value); + } + + public void addToScore(int value) { + score += value; + } + + public void clearScore() { + score = 0; + } + +} diff --git a/client/src/main/java/lingo/client/view/OpponentBoard.java b/client/src/main/java/lingo/client/view/OpponentBoard.java new file mode 100644 index 0000000..75cb233 --- /dev/null +++ b/client/src/main/java/lingo/client/view/OpponentBoard.java @@ -0,0 +1,18 @@ +package lingo.client.view; + +import javafx.scene.canvas.Canvas; + +public class OpponentBoard extends GameBoard { + + public OpponentBoard(Canvas canvas, double xInit, double yInit) { + super(canvas, xInit, yInit); + } + + @Override + public void drawBoard() { + drawScore(); + drawResults(); + drawGrid(); + } + +} diff --git a/client/src/main/java/lingo/client/view/PlayerBoard.java b/client/src/main/java/lingo/client/view/PlayerBoard.java new file mode 100644 index 0000000..c48edb3 --- /dev/null +++ b/client/src/main/java/lingo/client/view/PlayerBoard.java @@ -0,0 +1,120 @@ +package lingo.client.view; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javafx.scene.canvas.Canvas; +import javafx.scene.paint.Color; + +public class PlayerBoard extends GameBoard { + + /** Tracks the player's current guess */ + private final StringBuilder guess = new StringBuilder(); + + /** Tracks the player's previous guesses */ + private final List guesses = new ArrayList<>(); + + /** Tracks the player's progress toward the current word */ + private final Map progress = new HashMap<>(); + + public PlayerBoard(Canvas canvas, double xInit, double yInit) { + super(canvas, xInit, yInit); + } + + @Override + public void clearBoard() { + super.clearBoard(); + guess.setLength(0); + guesses.clear(); + progress.clear(); + results.clear(); + } + + @Override + public void drawBoard() { + drawScore(); + drawInput(); + drawResults(); + double yStart = drawGuesses(); + drawHint(yStart); + drawGrid(); + } + + private void drawInput() { + gc.setFill(Color.GREEN); + double x = xInit + SIDE * 0.5; + double y = yInit + SIDE * 0.5; + for (int i = 0; i < guess.length(); i++) { + String character = String.valueOf(guess.charAt(i)); + gc.fillText(character, x, y); + x += SIDE; + } + } + + private double drawGuesses() { + double y = yInit + SIDE * 1.5; + double numGuesses = Math.min(4, guesses.size()); + for (int i = 0; i < numGuesses; i++) { + double x = xInit + SIDE * 0.5; + String guess = guesses.get((int) (guesses.size() - numGuesses + i)); + for (int j = 0; j < 5; j++) { + String character = String.valueOf(guess.charAt(j)); + gc.setFill(Color.GREEN); + gc.fillText(character, x, y); + x += SIDE; + } + y += SIDE; + } + return y; + } + + private void drawHint(double yStart) { + double x = xInit + SIDE * 0.5; + for (int i = 0; i < 5; i++) { + if (progress.containsKey(i)) { + gc.fillText(progress.get(i), x, yStart); + } + x += SIDE; + } + } + + public void addGuess(String value) { + guesses.add(value); + } + + public String getGuess() { + return guess.toString(); + } + + public boolean handleBackspace() { + if (guess.length() > 0) { + guess.setLength(guess.length() - 1); + return true; + } + return false; + } + + public String handleEnter() { + if (guess.length() == 5) { + final String value = guess.toString(); + guess.setLength(0); + return value; + } + return null; + } + + public boolean handleLetter(String letter) { + if (guess.length() < 5) { + guess.append(letter); + return true; + } + return false; + } + + public void setProgress(int i, char letter) { + progress.put(i, String.valueOf(letter)); + } + +} diff --git a/client/src/main/resources/cube-grid.css b/client/src/main/resources/cube-grid.css new file mode 100644 index 0000000..eb9389d --- /dev/null +++ b/client/src/main/resources/cube-grid.css @@ -0,0 +1,195 @@ +h1 { + font: 24pt sans-serif; + font-variant: small-caps; + text-align: center +} + +/* Below based on http://tobiasahlin.com/spinkit */ + +.sk-cube-grid { + width: 200px; + height: 200px; + margin: 35px auto; +} + +.sk-cube-grid .sk-cube { + width: 20%; + height: 20%; + background-color: orange; + float: left; + -webkit-animation: sk-cubeGridScaleDelay 1.5s infinite ease-in-out; + animation: sk-cubeGridScaleDelay 1.5s infinite ease-in-out; +} + +/* +0.0s - 26 +0.1s - 27, 21 +0.2s - 28, 22, 16 +0.3s - 29, 23, 17, 11 +0.4s - 30, 24, 18, 12, 06 +0.5s - 25, 19, 13, 07, 01 +0.6s - 20, 14, 08, 02 +0.7s - 15, 09, 03 +0.8s - 10, 04 +0.9s - 05 +*/ + +/* 0 second delay */ +.sk-cube-grid .sk-cube26 { + -webkit-animation-delay: 0s; + animation-delay: 0s; +} + +/* 0.1 second delay */ +.sk-cube-grid .sk-cube27 { + -webkit-animation-delay: 0.1s; + animation-delay: 0.1s; +} +.sk-cube-grid .sk-cube21 { + -webkit-animation-delay: 0.1s; + animation-delay: 0.1s; +} + +/* 0.2 second delay */ +.sk-cube-grid .sk-cube28 { + -webkit-animation-delay: 0.2s; + animation-delay: 0.2s; +} +.sk-cube-grid .sk-cube22 { + -webkit-animation-delay: 0.2s; + animation-delay: 0.2s; +} +.sk-cube-grid .sk-cube16 { + -webkit-animation-delay: 0.2s; + animation-delay: 0.2s; +} + +/* 0.3 second delay */ +.sk-cube-grid .sk-cube29 { + -webkit-animation-delay: 0.3s; + animation-delay: 0.3s; +} +.sk-cube-grid .sk-cube23 { + -webkit-animation-delay: 0.3s; + animation-delay: 0.3s; +} +.sk-cube-grid .sk-cube17 { + -webkit-animation-delay: 0.3s; + animation-delay: 0.3s; +} +.sk-cube-grid .sk-cube11 { + -webkit-animation-delay: 0.3s; + animation-delay: 0.3s; +} + +/* 0.4 second delay */ +.sk-cube-grid .sk-cube30 { + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} +.sk-cube-grid .sk-cube24 { + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} +.sk-cube-grid .sk-cube18 { + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} +.sk-cube-grid .sk-cube12 { + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} +.sk-cube-grid .sk-cube6 { + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} + +/* 0.5 second delay */ +.sk-cube-grid .sk-cube25 { + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; +} +.sk-cube-grid .sk-cube19 { + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; +} +.sk-cube-grid .sk-cube13 { + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; +} +.sk-cube-grid .sk-cube7 { + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; +} +.sk-cube-grid .sk-cube1 { + -webkit-animation-delay: 0.5s; + animation-delay: 0.5s; +} + +/* 0.6 second delay */ +.sk-cube-grid .sk-cube20 { + -webkit-animation-delay: 0.6s; + animation-delay: 0.6s; +} +.sk-cube-grid .sk-cube14 { + -webkit-animation-delay: 0.6s; + animation-delay: 0.6s; +} +.sk-cube-grid .sk-cube8 { + -webkit-animation-delay: 0.6s; + animation-delay: 0.6s; +} +.sk-cube-grid .sk-cube2 { + -webkit-animation-delay: 0.6s; + animation-delay: 0.6s; +} + +/* 0.7 second delay */ +.sk-cube-grid .sk-cube15 { + -webkit-animation-delay: 0.7s; + animation-delay: 0.7s; +} +.sk-cube-grid .sk-cube9 { + -webkit-animation-delay: 0.7s; + animation-delay: 0.7s; +} +.sk-cube-grid .sk-cube3 { + -webkit-animation-delay: 0.7s; + animation-delay: 0.7s; +} + +/* 0.8 second delay */ +.sk-cube-grid .sk-cube10 { + -webkit-animation-delay: 0.8s; + animation-delay: 0.8s; +} +.sk-cube-grid .sk-cube4 { + -webkit-animation-delay: 0.8s; + animation-delay: 0.8s; +} + +/* 0.9 second delay */ +.sk-cube-grid .sk-cube5 { + -webkit-animation-delay: 0.9s; + animation-delay: 0.9s; +} + +@-webkit-keyframes sk-cubeGridScaleDelay { + 0%, 70%, 100% { + -webkit-transform: scale3D(1, 1, 1); + transform: scale3D(1, 1, 1); + } 35% { + -webkit-transform: scale3D(0, 0, 1); + transform: scale3D(0, 0, 1); + } +} + +@keyframes sk-cubeGridScaleDelay { + 0%, 70%, 100% { + -webkit-transform: scale3D(1, 1, 1); + transform: scale3D(1, 1, 1); + } 35% { + -webkit-transform: scale3D(0, 0, 1); + transform: scale3D(0, 0, 1); + } +} diff --git a/client/src/main/resources/cube-grid.html b/client/src/main/resources/cube-grid.html new file mode 100644 index 0000000..232538e --- /dev/null +++ b/client/src/main/resources/cube-grid.html @@ -0,0 +1,39 @@ + + + +

Waiting for Opponent

+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/client/src/main/resources/fxml/Lingo.fxml b/client/src/main/resources/fxml/Lingo.fxml new file mode 100644 index 0000000..dcd3469 --- /dev/null +++ b/client/src/main/resources/fxml/Lingo.fxml @@ -0,0 +1,38 @@ + + + + + + + + + + +
+ +
+ + +
+ + + +
+
+ +
diff --git a/client/src/main/resources/fxml/LingoMultiplayer.fxml b/client/src/main/resources/fxml/LingoMultiplayer.fxml new file mode 100644 index 0000000..e81f3ba --- /dev/null +++ b/client/src/main/resources/fxml/LingoMultiplayer.fxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/style.css b/client/src/main/resources/style.css new file mode 100644 index 0000000..857a159 --- /dev/null +++ b/client/src/main/resources/style.css @@ -0,0 +1,12 @@ +.text { + -fx-font-family: Helvetica; + -fx-font-smoothing-type: gray; +} + +.game-mode { + -fx-font-size: 24px; +} + +.game-nav { + -fx-font-size: 12px; +} diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 0000000..2097ea7 --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,31 @@ + + 4.0.0 + + + com.charego + lingo-websocket + 1.0 + + + lingo-websocket-common + Lingo WebSocket :: Common + + + + org.apache.commons + commons-lang3 + 3.3.2 + + + com.fasterxml.jackson.core + jackson-databind + + + junit + junit + test + + + + diff --git a/common/src/main/java/lingo/common/Game.java b/common/src/main/java/lingo/common/Game.java new file mode 100644 index 0000000..8ba4070 --- /dev/null +++ b/common/src/main/java/lingo/common/Game.java @@ -0,0 +1,91 @@ +package lingo.common; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +public class Game { + + public static final int INCORRECT_CHARACTER = 0; + public static final int INCORRECT_POSITION = 1; + public static final int CORRECT_CHARACTER = 2; + public static final int WORD_LENGTH = 5; + public static final int[] INVALID_GUESS = new int[] { 9, 9, 9, 9, 9 }; + + public final String playerOne; + + public final String playerTwo; + + private final Set acceptableGuesses; + + private final List possibleWords; + + private String word; + + private int wordIndex = 0; + + public Game(String playerOne, String playerTwo, List possibleWords, Set acceptableGuesses) { + this.playerOne = playerOne; + this.playerTwo = playerTwo; + this.possibleWords = possibleWords; + this.acceptableGuesses = acceptableGuesses; + } + + private static int indexOf(char[] array, char searchTerm) { + for (int i = 0; i < WORD_LENGTH; i++) { + if (array[i] == searchTerm) { + return i; + } + } + return -1; + } + + public static boolean isCorrect(int[] result) { + for (int i = 0; i < WORD_LENGTH; i++) { + if (result[i] != CORRECT_CHARACTER) { + return false; + } + } + return true; + } + + public int[] evaluate(String guess) { + if (!acceptableGuesses.contains(guess)) { + return INVALID_GUESS; + } + + // the guess is acceptable + int[] result = new int[WORD_LENGTH]; + char[] remaining = new char[WORD_LENGTH]; + for (int i = 0; i < WORD_LENGTH; i++) { + if (guess.charAt(i) == word.charAt(i)) { + result[i] = CORRECT_CHARACTER; + } else { + result[i] = INCORRECT_CHARACTER; + remaining[i] = word.charAt(i); + } + } + for (int i = 0; i < WORD_LENGTH; i++) { + if (result[i] == INCORRECT_CHARACTER) { + int index = indexOf(remaining, guess.charAt(i)); + if (index != -1) { + result[i] = INCORRECT_POSITION; + remaining[index] = 0; + } + } + } + return result; + } + + public String newGame() { + Collections.shuffle(possibleWords); + wordIndex = 0; + return newWord(); + } + + public String newWord() { + word = possibleWords.get(wordIndex++); + return word; + } + +} diff --git a/common/src/main/java/lingo/common/Report.java b/common/src/main/java/lingo/common/Report.java new file mode 100644 index 0000000..2334d2c --- /dev/null +++ b/common/src/main/java/lingo/common/Report.java @@ -0,0 +1,47 @@ +package lingo.common; + +public class Report { + + private boolean correct; + + private String firstLetter; + + private String guess; + + private int[] result; + + public Report() {} + + public String getFirstLetter() { + return firstLetter; + } + + public void setFirstLetter(String value) { + this.firstLetter = value; + } + + public String getGuess() { + return guess; + } + + public void setGuess(String value) { + this.guess = value; + } + + public int[] getResult() { + return result; + } + + public void setResult(int[] value) { + this.result = value; + } + + public boolean isCorrect() { + return correct; + } + + public void setCorrect(boolean value) { + this.correct = value; + } + +} diff --git a/common/src/main/java/lingo/common/WordReader.java b/common/src/main/java/lingo/common/WordReader.java new file mode 100644 index 0000000..aa574fa --- /dev/null +++ b/common/src/main/java/lingo/common/WordReader.java @@ -0,0 +1,38 @@ +package lingo.common; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class WordReader { + + private static void readFileToCollection(String filename, Collection c) throws IOException { + try (final InputStream stream = WordReader.class.getResourceAsStream(filename); + final InputStreamReader streamReader = new InputStreamReader(stream); + final BufferedReader bufferedReader = new BufferedReader(streamReader)) { + String line = null; + while ((line = bufferedReader.readLine()) != null) { + c.add(line); + } + } + } + + public static List readFileToList(String filename) throws IOException { + final List list = new ArrayList<>(); + readFileToCollection(filename, list); + return list; + } + + public static Set readFileToSet(String filename) throws IOException { + final Set list = new HashSet<>(); + readFileToCollection(filename, list); + return list; + } + +} diff --git a/common/src/main/resources/guesses.txt b/common/src/main/resources/guesses.txt new file mode 100644 index 0000000..ff2edfb --- /dev/null +++ b/common/src/main/resources/guesses.txt @@ -0,0 +1,9168 @@ +AAHED +AALII +AARGH +ABACA +ABACI +ABACK +ABAFT +ABAKA +ABAMP +ABASE +ABASH +ABATE +ABAYA +ABBAS +ABBES +ABBEY +ABBOT +ABEAM +ABELE +ABEND +ABETS +ABHOR +ABIDE +ABLED +ABLER +ABLES +ABMHO +ABODE +ABOHM +ABOIL +ABOMA +ABOON +ABORT +ABOUT +ABOVE +ABRIS +ABSIT +ABUSE +ABUTS +ABUZZ +ABYES +ABYSM +ABYSS +ACARI +ACERB +ACETA +ACHED +ACHES +ACHOO +ACIDS +ACIDY +ACING +ACINI +ACKED +ACKEE +ACMES +ACMIC +ACNED +ACNES +ACOCK +ACOLD +ACORN +ACRED +ACRES +ACRID +ACTED +ACTIN +ACTOR +ACUTE +ACYLS +ADAGE +ADAPT +ADDAX +ADDED +ADDER +ADDLE +ADEEM +ADEPT +ADIEU +ADIOS +ADITS +ADLIB +ADMAN +ADMEN +ADMIT +ADMIX +ADOBE +ADOBO +ADOPT +ADORE +ADORN +ADOWN +ADOZE +ADULT +ADUNC +ADUST +ADYTA +ADZED +ADZES +AECIA +AEDES +AEGIS +AEONS +AERIE +AFARS +AFFIX +AFIRE +AFOOT +AFORE +AFOUL +AFRIT +AFTER +AGAIN +AGAMA +AGAPE +AGARS +AGATE +AGAVE +AGAZE +AGENE +AGENT +AGERS +AGGER +AGGIE +AGGRO +AGHAS +AGILE +AGING +AGIOS +AGISM +AGIST +AGITA +AGLEE +AGLET +AGLEY +AGLOW +AGMAS +AGONE +AGONS +AGONY +AGORA +AGREE +AGRIA +AGUES +AHEAD +AHHHH +AHING +AHOLD +AHOYS +AHULL +AIDED +AIDER +AIDES +AILED +AIMED +AIMER +AIOLI +AIRED +AIRER +AIRNS +AIRTH +AIRTS +AISLE +AITCH +AIVER +AJIVA +AJUGA +AKEES +AKELA +AKENE +ALACK +ALAMO +ALAND +ALANE +ALANG +ALANS +ALANT +ALARM +ALARY +ALATE +ALBAS +ALBUM +ALCID +ALDER +ALDOL +ALECK +ALECS +ALEFS +ALEPH +ALERT +ALFAS +ALGAE +ALGAL +ALGAS +ALGID +ALGIN +ALGOR +ALGUM +ALIAS +ALIBI +ALIEN +ALIFS +ALIGN +ALIKE +ALINE +ALIST +ALIVE +ALIYA +ALKIE +ALKYD +ALKYL +ALLAY +ALLEE +ALLEY +ALLOD +ALLOT +ALLOW +ALLOY +ALLYL +ALMAH +ALMAS +ALMEH +ALMES +ALMUD +ALMUG +ALOES +ALOFT +ALOHA +ALOIN +ALONE +ALONG +ALOOF +ALOUD +ALPHA +ALTAR +ALTER +ALTHO +ALTOS +ALULA +ALUMS +ALWAY +AMAHS +AMAIN +AMASS +AMAZE +AMBER +AMBIT +AMBLE +AMBOS +AMBRY +AMEBA +AMEER +AMEND +AMENS +AMENT +AMIAS +AMICE +AMICI +AMIDE +AMIDO +AMIDS +AMIES +AMIGA +AMIGO +AMINE +AMINO +AMINS +AMIRS +AMISS +AMITY +AMMOS +AMNIA +AMNIC +AMNIO +AMOKS +AMOLE +AMONG +AMORT +AMOUR +AMPED +AMPLE +AMPLY +AMPUL +AMUCK +AMUSE +AMYLS +ANCHO +ANCON +ANDED +ANDRO +ANEAR +ANELE +ANENT +ANGAS +ANGEL +ANGER +ANGLE +ANGLO +ANGRY +ANGST +ANILE +ANILS +ANIMA +ANIME +ANIMI +ANION +ANISE +ANKHS +ANKLE +ANKUS +ANLAS +ANNAL +ANNAS +ANNEX +ANNOY +ANNUL +ANNUM +ANOAS +ANODE +ANOLE +ANOMY +ANSAE +ANTAE +ANTAS +ANTED +ANTES +ANTIC +ANTIS +ANTRA +ANTRE +ANTSY +ANVIL +ANYON +AORTA +APACE +APART +APEAK +APEEK +APERS +APERY +APHID +APHIS +APIAN +APING +APISH +APNEA +APODS +APORT +APPAL +APPEL +APPLE +APPLY +APRES +APRON +APSES +APSIS +APSOS +APTER +APTLY +AQUAE +AQUAS +ARAKS +ARAME +ARBOR +ARCED +ARCUS +ARDEB +ARDOR +AREAE +AREAL +AREAS +ARECA +AREIC +ARENA +ARENE +AREPA +ARETE +ARGAL +ARGIL +ARGLE +ARGOL +ARGON +ARGOT +ARGUE +ARGUS +ARHAT +ARIAS +ARIEL +ARILS +ARISE +ARITY +ARLES +ARMED +ARMER +ARMET +ARMOR +AROID +AROMA +AROSE +ARPEN +ARRAS +ARRAY +ARRIS +ARROW +ARSES +ARSIS +ARSON +ARTAL +ARTEL +ARTSY +ARUMS +ARVAL +ARVOS +ARYLS +ASANA +ASCOT +ASCUS +ASDIC +ASHED +ASHEN +ASHES +ASIDE +ASKED +ASKER +ASKEW +ASKOI +ASKOS +ASPEN +ASPER +ASPIC +ASPIS +ASSAI +ASSAY +ASSED +ASSES +ASSET +ASTER +ASTIR +ASTRO +ASYLA +ATAPS +ATAXY +ATILT +ATLAS +ATMAN +ATMAS +ATOLL +ATOMS +ATOMY +ATONE +ATONY +ATOPY +ATRIA +ATRIP +ATTAR +ATTIC +AUDAD +AUDIO +AUDIT +AUGER +AUGHT +AUGUR +AULIC +AUNTS +AUNTY +AURAE +AURAL +AURAR +AURAS +AUREI +AURES +AURIC +AURIS +AURUM +AUTOS +AUXIN +AVAIL +AVANT +AVAST +AVENS +AVERS +AVERT +AVGAS +AVIAN +AVION +AVISO +AVOID +AVOWS +AWAIT +AWAKE +AWARD +AWARE +AWASH +AWAYS +AWFUL +AWING +AWNED +AWOKE +AWOLS +AXELS +AXIAL +AXILE +AXILS +AXING +AXIOM +AXION +AXITE +AXLED +AXLES +AXMAN +AXMEN +AXONE +AXONS +AYAHS +AYINS +AZANS +AZIDE +AZIDO +AZINE +AZLON +AZOIC +AZOLE +AZONS +AZOTE +AZOTH +AZUKI +AZURE +BAAED +BAALS +BABAS +BABEL +BABES +BABKA +BABOO +BABUL +BABUS +BACCA +BACKS +BACON +BADDY +BADGE +BADLY +BAFFS +BAFFY +BAGEL +BAGGY +BAHTS +BAILS +BAIRN +BAITH +BAITS +BAIZA +BAIZE +BAKED +BAKER +BAKES +BALAS +BALDS +BALDY +BALED +BALER +BALES +BALKS +BALKY +BALLS +BALLY +BALMS +BALMY +BALSA +BANAL +BANCO +BANDA +BANDS +BANDY +BANED +BANES +BANGS +BANJO +BANKS +BANNS +BANTY +BARBE +BARBS +BARCA +BARDE +BARDS +BARED +BARER +BARES +BARFS +BARFY +BARGE +BARIC +BARKS +BARKY +BARMS +BARMY +BARNS +BARNY +BARON +BARRE +BARYE +BASAL +BASED +BASER +BASES +BASIC +BASIL +BASIN +BASIS +BASKS +BASSI +BASSO +BASSY +BASTE +BASTS +BATCH +BATED +BATES +BATHE +BATHS +BATIK +BATON +BATTS +BATTU +BATTY +BAUDS +BAULK +BAWDS +BAWDY +BAWLS +BAWTY +BAYED +BAYOU +BAZAR +BAZOO +BEACH +BEADS +BEADY +BEAKS +BEAKY +BEAMS +BEAMY +BEANO +BEANS +BEARD +BEARS +BEAST +BEATS +BEAUS +BEAUT +BEAUX +BEBOP +BEBUG +BECAP +BECKS +BEDEL +BEDEW +BEDIM +BEECH +BEEDI +BEEFS +BEEFY +BEEPS +BEERS +BEERY +BEETS +BEFIT +BEFOG +BEGAN +BEGAT +BEGET +BEGIN +BEGOT +BEGUM +BEGUN +BEIGE +BEIGY +BEING +BELAY +BELCH +BELGA +BELIE +BELLE +BELLI +BELLS +BELLY +BELON +BELOW +BELTS +BEMAS +BEMIX +BENCH +BENDS +BENDY +BENES +BENNE +BENNI +BENNY +BENTO +BENTS +BERET +BERGS +BERKS +BERME +BERMS +BERRY +BERTH +BERYL +BESES +BESET +BESOM +BESOT +BESTS +BETAS +BETEL +BETHS +BETON +BETTA +BEVEL +BEVOR +BEWIG +BEZEL +BEZIL +BHANG +BHOOT +BHOYS +BHUTS +BIALI +BIALY +BIBBS +BIBLE +BICEP +BICES +BIDDY +BIDED +BIDER +BIDES +BIDET +BIDIS +BIELD +BIERS +BIFFS +BIFFY +BIFID +BIGGY +BIGHT +BIGLY +BIGOS +BIGOT +BIJOU +BIKED +BIKER +BIKES +BIKIE +BILBO +BILBY +BILES +BILGE +BILGY +BILKS +BILLS +BILLY +BIMAH +BIMAS +BIMBO +BINAL +BINDI +BINDS +BINER +BINES +BINGE +BINGO +BINIT +BINTS +BIOGS +BIOME +BIONT +BIOTA +BIPED +BIPOD +BIRCH +BIRDS +BIRKS +BIRLE +BIRLS +BIROS +BIRRS +BIRSE +BIRTH +BISES +BISKS +BISON +BITCH +BITER +BITES +BITSY +BITTS +BITTY +BIZES +BLABS +BLACK +BLADE +BLAFF +BLAHS +BLAIN +BLAME +BLAMS +BLAND +BLANK +BLARE +BLASE +BLASH +BLAST +BLATE +BLATS +BLAWN +BLAWS +BLAZE +BLEAK +BLEAR +BLEAT +BLEBS +BLEED +BLEEP +BLEND +BLENT +BLESS +BLEST +BLETS +BLIMP +BLIMY +BLIND +BLINI +BLINK +BLIPS +BLISS +BLITE +BLITZ +BLOAT +BLOBS +BLOCK +BLOCS +BLOGS +BLOKE +BLOND +BLOOD +BLOOM +BLOOP +BLOTS +BLOWN +BLOWS +BLOWY +BLUBS +BLUED +BLUER +BLUES +BLUET +BLUEY +BLUFF +BLUME +BLUNT +BLURB +BLURS +BLURT +BLUSH +BLYPE +BOARD +BOARS +BOART +BOAST +BOATS +BOBBY +BOCCE +BOCCI +BOCHE +BOCKS +BODED +BODES +BODGE +BOFFO +BOFFS +BOGAN +BOGEY +BOGGY +BOGIE +BOGLE +BOGUS +BOHEA +BOHOS +BOILS +BOING +BOINK +BOITE +BOLAR +BOLAS +BOLDS +BOLES +BOLLS +BOLOS +BOLTS +BOLUS +BOMBE +BOMBS +BONDS +BONED +BONER +BONES +BONEY +BONGO +BONGS +BONKS +BONNE +BONNY +BONUS +BONZE +BOOBS +BOOBY +BOODY +BOOED +BOOGY +BOOKS +BOOKY +BOOMS +BOOMY +BOONS +BOORS +BOOST +BOOTH +BOOTS +BOOTY +BOOZE +BOOZY +BORAL +BORAS +BORAX +BORED +BORER +BORES +BORIC +BORKS +BORNE +BORON +BORTS +BORTY +BORTZ +BOSKS +BOSKY +BOSOM +BOSON +BOSSA +BOSSY +BOSUN +BOTAS +BOTCH +BOTEL +BOTHY +BOTTS +BOUGH +BOULE +BOUND +BOURG +BOURN +BOUSE +BOUSY +BOUTS +BOVID +BOWED +BOWEL +BOWER +BOWIE +BOWLS +BOWSE +BOXED +BOXER +BOXES +BOYAR +BOYLA +BOYOS +BOZOS +BRACE +BRACH +BRACK +BRACT +BRADS +BRAES +BRAGS +BRAID +BRAIL +BRAIN +BRAKE +BRAKY +BRAND +BRANK +BRANS +BRANT +BRASH +BRASS +BRATS +BRAVA +BRAVE +BRAVI +BRAVO +BRAWL +BRAWN +BRAWS +BRAXY +BRAYS +BRAZA +BRAZE +BREAD +BREAK +BREAM +BREDE +BREED +BREES +BRENS +BRENT +BREVE +BREWS +BRIAR +BRIBE +BRICK +BRIDE +BRIEF +BRIER +BRIES +BRIGS +BRILL +BRIMS +BRINE +BRING +BRINK +BRINS +BRINY +BRIOS +BRISK +BRISS +BRITH +BRITS +BRITT +BROAD +BROCK +BROIL +BROKE +BROME +BROMO +BRONC +BRONX +BROOD +BROOK +BROOM +BROOS +BROSE +BROSY +BROTH +BROWN +BROWS +BRUGH +BRUIN +BRUIT +BRUME +BRUNG +BRUNT +BRUSH +BRUSK +BRUTE +BRUTS +BUBAL +BUBBA +BUBBY +BUBUS +BUCKO +BUCKS +BUDDY +BUDGE +BUENA +BUENO +BUFFA +BUFFI +BUFFO +BUFFS +BUFFY +BUGGY +BUGLE +BUHLS +BUHRS +BUILD +BUILT +BULBS +BULGE +BULGY +BULKS +BULKY +BULLA +BULLS +BULLY +BUMFS +BUMPH +BUMPS +BUMPY +BUNAS +BUNCH +BUNCO +BUNDS +BUNDT +BUNGS +BUNKO +BUNKS +BUNNS +BUNNY +BUNTS +BUNYA +BUOYS +BUPPY +BURAN +BURAS +BURBS +BURDS +BURET +BURGH +BURGS +BURIN +BURKA +BURKE +BURLS +BURLY +BURNS +BURNT +BURPS +BURQA +BURRO +BURRS +BURRY +BURSA +BURSE +BURST +BUSBY +BUSED +BUSES +BUSHY +BUSKS +BUSTS +BUSTY +BUTCH +BUTEO +BUTES +BUTLE +BUTTE +BUTTS +BUTTY +BUTUT +BUTYL +BUXOM +BUYER +BUZZY +BWANA +BYLAW +BYRES +BYRLS +BYSSI +BYTES +BYWAY +CABAL +CABBY +CABER +CABIN +CABLE +CABOB +CACAO +CACAS +CACHE +CACTI +CADDY +CADES +CADET +CADGE +CADGY +CADIS +CADRE +CAECA +CAFES +CAFFS +CAGED +CAGER +CAGES +CAGEY +CAHOW +CAIDS +CAINS +CAIRD +CAIRN +CAJON +CAKED +CAKES +CAKEY +CALFS +CALIF +CALIX +CALKS +CALLA +CALLS +CALMS +CALOS +CALVE +CALYX +CAMAS +CAMEL +CAMEO +CAMES +CAMOS +CAMPI +CAMPO +CAMPS +CAMPY +CANAL +CANDY +CANED +CANER +CANES +CANID +CANNA +CANNY +CANOE +CANON +CANSO +CANST +CANTO +CANTS +CANTY +CAPED +CAPER +CAPES +CAPHS +CAPIZ +CAPON +CAPOS +CAPUT +CARAT +CARBO +CARBS +CARDS +CARED +CARER +CARES +CARET +CAREX +CARGO +CARKS +CARLE +CARLS +CARNE +CARNS +CARNY +CAROB +CAROL +CAROM +CARON +CARPI +CARPS +CARPY +CARRS +CARRY +CARSE +CARTE +CARTS +CARVE +CASAS +CASED +CASES +CASKS +CASKY +CASTE +CASTS +CASUS +CATCH +CATER +CATES +CATTY +CAULD +CAULK +CAULS +CAUSE +CAVED +CAVER +CAVES +CAVIE +CAVIL +CAWED +CEASE +CEBID +CECAL +CECUM +CEDAR +CEDED +CEDER +CEDES +CEDIS +CEIBA +CEILI +CEILS +CELEB +CELLA +CELLI +CELLO +CELLS +CELOM +CELTS +CENSE +CENTO +CENTS +CENTU +CEORL +CEPES +CERCI +CERED +CERES +CERIA +CERIC +CEROS +CESTA +CESTI +CETES +CHADS +CHAFE +CHAFF +CHAIN +CHAIR +CHAIS +CHALK +CHAMP +CHAMS +CHANG +CHANT +CHAOS +CHAPE +CHAPS +CHAPT +CHARD +CHARE +CHARK +CHARM +CHARR +CHARS +CHART +CHARY +CHASE +CHASM +CHATS +CHAWS +CHAYS +CHEAP +CHEAT +CHECK +CHEEK +CHEEP +CHEER +CHEFS +CHELA +CHEMO +CHERT +CHESS +CHEST +CHETH +CHEVY +CHEWS +CHEWY +CHIAO +CHIAS +CHICA +CHICK +CHICO +CHICS +CHIDE +CHIEF +CHIEL +CHIFF +CHILD +CHILE +CHILI +CHILL +CHIMB +CHIME +CHIMP +CHINA +CHINE +CHINK +CHINO +CHINS +CHIPS +CHIRK +CHIRM +CHIRO +CHIRP +CHIRR +CHIRU +CHITS +CHIVE +CHIVY +CHOCK +CHOIR +CHOKE +CHOKY +CHOLA +CHOLO +CHOMP +CHOOK +CHOOS +CHOPS +CHORD +CHORE +CHOSE +CHOTT +CHOWS +CHUBS +CHUCK +CHUFA +CHUFF +CHUGS +CHUMP +CHUMS +CHUNK +CHURL +CHURN +CHURR +CHUTE +CHYLE +CHYME +CIBOL +CIDER +CIGAR +CILIA +CILLS +CIMEX +CINCH +CINES +CIONS +CIRCA +CIRES +CIRRI +CISCO +CISSY +CISTS +CITED +CITER +CITES +CIVET +CIVIC +CIVIE +CIVIL +CIVVY +CLACH +CLACK +CLADE +CLADS +CLAGS +CLAIM +CLAMP +CLAMS +CLANG +CLANK +CLANS +CLAPS +CLAPT +CLARO +CLARY +CLASH +CLASP +CLASS +CLAST +CLAVE +CLAVI +CLAWS +CLAYS +CLEAN +CLEAR +CLEAT +CLEEK +CLEFS +CLEFT +CLEPE +CLEPT +CLERK +CLEWS +CLICK +CLIFF +CLIFT +CLIMB +CLIME +CLINE +CLING +CLINK +CLIPS +CLIPT +CLOAK +CLOCK +CLODS +CLOGS +CLOMB +CLOMP +CLONE +CLONK +CLONS +CLOOT +CLOPS +CLOSE +CLOTH +CLOTS +CLOUD +CLOUR +CLOUT +CLOVE +CLOWN +CLOYS +CLOZE +CLUBS +CLUCK +CLUED +CLUES +CLUMP +CLUNG +CLUNK +CNIDA +COACH +COACT +COALA +COALS +COALY +COAPT +COAST +COATI +COATS +COBBS +COBBY +COBIA +COBLE +COBRA +COCAS +COCCI +COCKS +COCKY +COCOA +COCOS +CODAS +CODEC +CODED +CODEN +CODER +CODES +CODEX +CODON +COEDS +COFFS +COGON +COHOG +COHOS +COIFS +COIGN +COILS +COINS +COIRS +COKED +COKES +COLAS +COLBY +COLDS +COLED +COLES +COLIC +COLIN +COLLY +COLOG +COLON +COLOR +COLTS +COLZA +COMAE +COMAL +COMAS +COMBE +COMBO +COMBS +COMER +COMES +COMET +COMFY +COMIC +COMIX +COMMA +COMMY +COMPO +COMPS +COMPT +COMTE +CONCH +CONDO +CONED +CONES +CONEY +CONGA +CONGE +CONGO +CONIC +CONIN +CONKS +CONKY +CONNS +CONTE +CONTO +CONUS +COOCH +COOED +COOEE +COOER +COOEY +COOFS +COOKS +COOKY +COOLS +COOLY +COOMB +COONS +COOPS +COOPT +COOTS +COPAL +COPAY +COPED +COPEN +COPER +COPES +COPRA +COPSE +COQUI +CORAL +CORBY +CORDS +CORDY +CORED +CORER +CORES +CORGI +CORIA +CORKS +CORKY +CORMS +CORNS +CORNU +CORNY +CORPS +CORSE +COSEC +COSES +COSET +COSEY +COSIE +COSTA +COSTS +COTAN +COTED +COTES +COTTA +COUCH +COUDE +COUGH +COULD +COUNT +COUPE +COUPS +COURT +COUTH +COVED +COVEN +COVER +COVES +COVET +COVEY +COVIN +COWED +COWER +COWLS +COWRY +COXAE +COXAL +COXED +COXES +COYED +COYER +COYLY +COYPU +COZEN +COZES +COZEY +COZIE +CRAAL +CRABS +CRACK +CRAFT +CRAGS +CRAKE +CRAMP +CRAMS +CRANE +CRANK +CRAPE +CRAPS +CRASH +CRASS +CRATE +CRAVE +CRAWL +CRAWS +CRAZE +CRAZY +CREAK +CREAM +CREDO +CREDS +CREED +CREEK +CREEL +CREEP +CREME +CREPE +CREPT +CREPY +CRESS +CREST +CREWS +CRIBS +CRICK +CRIED +CRIER +CRIES +CRIME +CRIMP +CRINK +CRIPE +CRISP +CRITS +CROAK +CROCI +CROCK +CROCS +CROFT +CRONE +CRONY +CROOK +CROON +CROPS +CRORE +CROSS +CROUP +CROWD +CROWN +CROWS +CROZE +CRUCK +CRUDE +CRUDS +CRUEL +CRUET +CRUFT +CRUMB +CRUMP +CRUOR +CRURA +CRUSE +CRUSH +CRUST +CRWTH +CRYPT +CUBBY +CUBEB +CUBED +CUBER +CUBES +CUBIC +CUBIT +CUDDY +CUFFS +CUIFS +CUING +CUISH +CUKES +CULCH +CULET +CULEX +CULLS +CULLY +CULMS +CULPA +CULTI +CULTS +CUMIN +CUNTS +CUPEL +CUPID +CUPPA +CUPPY +CURBS +CURCH +CURDS +CURDY +CURED +CURER +CURES +CURET +CURFS +CURIA +CURIE +CURIO +CURLS +CURLY +CURNS +CURRS +CURRY +CURSE +CURST +CURVE +CURVY +CUSEC +CUSHY +CUSKS +CUSPS +CUSPY +CUSSO +CUTCH +CUTER +CUTES +CUTEY +CUTIE +CUTIN +CUTIS +CUTTY +CUTUP +CUVEE +CYANO +CYANS +CYBER +CYCAD +CYCAS +CYCLE +CYCLO +CYDER +CYLIX +CYMAE +CYMAR +CYMAS +CYMES +CYMOL +CYNIC +CYSTS +CYTON +CZARS +DACES +DACHA +DADAS +DADDY +DADOS +DAFFS +DAFFY +DAGGA +DAGOS +DAHLS +DAILY +DAIRY +DAISY +DALES +DALLY +DAMAN +DAMAR +DAMES +DAMNS +DAMPS +DANCE +DANDY +DANGS +DANIO +DARBS +DARED +DARER +DARES +DARIC +DARKS +DARKY +DARNS +DARTS +DASHI +DASHY +DATED +DATER +DATES +DATOS +DATTO +DATUM +DAUBE +DAUBS +DAUBY +DAUNT +DAUTS +DAVEN +DAVIT +DAWED +DAWEN +DAWKS +DAWNS +DAWTS +DAZED +DAZES +DEADS +DEAIR +DEALS +DEALT +DEANS +DEARS +DEARY +DEASH +DEATH +DEAVE +DEBAG +DEBAR +DEBIT +DEBTS +DEBUG +DEBUT +DEBYE +DECAF +DECAL +DECAY +DECKS +DECOR +DECOS +DECOY +DECRY +DEDAL +DEEDS +DEEDY +DEEMS +DEEPS +DEERS +DEETS +DEFAT +DEFER +DEFIS +DEFOG +DEFUN +DEGAS +DEGUM +DEICE +DEIFY +DEIGN +DEILS +DEISM +DEIST +DEITY +DEKED +DEKES +DEKKO +DELAY +DELED +DELES +DELFS +DELFT +DELIS +DELLS +DELLY +DELTA +DELTS +DELVE +DEMES +DEMIC +DEMIT +DEMOB +DEMON +DEMOS +DEMUR +DENAR +DENES +DENIM +DENSE +DENTS +DEOXY +DEPOT +DEPTH +DEQUE +DERAT +DERAY +DERBY +DERMA +DERMS +DERRY +DESEX +DESKS +DETER +DETOX +DEUCE +DEVAS +DEVEL +DEVIL +DEVON +DEWAN +DEWAR +DEWAX +DEWED +DEWEY +DEXES +DEXIE +DHAKS +DHALS +DHOBI +DHOLE +DHOTI +DHOWS +DHUTI +DIALS +DIARY +DIAZO +DICED +DICER +DICES +DICEY +DICKS +DICKY +DICOT +DICTA +DICTU +DICTY +DICUT +DIDDY +DIDIE +DIDOS +DIDOT +DIDST +DIEMS +DIENE +DIEST +DIETH +DIETS +DIFFS +DIGHT +DIGIT +DIKED +DIKER +DIKES +DIKEY +DILDO +DILLS +DILLY +DIMER +DIMES +DIMLY +DINAR +DINED +DINER +DINES +DINGE +DINGO +DINGS +DINGY +DINKS +DINKY +DINOS +DINTS +DIODE +DIOLS +DIPPY +DIPSO +DIRAM +DIRER +DIRGE +DIRKS +DIRLS +DIRTS +DIRTY +DISCI +DISCO +DISCS +DISHY +DISKS +DISME +DITAS +DITCH +DITES +DITSY +DITTO +DITTY +DITZY +DIVAN +DIVAS +DIVED +DIVER +DIVES +DIVOT +DIVVY +DIWAN +DIXIT +DIZEN +DIZZY +DJINN +DJINS +DOATS +DOBBY +DOBIE +DOBLA +DOBRA +DOBRO +DOCKS +DODGE +DODGY +DODOS +DOERS +DOEST +DOETH +DOFFS +DOGES +DOGEY +DOGGO +DOGGY +DOGIE +DOGMA +DOILY +DOING +DOITS +DOJOS +DOLCE +DOLCI +DOLED +DOLES +DOLLS +DOLLY +DOLMA +DOLOR +DOLTS +DOMAL +DOMED +DOMES +DOMIC +DONAS +DONEE +DONGA +DONGS +DONNA +DONNE +DONOR +DONSY +DONUT +DOODY +DOOLY +DOOMS +DOOMY +DOORS +DOOZY +DOPAS +DOPED +DOPER +DOPES +DOPEY +DORKS +DORKY +DORMS +DORMY +DORPS +DORRS +DORSA +DORTY +DOSED +DOSER +DOSES +DOTAL +DOTED +DOTER +DOTES +DOTTY +DOUBT +DOUCE +DOUGH +DOULA +DOUMA +DOUMS +DOURA +DOUSE +DOVEN +DOVES +DOVEY +DOWDY +DOWED +DOWEL +DOWER +DOWIE +DOWNS +DOWNY +DOWRY +DOWSE +DOXIE +DOYEN +DOYLY +DOZED +DOZEN +DOZER +DOZES +DRABS +DRAFF +DRAFT +DRAGS +DRAIL +DRAIN +DRAKE +DRAMA +DRAMS +DRANK +DRAPE +DRATS +DRAVE +DRAWL +DRAWN +DRAWS +DRAYS +DREAD +DREAM +DREAR +DRECK +DREED +DREES +DREGS +DREKS +DRESS +DREST +DRIBS +DRIED +DRIER +DRIES +DRIFT +DRILL +DRILY +DRINK +DRIPS +DRIPT +DRIVE +DROID +DROIT +DROLL +DRONE +DROOL +DROOP +DROPS +DROPT +DROSS +DROUK +DROVE +DROWN +DRUBS +DRUGS +DRUID +DRUMS +DRUNK +DRUPE +DRUSE +DRYAD +DRYER +DRYLY +DUADS +DUALS +DUCAL +DUCAT +DUCES +DUCHY +DUCKS +DUCKY +DUCTS +DUDDY +DUDED +DUDES +DUELS +DUETS +DUFFS +DUFUS +DUITS +DUKED +DUKES +DULIA +DULLS +DULLY +DULSE +DUMAS +DUMBO +DUMBS +DUMKA +DUMKY +DUMMY +DUMPS +DUMPY +DUNAM +DUNCE +DUNCH +DUNES +DUNGS +DUNGY +DUNKS +DUNNO +DUNTS +DUOMI +DUOMO +DUPED +DUPER +DUPES +DUPLE +DURAL +DURAS +DURED +DURES +DURNS +DUROC +DUROS +DURRA +DURRS +DURST +DURUM +DUSKS +DUSKY +DUSTS +DUSTY +DUTCH +DUVET +DWARF +DWEEB +DWELL +DWELT +DWINE +DYADS +DYERS +DYING +DYKED +DYKES +DYKEY +DYNEL +DYNES +EAGER +EAGLE +EAGRE +EARED +EARLS +EARLY +EARNS +EARTH +EASED +EASEL +EASES +EASTS +EATEN +EATER +EAVED +EAVES +EBBED +EBBET +EBONS +EBONY +EBOOK +ECHED +ECHES +ECHOS +ECLAT +ECRUS +EDEMA +EDGED +EDGER +EDGES +EDICT +EDIFY +EDILE +EDITS +EDUCE +EDUCT +EERIE +EGADS +EGERS +EGEST +EGGAR +EGGED +EGGER +EGRET +EIDER +EIDOS +EIGHT +EIKON +EJECT +EKING +ELAIN +ELAND +ELANS +ELATE +ELBOW +ELDER +ELECT +ELEGY +ELEMI +ELFIN +ELIDE +ELINT +ELITE +ELOIN +ELOPE +ELUDE +ELUTE +ELVER +ELVES +EMAIL +EMBAR +EMBAY +EMBED +EMBER +EMBOW +EMCEE +EMEER +EMEND +EMERY +EMEUS +EMIRS +EMITS +EMMER +EMMET +EMMYS +EMOTE +EMPTY +EMYDE +EMYDS +ENACT +ENATE +ENDED +ENDER +ENDOW +ENDUE +ENEMA +ENEMY +ENJOY +ENNUI +ENOKI +ENOLS +ENORM +ENOWS +ENROL +ENSKY +ENSUE +ENTER +ENTIA +ENTRY +ENURE +ENVOI +ENVOY +ENZYM +EOSIN +EPACT +EPEES +EPHAH +EPHAS +EPHOD +EPHOR +EPICS +EPOCH +EPODE +EPOXY +EPSOM +EQUAL +EQUID +EQUIP +ERASE +ERECT +ERGOT +ERICA +ERNES +ERODE +EROSE +ERRED +ERROR +ERSES +ERUCT +ERUGO +ERUPT +ERVIL +ESCAR +ESCOT +ESKAR +ESKER +ESNES +ESSAY +ESSES +ESTER +ESTOP +ETAPE +ETEXT +ETHER +ETHIC +ETHOS +ETHYL +ETNAS +ETUDE +ETUIS +ETWEE +ETYMA +EUROS +EVADE +EVENS +EVENT +EVERT +EVERY +EVICT +EVILS +EVITE +EVOKE +EWERS +EXACT +EXALT +EXAMS +EXCEL +EXCON +EXEAT +EXECS +EXERT +EXILE +EXINE +EXING +EXIST +EXITS +EXONS +EXPAT +EXPEL +EXPOS +EXTOL +EXTRA +EXUDE +EXULT +EXURB +EYASS +EYERS +EYING +EYRAS +EYRES +EYRIE +EYRIR +FABLE +FACED +FACER +FACES +FACET +FACIA +FACIE +FACTO +FACTS +FADDY +FADED +FADER +FADES +FADGE +FADOS +FAENA +FAERY +FAGGY +FAGIN +FAGOT +FAILS +FAINT +FAIRE +FAIRS +FAIRY +FAITH +FAKED +FAKER +FAKES +FAKEY +FAKIR +FALLS +FALSE +FAMED +FAMES +FANCY +FANES +FANGA +FANGS +FANIN +FANNY +FANON +FANOS +FANUM +FAQIR +FARAD +FARCE +FARCI +FARCY +FARDS +FARED +FARER +FARES +FARLE +FARLS +FARMS +FAROS +FARTS +FASTS +FATAL +FATED +FATES +FATLY +FATSO +FATTY +FATWA +FAUGH +FAULD +FAULT +FAUNA +FAUNS +FAUVE +FAVAS +FAVES +FAVOR +FAVUS +FAWNS +FAWNY +FAXED +FAXER +FAXES +FAYED +FAZED +FAZES +FEARS +FEASE +FEAST +FEATS +FEAZE +FECAL +FECES +FECKS +FEDEX +FEEBS +FEEDS +FEELS +FEEZE +FEIGN +FEINT +FEIST +FELID +FELLA +FELLS +FELLY +FELON +FELTS +FEMES +FEMME +FEMUR +FENCE +FENDS +FENNY +FEODS +FEOFF +FERAL +FERES +FERIA +FERLY +FERMI +FERNS +FERNY +FERRY +FESSE +FESTS +FETAL +FETAS +FETCH +FETED +FETES +FETID +FETOR +FETUS +FEUAR +FEUDS +FEUED +FEVER +FEWER +FEYER +FEYLY +FEZES +FEZZY +FIARS +FIATS +FIBER +FIBRE +FICES +FICHE +FICHU +FICIN +FICUS +FIDGE +FIDOS +FIEFS +FIELD +FIEND +FIERY +FIFED +FIFER +FIFES +FIFTH +FIFTY +FIGHT +FILAR +FILCH +FILED +FILER +FILES +FILET +FILLE +FILLO +FILLS +FILLY +FILMI +FILMS +FILMY +FILOS +FILTH +FILUM +FINAL +FINCA +FINCH +FINDS +FINED +FINER +FINES +FINIF +FINIS +FINKS +FINNY +FINOS +FIORD +FIQUE +FIRED +FIRER +FIRES +FIRMA +FIRMS +FIRNS +FIRRY +FIRST +FIRTH +FISCS +FISHY +FISTS +FISTY +FITCH +FITLY +FIVER +FIVES +FIXED +FIXER +FIXES +FIXIT +FIZZY +FJELD +FJORD +FLABS +FLACK +FLAGS +FLAIL +FLAIR +FLAKE +FLAKS +FLAKY +FLAME +FLAMS +FLAMY +FLANK +FLANS +FLAPS +FLARE +FLASH +FLASK +FLATS +FLAWS +FLAWY +FLAXY +FLAYS +FLEAM +FLEAS +FLECK +FLEER +FLEES +FLEET +FLESH +FLEWS +FLEYS +FLICK +FLICS +FLIED +FLIER +FLIES +FLING +FLINT +FLIPS +FLIRS +FLIRT +FLITE +FLITS +FLOAT +FLOCK +FLOCS +FLOES +FLOGS +FLONG +FLOOD +FLOOR +FLOPS +FLORA +FLOSS +FLOTA +FLOUR +FLOUT +FLOWN +FLOWS +FLUBS +FLUED +FLUES +FLUFF +FLUID +FLUKE +FLUKY +FLUME +FLUMP +FLUNG +FLUNK +FLUOR +FLUSH +FLUTE +FLUTY +FLUYT +FLYBY +FLYER +FLYTE +FOALS +FOAMS +FOAMY +FOCAL +FOCUS +FOEHN +FOGEY +FOGGY +FOGIE +FOHNS +FOILS +FOINS +FOIST +FOLDS +FOLEY +FOLIA +FOLIC +FOLIO +FOLKS +FOLKY +FOLLY +FONDS +FONDU +FONTS +FOODS +FOOLS +FOOTS +FOOTY +FORAM +FORAY +FORBS +FORBY +FORCE +FORDO +FORDS +FORES +FORGE +FORGO +FORKS +FORKY +FORMA +FORME +FORMS +FORTE +FORTH +FORTS +FORTY +FORUM +FOSSA +FOSSE +FOULS +FOUND +FOUNT +FOURS +FOVEA +FOWLS +FOXED +FOXES +FOYER +FRAGS +FRAIL +FRAME +FRANC +FRANK +FRAPS +FRASS +FRATS +FRAUD +FRAYS +FREAK +FREED +FREER +FREES +FREMD +FRENA +FRERE +FRESH +FRETS +FRIAR +FRIED +FRIER +FRIES +FRIGS +FRILL +FRISE +FRISK +FRITH +FRITS +FRITT +FRITZ +FRIZZ +FROCK +FROES +FROGS +FROND +FRONS +FRONT +FRORE +FROSH +FROST +FROTH +FROWN +FROWS +FROZE +FRUGS +FRUIT +FRUMP +FRYER +FTPED +FUBAR +FUBSY +FUCKS +FUCUS +FUDDY +FUDGE +FUDGY +FUELS +FUGAL +FUGGY +FUGIO +FUGIT +FUGLE +FUGUE +FUGUS +FUJIS +FULLS +FULLY +FUMED +FUMER +FUMES +FUMET +FUNDI +FUNDS +FUNGI +FUNGO +FUNKS +FUNKY +FUNNY +FURAN +FURLS +FUROR +FURRY +FURZE +FURZY +FUSED +FUSEE +FUSEL +FUSES +FUSIL +FUSSY +FUSTY +FUTON +FUZED +FUZEE +FUZES +FUZIL +FUZZY +FYCES +FYKES +FYTTE +GABBY +GABLE +GADDI +GADID +GADIS +GADJE +GADJO +GAFFE +GAFFS +GAGED +GAGER +GAGES +GAILY +GAINS +GAITS +GALAH +GALAS +GALAX +GALEA +GALES +GALLS +GALLY +GALOP +GAMAS +GAMAY +GAMBA +GAMBE +GAMBS +GAMED +GAMER +GAMES +GAMEY +GAMIC +GAMIN +GAMMA +GAMMY +GAMPS +GAMUT +GANEF +GANEV +GANGS +GANJA +GANOF +GAOLS +GAPED +GAPER +GAPES +GAPPY +GARBS +GARDA +GARDE +GARNI +GARTH +GASES +GASPS +GASSY +GASTS +GATED +GATER +GATES +GATOR +GAUDS +GAUDY +GAUGE +GAULT +GAUMS +GAUNT +GAURS +GAUSS +GAUZE +GAUZY +GAVEL +GAVOT +GAWKS +GAWKY +GAWPS +GAWSY +GAYAL +GAYER +GAYLY +GAZAR +GAZED +GAZER +GAZES +GAZOO +GEARS +GECKO +GECKS +GEEKS +GEEKY +GEESE +GEEST +GELDS +GELEE +GELID +GELTS +GEMMA +GEMMY +GEMOT +GENES +GENET +GENIC +GENIE +GENII +GENIP +GENOA +GENOM +GENRE +GENRO +GENTS +GENUA +GENUS +GEODE +GEOID +GERAH +GERMS +GERMY +GESSO +GESTE +GESTS +GETAS +GETUP +GEUMS +GHAST +GHATS +GHAUT +GHAZI +GHEES +GHOST +GHOTI +GHOUL +GHYLL +GIANT +GIBED +GIBER +GIBES +GIDDY +GIFTS +GIGAS +GIGHE +GIGOT +GIGUE +GILDS +GILLS +GILLY +GILTS +GIMEL +GIMME +GIMPS +GIMPY +GINKS +GINNY +GINZO +GIPON +GIPSY +GIRDS +GIRLS +GIRLY +GIRNS +GIRON +GIROS +GIRSH +GIRTH +GIRTS +GISMO +GISTS +GITES +GIVEN +GIVER +GIVES +GIZMO +GLACE +GLADE +GLADS +GLADY +GLAIR +GLAMS +GLAND +GLANS +GLARE +GLARY +GLASS +GLAZE +GLAZY +GLEAM +GLEAN +GLEBA +GLEBE +GLEDE +GLEDS +GLEED +GLEEK +GLEES +GLEET +GLENS +GLEYS +GLIAL +GLIAS +GLIDE +GLIFF +GLIME +GLIMS +GLINT +GLITZ +GLOAM +GLOAT +GLOBE +GLOBS +GLOGG +GLOMS +GLOOM +GLOPS +GLORY +GLOSS +GLOST +GLOUT +GLOVE +GLOWS +GLOZE +GLUED +GLUER +GLUES +GLUEY +GLUGS +GLUME +GLUMS +GLUON +GLUTE +GLUTS +GLYPH +GNARL +GNARR +GNARS +GNASH +GNATS +GNAWN +GNAWS +GNOME +GOADS +GOALS +GOATS +GOBAN +GOBOS +GODET +GODLY +GOERS +GOEST +GOETH +GOFER +GOGOS +GOING +GOLDS +GOLEM +GOLFS +GOLLY +GOMBO +GOMER +GONAD +GONEF +GONER +GONGS +GONIA +GONIF +GONNA +GONOF +GONZO +GOODS +GOODY +GOOEY +GOOFS +GOOFY +GOOKS +GOOKY +GOONS +GOONY +GOOPS +GOOPY +GOOSE +GOOSY +GOPIK +GORAL +GORED +GORES +GORGE +GORMS +GORPS +GORSE +GORSY +GOTHS +GOTTA +GOUDA +GOUGE +GOURD +GOUTS +GOUTY +GOWAN +GOWDS +GOWKS +GOWNS +GOXES +GOYIM +GRAAL +GRABS +GRACE +GRADE +GRADS +GRAFT +GRAIL +GRAIN +GRAMA +GRAMP +GRAMS +GRANA +GRAND +GRANS +GRANT +GRAPE +GRAPH +GRAPY +GRASP +GRASS +GRATA +GRATE +GRAVE +GRAVY +GRAYS +GRAZE +GREAT +GREBE +GREED +GREEK +GREEN +GREES +GREET +GREGO +GREPS +GREYS +GRIDE +GRIDS +GRIEF +GRIFF +GRIFT +GRIGS +GRILL +GRIME +GRIMY +GRIND +GRINS +GRIOT +GRIPE +GRIPS +GRIPT +GRIPY +GRIST +GRITH +GRITS +GROAN +GROAT +GRODY +GROGS +GROIN +GROKS +GRONK +GROOK +GROOM +GROPE +GROSS +GROSZ +GROTS +GROUP +GROUT +GROVE +GROWL +GROWN +GROWS +GRUBS +GRUEL +GRUES +GRUFF +GRUME +GRUMP +GRUNT +GUACO +GUANO +GUANS +GUARD +GUARS +GUAVA +GUCKS +GUDES +GUESS +GUEST +GUFFS +GUIDE +GUIDS +GUILD +GUILE +GUILT +GUIRO +GUISE +GULAG +GULAR +GULCH +GULES +GULFS +GULFY +GULLS +GULLY +GULPS +GULPY +GUMBO +GUMMA +GUMMY +GUNKS +GUNKY +GUNNY +GUPPY +GURGE +GURRY +GURSH +GURUS +GUSHY +GUSSY +GUSTO +GUSTS +GUSTY +GUTSY +GUTTA +GUTTY +GUYED +GUYOT +GWINE +GYBED +GYBES +GYOZA +GYPPY +GYPSY +GYRAL +GYRED +GYRES +GYRON +GYROS +GYRUS +GYVED +GYVES +HAAFS +HAARS +HABIT +HABUS +HACEK +HACKS +HADAL +HADDA +HADED +HADES +HADJI +HADST +HAEMS +HAETS +HAFIZ +HAFTA +HAFTS +HAHAS +HAIKA +HAIKS +HAIKU +HAILS +HAINT +HAIRS +HAIRY +HAJES +HAJIS +HAJJI +HAKES +HAKIM +HAKUS +HALAL +HALED +HALER +HALES +HALID +HALLO +HALLS +HALMA +HALMS +HALON +HALOS +HALTS +HALVA +HALVE +HAMAL +HAMES +HAMMY +HAMZA +HANCE +HANDS +HANDY +HANGS +HANKS +HANKY +HANSA +HANSE +HANTS +HAOLE +HAPAX +HAPLY +HAPPY +HARDS +HARDY +HARED +HAREM +HARES +HARKS +HARLS +HARMS +HARPS +HARPY +HARRY +HARSH +HARTS +HARUM +HASPS +HASTE +HASTY +HATCH +HATED +HATER +HATES +HAUGH +HAULM +HAULS +HAUNT +HAUTE +HAVEN +HAVER +HAVES +HAVOC +HAWED +HAWKS +HAWSE +HAYED +HAYER +HAYEY +HAZAN +HAZED +HAZEL +HAZER +HAZES +HEADS +HEADY +HEALS +HEAPS +HEAPY +HEARD +HEARS +HEART +HEATH +HEATS +HEAVE +HEAVY +HEBES +HECKS +HEDER +HEDGE +HEDGY +HEEDS +HEELS +HEERD +HEEZE +HEFTS +HEFTY +HEIGH +HEILS +HEIRS +HEIST +HELIO +HELIX +HELLO +HELLS +HELMS +HELOS +HELOT +HELPS +HELVE +HEMAL +HEMES +HEMIC +HEMIN +HEMPS +HEMPY +HENCE +HENGE +HENNA +HENRY +HENTS +HERBS +HERBY +HERDS +HEREM +HERES +HERLS +HERMA +HERMS +HERNS +HERON +HEROS +HERRY +HERTZ +HESTS +HETHS +HEUCH +HEUGH +HEWED +HEWER +HEXAD +HEXED +HEXER +HEXES +HEXYL +HICKS +HIDED +HIDER +HIDES +HIGHS +HIGHT +HIJAB +HIJRA +HIKED +HIKER +HIKES +HILAR +HILLO +HILLS +HILLY +HILTS +HILUM +HILUS +HIMBO +HINDS +HINGE +HINKY +HINNY +HINTS +HIPLY +HIPPO +HIPPY +HIRED +HIREE +HIRER +HIRES +HISSY +HISTS +HITCH +HIVED +HIVER +HIVES +HOAGY +HOARD +HOARS +HOARY +HOBBY +HOBOS +HOCKS +HOCUS +HODAD +HOERS +HOGAN +HOGGS +HOICK +HOISE +HOIST +HOKED +HOKES +HOKEY +HOKKU +HOKUM +HOLDS +HOLED +HOLER +HOLES +HOLEY +HOLKS +HOLLA +HOLLO +HOLLY +HOLMS +HOLON +HOLTS +HOMED +HOMER +HOMES +HOMEY +HOMIE +HOMME +HOMOS +HONAN +HONDA +HONED +HONER +HONES +HONEY +HONGI +HONGS +HONKS +HONKY +HONOR +HOOCH +HOODS +HOODY +HOOEY +HOOFS +HOOKA +HOOKS +HOOKY +HOOLY +HOOPS +HOOTS +HOOTY +HOPED +HOPER +HOPES +HOPPY +HORAH +HORAL +HORAS +HORDE +HORNS +HORNY +HORSE +HORST +HORSY +HOSED +HOSEL +HOSEN +HOSER +HOSES +HOSEY +HOSTA +HOSTS +HOTCH +HOTEL +HOTLY +HOUND +HOURI +HOURS +HOUSE +HOVEL +HOVER +HOWDY +HOWES +HOWFF +HOWFS +HOWKS +HOWLS +HOYAS +HOYLE +HUBBA +HUBBY +HUCKS +HUFFS +HUFFY +HUGER +HULAS +HULKS +HULKY +HULLO +HULLS +HUMAN +HUMIC +HUMID +HUMOR +HUMPF +HUMPH +HUMPS +HUMPY +HUMUS +HUNCH +HUNKS +HUNKY +HUNTS +HURDS +HURLS +HURLY +HURRY +HURST +HURTS +HUSKS +HUSKY +HUSSY +HUTCH +HUZZA +HYDRA +HYDRO +HYENA +HYING +HYLAS +HYMEN +HYMNS +HYOID +HYPED +HYPER +HYPES +HYPHA +HYPOS +HYRAX +HYSON +IAMBI +IAMBS +ICERS +ICHOR +ICIER +ICILY +ICING +ICKER +ICONS +ICTIC +ICTUS +IDEAL +IDEAS +IDIOM +IDIOT +IDLED +IDLER +IDLES +IDOLS +IDYLL +IDYLS +IGGED +IGLOO +IGLUS +IHRAM +IKATS +IKONS +ILEAC +ILEAL +ILEUM +ILEUS +ILIAC +ILIAD +ILIAL +ILIUM +ILLER +IMAGE +IMAGO +IMAMS +IMAUM +IMBED +IMBUE +IMIDE +IMIDO +IMIDS +IMINE +IMINO +IMMIX +IMPED +IMPEL +IMPIS +IMPLY +IMPRO +INANE +INAPT +INARM +INBYE +INCOG +INCUR +INCUS +INDEX +INDIE +INDOL +INDOW +INDRI +INDUE +INEPT +INERT +INFER +INFIX +INFOS +INFRA +INGLE +INGOT +INION +INJUN +INKED +INKER +INKLE +INLAY +INLET +INNED +INNER +INODE +INPUT +INRUN +INSET +INTER +INTIS +INTRA +INTRO +INURE +INURN +INVAR +IOCTL +IODIC +IODID +IODIN +IONIC +IOTAS +IRADE +IRATE +IRIDS +IRING +IRKED +IROKO +IRONE +IRONS +IRONY +ISBAS +ISLED +ISLES +ISLET +ISSEI +ISSUE +ISTLE +ITCHY +ITEMS +ITHER +IVIED +IVIES +IVORY +IXIAS +IXNAY +IXORA +IXTLE +IZARS +JABOT +JACAL +JACKS +JACKY +JADED +JADES +JAGER +JAGGS +JAGGY +JAGRA +JAILS +JAKES +JALAP +JALOP +JAMBE +JAMBS +JAMMY +JANES +JANTY +JAPAN +JAPED +JAPER +JAPES +JARLS +JATOS +JAUKS +JAUNT +JAUPS +JAVAS +JAWAN +JAWED +JAZZY +JEANS +JEBEL +JEEPS +JEERS +JEFES +JEHAD +JEHUS +JELLO +JELLS +JELLY +JEMMY +JENNY +JERID +JERKS +JERKY +JERRY +JESSE +JESTS +JETES +JETON +JETTY +JEWED +JEWEL +JIBBS +JIBED +JIBER +JIBES +JIFFS +JIFFY +JIGGY +JIHAD +JILLS +JILTS +JIMMY +JIMPY +JINGO +JINGS +JINKS +JINNI +JINNS +JISMS +JIVED +JIVER +JIVES +JIVEY +JNANA +JOCKO +JOCKS +JOEYS +JOHNS +JOINS +JOINT +JOIST +JOKED +JOKER +JOKES +JOKEY +JOLES +JOLLY +JOLTS +JOLTY +JOMON +JONES +JORAM +JORUM +JOTAS +JOTTY +JOUAL +JOUKS +JOULE +JOUST +JOWAR +JOWED +JOWLS +JOWLY +JOYED +JUBAS +JUBES +JUCOS +JUDAS +JUDGE +JUDOS +JUGAL +JUGUM +JUICE +JUICY +JUJUS +JUKED +JUKES +JUKUS +JULEP +JUMBO +JUMPS +JUMPY +JUNCO +JUNKS +JUNKY +JUNTA +JUNTO +JUPES +JUPON +JURAL +JURAT +JUREL +JUROR +JUSTE +JUSTS +JUTES +JUTTY +KABAB +KABAR +KABOB +KADIS +KAFIR +KAGUS +KAIAK +KAIFS +KAILS +KAINS +KAKAS +KAKIS +KALAM +KALES +KALIF +KALPA +KAMES +KAMIK +KANAS +KANES +KANJI +KANZU +KAONS +KAPAS +KAPHS +KAPOK +KAPPA +KAPUT +KARAT +KARMA +KARNS +KAROO +KARST +KARTS +KASHA +KATAS +KAURI +KAURY +KAVAS +KAYAK +KAYOS +KAZOO +KBARS +KEBAB +KEBAR +KEBOB +KECKS +KEDGE +KEEFS +KEEKS +KEELS +KEENS +KEEPS +KEETS +KEEVE +KEFIR +KEIRS +KELEP +KELIM +KELLY +KELPS +KELPY +KELTS +KEMPS +KEMPT +KENAF +KENCH +KENDO +KENOS +KENTE +KEPIS +KERBS +KERFS +KERNE +KERNS +KERRY +KETCH +KETOL +KEVEL +KEVIL +KEXES +KEYED +KEYER +KHADI +KHAFS +KHAKI +KHANS +KHAPH +KHATS +KHEDA +KHETH +KHETS +KHOUM +KIANG +KIBBE +KIBBI +KIBEI +KIBES +KIBLA +KICKS +KICKY +KIDDO +KIDDY +KIEFS +KIERS +KIKES +KILIM +KILLS +KILNS +KILOS +KILTS +KILTY +KINAS +KINDA +KINDS +KINES +KINGS +KININ +KINKS +KINKY +KINOS +KIOSK +KIRKS +KIRNS +KISSY +KISTS +KITED +KITER +KITES +KITHE +KITHS +KITTY +KIVAS +KIWIS +KLICK +KLIEG +KLIKS +KLONG +KLOOF +KLUGE +KLUGY +KLUNK +KLUTZ +KNACK +KNAPS +KNARS +KNAUR +KNAVE +KNAWE +KNEAD +KNEED +KNEEL +KNEES +KNELL +KNELT +KNIFE +KNISH +KNITS +KNOBS +KNOCK +KNOLL +KNOPS +KNOSP +KNOTS +KNOUT +KNOWN +KNOWS +KNURL +KNURS +KOALA +KOANS +KOBOS +KOELS +KOHLS +KOINE +KOJIS +KOLAS +KOLOS +KOMBU +KONKS +KOOKS +KOOKY +KOPEK +KOPHS +KOPJE +KOPPA +KORAI +KORAS +KORAT +KORMA +KORUN +KOTOS +KOTOW +KRAAL +KRAFT +KRAIT +KRAUT +KREEP +KREWE +KRILL +KRONA +KRONE +KROON +KRUBI +KUDOS +KUDUS +KUDZU +KUFIS +KUGEL +KUKRI +KULAK +KUMYS +KURTA +KURUS +KUSSO +KVASS +KVELL +KYACK +KYAKS +KYARS +KYATS +KYLIX +KYRIE +KYTES +KYTHE +LAARI +LABEL +LABIA +LABOR +LABRA +LACED +LACER +LACES +LACEY +LACKS +LADED +LADEN +LADER +LADES +LADLE +LAEVO +LAGAN +LAGER +LAHAR +LAICH +LAICS +LAIGH +LAIRD +LAIRS +LAITH +LAITY +LAKED +LAKER +LAKES +LAKHS +LALLS +LAMAS +LAMBS +LAMBY +LAMED +LAMER +LAMES +LAMIA +LAMPS +LANAI +LANCE +LANDS +LANES +LANKY +LAPEL +LAPIN +LAPIS +LAPSE +LARCH +LARDS +LARDY +LAREE +LARES +LARGE +LARGO +LARIS +LARKS +LARKY +LARUM +LARVA +LASED +LASER +LASES +LASSI +LASSO +LASTS +LATCH +LATED +LATEN +LATER +LATEX +LATHE +LATHI +LATHS +LATHY +LATIN +LATKE +LATTE +LATUS +LAUAN +LAUDE +LAUDS +LAUGH +LAURA +LAVAS +LAVED +LAVER +LAVES +LAWED +LAWNS +LAWNY +LAWZY +LAXER +LAXES +LAXLY +LAYED +LAYER +LAYIN +LAYUP +LAZAR +LAZED +LAZES +LEACH +LEADS +LEADY +LEAFS +LEAFY +LEAKS +LEAKY +LEANS +LEANT +LEAPS +LEAPT +LEARN +LEARS +LEARY +LEASE +LEASH +LEAST +LEAVE +LEAVY +LEBEN +LEDGE +LEDGY +LEECH +LEEKS +LEERS +LEERY +LEETS +LEFTS +LEFTY +LEGAL +LEGER +LEGES +LEGGO +LEGGY +LEGIT +LEGOS +LEHRS +LEHUA +LEMAN +LEMMA +LEMME +LEMON +LEMUR +LENDS +LENES +LENIS +LENOS +LENSE +LENTO +LEONE +LEPER +LEPTA +LESBO +LESES +LETCH +LETHE +LETUP +LEUDS +LEVEE +LEVEL +LEVER +LEVIN +LEVIS +LEWIS +LEXES +LEXIS +LEZZY +LIANA +LIANE +LIANG +LIARD +LIARS +LIBEL +LIBER +LIBRA +LIBRI +LICHI +LICHT +LICIT +LICKS +LIDAR +LIDOS +LIEGE +LIENS +LIERS +LIEST +LIETH +LIEUS +LIEVE +LIFER +LIFTS +LIGAN +LIGER +LIGHT +LIGNE +LIKED +LIKEN +LIKER +LIKES +LILAC +LILOS +LILTS +LILTY +LIMAN +LIMAS +LIMBA +LIMBI +LIMBO +LIMBS +LIMBY +LIMED +LIMEN +LIMES +LIMEY +LIMIT +LIMNS +LIMOS +LIMPA +LIMPS +LINAC +LINDY +LINED +LINEN +LINER +LINES +LINEY +LINGA +LINGO +LINGS +LINGY +LININ +LINKS +LINKY +LINNS +LINOS +LINTS +LINTY +LINUM +LIONS +LIPID +LIPIN +LIPPY +LIRAS +LIROT +LISLE +LISPS +LISTS +LITAI +LITAS +LITER +LITES +LITHE +LITHO +LITRE +LIVED +LIVEN +LIVER +LIVES +LIVID +LIVRE +LLAMA +LLANO +LOACH +LOADS +LOAFS +LOAMS +LOAMY +LOANS +LOATH +LOBAR +LOBBY +LOBED +LOBES +LOBOS +LOCAL +LOCHS +LOCKS +LOCOS +LOCUM +LOCUS +LODEN +LODES +LODGE +LOESS +LOFTS +LOFTY +LOGAN +LOGES +LOGGY +LOGIA +LOGIC +LOGIN +LOGOI +LOGON +LOGOS +LOIDS +LOINS +LOLLS +LOLLY +LONER +LONGE +LONGS +LOOBY +LOOED +LOOEY +LOOFA +LOOFS +LOOIE +LOOKS +LOOKY +LOOMS +LOONS +LOONY +LOOPS +LOOPY +LOOSE +LOOTS +LOPED +LOPER +LOPES +LOPPY +LORAL +LORAN +LORDS +LORDY +LORES +LORIS +LORRY +LOSEL +LOSER +LOSES +LOSSY +LOTAH +LOTAS +LOTIC +LOTOS +LOTSA +LOTTA +LOTTE +LOTTO +LOTUS +LOUGH +LOUIE +LOUIS +LOUMA +LOUPE +LOUPS +LOURS +LOURY +LOUSE +LOUSY +LOUTS +LOVAT +LOVED +LOVER +LOVES +LOWED +LOWER +LOWES +LOWLY +LOWSE +LOXED +LOXES +LOYAL +LUAUS +LUBED +LUBES +LUBRA +LUCES +LUCID +LUCKS +LUCKY +LUCRE +LUDES +LUDIC +LUFFA +LUFFS +LUGED +LUGER +LUGES +LULAB +LULLS +LULUS +LUMAS +LUMEN +LUMPS +LUMPY +LUNAR +LUNAS +LUNCH +LUNES +LUNET +LUNGE +LUNGI +LUNGS +LUNKS +LUNTS +LUPIN +LUPUS +LURCH +LURED +LURER +LURES +LUREX +LURID +LURKS +LUSTS +LUSTY +LUSUS +LUTEA +LUTED +LUTES +LUVYA +LUXES +LWEIS +LYARD +LYART +LYASE +LYCEA +LYCEE +LYCRA +LYING +LYMPH +LYNCH +LYRES +LYRIC +LYSED +LYSES +LYSIN +LYSIS +LYSSA +LYTIC +LYTTA +MAARS +MABES +MACAW +MACED +MACER +MACES +MACHE +MACHO +MACHS +MACKS +MACLE +MACON +MACRO +MADAM +MADLY +MADRE +MAFIA +MAFIC +MAGES +MAGIC +MAGMA +MAGNA +MAGOT +MAGUS +MAHOE +MAHUA +MAIDS +MAILE +MAILL +MAILS +MAIMS +MAINS +MAIRS +MAIST +MAIZE +MAJOR +MAKAR +MAKER +MAKES +MAKOS +MALAR +MALES +MALIC +MALLS +MALMS +MALMY +MALTS +MALTY +MAMAS +MAMBA +MAMBO +MAMEY +MAMIE +MAMMA +MAMMY +MANAS +MANAT +MANED +MANES +MANGA +MANGE +MANGO +MANGY +MANIA +MANIC +MANLY +MANNA +MANOR +MANOS +MANSE +MANTA +MANUS +MAPLE +MAQUI +MARAS +MARCH +MARCS +MARES +MARGE +MARIA +MARKA +MARKS +MARLS +MARLY +MARRY +MARSE +MARSH +MARTS +MARVY +MASAS +MASER +MASHY +MASKS +MASON +MASSA +MASSE +MASSY +MASTS +MATCH +MATED +MATER +MATES +MATEY +MATHS +MATIN +MATTE +MATTS +MATZA +MATZO +MAUDS +MAULS +MAUND +MAUTS +MAUVE +MAVEN +MAVIE +MAVIN +MAVIS +MAWED +MAXED +MAXES +MAXIM +MAXIS +MAYAN +MAYAS +MAYBE +MAYED +MAYOR +MAYOS +MAYST +MAZED +MAZER +MAZES +MBIRA +MEADS +MEALS +MEALY +MEANS +MEANT +MEANY +MEATS +MEATY +MEBBE +MECCA +MECUM +MEDAL +MEDIA +MEDIC +MEDII +MEEDS +MEETS +MEINY +MELBA +MELDS +MELEE +MELIC +MELLS +MELON +MELTS +MELTY +MEMES +MEMOS +MENAD +MENDS +MENSA +MENSE +MENSH +MENTA +MENUS +MEOUS +MEOWS +MERCH +MERCS +MERCY +MERDE +MERER +MERES +MERGE +MERIT +MERKS +MERLE +MERLS +MERRY +MERSE +MESAS +MESHY +MESIC +MESNE +MESON +MESSY +METAL +METED +METER +METES +METHS +METIS +METOL +METRE +METRO +MEWED +MEWLS +MEZES +MEZZO +MIAOU +MIAOW +MIASM +MIAUL +MICAS +MICHE +MICKS +MICRA +MICRO +MIDDY +MIDGE +MIDIS +MIDST +MIENS +MIFFS +MIFFY +MIGGS +MIGHT +MIKED +MIKES +MIKRA +MILCH +MILDS +MILER +MILES +MILIA +MILKS +MILKY +MILLE +MILLS +MILOS +MILPA +MILTS +MILTY +MIMED +MIMEO +MIMER +MIMES +MIMIC +MIMSY +MINAE +MINAS +MINCE +MINCY +MINDS +MINED +MINER +MINES +MINGY +MINIM +MINIS +MINKE +MINKS +MINNY +MINOR +MINTS +MINTY +MINUS +MIRED +MIRES +MIREX +MIRIN +MIRKS +MIRKY +MIRTH +MIRZA +MISDO +MISER +MISES +MISOS +MISSY +MISTS +MISTY +MITER +MITES +MITIS +MITRE +MITTS +MIXED +MIXER +MIXES +MIXUP +MIZEN +MOANS +MOATS +MOCHA +MOCKS +MODAL +MODEL +MODEM +MODES +MODUS +MOGGY +MOGUL +MOHEL +MOHUR +MOILS +MOIRA +MOIRE +MOIST +MOJOS +MOKES +MOLAL +MOLAR +MOLAS +MOLDS +MOLDY +MOLES +MOLLS +MOLLY +MOLTO +MOLTS +MOMES +MOMMA +MOMMY +MOMUS +MONAD +MONAS +MONDE +MONDO +MONEY +MONGO +MONIC +MONIE +MONKS +MONOS +MONTE +MONTH +MOOCH +MOODS +MOODY +MOOED +MOOLA +MOOLS +MOONS +MOONY +MOORS +MOORY +MOOSE +MOOTS +MOPED +MOPER +MOPES +MOPEY +MORAE +MORAL +MORAS +MORAY +MOREL +MORES +MORNS +MORON +MORPH +MORRO +MORSE +MORTS +MOSEY +MOSKS +MOSSO +MOSSY +MOSTE +MOSTS +MOTEL +MOTES +MOTET +MOTEY +MOTHS +MOTHY +MOTIF +MOTOR +MOTTE +MOTTO +MOTTS +MOUCH +MOUES +MOULD +MOULT +MOUND +MOUNT +MOURN +MOUSE +MOUSY +MOUTH +MOVED +MOVER +MOVES +MOVIE +MOWED +MOWER +MOXAS +MOXIE +MOZOS +MRADS +MUCHO +MUCID +MUCIN +MUCKS +MUCKY +MUCOR +MUCRO +MUCUS +MUDDY +MUDRA +MUFFS +MUFTI +MUGGS +MUGGY +MUHLY +MUJIK +MULCH +MULCT +MULED +MULES +MULEY +MULLA +MULLS +MUMBO +MUMMS +MUMMY +MUMPS +MUMUS +MUNCH +MUNGE +MUNGO +MUNGS +MUNGY +MUNIS +MUONS +MURAL +MURAS +MURED +MURES +MUREX +MURID +MURKS +MURKY +MURRA +MURRE +MURRS +MURRY +MUSCA +MUSED +MUSER +MUSES +MUSHY +MUSIC +MUSKS +MUSKY +MUSOS +MUSSY +MUSTA +MUSTH +MUSTS +MUSTY +MUTCH +MUTED +MUTER +MUTES +MUTON +MUTTS +MUXES +MUZZY +MYLAR +MYNAH +MYNAS +MYOID +MYOMA +MYOPE +MYOPY +MYRRH +MYSID +MYTHS +MYTHY +NAANS +NABES +NABIS +NABLA +NABOB +NACHO +NACRE +NADAS +NADIR +NAEVI +NAFFS +NAGGY +NAIAD +NAIFS +NAILS +NAIRA +NAIRU +NAIVE +NAKED +NAKFA +NALAS +NALED +NAMED +NAMER +NAMES +NANAS +NANCE +NANCY +NANNY +NAPAS +NAPES +NAPPA +NAPPE +NAPPY +NARCO +NARCS +NARDS +NARES +NARIC +NARIS +NARKS +NARKY +NASAL +NASTY +NATAL +NATCH +NATES +NATTY +NAVAL +NAVAR +NAVEL +NAVES +NAVVY +NAWAB +NAZIS +NEAPS +NEARS +NEATH +NEATO +NEATS +NECKS +NEDDY +NEEDS +NEEDY +NEEMS +NEEPS +NEGRO +NEGUS +NEIFS +NEIGH +NEIST +NELLY +NEMAS +NENES +NEONS +NERDS +NERDY +NERFS +NEROL +NERTS +NERTZ +NERVE +NERVY +NESTS +NETOP +NETTS +NETTY +NEUKS +NEUME +NEUMS +NEVER +NEVES +NEVUS +NEWEL +NEWER +NEWIE +NEWLY +NEWSY +NEWTS +NEXUS +NGWEE +NICAD +NICER +NICHE +NICKS +NICOL +NIDAL +NIDED +NIDES +NIDUS +NIECE +NIEVE +NIFTY +NIGHS +NIGHT +NIHIL +NILLS +NIMBI +NINES +NINJA +NINNY +NINON +NINTH +NIPAS +NIPPY +NISEI +NISUS +NITER +NITES +NITID +NITON +NITRE +NITRO +NITTY +NIVAL +NIXED +NIXES +NIXIE +NIZAM +NOBBY +NOBLE +NOBLY +NOCKS +NODAL +NODDY +NODES +NODUS +NOELS +NOGGS +NOHOW +NOILS +NOILY +NOIRE +NOIRS +NOISE +NOISY +NOLOS +NOMAD +NOMAS +NOMEN +NOMES +NOMOI +NOMOS +NONAS +NONCE +NONES +NONET +NONNY +NONYL +NOOKS +NOOKY +NOONS +NOOSE +NOPAL +NORIA +NORIS +NORMS +NORTH +NOSED +NOSES +NOSEY +NOTAL +NOTCH +NOTED +NOTER +NOTES +NOTUM +NOUNS +NOVAE +NOVAS +NOVEL +NOWAY +NOWTS +NUBBY +NUBIA +NUCHA +NUDER +NUDES +NUDGE +NUDIE +NUDZH +NUKED +NUKES +NULLS +NUMBS +NUMEN +NURBS +NURDS +NURLS +NURSE +NUTSY +NUTTY +NYALA +NYLON +NYMPH +OAKEN +OAKUM +OARED +OASES +OASIS +OASTS +OATEN +OATER +OATHS +OAVES +OBEAH +OBELI +OBESE +OBEYS +OBIAS +OBITS +OBJET +OBOES +OBOLE +OBOLI +OBOLS +OCCUR +OCEAN +OCHER +OCHRE +OCHRY +OCKER +OCREA +OCTAD +OCTAL +OCTAN +OCTET +OCTYL +OCULI +ODAHS +ODDER +ODDLY +ODEON +ODEUM +ODIST +ODIUM +ODORS +ODOUR +ODYLE +ODYLS +OFAYS +OFFAL +OFFED +OFFEN +OFFER +OFTEN +OFTER +OGAMS +OGEES +OGHAM +OGIVE +OGLED +OGLER +OGLES +OGRES +OHHHH +OHIAS +OHING +OHMIC +OIDIA +OILED +OILER +OINKS +OINKY +OKAPI +OKAYS +OKEHS +OKRAS +OLDEN +OLDER +OLDIE +OLEIC +OLEIN +OLEOS +OLEUM +OLIOS +OLIVE +OLLAS +OLOGY +OMASA +OMBER +OMBRE +OMEGA +OMENS +OMERS +OMITS +ONCET +ONERY +ONION +ONIUM +ONLAY +ONSET +ONTIC +OODLE +OOHED +OOMPH +OORIE +OOTID +OOZED +OOZES +OPAHS +OPALS +OPENS +OPERA +OPINE +OPING +OPIUM +OPSIN +OPTED +OPTIC +ORACH +ORALS +ORANG +ORATE +ORBED +ORBIT +ORCAS +ORCIN +ORDER +ORDOS +OREAD +ORGAN +ORGIC +ORIBI +ORIEL +ORING +ORLES +ORLON +ORLOP +ORMER +ORNIS +ORPIN +ORRIS +ORTHO +ORZOS +OSIER +OSMIC +OSMOL +OSSIA +OSTIA +OTHER +OTTAR +OTTER +OTTOS +OUGHT +OUIJA +OUNCE +OUPHE +OUPHS +OURIE +OUSEL +OUSTS +OUTBY +OUTDO +OUTED +OUTEN +OUTER +OUTGO +OUTRE +OUTTA +OUZEL +OUZOS +OVALS +OVARY +OVATE +OVENS +OVERS +OVERT +OVINE +OVOID +OVOLI +OVOLO +OVULE +OWEST +OWETH +OWING +OWLET +OWNED +OWNER +OWSEN +OXBOW +OXEYE +OXIDE +OXIDS +OXIME +OXIMS +OXLIP +OXTER +OYERS +OZONE +PACAS +PACED +PACER +PACES +PACEY +PACHA +PACKS +PACTS +PADDY +PADIS +PADLE +PADRE +PADRI +PAEAN +PAEON +PAGAN +PAGED +PAGER +PAGES +PAGOD +PAIKS +PAILS +PAINS +PAINT +PAIRS +PAISA +PAISE +PALEA +PALED +PALER +PALES +PALET +PALLS +PALLY +PALMS +PALMY +PALPI +PALPS +PALSY +PAMPA +PANDA +PANDY +PANED +PANEL +PANES +PANGA +PANGS +PANIC +PANNE +PANSY +PANTO +PANTS +PANTY +PAPAL +PAPAS +PAPAW +PAPER +PAPPI +PAPPY +PARAE +PARAS +PARCH +PARDI +PARDS +PARDY +PARED +PAREN +PAREO +PARER +PARES +PAREU +PARGE +PARGO +PARIS +PARKA +PARKS +PARLE +PAROL +PARRS +PARRY +PARSE +PARTS +PARTY +PARVE +PARVO +PASEO +PASES +PASHA +PASSE +PASTA +PASTE +PASTS +PASTY +PATCH +PATED +PATEN +PATER +PATES +PATHS +PATIN +PATIO +PATLY +PATSY +PATTY +PAUSE +PAVAN +PAVED +PAVER +PAVES +PAVID +PAVIN +PAVIS +PAWED +PAWER +PAWKY +PAWLS +PAWNS +PAXES +PAYED +PAYEE +PAYER +PAYOR +PEACE +PEACH +PEAGE +PEAGS +PEAKS +PEAKY +PEALS +PEANS +PEARL +PEARS +PEART +PEASE +PEATS +PEATY +PEAVY +PECAN +PECHS +PECKS +PECKY +PEDAL +PEDES +PEDRO +PEEKS +PEELS +PEENS +PEEPS +PEERS +PEERY +PEEVE +PEINS +PEISE +PEKAN +PEKES +PEKIN +PEKOE +PELES +PELFS +PELON +PELTS +PENAL +PENCE +PENDS +PENES +PENGO +PENIS +PENNA +PENNE +PENNI +PENNY +PEONS +PEONY +PEPLA +PEPOS +PEPPY +PERCH +PERDU +PERDY +PEREA +PERES +PERIL +PERIS +PERKS +PERKY +PERMS +PERPS +PERRY +PERSE +PERVS +PESKY +PESOS +PESTO +PESTS +PESTY +PETAL +PETER +PETIT +PETRI +PETTI +PETTO +PETTY +PEWEE +PEWIT +PFFFT +PHAGE +PHASE +PHIAL +PHLOX +PHONE +PHONO +PHONS +PHONY +PHOTO +PHOTS +PHPHT +PHUTS +PHYLA +PHYLE +PIANO +PIANS +PIBAL +PICAL +PICAS +PICKS +PICKY +PICOT +PICUL +PIECE +PIERS +PIETA +PIETY +PIGGY +PIGMY +PIING +PIKAS +PIKED +PIKER +PIKES +PIKIS +PILAF +PILAR +PILAU +PILAW +PILEA +PILED +PILEI +PILES +PILIS +PILLS +PILOT +PILUS +PIMAS +PIMPS +PINAS +PINCH +PINED +PINES +PINEY +PINGO +PINGS +PINKO +PINKS +PINKY +PINNA +PINNY +PINON +PINOT +PINTA +PINTO +PINTS +PINUP +PIONS +PIOUS +PIPAL +PIPED +PIPER +PIPES +PIPET +PIPIT +PIQUE +PIRNS +PIROG +PISCO +PISMO +PISOS +PISTE +PITAS +PITCH +PITHS +PITHY +PITON +PITTA +PIVOT +PIXEL +PIXES +PIXIE +PIZZA +PLACE +PLACK +PLAGE +PLAID +PLAIN +PLAIT +PLANE +PLANK +PLANS +PLANT +PLASH +PLASM +PLATE +PLATS +PLATY +PLAYA +PLAYS +PLAZA +PLEAD +PLEAS +PLEAT +PLEBE +PLEBS +PLEIN +PLENA +PLEON +PLEWS +PLICA +PLIED +PLIER +PLIES +PLINK +PLODS +PLONK +PLOPS +PLOTS +PLOTZ +PLOWS +PLOYS +PLUCK +PLUGS +PLUMB +PLUME +PLUMP +PLUMS +PLUMY +PLUNK +PLUSH +PLYER +POACH +POBOY +POCKS +POCKY +PODGY +PODIA +POEMS +POESY +POETS +POGEY +POILU +POIND +POINT +POISE +POKED +POKER +POKES +POKEY +POLAR +POLED +POLER +POLES +POLIO +POLIS +POLKA +POLLS +POLLY +POLOS +POLYP +POLYS +POMES +POMMY +POMOS +POMPS +PONCE +PONDS +PONES +PONGS +POOCH +POODS +POOED +POOEY +POOFS +POOFY +POOHS +POOLS +POONS +POOPS +POORI +POOVE +POPES +POPPA +POPPY +POPSY +PORCH +PORED +PORES +PORGY +PORKS +PORKY +PORNO +PORNS +PORNY +PORTS +POSED +POSER +POSES +POSET +POSIT +POSSE +POSTE +POSTS +POTSY +POTTO +POTTY +POUCH +POUFF +POUFS +POULT +POUND +POURS +POUTS +POUTY +POWER +POXED +POXES +POYOU +PRAAM +PRAHU +PRAMS +PRANG +PRANK +PRAOS +PRASE +PRATE +PRATS +PRAUS +PRAWN +PRAYS +PREED +PREEN +PREES +PREOP +PREPS +PRESA +PRESE +PRESS +PREST +PREXY +PREYS +PRICE +PRICK +PRICY +PRIDE +PRIED +PRIER +PRIES +PRIGS +PRILL +PRIMA +PRIME +PRIMI +PRIMO +PRIMP +PRIMS +PRINK +PRINT +PRION +PRIOR +PRISE +PRISM +PRISS +PRIVY +PRIZE +PROAS +PROBE +PRODS +PROEM +PROFS +PROGS +PROLE +PROMO +PROMS +PRONE +PRONG +PROOF +PROPS +PROSE +PROSO +PROSS +PROST +PROSY +PROUD +PROVE +PROWL +PROWS +PROXY +PRUDE +PRUNE +PRUTA +PRYER +PSALM +PSEUD +PSHAW +PSOAE +PSOAI +PSOAS +PSSST +PSYCH +PUBES +PUBIC +PUBIS +PUCES +PUCKA +PUCKS +PUDGY +PUDIC +PUFFS +PUFFY +PUGGY +PUJAH +PUJAS +PUKED +PUKES +PUKKA +PULED +PULER +PULES +PULIK +PULIS +PULLS +PULPS +PULPY +PULSE +PUMAS +PUMPS +PUNAS +PUNCH +PUNGS +PUNJI +PUNKA +PUNKS +PUNKY +PUNNY +PUNTO +PUNTS +PUNTY +PUPAE +PUPAL +PUPAS +PUPIL +PUPPY +PUPUS +PURDA +PUREE +PURER +PURGE +PURIN +PURIS +PURLS +PURRS +PURSE +PURSY +PURTY +PUSES +PUSHY +PUSSY +PUTON +PUTTI +PUTTO +PUTTS +PUTTY +PYGMY +PYINS +PYLON +PYOID +PYRAN +PYRES +PYREX +PYRIC +PYROS +PYXES +PYXIE +PYXIS +QADIS +QAIDS +QANAT +QOPHS +QUACK +QUADS +QUAFF +QUAGS +QUAIL +QUAIS +QUAKE +QUAKY +QUALE +QUALM +QUALS +QUANT +QUARE +QUARK +QUART +QUASH +QUASI +QUASS +QUATE +QUAYS +QUBIT +QUEAN +QUEEN +QUEER +QUELL +QUERN +QUERY +QUEST +QUEUE +QUEYS +QUICK +QUIDS +QUIET +QUIFF +QUILL +QUILT +QUINS +QUINT +QUIPS +QUIPU +QUIRE +QUIRK +QUIRT +QUITE +QUITS +QUODS +QUOIN +QUOIT +QUOLL +QUOTA +QUOTE +QUOTH +QURSH +RABAT +RABBI +RABIC +RABID +RACED +RACER +RACES +RACKS +RACON +RADAR +RADII +RADIO +RADIX +RADON +RAFFS +RAFTS +RAGAS +RAGED +RAGEE +RAGES +RAGGS +RAGGY +RAGIS +RAIAS +RAIDS +RAILS +RAINS +RAINY +RAISE +RAITA +RAJAH +RAJAS +RAJES +RAKED +RAKEE +RAKER +RAKES +RAKIS +RAKUS +RALES +RALLY +RALPH +RAMAL +RAMEE +RAMEN +RAMET +RAMIE +RAMMY +RAMPS +RAMUS +RANCE +RANCH +RANDS +RANDY +RANEE +RANGE +RANGY +RANID +RANIS +RANKS +RANTS +RAPED +RAPER +RAPES +RAPHE +RAPID +RARED +RARER +RARES +RASAE +RASED +RASER +RASES +RASPS +RASPY +RATAL +RATAN +RATCH +RATED +RATEL +RATER +RATES +RATHE +RATHS +RATIO +RATOS +RATTY +RAVED +RAVEL +RAVEN +RAVER +RAVES +RAVIN +RAWER +RAWIN +RAWLY +RAXED +RAXES +RAYAH +RAYAS +RAYED +RAYON +RAZED +RAZEE +RAZER +RAZES +RAZOR +REACH +REACT +READD +READS +READY +REALM +REALS +REAMS +REAPS +REARM +REARS +REATA +REAVE +REBAR +REBBE +REBEC +REBEL +REBID +REBOP +REBOX +REBUS +REBUT +REBUY +RECAP +RECCE +RECIT +RECKS +RECON +RECTA +RECTI +RECTO +RECUR +RECUT +REDAN +REDDS +REDED +REDES +REDIA +REDID +REDIP +REDLY +REDON +REDOS +REDOX +REDRY +REDUB +REDUX +REDYE +REEDS +REEDY +REEFS +REEFY +REEKS +REEKY +REELS +REEST +REEVE +REFED +REFEL +REFER +REFIT +REFIX +REFLY +REFRY +REGAL +REGES +REGMA +REGNA +REHAB +REHEM +REIFS +REIFY +REIGN +REINK +REINS +REIVE +REJIG +REKEY +RELAX +RELAY +RELET +RELIC +RELIT +REMAN +REMAP +REMET +REMEX +REMIT +REMIX +RENAL +RENDS +RENEW +RENIG +RENIN +RENTE +RENTS +REOIL +REPAY +REPEG +REPEL +REPIN +REPLY +REPOS +REPOT +REPPS +REPRO +RERAN +RERIG +RERUN +RESAT +RESAW +RESAY +RESEE +RESET +RESEW +RESID +RESIN +RESIT +RESOD +RESOW +RESTS +RETAG +RETAX +RETCH +RETEM +RETIA +RETIE +RETRO +RETRY +REUSE +REVEL +REVET +REVUE +REWAN +REWAX +REWED +REWET +REWIN +REWON +REXES +RHEAS +RHEME +RHEUM +RHINO +RHOMB +RHUMB +RHYME +RHYTA +RIALS +RIANT +RIATA +RIBBY +RIBES +RICED +RICER +RICES +RICIN +RICKS +RIDER +RIDES +RIDGE +RIDGY +RIELS +RIFER +RIFFS +RIFLE +RIFTS +RIGHT +RIGID +RIGOR +RILED +RILES +RILEY +RILLE +RILLS +RIMED +RIMER +RIMES +RINDS +RINDY +RINGS +RINKS +RINSE +RIOJA +RIOTS +RIPED +RIPEN +RIPER +RIPES +RISEN +RISER +RISES +RISHI +RISKS +RISKY +RISUS +RITES +RITZY +RIVAL +RIVED +RIVEN +RIVER +RIVES +RIVET +RIYAL +ROACH +ROADS +ROAMS +ROANS +ROARS +ROAST +ROBED +ROBES +ROBIN +ROBLE +ROBOT +ROCKS +ROCKY +RODEO +RODES +ROGER +ROGUE +ROIDS +ROILS +ROILY +ROLES +ROLFS +ROLLS +ROMAN +ROMEO +ROMPS +RONDO +ROODS +ROOFS +ROOKS +ROOKY +ROOMS +ROOMY +ROOSE +ROOST +ROOTS +ROOTY +ROPED +ROPER +ROPES +ROPEY +ROQUE +ROSED +ROSES +ROSET +ROSHI +ROSIN +ROTAS +ROTCH +ROTES +ROTIS +ROTLS +ROTOR +ROTOS +ROTTE +ROUEN +ROUES +ROUGE +ROUGH +ROUND +ROUPS +ROUPY +ROUSE +ROUST +ROUTE +ROUTH +ROUTS +ROVED +ROVEN +ROVER +ROVES +ROWAN +ROWDY +ROWED +ROWEL +ROWEN +ROWER +ROWTH +ROYAL +RUANA +RUBBY +RUBEL +RUBES +RUBLE +RUBUS +RUCHE +RUCKS +RUDDS +RUDDY +RUDER +RUERS +RUFFE +RUFFS +RUGAE +RUGAL +RUGBY +RUING +RUINS +RULED +RULER +RULES +RUMBA +RUMEN +RUMMY +RUMOR +RUMPS +RUNES +RUNGS +RUNIC +RUNNY +RUNTS +RUNTY +RUPEE +RURAL +RUSES +RUSHY +RUSKS +RUSSE +RUSTS +RUSTY +RUTHS +RUTIN +RUTTY +RYKED +RYKES +RYNDS +RYOTS +SABAL +SABED +SABER +SABES +SABIN +SABIR +SABLE +SABOT +SABRA +SABRE +SACKS +SACRA +SADES +SADHE +SADHU +SADIS +SADLY +SAFER +SAFES +SAGAS +SAGER +SAGES +SAGGY +SAGOS +SAGUM +SAHIB +SAICE +SAIDS +SAIGA +SAILS +SAINS +SAINT +SAITH +SAJOU +SAKER +SAKES +SAKIS +SALAD +SALAL +SALEP +SALES +SALIC +SALLY +SALMI +SALOL +SALON +SALPA +SALPS +SALSA +SALTS +SALTY +SALVE +SALVO +SAMBA +SAMBO +SAMEK +SAMPS +SANDS +SANDY +SANED +SANER +SANES +SANGA +SANGH +SANTO +SAPID +SAPOR +SAPPY +SARAN +SARDS +SAREE +SARGE +SARGO +SARIN +SARIS +SARKS +SARKY +SAROD +SAROS +SASIN +SASSY +SATAY +SATED +SATEM +SATES +SATIN +SATIS +SATYR +SAUCE +SAUCH +SAUCY +SAUGH +SAULS +SAULT +SAUNA +SAURY +SAUTE +SAVED +SAVER +SAVES +SAVIN +SAVOR +SAVOY +SAVVY +SAWED +SAWER +SAXES +SAYED +SAYER +SAYID +SAYST +SCABS +SCADS +SCAGS +SCALD +SCALE +SCALL +SCALP +SCALY +SCAMP +SCAMS +SCANS +SCANT +SCAPE +SCARE +SCARF +SCARP +SCARS +SCART +SCARY +SCATS +SCATT +SCAUP +SCAUR +SCENA +SCEND +SCENE +SCENT +SCHAV +SCHMO +SCHUL +SCHWA +SCION +SCOFF +SCOLD +SCONE +SCOOP +SCOOT +SCOPE +SCOPS +SCORE +SCORN +SCOTS +SCOUR +SCOUT +SCOWL +SCOWS +SCRAG +SCRAM +SCRAP +SCREE +SCREW +SCRIM +SCRIP +SCROD +SCRUB +SCRUM +SCUBA +SCUDI +SCUDO +SCUDS +SCUFF +SCULK +SCULL +SCULP +SCUMS +SCUPS +SCURF +SCUSE +SCUTA +SCUTE +SCUTS +SCUZZ +SEALS +SEAMS +SEAMY +SEARS +SEATS +SEBUM +SECCO +SECTS +SEDAN +SEDER +SEDGE +SEDGY +SEDUM +SEEDS +SEEDY +SEEKS +SEELS +SEELY +SEEMS +SEEPS +SEEPY +SEERS +SEEST +SEETH +SEGNI +SEGNO +SEGOS +SEGUE +SEIFS +SEINE +SEISE +SEISM +SEIZE +SELAH +SELFS +SELLE +SELLS +SELVA +SEMEN +SEMES +SEMIS +SENDS +SENGI +SENNA +SENOR +SENSA +SENSE +SENTE +SENTI +SEPAL +SEPIA +SEPIC +SEPOY +SEPTA +SEPTS +SERAC +SERAI +SERAL +SERED +SERER +SERES +SERFS +SERGE +SERIF +SERIN +SEROW +SERRY +SERUM +SERVE +SERVO +SETAE +SETAL +SETON +SETTS +SETUP +SEVEN +SEVER +SEWAN +SEWAR +SEWED +SEWER +SEXED +SEXES +SEXTO +SEXTS +SHACK +SHADE +SHADS +SHADY +SHAFT +SHAGS +SHAHS +SHAKE +SHAKO +SHAKY +SHALE +SHALL +SHALT +SHALY +SHAME +SHAMS +SHANK +SHAPE +SHARD +SHARE +SHARK +SHARN +SHARP +SHAUL +SHAVE +SHAWL +SHAWM +SHAWN +SHAWS +SHAYS +SHEAF +SHEAL +SHEAR +SHEAS +SHEDS +SHEEN +SHEEP +SHEER +SHEET +SHEIK +SHELF +SHELL +SHEND +SHENT +SHEOL +SHERD +SHEWN +SHEWS +SHIED +SHIEL +SHIER +SHIES +SHIFT +SHIKI +SHILL +SHILY +SHIMS +SHINE +SHINS +SHINY +SHIPS +SHIRE +SHIRK +SHIRR +SHIRT +SHISH +SHIST +SHITS +SHIVA +SHIVE +SHIVS +SHLEP +SHLUB +SHMOO +SHNOR +SHOAL +SHOAT +SHOCK +SHOED +SHOER +SHOES +SHOGI +SHOGS +SHOJI +SHONE +SHOOK +SHOOL +SHOON +SHOOS +SHOOT +SHOPS +SHORE +SHORL +SHORN +SHORT +SHOTE +SHOTS +SHOTT +SHOUT +SHOVE +SHOWN +SHOWS +SHOWY +SHOYU +SHRED +SHREW +SHRIS +SHRUB +SHRUG +SHTIK +SHUCK +SHULN +SHULS +SHUNS +SHUNT +SHUSH +SHUTE +SHUTS +SHWAS +SHYER +SHYLY +SIALS +SIBBS +SIBYL +SICES +SICKO +SICKS +SIDED +SIDES +SIDHE +SIDLE +SIEGE +SIEUR +SIEVE +SIFTS +SIGHS +SIGHT +SIGIL +SIGLA +SIGMA +SIGNA +SIGNS +SIKAS +SIKER +SIKES +SILDS +SILEX +SILKS +SILKY +SILLS +SILLY +SILOS +SILTS +SILTY +SILVA +SIMAR +SIMAS +SIMPS +SINCE +SINES +SINEW +SINGE +SINGS +SINHS +SINKS +SINUS +SIPED +SIPES +SIRED +SIREE +SIREN +SIRES +SIRRA +SIRUP +SISAL +SISES +SISSY +SITAR +SITED +SITES +SITUP +SITUS +SIVER +SIXES +SIXMO +SIXTE +SIXTH +SIXTY +SIZAR +SIZED +SIZER +SIZES +SKAGS +SKALD +SKANK +SKATE +SKATS +SKEAN +SKEED +SKEEN +SKEES +SKEET +SKEGS +SKEIN +SKELL +SKELM +SKELP +SKENE +SKEPS +SKEWS +SKIDS +SKIED +SKIER +SKIES +SKIEY +SKIFF +SKILL +SKIMO +SKIMP +SKIMS +SKINK +SKINS +SKINT +SKIPS +SKIRL +SKIRR +SKIRT +SKITE +SKITS +SKIVE +SKOAL +SKORT +SKOSH +SKUAS +SKULK +SKULL +SKUNK +SKYED +SKYEY +SLABS +SLACK +SLAGS +SLAIN +SLAKE +SLAMS +SLANG +SLANK +SLANT +SLAPS +SLASH +SLATE +SLATS +SLATY +SLAVE +SLAWS +SLAYS +SLEDS +SLEEK +SLEEP +SLEET +SLEPT +SLEWS +SLICE +SLICK +SLIDE +SLIER +SLILY +SLIME +SLIMS +SLIMY +SLING +SLINK +SLIPE +SLIPS +SLIPT +SLITS +SLOBS +SLOES +SLOGS +SLOID +SLOJD +SLOMO +SLOOP +SLOPE +SLOPS +SLOSH +SLOTH +SLOTS +SLOWS +SLOYD +SLUBS +SLUED +SLUES +SLUFF +SLUGS +SLUMP +SLUMS +SLUNG +SLUNK +SLURB +SLURP +SLURS +SLUSH +SLUTS +SLYER +SLYLY +SLYPE +SMACK +SMALL +SMALT +SMARM +SMART +SMASH +SMAZE +SMEAR +SMEEK +SMELL +SMELT +SMERK +SMEWS +SMILE +SMIRK +SMITE +SMITH +SMOCK +SMOGS +SMOKE +SMOKY +SMOLT +SMOTE +SMURF +SMUSH +SMUTS +SNACK +SNAFU +SNAGS +SNAIL +SNAKE +SNAKY +SNAPS +SNARE +SNARF +SNARK +SNARL +SNASH +SNATH +SNAWS +SNEAK +SNEAP +SNECK +SNEDS +SNEER +SNELL +SNIBS +SNICK +SNIDE +SNIFF +SNIPE +SNIPS +SNITS +SNOBS +SNOGS +SNOOD +SNOOK +SNOOL +SNOOP +SNOOT +SNORE +SNORT +SNOTS +SNOUT +SNOWS +SNOWY +SNUBS +SNUCK +SNUFF +SNUGS +SNYES +SOAKS +SOAPS +SOAPY +SOARS +SOAVE +SOBAS +SOBER +SOCAS +SOCKO +SOCKS +SOCLE +SODAS +SODDY +SODIC +SODOM +SOFAR +SOFAS +SOFTA +SOFTS +SOFTY +SOGGY +SOILS +SOJAS +SOKES +SOKOL +SOLAN +SOLAR +SOLDI +SOLDO +SOLED +SOLEI +SOLES +SOLID +SOLON +SOLOS +SOLUM +SOLUS +SOLVE +SOMAN +SOMAS +SONAR +SONDE +SONES +SONGS +SONIC +SONLY +SONNY +SONSY +SOOEY +SOOKS +SOOTH +SOOTS +SOOTY +SOPHS +SOPHY +SOPOR +SOPPY +SORAS +SORBS +SORDS +SORED +SOREL +SORER +SORES +SORGO +SORNS +SORRY +SORTA +SORTS +SORUS +SOTHS +SOTOL +SOUGH +SOUKS +SOULS +SOUND +SOUPS +SOUPY +SOURS +SOUSE +SOUTH +SOWAR +SOWED +SOWER +SOYAS +SOYUZ +SOZIN +SPACE +SPACY +SPADE +SPADO +SPAED +SPAES +SPAHI +SPAIL +SPAIT +SPAKE +SPALE +SPALL +SPAMS +SPANG +SPANK +SPANS +SPARE +SPARK +SPARS +SPASM +SPATE +SPATS +SPAWN +SPAYS +SPAZZ +SPEAK +SPEAN +SPEAR +SPECK +SPECS +SPEED +SPEEL +SPEER +SPEIL +SPEIR +SPELL +SPELT +SPEND +SPENT +SPERM +SPEWS +SPICA +SPICE +SPICK +SPICS +SPICY +SPIED +SPIEL +SPIER +SPIES +SPIFF +SPIKE +SPIKS +SPIKY +SPILE +SPILL +SPILT +SPINA +SPINE +SPINS +SPINY +SPIRE +SPIRT +SPIRY +SPITE +SPITS +SPITZ +SPIVS +SPLAT +SPLAY +SPLIT +SPODE +SPOIL +SPOKE +SPOOF +SPOOK +SPOOL +SPOON +SPOOR +SPORE +SPORT +SPOTS +SPOUT +SPRAG +SPRAT +SPRAY +SPREE +SPRIG +SPRIT +SPROG +SPRUE +SPRUG +SPUDS +SPUED +SPUES +SPUME +SPUMY +SPUNK +SPURN +SPURS +SPURT +SPUTA +SQUAB +SQUAD +SQUAT +SQUAW +SQUEG +SQUIB +SQUID +STABS +STACK +STADE +STAFF +STAGE +STAGS +STAGY +STAID +STAIG +STAIN +STAIR +STAKE +STALE +STALK +STALL +STAMP +STAND +STANE +STANG +STANK +STAPH +STARE +STARK +STARS +START +STASH +STATE +STATS +STAVE +STAYS +STEAD +STEAK +STEAL +STEAM +STEED +STEEK +STEEL +STEEP +STEER +STEIN +STELA +STELE +STEMS +STENO +STENT +STEPS +STERE +STERN +STETS +STEWS +STEWY +STICH +STICK +STIED +STIES +STIFF +STILE +STILL +STILT +STIME +STIMY +STING +STINK +STINT +STIPE +STIRK +STIRP +STIRS +STOAE +STOAI +STOAS +STOAT +STOBS +STOCK +STOGY +STOIC +STOKE +STOLE +STOMA +STOMP +STONE +STONY +STOOD +STOOK +STOOL +STOOP +STOPE +STOPS +STOPT +STORE +STORK +STORM +STORY +STOSS +STOTS +STOTT +STOUP +STOUR +STOUT +STOVE +STOWP +STOWS +STRAP +STRAW +STRAY +STREP +STREW +STRIA +STRIP +STROP +STROW +STROY +STRUM +STRUT +STUBS +STUCK +STUDS +STUDY +STUFF +STULL +STUMP +STUMS +STUNG +STUNK +STUNS +STUNT +STUPA +STUPE +STURT +STYED +STYES +STYLE +STYLI +STYMY +SUAVE +SUBAH +SUBAS +SUBER +SUCKS +SUCKY +SUCRE +SUDDS +SUDOR +SUDSY +SUEDE +SUERS +SUETS +SUETY +SUGAR +SUGHS +SUING +SUINT +SUITE +SUITS +SULCI +SULFA +SULFO +SULKS +SULKY +SULLY +SULUS +SUMAC +SUMMA +SUMOS +SUMPS +SUNNA +SUNNS +SUNNY +SUNUP +SUPER +SUPES +SUPRA +SURAH +SURAL +SURAS +SURDS +SURER +SURFS +SURFY +SURGE +SURGY +SURLY +SURRA +SUSHI +SUTRA +SUTTA +SWABS +SWAGE +SWAGS +SWAIL +SWAIN +SWALE +SWAMI +SWAMP +SWAMY +SWANG +SWANK +SWANS +SWAPS +SWARD +SWARE +SWARF +SWARM +SWART +SWASH +SWATH +SWATS +SWAYS +SWEAR +SWEAT +SWEDE +SWEEP +SWEER +SWEET +SWELL +SWEPT +SWIFT +SWIGS +SWILL +SWIMS +SWINE +SWING +SWINK +SWIPE +SWIRL +SWISH +SWISS +SWITH +SWIVE +SWOBS +SWOON +SWOOP +SWOPS +SWORD +SWORE +SWORN +SWOTS +SWOUN +SWUNG +SYCEE +SYCES +SYKES +SYLIS +SYLPH +SYLVA +SYNCH +SYNCS +SYNOD +SYNTH +SYPHS +SYREN +SYRUP +SYSOP +TABBY +TABER +TABES +TABID +TABLA +TABLE +TABOO +TABOR +TABUN +TABUS +TACES +TACET +TACHE +TACHS +TACIT +TACKS +TACKY +TACOS +TACTS +TAELS +TAFFY +TAFIA +TAGUA +TAHRS +TAIGA +TAILS +TAINS +TAINT +TAJES +TAKAS +TAKEN +TAKER +TAKES +TAKIN +TALAR +TALAS +TALCS +TALER +TALES +TALKS +TALKY +TALLS +TALLY +TALON +TALUK +TALUS +TAMAL +TAMED +TAMER +TAMES +TAMIS +TAMMY +TAMPS +TANGA +TANGO +TANGS +TANGY +TANKA +TANKS +TANSY +TANTO +TAPAS +TAPED +TAPER +TAPES +TAPIR +TAPIS +TARDO +TARDY +TARED +TARES +TARGE +TARNS +TAROC +TAROK +TAROS +TAROT +TARPS +TARRE +TARRY +TARSI +TARTS +TARTY +TASKS +TASSE +TASTE +TASTY +TATAR +TATER +TATES +TATTY +TAUNT +TAUON +TAUPE +TAUTS +TAWED +TAWER +TAWIE +TAWNY +TAWSE +TAXED +TAXER +TAXES +TAXIS +TAXOL +TAXON +TAXUS +TAZZA +TAZZE +TEACH +TEAKS +TEALS +TEAMS +TEARS +TEARY +TEASE +TEATS +TECHS +TECHY +TECTA +TECUM +TEDDY +TEELS +TEEMS +TEENS +TEENY +TEETH +TEFFS +TEGGS +TEGUA +TEIID +TEIND +TELAE +TELCO +TELES +TELEX +TELIA +TELIC +TELLS +TELLY +TELOI +TELOS +TEMPI +TEMPO +TEMPS +TEMPT +TENCH +TENDS +TENDU +TENET +TENGE +TENIA +TENON +TENOR +TENSE +TENTH +TENTS +TENTY +TEPAL +TEPAS +TEPEE +TEPID +TEPOY +TERAI +TERCE +TERGA +TERMS +TERNE +TERNS +TERRA +TERRY +TERSE +TESLA +TESTA +TESTS +TESTY +TETHS +TETRA +TETRI +TEUCH +TEUGH +TEWED +TEXAS +TEXTS +THACK +THANE +THANK +THANX +THARM +THATS +THAWS +THEBE +THECA +THEES +THEFT +THEGN +THEIN +THEIR +THEME +THENS +THERE +THERM +THESE +THESP +THETA +THEWS +THEWY +THICK +THIEF +THIGH +THILL +THINE +THING +THINK +THINS +THIOL +THIRD +THIRL +THOLE +THONG +THORN +THORO +THORP +THOSE +THOUS +THRAW +THREE +THREW +THRIP +THROB +THROE +THROW +THRUM +THUDS +THUGS +THUJA +THUMB +THUMP +THUNK +THURL +THUYA +THWAP +THYME +THYMI +THYMY +TIARA +TIBIA +TICAL +TICKS +TIDAL +TIDED +TIDES +TIERS +TIFFS +TIGER +TIGHT +TIGON +TIKES +TIKIS +TIKKA +TILAK +TILDE +TILED +TILER +TILES +TILLS +TILTH +TILTS +TIMED +TIMER +TIMES +TIMID +TINCT +TINEA +TINED +TINES +TINGE +TINGS +TINNY +TINTS +TIPIS +TIPPY +TIPSY +TIRED +TIRES +TIRLS +TIROS +TITAN +TITER +TITHE +TITIS +TITLE +TITRE +TITTY +TIZZY +TOADS +TOADY +TOAST +TODAY +TODDY +TOEAS +TOFFS +TOFFY +TOFTS +TOFUS +TOGAE +TOGAS +TOGUE +TOILE +TOILS +TOITS +TOKAY +TOKED +TOKEN +TOKER +TOKES +TOLAN +TOLAR +TOLAS +TOLED +TOLES +TOLLS +TOLUS +TOLYL +TOMAN +TOMBS +TOMES +TOMMY +TONAL +TONDI +TONDO +TONED +TONER +TONES +TONEY +TONGA +TONGS +TONIC +TONNE +TONUS +TOOLS +TOONS +TOOTH +TOOTS +TOPAZ +TOPED +TOPEE +TOPER +TOPES +TOPHE +TOPHI +TOPHS +TOPIC +TOPIS +TOPOI +TOPOS +TOQUE +TORAH +TORAS +TORCH +TORCS +TORES +TORIC +TORII +TOROS +TOROT +TORRS +TORSE +TORSI +TORSK +TORSO +TORTA +TORTE +TORTS +TORUS +TOTAL +TOTED +TOTEM +TOTER +TOTES +TOTTY +TOUCH +TOUGH +TOURS +TOUSE +TOUTS +TOVES +TOWED +TOWEL +TOWER +TOWIE +TOWNS +TOWNY +TOXIC +TOXIN +TOYED +TOYER +TOYON +TOYOS +TRACE +TRACK +TRACT +TRADE +TRAGI +TRAIK +TRAIL +TRAIN +TRAIT +TRAMP +TRAMS +TRANK +TRANQ +TRANS +TRAPS +TRAPT +TRASH +TRASS +TRAVE +TRAWL +TRAYS +TREAD +TREAP +TREAT +TREED +TREEN +TREES +TREKS +TREND +TRESS +TRETS +TREWS +TREYS +TRIAC +TRIAD +TRIAL +TRIBE +TRIBS +TRICE +TRICK +TRIED +TRIER +TRIES +TRIGO +TRIGS +TRIKE +TRILL +TRIMS +TRINE +TRIOL +TRIOS +TRIPE +TRIPS +TRITE +TROAK +TROCK +TRODE +TROGS +TROIS +TROKE +TROLL +TROMP +TRONA +TRONE +TROOP +TROOZ +TROPE +TROTH +TROTS +TROUT +TROVE +TROWS +TROYS +TRUCE +TRUCK +TRUED +TRUER +TRUES +TRUGS +TRULL +TRULY +TRUMP +TRUNK +TRUSS +TRUST +TRUTH +TRYMA +TRYST +TSADE +TSADI +TSARS +TSKED +TSUBA +TUANS +TUBAE +TUBAL +TUBAS +TUBBY +TUBED +TUBER +TUBES +TUCKS +TUFAS +TUFFS +TUFTS +TUFTY +TULES +TULIP +TULLE +TUMID +TUMMY +TUMOR +TUMPS +TUNAS +TUNED +TUNER +TUNES +TUNGS +TUNIC +TUNNY +TUPIK +TUPLE +TUQUE +TURBO +TURDS +TURDY +TURFS +TURFY +TURKS +TURNS +TURPS +TUSHY +TUSKS +TUSKY +TUTEE +TUTOR +TUTTI +TUTTY +TUTUS +TUXES +TUYER +TWAES +TWAIN +TWANG +TWATS +TWEAK +TWEED +TWEEN +TWEET +TWERP +TWICE +TWIER +TWIGS +TWILL +TWINE +TWINK +TWINS +TWINY +TWIRL +TWIRP +TWIST +TWITS +TWIXT +TWYER +TYEES +TYERS +TYING +TYIYN +TYKES +TYNED +TYNES +TYPAL +TYPED +TYPES +TYPEY +TYPIC +TYPOS +TYPPS +TYRED +TYRES +TYROS +TYTHE +TZARS +UDDER +UDONS +UHLAN +UKASE +ULAMA +ULANS +ULCER +ULEMA +ULNAD +ULNAE +ULNAR +ULNAS +ULPAN +ULTRA +ULVAS +UMAMI +UMBEL +UMBER +UMBOS +UMBRA +UMIAC +UMIAK +UMIAQ +UMPED +UMPTY +UNAIS +UNAPT +UNARC +UNARM +UNARY +UNATE +UNAUS +UNBAN +UNBAR +UNBID +UNBOX +UNCAP +UNCIA +UNCLE +UNCOS +UNCOY +UNCUS +UNCUT +UNDEE +UNDER +UNDID +UNDUE +UNFED +UNFIT +UNFIX +UNGOT +UNHAT +UNHIP +UNHIT +UNIFY +UNION +UNITE +UNITS +UNITY +UNJAM +UNLAY +UNLED +UNLET +UNLIT +UNMAN +UNMAP +UNMET +UNMEW +UNMIX +UNPEG +UNPEN +UNPIN +UNRIG +UNRIP +UNSAY +UNSEE +UNSET +UNSEW +UNSEX +UNTIE +UNTIL +UNWED +UNWET +UNWIT +UNWON +UNZIP +UPBOW +UPBYE +UPDOS +UPDRY +UPEND +UPLIT +UPPED +UPPER +UPSET +URAEI +URARE +URARI +URASE +URATE +URBAN +URBIA +UREAL +UREAS +UREDO +UREIC +URGED +URGER +URGES +URIAL +URINE +URPED +URSAE +URSID +USAGE +USERS +USHER +USING +USNEA +USQUE +USUAL +USURP +USURY +UTERI +UTERO +UTILE +UTTER +UVEAL +UVEAS +UVULA +VACUA +VACUO +VAGAL +VAGUE +VAGUS +VAILS +VAIRS +VAKIL +VALES +VALET +VALID +VALOR +VALSE +VALUE +VALVE +VAMPS +VAMPY +VANDA +VANED +VANES +VANGS +VAPES +VAPID +VAPOR +VARAS +VARIA +VARIX +VARNA +VARUS +VARVE +VASAL +VASES +VASTS +VASTY +VATIC +VATUS +VAULT +VAUNT +VEALS +VEALY +VEENA +VEEPS +VEERS +VEERY +VEGAN +VEGES +VEGIE +VEILS +VEINS +VEINY +VELAR +VELDS +VELDT +VELUM +VENAE +VENAL +VENDS +VENGE +VENIN +VENOM +VENTS +VENUE +VENUS +VERBS +VERGE +VERSA +VERSE +VERSO +VERST +VERTS +VERTU +VERVE +VESTA +VESTS +VETCH +VEXED +VEXER +VEXES +VEXIL +VIALS +VIAND +VIBES +VICAR +VICED +VICES +VICHY +VIDEO +VIERS +VIEWS +VIEWY +VIGAS +VIGIA +VIGIL +VIGOR +VILER +VILLA +VILLE +VILLI +VILLS +VIMEN +VINAL +VINAS +VINCA +VINED +VINES +VINIC +VINOS +VINYL +VIOLA +VIOLS +VIPER +VIRAL +VIREO +VIRES +VIRGA +VIRID +VIRLS +VIRTU +VIRUS +VISAS +VISED +VISES +VISIT +VISOR +VISTA +VITAE +VITAL +VITAM +VITAS +VITRO +VITTA +VIVAS +VIVID +VIVRE +VIXEN +VIZIR +VIZOR +VOCAB +VOCAL +VOCES +VODKA +VODOU +VODUN +VOGIE +VOGUE +VOICE +VOIDS +VOILA +VOILE +VOLAR +VOLED +VOLES +VOLTA +VOLTE +VOLTI +VOLTS +VOLVA +VOMER +VOMIT +VOTED +VOTER +VOTES +VOUCH +VOWED +VOWEL +VOWER +VOXEL +VROOM +VROUW +VROWS +VUGGS +VUGGY +VUGHS +VULGO +VULVA +VYING +WACKE +WACKO +WACKS +WACKY +WADDY +WADED +WADER +WADES +WADIS +WAFER +WAFFS +WAFTS +WAGED +WAGER +WAGES +WAGON +WAHOO +WAIFS +WAILS +WAINS +WAIRS +WAIST +WAITS +WAIVE +WAKED +WAKEN +WAKER +WAKES +WALED +WALER +WALES +WALKS +WALLA +WALLS +WALLY +WALTZ +WAMES +WAMUS +WANDS +WANED +WANES +WANEY +WANKS +WANLY +WANNA +WANTA +WANTS +WARDS +WARED +WARES +WARKS +WARMS +WARNS +WARPS +WARTS +WARTY +WASHY +WASPS +WASPY +WASSA +WASTE +WASTS +WATAP +WATCH +WATER +WATSA +WATTS +WAUGH +WAUKS +WAULS +WAVED +WAVER +WAVES +WAVEY +WAWLS +WAXED +WAXEN +WAXER +WAXES +WAZOO +WEALD +WEALS +WEANS +WEARS +WEARY +WEAVE +WEBBY +WEBER +WECHT +WEDEL +WEDGE +WEDGY +WEEDS +WEEDY +WEEKS +WEENS +WEENY +WEEPS +WEEPY +WEEST +WEETS +WEFTS +WEIGH +WEIRD +WEIRS +WEKAS +WELCH +WELDS +WELLS +WELLY +WELSH +WELTS +WENCH +WENDS +WENNY +WESTS +WETLY +WHACK +WHALE +WHAMO +WHAMS +WHANG +WHAPS +WHARF +WHATS +WHAUP +WHEAL +WHEAT +WHEEE +WHEEL +WHEEN +WHEEP +WHELK +WHELM +WHELP +WHENS +WHERE +WHETS +WHEWS +WHEYS +WHICH +WHIDS +WHIFF +WHIGS +WHILE +WHIMS +WHINE +WHINS +WHINY +WHIPS +WHIPT +WHIRL +WHIRR +WHIRS +WHISH +WHISK +WHIST +WHITE +WHITS +WHITY +WHIZZ +WHOAS +WHOLE +WHOMP +WHOOF +WHOOO +WHOOP +WHOPS +WHORE +WHORL +WHORT +WHOSE +WHOSO +WHUMP +WHUPS +WICCA +WICKS +WIDDY +WIDEN +WIDER +WIDES +WIDOW +WIDTH +WIELD +WIFED +WIFES +WIFEY +WIFTY +WIGAN +WIGGY +WIGHT +WILCO +WILDS +WILED +WILES +WILLS +WILLY +WILTS +WIMPS +WIMPY +WINCE +WINCH +WINDS +WINDY +WINED +WINES +WINEY +WINGS +WINGY +WINKS +WINOS +WINZE +WIPED +WIPER +WIPES +WIRED +WIRER +WIRES +WIRRA +WISED +WISER +WISES +WISHA +WISPS +WISPY +WISTS +WITAN +WITCH +WITED +WITES +WITHE +WITHS +WITHY +WITTY +WIVED +WIVER +WIVES +WIZEN +WIZES +WOADS +WOALD +WODGE +WOFUL +WOKEN +WOLDS +WOLFS +WOMAN +WOMBS +WOMBY +WOMEN +WOMYN +WONKS +WONKY +WONTS +WOODS +WOODY +WOOED +WOOER +WOOFS +WOOLS +WOOLY +WOOPS +WOOSH +WOOZY +WORDS +WORDY +WORKS +WORLD +WORMS +WORMY +WORRY +WORSE +WORST +WORTH +WORTS +WOULD +WOUND +WOVEN +WOWED +WOWEE +WRACK +WRANG +WRAPS +WRAPT +WRATH +WREAK +WRECK +WRENS +WREST +WRICK +WRIED +WRIER +WRIES +WRING +WRIST +WRITE +WRITS +WRONG +WROTE +WROTH +WRUNG +WRYER +WRYLY +WURST +WUSHU +WUSSY +WYLED +WYLES +WYNDS +WYNNS +WYTED +WYTES +XEBEC +XENIA +XENIC +XENON +XERIC +XEROX +XERUS +XORED +XYLAN +XYLEM +XYLOL +XYLYL +XYSTI +XYSTS +YABBY +YACHT +YACKS +YAFFS +YAGER +YAGIS +YAHOO +YAIRD +YAMEN +YAMUN +YANGS +YANKS +YAPOK +YAPON +YARDS +YARER +YARNS +YAUDS +YAULD +YAUPS +YAWED +YAWEY +YAWLS +YAWNS +YAWNY +YAWPS +YCLAD +YEAHS +YEANS +YEARN +YEARS +YEAST +YECCH +YECHS +YECHY +YEGGS +YELKS +YELLA +YELLS +YELPS +YENTA +YENTE +YERBA +YERKS +YESES +YETIS +YETTS +YEUKS +YEUKY +YIELD +YIKES +YILLS +YINCE +YIPES +YIRDS +YIRRS +YIRTH +YLEMS +YOBBO +YOCKS +YODEL +YODHS +YODLE +YOGAS +YOGEE +YOGHS +YOGIC +YOGIN +YOGIS +YOKED +YOKEL +YOKES +YOLKS +YOLKY +YOMIM +YONIC +YONIS +YORES +YOUNG +YOURN +YOURS +YOUSE +YOUTH +YOWED +YOWES +YOWIE +YOWLS +YOYOS +YUANS +YUCAS +YUCCA +YUCCH +YUCKS +YUCKY +YUGAS +YUKKY +YULAN +YULES +YUMMY +YUPON +YUPPY +YURTA +YURTS +ZAIRE +ZAMIA +ZANZA +ZAPPY +ZARFS +ZAXES +ZAYIN +ZAZEN +ZEALS +ZEBEC +ZEBRA +ZEBUS +ZEINS +ZERKS +ZEROS +ZESTS +ZESTY +ZETAS +ZIBET +ZILCH +ZILLS +ZINCS +ZINCY +ZINEB +ZINES +ZINGS +ZINGY +ZINKY +ZIPPY +ZIRAM +ZITIS +ZIZIT +ZLOTE +ZLOTY +ZOEAE +ZOEAL +ZOEAS +ZOMBI +ZONAE +ZONAL +ZONED +ZONER +ZONES +ZONKS +ZOOEY +ZOOID +ZOOKS +ZOOMS +ZOONS +ZOOTY +ZORIL +ZORIS +ZOUKS +ZOWIE +ZUZIM +ZYMES diff --git a/common/src/main/resources/words.txt b/common/src/main/resources/words.txt new file mode 100644 index 0000000..74cb4e8 --- /dev/null +++ b/common/src/main/resources/words.txt @@ -0,0 +1,4651 @@ +ABACI +ABACK +ABASH +ABATE +ABBEY +ABBOT +ABETS +ABHOR +ABIDE +ABLED +ABLER +ABODE +ABORT +ABOUT +ABOVE +ABUSE +ABUZZ +ABYSS +ACHED +ACHES +ACHOO +ACIDS +ACING +ACMES +ACNED +ACNES +ACORN +ACRES +ACRID +ACTED +ACTOR +ACUTE +ADAGE +ADAPT +ADDED +ADDER +ADEPT +ADIEU +ADIOS +ADLIB +ADMIT +ADOBE +ADOPT +ADORE +ADORN +ADULT +AFFIX +AFIRE +AFOOT +AFOUL +AFTER +AGAIN +AGAPE +AGAVE +AGENT +AGILE +AGING +AGLOW +AGONY +AGREE +AGUES +AHEAD +AHOLD +AHOYS +AIDED +AIDES +AILED +AIMED +AIMER +AIRED +AIRER +AISLE +ALARM +ALBUM +ALDER +ALERT +ALGAE +ALIAS +ALIBI +ALIEN +ALIGN +ALIKE +ALIVE +ALLAY +ALLEY +ALLOT +ALLOW +ALLOY +ALOES +ALOFT +ALOHA +ALONE +ALONG +ALOOF +ALOUD +ALPHA +ALTAR +ALTER +ALTOS +AMASS +AMAZE +AMBER +AMBLE +AMEBA +AMEND +AMIGO +AMINO +AMISS +AMITY +AMONG +AMPED +AMPLE +AMPLY +AMUCK +AMUSE +ANGEL +ANGER +ANGLE +ANGRY +ANGST +ANKLE +ANNEX +ANNOY +ANNUL +ANODE +ANTES +ANTIC +ANTSY +ANVIL +AORTA +APART +APERS +APHID +APING +APISH +APNEA +APPLE +APPLY +APRON +APTLY +AQUAS +ARBOR +AREAS +ARENA +ARGON +ARGUE +ARIAS +ARISE +ARMED +ARMOR +AROMA +AROSE +ARRAY +ARROW +ARSES +ARSON +ARTSY +ASCOT +ASHEN +ASHES +ASIDE +ASKED +ASKER +ASKEW +ASSAY +ASSED +ASSES +ASSET +ASTER +ASTIR +ASTRO +ATILT +ATLAS +ATOLL +ATOMS +ATONE +ATRIA +ATTIC +AUDIO +AUDIT +AUGER +AUGHT +AUGUR +AUNTS +AURAE +AURAL +AURAS +AUTOS +AVAIL +AVANT +AVAST +AVERS +AVERT +AVIAN +AVOID +AVOWS +AWAIT +AWAKE +AWARD +AWARE +AWASH +AWFUL +AWING +AWOKE +AXELS +AXING +AXIOM +AXLED +AXLES +AXONS +AZURE +BABEL +BABES +BACKS +BACON +BADGE +BADLY +BAGEL +BAGGY +BAILS +BAITS +BAKED +BAKER +BAKES +BALDS +BALDY +BALED +BALER +BALES +BALKS +BALKY +BALLS +BALLY +BALMS +BALMY +BALSA +BANAL +BANDS +BANDY +BANES +BANGS +BANJO +BANKS +BARBS +BARDS +BARED +BARER +BARES +BARFS +BARGE +BARKS +BARKY +BARNS +BARON +BASAL +BASED +BASER +BASES +BASIC +BASIL +BASIN +BASIS +BASKS +BASTE +BATCH +BATED +BATES +BATHE +BATHS +BATON +BATTY +BAWDY +BAWLS +BAYED +BAYOU +BAZAR +BEACH +BEADS +BEADY +BEAKS +BEAKY +BEAMS +BEAMY +BEANO +BEANS +BEARD +BEARS +BEAST +BEATS +BEAUS +BEECH +BEEFS +BEEFY +BEEPS +BEERS +BEETS +BEFIT +BEGAN +BEGAT +BEGET +BEGIN +BEGOT +BEGUN +BEIGE +BEING +BELAY +BELCH +BELIE +BELLE +BELLS +BELLY +BELOW +BELTS +BENCH +BENDS +BENTS +BERET +BERGS +BERRY +BERTH +BESET +BESTS +BETAS +BEVEL +BIBLE +BIDDY +BIDED +BIDER +BIDES +BIDET +BIERS +BIGGY +BIGHT +BIGOT +BIKED +BIKER +BIKES +BILES +BILGE +BILGY +BILKS +BILLS +BILLY +BIMBO +BINDS +BINGE +BINGO +BIOME +BIPED +BIPOD +BIRCH +BIRDS +BIRTH +BISON +BITCH +BITER +BITES +BITSY +BITTY +BLABS +BLACK +BLADE +BLAHS +BLAME +BLAND +BLANK +BLARE +BLAST +BLATS +BLAZE +BLEAK +BLEAT +BLEED +BLEND +BLESS +BLIMP +BLIND +BLINK +BLIPS +BLISS +BLITZ +BLOAT +BLOBS +BLOCK +BLOCS +BLOKE +BLOND +BLOOD +BLOOM +BLOTS +BLOWN +BLOWS +BLUED +BLUER +BLUES +BLUFF +BLUNT +BLURB +BLURS +BLURT +BLUSH +BOARD +BOARS +BOAST +BOATS +BOBBY +BOCCE +BOCCI +BODED +BODES +BOGEY +BOGIE +BOGUS +BOILS +BOLTS +BOMBS +BONDS +BONED +BONER +BONES +BONGO +BONGS +BONKS +BONUS +BOOBS +BOOBY +BOOED +BOOKS +BOOMS +BOONS +BOORS +BOOST +BOOTH +BOOTS +BOOTY +BOOZE +BORED +BORES +BORNE +BORON +BOSOM +BOSON +BOSSY +BOTCH +BOUGH +BOUND +BOUTS +BOWED +BOWEL +BOWER +BOWLS +BOXED +BOXER +BOXES +BOZOS +BRACE +BRAGS +BRAID +BRAIN +BRAKE +BRAND +BRASH +BRASS +BRATS +BRAVE +BRAVO +BRAWL +BRAWN +BRAYS +BREAD +BREAK +BREED +BREWS +BRIBE +BRICK +BRIDE +BRIEF +BRIES +BRIGS +BRIMS +BRINE +BRING +BRINK +BRISK +BROAD +BROIL +BROKE +BROOD +BROOK +BROOM +BROTH +BROWN +BROWS +BRUIN +BRUSH +BRUTE +BUCKS +BUDDY +BUDGE +BUFFS +BUGGY +BUGLE +BUILD +BUILT +BULBS +BULGE +BULGY +BULKS +BULKY +BULLS +BUMPS +BUMPY +BUNCH +BUNKS +BUNNY +BUNTS +BUOYS +BURGS +BURLY +BURNS +BURNT +BURPS +BURST +BUSED +BUSES +BUSHY +BUSTS +BUSTY +BUTTE +BUTTS +BUXOM +BUYER +BUZZY +BYLAW +BYTES +BYWAY +CABAL +CABBY +CABIN +CABLE +CACHE +CACTI +CADDY +CADET +CADRE +CAFES +CAGED +CAGER +CAGES +CAGEY +CAKED +CAKES +CALKS +CALLS +CALMS +CALVE +CALYX +CAMEL +CAMEO +CAMPS +CAMPY +CANAL +CANDY +CANED +CANES +CANNY +CANOE +CANON +CANTS +CAPED +CAPER +CAPES +CAPON +CARAT +CARDS +CARED +CARER +CARES +CARET +CARGO +CAROL +CARPS +CARRY +CARTE +CARTS +CARVE +CASAS +CASED +CASES +CASKS +CASTE +CASTS +CATCH +CATER +CATTY +CAULK +CAUSE +CAVED +CAVES +CAWED +CEASE +CEDAR +CEDED +CEDER +CEDES +CELLO +CELLS +CENTS +CHAFE +CHAFF +CHAIN +CHAIR +CHALK +CHAMP +CHANT +CHAOS +CHAPS +CHARM +CHARS +CHART +CHASE +CHASM +CHATS +CHEAP +CHEAT +CHECK +CHEEK +CHEEP +CHEER +CHEFS +CHESS +CHEST +CHEWS +CHEWY +CHICK +CHIDE +CHIEF +CHILD +CHILI +CHILL +CHIME +CHIMP +CHINA +CHINK +CHINS +CHIPS +CHIRP +CHITS +CHIVE +CHOCK +CHOIR +CHOKE +CHOMP +CHOPS +CHORD +CHORE +CHOSE +CHOWS +CHUCK +CHUGS +CHUMP +CHUMS +CHUNK +CHURL +CHURN +CHUTE +CIDER +CIGAR +CILIA +CINCH +CIRCA +CITED +CITES +CIVIC +CIVIL +CLACK +CLADS +CLAIM +CLAMP +CLAMS +CLANG +CLANK +CLANS +CLAPS +CLASH +CLASP +CLASS +CLAWS +CLAYS +CLEAN +CLEAR +CLEAT +CLEFS +CLEFT +CLERK +CLICK +CLIFF +CLIMB +CLING +CLIPS +CLOAK +CLOCK +CLOGS +CLOMP +CLONE +CLOSE +CLOTH +CLOTS +CLOUD +CLOUT +CLOVE +CLOWN +CLOYS +CLUBS +CLUCK +CLUED +CLUES +CLUMP +CLUNG +CLUNK +COACH +COALS +COAST +COATS +COBRA +COCKS +COCKY +COCOA +CODED +CODER +CODES +CODEX +COEDS +COIFS +COILS +COINS +COKED +COKES +COLAS +COLDS +COLON +COLOR +COLTS +COMAS +COMBO +COMBS +COMER +COMES +COMET +COMFY +COMIC +COMMA +CONCH +CONDO +CONED +CONES +CONEY +CONIC +CONKS +COOCH +COOED +COOKS +COOKY +COOLS +COONS +COOPS +COOTS +COPED +COPER +COPES +CORAL +CORDS +CORDY +CORED +CORER +CORES +CORGI +CORKS +CORKY +CORNS +CORNY +CORPS +COSET +COSTA +COSTS +COTES +COTTA +COUCH +COUGH +COULD +COUNT +COUPE +COUPS +COURT +COUTH +COVEN +COVER +COVES +COVET +COWED +COWER +COYER +COYLY +CRABS +CRACK +CRAFT +CRAGS +CRAMP +CRAMS +CRANE +CRANK +CRAPS +CRASH +CRASS +CRATE +CRAVE +CRAWL +CRAWS +CRAZE +CRAZY +CREAK +CREAM +CREDO +CREED +CREEK +CREEP +CREME +CREPE +CREPT +CREST +CREWS +CRIBS +CRICK +CRIED +CRIER +CRIES +CRIME +CRIMP +CRINK +CRISP +CRITS +CROAK +CROCK +CROCS +CROFT +CRONE +CRONY +CROOK +CROON +CROPS +CROSS +CROUP +CROWD +CROWN +CROWS +CRUDE +CRUDS +CRUEL +CRUET +CRUMB +CRUMP +CRUSH +CRUST +CRYPT +CUBBY +CUBED +CUBER +CUBES +CUBIC +CUBIT +CUFFS +CUING +CUKES +CULLS +CULTS +CUMIN +CUNTS +CUPID +CURBS +CURDS +CURED +CURER +CURES +CURLS +CURLY +CURRY +CURSE +CURVE +CURVY +CUSHY +CUSPS +CUSPY +CUTER +CUTIE +CYCLE +CYNIC +CYSTS +CZARS +DADDY +DAILY +DAIRY +DAISY +DALLY +DAMES +DAMNS +DAMPS +DANCE +DANDY +DARED +DARER +DARES +DARKS +DARTS +DASHY +DATED +DATER +DATES +DATUM +DAUNT +DAWNS +DAZED +DAZES +DEALS +DEALT +DEANS +DEARS +DEATH +DEBIT +DEBTS +DEBUG +DEBUT +DECAF +DECAL +DECAY +DECKS +DECOR +DECOY +DECRY +DEEDS +DEEMS +DEEPS +DEFER +DEIFY +DEIGN +DEISM +DEIST +DEITY +DELAY +DELIS +DELTA +DELVE +DEMIT +DEMON +DEMOS +DEMUR +DENIM +DENSE +DENTS +DEPOT +DEPTH +DERBY +DESKS +DETER +DEUCE +DEVIL +DIALS +DIARY +DICED +DICER +DICES +DICEY +DICKS +DIETS +DIGIT +DIKES +DILDO +DILLS +DIMES +DIMLY +DINAR +DINED +DINER +DINES +DINGO +DINGS +DINGY +DIRER +DIRTS +DIRTY +DISCO +DISCS +DISKS +DITCH +DITTO +DIVAS +DIVED +DIVER +DIVES +DIVOT +DIVVY +DIZZY +DOCKS +DODGE +DODGY +DODOS +DOERS +DOGGY +DOGMA +DOING +DOLCE +DOLED +DOLES +DOLLS +DOLTS +DOMED +DOMES +DONNA +DONOR +DONUT +DOOMS +DOORS +DOOZY +DOPED +DOPER +DOPES +DOPEY +DORKS +DORKY +DORMS +DOSED +DOSER +DOSES +DOTED +DOTER +DOTES +DOTTY +DOUBT +DOUGH +DOUSE +DOVES +DOWNS +DOWNY +DOWRY +DOZED +DOZEN +DOZER +DOZES +DRABS +DRAFT +DRAGS +DRAIN +DRAMA +DRANK +DRAPE +DRAWL +DRAWN +DRAWS +DREAD +DREAM +DREAR +DREGS +DRESS +DRIED +DRIER +DRIES +DRIFT +DRILL +DRINK +DRIPS +DRIVE +DROID +DROLL +DRONE +DROOL +DROOP +DROPS +DROVE +DROWN +DRUBS +DRUGS +DRUID +DRUMS +DRUNK +DRYER +DRYLY +DUALS +DUCAT +DUCKS +DUCTS +DUDES +DUELS +DUETS +DUKES +DULLS +DULLY +DUMMY +DUMPS +DUMPY +DUNCE +DUNES +DUNGS +DUNKS +DUPED +DUPER +DUPES +DUSKS +DUSKY +DUSTS +DUSTY +DWARF +DWEEB +DWELL +DWELT +DYERS +DYING +EAGER +EAGLE +EARLS +EARLY +EARNS +EARTH +EASED +EASEL +EASES +EATEN +EATER +EAVES +EBBED +EBONY +ECHOS +EDGED +EDGER +EDGES +EDICT +EDIFY +EDITS +EERIE +EGRET +EIGHT +EJECT +EKING +ELANS +ELATE +ELBOW +ELDER +ELECT +ELEGY +ELFIN +ELIDE +ELITE +ELOPE +ELUDE +ELVES +EMAIL +EMBED +EMBER +EMCEE +EMIRS +EMITS +EMOTE +EMPTY +ENACT +ENDED +ENDER +ENDOW +ENEMA +ENEMY +ENJOY +ENNUI +ENSUE +ENTER +ENTRY +ENVOY +EPEES +EPICS +EPOCH +EPSOM +EQUAL +EQUIP +ERASE +ERECT +ERODE +ERRED +ERROR +ERUPT +ESSAY +ESSES +ETHER +ETHIC +ETHOS +ETHYL +ETUDE +EVADE +EVENS +EVENT +EVERY +EVICT +EVILS +EVOKE +EXACT +EXALT +EXAMS +EXCEL +EXERT +EXILE +EXIST +EXITS +EXPEL +EXPOS +EXTOL +EXTRA +EXUDE +EYERS +EYING +FABLE +FACED +FACES +FACET +FACIE +FACTO +FACTS +FADED +FADER +FADES +FAILS +FAINT +FAIRS +FAIRY +FAITH +FAKED +FAKER +FAKES +FALLS +FALSE +FAMED +FAMES +FANCY +FANGS +FANNY +FARCE +FARED +FARES +FARMS +FARTS +FASTS +FATAL +FATED +FATES +FATSO +FATTY +FATWA +FAULT +FAUNA +FAVOR +FAWNS +FAXED +FAXER +FAXES +FAZED +FAZES +FEARS +FEAST +FEATS +FECAL +FECES +FEEDS +FEELS +FEIGN +FEINT +FEIST +FELLA +FELLS +FELON +FELTS +FEMME +FEMUR +FENCE +FENDS +FERAL +FERNS +FERRY +FETAL +FETCH +FETES +FETID +FETUS +FEUDS +FEVER +FEWER +FIATS +FIBER +FIBRE +FIEFS +FIELD +FIEND +FIERY +FIFES +FIFTH +FIFTY +FIGHT +FILCH +FILED +FILER +FILES +FILET +FILLS +FILMS +FILMY +FILTH +FINAL +FINCH +FINDS +FINED +FINER +FINES +FIRED +FIRES +FIRMS +FIRST +FIRTH +FISHY +FISTS +FIVES +FIXED +FIXER +FIXES +FIZZY +FJORD +FLABS +FLACK +FLAGS +FLAIL +FLAIR +FLAKE +FLAKS +FLAKY +FLAME +FLAMS +FLANK +FLAPS +FLARE +FLASH +FLASK +FLATS +FLAWS +FLAYS +FLEAS +FLECK +FLEES +FLEET +FLESH +FLICK +FLICS +FLIED +FLIER +FLIES +FLING +FLINT +FLIPS +FLIRT +FLITS +FLOAT +FLOCK +FLOES +FLOGS +FLOOD +FLOOR +FLOPS +FLORA +FLOSS +FLOUR +FLOUT +FLOWN +FLOWS +FLUBS +FLUES +FLUFF +FLUID +FLUKE +FLUME +FLUNG +FLUNK +FLUSH +FLUTE +FLYER +FOALS +FOAMS +FOAMY +FOCAL +FOCUS +FOGEY +FOGGY +FOILS +FOLDS +FOLIA +FOLIO +FOLKS +FOLKY +FOLLY +FONDU +FONTS +FOODS +FOOLS +FOOTS +FORAY +FORCE +FORDS +FORES +FORGE +FORGO +FORKS +FORMS +FORTE +FORTH +FORTS +FORTY +FORUM +FOULS +FOUND +FOURS +FOWLS +FOXED +FOXES +FOYER +FRAIL +FRAME +FRANC +FRANK +FRATS +FRAUD +FRAYS +FREAK +FREED +FREER +FREES +FRESH +FRETS +FRIAR +FRIED +FRIER +FRIES +FRIGS +FRILL +FRISK +FRIZZ +FROGS +FROND +FRONT +FROST +FROWN +FROZE +FRUIT +FRYER +FUCKS +FUDGE +FUDGY +FUELS +FULLS +FULLY +FUMED +FUMES +FUNDS +FUNGI +FUNKS +FUNKY +FUNNY +FURLS +FUROR +FURRY +FUSED +FUSES +FUSSY +FUZED +FUZES +FUZZY +GABLE +GAFFE +GAGES +GAILY +GAINS +GAITS +GALAS +GALES +GALLS +GAMED +GAMER +GAMES +GAMMA +GAMUT +GANGS +GAPED +GAPER +GAPES +GAPPY +GARBS +GASES +GASPS +GASSY +GATED +GATES +GATOR +GAUDY +GAUGE +GAUNT +GAUZE +GAVEL +GAWKS +GAWKY +GAYER +GAYLY +GAZED +GAZER +GAZES +GEARS +GECKO +GEEKS +GEESE +GENES +GENIE +GENRE +GENTS +GENUS +GEODE +GERMS +GHOST +GHOUL +GIANT +GIDDY +GIFTS +GILDS +GILLS +GIMPS +GIMPY +GIRDS +GIRLS +GIRLY +GIRTH +GISTS +GIVEN +GIVER +GIVES +GIZMO +GLADE +GLAND +GLARE +GLASS +GLAZE +GLEAM +GLEAN +GLENS +GLIDE +GLINT +GLOAT +GLOBE +GLOBS +GLOOM +GLORY +GLOSS +GLOVE +GLOWS +GLUED +GLUES +GLUTS +GLYPH +GNARL +GNASH +GNATS +GNAWS +GNOME +GOADS +GOALS +GOATS +GODLY +GOERS +GOING +GOLDS +GOLEM +GOLFS +GOLLY +GONER +GONGS +GOODS +GOODY +GOOEY +GOOFS +GOOFY +GOOKS +GOOKY +GOONS +GOONY +GOOSE +GORED +GORES +GORGE +GOTHS +GOUDA +GOUGE +GOURD +GOUTS +GOWNS +GRABS +GRACE +GRADE +GRADS +GRAFT +GRAIL +GRAIN +GRAMS +GRAND +GRANT +GRAPE +GRAPH +GRAPY +GRASP +GRASS +GRATE +GRAVE +GRAVY +GRAYS +GRAZE +GREAT +GREED +GREEN +GREET +GREYS +GRIDS +GRIEF +GRIFT +GRILL +GRIME +GRIMY +GRIND +GRINS +GRIPE +GRIPS +GRITS +GROAN +GROGS +GROIN +GROOM +GROPE +GROSS +GROUP +GROUT +GROVE +GROWL +GROWN +GROWS +GRUBS +GRUEL +GRUFF +GRUMP +GRUNT +GUANO +GUARD +GUAVA +GUESS +GUEST +GUIDE +GUILD +GUILE +GUILT +GUISE +GULAG +GULCH +GULFS +GULLS +GULPS +GUMBO +GUMMY +GUPPY +GURUS +GUSHY +GUSTS +GUSTY +GUTSY +GYPSY +GYROS +HABIT +HACKS +HAIKU +HAILS +HAIRS +HAIRY +HALED +HALER +HALES +HALLS +HALOS +HALTS +HALVE +HANDS +HANDY +HANGS +HANKY +HAPLY +HAPPY +HARDY +HAREM +HARES +HARKS +HARMS +HARPS +HARPY +HARRY +HARSH +HARTS +HASTE +HASTY +HATCH +HATED +HATER +HATES +HAULS +HAUNT +HAVEN +HAVES +HAVOC +HAWED +HAWKS +HAZED +HAZEL +HAZES +HEADS +HEADY +HEALS +HEAPS +HEARD +HEARS +HEART +HEATH +HEATS +HEAVE +HEAVY +HEDGE +HEEDS +HEELS +HEFTS +HEFTY +HEIRS +HEIST +HELIX +HELLO +HELLS +HELMS +HELPS +HEMPS +HENCE +HENNA +HERBS +HERDS +HERON +HERTZ +HEWED +HEWER +HEXED +HEXER +HEXES +HICKS +HIDER +HIDES +HIGHS +HIKED +HIKER +HIKES +HILLS +HILLY +HILTS +HINDS +HINGE +HINTS +HIPPO +HIPPY +HIRED +HIRER +HIRES +HITCH +HIVED +HIVES +HOAGY +HOARD +HOBBY +HOBOS +HOCKS +HOCUS +HOIST +HOKEY +HOLDS +HOLED +HOLES +HOLEY +HOLLY +HOMED +HOMER +HOMES +HOMEY +HONED +HONES +HONEY +HONKS +HONKY +HONOR +HOODS +HOOEY +HOOFS +HOOKS +HOOKY +HOOPS +HOOTS +HOPED +HOPER +HOPES +HORDE +HORNS +HORNY +HORSE +HOSED +HOSES +HOSTS +HOTEL +HOTLY +HOUND +HOURS +HOUSE +HOVEL +HOVER +HOWDY +HOWLS +HUFFS +HUFFY +HUGER +HULAS +HULKS +HULKY +HULLS +HUMAN +HUMID +HUMOR +HUMPS +HUMPY +HUMUS +HUNCH +HUNKS +HUNKY +HUNTS +HURLS +HURLY +HURRY +HURTS +HUSKS +HUSKY +HYENA +HYING +HYMEN +HYMNS +HYPED +HYPER +HYPES +IAMBS +ICERS +ICIER +ICILY +ICING +ICONS +IDEAL +IDEAS +IDIOM +IDIOT +IDLED +IDLER +IDLES +IDOLS +IDYLL +IDYLS +IGLOO +IMAGE +IMAMS +IMBED +IMBUE +IMPEL +IMPLY +INANE +INCUR +INDEX +INDIE +INEPT +INERT +INFER +INFIX +INFRA +INGOT +INKED +INLAY +INLET +INNER +INPUT +INSET +INTER +INTRA +INTRO +IONIC +IOTAS +IRATE +IRKED +IRONS +IRONY +ISLES +ISLET +ISSUE +ITCHY +ITEMS +IVIED +IVIES +IVORY +JACKS +JADED +JADES +JAGGY +JAILS +JAKES +JAMMY +JANES +JAPAN +JAUNT +JAWED +JAZZY +JEANS +JEEPS +JEERS +JELLO +JELLY +JERKS +JERKY +JESTS +JETTY +JEWEL +JIBED +JIBER +JIBES +JIFFS +JIFFY +JIHAD +JILTS +JINGO +JINKS +JIVED +JIVES +JOCKS +JOEYS +JOHNS +JOINS +JOINT +JOIST +JOKED +JOKER +JOKES +JOLLY +JOLTS +JOULE +JOUST +JOYED +JUDGE +JUICE +JUICY +JUKES +JULEP +JUMBO +JUMPS +JUMPY +JUNKS +JUNKY +JUROR +JUTES +KABOB +KALES +KAPPA +KAPUT +KARAT +KARMA +KAYAK +KAZOO +KEBAB +KEBOB +KEELS +KEEPS +KELPS +KEYED +KHAKI +KICKS +KILLS +KILNS +KILOS +KILTS +KINDS +KINGS +KINKS +KINKY +KIOSK +KITED +KITES +KITTY +KIWIS +KNACK +KNAVE +KNEAD +KNEED +KNEEL +KNEES +KNELL +KNELT +KNIFE +KNITS +KNOBS +KNOCK +KNOLL +KNOTS +KNOWN +KNOWS +KOALA +KOOKS +KOOKY +KRILL +KUDOS +LABEL +LABIA +LABOR +LACED +LACES +LACKS +LADEN +LADLE +LAGER +LAIRS +LAITY +LAKER +LAKES +LAMAS +LAMBS +LAMER +LAMPS +LANCE +LANDS +LANES +LANKY +LAPEL +LAPSE +LARDS +LARGE +LARKS +LARVA +LASER +LASSO +LASTS +LATCH +LATER +LATEX +LATHE +LAUDS +LAUGH +LAVED +LAVER +LAVES +LAWNS +LAXER +LAYER +LAYUP +LAZED +LAZES +LEACH +LEADS +LEAFS +LEAFY +LEAKS +LEAKY +LEANS +LEANT +LEAPS +LEAPT +LEARN +LEASE +LEASH +LEAST +LEAVE +LEDGE +LEECH +LEEKS +LEERS +LEERY +LEFTS +LEFTY +LEGAL +LEGGY +LEMMA +LEMON +LEMUR +LENDS +LEPER +LEVEE +LEVEL +LEVER +LIARS +LIBEL +LIBRA +LICIT +LICKS +LIEGE +LIENS +LIFER +LIFTS +LIGHT +LIKED +LIKEN +LIKER +LIKES +LILAC +LILTS +LIMBO +LIMBS +LIMES +LIMEY +LIMIT +LIMOS +LIMPS +LINED +LINEN +LINER +LINES +LINGO +LINKS +LINTS +LINTY +LIONS +LIPID +LISPS +LISTS +LITHE +LITRE +LIVED +LIVEN +LIVER +LIVES +LIVID +LLAMA +LOADS +LOAFS +LOAMS +LOAMY +LOANS +LOATH +LOBED +LOBES +LOCAL +LOCHS +LOCKS +LOCUS +LODES +LODGE +LOFTS +LOFTY +LOGES +LOGGY +LOGIC +LOGIN +LOGOS +LOINS +LOLLS +LONER +LONGS +LOOKS +LOOKY +LOOMS +LOONS +LOONY +LOOPS +LOOPY +LOOSE +LOOTS +LOPED +LOPER +LOPES +LOPPY +LORDS +LORDY +LORES +LOSER +LOSES +LOSSY +LOTTO +LOTUS +LOUSE +LOUSY +LOUTS +LOVED +LOVER +LOVES +LOWER +LOWLY +LOXES +LOYAL +LUBES +LUCID +LUCKS +LUCKY +LULLS +LUMPS +LUMPY +LUNAR +LUNCH +LUNGE +LUNGS +LUPUS +LURCH +LURED +LURER +LURES +LURID +LURKS +LUSTS +LUSTY +LUTES +LYING +LYMPH +LYNCH +LYRES +LYRIC +MACAW +MACED +MACER +MACES +MACHO +MACRO +MADAM +MADLY +MAFIA +MAGIC +MAGMA +MAGNA +MAIDS +MAILS +MAIMS +MAIZE +MAJOR +MAKER +MAKES +MALES +MALLS +MALTS +MAMAS +MANED +MANES +MANGE +MANGO +MANGY +MANIA +MANIC +MANLY +MANOR +MANSE +MAPLE +MARCH +MARES +MARKS +MARRY +MARSH +MARTS +MASHY +MASKS +MASON +MASSE +MASTS +MATCH +MATED +MATER +MATES +MATEY +MATHS +MATTE +MAULS +MAVEN +MAXIM +MAYBE +MAYOR +MAZED +MAZES +MEADS +MEALS +MEALY +MEANS +MEANT +MEANY +MEATS +MEATY +MECCA +MEDAL +MEDIA +MEDIC +MEETS +MELEE +MELON +MELTS +MEMES +MEMOS +MENDS +MENUS +MEOWS +MERCY +MERGE +MERIT +MERRY +MESAS +MESON +MESSY +METAL +METED +METER +METES +METRO +MEWED +MICRO +MIDST +MIGHT +MILES +MILKS +MILKY +MILLS +MIMED +MIMER +MIMES +MIMIC +MINCE +MINDS +MINED +MINER +MINES +MINIS +MINKS +MINOR +MINTS +MINUS +MIRED +MIRES +MIRTH +MISER +MISSY +MISTS +MISTY +MITES +MIXED +MIXER +MIXES +MOANS +MOATS +MOCHA +MOCKS +MODAL +MODEL +MODEM +MODES +MOGUL +MOIST +MOLAR +MOLDS +MOLDY +MOLES +MOMMY +MONEY +MONKS +MONTH +MOOCH +MOODS +MOODY +MOOED +MOONS +MOORS +MOOSE +MOPED +MOPER +MOPES +MORAL +MORAY +MORNS +MORON +MORPH +MOSEY +MOSSY +MOTEL +MOTES +MOTHS +MOTIF +MOTOR +MOTTO +MOUND +MOUNT +MOURN +MOUSE +MOUTH +MOVED +MOVER +MOVES +MOVIE +MOWED +MOWER +MUCKS +MUCKY +MUCUS +MUDDY +MUFFS +MUGGY +MULCH +MULES +MULLS +MUMBO +MUMMY +MUMPS +MUNCH +MURAL +MURKS +MURKY +MUSED +MUSER +MUSES +MUSHY +MUSIC +MUSKS +MUSKY +MUSTS +MUSTY +MUTED +MUTER +MUTES +MUTTS +MYRRH +MYTHS +NACHO +NADIR +NAILS +NAIVE +NAKED +NAMED +NAMER +NAMES +NANNY +NAPES +NASAL +NASTY +NATAL +NAVAL +NAVEL +NAVES +NEARS +NECKS +NEEDS +NEEDY +NEIGH +NERDS +NERDY +NERVE +NESTS +NEVER +NEWER +NEWLY +NEWTS +NEXUS +NICER +NICHE +NIECE +NIFTY +NIGHT +NINES +NINJA +NINTH +NIPPY +NITRO +NITTY +NIXED +NIXES +NOBLE +NOBLY +NODAL +NODES +NOISE +NOISY +NOMAD +NONCE +NOOKS +NOONS +NOOSE +NORMS +NORTH +NOSES +NOSEY +NOTCH +NOTED +NOTES +NOUNS +NOVAE +NOVAS +NOVEL +NUDES +NUDGE +NUKED +NUKES +NULLS +NUMBS +NURSE +NUTTY +NYLON +NYMPH +OAKEN +OASES +OASIS +OATHS +OBESE +OBEYS +OBOES +OCCUR +OCEAN +OCHRE +OCTAL +OCTET +ODDER +ODDLY +ODIUM +ODORS +OFFER +OFTEN +OGLED +OGLER +OGLES +OGRES +OILED +OILER +OINKS +OLDEN +OLDER +OLDIE +OLIVE +OMEGA +OMENS +OMITS +ONION +ONSET +OODLE +OOZED +OOZES +OPALS +OPENS +OPERA +OPINE +OPIUM +OPTED +OPTIC +ORATE +ORBIT +ORCAS +ORDER +ORGAN +ORING +OTHER +OTTER +OUGHT +OUNCE +OUSTS +OUTDO +OUTER +OVALS +OVARY +OVATE +OVENS +OVERT +OWING +OWLET +OWNED +OWNER +OXIDE +OZONE +PACED +PACER +PACES +PACKS +PACTS +PADDY +PADRE +PAEAN +PAGAN +PAGED +PAGER +PAGES +PAILS +PAINS +PAINT +PAIRS +PALED +PALER +PALES +PALLS +PALLY +PALMS +PALMY +PALSY +PANDA +PANED +PANEL +PANES +PANGS +PANIC +PANSY +PANTS +PANTY +PAPAL +PAPAS +PAPER +PARCH +PARED +PARES +PARKA +PARKS +PARRY +PARSE +PARTS +PARTY +PASSE +PASTA +PASTE +PASTS +PASTY +PATCH +PATEN +PATER +PATES +PATHS +PATIO +PATSY +PATTY +PAUSE +PAVAN +PAVED +PAVER +PAVES +PAWED +PAWER +PAWKY +PAWLS +PAWNS +PAYED +PAYEE +PAYER +PEACE +PEACH +PEAKS +PEAKY +PEALS +PEARL +PEARS +PEASE +PEATS +PEATY +PECAN +PECKS +PEDAL +PEEKS +PEELS +PEENS +PEEPS +PEERS +PEEVE +PEKOE +PELTS +PENAL +PENCE +PENDS +PENES +PENGO +PENIS +PENNY +PEONS +PEONY +PEPPY +PERCH +PERDU +PERIL +PERKS +PERKY +PERMS +PESKY +PESOS +PESTO +PESTS +PETAL +PETER +PETIT +PETRI +PETTY +PEWEE +PEWIT +PFFFT +PHAGE +PHASE +PHIAL +PHLOX +PHONE +PHONY +PHOTO +PHYLA +PIANO +PICAS +PICKS +PICKY +PICOT +PIECE +PIERS +PIETA +PIETY +PIGGY +PIGMY +PIING +PIKER +PIKES +PILAF +PILAU +PILED +PILES +PILLS +PILOT +PIMPS +PINCH +PINED +PINES +PINEY +PINGS +PINKO +PINKS +PINKY +PINTO +PINTS +PINUP +PIONS +PIOUS +PIPED +PIPER +PIPES +PIPET +PIQUE +PISMO +PITAS +PITCH +PITHS +PITHY +PITON +PIVOT +PIXEL +PIXIE +PIZZA +PLACE +PLAID +PLAIN +PLAIT +PLANE +PLANK +PLANS +PLANT +PLASH +PLASM +PLATE +PLATS +PLAYA +PLAYS +PLAZA +PLEAD +PLEAS +PLEAT +PLEBE +PLEBS +PLEIN +PLENA +PLIED +PLIES +PLINK +PLODS +PLONK +PLOPS +PLOTS +PLOWS +PLOYS +PLUCK +PLUGS +PLUMB +PLUME +PLUMP +PLUMS +PLUMY +PLUNK +PLUSH +PLYER +POACH +POCKS +POCKY +PODGY +PODIA +POEMS +POESY +POETS +POINT +POISE +POKED +POKER +POKES +POKEY +POLAR +POLED +POLER +POLES +POLIO +POLIS +POLKA +POLLS +POLLY +POLOS +POLYP +POMPS +PONDS +PONES +POOCH +POOEY +POOHS +POOLS +POOPS +POPES +POPPY +PORCH +PORED +PORES +PORGY +PORKS +PORKY +PORNO +PORTS +POSED +POSER +POSES +POSET +POSIT +POSSE +POSTE +POSTS +POTTY +POUCH +POUFS +POUND +POURS +POUTS +POWER +POXED +POXES +PRAMS +PRANK +PRATE +PRATS +PRAWN +PRAYS +PREEN +PREPS +PRESS +PREST +PREXY +PREYS +PRICE +PRICK +PRIDE +PRIED +PRIER +PRIES +PRIGS +PRIMA +PRIME +PRIMO +PRIMP +PRIMS +PRINK +PRINT +PRIOR +PRISE +PRISM +PRIVY +PRIZE +PROBE +PRODS +PROEM +PROFS +PROMO +PROMS +PRONE +PRONG +PROOF +PROPS +PROSE +PROSY +PROUD +PROVE +PROWL +PROWS +PROXY +PRUDE +PRUNE +PRUTA +PRYER +PSALM +PSEUD +PSHAW +PSOAS +PSSST +PSYCH +PUBES +PUBIC +PUBIS +PUCKS +PUDGY +PUFFS +PUFFY +PUKED +PUKES +PUKKA +PULLS +PULPS +PULPY +PULSE +PUMAS +PUMPS +PUNCH +PUNKS +PUNKY +PUNNY +PUNTS +PUPAE +PUPAL +PUPAS +PUPIL +PUPPY +PUREE +PURER +PURGE +PURLS +PURRS +PURSE +PURTY +PUSHY +PUSSY +PUTTS +PUTTY +PYGMY +PYLON +PYRES +PYXIE +QOPHS +QUACK +QUADS +QUAFF +QUAIL +QUAIS +QUAKE +QUALM +QUALS +QUARK +QUART +QUASH +QUASI +QUAYS +QUEEN +QUEER +QUELL +QUERY +QUEST +QUEUE +QUICK +QUIDS +QUIET +QUIFF +QUILL +QUILT +QUINT +QUIPS +QUIPU +QUIRE +QUIRK +QUIRT +QUITE +QUITS +QUOIN +QUOIT +QUOTA +QUOTE +QUOTH +RABBI +RABID +RACED +RACER +RACES +RACKS +RADAR +RADII +RADIO +RADIX +RADON +RAFTS +RAGED +RAGES +RAIDS +RAILS +RAINS +RAINY +RAISE +RAJAH +RAJAS +RAKED +RAKER +RAKES +RALLY +RAMPS +RANCH +RANDS +RANDY +RANGE +RANGY +RANKS +RANTS +RAPED +RAPER +RAPES +RAPID +RARER +RASAE +RASPS +RASPY +RATED +RATER +RATES +RATHS +RATIO +RATTY +RAVED +RAVEL +RAVEN +RAVER +RAVES +RAWER +RAWLY +RAYED +RAYON +RAZED +RAZER +RAZES +RAZOR +REACH +REACT +READS +READY +REALM +REALS +REAMS +REAPS +REARM +REARS +REBAR +REBEL +REBID +REBOX +REBUS +REBUT +RECAP +RECTA +RECTO +RECUR +RECUT +REDID +REDIP +REDLY +REDOX +REDUX +REEDS +REEDY +REEFS +REEKS +REEKY +REELS +REEVE +REFER +REFIT +REFIX +REFLY +REFRY +REGAL +REHAB +REIFY +REIGN +REINS +RELAX +RELAY +RELET +RELIC +REMAN +REMAP +REMIT +REMIX +RENAL +RENDS +RENEW +RENTE +RENTS +REPAY +REPEL +REPLY +REPRO +RERAN +RERUN +RESAW +RESAY +RESET +RESEW +RESIN +RESTS +RETCH +RETRO +RETRY +REUSE +REVEL +REVET +REVUE +REWED +RHEAS +RHEUM +RHINO +RHUMB +RHYME +RIALS +RIBBY +RICED +RICER +RICES +RIDER +RIDES +RIDGE +RIDGY +RIFER +RIFLE +RIFTS +RIGHT +RIGID +RIGOR +RILED +RILES +RILLE +RILLS +RIMED +RIMER +RIMES +RINDS +RINGS +RINKS +RINSE +RIOTS +RIPEN +RIPER +RISEN +RISER +RISES +RISKS +RISKY +RITES +RITZY +RIVAL +RIVED +RIVEN +RIVER +RIVES +RIVET +ROACH +ROADS +ROAMS +ROANS +ROARS +ROAST +ROBED +ROBES +ROBIN +ROBLE +ROBOT +ROCKS +ROCKY +RODEO +ROGER +ROGUE +ROIDS +ROILS +ROILY +ROLES +ROLLS +ROMAN +ROMPS +RONDO +ROODS +ROOFS +ROOKS +ROOKY +ROOMS +ROOMY +ROOST +ROOTS +ROOTY +ROPED +ROPER +ROPES +ROSES +ROSIN +ROTOR +ROUGE +ROUGH +ROUND +ROUSE +ROUST +ROUTE +ROUTS +ROVED +ROVER +ROVES +ROWAN +ROWDY +ROWED +ROWER +ROYAL +RUBES +RUBLE +RUCHE +RUDDY +RUDER +RUFFS +RUGBY +RUING +RUINS +RULED +RULER +RULES +RUMBA +RUMEN +RUMMY +RUMOR +RUMPS +RUNES +RUNGS +RUNIC +RUNNY +RUNTS +RUNTY +RUPEE +RURAL +RUSES +RUSKS +RUSSE +RUSTS +RUSTY +RUTTY +SABER +SABLE +SABRA +SABRE +SACKS +SADLY +SAFER +SAFES +SAGAS +SAGER +SAGES +SAHIB +SAILS +SAINT +SAITH +SAKES +SALAD +SALES +SALLY +SALON +SALSA +SALTS +SALTY +SALVE +SALVO +SAMBA +SANDS +SANDY +SANER +SAPPY +SARAN +SARGE +SARIS +SASSY +SATED +SATES +SATIN +SATYR +SAUCE +SAUCY +SAUNA +SAUTE +SAVED +SAVER +SAVES +SAVOR +SAVVY +SAWED +SAWER +SAXES +SAYER +SCABS +SCADS +SCALD +SCALE +SCALP +SCALY +SCAMP +SCAMS +SCANS +SCANT +SCARE +SCARF +SCARP +SCARS +SCARY +SCATS +SCENE +SCENT +SCHMO +SCHWA +SCION +SCOFF +SCOLD +SCONE +SCOOP +SCOOT +SCOPE +SCOPS +SCORE +SCORN +SCOUR +SCOUT +SCOWL +SCOWS +SCRAM +SCRAP +SCREW +SCRIM +SCRIP +SCROD +SCRUB +SCRUM +SCUBA +SCUDI +SCUDO +SCUDS +SCUFF +SCULL +SCUMS +SCURF +SCUSE +SCUZZ +SEALS +SEAMS +SEAMY +SEARS +SEATS +SEBUM +SECCO +SECTS +SEDAN +SEDER +SEDGE +SEDGY +SEDUM +SEEDS +SEEDY +SEEKS +SEEMS +SEEPS +SEERS +SEEST +SEETH +SEGUE +SEINE +SEIZE +SELAH +SELFS +SELLS +SEMEN +SEMIS +SENDS +SENSE +SEPAL +SEPIA +SEPOY +SEPTA +SERFS +SERGE +SERIF +SERUM +SERVE +SERVO +SETUP +SEVEN +SEVER +SEWED +SEWER +SEXED +SEXES +SHACK +SHADE +SHADS +SHADY +SHAFT +SHAGS +SHAHS +SHAKE +SHAKO +SHAKY +SHALE +SHALL +SHALT +SHAME +SHAMS +SHANK +SHAPE +SHARD +SHARE +SHARK +SHARP +SHAVE +SHAWL +SHAWM +SHAYS +SHEAF +SHEAR +SHEDS +SHEEN +SHEEP +SHEER +SHEET +SHEIK +SHELF +SHELL +SHERD +SHEWS +SHIED +SHIER +SHIES +SHIFT +SHILL +SHIMS +SHINE +SHINS +SHINY +SHIPS +SHIRE +SHIRK +SHIRT +SHISH +SHITS +SHLEP +SHOAL +SHOCK +SHOED +SHOER +SHOES +SHOJI +SHONE +SHOOK +SHOOS +SHOOT +SHOPS +SHORE +SHORN +SHORT +SHOTS +SHOUT +SHOVE +SHOWN +SHOWS +SHOWY +SHRED +SHREW +SHRUB +SHRUG +SHUCK +SHUNS +SHUNT +SHUSH +SHUTE +SHUTS +SHYLY +SIBYL +SICKO +SICKS +SIDED +SIDES +SIDLE +SIEGE +SIEVE +SIFTS +SIGHS +SIGHT +SIGMA +SIGNS +SILKS +SILKY +SILLS +SILLY +SILOS +SILTS +SILTY +SINCE +SINES +SINEW +SINGE +SINGS +SINKS +SINUS +SIRED +SIREN +SIRES +SISSY +SITAR +SITED +SITES +SIXES +SIXTH +SIXTY +SIZED +SIZER +SIZES +SKATE +SKEET +SKEWS +SKIDS +SKIED +SKIER +SKIES +SKIFF +SKILL +SKIMP +SKIMS +SKINS +SKINT +SKIPS +SKIRT +SKITS +SKULK +SKULL +SKUNK +SKYED +SLABS +SLACK +SLAGS +SLAIN +SLAKE +SLAMS +SLANG +SLANT +SLAPS +SLASH +SLATE +SLATS +SLAVE +SLAWS +SLAYS +SLEDS +SLEEK +SLEEP +SLEET +SLEPT +SLEWS +SLICE +SLICK +SLIDE +SLIER +SLILY +SLIME +SLIMS +SLIMY +SLING +SLINK +SLIPS +SLITS +SLOBS +SLOGS +SLOPE +SLOPS +SLOSH +SLOTH +SLOTS +SLOWS +SLUGS +SLUMP +SLUMS +SLUNG +SLUNK +SLURP +SLURS +SLUSH +SLUTS +SLYER +SLYLY +SMACK +SMALL +SMART +SMASH +SMEAR +SMELL +SMELT +SMILE +SMIRK +SMITE +SMITH +SMOGS +SMOKE +SMOKY +SMOTE +SMURF +SNACK +SNAGS +SNAIL +SNAKE +SNAKY +SNAPS +SNARE +SNARK +SNARL +SNEAK +SNEER +SNIDE +SNIFF +SNIPE +SNIPS +SNOBS +SNOOK +SNOOT +SNORE +SNORT +SNOUT +SNOWS +SNOWY +SNUBS +SNUCK +SNUFF +SNUGS +SOAKS +SOAPS +SOAPY +SOARS +SOBER +SOCKS +SOCLE +SODAS +SOFAS +SOFTS +SOFTY +SOGGY +SOILS +SOLAR +SOLES +SOLID +SOLOS +SOLVE +SONAR +SONGS +SONIC +SONNY +SOOTH +SOOTS +SOOTY +SOPPY +SORER +SORES +SORRY +SORTA +SORTS +SOULS +SOUND +SOUPS +SOUPY +SOURS +SOUSE +SOUTH +SOWED +SOWER +SOYAS +SPACE +SPACY +SPADE +SPAKE +SPANG +SPANK +SPANS +SPARE +SPARK +SPARS +SPASM +SPATE +SPATS +SPAWN +SPAYS +SPAZZ +SPEAK +SPEAR +SPECK +SPECS +SPEED +SPELL +SPELT +SPEND +SPENT +SPERM +SPEWS +SPICE +SPICS +SPICY +SPIED +SPIEL +SPIER +SPIES +SPIFF +SPIKE +SPIKY +SPILL +SPILT +SPINE +SPINS +SPINY +SPIRE +SPITE +SPITS +SPITZ +SPLAT +SPLAY +SPLIT +SPOIL +SPOKE +SPOOF +SPOOK +SPOOL +SPOON +SPORE +SPORT +SPOTS +SPOUT +SPRAT +SPRAY +SPREE +SPRIG +SPRUE +SPUDS +SPUED +SPUME +SPUMY +SPUNK +SPURN +SPURS +SPURT +SQUAB +SQUAD +SQUAT +SQUAW +SQUIB +SQUID +STABS +STACK +STAFF +STAGE +STAGS +STAGY +STAID +STAIN +STAIR +STAKE +STALE +STALK +STALL +STAMP +STAND +STANK +STAPH +STARE +STARK +STARS +START +STASH +STATE +STATS +STAVE +STAYS +STEAD +STEAK +STEAL +STEAM +STEED +STEEL +STEEP +STEER +STELE +STEMS +STEPS +STERN +STETS +STEWS +STICK +STIED +STIES +STIFF +STILE +STILL +STILT +STING +STINK +STINT +STIRS +STOAE +STOAS +STOAT +STOCK +STOGY +STOIC +STOKE +STOLE +STOMP +STONE +STONY +STOOD +STOOL +STOOP +STOPS +STORE +STORK +STORM +STORY +STOUP +STOUT +STOVE +STOWS +STRAP +STRAW +STRAY +STREP +STREW +STRIP +STRUM +STRUT +STUBS +STUCK +STUDS +STUDY +STUFF +STUMP +STUNG +STUNK +STUNS +STUNT +STYES +STYLE +STYLI +SUAVE +SUCKS +SUDSY +SUEDE +SUERS +SUGAR +SUING +SUITE +SUITS +SULKS +SULKY +SULLY +SUMMA +SUMPS +SUNNY +SUNUP +SUPER +SUPES +SUPRA +SURAS +SURDS +SURER +SURFS +SURGE +SURLY +SUSHI +SWABS +SWAGS +SWAIN +SWAMI +SWAMP +SWANK +SWANS +SWAPS +SWARD +SWARE +SWARF +SWARM +SWART +SWASH +SWATH +SWATS +SWAYS +SWEAR +SWEAT +SWEDE +SWEEP +SWEET +SWELL +SWEPT +SWIFT +SWIGS +SWILL +SWIMS +SWINE +SWING +SWIPE +SWIRL +SWISH +SWISS +SWIVE +SWOON +SWOOP +SWORD +SWORE +SWORN +SWUNG +SYLPH +SYNCH +SYNCS +SYNOD +SYRUP +TABBY +TABLE +TABOO +TABOR +TABUS +TACET +TACIT +TACKS +TACKY +TACOS +TACTS +TAELS +TAFFY +TAGUA +TAILS +TAINT +TAKEN +TAKER +TAKES +TALCS +TALES +TALKS +TALKY +TALLY +TALON +TALUS +TAMED +TAMER +TAMES +TAMPS +TANGO +TANGS +TANGY +TANKS +TANSY +TAPED +TAPER +TAPES +TAPIR +TAPIS +TARDY +TARED +TARES +TARNS +TAROS +TAROT +TARPS +TARRY +TARTS +TASKS +TASTE +TASTY +TATER +TATTY +TAUNT +TAUPE +TAWNY +TAXED +TAXER +TAXES +TAXIS +TAXOL +TAXON +TEACH +TEAKS +TEALS +TEAMS +TEARS +TEARY +TEASE +TEATS +TECHS +TECHY +TECUM +TEDDY +TEEMS +TEENS +TEENY +TEETH +TELEX +TELLS +TELLY +TEMPI +TEMPO +TEMPS +TEMPT +TENCH +TENDS +TENET +TENON +TENOR +TENSE +TENTH +TENTS +TEPEE +TEPID +TERCE +TERMS +TERNS +TERRA +TERRY +TERSE +TESLA +TESTS +TESTY +TETRA +TEXAS +TEXTS +THANE +THANK +THANX +THATS +THAWS +THEES +THEFT +THEIR +THEME +THENS +THERE +THERM +THESE +THETA +THEWS +THICK +THIEF +THIGH +THINE +THING +THINK +THINS +THIRD +THONG +THORN +THOSE +THOUS +THREE +THREW +THROB +THROE +THROW +THRUM +THUDS +THUGS +THUMB +THUMP +THUNK +THWAP +THYME +TIARA +TIBIA +TICKS +TIDAL +TIDED +TIDES +TIERS +TIFFS +TIGER +TIGHT +TIKES +TIKIS +TILDE +TILED +TILER +TILES +TILLS +TILTH +TILTS +TIMED +TIMER +TIMES +TIMID +TINES +TINGE +TINGS +TINNY +TINTS +TIPPY +TIPSY +TIRED +TIRES +TIROS +TITAN +TITER +TITHE +TITLE +TITRE +TITTY +TIZZY +TOADS +TOADY +TOAST +TODAY +TODDY +TOFFS +TOFFY +TOGAS +TOILE +TOILS +TOKED +TOKEN +TOKER +TOKES +TOLLS +TOMBS +TOMES +TOMMY +TONAL +TONED +TONER +TONES +TONGS +TONIC +TOOLS +TOONS +TOOTH +TOOTS +TOPAZ +TOPED +TOPER +TOPES +TOPIC +TOPOI +TOPOS +TOQUE +TORAH +TORCH +TORIC +TORSI +TORSO +TORTE +TORTS +TORUS +TOTAL +TOTED +TOTEM +TOTER +TOTES +TOTTY +TOUCH +TOUGH +TOURS +TOUTS +TOVES +TOWED +TOWEL +TOWER +TOWNS +TOXIC +TOXIN +TOYED +TOYER +TOYON +TRACE +TRACK +TRACT +TRADE +TRAIL +TRAIN +TRAIT +TRAMP +TRAMS +TRANS +TRAPS +TRASH +TRAWL +TRAYS +TREAD +TREAP +TREAT +TREED +TREES +TREKS +TREND +TRESS +TREWS +TREYS +TRIAD +TRIAL +TRIBE +TRIBS +TRICE +TRICK +TRIED +TRIER +TRIES +TRIKE +TRILL +TRIMS +TRIOS +TRIPE +TRIPS +TRITE +TROLL +TROMP +TROOP +TROTH +TROTS +TROUT +TROVE +TROWS +TRUCE +TRUCK +TRUED +TRUER +TRUES +TRULY +TRUMP +TRUNK +TRUSS +TRUST +TRUTH +TRYST +TSARS +TUANS +TUBAL +TUBAS +TUBBY +TUBED +TUBER +TUBES +TUCKS +TUFAS +TUFTS +TUFTY +TULIP +TULLE +TUMMY +TUMOR +TUNAS +TUNED +TUNER +TUNES +TUNIC +TUNNY +TUPLE +TURBO +TURDS +TURDY +TURFS +TURFY +TURNS +TURPS +TUSKS +TUSKY +TUTOR +TUTTI +TUTUS +TUXES +TWAIN +TWANG +TWATS +TWEAK +TWEED +TWEET +TWERP +TWICE +TWIGS +TWILL +TWINE +TWINK +TWINS +TWINY +TWIRL +TWIRP +TWIST +TWITS +TWIXT +TYING +TYKES +TYPAL +TYPED +TYPES +TYPOS +TYRES +TYROS +TZARS +UDDER +UKASE +ULCER +ULNAR +ULNAS +ULTRA +UMBEL +UMBER +UMBRA +UMIAK +UMPED +UMPTY +UNAPT +UNARC +UNARM +UNARY +UNATE +UNBAN +UNBAR +UNBOX +UNCAP +UNCLE +UNCUT +UNDER +UNDID +UNDUE +UNFED +UNFIT +UNFIX +UNHIP +UNHIT +UNIFY +UNION +UNITE +UNITS +UNITY +UNJAM +UNLIT +UNMAN +UNMAP +UNMET +UNPEG +UNPIN +UNRIG +UNSAY +UNSEE +UNSET +UNSEW +UNSEX +UNTIE +UNTIL +UNWED +UNWON +UNZIP +UPEND +UPPED +UPPER +UPSET +URBAN +UREAS +URGED +URGER +URGES +URINE +USAGE +USERS +USHER +USING +USUAL +USURP +USURY +UTERI +UTERO +UTTER +UVULA +VACUA +VACUO +VAGUE +VAGUS +VAILS +VALES +VALET +VALID +VALOR +VALUE +VALVE +VAMPS +VANED +VANES +VAPES +VAPID +VAPOR +VARIA +VASES +VAULT +VAUNT +VEALS +VEEPS +VEERS +VEGAN +VEILS +VEINS +VEINY +VENAL +VENDS +VENOM +VENTS +VENUE +VERBS +VERGE +VERSE +VERVE +VESTS +VEXED +VEXES +VIALS +VIBES +VICAR +VICES +VIDEO +VIEWS +VIGIL +VIGOR +VILLA +VINES +VINYL +VIOLA +VIPER +VIRAL +VIRUS +VISIT +VISOR +VISTA +VITAE +VITAL +VITRO +VIVID +VIXEN +VOCAL +VODKA +VOGUE +VOICE +VOIDS +VOILA +VOLTS +VOMIT +VOTED +VOTER +VOTES +VOUCH +VOWED +VOWEL +VOWER +VROOM +VULVA +VYING +WACKY +WADED +WADES +WAFER +WAFTS +WAGES +WAGON +WAIFS +WAILS +WAIST +WAITS +WAIVE +WAKEN +WAKES +WALKS +WALLS +WALTZ +WANDS +WANED +WANES +WANTS +WARDS +WARES +WARMS +WARNS +WARPS +WARTS +WASPS +WASTE +WATCH +WATER +WATTS +WAVED +WAVER +WAVES +WAXED +WAXER +WAXES +WEALD +WEANS +WEARS +WEARY +WEAVE +WEDGE +WEEDS +WEEDY +WEEKS +WEEPS +WEEPY +WEIGH +WEIRD +WELDS +WELLS +WELTS +WENCH +WETLY +WHACK +WHALE +WHARF +WHEAT +WHEEL +WHELM +WHELP +WHERE +WHETS +WHICH +WHIFF +WHILE +WHIMS +WHINE +WHINY +WHIPS +WHIRL +WHIRR +WHIRS +WHISK +WHITE +WHOLE +WHORE +WHOSE +WICKS +WIDEN +WIDER +WIDOW +WIDTH +WIELD +WILLS +WILTS +WIMPS +WIMPY +WINCE +WINCH +WINDS +WINDY +WINES +WINGS +WINKS +WINOS +WIPED +WIPER +WIPES +WIRED +WIRER +WIRES +WISER +WITCH +WITTY +WIVES +WIZEN +WOKEN +WOMAN +WOMBS +WOMEN +WONTS +WOODS +WOODY +WOOED +WOOER +WOOFS +WOOLS +WOOLY +WORDS +WORDY +WORKS +WORLD +WORMS +WORRY +WORSE +WORST +WORTH +WORTS +WOULD +WOUND +WOVEN +WOWED +WRAPS +WRATH +WREAK +WRECK +WRENS +WREST +WRING +WRIST +WRITE +WRITS +WRONG +WROTE +WROTH +WRUNG +WRYER +WRYLY +YACHT +YARDS +YARNS +YAWNS +YEARN +YEARS +YEAST +YELLS +YELPS +YIELD +YIKES +YODEL +YOLKS +YOLKY +YOUNG +YOURS +YOUTH +YOYOS +YUCKY +YUMMY +ZEALS +ZEBRA +ZEROS +ZESTS +ZESTY +ZETAS +ZILCH +ZINCS +ZINGS +ZONED +ZONES +ZOOMS diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..829057d --- /dev/null +++ b/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 1.4.2.RELEASE + + + com.charego + lingo-websocket + 1.0 + pom + + Lingo WebSocket + + + UTF-8 + 1.8 + + + + client + client-api + common + server + + + diff --git a/server/LingoServer.launch b/server/LingoServer.launch new file mode 100644 index 0000000..7cf244c --- /dev/null +++ b/server/LingoServer.launch @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/pom.xml b/server/pom.xml new file mode 100644 index 0000000..9460bb1 --- /dev/null +++ b/server/pom.xml @@ -0,0 +1,53 @@ + + 4.0.0 + + + com.charego + lingo-websocket + 1.0 + + + lingo-websocket-server + Lingo WebSocket :: Server + + + + ${project.groupId} + ${project.version} + lingo-websocket-client-api + + + + + org.springframework.boot + spring-boot-starter-websocket + + + + + org.springframework.boot + spring-boot-devtools + + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + true + + src/main/config + + + + + + diff --git a/server/src/main/config/application.yaml b/server/src/main/config/application.yaml new file mode 100644 index 0000000..a233791 --- /dev/null +++ b/server/src/main/config/application.yaml @@ -0,0 +1,5 @@ +# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html + +server: + address: localhost + port: 8080 diff --git a/server/src/main/java/lingo/server/LingoController.java b/server/src/main/java/lingo/server/LingoController.java new file mode 100644 index 0000000..feae78e --- /dev/null +++ b/server/src/main/java/lingo/server/LingoController.java @@ -0,0 +1,179 @@ +package lingo.server; + +import static org.springframework.messaging.simp.SimpMessageHeaderAccessor.SESSION_ID_HEADER; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.messaging.MessageHeaders; +import org.springframework.messaging.handler.annotation.Header; +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.messaging.simp.SimpMessageHeaderAccessor; +import org.springframework.messaging.simp.SimpMessageType; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.messaging.simp.stomp.StompHeaderAccessor; +import org.springframework.stereotype.Controller; +import org.springframework.web.socket.messaging.AbstractSubProtocolEvent; +import org.springframework.web.socket.messaging.SessionConnectedEvent; +import org.springframework.web.socket.messaging.SessionDisconnectEvent; + +import lingo.client.api.StompTopics; +import lingo.common.Game; +import lingo.common.Report; + +@Controller +@MessageMapping("/lingo") +public class LingoController implements ApplicationListener { + + private static final Logger log = LoggerFactory.getLogger(LingoController.class); + + @Autowired + private SimpMessagingTemplate messagingTemplate; + + @Autowired + private WordRepository wordRepo; + + private final List waitingList = new ArrayList<>(); + + private final Map gameBySession = new HashMap<>(); + + @MessageMapping("/guess") + public void guess(String guess, @Header(SESSION_ID_HEADER) String sessionId) { + guess = guess.toUpperCase(); + log.info("Player {} guessed: {}", sessionId, guess); + final Game game = gameBySession.get(sessionId); + final int[] result = game.evaluate(guess); + + // Generate reports + final Report playerReport = new Report(); + final Report opponentReport = new Report(); + playerReport.setGuess(guess); + if (Game.isCorrect(result)) { + final String newWord = game.newWord(); + final String firstLetter = String.valueOf(newWord.charAt(0)); + log.info("New word: {}", newWord); + playerReport.setCorrect(true); + playerReport.setFirstLetter(firstLetter); + opponentReport.setCorrect(true); + opponentReport.setFirstLetter(firstLetter); + opponentReport.setGuess(guess); + } else { + playerReport.setResult(result); + opponentReport.setResult(result); + } + final String opponentId = sessionId.equals(game.playerOne) ? game.playerTwo : game.playerOne; + sendToUser(sessionId, StompTopics.PLAYER_REPORTS, playerReport); + sendToUser(opponentId, StompTopics.OPPONENT_REPORTS, opponentReport); + } + + @MessageMapping("/join") + public void join(@Header(SESSION_ID_HEADER) String sessionId) { + log.info("Player {} joined", sessionId); + joinWaitingList(sessionId); + } + + private void joinWaitingList(String sessionId) { + synchronized (waitingList) { + if (!waitingList.contains(sessionId)) { + waitingList.add(sessionId); + waitingList.notify(); + } + } + } + + private void leave(String sessionId) { + final Game game = gameBySession.remove(sessionId); + if (game == null) { + leaveWaitingList(sessionId); + } else { + log.info("Player {} left their game!", sessionId); + final String opponentId = sessionId.equals(game.playerOne) ? game.playerTwo : game.playerOne; + gameBySession.remove(opponentId); + sendToUser(opponentId, StompTopics.OPPONENT_LEFT, "You win!"); + joinWaitingList(opponentId); + } + } + + private void leaveWaitingList(String sessionId) { + synchronized (waitingList) { + waitingList.remove(sessionId); + waitingList.notify(); + } + } + + @Override + public void onApplicationEvent(AbstractSubProtocolEvent event) { + if (event instanceof SessionConnectedEvent) { + onSessionConnected((SessionConnectedEvent) event); + } else if (event instanceof SessionDisconnectEvent) { + onSessionDisconnect((SessionDisconnectEvent) event); + } + } + + private void onSessionConnected(SessionConnectedEvent event) { + final String sessionId = StompHeaderAccessor.wrap(event.getMessage()).getSessionId(); + log.info("Session connected: {}", sessionId); + } + + private void onSessionDisconnect(SessionDisconnectEvent event) { + final String sessionId = event.getSessionId(); + log.info("Session disconnected: {}", sessionId); + leave(sessionId); + } + + @PostConstruct + private void postConstruct() { + new Thread(new WaitingListListener()).start(); + } + + private void sendToUser(String user, String destination, Object payload) { + // TODO: cache the headers? + final SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE); + headerAccessor.setSessionId(user); + headerAccessor.setLeaveMutable(true); + final MessageHeaders headers = headerAccessor.getMessageHeaders(); + messagingTemplate.convertAndSendToUser(user, destination, payload, headers); + } + + /** + * Task that spawns a game whenever two players are waiting. + */ + private class WaitingListListener implements Runnable { + + @Override + public void run() { + while (true) { + final String playerOne; + final String playerTwo; + synchronized (waitingList) { + while (waitingList.size() < 2) { + try { + waitingList.wait(); + } catch (InterruptedException ok) { + ok.printStackTrace(); + } + } + playerOne = waitingList.remove(0); + playerTwo = waitingList.remove(0); + } + final Game game = new Game(playerOne, playerTwo, wordRepo.getWords(), wordRepo.getGuesses()); + gameBySession.put(playerOne, game); + gameBySession.put(playerTwo, game); + final String firstWord = game.newGame(); + final String firstLetter = String.valueOf(firstWord.charAt(0)); + log.info("First word: {}", firstWord); + sendToUser(playerOne, StompTopics.OPPONENT_JOINED, firstLetter); + sendToUser(playerTwo, StompTopics.OPPONENT_JOINED, firstLetter); + } + } + } + +} diff --git a/server/src/main/java/lingo/server/LingoServer.java b/server/src/main/java/lingo/server/LingoServer.java new file mode 100644 index 0000000..acc8713 --- /dev/null +++ b/server/src/main/java/lingo/server/LingoServer.java @@ -0,0 +1,13 @@ +package lingo.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class LingoServer { + + public static void main(String[] args) { + SpringApplication.run(LingoServer.class, args); + } + +} diff --git a/server/src/main/java/lingo/server/WebSocketConfig.java b/server/src/main/java/lingo/server/WebSocketConfig.java new file mode 100644 index 0000000..fbd90a2 --- /dev/null +++ b/server/src/main/java/lingo/server/WebSocketConfig.java @@ -0,0 +1,24 @@ +package lingo.server; + +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; + +@Configuration +@EnableWebSocketMessageBroker +public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { + + @Override + public void configureMessageBroker(MessageBrokerRegistry config) { + config.enableSimpleBroker("/topic"); + config.setApplicationDestinationPrefixes("/app"); + } + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + registry.addEndpoint("/stomp"); + } + +} diff --git a/server/src/main/java/lingo/server/WordRepository.java b/server/src/main/java/lingo/server/WordRepository.java new file mode 100644 index 0000000..eaad226 --- /dev/null +++ b/server/src/main/java/lingo/server/WordRepository.java @@ -0,0 +1,39 @@ +package lingo.server; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.springframework.stereotype.Component; + +import lingo.common.WordReader; + +@Component +public class WordRepository { + + private final Set guesses; + + private final List words; + + public WordRepository() throws IOException { + guesses = WordReader.readFileToSet("/guesses.txt"); + words = WordReader.readFileToList("/words.txt"); + } + + /** + * Returns the set of acceptable guesses (unmodifiable). + */ + public Set getGuesses() { + return Collections.unmodifiableSet(guesses); + } + + /** + * Returns a copy of the list of potential answers (OK to shuffle it). + */ + public List getWords() { + return new ArrayList<>(words); + } + +}