RUN_DESIGN 文字格式指南

本指南描述一種簡潔、便於人手編輯的互動故事文字格式(RUN_DESIGN)

RUN_DESIGN 文字格式指南

本指南描述一種簡潔、便於人手編輯的互動故事文字格式(RUN_DESIGN)。同時支援可逆轉換:JSON → RUN_DESIGN → JSON,在支援的欄位範圍內不會有語義流失。

目標

  • 簡單、可讀、利於版本控管的文字格式

  • 能編譯成 JSON 的故事結構

  • 能將 JSON 無語義差異地匯出回文字

檔案編碼

  • UTF-8

空白與註解(Whitespace & Comments)

  • 允許空白行。

  • // 開頭的單行為註解,編譯時會被忽略。請另開新行。

頂層後設資料(Metadata)

  • [meta] title "<Title>" 設定故事標題

  • [meta] author "<Author>" 設定作者(必填;匯入/更新時若缺少會被拒絕)

  • [intro] <text> 追加一行故事導言(可重複多行),在劇本開始時會顯示。

顯示行為:

  • .st list 中:

    • 指定 alias 時,會完整顯示該故事的導言(若有)。

    • 列出所有可啟動劇本時,會在每列標題下顯示導言第一行的預覽(最多 80 字)。

  • .st mylist 中:

    • 每項劇本會顯示導言第一行的預覽(最多 80 字)。

  • 在啟動遊戲後且玩家變數尚未完成設定時:

    • 角色設定提示前會先顯示【簡介】區塊,內容為導言全文。

範例:

玩家變數(Player Variables)

  • [player_var] <key> "<prompt>" ["<placeholder>"]

    • key:識別字,例如 cat_name

    • prompt:顯示給玩家的提問

    • placeholder:可選的提示文字

範例:

遊戲屬性(Game Stats)

  • [stat_def] <key> <min> <max> ["<label>"]

  • 初始化:未被明確設定時,首次開始時以 min~max 隨機整數初始化。

  • 鎖定:若該屬性曾被內容內的 [set] 明確指定,之後將不再被隨機初始化覆寫。

範例:

變數(Variables)

  • [var_def] <key> <min> <max> ["<label>"]

範例:

頁面(Pages)

故事由多個頁面組成。

  • 定義頁面標籤(ID):[label] <id>

    • 限制:頁面 ID 只能使用數字(如 0, 1, 2, 10 等)

    • 開點頁面[label] 0 為故事的起始頁面,遊戲開始時會自動載入此頁面

    • 其他頁面可使用任意數字作為 ID,建議使用連續數字以保持可讀性

  • 可選頁面標題:[title] <text>

  • 頁面內容(不限行數):

    • [text] <content>

    • [text|if=<expr>] <content> 條件顯示

    • [text|else] <content> 與前一或多個連續的 [text|if=...] 形成條件鏈,只會顯示第一個符合條件的項目;若皆不符合則顯示 else。也支援於結局區塊中使用。

    • [text|ifs=<expr>] <content> 獨立條件顯示:只要命中就顯示,不會與上下鄰近的 [text|if=...]/[text|else] 形成條件鏈。

    • [text|speaker=<key>] <content> 指定說話者

    • [text|speaker=<key>,if=<expr>] <content> 指定說話者且具條件

    • [random] <percent>% 僅影響「下一行」的 [text](例如 30%),percent 為 0~100 的整數。

    • [set] <key>=<expr> 在渲染時設定值:若 key 屬於已定義的 stat_def,則寫入 stats;否則寫入 variables<expr> 支援基本運算式(見下文)。

      • 任一屬性一旦被 [set] 明確設定,之後將不再由隨機初始化覆寫。

    • 文字內可直接擲骰:{xDy} 會在顯示時擲骰並以總和取代,例如 {1D100}{2d20}{3d6}

  • 結局標記:

    • [ending] 之後的 [text] 行視為結局文字,會使用第一個符合條件的結局

    • 支援條件鏈:可使用多行 [text|if=...] 後接一行 [text|else] 作為後備

    • 要求:一個有效的 RUN_DESIGN 必須至少包含一個帶有 [ending] 標記的頁面;若未定義結局,上傳/更新將被拒絕。

  • 選項區塊:

    • [choice] 開始定義選項列表

    • -> <text> | <頁面代號> [| if=<expr>] [| stat=a+1,b-2]

      • <頁面代號> 必須為數字頁面 ID,或使用帶字母尾碼的變體(例如 2a2b2c);或特殊值 END

      • 新功能:支援 2a, 2b, 2c 等格式,其中數字部分(如 2)為實際跳轉的頁面,字母部分(如 a, b, c)僅用於區分不同的加成或描述變體(實際跳轉到 2)。

      • <頁面代號>END 時,介面會提供「.st end」按鈕以結束遊戲。

      • stat= 僅支援整數加減,並在成功前往該選項之目標頁面時套用(例:Cuteness+1,Energy-2)。

新功能:多選項同頁面跳轉

使用 2a, 2b, 2c 等格式可以讓多個選項都跳轉到同一個頁面(如頁面 2),但每個選項可以有不同的加成效果:

當玩家使用 .st goto 2a.st goto 2b.st goto 2c 時:

  • 都會跳轉到頁面 2

  • 但會分別獲得不同的加成:淘氣度+1、萌度+1、活力+1

運算式(Expressions)

  • 條件以小型、類 JS 的子集合為語法,運行於 scope(variables + stats + playerVariables

  • 支援運算子:&& || ! < <= > >= == === != !== + - * / % ()

  • 安全限制:不允許任何函式呼叫;不可存取 globalThisglobalprocessthisFunctionconstructorrequire 等識別字。

    • 範例:if=Cuteness>=8 && Energy>3

  • 支援一元否定 !expr(可搭配括號以控制優先順序)。

    • 範例:if=(Strength>5) && !(Agility>5)

擲骰(Dice)

  • 在條件與賦值運算式中,可直接使用 xDy 字面量,會在運算前擲骰並以總和值替換,例如:

    • if=2d20>25

    • [set] luck=3d6+2

    • 允許的範圍:x 1100、y 110000;超出將被夾在此範圍內。

條件賦值(Conditional Set)

  • 支援在 [set] 上使用條件選項:[set|if=<expr>] key=<expr>

  • 結合擲骰,可實作常見的檢定流程。

範例:

範例頁面(Example Page)

結局頁(Ending Page)

佔位符(Placeholders)

  • [text] 內使用 {key} 會依序從 playerVariablesstatsvariables 取值並套入(優先順序如前,後者可覆蓋前者)。

  • 若找不到對應鍵,將保留原樣(例如 {unknown_key} 會原樣輸出)。

註:相容性與限制補充

  • 目前不支援以純字串作為頁面 ID;請使用數字頁面 ID(例如 0, 1, 2)。

  • [set] 行允許在值的後方加上行尾 // 註解,匯入時該註解會被忽略,不影響賦值內容。

往返轉換(Round Trip)

  • 匯入文字(於 Discord 夾帶檔案):傳送 .st import <alias> [title] 並附上 .txt(RUN_DESIGN)或 .json 檔案

  • 更新既有劇本:.st update <alias> [title] 並附上新檔案

  • 匯出文字:.st exportfile <alias>(機器人將以私訊傳送文字檔)

  • 驗證可逆:.st verify <alias>

正規化(Normalization)

  • 編譯器會將緊鄰的 [random] 與其後的第一行 [text] 合併解釋為「機率顯示」。

  • 匯出時,若頁面是結局頁,[ending] 會緊跟在該頁 [label] 之下,以維持可逆性。

慣例(Conventions)

  • 開點頁面[label] 0 為故事的起始頁面,遊戲開始時會自動載入此頁面。若需要可在編譯後的 JSON 再行設定。

  • 頁面 ID 限制:只能使用數字作為頁面 ID。

  • 說話者為可選;示例採用純文字。

  • 若需在內文中加入隨機性,請於欲影響的 [text] 之前「緊貼」放置 [random] <percent>%(percent 為整數)。

  • 若需在選項上改變屬性值,使用 stat=a+1,b-2(僅支援整數加減)。

  • 若需多個選項跳轉到同一頁面但有不同的加成效果,使用 2a, 2b, 2c 等格式。

最佳實務(Best Practices)

  • 為可讀性建議使用數字且連續的 ID

  • 條件判斷儘量簡單並以已定義的鍵為基礎

  • 避免過長的行;可拆分成多個 [text]

  • 確保每個結局頁面都提供重新開始或結束的選項

  • 善用 2a, 2b, 2c 格式來創建有不同加成的選項

限制(Limits)

  • 最多頁數:400

  • 每段文字(每一行 [text],包含結局文字)最長 500 字

  • 至少需包含一個帶有 [ending] 的頁面

  • 匯入/更新之附件大小上限:約 1 MB

  • 頁面 ID 只能使用數字

更多範例(More Examples)

說話者(Speakers)與條件鏈

說話者為可選欄位,渲染時僅作為資料欄位保存,不影響文字輸出。

隨機顯示(Random)

[random] <percent>% 僅作用於其後第一行 [text],編譯器在匯出時會保持可逆性。

內嵌擲骰(Dice)與條件檢定

在運算式中可使用 xDy 字面量;在文字中可用 {xDy} 直接內嵌擲骰,顯示總和。

條件賦值(Conditional Set)與字串值

RHS 以引號包裝時會被視為字串常值;否則會嘗試以表達式求值。

多個選項同頁面跳轉(帶加成)

玩家輸入 .st goto 2a/2b/2c 皆會抵達頁面 2,但各自套用不同的加成。

獨立條件顯示(ifs)

使用 ifs[text] 不會與相鄰的 if/else 形成條件鏈,命中就顯示,可同時出現多行。

結局區塊的條件鏈

結局的多行 [text|if=...] 與一行 [text|else] 形成條件鏈,僅顯示第一個符合條件者;可在其上方書寫無條件前言文字。

佔位符的優先順序與巢狀

{key} 查找順序為 playerVariablesstatsvariables。字串值內若再包含 {...},會進行一次巢狀展開。

Last updated