#!/usr/bin/env python # coding: utf-8 # In[1]: import json # In[23]: 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() # # Basic kitten # In[3]: kitten = Bot("Kitten") # In[4]: origin = State("origin", "'You have a kitten!'", Exit("name")) # In[5]: name = State("name", "'What do you want to name your kitten?'", Exit("respondToName", "*", action="name=INPUT")) # In[6]: respond = State("respondToName", "'I guess the kitten likes #/name#'") # In[7]: print(json.dumps(kitten.to_dict(), indent=2)) # # Full Kitten # In[24]: kitten = Bot("Kitten") # In[25]: hunger_wait = Exit("hungry", condition="wait:10") angry_wait = Exit("angry", condition="wait:10") idle_wait = Exit("idle", condition="wait:10") # In[26]: 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) # In[27]: kitten.exits.append(Exit("pet", "pet")) # In[28]: print(json.dumps(kitten.to_dict(), indent=2)) # In[ ]: