YuukSpace Script (YSS)

YSS is a small scripting language that lives inside your session lines. It turns a Mantra Spiral Task or Brainwash Spiral Task from a flat list of lines into a program: lines can be grouped into blocks, blocks can jump to each other, and any line can change the text style, play a sound, or drive the spiral while it is on screen.

Which session types support YSS?

YSS only works in Mantra Spiral Task (MST) and Brainwash Spiral Task (BST) sessions. The editor only offers the YSS feature for those two types. If you paste YSS into any other session type the brackets are shown to the subject as ordinary text.

Enabling YSS

  1. Open the session in the editor and go to the Settings tab.

  2. Click the + YSS (YuukSpace Script) chip to add the feature to the session.

  3. Make sure Enabled? is ticked in the YSS (YuukSpace Script) Settings box.

  4. Write your script in the ordinary Content → Lines list. There is no separate script field: every line in the list is one line of script.

When YSS is enabled, the player compiles the lines the first time the session ticks. If the script compiles to no playable lines at all (for example, only commands and no text) the session completes immediately.

How a line is read

Every line is scanned for commands. A command is anything between square brackets:

[key=value;arg=value;arg=value]
  • The part before the first ; is the command. Its value starts after the first = and may itself contain =.

  • Everything after a ; is an argument. The recognised arguments are id, goto, apply and fade. Unknown arguments are ignored.

  • A command cannot span two lines and cannot contain ]. A value cannot contain ;.

  • Commands are removed from the text the subject sees.

The single most important rule in YSS is what happens to the rest of the line:

The line contains…

What it is

When its commands run

Text and commands, e.g. sink [sound=/x.mp3] deeper

a content line

the moment the line is shown (inline)

Only commands, e.g. [style.text.main.color=#f00]

a command line

when the enclosing block starts (block entry)

Not every command may run inline. Only [sound], [style.*] and [setting.spiral.*] fire mid-line. Any other [setting.*] is always treated as a block-entry command even if you write it in the middle of a sentence.

Command reference

Blocks and flow

[block=start;id=NAME]

Opens a block. Every following line belongs to it until the block is closed. If you leave out id, the block gets an automatic name. Blocks cannot be nested: a second block=start simply replaces the current block.

[block=end;id=NAME;goto=TARGET]

Closes the block. The optional goto makes playback continue at TARGET (a block id or an anchor) when this block finishes, instead of the next block in the file.

[anchor;id=NAME]

Gives an extra name to the block the anchor sits in, so a goto can reach it. Playback always resumes at the top of that block, not at the anchor’s position.

[controller=sequential] / [controller=random]

Chooses the order blocks play in. sequential is the default. random shuffles the block order once at compile time. Lines that are not inside any block form an implicit first block.

Lines outside every block belong to an implicit default block that plays first.

Playing a sound

[sound=URL]

Plays an audio file once. The URL may be absolute or relative. Sound can be inline in a content line. Use a direct link to an audio file, such as one from your Stash.

Styling the focus text

Style commands change the centre “focus line” text. They persist until another command overwrites them.

Command

Effect

Example value

[style.text.main.color=…]

text colour

#ff2020, red

[style.text.main.size=…]

font size, any CSS length

8vh, 48px

[style.text.main.font_family=…]

font family

serif, Courier New

[style.text.main.add_class=…]

adds a CSS class to the focus text

pulse

add_class is the bridge to Custom CSS: define .pulse { } in the session’s custom CSS and switch it on from the script. Classes are added, never removed.

The apply= argument from older documentation is accepted but has no effect.

Re-pacing the session

[setting.spirals.line_duration=MILLISECONDS]

Changes how fast the session ticks from this block onward. In an MST this is the time each line stays on screen; in a BST it is the time each word stays on screen. The value must be a positive whole number of milliseconds. This is a block-entry command: put it on its own line at the top of a block.

[setting.session.type=…]

Accepted for compatibility but ignored. A session cannot change type mid-run.

Note the spelling: the plural setting.spirals.line_duration re-paces the session, while the singular setting.spiral.* family below drives the spiral. A typo in the plural form is silently ignored.

Driving the spiral live

[setting.spiral.NAME=VALUE;fade=MILLISECONDS]

Changes one property of the spiral while the session runs. These commands work inline or on block entry. Add fade= to ease smoothly to the new value over that many milliseconds; without it the change is instant.

These commands only work when the session uses the WebGL or Scripted WebGL (GLSL) spiral. With a media spiral (image or video) they do nothing.

Name

Value

Default

spiral_color

#rgb, #rrggbb, or r,g,b floats 0–1

from the spiral settings

bg_color

as above

from the spiral settings

spin_speed

number

1

throb_speed

number

2

throb_strength

number

1

zoom

number

1

opacity

0 to 1

from the spiral settings

If you wrote your own shader, any extra uniform float or uniform vecN you declared can be driven by its own name. Give vectors as comma- or space-separated numbers: [setting.spiral.myPulse=0.5;fade=2000] or [setting.spiral.tint=1,0.5,0]. See GLSL spirals.

MST and BST play scripts differently

Mantra Spiral Task plays the compiled lines in order, one per tick. All the inline commands on a line fire together when the line appears, so their position within the line does not matter.

Brainwash Spiral Task treats the compiled lines as a pool and picks a random line each time the previous one finishes, then flashes it one word at a time. An inline command occupies one word slot and shows as a blank flash for that tick. Because BST ignores block order, goto and controller are effectively MST features; in a BST, blocks are only useful for attaching entry settings and styles to a group of lines.

Loops and limits

A block that jumps to itself loops forever in the script, but the player caps the compiled session:

  • MST: four times the number of lines, kept between 200 and 5000 lines.

  • BST: the Number of lines to iterate over value, kept between 200 and 5000.

A goto pointing at a block that does not exist or has no text simply ends the session.

Errors

YSS never blocks saving and never shows an error to the subject. Problems are written to the browser console and to the in-player console panel:

Mistake

What happens

Unknown command, e.g. [wait=5]

logged as invalid; text shown without it

Unknown setting.* name

silently ignored

Unknown style.* name

silently ignored

setting.spiral.* with a media spiral

warning, nothing changes

Unparseable spiral value, e.g. zoom=huge

warning, old value kept

Unclosed bracket

shown to the subject as literal text

Worked examples

All of these are taken from the engine’s own test suite.

Ordered blocks

[block=start;id=a]
alpha one
alpha two
[block=end;id=a]
[block=start;id=b]
beta one
[block=end;id=b]

Plays alpha one, alpha two, beta one.

Skipping a block with goto

[block=start;id=a]
alpha
[block=end;id=a;goto=c]
[block=start;id=b]
beta
[block=end;id=b]
[block=start;id=c]
gamma
[block=end;id=c]

Plays alpha, then gamma. Block b never plays.

A block that loops

[block=start;id=loop]
again
[block=end;id=loop;goto=loop]

Repeats again until the line cap is reached, then the session completes.

Colour and pacing for one block

[block=start;id=deep]
[style.text.main.color=#ff0000]
[setting.spirals.line_duration=1500;id=deep]
you are sinking
deeper still
[block=end;id=deep]

When the block starts, the focus text turns red and the pace changes to 1.5 seconds per line (per word in a BST).

Inline spiral zoom with a fade

sinking [setting.spiral.zoom=2;fade=1500] deeper

Shown as sinking deeper; the spiral eases to double zoom over 1.5 seconds.

Spiral colour and opacity on block entry

[block=start;id=green]
[setting.spiral.spiral_color=#00ff00]
[setting.spiral.opacity=0.4]
alpha one
alpha two
[block=end;id=green]

A complete script

[block=start;id=intro]
[style.text.main.color=#ff2020]
welcome to the test
deeper and deeper
[block=end;id=intro;goto=loop]
[block=start;id=skip]
you should NOT see this
[block=end;id=skip]
[block=start;id=loop]
you are relaxing [sound=/static/utils/ding.mp3] now
let go completely
[block=end;id=loop]

Plays the two intro lines in red, jumps straight to loop (skipping skip), plays a chime on the relaxing line, and ends after let go completely.

Random block order

[controller=random]
[block=start;id=a]
alpha
[block=end;id=a]
[block=start;id=b]
beta
[block=end;id=b]

Every line still plays exactly once; only the block order varies between runs.