def calculate(self, state, actions, goal=None, force_terminal=False,
                  agent_role='system'):
        """
        Calculate the reward to be assigned for taking action from state.


        :param state: the current state
        :param actions: the action taken from the current state
        :param goal: the agent's goal, used to assess success
        :param force_terminal: force state to be terminal
        :param agent_role: the role of the agent
        :return: a number, representing the calculated reward
        """

        reward = self.turn_penalty

        if goal is None:
            print('Warning: SlotFillingReward() called without a goal.')
            return 0, False, False

        else:
            dialogue_success = False

            if state.is_terminal() or force_terminal:
                # Check that an offer has actually been made
                if state.system_made_offer:
                    dialogue_success = True

                    # Check that the item offered meets the user's constraints
                    for constr in goal.constraints:
                        if goal.ground_truth:
                            # Multi-agent case
                            if goal.ground_truth[constr] != \
                                    goal.constraints[constr].value and \
                                    goal.constraints[constr].value != \
                                    'dontcare':
                                reward += self.failure_penalty
                                dialogue_success = False
                                break

                        elif state.item_in_focus:
                            # Single-agent case
                            if state.item_in_focus[constr] != \
                                    goal.constraints[constr].value and \
                                    goal.constraints[constr].value != \
                                    'dontcare':
                                reward += self.failure_penalty
                                dialogue_success = False
                                break

                    # Check that all requests have been addressed
                    if dialogue_success:
                        not_met = 0

                        if agent_role == 'system':
                            # Check that the system has responded to all
                            # requests (actually) made by the user
                            for req in goal.actual_requests:
                                if not goal.actual_requests[req].value:
                                    not_met += 1

                        elif agent_role == 'user':
                            # Check that the user has provided all the
                            # requests in the goal
                            for req in goal.requests:
                                if not goal.requests[req].value:
                                    not_met += 1

                        if not_met > 0:
                            reward += self.failure_penalty
                            dialogue_success = False
                        else:
                            reward = self.success_reward

                else:
                    reward += self.failure_penalty
                    dialogue_success = False

        # Liu & Lane ASRU 2017 Definition of task success
        task_success = None
        if agent_role == 'system':
            task_success = True
            # We don't care for slots that are not in the goal constraints
            for slot in goal.constraints:
                # If the system proactively informs about a slot the user has
                # not yet put a constraint upon,
                # the user's DState is updated accordingly and the user would
                # not need to put that constraint.
                if goal.ground_truth:
                    if goal.ground_truth[slot] != \
                            goal.constraints[slot].value and \
                            goal.constraints[slot].value != 'dontcare':
                        task_success = False
                        break

                # Fall back to the noisier signal, that is the slots filled.
                elif state.slots_filled[slot] != \
                        goal.constraints[slot].value and \
                        goal.constraints[slot].value != 'dontcare':
                    task_success = False
                    break

            for req in goal.requests:
                if not goal.requests[req].value:
                    task_success = False
                    break

        return reward, dialogue_success, task_success

        Calculate the reward to be assigned for taking action from state.


        :param state: the current state
        :param actions: the action taken from the current state
        :param goal: the agent's goal, used to assess success
        :param force_terminal: force state to be terminal
        :param agent_role: the role of the agent
        :return: a number, representing the calculated reward
        
plato/agent/component/dialogue_policy/reinforcement_learning/reward_function.py