Addressing actors with correct titles

The example “Peers” in the Inform manual is helpful, but I would like to go a step farther. I see that the parser correctly attaches the title to the character, and it correctly fails when you mix the wrong title to the character. However, I am writing a Jane Austen-like game, and I would like a slightly different behavior: if the player uses the wrong title, I want the game to respond by pointing out the player’s insulting breach of protocol. For example:

Robert Crawley, the Earl of Grantham, is here. Lady Crawley is speaking quietly to Carson, the butler. Master George is playing by the fireplace.

GREET MR CARSON

It would be inappropriate for someone of your station to address a servant with a title.

GREET CARSON

You say hello to Carson.

ASK CARSON ABOUT SIR ROBERT

“You will refer to him as His Lordship,” Carson rumbles disapprovingly at you.

I have already constructed a way to disambiguate titles, such that “Miss Bennet” would refer to the eldest sister Jane, if she is present; but it would ask for clarification if Jane were not and one or more of Elizabeth, Mary, Kitty, and Lydia were around (to use another common example).

Somehow, if you refer to someone with the improper title (such as “Mr Jane” or “Mrs Darcy”) the parser simply gives the standard you-can’t-see-that-here error. Do I need to create a new error with higher priority? Can actors notice that error, or will the higher priority of the parser prevent such things from happening?

This is difficult, as I understand it. The paradigm in Inform is that you have a bunch of ways of referring to things and other objects, but once the parser processes your command into an action involving an object it discards the way that the command referred to the object. So you can use understanding by relations to know that “baron” can be used to refer to Maltravers (in the Peers example); but this will not allow “duke” to be used to refer to as Maltravers, so when you type “duke maltravers” the parser will simply not resolve that to an object, as if you had typed “X BLUE ORB” in the presence of a red orb. Which gives the you-can’t-see-that error. And if you did rig things so that the parser could understand “duke maltravers” as Maltravers, then at the action-processing stage the game would have forgotten that Maltravers was referred to using the wrong title! So that’s no good.

One thing you can do sometimes here is use a check on “if/when the player’s command includes…” to see if the command referred to an object by a forbidden string… but that seems like it would be very awkward in this case, when there are so many possible forbidden strings.

Here’s something inspired by the Puncak Jaya example, which uses “ghost” objects to allow you to refer to people you can’t see… by making sure the ghost object is nearby and can intercept commands that refer to an absent person. It’s pretty messy, though–I had to create a separate misnomer for every person for every possible title (and if you add another title you have to change the number of incorporated misnomers by hand, at least I don’t know how to automate it). Multiplying things like that might hammer the performance of your game. Also, it produces weird clarification messages, and it relies on Does The Player Mean rules which I never count on not to break. (If you already have a way to disambiguate titles you probably understand DTMP rules better than me.) But it might be a start.

[code]A title is a kind of value. The titles are Baron, Viscount, Earl, Marquess, Duke and Prince.
A peer is a kind of man. A peer has a title. A peer is usually a Baron. Before printing the name of a peer, say "[title] ". Understand the title property as describing a peer.

The House of Lords is a room. Maltravers, Pollifax, Omnium and St Vincent are peers in the House of Lords. Omnium is a Duke. St Vincent is an Earl.

A misnomer is a kind of thing. A misnomer is usually privately-named. Six misnomers are part of every peer. A misnomer has a title.

Misnomership relates one peer (called the owner) to various misnomers. The verb to misname means the reversed misnomership relation.
When play begins:
repeat with noble running through peers:
let current title be a title;
repeat with malaprop running through misnomers incorporated by noble:
now malaprop misnames noble;
now the title of malaprop is current title;
now current title is the title after current title.

Understand the title property as describing a misnomer. Understand “[something related by reversed misnomership]” as a misnomer.

Does the player mean doing something with a misnomer: it is very unlikely.

Before doing something when the noun is a misnomer (called malaprop): say “You can’t call [owner of malaprop] that!” instead.

Before doing something when the second noun is a misnomer (called malaprop): say “You can’t call [owner of malaprop] that!” instead. [/code]

Here’s another approach, using “after reading a command”. Half-baked, but somewhat promising.

A title is a kind of value. The titles are Untitled, Baron, Viscount, Earl, Marquess, Duke and Prince.

A person has a title. A person is usually Untitled. Before printing the name of a person, say "[title ?]".
Understand the title property as describing a person when the title of the item described is not Untitled.

A peer is a kind of man. A peer is usually a Baron.

To say (T - title) ?:
	say "[if T is not Untitled][title] ".

Title used is a title that varies.

[what about commands containing multiple titles?]
[commands containing only a title and no name (e.g., "x baron")?]
[commands requiring disambiguaton?]
After reading a command:
	If the player's command includes "[title]":
		now title used is the title understood;
		if the title used is not Untitled, cut the matched text;
	otherwise:
		now title used is Untitled.

Before doing something to someone when the title used is not the title of the noun:
	instead say "Title mismatch (used: [the title used], required: [the title of the noun])."
	
Before doing something when the second noun is a person and the title used is not the title of the second noun:
	instead say "Title mismatch (used: [the title used], required: [the title of the second noun])."

The House of Lords is a room. Maltravers, Pollifax, Omnium and St Vincent are peers in the House of Lords. Omnium is a Duke. St Vincent is an Earl.
Bob is a man in the House of Lords.

Test do with "x baron pollifax / x duke pollifax / x pollifax / x prince bob / x bob".
Test io with "say hi to baron pollifax / say hi to duke pollifax / say hi to pollifax / say hi to prince bob / say hi to bob".
Test broken with "x duke / x baron".
Test me with "test do / test io / test broken".

How about this?

A baron is a kind of man. Roderick is a baron. Definition: a title is non-baronial if it is not [whatever object or enum you're using for the title of "baron"]. An incorrect title is a privately-named backdrop. It is everywhere. Understand "[non-baronial title] [a baron]" as an incorrect title. Before doing anything when the action involves an incorrect title: say "Protocol must be observed!".
Takes a bit more writing overall, but won’t break anything else, and doesn’t require much parser hacking.

vlaviano, that’s a good preliminary solution. I was going down a similar path, reading the command and checking for bad combinations, but this is better. Thanks! I’ll keep going in this direction.

Here’s an updated version that handles more scenarios. See the TODOs for remaining issues.

A title is a kind of value. The titles are Untitled, Baron, Viscount, Earl, Marquess, Duke and Prince.

A person has a title. A person is usually Untitled. Before printing the name of a person, say "[title ?]".
Understand the title property as describing a person when the title of the item described is not Untitled.

A peer is a kind of man. A peer is usually a Baron.

To say (T - title) ?:
	say "[if T is not Untitled][title] ".

Title used is a title that varies.
Reparse previous command is initially false.

Rule for reading a command when reparse previous command is true: stop.

After reading a command when reparse previous command is false:
	now title used is Untitled;
	if the player's command includes "[title]", now title used is the title understood.
	
After reading a command when reparse previous command is true:
	now reparse previous command is false;
	say "[run paragraph on]".

[TODO: Handle commands containing multiple titles. We only remember and act on the first one.]
[TODO: Allow "untitled" in topics. Skip over Untitled and cut next title. If it's the only title, call standard version of activity.]
[TODO: Don't reset used title during disambiguation. "x duke baron"]
Rule for printing a parser error when the player's command includes "[title]" and the title understood is not Untitled:
	cut the matched text;
	now reparse previous command is true.
		
Before doing something to someone when the title used is not the title of the noun:
	instead say "Title mismatch (used: [the title used], required: [the title of the noun])."
	
Before doing something when the second noun is a person and the title used is not the title of the second noun:
	instead say "Title mismatch (used: [the title used], required: [the title of the second noun])."

[TODO: Handle titles embedded in topics.]

When play begins:
	now the right hand status line is "[turn count]".

The House of Lords is a room. Maltravers, Pollifax, Omnium and St Vincent are peers in the House of Lords. Omnium is a Duke. St Vincent is an Earl.
Bob is a man in the House of Lords.

Test do with "x baron pollifax / x duke pollifax / x pollifax / x prince bob / x bob".
Test io with "say hi to baron pollifax / say hi to duke pollifax / say hi to pollifax / say hi to prince bob / say hi to bob".
Test no-names with "x duke / x baron / maltravers / x duke baron / pollifax".
Test untitled with "x untitled / x untitled bob / x baron untitled pollifax / x baron pollifax untitled".
Test multiple with "x earl prince duke baron pollifax / x baron duke prince earl pollifax".
Test topics with "ask baron pollifax about duke omnium / ask baron pollifax about earl omnium / ask baron pollifax about omnium / ask baron pollifax about prince bob / ask baron pollifax about bob / say untitled to duke pollifax".
Test me with "test do / test io / test no-names / test untitled / test multiple / test topics".

:open_mouth:

You can do this to painlessly reparse commands without I6 hacking?

I have got to rip this off.

(By the way, I haven’t forgotten that you asked me about the way I bump into the limits of the parser! I started a draft post about that, and I’ll get back to it… sometime.)

I have tried to incorporate vlaviano’s solution into my game, but interestingly, Threaded Conversation does not play nice with it. It has something to do with the way TC creates new rules for printing parser errors. Since a quip can contain the name of a person or object, the error message favored giving the player a response such as “You’re not talking to anyone” or “That’s not a verb I recognize” instead of the expected “You can’t see any such thing.” I added a few extra lines to help produce more correct error messages — that is, when the player’s command includes a “quip” but which might actually be an object mentioned by a quip, we need to produce the correct error. This is also where I will have to include some useful error about mismatched titles. At this point, vlaviano’s code is still not included, but I am working toward that.

[code]Rule for printing a parser error when the latest parser error is the can’t see any such thing error (this is the quips are not visible rule):
if the player’s command includes “say/ask/answer/discuss/tell/a/t” or the player’s command includes “[any quip]”:
if the current interlocutor is a person and tc reparse flag is false:
say “That doesn’t seem to be a topic of conversation at the moment.” (A) instead;
else if the player’s command includes “[title]”: [I added these two lines so I could force a response.]
say “There is a problem with the title used (say/ask/answer/quip).” (B) instead;
otherwise:
say “[text of implicit-conversing needs current interlocutor rule response (D)][line break]” © instead; [‘You aren’t talking to anyone.’]
else if the player’s command includes “take/get/look/examine”: [I added these two lines because the “you can’t see that” error doesn’t appear with TC.]
say “You can’t see any such thing.” (D) instead;
else if the player’s command includes “[title]”: [I added these two lines so I could force a response.]
say “There is a problem with the title used (generic).” (E) instead;
otherwise:
make no decision.

Rule for printing a parser error when the latest parser error is the noun did not make sense in that context error (this is the prevent context error rule):
if the player’s command includes “say/ask/answer/discuss/tell/a/t” or the player’s command includes “[any quip]” or the current interlocutor is not a person:
say “[text of parser error internal rule response (N)][line break]” (A) instead; [‘Not a verb I recognize.’]
otherwise:
make no decision.[/code]

Interestingly, it looks like Threaded Conversation uses the same reparsing technique that my example does, with its own flag (tc reparse flag).

It also looks like SAY and ASK commands that would have produced actions and hit my mismatched title rules are now instead causing parser errors and never making it to the action stage. This is because the extension associates these verbs with new actions whose grammar requires matching [quip] rather than arbitrary topic text as before.

That would explain why commands of the format ASK FRED ABOUT THE ZORKMID no longer work. Is it possible to first parse as a topic and, failing that, parse as a quip?

A topic matches any text, so it wouldn’t fail to parse. The resulting action might elicit a default response that you’d think of as a failure.

We could probably hack something together, but Threaded Conversation wants to own the conversation commands. I don’t know if it’s worth fighting the core premise of the extension.

Assuming that you have a compelling reason for using it, would it be better to go with the flow and implement quips for your conversation topics?

Zorkmid is a subject.

There is a questioning quip called whether he has a zorkmid.
	It mentions zorkmid.
	It quip-supplies Pollifax.
	The comment is "'Hey, bro, can you spare a zorkmid?' you ask him."
	The reply is "'Begone, commoner!' he replies."
	It is repeatable.

I don’t have any specific desire to use Threaded Conversation; any conversation extension would do if I can get similar control over conversation flow. As I am starting to implement the game I’m realizing that there are limitations in TC that I’d rather not be shackled by (no ASK BOB ABOUT ZORKMID is caused by the same routine in TC that prevents enforcement of titles; a quip contains comments by all characters in a single quoted text so max-string limit is easy to hit).