{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import json" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Bot:\n", " _instance = None\n", " \n", " def __new__(cls, name):\n", " if cls._instance is not None:\n", " print(\"Overwriting active bot.\")\n", " cls._instance = super().__new__(cls)\n", " return cls._instance\n", " \n", " def __init__(self, name, grammar=None):\n", " self.name = name\n", " self.states = {}\n", " self.grammar = {}\n", " self.exits = []\n", " if grammar is not None:\n", " self.grammar = grammar\n", " self.initial_blackboard = {}\n", " State._active_bot = self\n", " \n", " def to_dict(self):\n", " out_dict = {\"grammar\": self.grammar}\n", " out_dict[\"states\"] = {state_name: state.to_dict() \n", " for state_name, state in self.states.items()}\n", " out_dict[\"exits\"] = [str(exit) for exit in self.exits]\n", " out_dict[\"initialBlackboard\"] = self.initial_blackboard\n", " return out_dict\n", " \n", " \n", "class State:\n", " _active_bot = None\n", " \n", " def __init__(self, name, on_enter, exits=None, chips=None):\n", " '''\n", " \n", " Exits can either be strings, or take the form\n", " (word, Target) or (word, Target, action)\n", " '''\n", " self.name = name\n", " self.on_enter = on_enter\n", " \n", " self.exits = []\n", " if exits is not None:\n", " if type(exits) is list:\n", " self.exits = exits\n", " elif isinstance(exits, Exit):\n", " self.exits.append(exits)\n", " \n", " self.chips = []\n", " \n", " if self._active_bot is not None:\n", " self._active_bot.states[self.name] = self\n", " \n", " def to_dict(self):\n", " out_dict = {\"onEnter\": self.on_enter}\n", " out_dict[\"exits\"] = [str(exit) for exit in self.exits]\n", " if len(self.chips) > 0:\n", " out_dict[\"chips\"] = list(self.chips)\n", " return out_dict\n", " \n", "class Exit:\n", " template = \"{} ->{} {}\"\n", " def __init__(self, target, word=\"\", condition=\"\", action=\"\"):\n", " if word != \"\" and condition != \"\":\n", " raise Exception(\"An exit can be either a word or a condition but not both\")\n", " self.word = word\n", " self.condition = condition\n", " self.action = action\n", " \n", " if isinstance(target, State):\n", " self.target = target.name\n", " else:\n", " self.target = target\n", " \n", " def __str__(self):\n", " \n", " condition = self.condition\n", " if self.word:\n", " condition = \"'{}'\".format(self.word)\n", " return self.template.format(condition, self.target, self.action).strip()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Basic kitten" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "kitten = Bot(\"Kitten\")" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "origin = State(\"origin\", \"'You have a kitten!'\", Exit(\"name\"))" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "name = State(\"name\", \"'What do you want to name your kitten?'\", \n", " Exit(\"respondToName\", \"*\", action=\"name=INPUT\"))" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "respond = State(\"respondToName\", \"'I guess the kitten likes #/name#'\")" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"states\": {\n", " \"respondToName\": {\n", " \"onEnter\": \"'I guess the kitten likes #/name#'\",\n", " \"exits\": []\n", " },\n", " \"name\": {\n", " \"onEnter\": \"'What do you want to name your kitten?'\",\n", " \"exits\": [\n", " \"'*' ->respondToName name=INPUT\"\n", " ]\n", " },\n", " \"origin\": {\n", " \"onEnter\": \"'You have a kitten!'\",\n", " \"exits\": [\n", " \"->name\"\n", " ]\n", " }\n", " },\n", " \"initialBlackboard\": {},\n", " \"grammar\": {}\n", "}\n" ] } ], "source": [ "print(json.dumps(kitten.to_dict(), indent=2))" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Full Kitten" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "kitten = Bot(\"Kitten\")" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": true }, "outputs": [], "source": [ "hunger_wait = Exit(\"hungry\", condition=\"wait:10\")\n", "angry_wait = Exit(\"angry\", condition=\"wait:10\")\n", "idle_wait = Exit(\"idle\", condition=\"wait:10\")" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "<__main__.State at 0x111f23278>" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "State(\"origin\", \"'You have a kitten!' desired_pets=randomInt(1,5)\", \n", " Exit(\"name\"))\n", "\n", "State(\"name\", \"'What do you want to name your kitten'\", \n", " Exit(\"respond_to_name\", word=\"*\", action=\"name=INPUT\"))\n", "\n", "State(\"respond_to_name\", \"'The kitten purrs; I guess it likes #/name#!'\",\n", " Exit(\"idle\"))\n", "\n", "State(\"pet\", \"'You pet the kitten' desired_pets--\",\n", " [Exit(\"happy_pet\", condition=\"desired_pets>=0\"), Exit(\"angry_pet\")])\n", "\n", "State(\"happy_pet\", \"'#/name# loves you!'\", idle_wait)\n", "\n", "State(\"angry_pet\", \"'Screech! #/name# doesn't want to be petted' desired_pets=randomInt(1,5)\", \n", " Exit(\"angry\"))\n", "\n", "State(\"idle\", \"'#/name# makes cute noises!'\", hunger_wait)\n", "\n", "State(\"angry\", \"*bite*\", Exit(\"sleeping\", condition=\"wait:10\"))\n", "\n", "State(\"sleeping\", \"'#/name# is sleeping'\", hunger_wait)\n", "\n", "State(\"hungry\", \"'The kitten is hungry'\", angry_wait)\n", "\n" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": true }, "outputs": [], "source": [ "kitten.exits.append(Exit(\"pet\", \"pet\"))" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"states\": {\n", " \"name\": {\n", " \"onEnter\": \"'What do you want to name your kitten'\",\n", " \"exits\": [\n", " \"'*' ->respond_to_name name=INPUT\"\n", " ]\n", " },\n", " \"sleeping\": {\n", " \"onEnter\": \"'#/name# is sleeping'\",\n", " \"exits\": [\n", " \"wait:10 ->hungry\"\n", " ]\n", " },\n", " \"origin\": {\n", " \"onEnter\": \"'You have a kitten!' desired_pets=randomInt(1,5)\",\n", " \"exits\": [\n", " \"->name\"\n", " ]\n", " },\n", " \"hungry\": {\n", " \"onEnter\": \"'The kitten is hungry'\",\n", " \"exits\": [\n", " \"wait:10 ->angry\"\n", " ]\n", " },\n", " \"happy_pet\": {\n", " \"onEnter\": \"'#/name# loves you!'\",\n", " \"exits\": [\n", " \"wait:10 ->idle\"\n", " ]\n", " },\n", " \"respond_to_name\": {\n", " \"onEnter\": \"'The kitten purrs; I guess it likes #/name#!'\",\n", " \"exits\": [\n", " \"->idle\"\n", " ]\n", " },\n", " \"pet\": {\n", " \"onEnter\": \"'You pet the kitten' desired_pets--\",\n", " \"exits\": [\n", " \"desired_pets>=0 ->happy_pet\",\n", " \"->angry_pet\"\n", " ]\n", " },\n", " \"angry\": {\n", " \"onEnter\": \"*bite*\",\n", " \"exits\": [\n", " \"wait:10 ->sleeping\"\n", " ]\n", " },\n", " \"angry_pet\": {\n", " \"onEnter\": \"'Screech! #/name# doesn't want to be petted' desired_pets=randomInt(1,5)\",\n", " \"exits\": [\n", " \"->angry\"\n", " ]\n", " },\n", " \"idle\": {\n", " \"onEnter\": \"'#/name# makes cute noises!'\",\n", " \"exits\": [\n", " \"wait:10 ->hungry\"\n", " ]\n", " }\n", " },\n", " \"initialBlackboard\": {},\n", " \"exits\": [\n", " \"'pet' ->pet\"\n", " ],\n", " \"grammar\": {}\n", "}\n" ] } ], "source": [ "print(json.dumps(kitten.to_dict(), indent=2))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python [Root]", "language": "python", "name": "Python [Root]" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.3" } }, "nbformat": 4, "nbformat_minor": 1 }