VASSAL Reference Manual

Home > Module > Expressions


Expressions

Expression

Any field within the Vassal Editor that is followed by a Calculator icon calculator allows the entry of an Expression. Expressions are essentially an in-line Calculated Property that are re-evaluated whenever their value is required. There are two main flavors of Expression: BeanShell Expressions which are identified by being surrounded by curly braces {}, and Simple Expressions which are not.

Property Match Expressions are specialized expressions (of either type) used to select which pieces to operate on by checking properties, e.g. in a Global Key Command.

The Expression Builder is a convenient tool for building expressions from available properties, operations, and methods.

Note
Beanshell expressions should not be confused with "old style" Simple Expressions, which have a different syntax and are far more limited.

BeanShell Expressions

BeanShell Expressions (named after the software package that implements them in Vassal) allow you to use arbitrarily complex formulae to define the value returned. BeanShell Expressions are marked by being surrounded by curly braces {}. The BeanShell processor is an accurate implementation of the Java programming language and BeanShell Expressions are made up of Java language components. You can use any introductory Java tutorial to learn more about the syntax of BeanShell Expressions. The basic components are as follows:

Type Options Examples Notes

Numbers

{35}

Vassal works with whole numbers. Decimal numbers are treated as strings.

Strings

{"German"}

A String literal, or text message, must be enclosed in "" quotation marks

Substitution

$..$

{"$Nation$"}
{$Attack$}

Property names enclosed by $..$ symbols immediately substitute the property value, based on the piece or component issuing the command. Not normally needed in BeanShell as there are simpler ways to use a property value in an expression, but sometimes useful in Property Match Expressions to use properties from the issueing piece rather than target piece.

Properties

{Nation}
{LocationName}
{CurrentMap}
{playerName}

Any word not enclosed in "" is interpreted as a Property name.

Can refer by name to Global Properties, Marker and Dynamic Properties of pieces, and properties exposed by traits. The current value of the property will be used.

Arithmetic

+ Add
- Subtract
* Multiply
/ Divide
% Modulo

{(CurrentHP + 2) * (Damage - Resistance)}
{FirstName + "-" + Surname}
{Height * 10}
{width / 5}
{Level % 10}

Using the + operator on two String will concatenate (join) them. If the values on both sides of the + look like whole numbers, Vassal will attempt to add them.

Parentheses can be used to organize operations and/or override the ordinary order of operations.

Comparison

> Greater than
< Less than
>= Not less than
<= Not greater than
== Equals
!= Not Equals
=~ Match regular Expression

{height > 10 && width >= Level}
{length < maxlength || breadth <= maxbreadth}
{Nation=="Germany"}
{Army!="Allied"}
{Type=="^A$"}

Comparison operators are used primarily in Property Match Expressions and also with the ? (ternary) operator.

Parentheses can be used to organize operations and/or override the ordinary order of operations.

Logical

&& Logical AND
|| Logical OR
! Logical NOT
() Grouping

{Nation=="Germany" && Type=="Unit"}
{Nation=="Germany" || Type=="Unit"}
{Nation=="Germany" && Type=="Unit"}
{!isInUse}
{A==B && (C==1 || D==2)}

Comparison operators are used primarily in Property Match Expressions and also in the If function.

Ternary

Expr ? IfTrue : IfFalse

{ (Nation=="Germany") ? "Axis" : "Allies" }
{ (Nation=="Germany") ? 5 : 2 }
{ States.contains(CurrentZone) ? 1 : 0 }
{ IsRandom() ? "Heads" : "Tails" }
{A==B ? C : D}

The Ternary or "?" operator can be thought of as posing a yes/no question: if the expression before the ? symbol evaluates as "true", then the value of the expression as a whole is equal to the middle ("if true") part of the expression; otherwise (initial part is false), the result is the right ("if false") side.

Math

Math.abs(value1)
Math.min(value1, value2)
Math.max(value1, value2)

{Math.abs(Number - 5)}
{Math.min(Health, Armor)}
{Math.max(3, Random(6))}

Math.abs() Returns the absolute value of the numeric property value1.

Math.min() Returns the smaller of two numeric values.

Math.max() Returns the larger of two numeric values.

Property

GetProperty(property)
GetString(property)
GetMapProperty(property,map)
GetZoneProperty(property,zone)
GetZoneProperty(property,zone,map)

{GetProperty("Nation"+myNation)}
{GetString("HowManyDogs")}
{GetMapProperty("Owner",CurrentMap)}
{GetZoneProperty("Militia","Georgia")}
{GetZoneProperty("Modifier",OldZone,OldMap)}

All GetProperty() family functions return the value of a named property. The name of the property can be constructed from an expression.

GetString() returns a string value even if the property contains a number or a boolean. You can also append .toString() to any other function or property to achieve the same effect.

GetMapProperty() looks only on the specific map for the property.

GetZoneProperty() looks only in a specific zone (and if specified, map) for the property.

Random

Random(value1)
Random(value1,value2)
IsRandom()
IsRandom(percent)

{Random(6)}
{Random(AttackPower,AttackPower * 2)}
{IsRandom()}
{IsRandom(75)}

Random(value1) returns a random number between 1 and value1.

Random(value1,value2) returns a random number between value1 and value2.

IsRandom() returns "true" 50% of the time.

IsRandom(percent) returns "true" the specified percent of the time.

String Methods

.length()
.contains(string2)
.startsWith(string2)
.endsWith(string2)
.matches(regExpr)
.indexOf(string2)
.lastIndexOf(string2)
.substring(start)
.substring(start, end)
.replace(old, new)
.toString()

{ LocationName.length() }
{ States.contains("Arkansas") }
{ OwnerString.startsWith("Axis") }
{ MaybeQuestion.endsWith("?") }
{ String.matches("[^abc]") }
{ WhereIsTheColon.indexOf(":") }
{ MaybeLotsOfDivs.lastIndexOf("div") }
{ CurrentZone.substring(5) }
{ PlayerName.substring(1,5) }
{ GetProperty("XX").replace("A","YY") }
{ AttackValue.toString() }

length() the length in characters of the string.

contains(string2) true if string2 is a substring of the original string.

startsWith(string2) true if string2 is the starting sequence of the original string.

endsWith(string2) true if string2 is the final sequence of the original string.

matches(regex) true if the original string matches the regular expression regex.

indexOf(string2) the first index where string2 can be found in the original string.

lastIndexOf(string2) the last index where string2 begins within the original string.

substring(start) from character indexed by start, the rest of the string.

substring(start,end) returns the substring from start to end, exclusive.

replace(old,new) the original string with all instances of the string old replaced by the string new

toString() converts the property or result into a string even if it was a number or a boolean

Sum and Count

SumStack(propertyName)
CountStack()
CountStack(propertyName)
Sum(prop, expression)
Sum(prop, expr, map)
Count(expr)
Count(expr, map)

{SumStack("Attack")}
{CountStack()}
{CountStack("Russian")}
{Sum("Defense", "{Type != \"Artillery\"}")}
{Sum("Cost", "{ Value > 0 }", "Purchases")}
{Count("{ Nation == \"$Nation$\" }")}
{Count("{ CombatValue > 0 }", "BattleMap") }

SumStack(prop) returns the total of the specified property in all pieces in the same stack as this one.

CountStack() returns the total number of pieces in the same stack as this one (including this piece)

CountStack(prop) returns the number of pieces in the same stack as this one, that have a non-blank value for the named property. If this piece has a non-blank value for the named property, it is counted in the total.

Sum(prop, expr) returns the total of the specified property for all pieces in the game matching the expression.

Sum(prop, expr, map) returns the total of the specified property for all pieces on a specific map matching the expression.

Count(expr) returns the number of pieces in the game that match the expression.

Count(expr, map) returns the number of pieces on a specific map matching the expression.

NOTE: Except for SumStack, these functions can have substantial performance cost as they must check all of the pieces on the map or in the entire game against the expression. Also, because Java requires that the expression itself must be passed as a string, the syntax is tricky here and quotation marks inside the expression must be quoted as \"

Alert

Alert(message)

{Alert("Adding 1 to HP")}

Alert displays a message in a popup dialog box, to the currently active player only. If a message needs to be shown to all players, the recommended method is to send something to the Chat Log e.g. with a Report Action trait or other Message Format field.

Simple Expressions

Simple expressions are not surrounded by braces and exist to provide compatibility with earlier versions of Vassal that only implemented a much simpler version of Expressions. Simple Expressions are far more limited than BeanShell Expressions, only allowing the substitution of property values into a pre-determined string. If you are learning VASSAL for the first time, it is recommended that you mostly learn the more powerful BeanShell Expressions.

A Simple Integer Expression:

SimpleExpression1

A whole number. In general, Vassal does not support decimal numbers, except when stored and used as Strings.

A basic Simple String Expression:

SimpleExpression2

A String in a Simple Expression is defined without quotation marks.

A more complex example:

SimpleExpression3

The string $Nation$ will be replaced by the value of the Nation property. You can use multiple $…​$ strings in an expression ($Nation$-$Division$), but can NOT nest them ($Nation$Count$$).

SEE ALSO: Properties