/****************************************************************************** * Top-level Emotion Understanding Agent. * todo: Anger reduces friendship level slightly, increases enemy level. ******************************************************************************/ void UA_Emotion(Actor *ac, Ts *ts, Obj *a, Obj *in) { Obj *emot_class, *from, *to; ObjList *p, *causes; if (GetActorSpatial(in, a, &from, &to)) { /* todo: If you ptrans to a place you like, you are happy. */ } else if (ISA(N("emotion"), I(in, 0)) && (!ISA(N("attitude"), I(in, 0))) && a == I(in, 1)) { /* [happy Jim] [sad Jim] [happy-for Mary Mary-roommate] */ emot_class = I(in, 0); for (p = ac->emotions; p; p = p->next) { if (I(p->obj, 0) == emot_class) { /* Emotion is same as an existing one: alter intensity. * For example, after A canceling an appointment with B, the input * "B is angry at A" makes sense because this emotion was * already added by the cancel. */ ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_TOTAL, NOVELTY_EXPECTED); if ((causes = CAUSES(p->obj, ac->cx))) { ContextAddMakeSenseReasons(ac->cx, causes); ObjListFree(causes); } ObjWeightSet(p->obj, ObjWeight(p->obj) + ObjWeight(in)); return; } /* todo: Perhaps handle emotion specifications and generalizations. * But this might not have so much meaning: You can be both happy * and proud. */ } UA_Emotion1(ac, ts, a, in); UA_EmotionAdd(ac, ts, in, NULL, NULL); } }
void ContextSetJustifiedSenses(Context *cx, Float sense, ObjList *justifications) { ContextSetSense(cx, sense); if (sense <= SENSE_LITTLE) { ContextAddNotMakeSenseReasons(cx, justifications); } else if (sense >= SENSE_MOSTLY) { ContextAddMakeSenseReasons(cx, justifications); } }
/****************************************************************************** * Examples: * a: Jim Jim Jim * other: Mary Mary Mary * in: [happy-for Jim Mary] [sorry-for J. M.] [gloating J. M.] * (positive-emotion) (negative-emotion) (positive-emotion) * attitude: like-human like-human like-human * weight: WEIGHT_DEFAULT WEIGHT_DEFAULT -WEIGHT_DEFAULT * o.e.c.: positive-emotion negative-emotion negative-emotion * att: [like-human J. M. WD] [like-human J. M. WD] [like-human J. M. * -WD] * * todo: Generalize this to work for all the related like/love attitudes as well * as friends/enemies relations. * The intensity rules are more complex: something like * value of actor2's emotion = value of actor1's emotion x * value of how much actor2 likes actor1. ******************************************************************************/ void UA_Emotion_FortunesOfOthers(Actor *ac, Ts *ts, Obj *a, Obj *in, Obj *other, Float weight, Obj *other_emot_class) { int found; Float weight1; Obj *other_emot_class1; ObjList *causes, *objs, *atts, *p, *q; /* Relate <a>'s emotion to <a>'s attitudes. */ if (0.0 != (weight1 = UA_FriendAttitude(ts, a, other, 1, &atts))) { if (FloatSign(weight1) == FloatSign(weight)) { /* The input emotion agrees with known attitudes. */ ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_TOTAL, NOVELTY_HALF); ContextAddMakeSenseReasons(ac->cx, atts); } else { /* The input emotion disagrees with known attitudes. */ ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_LITTLE, NOVELTY_TOTAL); ContextAddNotMakeSenseReasons(ac->cx, atts); } } else { /* Attitude of <a> toward <other> is unknown. */ ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_MOSTLY, NOVELTY_MOSTLY); UA_Infer(ac->cx->dc, ac->cx, ts, L(N("like-human"), a, other, NumberToObj(weight), E), in); } /* Relate <a>'s emotion to <other>'s emotion. * found = <other>'s emotion implied by <a>'s emotion is already known, * excluding motivating emotions. */ objs = RD(ts, L(other_emot_class, other, E), 0); found = 0; for (p = objs; p; p = p->next) { if (ISA(N("motivation"), I(p->obj, 0))) continue; if ((causes = CAUSES(p->obj, ac->cx))) { for (q = causes; q; q = q->next) { if (!ISA(N("active-goal"), I(q->obj, 0))) { found = 1; ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_TOTAL, NOVELTY_HALF); ContextAddMakeSenseReason(ac->cx, q->obj); } } } else { found = 1; ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_TOTAL, NOVELTY_HALF); ContextAddMakeSenseReason(ac->cx, p->obj); } ObjListFree(causes); } ObjListFree(objs); if (!found) { /* <other>'s emotion implied by <a>'s emotion is not yet known. */ ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_MOSTLY, NOVELTY_MOSTLY); if (other_emot_class == N("positive-emotion")) { other_emot_class1 = N("happiness"); } else if (other_emot_class == N("negative-emotion")) { other_emot_class1 = N("sadness"); } else { other_emot_class1 = other_emot_class; } UA_Infer(ac->cx->dc, ac->cx, ts, L(other_emot_class1, other, NumberToObj(FloatAbs(weight)), E), in); } /* todo: Relate <a>'s emotion to <other>'s goal. */ }