Example #1
0
 def __init__(self, o, c, e, a, n):
     self.personality = Personality(o, c, e, a, n)
     self.mood = self.personality.to_mood()
     self.emotions = []
     # Like/dislike relationships with objects
     self.relationships = {}
     self.beliefs = Beliefs()
     self.children = []
     super(Agent, self).__init__()
Example #2
0
 def test_get_unknown_entity_attr(self):
     """
     Test that an exception is raised when getting an attr
     of an unknown entity.
     """
     beliefs = Beliefs()
     entity = Object()
     with self.assertRaises(Exception):
         beliefs.get_entity_attr(entity.entity_id, 'alive')
Example #3
0
 def test_set_belief_unknown_entity(self):
     """
     Test an error is raised when setting a belief
     on an unregistered entity.
     """
     beliefs = Beliefs()
     entity = Object()
     belief = EntityAttrBelief(0, entity.entity_id, 'alive', True)
     with self.assertRaises(Exception):
         beliefs.set_belief(belief)
Example #4
0
 def test_set_entity_entity_belief(self):
     """Test that you can set an EntityEntityBelief."""
     # Register an entity
     beliefs = Beliefs()
     entity_1 = Object()
     entity_2 = Object()
     beliefs.register_entity(entity_1.entity_id)
     beliefs.register_entity(entity_2.entity_id)
     # Set a belief
     belief_1 = EntityEntityBelief(
         0, entity_1.entity_id, entity_2.entity_id, RELATIONSHIPS.IS, 1)
     beliefs.set_belief(belief_1)
     self.assertEqual(beliefs.beliefs_count(), 1)
     # Overwrite the belief
     belief_2 = EntityEntityBelief(
         1, entity_1.entity_id, entity_2.entity_id, RELATIONSHIPS.IS, 0)
     beliefs.set_belief(belief_2)
     self.assertEqual(beliefs.beliefs_count(), 1)
Example #5
0
 def test_get_entity_attr_belief(self):
     """Test that you can get entity attrs with defaults."""
     beliefs = Beliefs()
     entity = Object()
     beliefs.register_entity(entity.entity_id)
     # Set an attr belief
     belief = EntityAttrBelief(0, entity.entity_id, 'likes_icecream', 1)
     beliefs.set_belief(belief)
     # Get the attr back
     likes_icecream = beliefs.get_entity_attr(entity.entity_id, 'likes_icecream')
     self.assertEqual(likes_icecream, 1)
     # Get an unset attr with defaults
     alive = beliefs.get_entity_attr(entity.entity_id, 'alive', default=1)
     self.assertEqual(alive, 1)
Example #6
0
 def test_get_entity_attr_belief_not_found(self):
     """Test an exception is raised when no such belief exists."""
     beliefs = Beliefs()
     entity = Object()
     beliefs.register_entity(entity.entity_id)
     with self.assertRaises(BeliefNotFound):
         beliefs.get_entity_attr(entity.entity_id, 'likes_icecream')
Example #7
0
class Agent(Object):
    """An object that has a mood."""
    beliefs = None
    children = None
    culture = None
    emotions = None
    mood = None
    parents = None
    personality = None
    _preferences = None

    def __init__(self, o, c, e, a, n):
        self.personality = Personality(o, c, e, a, n)
        self.mood = self.personality.to_mood()
        self.emotions = []
        # Like/dislike relationships with objects
        self.relationships = {}
        self.beliefs = Beliefs()
        self.children = []
        super(Agent, self).__init__()

    def __str__(self):
        return self.name.encode('utf-8')

    def __unicode__(self):
        return self.name

    @classmethod
    def from_personality(cls, p):
        agent = Agent(p.o, p.c, p.e, p.a, p.n)
        return agent

    def set_preferences(self, preferences):
        agent_preferences = deepcopy(preferences)
        assert (isinstance(agent_preferences, Preferences))
        self._preferences = agent_preferences

    def get_preferences(self):
        if self._preferences is None:
            self._preferences = Preferences()
        return self._preferences

    def emotions_for_object(self, obj):
        emotions = []
        c = self.get_culture()
        l = c.get_love(obj)
        if l > 0:
            e = Love(l)
            emotions.append(e)
        if l < 0:
            e = Hate(l)
            emotions.append(e)
        return emotions

    def emotions_for_action(self,
                            action,
                            agent_entity_id,
                            obj_entity_id,
                            prob,
                            prior_prob=None):
        """
        Generate a list of emotions for actions based on
        probability of the action happening.
        """
        assert (isinstance(agent_entity_id, basestring))
        assert (isinstance(obj_entity_id, basestring))
        emotions = []
        # Calculate the expected joy/distress at an event's success
        joy_distress = self._expected_joy_distress(action, agent_entity_id,
                                                   obj_entity_id)
        if prob > 0 and prob < 1:
            if 'joy' in joy_distress:
                # Possible joyful event
                j = joy_distress['joy']
                e = Hope(j * prob)
                emotions.append(e)
            if 'distress' in joy_distress:
                # Possible distressing event
                d = joy_distress['distress']
                e = Fear(d * prob)
                emotions.append(e)

        if prob == 0 and prior_prob is not None:
            if prior_prob > 0:
                # Disconfirmed hope/fear
                if 'joy' in joy_distress:
                    # Disconfirmed hoped-for outcome
                    j = joy_distress['joy']
                    e = Disappointment(j * prior_prob)
                    emotions.append(e)
                if 'distress' in joy_distress:
                    # Disconfirmed feared outcome
                    d = joy_distress['distress']
                    e = Relief(j * prior_prob)
                    emotions.append(e)

        if prob == 1:
            confirmed_outcome_emotions = self._emotions_for_observed_action(
                action, agent_entity_id, obj_entity_id)
            emotions.extend(confirmed_outcome_emotions)
        return emotions

    def _expected_joy_distress(self, action, agent_entity_id, obj_entity_id):
        """Calculate the expected joy and distress at an actions success."""
        assert (isinstance(agent_entity_id, basestring))
        assert (isinstance(obj_entity_id, basestring))
        emotions = self._emotions_for_observed_action(action, agent_entity_id,
                                                      obj_entity_id)
        j = None
        d = None
        for e in emotions:
            if isinstance(e, Joy):
                j = e.amount
            if isinstance(e, Distress):
                d = e.amount
        hope_fear = {}
        if j:
            hope_fear['joy'] = j
        if d:
            hope_fear['distress'] = d
        return hope_fear

    def _emotions_for_observed_action(self, action, agent_entity_id,
                                      obj_entity_id):
        agent_emotions = self._action_agent_emotions(action, agent_entity_id)
        obj_emotions = self._action_object_emotions(action, obj_entity_id)
        emotions = agent_emotions + obj_emotions
        return emotions

    def _action_agent_emotions(self, action, agent_entity_id):
        assert (isinstance(agent_entity_id, basestring))
        preferences = self.get_preferences()
        if preferences is None:
            raise Exception("Cannot calculate emotions without a culture.")

        p = preferences.get_praiseworthiness(action)
        emotions = []
        related_entities = self.beliefs.get_related_entities(agent_entity_id)
        # Only count emotions for self once
        if self.entity_id in related_entities:
            related_entities = [self.entity_id]
        # These emotions are agnostic of the relationship between the
        # observer and the subject, thus we only calculate once for
        # each entity, though there may be many related entities.
        if agent_entity_id == self.entity_id:
            # Self-initiated
            if p > 0:
                # Praiseworthy
                e = Pride(p)
                emotions.append(e)
            if p < 0:
                # Shameworthy
                e = Remorse(-1 * p)
                emotions.append(e)
        else:
            # Other-initiaed
            if p > 0:
                # Praiseworthy
                e = Gratitude(p)
                emotions.append(e)
            if p < 0:
                # Shameworthy
                e = Anger(-1 * p)
                emotions.append(e)
        return emotions

    def _action_object_emotions(self, action, obj_entity_id):
        assert (isinstance(obj_entity_id, basestring))
        preferences = self.get_preferences()
        if preferences is None:
            raise Exception("Cannot calculate emotions without a culture.")
        g = preferences.get_goodness(action)
        emotions = []
        related_entities = self.beliefs.get_related_entities(obj_entity_id)
        # Only count emotions felt for self once
        if self.entity_id in related_entities:
            related_entities = [self.entity_id]
        # Loop through all entities that are the same concept and return
        # any emotions the action induces. For example, if The Red Knight is
        # terrible but turns out to be the same as Lancelot, when Lancelot is
        # hurt, people will feel bad for him as Lancelot (a good guy) but will
        # gloat over the bad thing happening to the person they knew as The Red
        # Knight.
        for related_obj_entity_id in related_entities:
            l = preferences.get_love(related_obj_entity_id)
            if related_obj_entity_id == self.entity_id:
                if g > 0:
                    # Good thing happened
                    e = Joy(g)
                    emotions.append(e)
                if g < 0:
                    # Bad thing happened
                    e = Distress(-1 * g)
                    emotions.append(e)
            else:
                if l > 0:
                    # Something happened to a liked agent
                    if g > 0:
                        # Good thing happened
                        e = HappyFor(l * g)
                        emotions.append(e)
                    if g < 0:
                        # Bad thing happened
                        e = SorryFor(l * g * -1)
                        emotions.append(e)
                if l < 0:
                    # Something happened to a disliked agent
                    if g > 0:
                        # Good thing happened
                        e = Resentment(-1 * l * g)
                        emotions.append(e)
                    if g < 0:
                        # Bad thing happened
                        e = Gloating(l * g)
                        emotions.append(e)
        return emotions

    def tick_mood(self):
        """Update mood state."""
        # Decay emotion amounts
        decayed_emotions = []
        for emotion in self.emotions:
            emotion.amount /= 2.0
            # Remove any emotions below the perceptible threshold
            if emotion.amount > EMOTION_THRESHOLD:
                decayed_emotions.append(emotion)
        self.emotions = decayed_emotions

        # Set a new mood based on decayed emotions
        mood = self.personality.to_mood()
        mood.update_from_emotions(decayed_emotions)
        self.mood = mood

    def set_parents(self, parent_1, parent_2):
        if not isinstance(parent_1, Agent) or not isinstance(parent_2, Agent):
            raise ValueError("Parents must be agents")
        self.parents = [parent_1, parent_2]

    def add_child(self, child):
        if child not in self.children:
            self.children.append(child)

    @classmethod
    def create_random_agent(cls, gender=None, origin="anglo-saxon"):
        """Create a first-generation agent."""
        # Randomize the personality
        o = random.random() * 2 - 1
        c = random.random() * 2 - 1
        e = random.random() * 2 - 1
        a = random.random() * 2 - 1
        n = random.random() * 2 - 1
        agent = cls(o, c, e, a, n)
        if gender is None:
            gender = random.choice([GENDERS.MALE, GENDERS.FEMALE])
        agent.gender = gender
        agent.name = generate_name(gender, origin=origin)
        return agent
Example #8
0
 def test_set_entity_attr_belief(self):
     """Test that you can set an EntityAttrBelief."""
     # Register an entity
     beliefs = Beliefs()
     entity = Object()
     beliefs.register_entity(entity.entity_id)
     # Set a belief
     self.assertEqual(beliefs.beliefs_count(), 0)
     belief_1 = EntityAttrBelief(0, entity.entity_id, 'alive', 1)
     beliefs.set_belief(belief_1)
     self.assertEqual(beliefs.beliefs_count(), 1)
     # Overwrite the belief
     belief_2 = EntityAttrBelief(1, entity.entity_id, 'alive', 0)
     beliefs.set_belief(belief_2)
     self.assertEqual(beliefs.beliefs_count(), 1)
Example #9
0
    def test_all_related_entities(self):
        """Test that all related entities are returned using 'is'."""
        beliefs = Beliefs()
        entity_1 = Object()
        beliefs.register_entity(entity_1.entity_id)
        entity_2 = Object()
        beliefs.register_entity(entity_2.entity_id)
        entity_3 = Object()
        beliefs.register_entity(entity_3.entity_id)

        beliefs.set_entity_is_entity(0, entity_1.entity_id, entity_2.entity_id, 1)
        beliefs.set_entity_is_entity(0, entity_2.entity_id, entity_3.entity_id, 1)

        related_entities = beliefs.get_related_entities(entity_1.entity_id)
        self.assertEqual(len(related_entities), 3)
        self.assertIn(entity_1.entity_id, related_entities)
        self.assertIn(entity_2.entity_id, related_entities)
        self.assertIn(entity_3.entity_id, related_entities)
Example #10
0
 def test_register_entity(self):
     beliefs = Beliefs()
     entity = Object()
     self.assertEqual(beliefs.entities_count(), 0)
     beliefs.register_entity(entity.entity_id)
     self.assertEqual(beliefs.entities_count(), 1)