SubRoutine 是什么,可以吃吗?

 SubRoutine 是指、在剧本中的某处「呼叫」其他剧本段落的功能。SubRoutine呼叫出的剧本段落在执行完后、就会返回原来的剧本。

 这和宏(Macro) ( → 宏(Macro)的使用 ) 的功能类似、但 SubRoutine 一般用于执行比较复杂的操作、而 Macro 则相对简单一些。(例如, Macro 中禁止使用标签)

SubRoutine 的基本使用方法

 SubRoutine 功能,要求呼叫的剧本段必须是以 标签(Label)作为开头的。而段落结束,需要返回原来的剧本,则是以 return 指令作为结束符号的。要进行呼叫,请使用 call 指令。
 请看以下的例子。

[wait time=200]
*start|开始
[cm]
要呼叫其他的剧本了哦。[l][r]
[call target=*subroutine]
呼叫完毕,返回原来的地方了。
[s]

*subroutine
我是被呼叫的剧本段,而这就是 subroutine 功能了。[l][r]
点鼠标就会回到原来的地方了。[l][r]
[return]


 那么、执行这个例子的时候、「要呼叫其他的剧本了哦。」的消息后,会显示的是「我是被呼叫的剧本段。」、「点鼠标就会回到原来的地方了。」对话后点鼠标、会显示「呼叫完毕,返回原来的地方了。」。
 也就是说、call 指令执行后,除了跳转到呼叫的剧本段以外、也会将之前的剧本位置进行记录、而使用 return 指令后、就会返回之前记录的位置了 ( 这种自动记录被称为「Call Stack」)。
 在以上的例子里、*subroutine[return] 之间的段落,就是「subroutine」了。

 在一个 subroutine 段落中,还可以继续呼叫其他的 subroutine 。这种呼叫可以一层一层地积累 ( return 之前再进行 call ) ,没有呼叫层数的限制。(提示:就算是这样,多层套叠很容易导致出错。可能的话,请尽量用jump而不用call。)

 另外,除了「使用选项分歧」的场合之类需要用 [cm] 消除文字外,假如不是保存标签 (带有 | 的标签) ,呼叫出的段落标签后面不带 [cm] 也无所谓的。(提示:不用理会这句,[cm] 能不用尽量不用。)


 Call Stack 记录的内容包括:剧本档名、最近的标签名、以及 call 指令距离该标签的行数、而并不是记录 call 指令的具体内容。请注意:假如在 debug 之类的情况下,改变了剧本档,可能会导致返回的时候,无法回到正确的位置。
 另外,请尽量不要将 subroutine 的开头标签当作存储标记 (带有 | 的标签) 用,在 subroutine 中,也不要创建存储标记比较好。

subroutine 相关的注意事项

 在某个剧本段落中,使用 call 呼叫自身的话,就会陷入死循环。
 call 与 return 没有一一对应的话、Call Stack 就会不断积累、有可能会造成 return 之后不是返回预期的标签的错误、请千万注意。

 此外还有、请小心如下的例子


*subroutine
・・・
[if exp="f.flag1"][jump target=*otherplaces1][endif]
[if exp="f.flag2"][jump target=*otherplaces2][endif]
・・・
[return]

*otherplaces1
・・・
[return]

*otherplaces2
;这段落里没有 return 指令・・・


 这是 subroutine 段落中,又跳转到其他地方的情况。假如是跳转到 otherplaces1 的情况、由于有 return 的标记,保持了 call 〜 return 的平衡。但是、假如跳转到了 otherplaces2 、段落里没有 return 指令出现、这个 subroutine 就变成了「无法返回」的状态。也就是说、call 〜 return 的平衡没有维持。

 如果、执行完毕后不想返回原来的呼叫处、而是想要返回其他的地方、return 指令也拥有 storage 和 target 属性、利用它们可以返回到任意位置。