Giving NPCs attitudes toward topics of conversation

I’m a newbie trying to give Inform 7 non-player characters attitudes toward subjects of conversation. That is, for each subject of conversation, I want my npcs to have only one of five possible attitudes toward it that will determine how they respond to questioning on the subject, so any character can like, dislike, love, hate or be indifferent to any subject. I understand I can implement the loving relation, but what I want to do is establish that if Lois loves Superman she can’t also hate Superman: one attitude automatically precludes the other. So I’ve been trying to get something like this to work:

Attitude is a variable relating people to various subjects. An attitude can be hostile, suspicious, indifferent, friendly, and adoring. A person’s attitude to any subject is usually indifferent. Lois loves Superman. Clark loves Lois. Lex is indifferent to Clark.

Instead of asking Lois about Superman:

if Lois loves the subject of Superman, say “‘He’s dreamy.’”

I know the above is too imprecise to work, but I also figure I’m trying to reinvent the wheel here anyway and that there is an existing extension that does this. Does anyone know what it’s called?

2 Likes

You may want to look at “Mood Variations” by Emily Short. http://inform7.com/extensions/Emily%20Short/Mood%20Variations/index.html

Though it sounds like you’re just writing different responses for different characters on varying subjects without having them change their attitude depending on their mood.

  • I suggest using an After rule rather than Instead so normal parsing rules will apply.
  • If Lois’s attitude about a subject doesn’t change, you don’t really need the if - unless, for example, her attitude about the subject changes depending on another factor - like what order the questions are asked in, or if the player can upset her before asking.
1 Like

Hanon beat me to the punch. I was going to suggest checking out this part of the Recipe Book.
http://inform7.com/learn/man/RB_7_10.html

1 Like

Thanks!

Thank you! I’m going to have a look at it right now.

1 Like

Yeah, unfortunately what you’re asking for is a three-way relation, which Inform doesn’t support. In theory, various-to-various relations use an adjacency matrix, which could totally support storing a third variable with every relationship—in practice, this hasn’t been implemented.

3 Likes

@Draconis, can you talk a little more about what you mean by a three-way relation. I’ve heard it mentioned in regard to Inform before and I’ve never quite gotten it.

The example by the original poster describes a weighted relation. (i.e. in graph theory, a weighted digraph showing the degree of love between characters.)

Is that what you mean by a 3-way relation?

I was going to suggest doing this with a table, but it seems to me that for your purposes maybe you can collect your relations into a list and write a special phrase to simultaneously set one and clear all the others. Like this:

Loving relates various persons to various persons. The verb to love means the loving relation.
Hating relates various persons to various persons. The verb to hate means the hating relation.
Liking relates various persons to various persons. The verb to like means the liking relation.
Disliking relates various persons to various persons. The verb to dislike means the disliking relation.
Indifference relates various persons to various persons. The verb to be indifferent to means the indifference relation.

The attitudes is a list of relations of persons that varies. The attitudes are {loving relation, hating relation, liking relation, disliking relation, indifference relation}.

When play begins:
	set most attitudes to indifference.
	
To set most attitudes to indifference:
	repeat with subject running through persons:
		repeat with object running through persons:
			let relation found be a truth state;
			repeat with tested attitude running through the attitudes:
				if the tested attitude relates the subject to the object:
					now relation found is true;
					break; [ends the repeat loop, which is not strictly necessary, but saves a bit of time]
			if relation found is false: [this is outside the repeat through the attitudes, so no relation has been found]
				now the subject is indifferent to the object.
			
To set the feeling of (subject - a person) about (object - a person) to (new attitude - a relation of persons):
	[if new attitude is not listed in the attitudes:
		say "Programming error! Tried to set the feeling of [subject] about [object] to [new attitude], which is not an attitude.";
	otherwise:]
	now the new attitude relates the subject to the object;
	repeat with tested attitude running through attitudes:
		if tested attitude is not the new attitude:
			now the tested attitude does not relate the subject to the object. 

Daily Planet is a room. Clark is a man in Daily Planet. Lois is a woman in Daily Planet. Lex is a man in Daily Planet.

Clark loves Lois. Lois likes Clark. Lex hates Clark. Clark dislikes Lex.

After jumping:
	set the feeling of Lois about Clark to the loving relation.
	
Every turn when Lois likes Clark:
	say "Lois says 'Can't wait to see Superman.'"
	
Every turn when Lois loves Clark:
	say "Lois says 'You were Superman all along!'"

You’d have to be very careful always to change relations with the “set the feeling” phrase rather than “now Lois loves Clark,” or you’ll introduce annoying bugs. And it can be hard to remember that (I just messed this up while trying to type up this example). But a nice thing about this, compared to storing everything in a table, is that it lets you keep the relation checks like “if Lois loves Clark” and even “the list of people who love Clark.”

(Also I realize that you’re talking about relating people to subjects rather than other people. This is doable–you’d say “relation of persons to subjects” rather than just “relation of persons.” See §13.14.)

1 Like

Thank you very much, Matt! It’s incredibly generous of you to take the time to consider my problem and provide all that code. I’m very excited to try it!

1 Like

And it’s fully playable!

No problem! Beats going through and putting the references in this paper I’m allegedly working on (sigh)!

1 Like

Indeed; to Inform, a weighted relation is a three-way relation between objects, objects, and numbers. Inform relations can’t have weights, or really any other information, associated with them: they have to be binary.

3 Likes

Oh, another thing about this code is that I tried to include code to make sure that the relation that was being set is an attitude, with “If new attitude is not listed in the attitudes.” But this did not work–even the attitudes showed up as not listed in the attitudes. Anyone have any idea why? It seems to happen with “is listed in” checks.

As a workaround, perhaps a Definition:?

Definition: a relation is attitudinal: no.
Definition: loving is attitudinal: yes.

That’s not a bad idea–though if I’m not mistaken the particular code mixes syntax for decide phrases and definitions–but it looks like I can’t repeat through attitudinal relations. The error message is that there are too many relations (like numbers) to repeat through, so I think a list of relations is necessary to enable the repeat through.

But that did help me think of a more complex workaround!

To decide whether (test relation - relation of persons) is not attitudinal:
	repeat with test attitude running through the attitudes:
		if test attitude is test relation, no;
	yes.

Then you can include the check:

To set the feeling of (subject - a person) about (object - a person) to (new attitude - a relation of persons):
	if new attitude is not attitudinal:
		say "Programming error! Tried to set the feeling of [subject] about [object] to [new attitude], which is not an attitude.";
	otherwise:
		now the new attitude relates the subject to the object;
		repeat with tested attitude running through attitudes:
			if tested attitude is not the new attitude:
				now the tested attitude does not relate the subject to the object. 

You guys are operating so far over my head that I can only gawp admiringly…