The Rez Language

Rez is a language for writing hypermedia games built using HTML/Javascript/CSS and optionally incorporating graphics, audio, and movie files.

Rez shares a little DNA with Twine which describes itself as an “open source tool for telling interactive, nonlinear stories.” Where Twine shines is in making it relatively easy for those with little development experience to get started. However as the complexity of a game increases Twine offers less and less support.

Rez was created to serve a niche of games that are too complex for Twine. In sits somewhere between Twine and Inform/TADS in terms of complexity. The Rez syntax is fairly simple and uses Javascript for event handlers and utility code. Rez has built-in support for things like NPCs, inventories, scene management, and maps. Rez features a simple but powerful layout and event system.

Rez is designed to be flexible enough to support a number of use-cases while offering a useful framework for getting started.

Outline of a Rez Game

Rez games are built from .rez source files and are composed of elements describing different parts of the game.

At the top level is the @game element that contains the game metadata and other elements that make up the game.

Creating a new game

The command

rez new <name>

Will create a new folder containing a default structure and source files ready to be customised.

Compiling your game

The command

rez compile <path/to/source.rez>

Will compile the specific source file into a game in the dist folder. It creates an index.html and assorted javascript files containing the games runtime as well as packaging any assets included in the game.

Defaults

Rez uses the Bulma CSS framework.

Rez uses Apline.js for dynamic UI support.

Rez uses Handlebars.js for dynamic templating.

Comments

Line comments are supported by placing %% in column 0.

In future the restriction that comments must start in the first column will be lifted.

Includes

Once source file may include another by using the include macro %(…), for example:

%(act_one.rez)

An included file may include other files but beware of creating a cyclic dependency. For example this code will hang the compiler.

%% file1.rez
%(file2.rez)

%% file2.rez
%(file1.rez)

Elements

Most element is specified using a common syntax:

@element <id> begin
  attr1: val1
  attr2: val2
  ...
end

For example,

@game begin
  name: "Twisty Maze Adventure"
  IFID: "D2050DE2-97A2-1ED1-4CCA-AF9D3B0DD883"
  created: "2022-08-31 22:13:43.830755Z"
  version: 10
  initial_scene: #intro_scene
  …
end

Every element has an ID (the @game element has an implicit id of game) which must be unique and follow the rules for legal Javascript identifiers.

Scripts and Styles

If you need to include custom Javascript code (outside of the in-game event handlers) or CSS styles in your game you can use the @script and @style elements respectively. These elements do not have an ID, nor do they have attibutes and are written as follows:

@script begin
  function foo() {
    // I need this function to be available to my event handlers
  }
end

@style begin
  /* https://gist.github.com/JoeyBurzynski/617fb6201335779f8424ad9528b72c41 */
  .main {
    max-width: 38rem;
    padding: 2rem;
    margin: auto;
  }
end

The content of @script and @style tags will automatically be included into the relevant parts of the generated game files.

Attributes

A Rez element is defined in terms of attributes. Some attributes are expected (and perhaps required) by the game (e.g. the content attribute of @card) while some you will define yourself and use in your event handlers and glue code.

An attribute has a name and a value. The name follows the rules for legal Javascript identifiers:

  • cannot contain spaces
  • must begin with a letter, underscore (_), or dollar sign ($)
  • can only contain letters, numbers, underscores, or dollar signs
  • are case sensitive

This means that any attribute defined on any in-game object can be referenced naturally in user Javascript code.

Note that attributes with a leading underscore are considered to be “internal” to the Rez compiler and will not appear in the generated code.

Attributes are written:

name: value

There should be no space between the end of the attribute name and the : and at least one whitespace between the : and the value.

Legal

title: #foo

Not-legal

title : #foo
title :#foo
title:#foo

Attribute Types

The following types are supported:

Boolean

The values true, false, and yes, no are recognised and can be used interchangably to represent truthy values.

Number

Positive and negative integer and floating point numbers, e.g.

12, -2.5

String

Text delimited by " useful for short strings such as descriptions. However, for passages of text it can be easier to use a Heredoc String

Heredoc Strings

Text delimited by """. These can span over multiple lines.

Attribute reference

An attribute reference is & prefix followed by the name of the attribute to be referenced.

name_gen: () => {...function returning a name...}
name: &name_gen

Element reference

An element reference consists of a # prefix followed by an element ID, e.g.

favourite_monster: #ugly_troll
initial_scene: #lost_scene

A reference is used to refer to a unique element in the game. The compiler will generates an error if the referenced element does not exist.

Dice Roll

A dice roll is specified in the form [count]d[sides][+|- modifier]. So that:

strength: d6
strength: 2d6
strength: 3d6-1
strength: d20+1

Are all legal die roll specifiers.

Keyword

A keyword is a : prefix followed by a Javascript compatible id, e.g.

:continuous
:weapon
:item

Keywords are used for constant values, for example the type of an item (e.g. :sword) or the layout mode of a scene (:continuous).

Keywords can be formed into hierarchies using the @derive pseudo-element.

Function

A function is an arrow-style Javascript function, typically used as an event handler

(game, event) => {
  if(event.target.value == "Fight") {
    game.setCurrentScene("fight");
  }
}

Most event handlers take two arguments. A reference to the game element and an ‘event object’. See the specific handler documention for details.

List

A [] bracketed list of values that can include other collections such as lists, sets, & tables

[#ugly_troll #friendly_troll]
[1 2 3 4]
[[:a 1] [:b 2] [:c 3]]

Note that lists in Rez are whitespace, not comma, separated.

Set

A #[] bracketed list of values that are constrained to be unique (according to the JS notion of equality).

#[:one :two :three]

Note that sets in Rez are whitespace, not comma, separated.

Table

A {} bracketed list of name/value pairs where the name follows the attribute naming rules and the value can include other collections such as lists, sets, and tables.

{
  hostile: true
  coordinates: [1 2]
  attrs: {
    strength: 10
    hp: 15
  }
}

Note that key/value pairs in tables are whitespace, not comma, separated.

Notes

Please note that sets, lists, and tables use whitespace as a separator between elements/pairs rather than a comma as is common in many programming languages.

So a list is written:

numbers: [1 2 3 4]

rather than:

numbers: [1, 2, 3, 4]

The latter will cause a syntax error.

Elements

Rez includes many elements that you will combine to create your game, starting with the @game element that wraps the whole thing.

All elements in a Rez source file are prefixed by @ including aliases.

A few Rez elements like @game and @zone contain other elements but most do not.

The elements available are:

The elements are:

Alias

Using @alias you can create a new element name that aliases one of the existing game elements.

Why would you want to do this? Two reasons:

  1. It’s more meaningful to refer to @sword than @item in your source
  2. An alias can supply supply default values for attributes

Example

In our Maltese Falcon game hats are a big deal and a range of hat items will be needed but we don’t want to repeat ourselves defining each one using @item so we can create an alias that specifies that a Hat is an Item and how hats are, generally, configured. Then our Hat definition just needs to supply what’s different about that hat.

@alias hat = item # begin
  type: :hat
  wearable: true
  usable: false
  bogie_would_approve: false
end

@hat wool_fedora begin
  material: :wool
  colour: :brown
  description: "A Messer brown wool fedora hat"
  bogie_would_approve: true
end

Note that, at present, it is not possible to alias an alias and an error will be generated.

Required Attributes

None

Event Handlers

None

Actor

An @actor element is used to define a character (either playable or a non-playable NPC).

Typically you would use Actors when you want to represent them in game with their own attributes, behaviours, and potentially relationships.

The Twine approach would be to write all interactions with NPCs in the form of pre-defined passages. This is possible in Rez but if you want more sophisticated handling of NPC behaviour use an Actor.

Example

@list player_names begin
  content: ["Elric" "Yrkoon" "Cymoril" "Moonglum" "Rackhir" "Smiorgan" "Yishana" "Zarozinia"]
end

@actor player begin
  name: &name_gen
  name_gen: (game, player) => {
    const list = game.getGameObject("player_names");
    return list.randomElement();
  }

  stats: {
    blood: 10
    power: 5
  }

  on_init: (game, player) => {
    // Custom initialization can go here
  }
end

Required Attributes

None

Optional Attributes

  • tags: set of keywords (#[:tag1 :tag2])
  • container: element-id #ugly_troll

Event Handlers

  • on_enter
  • on_leave
  • on_turn

Asset

An @asset element refers to a file on disk, typically an image, audio, or video file, that will be presented in game.

Rez automatically copies Asset files into the game distribution folder when the game is compiled and manages pathing so that assets can be referred to in game without worrying about filenames and paths.

By specifying an Assett Rez will copy the asset file into the game dist folder and the asset can be referenced within the game without needing to know its path.

Assets can be collected into a a Group to dynamically choose them.

Example

@asset hat_01 begin
  file: "hat_01.png"
  tags: #[:hat]
end

This defines an asset that will be copied into the game when built and which can be referred to in-game by it’s id.

Rez will ensure that all assets are available during compilation.

Assets are the key to using asset groups that can be used for showing different but randomised media.

Required Attributes

  • file: string ("hat_01.jpg")

Optional Attributes

  • tags: set of keywords (#[:tag1 :tag2 …])

Event Handlers

None

Card

Cards in Rez are broadly equivalent to passages in Twine although they are defined differently. A card is a block of hypermedia defined using the Markdown format.

Internally a card is transformed into a Javascript Handlerbars template so rendering them is performant.

Example

@card intro_part_1 begin
  content: """
  You are in a mazy of twisty passages all alike.
  [[Go forward|#intro_part_2]]
  """
end

@card intro_part_2 begin
    …
end

Required Attributes

  • content

Optional Attributes

  • blocks: list of element-id (#[#sidebar_menu #header])
  • bindings: list of element-id (#[#bandit #player])
  • tags: set of keywords (#[:tag1 :tag2 …])

blocks

If specified, the blocks attribute should contain a list of ids of cards that are going to be included in the output content of this card. At render time all blocks are pre-rendered and passed into the rendering context.

Example @card test_card begin blocks: [#other_card]

  content: """
  This is what is in #other_card
  {{{other_card}}}
  """
end

bindings

If specified this should be a map of keys to game object ids. When the card is rendered all bindings will be resolved and made available to the rendering context. You can then use the $ macro to render attributes of the bound objects.

Example @card test_card begin bindings: {player #player}

  content: """
  The player's name is {{$ player "name}}
  """
end

Event Handlers

  • on_enter: (card) => {}
  • on_render: (game, card) => {}
  • on_ready: (card) => {}
  • on_leave: (card) => {}

Notes

Although a Rez card definition looks a little different to a Twine passage the simple case looks pretty similar. Internally the `[[Go forward|intro_part_2]]`` syntax is transformed into an event that loads the referenced card.

However it’s possible as an author to hijack this mechanism:

@card intro_part_1 begin
  content: """
  You are in a mazy of twisty passages all alike.
  [[Go forward]]
  """
  on_go_forward: (game, evt) => {return Scene.load_card(game, "intro_part_2");}
end

Here we define an event handler which will respond to the link being clicked. By default Rez will automatically convert a link such as “Go forward” into the equivalent “go_forward” by downcasing and replacing whitespace with a single underscore(_).

Rez also has support for more dynamic types of links:

@card intro_part_1 begin
  content: """
  You are in a mazy of twist passages all alike.
  [[Go forward|go_forward]]
  """
  go_forward: (game, evt) => {evt.choice.show("Go forward);}
  on_go_forward: (game, evt) => {return Scene.load_card(game, "intro_part_2")}

When a card link is written in this format, Rez will look inside the card for an attribute with the same name and a function value. It will call the function which can determine whether the link should be shown or hidden and, if it is shown whether it should be enabled or disabled. whether it is enabled or disabled.

See the COOKBOOK for more.

Derive

The @derive element is used to form keyword hierarchies. Let’s take an example of where this might be useful: inventories.

We setup a hierarchy as follows:

@derive :weapon :item @derive :sword :weapon @derive :mace :weapon @derive :potion :item

The result is that an item with type: :sword, type: :mace, or type: :potion can be placed into a slot that accepts: :item. It’s not required to list all the different types of items that are legal in that slot.Equally our sword can be placed into a slot that accepts: :sword but an item type: :mace cannot, nor can an item type: :potion.

An item hierarchy can be as simple of complex as you need. At run-time all of the item type information is converted into tags. For example an item with type: :sword would have tags as if we had written tags: #[:sword :weapon :item].

Effect

Note that this element is not yet fully implemented in the stdlib

An Effect is a non-permanent modifier to some aspect of the game. For example an Item that needs to confer some benefit either when possessed or worn where that effect is only meant to last for a certain period, number of “uses”, or until the Item is no longer worn/carried.

Example

@effect fire_resist begin
  name: "Fire Resistance"
  on_apply: (game) => {
    let fire_resist = game.player.getAttribute("fire_resistance");
    game.player.setAttribute("fire_resistance", fire_resist + 10);
  }
  on_remove: (game) => {
    let fire_resist = game.player.getAttribute("fire_resistance");
    game.player.setAttribute("fire_resistance", fire_resist - 10);
  }
end

Required Attributes

  • on_apply -> function
  • on_remove -> function

Optional Attributes

  • tags: set of keywords (#[:tag1 :tag2 …])

Event Handlers

None

Faction

Note that this element is not yet implemented in the stdlib

A @faction element is used to define an in-game faction to which different @actors may be affiliated. A faction has an attitude towards an actor that represents how it views the actor.

This can be used to determine whether actors will interact and how they will interact.

Example

Required Attributes

Optional Attributes

  • tags: #[:kw1 :kw2 …]

Event Handlers

Game

The @game element is the top level and contains all other elements. It has an implicit ID of game and a number of required attributes and can also hold game-scoped data.

Example

@game begin
  name: "Twisty Maze Adventure"
  IFID: "D2050DE2-97A2-1ED1-4CCA-AF9D3B0DD883"
  created: "2022-08-31 22:13:43.830755Z"
  version: 10
  initial_scene: #intro_scene
end

Required Attributes

  • name:
  • initial_scene:
  • IFID:

Optional Attributes

  • tags: <set>

Event Handlers

None

Group

Note this element is not included in the current stdlib

Example

Required Attributes

Optional Attributes

Event Handlers

Inventory

The @inventory element creates a container that can hold @items through the use of @slots. Rez inventories are deliberately flexible to handle a range of use cases for example working memory (where items are thoughts) or spell books (where items are spells).

Rez has a fairly flexible inventory system that is based around ‘slots’ that define how items can be held. This allows an inventory to hold different kinds of items: you could have an inventory for items as well as an inventory for spells (spell book).

Inventory slots are matched against items to determine whether it’s possible to put an item in a slot.

Inventories are defined using the @inventory tag.

Inventories have a category which determines the kind of items that can be added to their slots. For example “spell” could represent a spell book, while “equipment” could represent the players inventory.

Example

@inventory player_inventory begin
  slots: #[#hat_slot #jacket_slot #trousers_slot #shoes_slot]
end

Required Attributes

  • slots: set of element-ids

Optional Attributes

  • tags: set of keywords

Event Handlers

None.

Item

The @item element defines a conceptual item the player the player (or potentially an NPC) can acquire and add to an inventory. Items don’t have to represent physical objects but anything a player has for example a spell could be an item or even a memory.

Items are required to have a type keyword-attribute that connects them to compatible slots in inventories. That might include a shop, a wardobe, and a players backpack inventories.

However the Item/Inventory system is quite flexible so we can also think about spells as Items with the Inventory being a spell-book, or knowledge as Items with an Inventory being memory.

Items may be usable in which case they may have a limit to the number of times they can be used.

Some items can grant effects, either when the item is acquired, put into a specific slot (e.g. equipped), or when it is used.

The can_equip/on_equip scripts are used to decide whether the player can put an item in a given inventory & slot, and to process what happens when doing so.

For example equipping a magic ring might confer an effect on the player. But first it may be necessary to check that the player doesn’t already have a magic ring equipped.

A potion on the other hand confers no effect until it is used and might have only one use after which is presumed to be consumed.

Example

@item black_fedora begin
  type: :hat
  description: "black fedora"
  wearable: true
  description: "A Messer wool fedora hat. Classy."
end

Note that this example throws up a design issue to be aware of: tags and boolean attributes are equivalent. For example wearable: true can also be represented by presence or absence of a tag wearable. In the case of Item elements its further possible to use the type system:

@derive :wearable :item
@derive :hat :wearable

In this case an Item with type: :hat will automatically be tagged as :wearable and :item.

@item <id> begin
  type: :...
  name: "..."
  description: "..."
  usable: false
  can_equip: () => {...}
  on_equip: () => {...}
end

Required attributes

  • type: keyword
  • name: string
  • description: string

Optional attributes

  • usable: boolean
  • uses: number (assumed >= 0)
  • on_equip: script
  • can_equip: script
  • on_use: script
  • can_use: script

Location

Locations in Rez are an optional concept that can be used to create a “stage” for one or more scenes. In cases where different scenes may play out in one virtual location it may make sense to use a Location to represent what is the same about the background. If scenes and cards get the job done, you don’t have to worry about using locations.

Locations are defined using the @location tag.

Tag: @location

Example

Required Attributes

Optional Attributes

Event Handlers

List

The @list element is for creating lists for use in-game. For example a list of names, or places. At run-time the list element supports selecting randomly from lists including with & without replacement.

Example

@list tourist_traps begin
  content: ["Bree" "Buckland" "Dead Marshes" "Dol Guldur" "Esgaroth" "Mirkwood" "Rivendell" "Weathertop"]
end

API

list.randomElement()

Return a random element of the list.

list.nextForCycle(key)

Cycles through the list element by element. Each cycle is identified by a key.

list.randomUnique(key)

Returns a random element of the list without repeating elements. Each random walk is idenfied by a key.

Example

Required Attributes

Optional Attributes

  • tags: set of keywords

Event Handlers

Plot

Example

Required Attributes

Optional Attributes

  • tags: set of keyword (#[:tag1 :tag2 …])

Event Handlers

Scene

A Game in Rez is authored in terms of @scenes and @cards. Each @card represents some content that is presented to the player. By contrast the @scene represent the structure and intelligence about which @cards to present and how to respond to player input.

If you are familiar with Twine then a @card is roughly equivalent to a Twine passage. A Twine game is one long stream of passages woven together. Rez differs from Twine in that it uses the @scene to organise how the player interacts with the game and which/how the content is presented.

For example you might use different scenes for moving around the map, examining items, interacting with NPCs, buying from shops, and so on. You don’t have to, you could implement the game in a single scene, but the different layout and event handling possibilities make it easier.

A @scene requires an initial_card: #card_ref attribute that identifies the card that will be rendered when the scene begins. Additionally it requires a layout: attribute that specifies the surrounding markup.

Within the layout using the {{{content}}} macro to specify where scene content is inserted.

A @scene requires a layout_mode: attribute which must be either :single or :continuous. In the :single layout mode only a single @card is ever displayed. While in :continuous mode each new @card is layed out after the previous one.

Lastly a @scene may optionally have a blocks: [#card_id_1 #card_id_2 ...] attribute. Each referenced @card will be rendered and it’s content can be inserted into the layout using {{{card_id_1}}}, {{card_id_2}}, etc.

Example

@scene introduction begin
  title: "Introduction"
  initial_card: #intro_part_1
  blocks: [#sidebar_1 #sidebar_2]
  layout_mode: :single
  layout: """
    <div class="sidebar">
      {{{sidebar_1}}}
      {{{sidebar_2}}}
    </div>
    <div>
      {{{content}}}
    </div>
  """
  on_new_card: (game, evt) => { … }
end

Required Attributes

  • title: string
  • initial_card: element-id #card_id
  • layout string

Optional Attributes

  • tags: set of keyword
  • mode: keyword (:single or :continuous)
  • blocks: list of element-id

Event Handlers

  • on_start
  • on_ready
  • on_new_card
  • on_end

Slot

A @slot describes a component of an @inventory so that an inventory can hold different types of things.

For example an inventory representing what a player is wearing might have slots for coats, trousers, and so forth while an inventory representing a spell book might have slots for different levels of spell.

Example

@slot sword_slot begin
  name: "Sword"
  accepts: :sword
end

Required Attributes

  • name: string
  • accepts: keyword

Optional Attributes

  • tags: set of keyword
  • usable: boolean
  • capacity: number
  • on_insert: script
  • on_remove: script

Event Handlers

  • on_insert

When an Item is placed into a Slot the on_insert event handler will be called.

on_insert: (game, evt) => {return game;}
  • on_remove

When an Item is taken out of a Slot the on_remove event handler will be called.

on_remove: (game, evt) => {return game;}

Style

Example

Required Attributes

Optional Attributes

Event Handlers

Zone

Zones are a way of grouping Locations together based. Locations in the same Zone are assumed to be near to each other and reachable (although possibly not directly) while Locations in a different Zone are not and need to be reached via some special action or connecting location.

For example a “downtown” Zone might be connected to a “suburbs” Zone via cab. A cab rank Location in each Zone could act as the gateway to the other Zone and its Locations.

Example

@zone home begin
  @location … begin
  end

  @location … begin
  end

  …
end

Required Attributes

  • name: string

Event Handlers

Zones do not handle any of the default events.

Notes

All element tags start with the ‘@’ symbol however the begin and end statements delimiting the definition do not.

Attributes begin with a legal Javascript identifier followed immediately by a ‘:’ and at least one space.

Attributes that start with on_ are expected to be event handlers and should be of script type taking the arguments game and event. At runtime when the event occurs the function will be called to handle it.

Key Concepts

Elements

Attributes

Game

@game options

One @game directive is required and specifies top-level attributes such as the games title and IFID.

Required attributes

name: a string containing the name of the game IFID: a string containing the game IFID (a UUID) output: a string containing a path where the game will be written by the compiler initial_scene: a reference to the @scene id of the starting scene

Optional attributes

title: a longer form of name, if not supplied name will be used on_init: an event handler called before the game starts on_start: an event handler called before the first card is to be rendered

Example

Group

@group group-id {options}

The @group directive specifies an asset group which collects together one or more assets.

For example an asset group could collect together a set of similar images and in-game select an image at random, or cycle through the collection one-by-one.

The members of an asset group can be determined either by the author by including the ID’s directly, or through the use of tagging.

Attributes

assets: list of ID’s of assets to be statically included in the group tags: list of tags to dynamically include assets in the group

Card options

The card directive specifies a block of content that will be shown to the player. It’s analgous to a passage in Twine with a few upgrades.

@card <id> [options] """[content]"""

Example: @card intro_1 begin content: ““” Markdown goes here ““” on_enter: (game, event) => {} end

Optional Attributes

on_enter

Specifies an event handler that will be called when the card is being entered and before rendering occurs.

on_shown

Specifies an event handler that will be called when the passge is about to be shown to the player, after rendering has occurred.

on_leave

Specifies an event handler that will be called just before the game switches to another card.

Assigns

Any option specified with a ‘$’ at the beginning of its name is considered to be an ‘assign’. What this means is that whenever the card is being rendered the value of all assigns will be updated using either a function or an expression. Assigns are made available to the card as a variable that can be interpolated in a template.

For example:

$player_name: #game.player.name

can then be interpolated into a template as

{{player_name}}

Alternatively:

$player_name: (game, event) => {return game.player.name;}

uses the function sequence. The expression syntax is a syntactic sugar.

Using functions an assign can be arbitrarily complex.

This keeps the logic out of the template itself.

Event handlers

A card can define event handlers that respond to what happens in the game.

There are presently three event handlers:

  • on_enter
  • on_shown
  • on_leave

The on_enter and on_shown call backs happen in sequence. When the active card is switched any on_enter handler is called. At the ender of the rendering process when the new card is visible the on_shown handler is called. Finally when the user triggers a new card the on_leave handler has a chance to run before the on_enter for the new card is invoked.

Handlers are passed the game state and details of the event that has been triggered and are expected to return the (possibly modified) game state.

The assigns process happens between after the on_enter handler is called and before the on_shown handler runs. The on_enter handler is a good opportunity to set values that assigns will depend upon.

Dependencies

NPM

Rez depends upon NPM to deliver dependencies of the game:

  • Alpine.js
  • Bulma CSS
  • Handlebars

Issues

Content delimiter

We need a safe way of delimiting content blocks.

Using {** and **} seemed safe until I remembered that Markdown uses the double star for bold so **}** would prematurely terminate parsing of a content section.

Alternatives <<< >>> - Javascript unsigned right & left shift operators === === - Javascript operator

““” ““” - it’s nice to have a visual distinction between open & close %%% %%% - ditto

Event Hooks

Game Events

on_start
on_scene_change

The on_start event is triggered right after the Rez framework has initialized itself and before the first scene or card gets rendered. It’s an opportunity to customise game setup.

The on_scene_change and on_card_change are interstitial event handlers. To take scene changes for example, the current scene is sent an on_end event when a scene change is being made and the new scene will receive an on_begin event after that. The on_scene_change handler will be called between these other events. It can even change which scene is being routed to.

Scene Events

on_start
on_card_change
on_end

The on_start handler is called when a scene is about to be started and before the first card is rendered. It can change the card to be rendered.

The on_card_change handler is conceptually similar to the on_scene_change handler in the Game object and runs between the on_end and on_start events of cards.

The on_end handler is called right after a scene is over and before the transition to a new scene.

Card Events

on_start
on_action
on_end