def next_action(self, dialogue_state):
        """
        Generate a response given which conditions are met by the current
        dialogue state.

        :param dialogue_state:
        :return:
        """
        # Check for terminal state
        if dialogue_state.is_terminal_state:
            return [DialogueAct('bye', [DialogueActItem('', Operator.EQ, '')])]

        # Check if the user has made any requests
        elif dialogue_state.requested_slot:
            if dialogue_state.item_in_focus and \
                    dialogue_state.system_made_offer:
                requested_slot = dialogue_state.requested_slot

                # Reset request as we attempt to address it
                dialogue_state.requested_slot = ''

                value = 'not available'
                if requested_slot in dialogue_state.item_in_focus and \
                        dialogue_state.item_in_focus[requested_slot]:
                    value = dialogue_state.item_in_focus[requested_slot]

                return \
                    [DialogueAct(
                        'inform',
                        [DialogueActItem(requested_slot, Operator.EQ, value)])]

            # Else, if no item is in focus or no offer has been made,
            # ignore the user's request

        # Try to fill slots
        requestable_slots = \
            deepcopy(self.ontology.ontology['system_requestable'])

        if not hasattr(dialogue_state, 'requestable_slot_entropies') or \
                not dialogue_state.requestable_slot_entropies:
            slot = random.choice(requestable_slots)

            while dialogue_state.slots_filled[slot] and \
                    len(requestable_slots) > 1:
                requestable_slots.remove(slot)
                slot = random.choice(requestable_slots)

        else:
            slot = ''
            slots = \
                [k for k, v in
                 dialogue_state.requestable_slot_entropies.items()
                 if v == max(
                    dialogue_state.requestable_slot_entropies.values())
                 and v > 0 and k in requestable_slots]

            if slots:
                slot = random.choice(slots)

                while dialogue_state.slots_filled[slot] \
                        and dialogue_state.requestable_slot_entropies[
                    slot] > 0 \
                        and len(requestable_slots) > 1:
                    requestable_slots.remove(slot)
                    slots = \
                        [k for k, v in
                         dialogue_state.requestable_slot_entropies.items()
                         if v == max(
                            dialogue_state.requestable_slot_entropies.values())
                         and k in requestable_slots]

                    if slots:
                        slot = random.choice(slots)
                    else:
                        break

        if slot and not dialogue_state.slots_filled[slot]:
            return [DialogueAct(
                'request',
                [DialogueActItem(slot, Operator.EQ, '')])]

        elif dialogue_state.item_in_focus:
            name = dialogue_state.item_in_focus['name'] \
                if 'name' in dialogue_state.item_in_focus \
                else 'unknown'

            dacts = [DialogueAct(
                'offer',
                [DialogueActItem('name', Operator.EQ, name)])]

            for slot in dialogue_state.slots_filled:
                if slot != 'requested' and dialogue_state.slots_filled[slot]:
                    if slot in dialogue_state.item_in_focus:
                        if slot not in ['id', 'name']:
                            dacts.append(
                                DialogueAct(
                                    'inform',
                                    [DialogueActItem(
                                        slot,
                                        Operator.EQ,
                                        dialogue_state.item_in_focus[slot])]))
                    else:
                        dacts.append(DialogueAct(
                            'inform',
                            [DialogueActItem(
                                slot,
                                Operator.EQ,
                                'no info')]))

            return dacts
        else:
            # Fallback action - cannot help!
            # Note: We can have this check (no item in focus) at the beginning,
            # but this would assume that the system
            # queried a database before coming in here.
            return [DialogueAct('canthelp', [])]

        Generate a response given which conditions are met by the current
        dialogue state.

        :param dialogue_state:
        :return:
        
plato/agent/component/dialogue_policy/slot_filling_policy.py