Пример #1
0
    def setUp(self):
        self.tree = {
            'START': 'main',
            'AVATAR': 'npc.png',
            'SECTIONS': {
                'main': [
                    { "say": "Greetings stranger" },
                    { "responses": [
                        ["Hi, can you tell me where I am?", "friendly"],
                        ["Watch your words", "aggro"],
                        ["This one toggles", "toggles", "show == True"],
                        ["Always display this one", "display", "True and True"],
                        ["response3", "stop"],
                    ] }
                ],
                'friendly': [
                    { "say": "You sure are lost" },
                    { "responses": [
                        ["Thanks, I know", "thanks"],
                        ["Wait what did you say before?", "back"],
                    ] }
                ],
                'thanks': [
                    { "say": "We haven't seen one of your kind in ages" },
                    { "responses": [
                        ["Blah blah blah", "foo"],
                        ["Say the other thing again", "back"],
                    ] }
                ],
            }
        }
        # record actions in test_vars
        test_vars = { "say": None, "responses": [] }

        def say_cb(state, text):
            state["say"] = text

        self.replies = ["resp1", "back", "stop"]

        def npc_avatar_cb(state, image):
            state['npc_avatar'] = image

        def responses_cb(state, responses):
            state['responses'] = responses

        callbacks = {
            "say": say_cb,
            "responses": responses_cb,
            "npc_avatar": npc_avatar_cb
        }

        self.dialogue = DialogueEngine(self.tree, callbacks, test_vars)
Пример #2
0
    def __init__(self, npc):
        dialogue_callbacks = {
            'say': self.handleSay,
            'responses': self.handleResponses,
            'start_quest': self.startQuest,
            'complete_quest': self.completeQuest,
            'npc_avatar': self.handleAvatarImage,
            'end': self.handleEnd
        }

        # For testing purposes we're just using a a dummy player object  here
        # until we decide on a player/quest model.
        # TODO
        # link this up to the actual PC and NPC instances, so that state can
        # be persistent.
        pc = Player()
        self.npc = npc
        state = {
            'pc': pc
        }
        self.dialogue_engine = DialogueEngine('dialogue/sample.yaml',
                                              dialogue_callbacks, state)
        self.dialogue_gui = pychan.loadXML("gui/dialogue.xml")
Пример #3
0
    def __init__(self, npc, quest_engine, pc):
        self.pc = pc

        # define dialogue engine callbacks
        def start_quest(state, quest):
            print "You've picked up the '%s' quest!" % quest
            state['quest'].addQuest(quest)

        def complete_quest(state, quest_id):
            print "You've finished the quest %s" % quest_id
            state['quest'].finishQuest(quest_id)

        def delete_quest(state, quest_id):
            print "You've deleted quest %s" % quest_id
            state['quest'].deleteQuest(quest_id)

        def increase_value(state, quest_id, variable, value):
            print "Increased %s by %i"%(variable,value)
            state['quest'][quest_id].increaseValue(variable,value)

        def decrease_value(state, quest_id, variable, value):
            print "Decreased %s by %i"%(variable,value)
            state['quest'][quest_id].decreaseValue(variable,value)

        def set_value(state,quest_id, variable, value):
            print "Set %s to %s"%(variable,value)
            state['quest'][quest_id].setValue(variable,value)

        def meet(state, npc):
            print "You've met %s!" % npc
            state['pc'].meet(npc)

        def get_stuff(state, thing):
            if not state['pc'].inventory.has(thing):
                state['pc'].inventory.placeItem(thing)
                print "You've now have the %s" % thing

        def take_stuff(state,thing):
            if state['pc'].inventory.has(thing):
                state['pc'].inventory.takeItem(thing)
                print "You no longer have the %s" % thing

        dialogue_callbacks = {
            'complete_quest': complete_quest,
            'decrease_value': decrease_value,
            'delete_quest'  : delete_quest,
            'end'           : self.handleEnd,
            'get_stuff'     : get_stuff,
            'increase_value': increase_value,
            'meet'          : meet,
            'npc_name'      : self.handleNpcName,
            'npc_avatar'    : self.handleAvatarImage,
            'responses'     : self.handleResponses,
            'say'           : self.handleSay,
            'set_value'     : set_value,
            'start_quest'   : start_quest,
            'take_stuff'    : take_stuff
        }

        self.npc = npc
        state = {
            'pc': self.pc,
            'quest': quest_engine
        }
        self.dialogue_engine = DialogueEngine(npc.dialogue,
                                              dialogue_callbacks, state)
        self.dialogue_gui = pychan.loadXML("gui/dialogue.xml")
Пример #4
0
class DialogueGUI(object):
    def __init__(self, npc, quest_engine, pc):
        self.pc = pc

        # define dialogue engine callbacks
        def start_quest(state, quest):
            print "You've picked up the '%s' quest!" % quest
            state['quest'].addQuest(quest)

        def complete_quest(state, quest_id):
            print "You've finished the quest %s" % quest_id
            state['quest'].finishQuest(quest_id)

        def delete_quest(state, quest_id):
            print "You've deleted quest %s" % quest_id
            state['quest'].deleteQuest(quest_id)

        def increase_value(state, quest_id, variable, value):
            print "Increased %s by %i"%(variable,value)
            state['quest'][quest_id].increaseValue(variable,value)

        def decrease_value(state, quest_id, variable, value):
            print "Decreased %s by %i"%(variable,value)
            state['quest'][quest_id].decreaseValue(variable,value)

        def set_value(state,quest_id, variable, value):
            print "Set %s to %s"%(variable,value)
            state['quest'][quest_id].setValue(variable,value)

        def meet(state, npc):
            print "You've met %s!" % npc
            state['pc'].meet(npc)

        def get_stuff(state, thing):
            if not state['pc'].inventory.has(thing):
                state['pc'].inventory.placeItem(thing)
                print "You've now have the %s" % thing

        def take_stuff(state,thing):
            if state['pc'].inventory.has(thing):
                state['pc'].inventory.takeItem(thing)
                print "You no longer have the %s" % thing

        dialogue_callbacks = {
            'complete_quest': complete_quest,
            'decrease_value': decrease_value,
            'delete_quest'  : delete_quest,
            'end'           : self.handleEnd,
            'get_stuff'     : get_stuff,
            'increase_value': increase_value,
            'meet'          : meet,
            'npc_name'      : self.handleNpcName,
            'npc_avatar'    : self.handleAvatarImage,
            'responses'     : self.handleResponses,
            'say'           : self.handleSay,
            'set_value'     : set_value,
            'start_quest'   : start_quest,
            'take_stuff'    : take_stuff
        }

        self.npc = npc
        state = {
            'pc': self.pc,
            'quest': quest_engine
        }
        self.dialogue_engine = DialogueEngine(npc.dialogue,
                                              dialogue_callbacks, state)
        self.dialogue_gui = pychan.loadXML("gui/dialogue.xml")

    def initiateDialogue(self):
        """Callback for starting a quest"""
        stats_label = self.dialogue_gui.findChild(name='stats_label')
        stats_label.text = u'Name: John Doe\nAn unnamed one'

        events = {
            'end_button': self.handleEnd
        }
        self.dialogue_gui.mapEvents(events)
        self.dialogue_gui.show()
        responses_list = self.dialogue_gui.findChild(name='choices_list')
        responses = self.dialogue_engine.run()
        self.setResponses(responses)

    def handleSay(self, state, say):
        """Callback for NPC speech"""
        speech = self.dialogue_gui.findChild(name='speech')
        # to append text to npc speech box, uncomment the following line
        #speech.text = speech.text + "\n-----\n" + unicode(say)
        speech.text = unicode(say)

    def handleEntered(self, *args):
        """Callback for when user hovers over response label"""
        pass

    def handleExited(self, *args):
        """Callback for when user hovers out of response label"""
        pass

    def handleClicked(self, *args):
        """Handle a response being clicked"""
        response = int(args[0].name.replace('response', ''))
        if not self.dialogue_engine.reply(response):
            self.handleEnd()

    def handleEnd(self):
        """Handle the end of the conversation being reached. Either from the
           GUI or from within the conversation itself."""
        self.dialogue_engine = None
        self.dialogue_gui.hide()
        self.npc.behaviour.state = 1
        self.npc.behaviour.idle()

    def handleNpcName(self, name):
        """Callback to handle setting the NPC name.
           @type name: str
           @param name: The name of the NPC to set. """
        
        stats_label = self.dialogue_gui.findChild(name='stats_label')
        try:
            (first_name, desc) = name.split(" ",1)
            stats_label.text = u'Name: ' + first_name + "\n" + desc
        except:
            stats_label.text = u'Name: ' + name 
            
        self.dialogue_gui.title = name
        
    def handleAvatarImage(self, image):
        """Callback to handle when the dialogue engine wants to set the NPC 
        image
           @type image: str
           @param image: filename of avatar image"""
        avatar_image = self.dialogue_gui.findChild(name='npc_avatar')
        avatar_image.image = image

    def handleResponses(self, *args):
        """Callback to handle when the dialogue engine wants to display a new
           list of options"""
        self.setResponses(args[1])

    def setResponses(self, responses):
        """Creates the list of clickable response labels and sets their
           respective on-click callbacks
           @type responses: [ [ "response text", section, condition ], ...]
           @param responses: the list of response objects from the dialogue
                             engine"""
        choices_list = self.dialogue_gui.findChild(name='choices_list')
        choices_list.removeAllChildren()
        for i,r in enumerate(responses):
            button = widgets.Label(
                name="response%s"%(i,),
                text=unicode(r[0]),
                hexpand="1",
                min_size=(100,16),
                max_size=(490,48),
                position_technique='center:center'
            )
            button.margins = (5,5)
            button.background_color = fife.Color(0,0,0)
            button.color = fife.Color(0,255,0)
            button.border_size = 0
            button.wrap_text = 1
            button.capture(lambda button=button: self.handleEntered(button), \
                           event_name='mouseEntered')
            button.capture(lambda button=button: self.handleExited(button), \
                           event_name='mouseExited')
            button.capture(lambda button=button: self.handleClicked(button), \
                           event_name='mouseClicked')
            choices_list.addChild(button)
            self.dialogue_gui.adaptLayout(True)
Пример #5
0
class TestDialogue(unittest.TestCase):
    def setUp(self):
        self.tree = {
            'START': 'main',
            'AVATAR': 'npc.png',
            'SECTIONS': {
                'main': [
                    { "say": "Greetings stranger" },
                    { "responses": [
                        ["Hi, can you tell me where I am?", "friendly"],
                        ["Watch your words", "aggro"],
                        ["This one toggles", "toggles", "show == True"],
                        ["Always display this one", "display", "True and True"],
                        ["response3", "stop"],
                    ] }
                ],
                'friendly': [
                    { "say": "You sure are lost" },
                    { "responses": [
                        ["Thanks, I know", "thanks"],
                        ["Wait what did you say before?", "back"],
                    ] }
                ],
                'thanks': [
                    { "say": "We haven't seen one of your kind in ages" },
                    { "responses": [
                        ["Blah blah blah", "foo"],
                        ["Say the other thing again", "back"],
                    ] }
                ],
            }
        }
        # record actions in test_vars
        test_vars = { "say": None, "responses": [] }

        def say_cb(state, text):
            state["say"] = text

        self.replies = ["resp1", "back", "stop"]

        def npc_avatar_cb(state, image):
            state['npc_avatar'] = image

        def responses_cb(state, responses):
            state['responses'] = responses

        callbacks = {
            "say": say_cb,
            "responses": responses_cb,
            "npc_avatar": npc_avatar_cb
        }

        self.dialogue = DialogueEngine(self.tree, callbacks, test_vars)

    def assert_say(self, text):
        self.assertEqual(text, self.dialogue.state['say'])

    def assert_responses(self, responses):
        self.assertEqual(responses, self.dialogue.state['responses'])

    def assert_npc_image(self, image):
        self.assertEqual(image, self.dialogue.state['npc_avatar'])

    def test_simple(self):
        """Test basic dialogue interaction"""
        self.dialogue.state['show'] = False
        self.dialogue.run()

        self.assert_npc_image('npc.png')
        self.assert_say('Greetings stranger')
        self.assert_responses([
            ["Hi, can you tell me where I am?", "friendly"],
            ["Watch your words", "aggro"],
            ["Always display this one", "display", "True and True"],
            ["response3", "stop"],
        ])
        self.dialogue.reply(0)

        self.assert_say('You sure are lost')
        self.assert_responses([
            ["Thanks, I know", "thanks"],
            ["Wait what did you say before?", "back"]
        ])
        self.dialogue.state['show'] = True
        self.dialogue.reply(1)

        self.assert_say('Greetings stranger')
        self.assert_responses([
            ["Hi, can you tell me where I am?", "friendly"],
            ["Watch your words", "aggro"],
            ["This one toggles", "toggles", "show == True"],
            ["Always display this one", "display", "True and True"],
            ["response3", "stop"],
        ])
        self.dialogue.reply(0)

        self.assert_say('You sure are lost')
        self.dialogue.reply(1)

        self.assert_say('Greetings stranger')
        self.dialogue.reply(0)

        self.assert_say('You sure are lost')
        self.dialogue.reply(0)

        self.assert_say("We haven't seen one of your kind in ages")
        self.dialogue.reply(1)

        self.assert_say('You sure are lost')
        self.dialogue.reply(1)

        self.assert_say('Greetings stranger')
Пример #6
0
    def setUp(self):
        self.tree = {
            'NPC': 'Mr. Npc',
            'START': 'main',
            'AVATAR': 'gui/icons/npc.png',
            'SECTIONS': {
                'main': [
                    { "say": "Greetings stranger" },
                    { "responses": [
                        ["Hi, can you tell me where I am?", "friendly"],
                        ["Watch your words", "aggro"],
                        ["This one toggles", "toggles", "show == True"],
                        ["Always display this one", "display", "True and True"],
                        ["response3", "end"],
                    ] }
                ],
                'friendly': [
                    { "say": "You sure are lost" },
                    { "responses": [
                        ["Thanks, I know", "thanks"],
                        ["Wait what did you say before?", "back"],
                    ] }
                ],
                'aggro': [
                    { "say": "Die Pig! PAAAAR!!!!" },
                    { "responses": [
                        ["ruh-ro raggy!", "toggles"],
                        ["Uh, just kidding??", "back"],
                    ] }
                ],
                'toggles': [
                    { "say": "you turn me on!" },
                    { "responses": [
                        ["you turn me off", "back"],
                    ] }
                ],
                'display': [
                    { "say": "Forever Young!" },
                    { "responses": [
                        ["Alphaville sucks!", "back"],
                    ] }
                ],
                'thanks': [
                    { "say": "We haven't seen one of your kind in ages" },
                    { "responses": [
                        ["Blah blah blah", "display"],
                        ["Say the other thing again", "back"],
                    ] }
                ],
            }
        }
        # record actions in test_vars
        test_vars = { "say": None, "responses": [] }

        def sayCb(state, text):
            state["say"] = text

        self.replies = ["resp1", "back", "end"]

        def npcAvatarCb(state, image):
            state['npc_avatar'] = image

        def responsesCb(state, responses):
            state['responses'] = responses

        callbacks = {
            "say": sayCb,
            "responses": responsesCb,
            "npc_avatar": npcAvatarCb
        }

        self.dialogue = DialogueEngine(self.tree, callbacks, test_vars)
Пример #7
0
class TestDialogue(unittest.TestCase):
    def setUp(self):
        self.tree = {
            'NPC': 'Mr. Npc',
            'START': 'main',
            'AVATAR': 'gui/icons/npc.png',
            'SECTIONS': {
                'main': [
                    { "say": "Greetings stranger" },
                    { "responses": [
                        ["Hi, can you tell me where I am?", "friendly"],
                        ["Watch your words", "aggro"],
                        ["This one toggles", "toggles", "show == True"],
                        ["Always display this one", "display", "True and True"],
                        ["response3", "end"],
                    ] }
                ],
                'friendly': [
                    { "say": "You sure are lost" },
                    { "responses": [
                        ["Thanks, I know", "thanks"],
                        ["Wait what did you say before?", "back"],
                    ] }
                ],
                'aggro': [
                    { "say": "Die Pig! PAAAAR!!!!" },
                    { "responses": [
                        ["ruh-ro raggy!", "toggles"],
                        ["Uh, just kidding??", "back"],
                    ] }
                ],
                'toggles': [
                    { "say": "you turn me on!" },
                    { "responses": [
                        ["you turn me off", "back"],
                    ] }
                ],
                'display': [
                    { "say": "Forever Young!" },
                    { "responses": [
                        ["Alphaville sucks!", "back"],
                    ] }
                ],
                'thanks': [
                    { "say": "We haven't seen one of your kind in ages" },
                    { "responses": [
                        ["Blah blah blah", "display"],
                        ["Say the other thing again", "back"],
                    ] }
                ],
            }
        }
        # record actions in test_vars
        test_vars = { "say": None, "responses": [] }

        def sayCb(state, text):
            state["say"] = text

        self.replies = ["resp1", "back", "end"]

        def npcAvatarCb(state, image):
            state['npc_avatar'] = image

        def responsesCb(state, responses):
            state['responses'] = responses

        callbacks = {
            "say": sayCb,
            "responses": responsesCb,
            "npc_avatar": npcAvatarCb
        }

        self.dialogue = DialogueEngine(self.tree, callbacks, test_vars)

    def assertSay(self, text):
        self.assertEqual(text, self.dialogue.state['say'])

    def assertResponses(self, responses):
        self.assertEqual(responses, self.dialogue.state['responses'])

    def assertNpcImage(self, image):
        self.assertEqual(image, self.dialogue.state['npc_avatar'])

    def testSimple(self):
        """Test basic dialogue interaction"""
        self.dialogue.state['show'] = False
        self.dialogue.run()

        self.assertNpcImage('gui/icons/npc.png')
        self.assertSay('Greetings stranger')
        self.assertResponses([
            ["Hi, can you tell me where I am?", "friendly"],
            ["Watch your words", "aggro"],
            ["Always display this one", "display", "True and True"],
            ["response3", "end"],
        ])
        self.dialogue.reply(0)

        self.assertSay('You sure are lost')
        self.assertResponses([
            ["Thanks, I know", "thanks"],
            ["Wait what did you say before?", "back"]
        ])
        self.dialogue.state['show'] = True
        self.dialogue.reply(1)

        self.assertSay('Greetings stranger')
        self.assertResponses([
            ["Hi, can you tell me where I am?", "friendly"],
            ["Watch your words", "aggro"],
            ["This one toggles", "toggles", "show == True"],
            ["Always display this one", "display", "True and True"],
            ["response3", "end"],
        ])
        self.dialogue.reply(0)

        self.assertSay('You sure are lost')
        self.dialogue.reply(1)

        self.assertSay('Greetings stranger')
        self.dialogue.reply(0)

        self.assertSay('You sure are lost')
        self.dialogue.reply(0)

        self.assertSay("We haven't seen one of your kind in ages")
        self.dialogue.reply(1)

        self.assertSay('You sure are lost')
        self.dialogue.reply(1)

        self.assertSay('Greetings stranger')

    def testAllDialogueFiles(self):
        """ Runs the validator on all dialogue files available. """
        
        val = DialogueValidator()
        diag_dir = os.path.join(os.path.curdir, "dialogue");
        num_faulty_files = 0
        
        # Test the dialogue files 
        for dialogue in os.listdir(diag_dir):
            fname = os.path.join(diag_dir, dialogue)
            if os.path.isfile(fname) :
                try:
                    assert(val.validateDialogueFromFile(fname,"."))
                except DialogueFormatException as dfe:
                    print "\nError found in file: ", fname 
                    print "Error was: %s" % (dfe)
                    num_faulty_files += 1
        
        # Test the internal tree 
        try:
            assert(val.validateDialogue(self.tree,"."))
        except DialogueFormatException, dfe:
            print "\nError found in internal tree: ", fname 
            print "Error was: %s" % (dfe)
            num_faulty_files += 1            
        
        assert(num_faulty_files == 0)
Пример #8
0
class DialogueGUI(object):
    def __init__(self, npc):
        dialogue_callbacks = {
            'say': self.handleSay,
            'responses': self.handleResponses,
            'start_quest': self.startQuest,
            'complete_quest': self.completeQuest,
            'npc_avatar': self.handleAvatarImage,
            'end': self.handleEnd
        }

        # For testing purposes we're just using a a dummy player object  here
        # until we decide on a player/quest model.
        # TODO
        # link this up to the actual PC and NPC instances, so that state can
        # be persistent.
        pc = Player()
        self.npc = npc
        state = {
            'pc': pc
        }
        self.dialogue_engine = DialogueEngine('dialogue/sample.yaml',
                                              dialogue_callbacks, state)
        self.dialogue_gui = pychan.loadXML("gui/dialogue.xml")

    def startQuest(self, state, quest):
        """Callback for starting a quest"""
        print "You've picked up the '%s' quest!" % quest,
        state['pc'].startQuest(quest)

    def completeQuest(self, state, quest):
        """Callback for starting a quest"""
        print "You've finished the '%s' quest" % quest
        state['pc'].completeQuest(quest)

    def initiateDialogue(self):
        """Callback for starting a quest"""
        stats_label = self.dialogue_gui.findChild(name='stats_label')
        stats_label.text = u'Name: Ronwell\nA grizzled villager'

        events = {
            'end_button': self.handleEnd
        }
        self.dialogue_gui.mapEvents(events)
        self.dialogue_gui.show()
        responses_list = self.dialogue_gui.findChild(name='choices_list')
        responses = self.dialogue_engine.run()
        self.setResponses(responses)

    def handleSay(self, state, say):
        """Callback for NPC speech"""
        speech = self.dialogue_gui.findChild(name='speech')
        # to append text to npc speech box, uncomment the following line
        #speech.text = speech.text + "\n-----\n" + unicode(say)
        speech.text = unicode(say)

    def handleEntered(self, *args):
        """Callback for when user hovers over response label"""
        pass

    def handleExited(self, *args):
        """Callback for when user hovers out of response label"""
        pass

    def handleClicked(self, *args):
        """Handle a response being clicked"""
        response = int(args[0].name.replace('response', ''))
        if not self.dialogue_engine.reply(response):
            self.handleEnd()

    def handleEnd(self):
        """Handle the end of the conversation being reached. Either from the
           GUI or from within the conversation itself."""
        self.dialogue_engine = None
        self.dialogue_gui.hide()
        self.npc.behaviour.state = 1
        self.npc.behaviour.idle()

    def handleAvatarImage(self, state, image):
        """Callback to handle when the dialogue engine wants to set the NPC image
           @type image: str
           @param image: filename of avatar image"""
        avatar_image = self.dialogue_gui.findChild(name='npc_avatar')
        avatar_image.image = image

    def handleResponses(self, *args):
        """Callback to handle when the dialogue engine wants to display a new
           list of options"""
        self.setResponses(args[1])

    def setResponses(self, responses):
        """Creates the list of clickable response labels and sets their
           respective on-click callbacks
           @type responses: [ [ "response text", section, condition ], ...]
           @param responses: the list of response objects from the dialogue
                             engine"""
        choices_list = self.dialogue_gui.findChild(name='choices_list')
        choices_list.removeAllChildren()
        for i,r in enumerate(responses):
            button = widgets.Label(
                name="response%s"%(i,),
                text=unicode(r[0]),
                hexpand="1",
                min_size=(100,16),
                max_size=(490,48),
                position_technique='center:center'
            )
            button.margins = (5,5)
            button.background_color = fife.Color(0,0,0)
            button.color = fife.Color(0,255,0)
            button.border_size = 0
            button.wrap_text = 1
            button.capture(lambda button=button: self.handleEntered(button), \
                           event_name='mouseEntered')
            button.capture(lambda button=button: self.handleExited(button), \
                           event_name='mouseExited')
            button.capture(lambda button=button: self.handleClicked(button), \
                           event_name='mouseClicked')
            choices_list.addChild(button)
            self.dialogue_gui.adaptLayout(True)