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 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')
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)
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)
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)
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')
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
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)
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)
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)