What is TAME?

TAME (Text Adventure Module Engine) is an Interactive Fiction Engine that assists in the creation of text-command-driven interactive fiction, similar to the adventure games of yesteryear.

Why should I use TAME?

TAME handles the heavy lifting of interpretation and logic, and the user defines the world via a scripting language called TAMEScript.

TAME's modules can compile to stand-alone Embedded HTML and JS or a stand-alone NodeJS or web browser module, for server-side applications, allowing virtually anyone to play your modules! If you have a web server or hosted space, deployment can be as easy as uploading a single HTML page!

TAME modules can also compile to a general serialized format for use in other TAME implementations.

What's so special about TAME?

TAME is essentially a logic system - unlike most authoring tools that offer an all-in-one, all-or-nothing system, TAME's setup and design is modular - its presentation, logic, and context storage are all separable.

The input you type in at a prompt is a query that executes your module's logic, changes a context, and sends back a set of "cues" to be processed by a Shell, separating the development work between model and view, similar to how web technology works.

How do I use TAME?

If you've got a command line and a text editor, you can make TAME modules for everybody!

But even though TAME's primary implementation is in Java, you don't need a full Java Runtime Environment in order to write or run modules - the tools are downloadable and available for most platforms, without needing any extra dependencies!

$ tamec adventure.tscript --outfile adventure.tame
Wrote adventure.tame successfully.

$ tame adventure.tame

Escape the room!
There's a key, here.
There's a wooden door, here.

] _

What does a TAME module look like?

A Small Adventure


module
{
	title = "A Small Adventure";
	author = "Matthew Tropiano";
	email = "email@somesite.com";
}

action general a_quit named "quit";
action general a_look named "look around", "look", "l";
action transitive a_take named "take", "pick up", "t", "p";
action transitive a_examine named "look at", "examine", "x";
action transitive a_open named "open", "o";
action ditransitive a_use named "use" uses conjunctions "with", "and";

// The KEY!
object o_key named "key", "small key"
{
	onAction(a_examine)
	{
		textln("Looks like a small key.");
	}
	
	onAction(a_take)
	{
		if (!hasObject(player, this))
		{
			giveObject(player, this);
			textln("You take the key.");
		}
		else
			textln("You already have this.");
	}
	
	onRoomBrowse()
	{
		textln("There's a key, here.");
	}
	
	onPlayerBrowse()
	{
		textln("A key.");
	}
	
}

// The DOOR!
object o_door named "door" uses determiners "the"
{
	init()
	{
		locked = true;
	}

	onAction(a_examine)
	{
		textln("Looks like a wooden door.");
		addObjectName(this, "wooden door");
	}
	
	onActionWith(a_use, o_key)
	{
		if (locked)
		{
			locked = false;
			textln("You unlocked the door!");
		}
		else
		{
			textln("The door is already unlocked.");
		}
	}
	
	onAction(a_take)
	{
		textln("You can't pick up a door.");
	}
	
	onAction(a_open)
	{
		queue a_use, this;
	}
	
	onAction(a_use)
	{
		if (locked)
			textln("The door is locked.");
		else
		{
			textln("You open the door.");
			world.win = true;
		}
	}

	onRoomBrowse()
	{
		textln("There's a wooden door, here.");
	}

}

// YOU!
player p_guy
{
	function oops()
	{
		local x = irandom(3);
		if (x == 0)
			textln("I can't do that.");
		else if (x == 1)
			textln("I don't understand.");
		else
			textln("I don't think so.");
	}
	
	onUnhandledAction()
	{
		oops();
	}
	
	onMalformedCommand()
	{
		oops();
	}
	
	onUnknownCommand()
	{
		oops();
	}
	
	onIncompleteCommand()
	{
		oops();
	}

}

// The ROOM!
room r_startroom
{
	init()
	{
		giveObject(r_startroom, o_key);
		giveObject(r_startroom, o_door);
	}
}

// HELLO, WORLD!
world
{
	init()
	{
		win = false;
	}

	afterSuccessfulCommand()
	{
		if (win == true)
		{
			textln("You escaped the room!");
			quit;
		}
		else if (objectCount(player) > 0)
		{
			textln("You have:");
			browse(player);
		}
	}
	
	start()
	{
		setRoom(p_guy, r_startroom);
		setPlayer(p_guy);

		textln("Escape the room!");
		browse(room);
	}
}

How much does TAME cost?

TAME is provided free of charge! Also, no royalties are owed if you publish a commercial product with TAME. You don't even have to tell people that you made your amazing work with TAME (though we'd prefer it if you did somewhere)!

How about its licensing?

TAME is open source, and licensed under the LGPL, version 2.1.

The license allows:
  • Commercial use of the library and its utilities.
  • Private use of the library and its utilities.
  • Distribution of TAME's source code.
  • Modification of TAME's source code.
The license requires:
  • Disclosure of modifications to source.
  • Disclosing what was changed.
  • Including this license and notice in derivative works.
  • Keeping this license on a derivative work, or a compatible one.
The license does not provide:
  • Any warranty with its use.
  • Unlimited liability through its use.

Please note that this license only refers to TAME itself, and not the works created using it!

TAME also does not provide support for unofficial, derivative implementations.

TAME's Java distributions contain code from Black Rook Software.

NOTE: TAME is still in BETA.

This means that the commands in the language, its structure, and their behavior may change before version 1.0, but it is completely functional and consistent in both the Java and JS implementations.

Until otherwise specified, any changes to the TAME commands or entry points may invalidate TAME modules that are compiled to the serialized format or JS modules (but not embedded ones - those are safe).

Please report any engine issues on the Github Issues page!