VariablesWML

From Wesnoth


Contents

Purpose

Variables are used to record information for later use.

For instance, assume that a choice a player makes in one scenario should affect a later scenario. With a variable, that choice can be recorded, and made available to the later scenario.

Overview

Each variable is given a name. A given variable name may contain only alphabetic characters, digits, and underscores.

A variable can be assigned, queried, and cleared.

  • Assigning a value to a variable (usually with [set_variable]) stores that value in the variable. Every variable can be assigned an initial value at the beginning of a scenario by using the [variables] tag.
  • Querying a variable returns the last value stored in it (or the empty string, if no value was).
  • Clearing a variable makes Wesnoth forget about that variable. This is useful since Wesnoth must save all used variables when a game is saved. A variable can be cleared using [clear_variable].

In these operations, a variable is identified by its full name.

Kinds of Variables

Scalar

A scalar variable can store a single string or number. It is usually assigned using [set_variable] or with the {VARIABLE} macros, for example:

{VARIABLE my_variable "sample value"}

which is shorthand for:

[set_variable]
   name=my_variable
   value="sample value"
[/set_variable]


The full name of a scalar variable is simply its given name, in this case my_variable.

Values such as "sample value" can also be marked as translatable (_"sample value") or even include special formula syntax ("$(1+2)"). For more details about WML syntax features, refer to SyntaxWML.

Container

A container variable can store any number of scalar and/or array variables. There are tags to assign specific information, for instance [store_side].

To refer to a variable bar stored in a container foo you would write foo.bar. An explicit index inside an array is also considered a container.

Array

An array variable is a numbered sequence of container variables.

There are some specific tags that assign array information, for example [store_unit] and [store_locations]. You can create your own arrays using [set_variable] like this:

[set_variable]
   name=my_awesome_array[0].x
   value=10
[/set_variable]
[set_variable]
   name=my_awesome_array[1].x
   value=12
[/set_variable]
[set_variable]
   name=my_awesome_array[2].x
   value=14
[/set_variable]

However, when working with arrays it is usually easier to make use of the [set_variables] command (note the extra 's' at the end). This would be written as follows:

[set_variables]
   name=my_awesome_array
   [value]
       x=10
   [/value]
   [value]
       x=12
   [/value]
   [value]
       x=14
   [/value]
[/set_variables]

If foo is the name of an array, foo[0] is the full name of its first container variable, foo[1] the full name of its second, ..., and foo.length is the special variable that always stores the number of containers in foo. Hence, if the value stored in foo.length is 18, the last container is foo[17].

If you try to use an Array as if it were a Container, then it will simply use the first index[0]. So $foo.bar would be the same as $foo[0].bar

Note: Do not attempt to store a scalar value to the explicit index of an array, which is a container of scalar variables. Hence referring to a variable named foo[3] as if it were a scalar one is illegal; instead, you would use foo[3].value or foo_3 to store a scalar value. (While it may appear to work to an extent if you ignore this rule, it may also cause undefined behavior. For example, loading a text save of a game that contains such variables will fail with a WML error.)

Variable testing

Variables can be tested by using [variable] inside an [if] or [while]. See ConditionalWML for more details.

Variable substitution (variable's $)

in short:

Whenever using a $ in front of a variable name, the content which has previously been put into this variable name is used instead of the name of the variable, for example:

[event]
    name=moveto
    [set_variable]
        name=my_var
        value=my_value
    [/set_variable]
    [message]
        speaker=narrator
        message=_"my_var: $my_var|" # output: "my_var: my_value"
    [/message]
[/event]


technical explanation:

When writing scenario events using EventWML, a scalar variable can generally be substituted into the right-hand of any key=value assignment, for example:

message="Hello, $my_variable"

When providing attributes, there are 2 different substitution modes:

literal
the attribute value is used exactly as provided
complex
while the provided value contains a $, interpret what is between the rightmost $ and the next | as a full variable name to be queried, and replace $variablename| with the result of this query.
In certain situations, the | that marks the end of the variable name to be queried can be omitted. The precise rule is:
If there is no |, variable names span letters, digits, underlines, balanced square brackets and some periods. Doubled periods and some periods that would result in an illegal variable name will not be included. If the variable name ends up being empty (e.g. when using $|), then it will be replaced by just $, giving you an easy way to include a dollar sign in an interpolated string.


The substitution mode used depends on the attribute being provided:

literal
[set_variable] literal=
[set_variables] [literal]
complex
everywhere else (in EventWML)

The [variables] tag

The [variables] tag is used in saved games to describe the current value of each variable, and in scenario files for assigning initial values to variables at scenario start.

A scalar variable is assigned using an attribute, where the attribute's key is the variable's given name, and the attribute's value is the value to be stored in the variable.

A container variable with given name foo is assigned using a [foo] tag that contains the definitions for the contained variables.

An array variable with given name foo is assigned using several [foo] tags, where the first tag describes foo[0], the second foo[1], ...

Storing variables inside units

Sometimes it is useful to store a custom WML variable inside a unit. Units stored with the [store_unit] command have a unit.variables sub-container where custom variables related to that unit may be saved. (Remember to [unstore_unit] for the changes to be kept.) One benefit of this approach is that the unit may then be filtered based on the value, for example:

[filter]
  [filter_wml]
    [variables]
      my_variable="test"
    [/variables]
  [/filter_wml]
[/filter]

Automatically stored variables

  • side_number: the number of the current player's side (may be empty during start or prestart events)
  • turn_number: the number of the current turn (may be empty during start or prestart events)
  • x1: this is the x-coordinate of the location where the most recent event was triggered
  • y1: this is the y-coordinate of the location where the most recent event was triggered
  • x2: this is the x-coordinate of the location that assisted in triggering the most recent event
  • y2: this is the y-coordinate of the location that assisted in triggering the most recent event
  • unit: inside an event, this is the unit at $x1,$y1
  • second_unit: inside an event, this is the unit at $x2,$y2
  • this_unit: inside a standard unit filter, this is the unit currently being considered for a possible match
  • damage_inflicted: inside attacker_hits and defender_hits events, this is the amount of damage that was inflicted
  • weapon: inside attack, attacker_hits, defender_hits, die and last_breath events, this is some information about the weapon that is/was being used by the unit at $x1,$y1. It contains the attributes from [attack], see UnitTypeWML.
  • second_weapon: inside attack, attacker_hits, defender_hits, die and last_breath events, this is some information about the weapon that is/was being used by the unit at $x2,$y2. It contains the attributes from [attack], see UnitTypeWML.

Examples

Consider a saved game with the following [variables] tag (or a freshly started scenario with that tag)

[variables]
    attitude_of_elves=hate
    attitude_of_dwarves=love
    attitude_of_humans=like
    current_opponent=elves
[/variables]

Then,

[message]
   message="Oh, I see $current_opponent|! They surely $attitude_of_$current_opponent|| us!"
[/message]

displays the message

Oh, I see elves! They surely hate us!

Consider another game with variables

[variables]
    our_side=1
    their_side=2
[/variables]

where side 1 has 75 gold, and side 2 50 gold. Then,

[store_side]
    side=$our_side
    variable=we
[/store_side]
[store_side]
    side=$their_side
    variable=they
[/store_side]
[message]
    message=We have $we.gold gold, they have $they.gold gold.
[/message]
[if]
    [variable]
        name=we.gold
        greater_than=$they.gold
    [/variable]
    [then]
        [message]
            message=This should be easy!
        [/message]
    [/then]
    [else]
        [message]
            message=This will not be easy!
        [/message]
    [/else]
[/if]
[clear_variable]
    name=we
[/clear_variable]
[clear_variable]
    name=they
[/clear_variable]

displays the messages

We have 75 gold, they have 50 gold.
This should be easy!

If side 2 had 100 gold instead, the same code would display the messages

We have 75 gold, they have 100 gold.
This will not be easy!

The code

[store_unit]
    [filter]
        canrecruit=yes
        side=1
    [/filter]
    variable=leader
[/store_unit]
[message]
    message=Our leader's first attack does $leader[0].attack[0].damage damage per hit.
[/message]
[clear_variable]
    name=leader
[/clear_variable]

always displays a true sentence.

More Examples

The implemention of UtilWML makes heavy use of variables, in particular the definition of {FOR_EACH} and {MODIFY_UNIT}. You may find more complicated examples of variable use in the UsefulWMLFragments section.

See Also

This page was last modified on 14 August 2010, at 12:28.