Verb:type
Instance of: AdventureJS.Dictionary.Verb
Defined in: Adventure/Dictionary/verbs/type.js, line 6
Tutorials: Subscriptions HowAVerbIsBuilt HowAVerbWorks ModifyVerbs
Description
Type on a Entity
Asset.
Requires that the Asset has
asset.dov.type.enabled set to true. Type
considers a direct object's parent. For instance, type can
infer the meaning of
type on paper
if the specified paper is in a typewriter.
Demo
// WritingDemo.js
// ----------
/*global AdventureJS WritingDemo*/
var WritingDemo = new AdventureJS.Game("WritingDemo", "WritingDemoContainer");
// Let's set some Game settings
WritingDemo.settings.set({
// title, version, and author are shown in the title bar
title: "Writing Demo",
version: "0.0.1",
author: "Ivan Cockrum",
description: "This is my great game! Thanks for playing!",
// apply_color_classes_to_written_strings: true,
// if any of these are true, AdventureJS will log
// messages to the browser's console
// See the full list of available settings in
// /doc/adventure_Settings.js.html
log: {
verbaction: true,
verbreaction: true,
verbphase: true,
game: true,
parser: true,
verb: true,
},
// if any of these are true, AdventureJS will print
// debug messages to the game display
debug: {
general: true,
// verbaction: true,
// verbreaction: true,
// verbphase: true,
},
// if this is false, the game won't infer objects
// until player has already used them
// good for preventing spoilers but can be annoying
allow_inference_on_first_use: true,
// if this is true, lists of exits will
// show the names of rooms they lead to
print_exits_room_names: true,
// if this is true, lists of exits will
// only include room names known to player
print_exits_room_names_if_known: false,
// if this is true, lists of exits will only
// show room names for exits player has used
print_exits_room_names_if_used: false,
// if this is true, verbose room descriptions will be
// shown on first visit regardless of verbosity settings
print_verbose_room_descriptions_on_first_visit: true,
responses: {
// set this to set a default response to
// player input that is not understood
no_response: "I have no response to your input. ",
// set this to provide a default
// response to blank input
empty_input: "I didn't see any input. ",
},
// alternately, game can be set to print
// the current room description with
// if_input_is_empty_print_room_description: true
// when the parser infers an action, it may print
// the inference, such as "take pot (from stove)"
// for this game we want to turn these off
print_inferred: false,
});
WritingDemo.createAsset({
class: "Room",
name: "Writing Demo Foyer",
// setting definite_article to "the" sets it so the room
// name appears as "the Writing Demo Foyer" in lists
definite_article: "the",
descriptions: {
look: `Welcome to the Writing Demo, where you can try interacting with assets of several related classes including
<a href="/doc/AdventureJS.Assets.WritingImplement.html">WritingImplement</a>
(<a href="/doc/AdventureJS.Assets.Pen.html">Pen</a>,
<a href="/doc/AdventureJS.Assets.Pencil.html">Pencil</a>,
<a href="/doc/AdventureJS.Assets.Chalk.html">Chalk</a>,
<a href="/doc/AdventureJS.Assets.Marker.html">Marker</a>),
<a href="/doc/AdventureJS.Assets.WritingSurface.html">WritingSurface</a>
(<a href="/doc/AdventureJS.Assets.Paper.html">Paper</a>,
<a href="/doc/AdventureJS.Assets.Blackboard.html">Blackboard</a>,
<a href="/doc/AdventureJS.Assets.Whiteboard.html">Whiteboard</a>),
<a href="/doc/AdventureJS.Assets.Typewriter.html">Typewriter</a>, and
<a href="/doc/AdventureJS.Assets.Eraser.html">Eraser</a>. Try
<a href="/doc/write.html">writing</a> on,
<a href="/doc/write.html">drawing</a> on,
<a href="/doc/type.html">typing</a> on, and
<a href="/doc/erase.html">erasing</a> things.
Visit the other rooms in this demo to find some
demonstrations. `,
brief: `Try verbs.
<a href="/doc/read.html">Read</a>,
<a href="/doc/write.html">write</a>,
<a href="/doc/type.html">type</a>,
<a href="/doc/erase.html">erase</a>. `,
},
exits: {
north: "Classroom",
south: "Library",
east: "Office",
west: "Playroom",
},
}); // Writing Demo Foyer
WritingDemo.createAsset({
class: "Player",
name: "Will",
place: { in: "Writing Demo Foyer" },
is: { active: true },
pronouns: "second",
});
// createClass()
// We're going to create several pieces of paper for this game.
// AdventureJS has a Paper class, but we want to add some
// specific properties to every instance of Paper. First, we
// want to specify several subclasses of WritingImplements that
// can write on them - Pen, Pencil, Crayon - but not Chalk or
// Marker. Then, we want to specify a particular Eraser that
// can erase them - the rubber eraser but not the Whiteboard
// eraser or Blackboard eraser.
//
// This is a minimal class definition. It extends the
// Paper class by customizing its write and erase verb
// subscriptions.
//
// Creating custom classes is an advanced move, so if you decide
// to create some, be sure to RTFM and test them extensively.
// See https://adventurejs.com/doc/AdvancedScripting_CustomClasses.html
// for more info.
WritingDemo.createClass({
class: "CustomPaper",
extend: "Paper",
// Limit what assets can erase this class.
dov: {
erase: { with_assets: ["rubber eraser"] },
},
// Limit what classes can write on this class.
iov: {
write: {
with_classes: ["Crayon", "Pen", "Pencil"],
on_success: function () {
WritingDemo.scorecard.awardPoint("write on paper");
},
},
type: {
// We want to set a custom message when a player tries
// and fails to type on this class. Though it seems
// that "type on paper" would have paper be a direct
// object, type is tricky to parse because technically,
// the information being typed is the direct object,
// even if no information is specified. So, for type,
// the paper and the typewriter are both indirect
// objects.
// Here is one valid way to return a message, but...
// on_failure: `{We} might try putting it in a typewriter. `,
// ...we're going to be nitpicky about how we refer
// to the typewriter. If it's present we'll say
// "the typewriter" and if it's not we'll say
// "a typewriter". We'll use some embedded Javascript
// to test the typewriter's presence.
on_failure: function () {
return `{We} might try putting it in ${
WritingDemo.$("typewriter").$is("present") ? "the" : "a"
} typewriter. `;
},
},
},
});
// now we can create an instance of our new CustomPaper class
WritingDemo.createAsset({
class: "CustomPaper",
name: "pink paper",
// indefinite articles are handled automatically,
// but they can be set manually
indefinite_article: "a sheet of",
synonyms: ["sheet", "sheet of pink paper"],
description: "It's a sheet of pink paper. ",
place: { in: "Writing Demo Foyer" },
typed_strings: ["Find the two bonus points!"],
});
// Office.js
// ----------
/*global AdventureJS A WritingDemo*/
WritingDemo.createAsset({
class: "Room",
name: "Office",
definite_article: "the",
descriptions: {
look: `This office is dominated by an oak mission style desk
with an old fashioned office chair. One wall is covered by a
whiteboard, with a narrow ledge for accessories. Try writing
on things with other things. See the example code
in <a href="/examples/WritingDemo/Office.js">Office.js</a> for particulars. `,
brief: "Time to get to work. ",
},
exits: { west: "Writing Demo Foyer" },
}); // Office
WritingDemo.createAsset({
class: "Whiteboard",
name: "whiteboard",
place: { in: "Office" },
description: `It's a classic office whiteboard. `,
// Because the whiteboard is mentioned in the room description,
// we don't need it listed as a piece of inventory in the room.
// We can prevent it from being listed by setting
// is.listed to false.
is: { listed: false },
dov: {
// Though player can use an eraser to erase the whiteboard,
// setting whiteboard.dov.erase.with_nothing = true allows
// the player to erase the whiteboard without another asset,
// which we'll understand to mean that they're using their hand.
// (In fact this is the default setting for class Whiteboard,
// but we're redefining it here just to make this point.)
erase: {
with_nothing: true,
on_success: function () {
WritingDemo.scorecard.awardPoint("erase whiteboard");
},
},
},
iov: {
write: {
on_success: function () {
WritingDemo.scorecard.awardPoint("write on whiteboard");
},
},
},
// Should a player erase the whiteboard without an eraser,
// the verb action doEraseThis() will be called and we can
// treat it as if player is using their hand as an eraser.
doEraseThis: function () {
WritingDemo.appendOutput(`It leaves a smudge of ink on {our} hand. `);
},
}); //
// We don't have any special class for this whiteboard
// ledge so we'll just use the generic Thing class,
// and set whatever properties we might need.
WritingDemo.createAsset({
class: "Entity",
name: "whiteboard ledge",
description: `A narrow ledge that runs the length of the whiteboard, on which to store whiteboard accessories. `,
place: { in: "Office" },
// ensure that player can take things from and put things on the ledge
iov: { take: true, put: true },
// Because the ledge is mentioned in the room description,
// we don't need it listed as a piece of inventory in the room.
// We can prevent it from being listed by setting
// is.listed to false.
is: { listed: false },
// Thing has no aspects by default, so we'll do the bare
// minimum to define an "on" aspect. Now we can put things
// on it.
aspects: { on: true },
}); //
WritingDemo.createAsset({
class: "WhiteboardEraser",
name: "microfiber eraser",
place: { on: "whiteboard ledge" },
descriptions: { look: "It's a microfiber eraser. " },
// Verb subscriptions
// By setting iov.erase.with_classes to ["Whiteboard"]
// we're customizing this asset's erase verb subscription
// to establish that the whiteboard is the only
// thing this eraser can erase.
//
// This is similar to what we did with the WhiteboardMarker
// class, but we didn't bother to create a new class for
// WhiteboardErasers because there's only one of them,
// so we're just adjusting its individual properties.
// iov: { erase: { with_classes: ["Whiteboard"] } },
// Verb action hooks - doEraseThatWithThis()
// Verb action hooks allow authors
// to call custom code after specific actions.
//
// Verb action hooks can be formatted in different
// ways depending on the level of specificity needed.
//
// In this case, since the whiteboard is the only thing
// the eraser can erase, we know that the "That" in
// doEraseThatWithThis must be the whiteboard, and we can
// refer to it unambiguously in this verb action hook.
doEraseThatWithThis: function () {
WritingDemo.appendOutput(
`The eraser squeaks as it's dragged across the board. `
);
},
}); //
WritingDemo.createAsset({
class: "WhiteboardMarker",
name: "red marker",
adjectives: ["red", "dry erase", "red dry erase"],
place: { on: "whiteboard ledge" },
descriptions: { look: "It's a red dry erase marker. " },
appearance: { color: "red" },
}); // RedMarker
WritingDemo.createAsset({
class: "WhiteboardMarker",
name: "orange marker",
adjectives: ["orange", "dry erase", "orange dry erase"],
place: { on: "whiteboard ledge" },
descriptions: { look: "It's a orange dry erase marker. " },
appearance: { color: "orange" },
}); // OrangeMarker
WritingDemo.createAsset({
class: "WhiteboardMarker",
name: "cyan marker",
adjectives: ["cyan", "dry erase", "cyan dry erase"],
place: { on: "whiteboard ledge" },
descriptions: { look: "It's a cyan dry erase marker. " },
appearance: { color: "cyan" },
}); // CyanMarker
WritingDemo.createAsset({
class: "Desk",
name: "desk",
place: { in: "Office" },
// describeDeskDrawers() is an example of a custom function.
// See the function description below for more information.
// Note how we've set description to be a function rather than
// a string, as we've done elsewhere. That is because we're
// using a Javascript ${template literal}, which is always
// evaluated immediately, and so if we set this as a string,
// it would be evaluated at runtime, before the game has built,
// and throw an error. By making it a function, it won't be
// evaluated until we call it.
description: function () {
return `It's an oak mission style desk, with an old fashioned office
chair. It has three drawers stacked vertically.
${describeDeskDrawers()}`;
},
synonyms: [""],
adjectives: ["mission style", "mission", "style", "oak"],
// Just for fun, let's say the player can go under the desk.
aspects: {
under: {
list_contents_in_room: false,
list_contents_in_examine: true,
nest: {
posture: "kneel",
can: { enter: true, exit: true, kneel: true, stand: false },
},
},
},
// Because the desk is mentioned in the room description,
// we don't need it listed as a piece of inventory in the room.
// We can prevent it from being listed by setting
// is.listed to false.
is: { listed: false },
});
WritingDemo.createAsset({
class: "Drawer",
name: "top drawer",
synonyms: [
"top desk drawer",
"top drawer lock",
"top drawer lock plate",
"lock",
"lock plate",
],
adjectives: ["brass", "desk"],
// Here we're using an AdventureJS custom template
// to print whether the drawer is open or closed.
// Placeholders are like Javascript template literals,
// but a little different.
description: `The top drawer has a small brass lock plate. The drawer is { top drawer [is] open [or] closed }. `,
place: { attached: "desk" },
// We're setting this drawer closed and locked.
// We set listed to false so it doesn't
// get listed like a piece of inventory.
is: {
closed: true,
locked: true,
listed: false,
},
// Setting dov.unlock.with_assets["tiny brass key"]
// means that only the tiny brass key can unlock this.
dov: { unlock: { with_assets: ["tiny brass key"] } },
});
WritingDemo.createAsset({
class: "Drawer",
name: "middle drawer",
synonyms: "middle desk drawer",
description: "The middle drawer is { middle drawer [is] open [or] closed }. ",
adjectives: "desk",
place: { attached: "desk" },
is: {
closed: true,
listed: false,
},
});
WritingDemo.createAsset({
class: "Drawer",
name: "bottom drawer",
synonyms: "bottom desk drawer",
description: "The bottom drawer is { bottom drawer [is] open [or] closed }. ",
adjectives: "desk",
place: { attached: "desk" },
is: {
closed: true,
listed: false,
},
});
// Collections
// In our current example, the desk has three drawers. Though
// the parser understands plurals, if a player asked for
// "desk drawers", the parser's default behavior would be
// to prompt for disambiguation: "which drawer did you mean?"
//
// From a player's perspective, that's just tedious, because
// it's perfectly reasonable to expect "examine desk drawers"
// to return a description that includes all three. That's what
// Collections are for. Collections describe a group of assets,
// so that players can refer to multiple assets with one term.
//
// In this case, "desk drawers" is a Collection that represents
// all three desk drawers.
WritingDemo.createAsset({
class: "Collection",
name: "desk drawers",
place: { attached: "desk" },
targets: "top drawer, middle drawer, bottom drawer",
synonyms: ["drawers", "three drawers"],
is: {
listed: false,
},
// describeDeskDrawers() is an example of a custom function.
// See the function description below for more information.
// Note how we've set description to be a function rather than
// a string, as we've done elsewhere. That is because we're
// using a Javascript ${template literal}, which is always
// evaluated immediately, and so if we set this as a string,
// it would be evaluated at runtime, before the game has built,
// and throw an error. By making it a function, it won't be
// evaluated until we call it.
description: function () {
return `The desk has three drawers stacked vertically: top, middle and bottom. ${describeDeskDrawers()}`;
},
});
// describeDeskDrawers()
// Here, we've made a custom function that describes the state
// of all three desk drawers. The reason we've done this
// is so that we can show it in two places without repeating
// code. We use this in the desk's description, and also in
// the desk drawers collection. This function exists in the
// global scope, aka the browser window, which means that
// you can call it from anywhere. (Technically, this is kind
// of sloppy, and you probably shouldn't do it in other
// environments, but it won't hurt anything in AdventureJS.)
// @returns string
function describeDeskDrawers() {
const open = [];
const closed = [];
let msg = "The top drawer has a small brass lockplate. ";
// get a list of all the open drawers
// and a list of all the closed drawers
WritingDemo.$("top drawer").is.closed ? closed.push("top") : open.push("top");
WritingDemo.$("middle drawer").is.closed
? closed.push("middle")
: open.push("middle");
WritingDemo.$("bottom drawer").is.closed
? closed.push("bottom")
: open.push("bottom");
// print a slightly different description based
// on however many drawers are open or closed
switch (open.length) {
case 0:
msg += `All three drawers are closed. `;
break;
case 1:
msg += `The ${closed[0]} and ${closed[1]} drawers are closed. The ${open[0]} drawer is open. `;
break;
case 2:
msg += `The ${open[0]} and ${open[1]} drawers are open. The ${closed[0]} drawer is closed. `;
break;
case 3:
msg += `All three drawers are open. `;
break;
}
return msg;
}
WritingDemo.createAsset({
class: "Chair",
name: "office chair",
place: { in: "Office" },
// It's a swivel chair, so we're going to allow
// the verb turn to act on it.
dov: { turn: true },
description: `It's an old fashioned wooden office chair that rolls on swiveling castors. `,
// Because the chair is mentioned in the room description,
// we don't need it listed as a piece of inventory in the room.
// We can prevent it from being listed by setting
// is.listed to false.
is: { listed: false },
// Use as many adjectives and synonyms as you like.
// Adding more words makes it easier for you and your
// player. It reduces players' chances of getting stuck
// playing guess-the-word, and increases your chances
// of correctly parsing players' input.
synonyms: ["castor", "castors"],
adjectives: ["old", "fashioned", "old fashioned", "heavy", "wooden"],
// This is an example of a verb reaction hook. Any time
// Will (the player character of this game) gets out of
// the chair, this string will be prepended to the
// game's default output. It's also possible to
// appendOutput or overrideOutput.
doUnnestThatFromThis: {
Will: function () {
WritingDemo.prependOutput(
`The office chair creaks as {we} climb out of it. `
);
},
},
aspects: {
on: {
// Because we're not listing the chair, things placed on it
// won't be listed either. We're explicitly setting it so
// that they will be.
list_contents_in_room: true,
// By default, when the player is nested in one asset,
// they can't reach things in/on other assets.
// Setting aspects.on.nest.can.reach["student desk"] enables
// the player to reach the desk and items in/on it,
// such as the drawers and typewriter, while sitting
// in the office chair.
nest: { can: { reach: ["desk"] } },
},
},
});
WritingDemo.createAsset({
class: "Key",
name: "tiny brass key",
image: "brasskey",
description: "It's a tiny key, made of brass. ",
adjectives: ["tiny", "brass"],
place: { on: "desk" },
});
WritingDemo.createAsset({
class: "Pencil",
name: "mechanical pencil",
adjectives: "brass",
synonyms: ["design", "designs"],
place: { on: "desk" },
description:
"It's a mechanical pencil made out of pressed brass, with intricate designs stamped into it. ",
}); // BrassPencil
WritingDemo.createAsset({
class: "Eraser",
name: "rubber eraser",
place: { on: "desk" },
description: `It's an ordinary rubber eraser. `,
iov: {
erase: {
on_success: function () {
WritingDemo.scorecard.awardPoint("erase paper");
},
},
},
}); // BrassPencil
WritingDemo.createAsset({
class: "Pen",
name: "indigo pen",
adjectives: "indigo",
place: { in: "top drawer" },
descriptions: { look: "It's a pen with indigo ink. " },
appearance: { color: "indigo" },
}); // IndigoPen
WritingDemo.createAsset({
class: "Pen",
name: "yellow pen",
adjectives: "yellow",
place: { in: "top drawer" },
descriptions: { look: "It's a pen with yellow ink. " },
appearance: { color: "yellow" },
}); // YellowPen
WritingDemo.createAsset({
class: "Pen",
name: "green pen",
adjectives: "green",
place: { in: "top drawer" },
descriptions: { look: "It's a pen with green ink. " },
appearance: { color: "green" },
iov: {
write: {
on_first_success: function () {
WritingDemo.scorecard.awardPoint("write with green pen");
},
},
},
}); //GreenPen
WritingDemo.createAsset({
class: "PenCap",
name: "pen cap",
place: { attached: "green pen" },
descriptions: { look: "It's a cap for a pen. " },
}); //
WritingDemo.createAsset({
class: "CustomPaper",
name: "white paper",
// indefinite articles are handled automatically,
// but they can be set manually
indefinite_article: "a sheet of",
synonyms: ["sheet", "sheet of white paper"],
adjectives: [""],
description: "It's a sheet of white paper. ",
place: { on: "desk" },
dov: { erase: { with_assets: ["rubber eraser"] } },
});
// Playroom.js
// ----------
/*global AdventureJS A WritingDemo*/
WritingDemo.createAsset({
class: "Room",
name: "Playroom",
definite_article: "the",
descriptions: {
look: `Generations of children have lounged upon floor cushions scattered around a low activity table.
See the example code in <a href="/examples/WritingDemo/Playroom.js">Playroom.js</a> for particulars. `,
brief: "Table. Cushions. Please take your seat. ",
},
exits: { east: "Writing Demo Foyer" },
}); // Playroom
WritingDemo.createAsset({
class: "Table",
name: "activity table",
place: { in: "Playroom" },
description: `It's a low table, perfect for arts and crafting. `,
adjectives: [""],
// The activity table is mentioned in the room description,
// so we don't need it listed in the room, but we do want
// the things on it to be listed in the room.
is: { listed: false },
// By default, Table class has an under aspect which is not
// revealed until player examines table, but in this case,
// we want player to see what's under the table as soon
// as they enter the room.
aspects: {
under: { know_contents_with_parent: true, list_contents_in_room: true },
},
});
WritingDemo.createAsset({
class: "Entity",
name: "cushions",
synonyms: ["cushion"],
adjectives: ["floor"],
place: { in: "Playroom" },
description: `A gang of comfortable floor cushions. `,
is: { listed: false },
// Because we're building on the basic Thing class, we have
// to define some basic setup stuff that might otherwise have
// been preset if we'd used a more specialized class.
// (The Furniture class would been suitable for these cushions.)
// Here, we need to set up an on aspect with a nest for the
// player to enter, and specify that the activity table is
// reachable while sitting in it.
aspects: {
on: {
nest: {
posture: "sit",
can: { enter: true, exit: true, sit: true, reach: ["activity table"] },
},
},
},
// Continuing with the basic setup...
// If player says "get up", which gets parsed as "stand up",
// while sitting on the cushions, we want to ensure they
// get off the cushions, as opposed to trying to stand up
// in place on the cushions, which is the default behavior
// for stand.
quirks: { stand_means_get_off: true },
// We want to print a custom message when the player sits here.
doNestThatToThis: {
Will: function () {
WritingDemo.scorecard.awardPoint("sit on cushions");
WritingDemo.overrideOutput(
`{We} settle down cross legged among the floor cushions, {our} knees pressed against the low activity table. `
);
},
},
// We want to print a custom message when the player leaves this.
doUnnestThatFromThis: {
Will: function () {
WritingDemo.overrideOutput(
`{We} climb up off the cushions, bumping the table along the way. `
);
},
},
}); // Cushions
WritingDemo.createAsset({
class: "Pencil",
name: "blue pencil",
adjectives: ["blue", "colored"],
place: { on: "activity table" },
description: "It's a blue colored pencil. ",
appearance: { color: "blue" },
}); // BluePencil
WritingDemo.createAsset({
class: "Pencil",
name: "pink pencil",
adjectives: ["pink", "colored"],
place: { on: "activity table" },
description: `It's an pink colored pencil. `,
appearance: { color: "pink" },
}); // PinkPencil
WritingDemo.createAsset({
class: "Pencil",
name: "teal pencil",
adjectives: ["teal", "colored"],
place: { on: "activity table" },
description: `It's a teal colored pencil. `,
appearance: { color: "teal" },
}); // TealPencil
WritingDemo.createAsset({
class: "CustomPaper",
name: "drawing paper",
// indefinite articles are handled automatically,
// but they can be set manually
indefinite_article: "a sheet of",
synonyms: ["sheet", "sheet of drawing paper"],
adjectives: [""],
description: "It's a sheet of drawing paper. ",
place: { on: "activity table" },
// It isn't necessary to include this next line because it is
// baked into the Paper class, but it's worth seeing how we
// determine which WritingImplements may write on which
// WritingSurfaces. Here, we're saying that Paper is
// subscribed to the verb write with these classes. If
// player tries to write on Paper with anything else, they'll
// get an error message.
// dov: { write: { with_classes: ["Crayon", "Pen", "Pencil"] } },
dov: { erase: { with_assets: ["rubber eraser"] } },
});
WritingDemo.createAsset({
class: "Crayon",
name: "purple crayon",
adjectives: [""],
place: { under: "activity table" },
description: `It's a purple crayon. `,
// Assigning a color to a WritingImplement is optional.
// If provided, the text that is written will be printed
// back with a CSS class with the name of that color, and
// a CSS class of the particular WritingImplement subclass.
// You can use this to make that text print in that color,
// or in a different font, etc.
//
// For example, strings written with this purple crayon
// will be printed like this and appear in purple:
// <span class="string purple crayon">foo</span>
//
// adventurejs.css has a few standard color classes defined.
// You're welcome to customize such classes as you like.
appearance: { color: "purple" },
}); //
// Classroom.js
// ----------
/*global AdventureJS A WritingDemo*/
WritingDemo.createAsset({
class: "Room",
name: "Classroom",
definite_article: "the",
descriptions: {
look: `This classroom features an antique student desk with
an attached bench, facing a large blackboard
with a narrow ledge for accessories. Try writing
on things and erasing things. See the example code in
<a href="/examples/WritingDemo/Classroom.js">Classroom.js</a> for particulars. `,
brief: "Blackboard. Desk. Bench. Please take your seat. ",
},
exits: { south: "Writing Demo Foyer" },
}); // Classroom
WritingDemo.createAsset({
class: "Blackboard",
name: "blackboard",
place: { in: "Classroom" },
description: `It's a classic schoolroom blackboard. `,
// Because the blackboard is mentioned in the room description,
// we don't need it listed as a piece of inventory in the room.
// We can prevent it from being listed by setting
// is.listed to false.
is: { listed: false },
dov: {
// Though player can use an eraser to erase the blackboard,
// setting dov.erase.with_nothing = true allows the player
// to erase the blackboard without another asset.
// (This is the default setting for class Blackboard.
// We're redefining it here just to make the point.)
erase: {
with_nothing: true,
on_success: function () {
WritingDemo.scorecard.awardPoint("erase blackboard");
},
},
},
iov: {
// The reason why write is defined under iov rather
// than dov is because when writing, the thing being
// written is always the direct object, while both
// the writing implement and the writing surface are
// indirect objects.
write: {
with_classes: ["Chalk"],
on_success: function () {
WritingDemo.scorecard.awardPoint("write on blackboard");
},
},
},
// Should a player erase the blackboard without an eraser,
// the verb action doEraseThis() will be called and we can
// treat it as if player is using their hand as an eraser.
doEraseThis: function () {
WritingDemo.appendOutput(
`It leaves a powdering of chalk dust on {our} hand. `
);
},
}); //
// We don't have any special class for this blackboard
// ledge so we'll just use the generic Thing class,
// and set whatever properties we might need.
WritingDemo.createAsset({
class: "Entity",
name: "blackboard ledge",
description: `A narrow ledge that runs the length of the blackboard, on which to store blackboard accessories. `,
place: { in: "Classroom" },
// ensure that player can take things from and put things on the ledge
iov: { take: true, put: true },
// Because the ledge is mentioned in the room description,
// we don't need it listed as a piece of inventory in the room.
// We can prevent it from being listed by setting
// is.listed to false.
is: { listed: false },
// Thing has no aspects by default, so we'll do the bare
// minimum to define an "on" aspect. Now we can put things
// on it. Though the ledge's listed is false,
// we can still have its contents listed in the room by
// setting the on aspect's list_contents_in_room to true.
aspects: { on: { list_contents_in_room: true } },
}); //
WritingDemo.createAsset({
class: "BlackboardEraser",
name: "felt eraser",
place: { on: "blackboard ledge" },
descriptions: { look: "It's a felt eraser. " },
// Verb action hooks - doEraseThatWithThis()
//
// Verb action hooks allow authors
// to call custom code after specific actions.
// Verb action hooks can be formatted in different
// ways depending on the level of specificity needed.
//
// In this case, since the whiteboard is the only thing
// the eraser can erase, we know that the "That" in
// doEraseThatWithThis must be the whiteboard, and we can
// refer to it unambiguously in this verb action hook.
doEraseThatWithThis: {
blackboard: function () {
WritingDemo.appendOutput(`A small cloud of chalk dust puffs out. `);
},
},
}); //
WritingDemo.createAsset({
class: "Chalk",
name: "stick of white chalk",
synonyms: "white chalk",
adjectives: "white",
place: { on: "blackboard ledge" },
descriptions: { look: "It's a stick of white chalk. " },
appearance: { color: "white" },
}); //
WritingDemo.createAsset({
class: "Chalk",
name: "stick of pink chalk",
synonyms: "pink chalk",
adjectives: "pink",
place: { on: "blackboard ledge" },
descriptions: { look: "It's a stick of pink chalk. " },
// Setting appearance.color is optional, but when it's set
// for WritingImplements, anything written with that tool
// will be printed to the game display with that color as
// a CSS class name. For example:
// <span class="pink">whatever player wrote</span>
appearance: { color: "pink" },
}); //
WritingDemo.createAsset({
class: "Chalk",
name: "stick of blue chalk",
synonyms: "blue chalk",
adjectives: "blue",
place: { on: "blackboard ledge" },
descriptions: { look: "It's a stick of blue chalk. " },
appearance: { color: "blue" },
}); //
WritingDemo.createAsset({
class: "Paper",
name: "blue paper",
synonyms: ["sheet", "sheet of blue paper"],
// indefinite articles are handled automatically,
// but they can be set manually
indefinite_article: "a sheet of",
adjectives: [""],
description: "It's a sheet of blue paper. ",
place: { in: "student desk" },
dov: { erase: { with_assets: ["rubber eraser"] } },
});
WritingDemo.createAsset({
class: "Desk",
name: "student desk",
place: { in: "Classroom" },
description: function () {
return `It's an old-fashioned lift top school desk with an
attached bench. The desk top is {student desk [is] open [or] closed}. `;
},
synonyms: [""],
adjectives: [""],
dov: { open: true, close: true },
// Because the desk is mentioned in the room description,
// we don't need it listed as a piece of inventory in the room.
// We can prevent it from being listed by setting
// is.listed to false.
is: { closed: true, listed: false },
// If the desk's listed were true, the things sitting
// on it would be automatically listed. But since we've made
// the desk unlisted, we need to explicitly tell the game
// to list the things on the desk.
aspects: {
on: { list_contents_in_room: true },
in: { list_contents_in_room: true },
attached: {
// We've included the bench in the desk's description, so
// we don't want it listed as an inventory item when
// the desk is examined.
list_contents_in_examine: false,
// However, we do want the bench known/seen with the desk.
// The Desk class sets know_contents_with_parent and
// see_contents_with_parent to false, because the class
// definition assumes that anything attached to the desk
// is a drawer or something similar, where you might not
// want the player knowing about their contents until they
// open the drawer. We're going to override these properties
// to ensure that the player knows/sees the bench.
know_contents_with_parent: true,
see_contents_with_parent: true,
},
},
});
WritingDemo.createAsset({
class: "Chair",
name: "bench",
place: { attached: "student desk" },
synonyms: [""],
adjectives: ["uncomfortable", "wooden"],
description: `It's an uncomfortable looking wooden bench. `,
// Because the chair is mentioned in the room description,
// we don't need it listed as a piece of inventory in the room.
// We can prevent it from being listed by setting
// is.listed to false.
is: {
listed: false,
// Because the bench is attached to the desk, it needs the
// is.deep_nest flag to allow player to nest to it.
// Technically it wasn't necessary to attach the bench to
// the desk - we could have just described it as being
// attached without actually attaching it. In this case it's
// just a matter of organizational preference.
deep_nest: true,
},
aspects: {
on: {
// Because we're not listing the chair, things placed on it
// won't be listed either. We're explicitly setting it so
// that they will be.
list_contents_in_room: true,
// By default, when the player is nested in one asset,
// they can't reach things in/on other assets.
// Setting aspects.on.nest.can.reach["student desk"] enables
// the player to reach the desk and items in/on it,
// such as the drawers and typewriter, while sitting
// in the office chair.
nest: { can: { reach: ["student desk"] } },
},
},
// doNestThatToThis()
// This is an example of a verb reaction hook. Any time
// Will (the player character of this game) gets into or
// out of the bench, the provided string will override the
// game's default output. It's also possible to
// appendOutput or prependOutput.
doNestThatToThis: {
Will: function () {
WritingDemo.overrideOutput(`{We} fold {ourself} into the small bench. `);
},
},
doUnnestThatFromThis: {
Will: function () {
WritingDemo.overrideOutput(
`{We} unfold {ourself} from the small bench. `
);
},
},
});
// Library.js
// ----------
/*global AdventureJS A WritingDemo*/
WritingDemo.createAsset({
class: "Room",
name: "Library",
definite_article: "the",
descriptions: {
look: `Cramped shelves full of dusty books, but they're unimportant right now. A modest rolltop desk is permanently open to display an antique typewriter. Try typing. See the example code in <a href="/examples/WritingDemo/Library.js">Library.js</a> for particulars. `,
brief: "Shelves. Books. Desk. Type! ",
},
exits: { north: "Writing Demo Foyer" },
}); // Library
WritingDemo.createAsset({
class: "Desk",
name: "rolltop desk",
adjectives: ["modest"],
place: { in: "Library" },
description: `It's a modest rolltop desk, locked in the open position. `,
// Because the desk is mentioned in the room description,
// we don't need it listed as a piece of inventory in the room.
// We can prevent it from being listed by setting
// is.listed to false.
is: { listed: false },
}); // RolltopDesk
WritingDemo.createAsset({
class: "Scenery",
name: "cramped shelves",
place: { in: "Library" },
description: `The cramped shelves are just a scenery object. You know. For verisimilitude. `,
// The shelves, being a scenery asset, aren't
// subscribed to verb climb and can't be climbed,
// but if a player should try to climb them, we
// want to offer a snappy response. We have a variety
// of verb hooks to work with. In this case,
// tryClimb() is the simplest option. We'll use
// overrideOutput to override the default response.
tryClimb: function () {
WritingDemo.overrideOutput(`In Soviet Russia, shelves climb you! `);
WritingDemo.scorecard.awardPoint("try to climb shelves");
},
// dov: { climb: true },
}); // cramped shelves
WritingDemo.createAsset({
class: "Scenery",
name: "dusty books",
place: { in: "Library" },
description: `The dusty books are just another lousy scenery object. `,
// The books, like the shelves, are a scenery object
// that can't be interacted with, but we want to
// offer snappy responses to a few likely player actions.
tryRead: function () {
WritingDemo.print(`In Soviet Russia, books read you! `);
// return false ends the turn without further processing
return false;
},
tryTake: function () {
WritingDemo.print(`In Soviet Russia, books take you! `);
// return false ends the turn without further processing
return false;
},
}); // dusty books
WritingDemo.createAsset({
class: "CustomPaper",
name: "onionskin paper",
// indefinite articles are handled automatically,
// but they can be set manually
indefinite_article: "a sheet of",
synonyms: ["sheet", "sheet of onionskin paper"],
description: "It's a sheet of onionskin paper. ",
place: { on: "rolltop desk" },
});
WritingDemo.createAsset({
class: "Typewriter",
name: "typewriter",
adjectives: ["spindly", "old", "mechanical"],
place: { on: "rolltop desk" },
description: `It's a spindly old mechanical typewriter. `,
// By default, instances of Typewriter can be carried
// as inventory but we don't want this one to be moved
// so we're going to unset these verb subscriptions.
dov: {
take: false,
put: false,
get: false,
give: false,
move: false,
},
// Here, we want to check if there is a piece of paper
// in the typewriter when player types on it.
// There are several different ways to hook into verbs,
// ranging from broad to very granular, and taking into
// account whether the asset was the direct or indirect
// object of the verb. That gets a little tricky with
// the verb type, because player may input
// "type on typewriter", "type on paper",
// "type 'Hello, World!' on paper,"
// "type 'Hello, World!' on typewriter," etc.
// All of these will work, and the typewriter may be
// direct or indirect, depending on how the input was
// structured. So we're going to use a broad hook:
// doType is called any time the verb type is used on
// the typewriter, regardless of direct / indirect,
// and we're going to check if the typewriter has paper in it.
// See https://adventurejs.com/doc/Scripting_VerbHooks.html
// for more info on verb hooks.
doType: function () {
if (this.hasContents("in")) {
// Paper is the only class that can be put in Typewriter
// so if it's not empty, it's got a piece of paper in it
// and we can confidently refer to paper in our appended
// output.
WritingDemo.appendOutput(`Now try reading the paper. `);
WritingDemo.scorecard.awardPoint("type on paper");
} else {
// The typewriter is empty so let's append the default
// verb message to help inform the player.
WritingDemo.appendOutput(
`{We} might try putting a piece of paper in it. `
);
}
},
});
WritingDemo.createAsset({
class: "Entity",
name: "small placard",
place: { on: "rolltop desk" },
// See how this placard description uses custom HTML/CSS.
// We defined the CSS for this style inside the Styles.css
// file that loads with this game. You can load CSS
// via the html link tag, or embed it in a style tag
// in the HTML page that loads your game.
descriptions: {
look: `{We} see a neat typewritten note.
<span class="placard">To use the typewriter, <br/>
insert a sheet of paper, use the verb type, <br/>
and put quotes around the string to be typed. <br/><br/>
type "hello world"
</span> `,
// We want to return the same description whether
// player looks at the placard or reads it, and we
// don't want to duplicate that code, so we set
// placard.descriptions.read to point to
// placard.descriptions.look
read: function () {
return this.descriptions.look;
},
},
dov: { read: true },
});
// Scorecard.js
// ----------
/*global AdventureJS WritingDemo*/
// Scoring
WritingDemo.scorecard.set({
// This is how you set score events for your game.
// You can add as few or as many as you like,
// and set points to whatever number you like.
// The names are up to you, so set them however you like.
// See http://adventurejs.com/doc/GoalsScoresHints_Scorecards.html
// for more info.
overview: "",
noscore: "",
points: {
"write on whiteboard": 1,
"erase whiteboard": 1,
"write on blackboard": 1,
"erase blackboard": 1,
"type on paper": 1,
"write on paper": 1,
"erase paper": 1,
// You can also assign "bonus" points. These won't be
// counted in the total, allowing player to earn a
// score like 110/100.
"try to climb shelves": {
value: 1,
bonus: true,
// Customize the score message by setting message
// to a string or array or function.
award_text: "[ ** {We} got a bonus point! ** ]",
complete_text: "{We} tried to climb the library shelves. ",
awarded: false,
},
"write with green pen": {
value: 1,
bonus: true,
// Customize the score message by setting message
// to a string or array or function.
award_text: "[ ** {We} got a bonus point for getting the cap off! ** ]",
awarded: false,
},
},
});
Demo Source files
Right-click and choose "Save as..." to download source files.
Notes:
- Demo games are set to a small size to fit doc pages. They can easily be enlarged via display settings.
- Demo games all use the same theme. Colors and fonts can be changed via custom CSS.
- Demo games don't include the core AdventureJS code. To run downloaded games locally, you'll need to also download copies of the core JS and CSS and set up this local folder structure.
AdventureJS └── js | └── adventure.js └── css | └── adventurejs.css └── games ├── demogame01 ├── demogame02 └── demogame03
type verb logic
Verb logic falls into a few recognizable patterns. Direction verbs tend to be simple and redirect to tryTravel(). Manipulation verbs test whether one asset is allowed to interact with another asset. Locomotion verbs test the player's current ability to move in a specified way. Many verbs are similar, but no two verbs are identical. Each verb has its quirks. If you would like to learn more about general verb logic, we recommend you see the Verb Anatomy and Verb Process pages. Verb phases and verb actions / reactions offer various hooks to customize verb behavior. If you find that you want still more flexibility, you may want to investigate the modifyVerb method, which lets you replace entire blocks of verb code. You can also write verbs from scratch if you're so inclined. See Modify Verbs for a complete list of verb modification methods.
The following sections provide information that is specific to the verb type, though they include many features which are common to most verbs.
- Verb Demo
- Verb Subscriptions enable
typeto act on specific assets, and provide a collection of properties for customizing those interactions. - Sentence Structures help filter player input by defining what sentence structures
typecan handle. - Verb Phrases describe the direct and indirect objects that
typecan handle. - Verb Phase Hooks offer a broad method for authors to hook into default logic and override it with custom code.
- Verb Action Hooks offer a surgical method for authors to hook into
type's default logic and inject custom code. - Verb Reaction Hooks are like verb actions, but occur as secondary effects of successfully applying
type. - Verb Params contain properties that are distinct to
type. Not all verbs have params. - Verb Methods lists the methods that
typeinherits from the Verb class. - Verb Properties lists the properties that
typeinherits from the Verb class.
type subscriptions
An asset must be subscribed to a verb for that verb to act upon that asset (with some exceptions). Though verbs are universal, each asset's verb subscriptions are distinct objects that can be used to customize how a given verb interacts with a given asset. To say it another way, a verb subscription is a collection of properties that defines how a verb should be applied to an asset; which allow authors to override a verb's default behaviors on a per-asset basis.
It's important to note that verb subscriptions need to be declared as direct or indirect, depending on whether the asset will be used as a direct object or indirect object. In the case of "unlock lock with key", the lock is the direct object and the key is the indirect object, and each asset needs to be subscribed to unlock in the appropriate way. (It's allowed, and a common pattern, to subscribe assets directly and indirectly to the same verb.)
Expand for example
MyGame.createAsset({
class: "Lock",
name: "lock",
dov: { unlock: true },
});
MyGame.createAsset({
class: "Key",
name: "key",
iov: { unlock: true },
});
As shown in the above example, dov: { unlock: true } is the minimum that is required to subscribe an asset to a verb. However, verb subscriptions have many properties that can be used to customize how this verb is applied to this asset. (Setting any property eliminates the need to set verb: true. ) Below is a list of verb subscription properties that authors may find useful.
-
automatically
{Boolean}
Allows for some verbs to be performed automatically if context calls for
it; for example, when unlocking a door in order to pass through it. An asset's verb subscription setting takes precedence over game settings.
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { automatically: true } }, }); -
automatically_after_use
{Boolean}
This sets it so that a verb can only be applied automatically after a
player has already used it manually. This is to prevent automatic use of
tools from breaking puzzles. For example, imagine one door with many keys
but only one that works; if choosing the right key is part of the puzzle,
this option prevents players from simply saying "unlock door" and having
the right key automatically selected for them. When setting
automatically_after_useto true you don't also have to setautomatically.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { automatically_after_use: true } }, }); -
enabled
{Boolean}
Verb subscriptions are enabled by default, but can be disabled manually.
Temporarily disabling a verb subscription can be a useful method for
controlling an asset. For example, you might disable
openfor a door that needs another action to be completed before it can be opened.Individual verb subscriptions can be enabled / disabled viaExpand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { enabled: true } }, });asset.setDOV(verbname)andasset.unsetDOV(verbname). -
on_success
{String|Array|Function}
If this property returns a string, the string will be appended to the
verb's default success message. Though a string is expected, this property
is handled by
getStringArrayFunction().
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { on_success: "You type the universal widget. " } }, }); -
on_first_success
{String|Array|Function}
If this property returns a string, the string will be appended to the
verb's default success message the first time it is applied to this asset.
Though a string is expected, this property is handled by
getStringArrayFunction().
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { on_first_success: "You type the universal widget for the first time. " } }, }); -
on_failure
{String|Array|Function}
If this property returns a string, the string will be appended to the
verb's default failure message. Though a string is expected, this property
is handled by
getStringArrayFunction().
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { on_failure: "You failed to type the universal widget. " } }, }); -
on_first_failure
{String|Array|Function}
If this property returns a string, the string will be appended to the
verb's default failure message the first time it is applied to this asset.
Though a string is expected, this property is handled by
getStringArrayFunction().
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { on_first_failure: "You failed to type the universal widget this first time. " } }, }); -
once
{Boolean}
if true, the verb can only be applied once to the asset. The verb
subscription will be disabled after use. No special message will be printed, but subsequent attempts to use the verb on this asset will explain why it can't be used again.
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { once: true } }, }); -
then_destroy
{Boolean}
If this property is true, the asset will be destroyed after the verb is
applied.
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { then_destroy: true } }, }); -
on_destroy
{String|Array|Function}
If this property returns a string, the asset will be destroyed after the
verb is applied, and the string will be appended to the verb's success
message. Though a string is expected, this property is handled by
getStringArrayFunction().
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { then_destroy: true, on_destroy: "The widget is destroyed!" } }, }); -
with_anything
{Boolean}
Pertains only to indirect objects. If true, this asset can be used as an indirect object of this verb with any direct object.
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", iov: { type: { with_anything: true } }, }); -
with_assets
{Boolean}
Use to specify particular assets that can interact with this one using the given verb. For example "unlock door with key" where the specified key is the only asset that can unlock door. This works distinctly for direct and indirect verb subscriptions. So, for instance, in "unlock door with key", the door might have a direct object subscription, while the key has an indirect object description.
Expand for example
MyGame.createAsset({ class: "Door", name: "gold door", dov: { unlock: { with_assets: [ "gold key" ] } }, }); MyGame.createAsset({ class: "Key", name: "gold key", iov: { unlock: { with_assets: [ "gold door" ] } }, }); -
with_classes
{Array}
Use to specify particular classes that can interact with this asset using the given verb. For example "unlock door with skeleton key" where any instance of the class SkeletonKey can unlock door. This works distinctly for direct and indirect verb subscriptions. So, for instance, in "unlock door with skeleton key", the door might have a direct object subscription, while the key has an indirect object description.
Expand for example
MyGame.createAsset({ class: "Door", name: "red door", dov: { unlock: { with_classes: [ "SkeletonKey" ] } }, }); MyGame.createAsset({ class: "SkeletonKey", name: "skeleton key", iov: { unlock: { with_classes: [ "Door", "Chest" ] } }, }); -
with_nothing
{Array}
Pertains only to direct objects. If true, the specified verb can be applied to the direct object without the use of any indirect object.
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { with_nothing: true } }, }); -
with_params
{Object}
Used to contain a set of parameters that are specific to this particular verb. For example, plugIn includes
with_params.max_connectionsfor setting limits on how many other assets this asset can be plugged into. See the with_params section on this page to learn more abouttype's parameters.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { with_params: { // tool is a typing implement tool: false, // target is a typing target target: false, } } }, }); -
with_prepositions
{Array}
Use to limit the prepositions that can be used with this asset. For
instance: "knock over umbrella stand" might fail with a message of "you
can't knock over the umbrella stand"; setting
umbrella_stand.dov.knock.with_prepositions = ["over"]will allow the action to succeed.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { with_prepositions: [ "through", "over" ] } }, }); -
doBeforeTry
{Function}
Verb phases provide methods to override default verb behaviors. See the verb phases section on this page to learn more about
type's verb phases.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { doBeforeTry: function () { console.log("type.doBeforeTry"); }, } }, }); -
doAfterTry
{Function}
Verb phases provide methods to override default verb behaviors. See the verb phases section on this page to learn more about
type's verb phases.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { doAfterTry: function () { console.log("type.doAfterTry"); }, } }, }); -
doBeforeSuccess
{Function}
Verb phases provide methods to override default verb behaviors. See the verb phases section on this page to learn more about
type's verb phases.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { doBeforeSuccess: function () { console.log("type.doBeforeSuccess"); }, } }, }); -
doAfterSuccess
{Function}
Verb phases provide methods to override default verb behaviors. See the verb phases section on this page to learn more about
type's verb phases.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { type: { doAfterSuccess: function () { console.log("type.doAfterSuccess"); }, } }, });
Notes
- To learn more about working with verb subscriptions, see Verb Subscriptions.
- These are most, but not all, of the properties of a verb subscription. For full reference, see the VerbSubscription class.
type sentence structures
accepts_structures: [
"verb noun",
"verb preposition noun",
"verb noun preposition noun",
"verb preposition noun preposition noun",
"verb noun preposition noun preposition noun"
]
The parser uses multiple filtering methods to try to channel player input into useable tokens. Sentence structures are defined for each verb in order to narrow down the input that the verb can handle. For example, the verb "hit" might accept "verb noun" as in "hit troll", or "verb noun preposition noun" as in "hit troll with sword", whereas an intransitive verb like "jump" might accept "verb" as a complete sentence. Input that isn't accepted will return a warning to the player.
A note about adverbs: though the parser does handle some adverbs, such as "carefully examine tiara" and "turn left", it excludes them from consideration in sentence structures. Due to the slipperyness of the English language, an adverb can appear in multiple positions in a sentence while still describing the same verb, which presents enough possible word combinations to make sentence structures less useful as a filtering tool. Instead, the parser puts adverbs aside and handles them separately.
Notes
- It is possible for authors to modify a verb's structures through the use of modifyVerb.
- To learn more about modifying verbs, see Modify Verbs.
type phrases
phrase1:
{
accepts_noun: true,
requires_noun: true,
noun_must_be:
{
known: true,
present_if_tangible: true,
reachable_if_tangible: true,
},
accepts_preposition: true,
preposition_must_be: ["on", "with"],
},phrase2:
{
accepts_noun: true,
requires_noun: true,
noun_must_be:
{
known: true,
present_if_tangible: true,
reachable_if_tangible: true,
},
accepts_preposition: true,
requires_preposition: true,
preposition_must_be: ["on", "with"],
},phrase3:
{
accepts_noun: true,
requires_noun: true,
noun_must_be:
{
known: true,
present_if_tangible: true,
reachable_if_tangible: true,
},
accepts_preposition: true,
requires_preposition: true,
preposition_must_be: ["on", "with"],
},
The AdventureJS parser uses multiple filtering methods to try to interpret player input. A verb's phrases may consist of a noun and/or a preposition. Whether any noun is defined as a direct or indirect object is up to that verb's unique logic. Each verb defines a unique set of phrases depending on what its logic can handle. Verbs may handle zero, one, two, or three nouns. The nested noun_must_be object sets conditional qualifiers to help narrow down assets that the verb might act upon. Input that isn't accepted will return a warning to the player.
Notes
- It is possible for authors to modify a verb's phrases through the use of modifyVerb.
- To see a list of properties that can be set for phrases, see the Phrase class.
- To see a list of properties that can be set for phrase.noun_must_be, see the NounMustBe class.
- To learn more about modifying verbs, see Modify Verbs.
type phase hooks
Verb phase hooks let authors override verb subscriptions for specific assets when type is applied to them. This is a broad method for customizing verb/noun interactions on a per-asset basis. For example, an author might supply completely different logic for "throw feather" vs "throw baseball" vs "throw anvil".
When type.do() is called, it attempts to run a sequence of methods, or phases, as listed below. The four hooks have no default logic of their own but provide methods to inject custom code at any point in the life cycle of the verb action. See below for examples of how to use verb phases for type.
do
doBeforeTry hook
MyGame.createAsset({
class: "Entity",
name: "This Asset",
dov: {
type: {
doBeforeTry: function( params )
{
let msg = `You're about to try to type ${this.article_name}. `;
this.game.print(msg);
return;
},
},
},
});
doTry handles logic to determine if type can be applied
doAfterTry hook
MyGame.createAsset({
class: "Entity",
name: "This Asset",
dov: {
type: {
doAfterTry: function( params )
{
let msg = `You just tried to type ${this.article_name}! `;
this.game.print(msg);
return;
},
},
},
});
doBeforeSuccess hook
MyGame.createAsset({
class: "Entity",
name: "This Asset",
dov: {
type: {
doBeforeSuccess: function( params )
{
let msg = `You're about to succeed in performing type on ${this.article_name}. `;
this.game.print(msg);
return;
},
},
},
});
doSuccess handles state changes and printing messages
doAfterSuccess hook
MyGame.createAsset({
class: "Entity",
name: "This Asset",
dov: {
type: {
doAfterSuccess: function( params )
{
let msg = `You succeeded in performing type on ${this.article_name}. `;
this.game.print(msg);
return;
},
},
},
});
Expand for example
Assets must have separate direct and indirect verb subscriptions. Consider this singing sword, which is directly subscribed to the verb "take". We want our game to print a custom message when the player tries to take the sword, and a different message when the player succeeds in taking it.
MyGame.createAsset({
class: "Sword",
name: "singing sword",
dov: {
take:
{
doAfterTry: function()
{
let msg = "The sword begins to vibrate as your hand curls around its haft. ";
MyGame.print( msg );
},
doAfterSuccess: function()
{
let msg = "The sword bursts into song in your hand. ";
MyGame.print( msg );
},
},
},
});
Now consider this stone, which is indirectly subscribed to "remove". We want to print messages when the sword is removed from it, so we'll hook into the stone's indirect object subscription. We could put this code on either object. A case like this comes down to author's choice.
MyGame.createAsset({
class: "Entity",
name: "stone",
iov: {
remove:
{
doBeforeTry: function()
{
let msg = "Will the stone judge you worthy enough to remove the sword? "
MyGame.print( msg );
},
doAfterSuccess: function()
{
let msg = "With the sword removed, the stone bursts into rubble! ";
MyGame.print( msg );
MyGame.destroyAsset(this);
},
},
},
});
Notes
- To learn more, see verb phase hooks.
- Verb phase hooks are similar to, but distinct from, verb action hooks and verb reaction hooks, which offer more surgical hooks.
type action hooks
Every asset referred to in the turn's input is checked for verb action hooks. These hooks allow authors to inject custom code or print custom text during verb operations. There are two distinct approaches to defining verb actions, designed to accommodate different levels of scripting experience. Authors may use whichever approach they find most comfortable. For more details, see Action Hooks.
-
Simple approach: Define string properties such as
asset.do_type. If AdventureJS finds a string, it prints it instead of the default output for that turn. This option is best for authors who want to customize output without writing code. -
Advanced approach: Define method properties such as
asset.doType(). If a method is found, it is called with a parameter object containing any relevant assets from the input (e.g.,asset.doType({asset1,asset2})). The author may use or ignore these parameters. This approach offers complete control over the turn’s outcome: authors can add conditional logic, force success or failure, or revise the default output.
Expand any item to see code examples. Methods are called with a parameter object in the form of action({asset1, asset2, params}) which authors may use or ignore.
tryTypeThis
Called on This asset in a phrase such as "type this". Since no indirect object is given, we treat the player character as an indirect object.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of which player character uses the verb.
MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeThis: function () { let msg = "Found custom method at thing_one.tryTypeThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
tryTypeThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeThis: { "Player Two": function () { let msg = "Found custom method at thing_one.tryTypeThis['Player Two']()"; MyGame.print(msg); }, }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this particular verb action, asset1 is the player character, because we've treated it as the indirect object in absence of a player specified object.
MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeThis: function ({asset1}) { switch (asset1.name) { case "Player Two": let msg = "Found custom method at thing_one.tryTypeThis('Player Two')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
doTypeThis
Called on This asset in a phrase such as "type this".
Since no indirect object is given, we treat the player character as an indirect object.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of which player character uses the verb.
MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeThis: function () { let msg = "Found custom method at thing_one.doTypeThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
doTypeThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeThis: { "Player Two": function () { let msg = "Found custom method at thing_one.doTypeThis['Player Two']()"; MyGame.print(msg); }, }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this particular verb action, asset1 is the player character, because we've treated it as the indirect object in absence of a player specified object.
MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeThis: function ({asset1}) { switch (asset1.name) { case "Player Two": let msg = "Found custom method at thing_one.doTypeThis('Player Two')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
tryTypePrepositionThis
Called on This asset in a phrase such as "type on this". Since no indirect object is given, we treat the player character as an indirect object. This example uses "with" as the preposition, but any preposition can set a unique response.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of which player character uses the verb.
MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeWithThis: function () { let msg = "Found custom method at thing_one.tryTypeWithThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
tryTypePrepositionThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeWithThis: { "Player Two": function () { let msg = "Found custom method at thing_one.tryTypeWithThis['Player Two']()"; MyGame.print(msg); }, }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this particular verb action, asset1 is the player character, because we've treated it as the indirect object in absence of a player specified object.
MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeWithThis: function ({asset1}) { switch (asset1.name) { case "Player Two": let msg = "Found custom method at thing_one.tryTypeWithThis('Player Two')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
doTypePrepositionThis
Called on This asset in a phrase such as "type on this". Since no indirect object is given, we treat the player character as an indirect object. This example uses "with" as the preposition, but any preposition can set a unique response.
Note that sentence structures are commonly mutated during the doTry verb phase, so try and do may act on different sentence structures.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of which player character uses the verb.
MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeWithThis: function () { let msg = "Found custom method at thing_one.doTypeWithThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
doTypePrepositionThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeWithThis: { "Player Two": function () { let msg = "Found custom method at thing_one.doTypeWithThis['Player Two']()"; MyGame.print(msg); }, }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this particular verb action, asset1 is the player character, because we've treated it as the indirect object in absence of a player specified object.
MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeWithThis: function ({asset1}) { switch (asset1.name) { case "Player Two": let msg = "Found custom method at thing_one.doTypeWithThis('Player Two')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
tryTypeThisPrepositionThat
Called on This asset in a phrase such as "type this with that", where This is the direct object and That is the indirect object.
tryTypeThisPrepositionThat mirrors tryTypeThatPrepositionThis. One is called on a direct object; the other on an indirect object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "with" as the preposition, but any preposition can set a unique response.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeThisWithThat: function () { let msg = "Found custom method at thing_one.tryTypeThisWithThat()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
tryTypeThisPrepositionThatfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeThisWithThat: { "Thing Two": function (params) { let msg = "Found custom method at thing_one.tryTypeThisWithThat['Second Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeThisWithThat: function ({asset1}) { switch (asset1.name) { case "Thing Two": let msg = "Found custom method at thing_one.tryTypeThisWithThat('Second Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
doTypeThisPrepositionThat
Called on This asset in a phrase such as "type this with that", where This is the direct object and That is the indirect object.
doTypeThisPrepositionThat mirrors doTypeThatPrepositionThis. One is called on a direct object; the other on an indirect object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "with" as the preposition, but any preposition can set a unique response.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeThisWithThat: function () { let msg = "Found custom method at thing_one.doTypeThisWithThat()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
doTypeThisPrepositionThatfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeThisWithThat: { "Thing Two": function (params) { let msg = "Found custom method at thing_one.doTypeThisWithThat['Second Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeThisWithThat: function ({asset1}) { switch (asset1.name) { case "Thing Two": let msg = "Found custom method at thing_one.doTypeThisWithThat('Second Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
tryTypeThatPrepositionThis
Called on That asset in a phrase such as "type this with that", where That is the indirect object and This is the direct object.
tryTypeThatPrepositionThis mirrors tryTypeThisPrepositionThat. One is called on an indirect object; the other on a direct object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "with" as the preposition, but any preposition can set a unique response.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing Two", tryTypeThatWithThis: function () { let msg = "Found custom method at thing_two.tryTypeThatWithThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
tryTypeThatPrepositionThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing Two", tryTypeThatWithThis: { "Thing One": function (params) { let msg = "Found custom method at thing_two.tryTypeThatWithThis['First Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing Two", tryTypeThatWithThis: function ({asset1}) { switch (asset1.name) { case "Thing One": let msg = "Found custom method at thing_two.tryTypeThatWithThis('First Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
doTypeThatPrepositionThis
Called on That asset in a phrase such as "type this with that", where That is the indirect object and This is the direct object.
doTypeThatPrepositionThis mirrors doTypeThisPrepositionThat. One is called on an indirect object; the other on a direct object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "with" as the preposition, but any preposition can set a unique response.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing Two", doTypeThatWithThis: function () { let msg = "Found custom method at thing_two.doTypeThatWithThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
doTypeThatPrepositionThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing Two", doTypeThatWithThis: { "Thing One": function (params) { let msg = "Found custom method at thing_two.doTypeThatWithThis['First Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing Two", doTypeThatWithThis: function ({asset1}) { switch (asset1.name) { case "Thing One": let msg = "Found custom method at thing_two.doTypeThatWithThis('First Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
tryTypePrepositionThisPrepositionThat
Called on This asset in a phrase such as "type from this to that", where This is the direct object and That is the indirect object.
tryTypePrepositionThisPrepositionThat mirrors tryTypePrepositionThatPrepositionThis. One is called on a direct object; the other on an indirect object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "from" and "to" as the prepositions, but any prepositions can set unique responses.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeFromThisToThat: function () { let msg = "Found custom method at thing_one.tryTypeFromThisToThat()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
tryTypePrepositionThisPrepositionThatfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeFromThisToThat: { "Thing Two": function (params) { let msg = "Found custom method at thing_one.tryTypeFromThisToThat['Second Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeFromThisToThat: function ({asset1}) { switch (asset1.name) { case "Thing Two": let msg = "Found custom method at thing_one.tryTypeFromThisToThat('Second Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
doTypePrepositionThisPrepositionThat
Called on This asset in a phrase such as "type from this to that", where This is the direct object and That is the indirect object.
doTypePrepositionThisPrepositionThat mirrors doTypePrepositionThatPrepositionThis. One is called on a direct object; the other on an indirect object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "from" and "to" as the prepositions, but any prepositions can set unique responses.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeFromThisToThat: function () { let msg = "Found custom method at thing_one.doTypeFromThisToThat()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
doTypePrepositionThisPrepositionThatfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeFromThisToThat: { "Thing Two": function (params) { let msg = "Found custom method at thing_one.doTypeFromThisToThat['Second Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeFromThisToThat: function ({asset1}) { switch (asset1.name) { case "Thing Two": let msg = "Found custom method at thing_one.doTypeFromThisToThat('Second Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
tryTypePrepositionThatPrepositionThis
Called on That asset in a phrase such as "type from this to that", where This is the direct object and That is the indirect object.
tryTypePrepositionThatPrepositionThis mirrors tryTypePrepositionThisPrepositionThat. One is called on an indirect object; the other on a direct object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "to" and "from" as the prepositions, but any prepositions can set unique responses.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing Two", tryTypeToThatFromThis: function () { let msg = "Found custom method at thing_two.tryTypeToThatFromThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
tryTypePrepositionThatPrepositionThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing Two", tryTypeToThatFromThis: { "Thing One": function (params) { let msg = "Found custom method at thing_two.tryTypeToThatFromThis['First Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing Two", tryTypeToThatFromThis: function ({asset1}) { switch (asset1.name) { case "Thing One": let msg = "Found custom method at thing_two.tryTypeToThatFromThis('First Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
doTypePrepositionThatPrepositionThis
Called on That asset in a phrase such as "type from this to that", where This is the direct object and That is the indirect object.
doTypePrepositionThatPrepositionThis mirrors doTypePrepositionThisPrepositionThat. One is called on an indirect object; the other on a direct object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "to" and "from" as the prepositions, but any prepositions can set unique responses.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing Two", doTypeToThatFromThis: function () { let msg = "Found custom method at thing_two.doTypeToThatFromThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
doTypePrepositionThatPrepositionThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing Two", doTypeToThatFromThis: { "Thing One": function (params) { let msg = "Found custom method at thing_two.doTypeToThatFromThis['First Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing Two", doTypeToThatFromThis: function ({asset1}) { switch (asset1.name) { case "Thing One": let msg = "Found custom method at thing_two.doTypeToThatFromThis('First Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
tryTypeThisPrepositionThatPrepositionOther
Called on This asset in a phrase such as "type this to that with other", where This is the direct object, That is the indirect object, and Other is assumed to be a second indirect object (likely a tool).
tryTypeThisPrepositionThatPrepositionOther mirrors tryTypePrepositionThatThisPrepositionOther. One is called on a direct object; the other on an indirect object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "to" and "with" as the prepositions, but any prepositions can set unique responses.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeThisToThatWithOther: function () { let msg = "Found custom method at thing_one.tryTypeThisToThatWithOther()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
tryTypeThisPrepositionThatPrepositionOtherfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.
This nested key / value approach can be extended to handle theMyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeThisToThatWithOther: { "Thing Two": function (params) { let msg = "Found custom method at thing_one.tryTypeThisToThatWithOther['Second Thing']()"; MyGame.print(msg); } }, });Otherasset.MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeThisToThatWithOther: { "Thing Two": { "Thing Three": function (params) { let msg = "Found custom method at thing_one.tryTypeThisToThatWithOther['Second Thing']['Third Thing']()"; MyGame.print(msg); } } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
This logic can be extended to handle theMyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeThisToThatWithOther: function ({asset1}) { switch (asset1.name) { case "Thing Two": let msg = "Found custom method at thing_one.tryTypeThisToThatWithOther('Second Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });Otherasset.MyGame.createAsset({ class: "Entity", name: "Thing One", tryTypeThisToThatWithOther: function ({asset1, asset2}) { switch (asset1.name) { case "Thing Two": if(asset2.name === "Thing Three"){ let msg = "Found custom method at thing_one.tryTypeThisToThatWithOther('Second Thing', 'Third Thing')"; MyGame.print(msg); } else return; break; default: // do nothing and allow the default result break; } return; }, });
doTypeThisPrepositionThatPrepositionOther
Called on This asset in a phrase such as "type this to that with other", where This is the direct object, That is the indirect object, and Other is assumed to be a second indirect object (likely a tool).
doTypeThisPrepositionThatPrepositionOther mirrors doTypePrepositionThatThisPrepositionOther. One is called on a direct object; the other on an indirect object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "to" and "with" as the prepositions, but any prepositions can set unique responses.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeThisToThatWithOther: function () { let msg = "Found custom method at thing_one.doTypeThisToThatWithOther()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
doTypeThisPrepositionThatPrepositionOtherfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.
This nested key / value approach can be extended to handle theMyGame.createAsset({ class: "Entity", name: "Thing One", doTypeThisToThatWithOther: { "Thing Two": function (params) { let msg = "Found custom method at thing_one.doTypeThisToThatWithOther['Second Thing']()"; MyGame.print(msg); } }, });Otherasset.MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeThisToThatWithOther: { "Thing Two": { "Thing Three": function (params) { let msg = "Found custom method at thing_one.doTypeThisToThatWithOther['Second Thing']['Third Thing']()"; MyGame.print(msg); } } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
This logic can be extended to handle theMyGame.createAsset({ class: "Entity", name: "Thing One", doTypeThisToThatWithOther: function ({asset1}) { switch (asset1.name) { case "Thing Two": let msg = "Found custom method at thing_one.doTypeThisToThatWithOther('Second Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });Otherasset.MyGame.createAsset({ class: "Entity", name: "Thing One", doTypeThisToThatWithOther: function ({asset1, asset2}) { switch (asset1.name) { case "Thing Two": if(asset2.name === "Thing Three"){ let msg = "Found custom method at thing_one.doTypeThisToThatWithOther('Second Thing', 'Third Thing')"; MyGame.print(msg); } else return; break; default: // do nothing and allow the default result break; } return; }, });
tryTypePrepositionThatThisPrepositionOther
Called on That asset in a phrase such as "type this to that with other", where This is the direct object, That is the indirect object, and Other is assumed to be a second indirect object (likely a tool).
tryTypePrepositionThatThisPrepositionOther mirrors tryTypeThisPrepositionThatPrepositionOther. One is called on an indirect object; the other on a direct object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "to" and "with" as the prepositions, but any prepositions can set unique responses.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thisasset is.MyGame.createAsset({ class: "Entity", name: "Thing Two", tryTypeToThatThisWithOther: function () { let msg = "Found custom method at thing_two.tryTypeToThatThisWithOther()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
tryTypePrepositionThatThisPrepositionOtherfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.
This nested key / value approach can be extended to handle theMyGame.createAsset({ class: "Entity", name: "Thing Two", tryTypeToThatThisWithOther: { "Thing One": function (params) { let msg = "Found custom method at thing_two.tryTypeToThatThisWithOther['First Thing']()"; MyGame.print(msg); } }, });Otherasset.MyGame.createAsset({ class: "Entity", name: "Thing Two", tryTypeToThatThisWithOther: { "Thing One": { "Thing Three": function (params) { let msg = "Found custom method at thing_two.tryTypeToThatThisWithOther['First Thing']['Third Thing']()"; MyGame.print(msg); } } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
This logic can be extended to handle theMyGame.createAsset({ class: "Entity", name: "Thing Two", tryTypeToThatThisWithOther: function ({asset1}) { switch (asset1.name) { case "Thing One": let msg = "Found custom method at thing_two.tryTypeToThatThisWithOther('First Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });Otherasset.MyGame.createAsset({ class: "Entity", name: "Thing Two", tryTypeToThatThisWithOther: function ({asset1, asset2}) { switch (asset1.name) { case "Thing One": if(asset2.name === "Thing Three"){ let msg = "Found custom method at thing_two.tryTypeToThatThisWithOther('First Thing', 'Third Thing')"; MyGame.print(msg); } else return; break; default: // do nothing and allow the default result break; } return; }, });
doTypePrepositionThatThisPrepositionOther
Called on That asset in a phrase such as "type this to that with other", where This is the direct object, That is the indirect object, and Other is assumed to be a second indirect object (likely a tool).
doTypePrepositionThatThisPrepositionOther mirrors doTypeThisPrepositionThatPrepositionOther. One is called on an indirect object; the other on a direct object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "to" and "with" as the prepositions, but any prepositions can set unique responses.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thisasset is.MyGame.createAsset({ class: "Entity", name: "Thing Two", doTypeToThatThisWithOther: function () { let msg = "Found custom method at thing_two.doTypeToThatThisWithOther()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
doTypePrepositionThatThisPrepositionOtherfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.
This nested key / value approach can be extended to handle theMyGame.createAsset({ class: "Entity", name: "Thing Two", doTypeToThatThisWithOther: { "Thing One": function (params) { let msg = "Found custom method at thing_two.doTypeToThatThisWithOther['First Thing']()"; MyGame.print(msg); } }, });Otherasset.MyGame.createAsset({ class: "Entity", name: "Thing Two", doTypeToThatThisWithOther: { "Thing One": { "Thing Three": function (params) { let msg = "Found custom method at thing_two.doTypeToThatThisWithOther['First Thing']['Third Thing']()"; MyGame.print(msg); } } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
This logic can be extended to handle theMyGame.createAsset({ class: "Entity", name: "Thing Two", doTypeToThatThisWithOther: function ({asset1}) { switch (asset1.name) { case "Thing One": let msg = "Found custom method at thing_two.doTypeToThatThisWithOther('First Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });Otherasset.MyGame.createAsset({ class: "Entity", name: "Thing Two", doTypeToThatThisWithOther: function ({asset1, asset2}) { switch (asset1.name) { case "Thing One": if(asset2.name === "Thing Three"){ let msg = "Found custom method at thing_two.doTypeToThatThisWithOther('First Thing', 'Third Thing')"; MyGame.print(msg); } else return; break; default: // do nothing and allow the default result break; } return; }, });
Notes
- Verb action hooks are specific to their particular verb.
- Which verb action hooks are called depends on the structure of the player's input. Hooks are checked for every asset in the input, including the player character. Which hooks are called depends on the sentence structure of the player's input:
-
Single-object input (e.g., "type this"): The hook is called on
Thisasset. Since no indirect object is specified, the player character is treated as an indirect object. -
Multiple-object input (e.g., "type this with that"): The hook is called depending on the object’s role in the phrase.
doThisPrepositionThatruns onThisdirect object, whiledoThatPrepositionThisruns onThatindirect object. These are equivalent, and you may place code on whichever asset makes sense to you. Any preposition can be used to define a unique response, for exampletype withvstype on. -
Sentence structures are commonly mutated during the doTry verb phase, so
tryanddomay act on different sentence structures. -
Verb actions are extremely granular and depend on specific combinations of assets and prepositions. Verb actions are called during a verb's doTry and doSuccess phases, which lets them override a verb's operations. Use them if you want to customize output for specific inputs, but beware of that granularity. Consider
doTake(): it's called when a player takes an asset, so you might want to hook into that; but many other verbs may also move the asset into the player. If you want to catch any method that moves an asset into the player, you may find thedoMoveThisToThatverb reaction more broadly applicable. - By default, string properties override a turn's output, but they can also be set to append or prepend the turn's default output. See verb action hooks for more information.
- Verb reaction hooks are functionally the same as action hooks. The only difference is that reaction hooks are not specific to any verb.
- Verb phase hooks are a different form of hook that allows authors to override entire verb phases.
type reaction hooks
Every asset affected by the turn is checked for verb reaction hooks. These hooks allow authors to inject custom code or print custom text during verb operations. Verb reactions are subject to String Array Function, which means they can be set to any of those three types. Authors may use whichever they find most comfortable. See verb reaction hooks for details.
- String: If AdventureJS finds a string, it prints it instead of the default output for that turn. This option is best for authors who want to customize output without writing code.
- Array: If AdventureJS finds an array, it will print an item from the array, using randomization or not according to global settings.
-
Functions: Set a function like
asset.doMoveThisToThat(). If a function is found, it is called with a parameter object containing any relevant assets from the input (e.g.,asset.doMoveThisToThat({asset1})). The author may use or ignore these parameters. This approach offers complete control over the turn’s outcome: authors can add conditional logic, force success or failure, or revise the default output.
Expand any item to see code examples. All methods are called with a parameter object in the form of asset.reaction({asset1, asset2, params}) which authors may use or ignore.
No verb reactions listed for type
Notes
- See verb reaction hooks for more details.
- Reaction hooks aren't specific to any particular verb.
-
Verb reactions fire at the end of a turn after the verb's doSuccess phase. Many verbs may call the same reactions. For instance, any verb that moves an asset into the player calls
doMoveThisToThat. This makes them more broadly applicable than verb actions and lets you customize the turn's output regardless of what verb is used. - Verb action hooks work the same way as reaction hooks, but are specific to their particular verb.
- Verb phase hooks are a different form of hook that allows authors to override entire verb phases.