This page explains the Shogi expression format that can be used in shogi.json or other supported config files.
These are all valid rules:
220
'Disabled in this area'
true
$distance
What these mean:
220 evaluates as a number'Disabled in this area' evaluates as a stringtrue evaluates as a boolean$distance reads a variable provided by the active rule contextcondition -> result for conditional rulesThe most common pattern is:
condition_name(...) -> result_here
Examples:
is_dimension('minecraft:the_nether') -> 180
is_inventory_button -> cooldown_cost('inventory_button', '300s')
is_interdimensional -> failure('Interdimensional travel is disabled')
What happens:
-> runs+ means all, , means anyUse + when every condition must match:
is_dimension('minecraft:the_nether') + is_below_y(0) -> failure('Too dangerous here')
Use , when either condition may match:
is_dimension('minecraft:the_nether'), is_dimension('minecraft:the_end') -> 256
If you mix them, + is checked first:
is_dimension('minecraft:the_nether') + is_below_y(0), is_player_nearby(12) -> failure('Unsafe teleport target')
That reads like:
(in the Nether AND below Y 0) OR player is nearbyUse parentheses when you want to make grouping obvious:
is_dimension('minecraft:the_nether') + (is_below_y(0), is_below_y(16)) -> failure('Too low for this teleport')
! means “not”You can negate a single condition:
!is_interdimensional -> damage_item(20)
Or a grouped condition:
!(is_dimension('minecraft:the_nether'), is_dimension('minecraft:the_end')) -> 220
Most Shogi rules are built from effect or condition calls:
damage_item(80)
failure('You need more XP')
clamp($distance * 0.01, 0, 27)
if(condition = is_interdimensional, then = 27, else = $distance * 0.01)
Two useful patterns:
is_inventory_buttonUse single quotes, since double quotes require escaping in most contexts:
'minecraft:the_nether'
'300s'
Both integers and decimals are supported:
27
0.01
256
Use lowercase:
true
false
Variables start with $:
$distance
$xp_cost
You can assign to a variable and use it later:
$xp_cost = if(condition = is_interdimensional, then = 27, else = $distance * 0.01)
$xp_cost = clamp($xp_cost, 0, 27)
$xp_cost
This is a common pattern for rules that need a few calculation steps.
In aggregate-style configs such as rule lists, assigning to some variable names can also create a matching effect automatically.
Example:
$xp_points_cost = if(condition = is_interdimensional, then = 27, else = $distance * 0.01)
$xp_points_cost = clamp($xp_points_cost, 0, 27)
If the active scope has a single-parameter effect named xp_points_cost, Shogi treats this like you had also written:
xp_points_cost($xp_points_cost)
Why this is useful:
This only works when the variable name matches a real effect name that accepts one main value.
If there is no matching effect, the variable stays just a variable.
You can use regular math operators inside expressions:
$distance * 0.01
($distance + 500) / 2
clamp($height - 8, 128, 320)
Operator order works the usual way:
* and / happen before + and -Examples:
1 + 2 * 3
(1 + 2) * 3
Some calls are clearer with named arguments:
if(condition = is_interdimensional, then = 27, else = 0)
This is also valid even if the named arguments are in a different order:
if(else = 0, then = 27, condition = is_interdimensional)
Do not mix named and positional arguments in the same call.
Use one style per call:
clamp($xp_cost, 0, 27)
if(condition = is_interdimensional, then = 27, else = 0)
These mean the same thing:
is_inventory_button -> cooldown_cost('inventory_button', '300s')
is_inventory_button->cooldown_cost('inventory_button','300s')
Extra spaces are fine. Clear spacing is still easier to maintain.
'minecraft:the_nether', not minecraft:the_nether->, not =>foo(bar = 1, 2)This pattern is typical for a property hook that calculates a value and applies extra effects:
$xp_points_cost = if(condition = is_interdimensional, then = 27, else = $distance * 0.01)
$xp_points_cost = clamp($xp_points_cost, 0, 27)
is_inventory_button -> cooldown_cost('inventory_button', '300s')
is_warp_stone -> damage_item(80)
Read it as:
xp_points_cost($xp_points_cost) because the variable name matches that effect