OnActionWithAncestor Block
OnActionWithAncestor Block

OnActionWithAncestor Block

OnActionWithAncestor ( ACTION, OBJECT )

A block that describes what to do when an element is the target of a valid ditransitive or transitive action with another nonspecific object.

Valid on Elements

Parameters

ACTION A DITRANSITIVE or TRANSITIVE action. The action that this block handles.
OBJECT Any object (including archetypes).  

When it is Called

Ditransitive Actions

The onActionWithAncestor() block is called when a ditransitive action would ordinarily call an onActionWith() block, but it is is passed over due to no match, and needs to be handled using one of the object's ancestors, searching backwards in the lineage starting from the interpreted object.

DITRANSITIVE action handling is a little tricky - depending on whether or not the action is labelled strict, it will try both combinations of "object 1 on-action-with object 2" and "object 2 on-action-with object 1", stopping after it finds a qualifying block. Only the first interpreted object is used as the target element (including the "ancestor" and "other" handling blocks) if the action is strict, and only the second interpreted object is used as the target element (including the "ancestor" and "other" handling blocks) if the action is strict and reversed.

If a valid onActionWith() block for a ditransitive action and target object is not found, TAME looks for an onActionWithAncestor() block to call that matches. If that does not exist, it calls onActionWithOther(). And if that does not exist, TAME looks for onUnhandledAction() blocks to call on the current player, if any, and then the world.

Then if that is not found, an ERROR cue is added to the Response.

Transitive Actions

The onActionWithAncestor() block is called on a room, player, or world when a transitive action needs to handle a target object, but an onAction() block does not exist on the target object, or a matching onActionWith() block didn't exist on the room, player, or world.

If an onAction() block is not found on the target object, TAME looks for onActionWith(), onActionWithAncestor(), then onActionWithOther() blocks on the current room, if any, the current player, if any, and then the world. And if that does not exist, TAME looks for onUnhandledAction() blocks to call (on the current player, if any, and then the world).

Then if that is not found, an ERROR cue is added to the Response.

Inheritance rules apply when searching for callable blocks, always!

If this block is executed, it counts as a "successful command", so this will execute the afterSuccessfulCommand() block after the initial action handling and queued actions.

Example

Ditransitive Action Example


action general a_quit named "quit", "exit";

action transitive a_talk named "talk to";
action transitive a_examine named "examine", "look at", "x";

action strict ditransitive a_mix named "mix", "combine" uses conjunctions "with", "and";
action strict reversed ditransitive a_give named "give" uses conjunctions "to";

module
{
	title = "Paint Delivery";
}

/********************************** All paint. *******************************/

object archetype o_paint
{
	// Override this!
	function getColor()
	{
		return false;
	}

	// On mix with any other paint-category item.
	onActionWithAncestor(a_mix, o_paint)
	{
		textln("I think these don't need any more mixing.");
	}

	// On mix with anything else.
	onActionWithOther(a_mix)
	{
		textln("I can't mix these together.");
	}
	
	onAction(a_examine)
	{
		textln("Looks like a can of " + getColor() + " paint.");
	}
	
	onWorldBrowse()
	{
		textln("A can of " + getColor() + " paint is here.");
	}
	
}

object o_paint_orange : o_paint named "paint", "orange paint"
{
	override function getColor()
	{
		return "orange";
	}

}

object o_paint_purple : o_paint named "paint", "purple paint"
{
	override function getColor()
	{
		return "purple";
	}
	
}

object o_paint_green : o_paint named "paint", "green paint"
{
	override function getColor()
	{
		return "green";
	}
}

object o_paint_blue : o_paint named "paint", "blue paint"
{
	override function getColor()
	{
		return "blue";
	}
}

object o_paint_yellow : o_paint named "paint", "yellow paint"
{
	override function getColor()
	{
		return "yellow";
	}
	
	onActionWith(a_mix, o_paint_blue)
	{
		textln("Hey, it made green paint!");
		giveObject(world, o_paint_green);
	}

}

object o_paint_red : o_paint named "paint", "red paint"
{
	override function getColor()
	{
		return "red";
	}
	
	onActionWith(a_mix, o_paint_yellow)
	{
		textln("Hey, it made orange paint!");
		giveObject(world, o_paint_orange);
	}
	
	onActionWith(a_mix, o_paint_blue)
	{
		textln("Hey, it made purple paint!");
		giveObject(world, o_paint_purple);
	}
	
}


/********************************** All people. *******************************/

object archetype o_person
{
	init()
	{
		talkedto = false;
	}

	// fallback on wrong paint.
	onActionWithAncestor(a_give, o_paint)
	{
		textln("\"I don't want that color of paint!\"");
	}

	onActionWithOther(a_give)
	{
		textln("I don't think they want that.");
	}
	
}

// It's a person named Bob!
object o_bob : o_person named "bob", "guy", "man"
{
	onAction(a_talk)
	{
		if (!talkedto)
		{
			textln("Bob says, \"I want orange paint.\"");
			talkedto = true;
		}
		else
		{
			textln("Bob says, \"I still want orange paint.\"");
		}
	}

	onAction(a_examine)
	{
		textln("It's a guy named Bob.");
		if (talkedto)
			textln("He wants orange paint.");
	}
	
	onWorldBrowse()
	{
		textln("A guy named Bob is here.");
	}

	onActionWith(a_give, o_paint_orange)
	{
		textln("Bob says \"thank you\" and disappears.");
		removeObject(o_paint_orange);
		removeObject(o_bob);
	}

}

// It's a woman named Susan!
object o_susan : o_person named "susan", "gal", "woman"
{
	onAction(a_talk)
	{
		if (!talkedto)
		{
			textln("Susan says, \"I want purple paint.\"");
			talkedto = true;
		}
		else
		{
			textln("Susan says, \"I still want purple paint.\"");
		}
	}

	onAction(a_examine)
	{
		textln("It's a gal named Susan.");
		if (talkedto)
			textln("She wants purple paint.");
	}
	
	onWorldBrowse()
	{
		textln("A gal named Susan is here.");
	}

	onActionWith(a_give, o_paint_purple)
	{
		textln("Susan says \"thank you\" and disappears.");
		removeObject(o_paint_purple);
		removeObject(o_susan);
	}

}

world
{
	function winCheck()
	{
		textln("");
		// check if Bob and Susan have absconded.
		if (objectHasNoOwner(o_bob) & objectHasNoOwner(o_susan))
		{
			textln("Everyone is happy!");
			quit;
		}
		else
		{
			browse(world);
		}
	}

	start()
	{
		giveObject(world, o_bob);
		giveObject(world, o_susan);
		giveObject(world, o_paint_red);
		giveObject(world, o_paint_yellow);
		giveObject(world, o_paint_blue);
		textln("These people need a color of paint.");
		textln("TALK TO them to figure out what they want.");
		textln("MIX the paint to make different colors, then GIVE the paint to them.");
		winCheck();
	}

	onAction(a_quit)
	{
		quit;
	}
	
	onUnhandledAction(a_give)
	{
		textln("I can't give that to somebody.");
	}

	onUnhandledAction(a_mix)
	{
		textln("I can't mix those things together.");
	}

	onIncompleteCommand(a_give)
	{
		textln("What do you want to give to whom?");
	}

	onIncompleteCommand(a_mix)
	{
		textln("What do you want to mix with what?");
	}

	onIncompleteCommand(a_examine)
	{
		textln("What do you want to examine?");
	}

	onIncompleteCommand(a_talk)
	{
		textln("Who do you want to talk to?");
	}

	onAmbiguousCommand()
	{
		textln("Be more specific.");
	}

	onMalformedCommand(a_talk)
	{
		textln("I can't talk to that.");
	}

	onMalformedCommand()
	{
		textln("I don't understand.");
	}

	onUnknownCommand()
	{
		textln("I can't do that.");
	}

	afterSuccessfulCommand()
	{
		winCheck();
	}
	
}

See Also

OnAction() — Called to handle an action with another object, or a general action on the current player or room.
OnActionWith() — Called by ditransitive or transitive actions for handling an action with another object.
OnActionWithOther() — Called by ditransitive or transitive actions for handling an action with another object after no specific entry points exist.
OnUnhandledAction() — Called if a command is valid, but an action is unhandled.

Additional Technical Notes

The "first" and "second" objects are determined by the interpreter. The order still matters even if the action is not strict. This stops when it finds a single relevant block.

If not strict, the object test order is always first-onActionWith-second, then second-onActionWith-first. Ancestor checks are the same way.

For transitive actions, the onModalAction() block is context sensitive involving the current player or the current room. This is assessed when finding the relevant block to execute for the current action being processed. This will affect program flow if rooms and players change.

×

Modal Header