Customize Output:Placeholders
Placeholders let authors write dynamic strings without writing code. The
following example prints
"open" or "closed" depending on the state of the
icy door asset.
MyGame.createAsset({
class: "Door",
name: "icy door",
description: "The icy north door is { icy door [is] open [or] closed }."
});
You can see that the icy door description features a
{placeholder} wrapped in curly braces. Inside the curly braces are several
[conditionals] wrapped in square brackets. In AdventureJS, a {placeholder}
indicates that a string contains dynamic information to be processed, and
[conditionals] provide a very simple form of logic. In this example, the
placeholder { icy door [is] open [or] closed } is roughly
equivalent to this code:
if( MyGame.$("icy door").$is("open")){
return "open";
} else {
return "closed"
};
Types of Placeholders
As the above example shows, placeholders can streamline the process of printing asset states. Several other forms of placeholders are available as well. Expand any item to see examples.
Subject Pronouns (and contractions)
Use pronoun and contraction placeholders to write text that adapts to the
subject's pronouns setting. We use plural pronouns as lookup keys for our
pronouns table – which means we use we to find
I or you – because plural is the only set of
pronouns where every item is unique. (For example, consider
our|ours vs his|his.) By default, pronoun
placeholders are replaced with the pronouns of the subject of that turn.
Usually that means the player, but it might also mean an NPC who has been
given a directive. By prepending p:, placeholders can be
mapped to a separate parser pronoun, which is set at
game.settings.game_pronouns. See
Gender & Pronouns: Gender & Pronouns
to learn more about working with pronouns.
MyGame.createAsset({
class: "Chest",
name: "brass chest",
description: `It's a small but sturdy looking chest bound in brass. `,
is: {
closed: true,
},
dov: {
open: {
on_failure:
`{We} {don't} see a way to do that. `
},
},
});
{we} or {p:we}
Converts to I, we, you,
they, he, she, it.
{us} or {p:us}
Converts to me, us, you,
them, him, her, it.
{we'd} or {p:we'd}
Converts to I'd, we'd,
you'd, they'd, he'd, she'd, it'd.
{we've} or {p:we've}
Converts to I've,
we've, you've, they've, he's, she's, it's.
{we'll} or {p:we'll}
Converts to I'll,
we'll, you'll, they'll, he'll, she'll, it'll.
{we're} or {p:we're}
Converts to I'm,
we're, you're, they're, he's, she's, it's.
{our} or {p:our}
Converts to my, our, your,
their, his, her, its.
{ours} or {p:ours}
Converts to mine, ours,
yours, theirs, his, hers, its.
{ourself} or {p:ourself}
Converts to
myself, ourself, yourself, themself, himself, herself, itself.
{ourselves} or {p:ourselves}
Converts to
myself, ourselves, yourself, themself, himself, herself, itself.
{don't} or {p:don't}
Converts to don't or
doesn't.
{haven't} or {p:haven't}
Converts to
haven't or hasn't.
{weren't} or {p:weren't}
Converts to
weren't or wasn't.
{have} or {p:have}
Converts to have or has.
{were} or {p:were}
Converts to were or was.
{are} or {p:are}
Converts to are or is.
Asset Pronouns
By default, a {pronoun} placed in text resolves to the turn's
subject, usually the player. In order to assign a placeholder to a
particular asset, use the form {asset name: pronoun} as in
this example.
msg += `{We} can't put ${this.$name()} inside {${this.id}:itself}. `;
Player Conditionals: if player is...
{[if player is on asset] print this string }
{[if player is on asset] print this string [else] print that
string}
if player is is a specific type of conditional that tests
whether the player is nested in/on/under/behind/attached to another asset.
asset is the name of your asset, and the words following the
bracketed conditional will be printed if the condition is true.
MyGame.createAsset({
class: "Chair",
name: "crash couch",
description: `The heavy crash couch {[if player is on crash couch] that you are strapped to} dominates the center of the cramped Control Room. `,
});
Player Conditionals: if player is not...
{[if player is not on asset] print this string }
{[if player is not on asset] print this string [else] print that string
}
if player is not is a specific type of conditional that tests
whether the player is NOT nested in/on/under/behind/attached to another
asset. asset is the name of your asset, and the words
following the bracketed conditional will be printed if the condition is
true.
MyGame.createAsset({
class: "Chair",
name: "crash couch",
description: `The heavy crash couch {[if player is not on crash couch] that you should be strapped to} dominates the center of the cramped Control Room. `,
});
Player Conditionals: if player has...
{[if player has asset] print this string }
{[if player has asset] print this string [else] print that string
}
if player has is a specific type of conditional that tests
whether the player is carrying another asset. asset is the
name of your asset, and the words following the bracketed conditional will
be printed if the condition is true.
MyGame.createAsset({
class: "Room",
name: "Ruby Room",
description: `Everything in the Ruby Room is red, making it hard to distinguish one thing from another{[if player has glasses], but thanks to the 3D glasses, one particular gem leaps out at you}. `,
});
Player Conditionals: if player has not...
{[if player has not asset] print this string }
{[if player has not asset] print this string [else] print that string
}
if player has not is a specific type of conditional that
tests whether the player is NOT carrying another asset.
asset is the name of your asset, and the words following the
bracketed conditional will be printed if the condition is true.
MyGame.createAsset({
class: "Room",
name: "Ruby Room",
description: `Everything in the Ruby Room is red, making it hard to distinguish one thing from another{[if player has not glasses]. If only you could tell things apart}. `,
});
Asset Conditionals: if asset is...
{[if asset is in asset] print this string }
{[if asset is in asset] print this string [else] print that string
}
{[if asset is locked] print this string }
{[if asset is locked] print this string [else] print that string
}
if asset is is a specific type of conditional that tests for
two things, depending on what is provided : 1) whether the asset is nested
in/on/under/behind/attached to another asset, 2) whether the asset has a
specified property. asset is the name of your asset, and the
words following the bracketed conditional will be printed if the condition
is true. The second form is equivalent to
{ asset [is] property [then] text }.
MyGame.createAsset({
class: "Gem",
name: "glittering gem",
description: `The gem glitters brightly{[if gem is in chest], casting light on the inner lid of the chest}. `,
});
MyGame.createAsset({
class: "Lantern",
name: "brass lantern",
description: `The lamp sits on the pedestal{[if lamp is on], lighting the room}.
});
Asset Conditionals: if asset is not...
{[if asset is not in asset] print this string }
{[if asset is not in asset] print this string [else] print that string
}
{[if asset is not locked] print this string }
{[if asset is not locked] print this string [else] print that string
}
if asset is not is a specific type of conditional that tests
for two things, depending on what is provided : 1) whether the asset is
NOT nested in/on/under/behind/attached to another asset, 2) whether the
asset has NOT got a specified property. asset is the name of
your asset, and the words following the bracketed conditional will be
printed if the condition is true.
MyGame.createAsset({
class: "Gem",
name: "glittering gem",
description: `The gem glitters brightly{[if gem is not in chest], casting light in all directions}. `,
});
MyGame.createAsset({
class: "Lantern",
name: "brass lantern",
description: `The lamp sits on the pedestal{[if lamp is not on], sucking light from the room}.
});
Asset Conditionals: if asset has...
{[if asset has asset] print this string }
{[if asset has asset] print this string [else] print that string
}
if asset has is a specific type of conditional that tests
whether one asset contains another asset. asset is the name
of your asset, and the words following the bracketed conditional will be
printed if the condition is true.
MyGame.createAsset({
class: "Chest",
name: "treasure chest",
description: `The chest rests on the pedestal{[if chest has gem], barely masking the light of the glittering gem inside it}. `,
});
Asset Conditionals: if asset has not...
{[if asset has not asset] print this string }
{[if asset has not asset] print this string [else] print that string
}
if asset has not is a specific type of conditional that tests
whether one asset does NOT contain another asset. asset is
the name of your asset, and the words following the bracketed conditional
will be printed if the condition is true.
MyGame.createAsset({
class: "Chest",
name: "treasure chest",
description: `The chest rests on the pedestal{[if chest has not gem], darkly drawing light into itself}. `,
});
Asset Conditionals
{ asset [is] property [or] property }
asset is the name of your asset, and the words following
[is] and [or] are properties on the asset, such
as asset.is.open and asset.is.closed. The idea
here is to use matching state properties such as open | closed, locked |
unlocked, sealed | unsealed.
MyGame.createAsset({
class: "Chest",
name: "brass chest",
description: `It's a small but sturdy looking chest bound in brass{ brass chest [is] open [or] closed }. `,
is: {
closed: true,
},
});
{ asset [is] property [then] text }
asset is the name of your asset, and the word following
[is] is a property on the asset, such as
asset.is.open. If the property is true, then the text
following [then] will be printed. If an invalid property is
used, the game will print "unknown state".
MyGame.createAsset({
class: "Chest",
name: "brass chest",
description: `It's a small but sturdy looking chest bound in brass{ brass chest [is] open [then] and lined with yolk colored satin }. `,
is: {
closed: true,
},
});
{ asset [is] property [then] text [else] text }
asset is the name of your asset, and the word following
[is] is a property on the asset, such as
asset.is.open. If the property is true, then the text
following [then] will be printed, otherwise the text
following [else] will be printed. If an invalid property is
used, the game will print "unknown state".
MyGame.createAsset({
class: "Chest",
name: "brass chest",
description: `It's a small but sturdy looking chest bound in brass{ brass chest [is] open [then] and lined with yolk colored satin [else] and sealed with wax }. `,
is: {
closed: true,
},
});
Identify exit by direction
Most assets can be specified in placeholders by their name or id. Exits
don't have names, and though they do have ids, those ids are created at
runtime and aren't shared back with the author. Exits can be identified
simply by providing the direction they exit to. The game's print method
understands that a direction refers to an exit in the current room. So for
example
{ north [is] open [or] closed }.
MyGame.createAsset({
class: "Exit",
direction: "north",
place: { in: "South Room" },
destination: "North Room",
description: `The north exit is { north [is] open [or] closed }. `,
is: {
closed: true,
},
});
Game Metadata
Authors may print certain game metadata using these shortcuts, such as in
a
introcard
or in response to an info command. This includes
title, version, author,
ifid, and description. See
Customize Output: Introcards
for more info.
MyGame.introcard.set({
text: `
{title}
Version {version}
By {author}
{description}
`,
prompt_to_continue: true,
});
This would result in a printout something like this:
Verb
Print the verb that was used this turn.
MyGame.createAsset({
class: "Scenery",
name: "imaginary object",
print_on_verb_failure: function () {
return `Though {we} can think about the imaginary object, {we} can't {verb} it. `;
},
});
Adverbs
This is a goofy little gimmick we threw in for fun. Use it to add a tiny random element to canned responses.
{ success_adverb }
Randomly pick an adverb from
game.dictionary.success_adverbs
MyGame.createAsset({
class: "Chest",
name: "brass chest",
description: `It's a small but sturdy looking chest bound in brass. `,
dov: {
open: {
on_first_success:
`{We} succeed {success_adverb} in opening the chest! `
},
},
});
{ fail_adverb }
Randomly pick an adverb from
game.dictionary.failure_adverbs
MyGame.createAsset({
class: "Chest",
name: "brass chest",
description: `It's a small but sturdy looking chest bound in brass. `,
dov: {
open: {
on_failure:
`{We} fail {fail_adverb} to open the chest. `
},
},
});
Links
Two types of placeholders can be used to place links in text using
standard HTML <a> tags.
{>:input text}
Makes a link of the text that, when clicked, is input to the parser. Use this for verb directives.
MyGame.createAsset({
class: "Room",
name: "Monte Barraù",
description: `
The summit of Monte Barraù is capped by the wide flat family-style Tavolo,
at which is placed a high chair, the Residenza di Famiglia.
{We} should try to {>:sit in the Residenza di Famiglia}.
`,
});
{a:asset name}
Makes a link of the asset name that, when clicked, is input to the parser.
MyGame.createAsset({
class: "Room",
name: "Monte Barraù",
description: `
The summit of {a:Monte Barraù} is capped by the wide flat family-style Tavolo,
at which is placed a high chair, the {a:Residenza di Famiglia}.
{We} should try to sit in the Residenza di Famiglia.
`,
});
- If the player has entered any text in the input field, the name of the asset will be appended to the input field.
- If no text has been entered in the input field, clicking the link will be treated as if the player had input examine asset name.
-
Examine is the default verb for this action, but it can be adjusted by
changing
game.settings.asset_link_verb.
MyGame.settings.set({
asset_link_verb: "take",
});
Placeholders vs Template Literals
Template literals are a native Javascript ES6 feature. If you're just starting out with AdventureJS and/or Javascript, you may not need to think about this right now. If you're an experienced Javascript user, you may find that placeholders look similar to template literals. However, they are distinctly different.
Placeholders...
- do not have a leading dollar sign {}
- can be placed within any string delimiters including single quotes '...', double quotes "...", or backtick characters `...`
- have no scope to speak of, as they only provide variables to a handler method
- are not evaluated until they are printed to the display
Template literals...
- have a leading dollar sign ${}
- must be placed within backtick `...` characters
- permit active Javascript, scoped to the method they are running in
- are evaluated as soon as they are encountered at runtime
AdventureJS placeholders can be mixed & matched with Javascript template
literals. Placeholders can even be nested inside template literals and
vice versa, because they are evaluated separately. Placeholders can be
used in any string that outputs to the game display. However, template
literals must be returned by functions, rather than stored in string
properties, to avoid errors on game startup by letting them be evaluated
too soon. Here's an example that assumes that
aurora_color stores a string that describes a color:
MyGame.createAsset({
class: "Window",
name: "frosted window",
description: function () {
return `The frosted window
${MyGame.$("frosted window").$is("closed") ?
"is closed, obscuring the aurora. " :
"is open, revealing the {aurora_color} light of the aurora." }`;
},
});
Further Reference
To learn more about template literals, we recommend the MDN reference library.