import json
class Bot:
_instance = None
def __new__(cls, name):
if cls._instance is not None:
print("Overwriting active bot.")
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, name, grammar=None):
self.name = name
self.states = {}
self.grammar = {}
self.exits = []
if grammar is not None:
self.grammar = grammar
self.initial_blackboard = {}
State._active_bot = self
def to_dict(self):
out_dict = {"grammar": self.grammar}
out_dict["states"] = {state_name: state.to_dict()
for state_name, state in self.states.items()}
out_dict["exits"] = [str(exit) for exit in self.exits]
out_dict["initialBlackboard"] = self.initial_blackboard
return out_dict
class State:
_active_bot = None
def __init__(self, name, on_enter, exits=None, chips=None):
'''
Exits can either be strings, or take the form
(word, Target) or (word, Target, action)
'''
self.name = name
self.on_enter = on_enter
self.exits = []
if exits is not None:
if type(exits) is list:
self.exits = exits
elif isinstance(exits, Exit):
self.exits.append(exits)
self.chips = []
if self._active_bot is not None:
self._active_bot.states[self.name] = self
def to_dict(self):
out_dict = {"onEnter": self.on_enter}
out_dict["exits"] = [str(exit) for exit in self.exits]
if len(self.chips) > 0:
out_dict["chips"] = list(self.chips)
return out_dict
class Exit:
template = "{} ->{} {}"
def __init__(self, target, word="", condition="", action=""):
if word != "" and condition != "":
raise Exception("An exit can be either a word or a condition but not both")
self.word = word
self.condition = condition
self.action = action
if isinstance(target, State):
self.target = target.name
else:
self.target = target
def __str__(self):
condition = self.condition
if self.word:
condition = "'{}'".format(self.word)
return self.template.format(condition, self.target, self.action).strip()
kitten = Bot("Kitten")
origin = State("origin", "'You have a kitten!'", Exit("name"))
name = State("name", "'What do you want to name your kitten?'",
Exit("respondToName", "*", action="name=INPUT"))
respond = State("respondToName", "'I guess the kitten likes #/name#'")
print(json.dumps(kitten.to_dict(), indent=2))
{ "states": { "respondToName": { "onEnter": "'I guess the kitten likes #/name#'", "exits": [] }, "name": { "onEnter": "'What do you want to name your kitten?'", "exits": [ "'*' ->respondToName name=INPUT" ] }, "origin": { "onEnter": "'You have a kitten!'", "exits": [ "->name" ] } }, "initialBlackboard": {}, "grammar": {} }
kitten = Bot("Kitten")
hunger_wait = Exit("hungry", condition="wait:10")
angry_wait = Exit("angry", condition="wait:10")
idle_wait = Exit("idle", condition="wait:10")
State("origin", "'You have a kitten!' desired_pets=randomInt(1,5)",
Exit("name"))
State("name", "'What do you want to name your kitten'",
Exit("respond_to_name", word="*", action="name=INPUT"))
State("respond_to_name", "'The kitten purrs; I guess it likes #/name#!'",
Exit("idle"))
State("pet", "'You pet the kitten' desired_pets--",
[Exit("happy_pet", condition="desired_pets>=0"), Exit("angry_pet")])
State("happy_pet", "'#/name# loves you!'", idle_wait)
State("angry_pet", "'Screech! #/name# doesn't want to be petted' desired_pets=randomInt(1,5)",
Exit("angry"))
State("idle", "'#/name# makes cute noises!'", hunger_wait)
State("angry", "*bite*", Exit("sleeping", condition="wait:10"))
State("sleeping", "'#/name# is sleeping'", hunger_wait)
State("hungry", "'The kitten is hungry'", angry_wait)
<__main__.State at 0x111f23278>
kitten.exits.append(Exit("pet", "pet"))
print(json.dumps(kitten.to_dict(), indent=2))
{ "states": { "name": { "onEnter": "'What do you want to name your kitten'", "exits": [ "'*' ->respond_to_name name=INPUT" ] }, "sleeping": { "onEnter": "'#/name# is sleeping'", "exits": [ "wait:10 ->hungry" ] }, "origin": { "onEnter": "'You have a kitten!' desired_pets=randomInt(1,5)", "exits": [ "->name" ] }, "hungry": { "onEnter": "'The kitten is hungry'", "exits": [ "wait:10 ->angry" ] }, "happy_pet": { "onEnter": "'#/name# loves you!'", "exits": [ "wait:10 ->idle" ] }, "respond_to_name": { "onEnter": "'The kitten purrs; I guess it likes #/name#!'", "exits": [ "->idle" ] }, "pet": { "onEnter": "'You pet the kitten' desired_pets--", "exits": [ "desired_pets>=0 ->happy_pet", "->angry_pet" ] }, "angry": { "onEnter": "*bite*", "exits": [ "wait:10 ->sleeping" ] }, "angry_pet": { "onEnter": "'Screech! #/name# doesn't want to be petted' desired_pets=randomInt(1,5)", "exits": [ "->angry" ] }, "idle": { "onEnter": "'#/name# makes cute noises!'", "exits": [ "wait:10 ->hungry" ] } }, "initialBlackboard": {}, "exits": [ "'pet' ->pet" ], "grammar": {} }