Larger Than Infinity by Zul Nadzri reveals the results of Zul's experiments with White Noise.
Any feedback would be greatly appreciated.
;redcode-nano ;name medusa's mirror ;author John Metcalf ;strategy evolved using TEV12 with hints ;assert CORESIZE==80 mov.i <46, $11 spl.i #-4, {56 mov.i <36, {79 mov.i {79, {54 djn.f $78, {59 end
@dir /b /o-d *.red >w.evo
@echo END >>w.evo
@gwbasic tev12
@erase ?.evo
10 P$="pmars -s 80 -p 80 -c 800 -l 5 -b -k -P":R=142:L=5:P=25:K=80
20 O$="mov.imov.ispl.bdjn.f;xxxx":M$="<@>{*}$#"
30 DIM W$(99),A$(L,P),B$(L,P),C(L,P),D$(L,P),E(L,P),S(P):RANDOMIZE TIMER
40 W=0:OPEN "w.evo" FOR INPUT AS #1:M=LEN(M$):q=0:h=1
50 INPUT #1,W$(W+1):IF W$(W+1)<>"END" THEN W=W+1:GOTO 50 ELSE CLOSE #1
60 q=(q mod p)+1:J=1:FOR I=2 TO P:IF S(I)<s(j) THEN j=i
70 NEXT i:FOR I=1 TO L:A$(I,J)=A$(I,q):B$(I,J)=B$(I,q):C(I,J)=C(I,q)
80 D$(I,J)=D$(I,q):E(I,J)=E(I,q):NEXT I:S(J)=s(q)
90 Z=S(Q)/H:FOR I=1 TO L:IF RND*Z<.3 THEN C(I,q)=INT(RND*K)
100 IF RND*Z<.3 THEN E(I,q)=INT(RND*K)
110 Z$=MID$(M$,INT(RND*M)+1,1):IF RND*Z<.3 THEN B$(I,q)=Z$
120 IF RND*Z<.3 THEN D$(I,q)=","+Z$
130 IF RND*Z<.1 THEN A$(I,q)=MID$(O$,INT(RND*LEN(O$)/5)*5+1,5)+" "
140 NEXT I:OPEN "w.evo" FOR OUTPUT AS #1:FOR I=1 TO L
150 PRINT #1,A$(I,q);B$(I,q);C(I,q);D$(I,q);E(I,q):NEXT I:CLOSE #1
160 s(q)=0:FOR I=1 TO W:SHELL P$+" w.evo "+W$(I)+" >s.evo"
170 OPEN "s.evo" FOR INPUT AS #1:INPUT #1,Z$:CLOSE #1:Z=1
180 IF MID$(Z$,Z,1)<>" " THEN Z=Z+1:GOTO 180
190 s(q)=s(q)+3*VAL(LEFT$(Z$,Z))+VAL(RIGHT$(Z$,LEN(Z$)-Z)):NEXT I
200 IF s(q)>H THEN H=s(q):SHELL "copy w.evo best.war"
210 goto 60
;redcode-nano ;name wrath of the machines ;author John Metcalf ;strategy evolved mad mad bomber ;strategy 28 hours with TEV 1.2K ;assert CORESIZE==80 spl.b #76, {32 mov.i >11, {49 mov.i }79, {76 mov.i <64, {29 djn.f $-3, {58 end
@dir /b /o-d *.red >w.evo @echo END >>w.evo @gwbasic tev0 @erase ?.evo
10 P$="pmars -s 80 -p 80 -c 800 -l 5 -b -k -P":R=142:L=5:P=20:K=80 20 O$="mov.ispl.bdjn.f;xxxx":M$="<@>{*}$#" 30 DIM W$(500),A$(L,P),B$(L,P),C(L,P),D$(L,P),E(L,P),S(P):RANDOMIZE TIMER 40 W=0:OPEN "w.evo" FOR INPUT AS #1:M=LEN(M$):H=80 50 INPUT #1,W$(W+1):IF W$(W+1)<>"END" THEN W=W+1:GOTO 50 ELSE CLOSE #1 60 FOR I=1 TO L:IF RND*S(1)/H<.6/L THEN C(I,1)=(C(I,1)+INT((RND-RND)*K))MOD K 70 IF RND*S(1)/H<.7/L THEN E(I,1)=(E(I,1)+INT((RND-RND)*K))MOD K 80 IF RND*S(1)/H<.3/L THEN B$(I,1)=MID$(M$,INT(RND*M)+1,1) 90 IF RND*S(1)/H<.4/L THEN D$(I,1)=MID$(M$,INT(RND*M)+1,1) 100 IF RND*S(1)/H<.3/L THEN A$(I,1)=MID$(O$,INT(RND*LEN(O$)/5)*5+1,5) 110 NEXT I 120 OPEN "w.evo" FOR OUTPUT AS #1:FOR I=1 TO L 130 PRINT #1,A$(I,1)+" "+B$(I,1);C(I,1);","+D$(I,1);E(I,1):NEXT I:CLOSE #1 140 S(1)=0:FOR I=1 TO W:SHELL P$+" w.evo "+W$(I)+" >s.evo" 150 OPEN "s.evo" FOR INPUT AS #1:INPUT #1,Z$:CLOSE #1:Z=1 160 IF MID$(Z$,Z,1)<>" " THEN Z=Z+1:GOTO 160 170 S(1)=S(1)+3*VAL(LEFT$(Z$,Z))+VAL(RIGHT$(Z$,LEN(Z$)-Z)) 180 IF I>W/5 AND S(1)*150/H<I*R THEN 240 ELSE NEXT I 190 S(1)=100*S(1)/(W*R):IF S(1)>H THEN H=S(1):SHELL "copy w.evo best.war" 200 FOR J=2 TO P:IF S(J)>S(1) THEN NEXT J:GOTO 230 210 FOR I=1 TO L:A$(I,J)=A$(I,1):B$(I,J)=B$(I,1):C(I,J)=C(I,1) 220 D$(I,J)=D$(I,1):E(I,J)=E(I,1):NEXT I:S(J)=S(1) 230 IF S(1)>H*.9 THEN 60 240 Z=INT(RND*(P-1))+2:FOR I=1 TO L:A$(I,1)=A$(I,Z):B$(I,1)=B$(I,Z) 250 C(I,1)=C(I,Z):D$(I,1)=D$(I,Z):E(I,1)=E(I,Z):NEXT I:S(1)=S(Z):GOTO 60
Program "Incredible!" (length 5) by "John Metcalf"
;strategy tweaked away one instruction
Last battle concluded at : Sun Dec 1 17:26:58 EST 2002
# %W/ %L/ %T Name Author Score Age
1 40/ 42/ 18 Herbal Avenger Michal Janeczek 139 18
2 39/ 42/ 19 Combatra David Moore 136 7
3 24/ 11/ 65 Blowrag Metcalf/Schmidt 136 62
4 35/ 35/ 30 Mantrap Arcade Dave Hillis 136 2
5 24/ 13/ 64 Incredible! John Metcalf 135 1
6 28/ 22/ 51 Reepicheep Grabun/Metcalf 133 135
7 27/ 22/ 52 Son of Vain Oversby/Pihlaja 132 106
8 33/ 34/ 33 Cyanide Excuse Dave Hillis 131 8
9 25/ 22/ 53 Paperazor Christian Schmidt 129 79
10 28/ 27/ 45 Uninvited John Metcalf 129 125
;redcode-94
;name length exploit
;author John Metcalf
;strategy demonstrate how to hide a program's true length
;assert CORESIZE == 8000
for ROUNDS < 5
;the front-end sees this code
for 5
dat 0, 0
rof
rof
for ROUNDS > 4
;the back-end sees this code
;insert warrior code here
rof
end
;redcode-nano ;name plateau ;author John Metcalf ;strategy evolved mad mad bomber ;strategy hit a plateau after 4 hours ;assert CORESIZE==80 spl.b #16, <28 mov.i <-15, {-35 mov.i {-1, {-3 mov.i <-28, <25 djn.f $-3, <33 endThe evolver creates warriors through pure evolution. The soup is seeded with random instructions and evolution is guided only by performance against the 2007 Nano Benchmark. If a benchmark test is scoring below a certain threshold, the test breaks out early.
DJN
.DJN X, Y
uses Y as a pointer into memory. 1 is subtracted from the value stored at location Y. If the result is non-zero, DJN
jumps to X. Here's an example demonstrating how to copy A to B using DJN
:DJN 0, TEMP
DJN 0, B
DJN 1, TEMP
DJN -1, A
DJN 1, A
DJN 1, B
DJN -2, TEMP
MOV
!DJN
is Turing complete by equivalence to SUBLEQ A, B, C:DJN 0, TEMP
DJN 1, TEMP
DJN 10, B
DJN 4, SCRATCH
DJN 3, SCRATCH
DJN 1, TEMP
DJN 1, B
DJN -2, A
DJN 1, A
DJN -1, TEMP
DJN C, SCRATCH
DJN C, SCRATCH
DJN -11, A
DJN 1, A
DJN -1, TEMP
Here are the top resources to discover more about Core War:
dat lit ; push 1111A more compact representation would be to store addresses in both the a-field and b-field. Unfortunately this would be at the expense of more complex flow control:
dat 1111
dat lit ; push 1234
dat 1234
dat plus ; add TOS to 2OS
dat udot ; display TOS
dat lit, 1111I'm open to suggestions how the interpreter can use the compact representation without causing too many difficulties.
dat lit, 1234
dat plus, udot
Ins | Description |
---|---|
- | subtract TOS from 2OS |
+ | add TOS to 2OS |
* | multiply TOS by 2OS |
U. | print TOS as an unsigned number |
SPACE | print a space |
DUP | copy TOS |
DROP | remove TOS |
ABS | replace TOS with its absolute value |
NEGATE | replace TOS with -TOS |
! | 2OS is stored at the address in TOS |
+! | 2OS is added to the address in TOS |
@ | fetch the value at the address in TOS |
= | TRUE if TOS=2OS, else FALSE |
SWAP | exchange TOS with 2OS |
DEPTH | number of elements on stack |
BEGIN | start of BEGIN .. UNTIL structure |
UNTIL | if TRUE, return to matching BEGIN |
DO | start of DO .. LOOP structure |
LOOP | inc counter, jump to DO if below limit |
org next
stack dat 0, 0
; LIT - place the next value on the stack
lit mov.b }ip, <stack
jmp next
; + - remove 2OS and TOS and put their sum on stack
plus add.b >stack, @stack
jmp next
; U. - remove and display TOS as an unsigned number
udot mov.b @stack, <stack
div #10, >stack
mod #10, @stack
add #48, @stack
add #1, udcount
jmn udot, <stack
add #1, stack
udloop sts >stack, 0
udcount djn udloop, #0
sts.a #32, 0
jmp next
; --------------------------------
next
ip jmp @prog, }ip
; --------------------------------
prog
dat lit ; push 1111
dat 1111
dat lit ; push 1234
dat 1234
dat plus ; add TOS to 2OS
dat udot ; display TOS
end
Ins | Description |
---|---|
: | copy the top stack entry |
! | drop the top stack entry |
~ | swap the top two stack entries |
* | join the top two stack entries |
S | display then drop the top stack entry |
^ | drop then run the top stack entry |
a | enclose the top stack entry in parentheses |
( ) | add a new stack entry |
dot slt @stack, #1+CORESIZE/2Unfortunately, the code is pretty ugly. Can you suggest a more elegant solution?
sts.a #45, 0
slt @stack, #1+CORESIZE/2
mul #-1, @stack
udot mov.b @stack, <stack
div.b base, >stack
mod.b base, @stack
slt @stack, #10
add #7, @stack
add #48, @stack
add #1, udcount
jmn udot, <stack
add #1, stack
udloop sts >stack, 0
udcount djn udloop, #0
base dat 10
Ins | Macro | Description |
---|---|---|
< | lt | move pointer left |
> | gt | move pointer right |
+ | inc | increment memory cell at pointer |
- | dec | decrement memory cell at pointer |
. | out | output a character from the cell at pointer |
, | in | input a character and store in cell at pointer |
[ | op | jump past matching ] if cell at pointer is 0 |
] | cl | jump to matching [ if cell at pointer not 0 |
lt equ sub #1, ptr
gt equ add #1, ptr
inc equ add #1, @ptr
dec equ sub #1, @ptr
out equ sts @ptr, 0
in equ lds @ptr, 0
op equ jmz 0, @ptr
cl equ jmn 2, @ptr
org seek
ptr mov.ba #0, #prog
find sne.a #2, *ptr
sub #1, count
sne.a #0, }ptr
jmp find, >count
count jmn find, #0
mov.a ptr, @ptr
sub.ba ptr, >ptr
mov.ba ptr, {ptr
sub.a ptr, *ptr
seek jmn.a seek, >ptr
jmn ptr, <ptr
prog
org rssbint
rssbint mov.ba >ip, ip ; load next instruction
mov #0, zero ; set zero
sne.a #3, ip ; handle input
lds in, 0
sne.a #4, ip ; handle output
sts acc, 0
mov acc, out
add out, out
slt *ip, acc ; set flag for skip
mov #2, skip
sub.b acc, *ip ; acc, *ip = *ip - acc
mov.b *ip, acc
skip djn noskip, #1 ; skip if required
nop >ip, >skip
noskip slt #7900, @ip ; protect interpreter
jmn rssbint, ip ; loop until ip = 0
; --------------------------------------
ip dat 5 ; instruction pointer
acc dat 0 ; accumulator
zero dat 0 ; always 0
in dat 0 ; character input
out dat 0 ; character output
; --------------------------------------
loop dat -ip+ acc ; acc = character from ptr
ptr dat -ip+ hello
dat -ip+ out ; display character
dat -ip+ zero ; acc = -acc
dat -ip+ zero ; always skipped
dat -ip+ sum ; subtract acc from sum
dat -ip+ ip ; skipped if sum is negative,
; otherwise jump to 0
one dat -ip+ acc ; subtract 1 from ptr
dat -ip+ one
dat -ip+ ptr
dat -ip+ acc ; jump to loop
dat -ip+ loopoff
dat -ip+ ip
loopoff dat -loop
sum dat -1116
dat 33 ; '!'
dat 100 ; 'd'
dat 108 ; 'l'
dat 114 ; 'r'
dat 111 ; 'o'
dat 87 ; 'W'
dat 32 ; ' '
dat 44 ; ','
dat 111 ; 'o'
dat 108 ; 'l'
dat 108 ; 'l'
dat 101 ; 'e'
hello dat 72 ; 'H'
end
PIN
and MAXPROCESSES
is forbidden. The maximum length is 200.call
/ ret
problem in Redcode. Unfortunately the offsets in multi-line-equates can be slightly out. In this solution, the offsets are adjusted the first time the call
is executed. Here's how it works:call routine
compiles as follows:mov #2-return, <stack ; save return address
jmp callsub, 1+routine ; jump to callsub which adjusts the address
; b-field pointer is either correct or out by 1
callsub
then adjusts the pointer if necessary and moves it to the a-field of the jmp
:mov #2-return, <stack ; save return addressThe
jmp routine, 1+routine ; jump to routine, a-field is correct
jmp
now contains the correct offset and jumps directly to routine
in future.stack dat 0
call equ mov #2-return, <stack
equ jmp callsub, 1+
ret equ jmp return
return mov.b >stack, #0
jmp @return
callsub mov.b @stack, #0
add #return-callsub, callsub
mov.ba <callsub, @callsub
slt.b @callsub, #CORESIZE/2
jmp @callsub
djn.a @callsub, @callsub
call
/ ret
macros in Redcode so I can call subroutines. The obvious solution is as follows and doesn't work correctly:; this code is buggyUnfortunately, this only works for forward calls. The address offset is out by 1 for reverse calls and I can't find a simple fix. I've tried the following solutions, but I'm not particularly happy with any of them:
stack dat 0
call equ mov #2-return, <stack
equ jmp
ret equ jmp return
return mov.b >stack, #0
jmp @return
nop
to the top of all subroutines (extra code)call subroutine adjust
(ugly)