Gamefic

Adventure Games and Interactive Fiction

Scripts

Scripts are blocks of code that define game rules, such as introductory scenes and commands that players can perform.

Script Methods

Scripts provide a domain specific language that allows authors to create entities, define commands, and create custom scenes. Here’s a quick rundown of the methods available in the DSL.

respond(verb, *arguments, &proc)

Create a command response. The proc gets executed when a command matches the response’s verb and arguments.

Simple example:

Mygame::Plot.script do
  respond :think do |actor|
    actor.tell 'You ponder your predicament.'
  end
end

Example with an argument:

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

Example of a custom response that targets a specific entity:

Mygame::Plot.seed { @ball = make Item, name: 'soccer ball' }

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

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

meta(verb, *arguments, &proc)

Create a meta command response. A meta response is simply a response that’s flagged as meta (Response#meta?) to indicate that they provide a feature that is not considered an in-game action, such as displaying help documentation or a scoreboard.

before_action(verb = nil, &proc)

Create a proc to be evaluated before a character executes an action. When a verb is specified, the proc will only be evaluated if the action’s verb matches it.

Mygame::Plot.script do
  before_action :look do |action|
    action.cancel
    action.actor.tell "You would look at #{action.arguments.first} now, but the action got cancelled."
  end
end

interpret(command, translation)

Define a syntax to be translated into another command. Parameters are prefixed with a colon(:).

Mygame::Plot.script do
  interpret 'ponder', 'think' # When the user enters "ponder," it gets converted to the "think" command

  interpret 'scrutinize :thing', 'look :thing' # "scrutizine something" => "look something"
end

verbs

Get a list of all the verbs defined via respond and meta.

synonyms

Get a list of all verbs and synonyms.

This differs from verbs in that it will include verbs that get interpreted as other verbs. For example, gamefic-standard defines a take action and interprets get and carry as synonyms of take. The verbs array will include take, and the synonyms array will include take, get, and carry.

syntaxes

Get a list of all syntaxes.

anywhere(*args, ambiguous: false)

Create a response query that searches for entities anywhere in the game.

Mygame::Plot.script do
  @object = make Thing, name: 'object'

  respond :find, anywhere(Thing) do |actor, thing|
    actor.tell "There's something called #{a thing} somewhere in the game, but not necessarily in your vicinity."
  end
end

available(*args, ambiguous: false)

Create a response query that searches for entities that are currently available to the actor. An entity is considered available if it shares the actor’s parent or is a child of an accessible child or sibling.

Mygame::Plot.script do
  respond :kick, available(Thing) do |actor, thing|
    # ...
  end

  respond :kick, Thing do |actor, thing| # shortcut to `available(Thing)`
    # ...
  end
end

parent(*args, ambiguous: false)

Create a response query that checks the command’s argument against the actor’s parent.

Mygame::Plot.script do
  @auditorium = make Room, name: 'auditorium'

  respond :verify, parent(@auditorium) do |actor, room|
    # Players will see this message in response to "verify auditorium" if the
    # auditorium is their current parent.
    actor.tell "Yes, you're in #{the @auditorium}."
  end
end

children(*args, ambiguous: false)

Create a response query that checks the command’s argument against the actor’s children

Mygame::Plot.script do
  respond :use, children(Thing) do |actor, thing|
    actor.tell "You're allowed to use #{the thing} because it's in your inventory."
  end
end

siblings(*args, ambiguous: false)

Create a response query that checks the command’s argument against the actor’s siblings (e.g., entities that share the actor’s parent).

Mygame::Plot.script do
  respond :use, siblings(Thing) do |actor, thing|
    actor.tell "You're allowed to use #{the thing} because it's in ths same room with you."
  end
end

myself(*args, ambiguous: false)

Create a response query that checks the command’s argument against the actor itself.

Mygame::Plot.script do
  respond :kick, myself do |actor, _|
    actor.tell "You kick yourself."
  end
end

plaintext(arg = nil)

Create a response query that performs a plaintext search. The argument can be a String or a RegExp. If no argument is provided, it will match any text if finds in the command. A successful query returns the corresponding text instead of an entity.

Mygame::Plot.script do
  respond :say, plaintext do |actor, text|
    actor.tell "You say: #{text}."
  end
end

introduction(&proc)

Create an introductory scene. This scene will run when the game starts.

Mygame::Plot.script do
  @entrance = make Room, name: 'entrance'

  introduction do |actor|
    actor.parent = @entrance
    actor.tell "You start the game at #{the @entrance}."
  end
end

multiple_choice()

TODO: Documentation pending

yes_or_no()

TODO: Documentation pending

pause()

TODO: Documentation pending

conclusion(&proc)

Add a conclusion scene. Running a conclusion ends the game.

Mygame::Plot.script do
  introduction do |actor|
    actor.tell "A mystery's afoot! Enter SOLVE to solve it."
  end

  respond :solve do |actor|
    actor.cue :solved
  end

  conclusion :solved do |actor|
    actor.tell 'You solved the mystery!'
  end
end

block()

TODO: Documentation pending

scenes

Get the names of all the scenes defined in this plot, including the default scene and default conclusion.

on_ready(&proc)

Define a block of code to be executed every time a turn starts (i.e., before player input gets received).

Mygame::Plot.script do
  @turn_number = 0

  on_ready do
    @turn_number += 1
  end
end

on_player_ready(&proc)

Define a block of code to be executed for each player when a turn starts.

Mygame::Plot.script do
  @turn_number = 0

  on_ready do
    @turn_number += 1
  end

  on_player_ready do |player|
    player.tell "You're about to start turn number #{@turn_number}."
  end
end

on_update(&proc)

Define a block of code to be executed every time a turn ends (i.e., after player input has been processed.)

Mygame::Plot.script do
  on_update do
    # ...
  end
end

on_player_update(&proc)

Define a block of code to be executed for each player when a turn ends.

Mygame::Plot.script do
  on_player_update do |player|
    player.tell "You just finished a game turn and a new one is about to start."
  end
end

on_player_conclude(&proc)

Define a block of code to be executed when a player reaches a conclusion.

Mygame::Plot.script do
  on_player_conclude do |player|
    player.tell '***GAME OVER***'
  end
end

on_player_output(&proc)

Define a block of code to be executed when player output is ready to render.

Mygame::Plot.script do
  on_player_output do |actor, output|
    # Add a `:time` attribute to the output that gets sent to the game client.
    output[:time] = Time.now
  end
end

branch(klass, **config)

Start a subplot. See subplots for more information.

Next: Running your game in a web browser