复制器(第一部分)

作为本周的 Hint,我先从我更喜欢的而且可以做得更好的战士类型开始,那就是复制者(replicator)或纸(paper);这类战士依靠数量优势来战胜敌人。 纸战士,和其他战士一样,从游戏开始到现在已经发展了很多;目前他们几乎都使用所谓的“丝绸(silk)”风格,即在复制之前进行分裂。这只能在 94 规则下完成,因为它需要后增量和 a 字段寻址。现在让我们来看一个非常简单的家伙。

start   spl     1
        mov     -1,     0       ;生成 3 个并行进程

1 silk  spl.a   @0,     100     ;拆分
2       mov.i   }silk,  >silk   ;复制
3       jmp.a   silk,   {silk   ;重复此操作并重置指针

前两行代码会生成 3 个进程,它们依次执行同一行代码,然后再执行下一行。第一行代码会创建另一个进程来执行从 start+1 开始的行,然后进程 1 将 start 行复制到 mov 行,进程 2 进行拆分,并添加另一个进程来执行 silk。生成精确数量的并行进程的更简单方法是将所需数量转换为二进制 3 -> 11,再减去 1 -> 10,对于每个 1 使用一个spl 1,对于每个 0 使用一个mov -1, 0。实际操作比解释要简单得多。为了让战士工作,我们需要的进程数量至少要与要复制的行数一样多。

让我们回到我们的战士;现在我们有三个进程正在执行 line1,它们在此处发生分裂,即在 a 字段地址,即第 0 行 b 字段所指向的地址,它们正在执行的行的 b 字段,相隔 100 个位置。当所有这三个进程都执行完这一行时,另外三个进程准备好执行第 silk+100 行,这里没有可执行的行,但我们还有一些时间,因为新生成的进程会在那些执行分裂的进程之后排队。

现在,前三个进程执行 line2,它们将 line1 的 a 字段所指向的内容移动到 line1 的 b 字段所指向的位置,然后它们同时递增 line1 的 a 和 b 字段。第一个进程将 line1 移动 100 个单元格,并使 line1 变为:1 silk spl.a @1, 101,这样它(译注:进程 2)就在上一行之后,将 line2 复制到距离“silk”101 个单元格的位置。

进程 3 执行的操作与复制 line3 相同。

现在轮到由 line1 创建的新进程来执行了,它们不再坐在一个空单元上,而是坐在由 line2 创建的 line1 的副本上,它们执行该副本并开始创建第三代副本。

前三个流程现在已到达 line3,现在战士已经以这种方式进行了修改

1 silk  spl.a   @3,     102
2       mov.i   }silk,  >silk
3       jmp.a   silk,   {silk

line3 的 a 字段是跳转的地址,而 b 字段会递减第 1 行的 a 字段,以便战士可以继续分裂和复制。

这个并不是真正的战士,它的攻击潜力太小,只是为了理解丝绸复制器的工作原理。简单的改进是增加一条附加行,这样副本就不会一个挨着一个地打包,并添加一些爆炸效果,让它变得稍微棘手一些。接下来的战士是 Paperone,它是我第一个进入 94 号山的战士,几个月前它曾在初级山称霸一时。 这与常见问题解答中的示例很相似(确实非常相似:-)),但为了让它运行良好,我必须对许多常量进行调整。

;redcode-94
;name Paperone
;author Beppe Bezzi
;strategy Silk replicator
;kill Paperone
;assert CORESIZE == 8000

start   spl     1,      <300    ;\
        spl     1,      <150    ;  生成7个连续的进程
        mov     -1,     0       ;/

silk    spl     3620,   #0      ;分裂为新副本
        mov.i   >-1,    }-1     ;将自身复制到新位置

;这是使用多个进程进行复制的另一种方法,另一种方法稍微好一些,因为我们可以减少要拆分的单元格数量,如果幸运的话,甚至可以消灭一个“小鬼”。

        mov.i   bomb,   >2005   ;线性轰炸
        mov.i   bomb,   }2042   ;A-间接轰炸,用于反吸血鬼
;放置的第一枚炸弹作为后续流的指针,铺设地毯。

        add.a   #50,     silk   ;计算新副本的距离
        jmp     silk,   <silk   ;重置源指针,制作新副本
bomb    dat.f   >2667,  >5334   ;反imp炸弹

这对三段式的 imp 环非常有效。在执行过程中,一次幸运的命中可以杀死许多其他的;至于其他类型的炸弹,至少就我而言,我们下次再讨论。

下次我们会讨论更高级的问题:另一种比这个更好的复制引擎,以及其他与纸相关的主题,如扩散常数、炸弹、策略等…

如有疑问,请发邮件至bezzi@iol.it,或者,如果你认为这会引起普遍兴趣,请发至 rec.games.corewar

欢迎任何有 hint 或战士要发布的人。