嗨,
这次我们来谈谈 p-space,这是由 pmars08 实现的最后一个工具,它允许我们的战士根据比赛的历史来改变策略。
P-space 是一个受保护的内存区域,也就是说,每个战士都有自己的 p-space,无法读取或写入对手的 p-space。P-space 只存储数值,而非完整的指令,通过两个特定的指令 LDP 和 STP 来加载和存储 P-space。
在每一轮开始时,p-space 的第 0 个单元存储着上一轮的结果(比赛最初为-1),其他单元则保持上一轮结束时的值(比赛开始时为 0)。如果我们输了,值为 0;如果我们存活,值为存活的战士数量;在标准的一对一比赛中,这些值是 1 代表胜利,2 代表平局。
使用 p-space 的战士被称为 p-warriors 或 p-switchers;它们在一个 p-space 位置中存储当前使用的策略信息。在每轮结束时,它们评估上一轮的结果,并根据该结果(有时也根据其他轮次的结果)决定是继续当前策略还是切换到另一个,以期获得更好的表现。实际上,如果你是一位制定长期战略的将军,那么切换者就是你的上校,在战场上决定用什么来对抗你的对手。
需要重点说明的是,如果你没有可靠的战斗程序,即使是最好的切换程序也毫无价值;如果你的所有组件都输给了敌人,那么组合起来也会输,有时甚至更糟,因为你在开始时浪费了一些时间来计划本轮,并且需要将组件从庞大的战士主体中启动出去。
P-space 是中级玩家的工具,不适合初学者;除非你至少有两个中等水平的不同战士(例如石头和布),否则你无法从中获得任何好处。
现在,让我们看看如何组装一个 p-warrior;首先,我们需要好的组件,能够针对不同类型的敌人得分;我们拥有这些组件:
Paper01,用于对抗敌方轰炸机得分;juliet storm,用于击杀敌方扫描器;面对敌方布,我们并非毫无防备,布通常无法击败另一块布,因此我们应该能够:
很好地对抗轰炸机,感谢Paper01
很好地对抗扫描器,感谢juliet
与复制器战平,感谢Paper01。
一旦选择了我们的“手牌”,我们就需要组装“大脑”;除非你想做一些非常复杂的事情,否则切换程序并不难做。让我们看一个非常简单且成功的例子,Jack in the Box 的切换程序,主要有三个原因:这是我的一个战士,表现良好,而且是唯一一个公开发布的:-)
Jack 有两个组件,一个非常重的复制者(四倍的Paper01)和一个非常快速的轰炸机Tornado。
它的策略很简单:复制者在对阵敌方轰炸机时能得很多分,但由于体积大,相当容易被扫描器攻击;如果我们赢了或平局,一切顺利,我们就继续同样的策略;如果遇到糟糕的扫描器杀死了布,那么,Tornado就会出现,以其高速和彩色炸弹杀死它。
就是这样,确实非常简单。
_RES equ 0 ;pmars在这里加载结果
_STR equ 1 ;我在这里存储我的策略
res ldp.ab _RES, #0 ;加载上一场比赛结果
str ldp.a _STR, str1 ;加载正在使用的策略
sne.ab #0, res ;检查结果,胜利或平局都OK
lost add.a #1, str1 ;输了就改变
mod.a #2, str1 ;确保安全跳转
win stp.ab str1, _STR ;保存策略
str1 jmp @0, juliet
dat 0, paper
我们将上一场比赛的结果加载到 res.b,将我们使用的策略加载到 str1.a,然后将 res 与 0 比较,如果为零,我们就给策略加一,如果不为零(平局或胜利),我们就不加。mod 指令确保我们有一个 0 或 1 的值。
最后,我们为本轮保存新策略,并根据 str1.a 跳转到轰炸机或布。
我们在 7 个周期内完成,因此即使是 Qscan 也很难挂上。
现在来看代码,无非是获取战士、切换程序并将它们组合在一起。
最后一个注意事项,差点忘了,P-space 有一个“阴暗面”,洗脑。
你无法访问对手的 p-space,但如果你设法通过吸血鬼攻击迫使对手执行这些代码行或类似代码:
bwash spl 0,>1
stp.ab #0,#0
jmp -2,{-1
(通常这段代码与其他 spl 和核心清除代码一起使用)
它的 p-space 很快就会充满垃圾,并且在接下来的回合中,它的切换程序很难找到做出正确决策所需的信息。所以,当你制作切换程序时,别忘了考虑如果你的 p-space 出了问题会发生什么,并且,最重要的是,在执行跳转之前永远不要忘记对你的 STR 值进行 mod。
mod #2, 1
str jmp @0, paper ;一个字段保存策略
dat 0, juliet
如果你忘记了,你的战士可能不得不执行类似这样的指令:
str jmp @1234,paper
而你的得分可能会像 0/249/1 这样 :-(
以下是代码。我已将此战士提交到-94 和新手山,如果你有任何问题,或对结果感兴趣,请给我发邮件bezz@iol.it。
;redcode-b quiet
;name juliet and paper
;author M R Bremer, B. Bezzi
;strategy p-warrior for C.W. n.5 hint
;strategy switches juliet storm and Paper01
;kill juliet and paper
;assert CORESIZE == 8000
ptr EQU -1333
dest0 equ 2200
dest1 equ 3740
dest2 equ -1278
range equ 933
RES equ 0 ;here pmars loads results
STR equ 1 ;here I store my strategy
imp_sz equ 2667
org start
gate dat <-445, <-446
s spl #445, <-445
spl #0, <-446
mov {445-1, -445+2
add -3, -1
djn.f -2, <-2667-500
mov 32, <-20
go dat #0, #ptr
juliet mov {-1, <-1
mov {-2, <-2
mov {-3, <-3
mov {-4, <-4
mov {-5, <-5
mov {-6, <-6
mov gate, ptr+24
mov gate, ptr+24
spl @go, <4000
jmp boot, <4013
start
res ldp.ab RES, #0 ;load result last match
str ldp.a STR, str1 ;load strategy in use
sne.ab #0, res ;check result, win or tie OK
lost add.a #1, str1 ;lost change
mod.a #2, str1 ;secure jump
win stp.ab str1, _STR ;save strategy
str1 jmp @0, juliet
dat 0, paper
paper
spl 1, <300 ;\
spl 1, <400 ;-> generate 8 consecutive processes
spl 1, <500
silk spl @0, {dest0
mov.i }-1, >-1
silk1 spl @0, <dest1 ;split to new copy
mov.i }-1, >-1 ;copy self to new location
mov.i bomba, }range
mov {silk1, <silk2
silk2 jmp @0, >dest2
bomba dat <2667, <1
for MAXLENGTH-CURLINE-9
dat 0,0
rof
boot spl 1 ,#0
spl 1 ,#0
spl <0 ,#vector+1
djn.a @vector,#0
imp mov.i #0,imp_sz
jmp imp+imp_sz*7,imp+imp_sz*6
jmp imp+imp_sz*5,imp+imp_sz*4
jmp imp+imp_sz*3,imp+imp_sz*2
vector jmp imp+imp_sz ,imp
end