Introduction
PyCube is a Twine story format inspired by the clarity of Python and the interactive power of SugarCube. It enables authors to write interactive stories and games using clean, indentation-based logic, familiar assignment, and powerful variable handling—all in a way that's easy to read and write.
PyCube-Enhanced Twine Editor
https://github.com/BwendyGames/twinepy
This is a forked version of the Twine editor with several changes and additions to support development with the PyCube story format, as well as some quality of life features:
- PyCube 0.2.5 is loaded as a built-in format.
- The passage editor better supports the typing style of PyCube, with increased support for lots of indenting/unindenting.
- Syntax highlighting for PyCube.
- Catppuccin themes (all four versions) are available as options in Twine → Preferences → Theme.
- Ctrl+F keybind opens a search bar in the passage editor, allowing you to search for keywords and cycle through them with Enter.
Syntax Overview
- Indentation: Use tabs or 4 spaces to create code blocks, just like in Python.
- Assignments: Assign variables with
$
(persistent) or_
(temporary). E.g.,$gold = 5
,_rand = 2
. - Display variables: Use
{var}
for persistent,[var]
for temporary. E.g.,{gold}
,[rand]
. - Links: Use
[[Go|Destination]]
to create choices. - Macros: Use
choice
,option
,replace
, andrand
for advanced interactivity.
$gold = 10
_rand = rand(1, 6)
if gold >= 10:
You have enough!
else:
Not quite there.
You rolled [rand]
[[Go to Shop|Shop]]
Variables
- Persistent variables: Use
$var
. These are global and persist until restart or reload. - Temporary variables: Use
_var
. These are reset each passage and are not saved. - Set a variable:
$score = 0
or_rand = 2
- Modify a variable:
$score += 1
- Show a persistent variable:
You have {score} points.
- Show a temporary variable:
You rolled [rand]
$inventory = 2
You have {inventory} items.
_rand = rand(1, 6)
You rolled [rand]
Conditionals (if/else)
PyCube supports Python-style conditional blocks with indentation:
$gold = 3
if gold >= 5:
You are rich!
else:
You need more gold.
- Supports
==
,!=
,>=
,<=
,>
,<
, andin
for lists. - Blocks must be indented with at least 1 tab or 4 spaces.
Links & Navigation
Create interactive choices using [[Link Text|Destination]]
:
[[Go to Forest|Forest]]
[[Check Inventory|Inventory]]
- If no
|Destination
is provided, link text is used as the passage name.
Special Passages
PyCube recognizes certain passage names as special, which gives them unique behavior in your story. These passages are run automatically at key times or displayed in special locations.
Init Passage
- Init is a passage (case-insensitive) run once at the start of your story—before the first passage is shown.
- Use Init to set up variables, initial inventory, player name, or any world state that must exist for the story to work.
- Does not display output—use it only for setup, not narration.
$player_name = "John Doe"
$gold = 10
$inventory = []
Tip: You may create an Init passage in the Twine editor like any other passage. PyCube will detect and run it automatically.
Sidebar Passage
- Sidebar is a special passage whose contents are displayed in the middle of the sidebar, below the navigation menu.
- Use Sidebar to show stats, inventory, or any contextual information you want visible throughout the story.
Sidebar:
You have {gold} gold.
Inventory: {inventory}
Author Passage
- Author is a special passage whose contents are displayed at the very top of the sidebar, above the navigation menu.
- Use Author to show author info, a logo, or a custom title for your story.
Author:
By John Doe
Other Special Passages
- In the future, PyCube will support other special passages, such as Header (for code/content at the top of every page) and Footer.
- Currently, Init, Sidebar, and Author are supported.
Macros & Blocks
- Currently Supported:
if
/else
blocks,choice
/option
,replace
, andrand
. - More macros/widgets (loops, custom blocks) will be added in future versions.
if score >= 10:
print("You win!")
else:
print("Keep playing.")
_rand = rand(1, 100)
You rolled [rand]
Choice Macro
Use choice
and option
to present interactive choices that reveal content when selected. Only one option can be chosen.
choice("Choose your path"):
option("Option 1"):
$choice = 1
_rand = rand(1,6)
You get [rand] bugs!
option("Option 2"):
$choice = 2
_rand = rand(1,6)
You get [rand] hugs!
Replace Macro
Use replace
to create a clickable element that, when clicked, is replaced by its indented content.
replace("Click this"):
You clicked it!
Rand Macro
Use rand(min, max)
to generate a random integer between min
and max
(inclusive).
_rand = rand(1, 100)
You rolled [rand]
Saving, Loading & History
- Click the menu button (☰) on the left to open the sidebar.
- Use Save/Load Slots to manage up to 5 separate save slots.
- Export and Import lets you back up or transfer saves.
- Restart clears all progress and starts over.
- Back (←) and Forward (→) let you retrace your choices and variable state, just like in SugarCube.
Error Handling
- If your script contains an error (invalid math, syntax, etc.), PyCube will show a red error banner at the top.
- Click the ✕ to dismiss the error.
Example of an error:
$gold = x + 5 # 'x' is not defined
This will display: Error evaluating expression: x + 5
Full Examples
Visit Example PyCube.orgSimple Choice:
$apples = 2
if apples > 0:
print("You eat an apple.")
$apples -= 1
else:
print("No apples left!")
[[Next|SecondPassage]]
Choice Macro Example:
choice("Choose your path"):
option("Option 1"):
$choice = 1
_rand = rand(1,6)
You get [rand] bugs!
option("Option 2"):
$choice = 2
_rand = rand(1,6)
You get [rand] hugs!
Replace Macro Example:
replace("Click this"):
You clicked it!
Rand Macro Example:
_rand = rand(1, 100)
You rolled [rand]
Testing Errors:
$score = 3 * *
Your score is {score}.
How to Use PyCube in Twine
- Open Twine, and select Formats in the menu.
- Add a new story format with the URL:
https://pycube.org/format.js
- Switch your story's format to PyCube (via the Story menu → Change Story Format).
- Write passages using PyCube's Pythonic syntax!