The printed name of the player, "you" vs "yourself"

I’m trying to make some adjustments to the way actions are described and carried out, and I’m running into difficulty making the grammar correct while the player is the actor.

Instead of taking while the noun is carried by a person (called the target):
	now the prior named noun is the actor;
	say "[Actor] take[s] [the noun] from [target].";
	now the actor is holding the noun;

I’m using Plurality by Emily Short. I plan to expand on this to put checks in place that don’t allow people to just take one another’s stuff without conflict, but for now I’m just trying to get the basics. The problem with the above is that when the player is the actor, it returns stuff like this:

take Bob’s sword
yourself take the sword from Bob.

The obvious question is: how do I make “yourself” print as “you” when needed, and with the correct capitalization when appropriate?

You could add a “for printing the name” rule, but it would be hard to figure out from context when “You” is needed.

The simple solution is to define a new printing phrase [actor-subject] (and [Actor-subject], for beginnings of sentences) which has the appropriate logic. I suspect there are already extensions that cover this, actually.

This is what you want:

say "[The actor] take[s] [the noun] from [target].";

Yes… it was! What the heck? I thought “the” and “a” before nouns didn’t really matter? So, to get “you” “the” needs to precede the token, and to get “yourself” not? I feel like I’ve asked this question before, dangit, why is this hard to remember. I guess I just still don’t understand the difference in the internal mechanics there.

Outside of quotes, “the” and “a” don’t matter, and neither does capitalization. But in text substitutions, they do matter - so “[the noun]” vs. “[The noun]” vs. “[a noun]” vs. “[noun]” all produce different results when the noun is an apple, for instance. And the standard text substitutions do contain special code to handle the case when the object is the player.

That seems rather inconvenient. The reasons for using you vs. yourself in prose are very different from the reasons for using the vs. a.

Actually, what’s going on in this case is that when the actor is the player, “[The actor]” prints “You” and “[the actor]” prints “yourself”. The idea is that “You” is much more likely to be intended at the beginning of the sentence and “yourself” when in the middle, but it’s pretty crude. (For instance, if you change the message for waiting to “Some dust settles on [the actor]” then the message for you waiting is “Some dust settles on yourself,” which isn’t actually right.)

If you want to do something less crude, you can use Assorted Text Generation by Emily Short. Then in my above example you could write “Some dust settles on [you or the actor]” and it should print “Some dust settles on you.” I suppose there’s no explicit phrase in that extension for the capitalized form, “You or the (culprit - a person),” because Inform already turns any call like “The (culprit - a person)” into “You” when the person plugged into the phrase evaluates to the player. But if you need more phrase options in custom phrases you could write more.

Hmm, I have to write some code to make sure that I get messages like “The ghost peers closely at itself” rather than “The ghost peers closely at the ghost” (actually that one should probably be special-cased). Maybe some of this will help.

While doing something else, I ran into the section of code that handles the determination of whether to use “you” vs. “yourself” when printing an object that is the player (the standard name printing rule). The algorithm is as described by matt_weiner above: If the player object’s name is to be capitalized, then “You” is printed, otherwise “yourself.”

The problem is that when you invoke a say <player object> with a line like

say "[The actor] [foo] [the noun]."

then there is no context for the text substitution to let the standard name printing rule know whether the player should be printed as subject or object of the sentence, or whether the object should be treated as reflexive. Text substitutions do exist for the various cases ([we] vs [us] vs [ourselves]), but it’s up to the author to select the right one in the context of a rule sensing the situation.

I’m not sure that there’s any way to 100% solve the problem of automating the selection based on object alone, but the default algorithm can be improved a bit. Here’s a demo for 6M62:

Fixing You vs Yourself
"Fixing You vs Yourself"

[An improvement over default processing of "you" vs. "yourself" when printing the player object. Probably still not perfect.]

Part - The Test Scenario

Place is a room.

Bob is a man in Place.

A persuasion rule: persuasion succeeds.

The player carries a mirror.

Examining it with is an action applying to one visible thing and one carried thing. Understand "examine [something] with [something]" as examining it with.

To inspect is a verb.

Report an actor examining with:
	say "[The actor] [inspect] [the noun] through [the second noun]."

The block giving rule does nothing.

Test me with "actions / x me / bob, x me / x me with mirror / x bob with mirror / give mirror to bob / bob, x me with mirror".

[Before asking someone to try doing something:
	showme whether or not processing the action activity is going on;
	say "P ASK actor: [actor], the p: [the player], a p: [a player], p: [player]."

Before an actor doing something:
	showme whether or not processing the action activity is going on;
	say "A DO actor: [actor], the p: [the player], a p: [a player], p: [player]."

Every turn:
	showme whether or not processing the action activity is going on;
	say "ET actor: [actor], the p: [the player], a p: [a player], p: [player].";
	say "[current action]."]

Every turn:
	say "[The player] [are] in [location of player], just like [the player] always [are][if not waiting]. I think [the actor] did something[end if]."

Part - Modified Guts

Processing the action of something is an activity on action names.

Include (-

! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
! Actions.i6t: Action Primitive
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====

[ ActionPrimitive  rv p1 p2 p3 p4 p5 frame_id;
	BeginActivity( (+ processing the action +) );	! ADDED
	MStack_CreateRBVars(ACTION_PROCESSING_RB);

	if ((keep_silent == false) && (multiflag == false)) DivideParagraphPoint();
	reason_the_action_failed = 0;

	frame_id = -1;
	p1 = FindAction(action);
	if ((p1) && (ActionData-->(p1+AD_VARIABLES_CREATOR))) {
		frame_id = ActionData-->(p1+AD_VARIABLES_ID);
		Mstack_Create_Frame(ActionData-->(p1+AD_VARIABLES_CREATOR), frame_id);
	}
	if (ActionVariablesNotTypeSafe()) {
		if (actor ~= player) { ACTION_PROCESSING_INTERNAL_RM('K'); new_line; }
		if (frame_id ~= -1)
			Mstack_Destroy_Frame(ActionData-->(p1+AD_VARIABLES_CREATOR), frame_id);
		MStack_DestroyRBVars(ACTION_PROCESSING_RB);
		EndActivity( (+ processing the action +) );	! ADDED
		return;
	}

	FollowRulebook(SETTING_ACTION_VARIABLES_RB);

	#IFDEF DEBUG;
	if ((trace_actions) && (FindAction(-1))) {
		print "["; p1=actor; p2=act_requester; p3=action; p4=noun; p5=second;
		DB_Action(p1,p2,p3,p4,p5);
		print "]^"; ClearParagraphing(5);
	}
	++debug_rule_nesting;
	#ENDIF;
	TrackActions(false, meta);
	if ((meta) && (actor ~= player)) {
		ACTION_PROCESSING_INTERNAL_RM('A', actor); new_line; rv = RS_FAILS; }
	else if (meta) { DESCEND_TO_SPECIFIC_ACTION_R(); rv = RulebookOutcome(); }
	else { FollowRulebook(ACTION_PROCESSING_RB); rv = RulebookOutcome(); }
	#IFDEF DEBUG;
	--debug_rule_nesting;
	if ((trace_actions) && (FindAction(-1))) {
		print "["; DB_Action(p1,p2,p3,p4,p5); print " - ";
		switch (rv) {
			RS_SUCCEEDS: print "succeeded";
			RS_FAILS: print "failed";
				#IFNDEF MEMORY_ECONOMY;
				if (reason_the_action_failed)
					print " the ",
						(RulePrintingRule) reason_the_action_failed;
				#ENDIF;
			default: print "ended without result";
		}
		print "]^"; say__p = 1;
		SetRulebookOutcome(rv); ! In case disturbed by printing activities
	}
	#ENDIF;
	if (rv == RS_SUCCEEDS) UpdateActionBitmap();
	if (frame_id ~= -1) {
		p1 = FindAction(action);
		Mstack_Destroy_Frame(ActionData-->(p1+AD_VARIABLES_CREATOR), frame_id);
	}
	MStack_DestroyRBVars(ACTION_PROCESSING_RB);
	if ((keep_silent == false) && (multiflag == false)) DivideParagraphPoint();
	EndActivity( (+ processing the action +) );	! ADDED
	if (rv == RS_SUCCEEDS) rtrue;
	rfalse;
];

-) instead of "Action Primitive" in "Actions.i6t".

[replaces Standard Rules version; not all responses are used in the standard name printing rule]
The print protagonist internal rule translates into I6 as
	"PRINT_PROTAGONIST_INTERNAL_R" with
	"[We]" (A),
	"[we]" (B),
	"[Us]" (C),
	"[us]" (D),
	"[Ourselves]" (E),
	"[ourselves]" (F),
	"[our] former self" (G).

Include (-

! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
! Printing.i6t: Standard Name Printing Rule
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====

Global caps_mode = false;

[ STANDARD_NAME_PRINTING_R obj;
	obj = parameter_value;
	if (obj == 0) {
		LIST_WRITER_INTERNAL_RM('Y'); return;
	}
	switch (metaclass(obj)) {
		Routine:  print "<routine ", obj, ">"; return;
		String:   print "<string ~", (string) obj, "~>"; return;
		nothing:  print "<illegal object number ", obj, ">"; return;
	}
	! BEGIN MODIFICATION
	if (obj == player) { 
		if (TestActivity( (+ processing the action +) ) && actor == player) {
			if (caps_mode)	! assumed to be subject
				PRINT_PROTAGONIST_INTERNAL_RM('A');
			else {			! might be direct or indirect object
				if (actor == noun) {
					PRINT_PROTAGONIST_INTERNAL_RM('F');
				} else if (actor == second && noun == second) {
					PRINT_PROTAGONIST_INTERNAL_RM('F');
				} else {
					PRINT_PROTAGONIST_INTERNAL_RM('D');
				}
			}
		} else {	! actor ~= player
			if (caps_mode)
				PRINT_PROTAGONIST_INTERNAL_RM('C');
			else
				PRINT_PROTAGONIST_INTERNAL_RM('D');
		} 
   	    return;
   	}
	! END MODIFICATION
	#Ifdef LanguagePrintShortName;
	if (LanguagePrintShortName(obj)) return;
	#Endif; ! LanguagePrintShortName
	if (indef_mode && obj.&short_name_indef ~= 0 &&
		PrintOrRun(obj, short_name_indef, true) ~= 0) return;
	if (caps_mode &&
		obj.&cap_short_name ~= 0 && PrintOrRun(obj, cap_short_name, true) ~= 0) {
		caps_mode = false;
		return;
	}
	if (obj.&short_name ~= 0 && PrintOrRun(obj, short_name, true) ~= 0) return;
	print (object) obj;
];

-) instead of "Standard Name Printing Rule" in "Printing.i6t".

Include (-

! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
! WorldModel.i6t: Changing the Player
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====

[ ChangePlayer obj flag;
	if (~~(obj ofclass K8_person)) return RunTimeProblem(RTP_CANTCHANGE, obj);
	if (~~(OnStage(obj, -1))) return RunTimeProblem(RTP_CANTCHANGEOFFSTAGE, obj);
	if (obj.component_parent) return RunTimeProblem(RTP_CANTMAKEPART, obj);
	if (obj == player) return;

	give player ~concealed;
	if (player has remove_proper) give player ~proper;
	if (player == selfobj) {
		player.saved_short_name = player.short_name;
		player.short_name = PRINT_PROTAGONIST_INTERNAL_RM('G');
	}
	player = obj;
	if (player == selfobj) {
		player.short_name = player.saved_short_name;
	}
	if (player hasnt proper) give player remove_proper; ! when changing out again
	give player concealed proper;

	location = LocationOf(player); real_location = location;
	MoveFloatingObjects();
	SilentlyConsiderLight();
];

-) instead of "Changing the Player" in "WorldModel.i6t".

I think the same basic changes will still work in 10.1.

My only issue with those substitutions is that they violate the convention that substitutions always use the plural in either 1st or 3rd person. So they should really be called “we or (actor)” instead of “you or (actor)”. (Thus I made my own version of them instead of using Emily Short’s.)