void UA_Trade(Actor *ac, Ts *ts, Obj *a, Obj *in) { ObjList *products, *forsales, *p, *commentary; Intension *itn; if (ISA(N("active-goal"), I(in, 0)) && I(in, 1) == a && ISA(N("buy-from"), I(I(in, 2), 0)) && I(I(in, 2), 1) == a && (!ObjIsNa(I(I(in, 2), 3)))) { /* "I want to buy a desk phone." */ if ((products = UA_AskerSelect(ac->cx, I(I(in, 2), 3), &itn))) { commentary = NULL; for (p = products; p; p = p->next) { /* todo: Filter out old ads. */ forsales = RE(&TsNA, L(N("for-sale"), p->obj, ObjWild, ObjWild, ObjWild, ObjWild, ObjWild, E)); commentary = ObjListAppendDestructive(commentary, forsales); } /* if ((!(ac->cx->dc->mode & DC_MODE_CONV)) || ObjListLen(products) < 10 || ObjListLen(commentary) < 10) */ if ((!(ac->cx->dc->mode & DC_MODE_CONV)) || ObjListLen(products) < 18) { if (commentary) { CommentaryAdd(ac->cx, commentary, NULL); ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_TOTAL, NOVELTY_TOTAL); } } else { /* Too much output. Try to narrow down with a question. An answer * to the question should result in this function being reinvoked * with something that UA_AskerSelect is able to use to narrow down * the selected products. */ if (UA_AskerNarrowDown(ac->cx, 1.0, N("UA_Trade"), itn, products, L(N("active-goal"), a, L(N("buy-from"), a, I(I(in, 2), 2), N("?answer"), I(I(in, 2), 4), E), E), 1)) { ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_TOTAL, NOVELTY_TOTAL); } } } } }
/****************************************************************************** * 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 UA_Weather1(Context *cx, Ts *ts, Obj *in, Obj *grid) { Obj *head, *obj; if (I(in, 0) == N("not") && (head = I(I(in, 1), 0)) && (obj = I(I(in, 1), 1)) && ISA(N("weather-evaluation"), head) && WeatherPronoun(obj)) { /* "It was not a beautiful day." [not [beautiful-day pronoun-ce-expletive]] * todo: Generalize this. */ ContextSetRSN(cx, RELEVANCE_TOTAL, SENSE_TOTAL, NOVELTY_TOTAL); if (ISA(N("good-weather"), head)) { AS(ts, 0L, L(N("bad-weather"), grid, E)); } else if (ISA(N("bad-weather"), head)) { AS(ts, 0L, L(N("good-weather"), grid, E)); } return; } if (!(head = I(in, 0))) return; if (!(obj = I(in, 1))) return; if (ISA(N("weather-evaluation"), head) && WeatherPronoun(obj)) { /* "It was beautiful." [beautiful-day pronoun-it-expletive] */ goto assertit; } else if (ISA(N("sky-coverage"), head) && WeatherPronounSky(obj)) { /* "The sky was overcast." [overcast-sky sky] * "It was sunny." [sunny pronoun-it-expletive] */ goto assertit; } else if (ISA(N("humidity-description"), head) && WeatherPronounAir(obj)) { /* "The air was dry." [dry air] * "It was humid". [humid pronoun-it-expletive] */ goto assertit; } else if (ISA(N("temperature-description"), head) && WeatherPronounAir(obj)) { /* "The air was cold." [cold air] * "It was freezing." [freezing pronoun-it-expletive] */ goto assertit; } return; assertit: ContextSetRSN(cx, RELEVANCE_TOTAL, SENSE_TOTAL, NOVELTY_TOTAL); AS(ts, 0L, L(head, grid, E)); }
void UA_GoalSetStatus(Actor *ac, Subgoal *sg, Obj *new_status, Obj *spin_emotion) { Obj *prev_status; prev_status = SubgoalStatus(sg); if (prev_status == new_status) { /* No change in this subgoal's status. */ /* todo: This case isn't needed because existing goals should already have * created these associated emotions and hence the existing emotion would * be found in UA_Emotion? */ ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_TOTAL, NOVELTY_EXPECTED); return; } if (new_status == N("active-goal")) { /* Flashback? */ ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_HALF, NOVELTY_TOTAL); } else { /* Possible irony. */ ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_LITTLE, NOVELTY_TOTAL); ContextAddNotMakeSenseReason(ac->cx, sg->cur_goal); } PA_SpinToGoalStatus(ac->cx, sg, new_status, spin_emotion); }
/****************************************************************************** * This function is invoked in case no existing goals are found related to the * input emotion. Goals are inferred here. * Examples: * in: [embarrassment Jim] [suffocation Jim] * rel: failure-emotion-of activated-emotion-of * goal_status:failed-goal active_goal * goal_class: p-social-esteem s-air * infer: [failed-goal J. [p-social-esteem J.]] [active-goal Jim * [s-air Jim]] ******************************************************************************/ Bool UA_Emotion_NewGoals(Actor *ac, Ts *ts, Obj *a, Obj *in, Obj *rel, Obj *goal_status) { Obj *goal_class; Subgoal *sg; if (!(goal_class = DbGetRelationValue1(&TsNA, NULL, rel, I(in, 0), NULL))) { return(0); } if (goal_class == N("goal-objective")) { /* This is not specific enough to bother with. */ return(0); } ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_MOSTLY, NOVELTY_TOTAL); sg = TG(ac->cx, &ac->cx->story_time.stopts, a, L(goal_class, a, E)); PA_SpinToGoalStatus(ac->cx, sg, goal_status, in); return(1); }
/****************************************************************************** * Top-level Goal Understanding Agent. ******************************************************************************/ void UA_Goal(Actor *ac, Ts *ts, Obj *a, Obj *in) { Obj *goal; Subgoal *sg; if (ISA(N("goal-status"), I(in, 0)) && a == I(in, 1)) { /* Goal is stated explicitly. * Examples: * [active-goal Jim [s-employment Jim]] * [succeeded-goal Jim [s-employment Jim]] * [failed-goal Jim [s-employment Jim]] * Note that emotional responses occur as a result of spinning * the goal. */ goal = I(in, 2); /* If <in> corresponds to existing subgoal, steer that subgoal according * to <in>. */ for (sg = ac->subgoals; sg; sg = sg->next) { if (ObjSimilarList(goal, sg->obj)) { UA_GoalSetStatus(ac, sg, I(in, 0), NULL); return; } } /* This is a new subgoal. */ /* todo: Add more heuristics for making sense. * For example, N("s-employment") doesn't make sense if <a> already has * a job. */ ContextSetRSN(ac->cx, RELEVANCE_TOTAL, SENSE_TOTAL, NOVELTY_TOTAL); if ((sg = TG(ac->cx, &ac->cx->story_time.stopts, a, goal))) { PA_SpinToGoalStatus(ac->cx, sg, I(in, 0), NULL); } } else if (ISA(N("prep-goal-for"), I(in, 0))) { UA_GoalSubgoal(ac, ts, a, in, I(in, 2), I(in, 1)); } else if (ISA(N("intends"), I(in, 0))) { UA_GoalSubgoal(ac, ts, a, in, I(in, 1), I(in, 2)); } }
/****************************************************************************** * 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. */ }