kipedia.org/wiki/Finite_state_machine In fact, it is a transducer. States are denoted by the enum ConversationStates. Input is the text that the player says to the SpeakerNPC. Output is the text that the SpeakerNPC answers. See examples to understand how it works. RULES: State IDLE is both the start state and the state that will end the conversation between the player and the SpeakerNPC. State ATTENDING is the state where only one player can talk to NPC and where the prior talk doesn't matter. State ANY is a wildcard and is used to jump from any state whenever the trigger is active. There are states that are reserved for special behaviours and quests. Example how it works: First we need to create a message to greet the player and attend it. We add a hi event: add(ConversationStates.IDLE, ConversationPhrases.GREETING_MESSAGES, ConversationStates.ATTENDING, "Welcome, player!", null) Once the NPC is in the IDLE state and hears the word "hi", it will say "Welcome player!" and move to ATTENDING. Now let's add some options when player is in ATTENDING_STATE, like job, offer, buy, sell, etc. add(ConversationStates.ATTENDING, ConversationPhrases.JOB_MESSAGES, ConversationStates.ATTENDING, "I work as a part time example showman", null) add(ConversationStates.ATTENDING_STATE, "offer", ConversationStates.ATTENDING_STATE, "I sell best quality swords", null) Ok, two new events: job and offer, they go from ATTENDING state to ATTENDING state, because after reacting to "job" or "offer", the NPC can directly react to one of these again.
add(ConversationStates.ATTENDING, "buy", ConversationStates.BUY_PRICE_OFFERED, null, new ChatAction() { public void fire(Player player, String text, SpeakerNPC npc) { int i = text.indexOf(" "); String item = text.substring(i + 1); if (item.equals("sword")) { npc.say(item + "costs 10 coins. Do you want to buy?"); } else { npc.say("Sorry, I don't sell " + item + "."); npc.setActualState(ConversationStates.ATTENDING); } } });
Now the hard part. We listen to "buy", so we need to process the text, and for that we use the ChatAction class, we create a new class that will handle the event. Also see that we move to a new state, BUY_PRICE_OFFERED. The player is then replying to a question, so we only expect two possible replies: yes or no. add(ConversationStates.BUY_PRICE_OFFERED, ConversationPhrases.YES_MESSAGES, ConversationStates.ATTENDING, "Sorry, I changed my mind. I won't sell anything.", null); // See SellerBehaviour.java for a working example. Whatever the reply is, return to ATTENDING state so we can listen to new things. Finally we want to finish the conversation, so whatever state we are, we want to finish a conversation with "Bye!". add(ConversationStates.ANY, ConversationPhrases.GOODBYE_MESSAGES, ConversationStates.IDLE, "Bye!", null); We use the state ANY as a wildcard, so if the input text is "bye" the transition happens, no matter in which state the FSM really is, with the exception of the IDLE state.