有时,您需要多次执行重复性操作。 在此情况下,大多数文本编辑器都提供了所谓的“宏”功能。 通常,这是指您录制某些操作,以便多次执行这些操作。 在YSokoban中,您可以使用简单的文本编辑器,通过复制/粘贴功能来完成此任务。 自版本1.500后,您可以在“宏”对话框的帮助下完成该任务。 按“宏”按钮可激活此功能。 在“宏”对话框中,要创建新宏,您可以直接以lurd表示法输入步骤,或按“开始记录”按钮。 然后,YSokoban会记录您的所有操作。 完成之后,请按“停止记录”按钮(“宏”将更改为“停止记录”),您的所有移动步骤将记录在新宏中。 现在,您就可以多次执行该宏,并且/或者在“名字”编辑框中输入名称,然后按“保存”按钮来保存宏。 “宏”对话框的左侧部分将显示保存的所有宏。 您可以从中选择并执行选定的某个宏。

执行宏

在YSokoban中,玩家可以通过按M和Shift-M键来执行新宏或选定的宏。

用鼠标点击已保存宏的列表,将完成以下操作:

重复计数器

如果将“*”(而不是数字)用作重复计数器,则会重复执行后续命令(或者宏或组),直到出错。例如:*(lddr)或*{macro}或只是*l。 如果使用*(lr)或*(ldru),小人将进行无限循环移动(如果有空间给它移动)。

严格检查

如果使用“&”而不是“*”作为重复计数器,那么YSokoban会对移动/推动进行严格检查。 这意味着,进行严格检查时,如果指定了移动,则它不会进行推动。 因此,对严格检查来说,“r”指向右移动,而不是向右推动,“R”指向右推动,而不只是移动。

撤销执行宏

可以在宏中指定撤销——用“~”表示撤销。

保存小人的位置(并返回该位置)

有时需要保存小人当前所在的位置,并在稍后返回该位置。

使用[x,y]可以指定推动位置的相对偏移值,或者用(x,y)指定用绝对值的坐标。 例如,+[3,4]将小人的推动位置增加3列4行(正数表示向右或向下,负数表示向左或向上)。 但+(3,4)会推动到绝对值坐标3,4这个位置。 稍后,^(或者@)会将小人移动到那里。

@[3,5]不会从堆栈中提取位置,小人只会相对于偏移值3,5移动(位置current_x+3和current_y+5)。 @(3,5)(请注意,是圆括号而不是方括号)会将小人移动到绝对位置3, 5。 (不会从堆栈中提取任何内容)

绝对坐标与alt-R中的坐标相同(用数字表示的标尺),第一个坐标为x(列),第二个坐标为y(行)。

总结上面这些符号的用途:

符号 操作 使用[x,y]时的操作 使用(x,y)时的操作
+ 将小人的目前位置保存到堆栈中 保存用相对坐标修改后的目前位置 保存绝对值坐标x, y
^ 从堆栈中提取位置, 然后去到这个位置 从堆栈中提取位置, 然后去到这个位置+相对坐标 从堆栈中提取位置, 然后去到绝对坐标的位置 (堆栈中的坐标资料完全没有用到)
# 从堆栈中提取位置(但不用这个位置) pop position from stack modify it with relative coordinates and push back to stack (modify top of stack)从堆栈中提取位置,用这个提取的位置+相对坐标,然后将这个新位置保存到堆栈中(修改堆栈顶部) 从堆栈中提取位置,然后将这个绝对坐标位置保存到堆栈中(修改堆栈顶部)
@ 从堆栈中提取位置, 然后去到这个位置(操作与^相同) 去目前人的位置+相对偏移值 (完全不提取堆栈中的位置) 去到绝对坐标的位置x,y (完全不提取堆栈中的位置)

条件执行

IF

在宏中可以使用类似于if-then-else这样的结构。语法为:

? expression : then-moves / else-moves ;

或者为

? expression : then-moves ;

因此,关键字符为?、 :、 / 和 ;

WHILE

在宏中可以使用类似于while-do-otherwise这样的结构。 语法为(与IF的语法相同,但使用两个?):

?? expression : do-moves / otherwise-moves ;

或者为

?? expression : do-moves ;

在此情况下,当表达式为真时,将重复执行do-move。 如果表达式为假,则执行otherwise-moves,但只执行一次。

条件表达式 - 简单比较

在条件表达式中,您可以通过指定单元格坐标来比较单元格的内容:

单元格可以与以下项目进行比较:

比较结果可以为:

组合条件表达式

可以使用二元运算符:

没有规定优先次序,因此,将从左至右执行&和|(如果需要优先级,请使用{和})

中断循环

要中断循环,请使用!

它会中断 ?? 循环或 &(...) 或 *(...)

用在 ?? 循环的 / ... ; 部分中时,它会中断外部循环(没有理由会中断??循环的/部分,因为该部分只执行一次)。

示例:

*(
  ...                // 一些移动步骤
  ? [1,1]=# : ! ;    // 这会中断 *( ... ) 循环
  ...                // 其它一些移动步骤
 )
*(
  ...                   // 一些移动步骤
  ?? [1,1]=_ : rd / ! ; // 这会向右向下移动,然后在 ?? 末尾中断 *( ... ) 循环
  ...                   // 其它一些移动步骤
 )

如果要中断多个嵌套循环,请连续使用几个!(不空格)。 例如:

*(
  *(
    ...                // 一些移动步骤
    ? [1,1]=# : !! ;    // 这会中断 *( *( ...) ) 循环
    ...                // 其它一些移动步骤
   )
 )

另一个示例:

*(
  ?? [1,1]=_ :
    ...                // 一些移动步骤
    ? [1,1]=# : !! ;    // this will break *( ) loop (actually both loops, the *(...) and the ?? ... ;)这会中断 *( )循环,实际为两个循环,  *(...) 和 ?? ... ;
    ...                // 其它一些移动步骤
  ;
 )

注释

宏文本可以包含C++注释,因此,宏会直接忽略一行中//之后的任何内容。

调试模式

处于调试模式时,将会逐步执行宏。 按“调试”按钮可以激活调试模式。

重置宏

要重置宏,请按“重置”按钮。

断点

在宏代码的某个位置插入“`”符号(后单引号)将会中断执行宏并激活“宏”对话框,即使当前宏未处理调试模式也是如此。 此时不会打开调试模式,因此,按“执行”将继续执行宏。 玩家可以切换到调试模式,继续逐步执行宏。


Created with Ywiki