List

Actions

Actions are commands that can be performed by actors. In a text adventure, player input gets parsed into commands for their characters. Examples of possible commands are GO NORTH and GET LAMP.

Scripts define actions with the respond method.

Simple Commands

The simplest command form is a single verb. Example:

Gamefic.script do
  respond :think do |actor|
    actor.tell "You ponder your predicament."
  end
end

The respond method’s block gets executed in response to the THINK command. The block’s first argument is always the character performing the action.

Action Targets

The respond method can take additional arguments that identify the action’s targets, e.g., the direct object of a command.

Gamefic.script do
  respond :kick, Thing do |actor, thing|
    actor.tell "You kick #{the thing}."
  end
end

This action allows characters to KICK any object in their direct vicinity.

Actions identify targets by comparing the command’s direct object to the entities the player can access, e.g., other items in the room, items in the character’s inventory, items in nearby open containers, etc. The component used to perform comparisons is called a Query.

There are different types of queries that actions can use. In the standard library, the default query is Available. The above example will compare the user’s input to each Thing available to the character.

Using Queries

The standard library provides a Use module for specifying which query to use for each target. The above KICK example is equivalent to specifying Use.available:

Gamefic.script do
  respond :kick, Use.available(Thing) do |actor, thing|
    actor.tell "You kick #{the thing}."
  end
end

Actions with Specific Targets

The above examples specify Thing as the target. This means the action will be triggered for any Thing the query can find. Authors can specify a specific object to make a specialized version of the action.

In this example, the plot triggers a different action in response to KICK BALL.

require 'gamefic-standard'

Gamefic.script do
  @field = make Room, name: 'field'
  @ball = make Item, name: 'ball', parent: @field
  @can = make Item, name: 'can', parent: @field

  introduction do |actor|
    actor.parent = @field
    actor.tell "You're in a field. You see a ball and a can here."
  end

  respond :kick, Thing do |actor, thing|
    actor.tell "You kick #{the thing}."
  end

  respond :kick, @ball do |actor, thing|
    actor.tell "You're playing soccer!"
  end
end

If the command’s direct object is the ball, the second action gets triggered. For any other object, the first gets triggered.

Action Orders

The response method associates an action with a verb. In the above examples, the verbs are :think and :kick.

Multiple actions can be associated with the same verb. When a player’s command gets parsed, the game identifies all the actions that potentially match based on the verb and queries. As a general rule, the most recently defined match is the one that gets executed.

In this example, the first action will never get executed because the second action overrides it:

Gamefic.script do
  respond :think do |actor|
    actor.tell "This won't happen."
  end

  respond :think do |actor|
    actor.tell "This is the first THINK action the game finds."
  end
end

Cascading through Multiple Actions with proceed

Sometimes authors want to add custom behavior for a command but still have the option to execute the previous action. The actor’s proceed method allows it to execute the previous match for the current command.

We can modify the KICK example above so the action that responds to kicking the @ball executes the previous action:

Gamefic.script do
  respond :kick, @ball do |actor, thing|
    actor.proceed
    actor.tell "You're playing soccer!"
  end
end

Result:

$ rake ruby:run

You're in a field. You see a ball and a can here.

> kick can

You kick the can.

> kick ball

You kick the ball.

You're playing soccer!

Next: Creating custom scenes