Starting with this post, I shall publish all my warriors of any
interest that have been pushed off the hills, so stay tuned in the
next few days! Today I don't have much time, so it's just one, but
important thing - my quickscanner written from scratch, q^i. So what
it achieves besides pushing qscan numeration into the complex plane?
- Way simpler than q^4 - I really don't like q^4's complex math
- Less qTabs (just one)
- Position-invariant - no dependence on position of qTab
- Maybe a minor advantage against warriors with q^4 (haven't done much
testing, but Red Birds with q^i had a higher score on the 94nop than
with q^4)
There's yet work to be done, as I haven't investigated things like
minimal scan separation and optimal constants. Also, presented below
is the full version, but actual warriors work better with the mini
version without some of the scans (wait for next posts to see
examples). It's been a while and I don't remember all the details, so
figure out how it works yourself!
------------------------------------------------------------------------
qbstep equ 7
qbhop equ -86
qbcnt equ 20
qxa equ 6980
qxb equ 2512
qa1 equ 5354
qa2 equ 5514
qb1 equ 6352
qb2 equ 4163
qstep equ 2379
nil equ (-CURLINE-1)
org qgo
boot jmp 0, 0
dat 0, 0
; --------
~~~~~~~~([ instant ])~~~~~~~~-------- ;
; [ 2
pairs ] ;
qgo sne found
+qxa , found+qxb
seq found+qxa
+qstep , found+qxb+qstep
jmp decide, 0
; --------~~~~~~~~([+0
cycles])~~~~~~~~-------- ;
; [ 8
pairs ] ;
sne found
+qxa*qa2 , found+qxb*qb2
seq found
+qxa*qa2+qstep , found+qxb*qb2+qstep
jmp dec0de, 0
sne found
+qxa*qa1 , found+qxb*qb1
seq found
+qxa*qa1+qstep , found+qxb*qb1+qstep
jmp dec0de, <dec1
sne found
+qxa*(qa2-1) , found+qxb*(qb2-1)
seq found
+qxa*(qa2-1)+qstep , found
+qxb*(qb2-1)+qstep
djn.f dec0de, qtab
sne found+
(qxa-1)*qa2 , found+(qxb-1)*qb2
seq found+
(qxa-1)*qa2+qstep , found+
(qxb-1)*qb2+qstep
djn.f dec0de, found
; --------~~~~~~~~([+1
cycle ])~~~~~~~~-------- ;
; [16
pairs ] ;
sne found
+qxa*((qa2*qb2)%CORESIZE) , found
+qxb*((qa2*qb2)%CORESIZE)
seq found+qxa*((qa2*qb2)%CORESIZE)
+qstep , found+qxb*((qa2*qb2)%CORESIZE)+qstep
jmp dec1, 0
sne found
+qxa*(((qa2-1)*qb2)%CORESIZE) , found
+qxb*(((qa2-1)*qb2)%CORESIZE)
seq found+qxa*(((qa2-1)*qb2)%CORESIZE)
+qstep , found+qxb*(((qa2-1)*qb2)%CORESIZE)+qstep
jmp dec1, {qtab
sne found
+qxa*(((qa2+1)*qb2)%CORESIZE) , found
+qxb*(((qa2+1)*qb2)%CORESIZE)
seq found+qxa*(((qa2+1)*qb2)%CORESIZE)
+qstep , found+qxb*(((qa2+1)*qb2)%CORESIZE)+qstep
jmp dec1, }qtab
sne found+qxa*((qa2*(qb2-1))
%CORESIZE) , found+qxb*((qa2*(qb2-1))%CORESIZE)
seq found+qxa*((qa2*(qb2-1))%CORESIZE)
+qstep , found+qxb*((qa2*(qb2-1))%CORESIZE)+qstep
jmp dec1, <qtab
sne found+qxa*((qa2*(qb2+1))
%CORESIZE) , found+qxb*((qa2*(qb2+1))%CORESIZE)
seq found+qxa*((qa2*(qb2+1))%CORESIZE)
+qstep , found+qxb*((qa2*(qb2+1))%CORESIZE)+qstep
jmp dec1, >qtab
sne found
+qxa*((qa2*qb1)%CORESIZE) , found
+qxb*((qa1*qb2)%CORESIZE)
seq found+qxa*((qa2*qb1)%CORESIZE)
+qstep , found+qxb*((qa1*qb2)%CORESIZE)+qstep
jmp dec1, {dec1
sne found+qxa*((qa2*(qb1-1))
%CORESIZE) , found+qxb*(((qa1-1)*qb2)%CORESIZE)
seq found+qxa*((qa2*(qb1-1))%CORESIZE)
+qstep , found+qxb*(((qa1-1)*qb2)%CORESIZE)+qstep
djn.f dec1, {dec1
sne found
+qxa*((qa1*qb1)%CORESIZE) , found
+qxb*((qa1*qb1)%CORESIZE)
seq found+qxa*((qa1*qb1)%CORESIZE)
+qstep , found+qxb*((qa1*qb1)%CORESIZE)+qstep
djn.f dec1, dec1
;(2 + 8 + 16) * 2 = 52 scans total
jmp boot, 0
dec1 mul.x qtab, qtab
dec0de mul @dec1, found
;decide - 1 + 0.5 + 1 + 0.5 = 3 cycles (average)
decide sne *found, @found
add qinc, found
seq nil, *found
mov.x found, found
qbloop mov qbomb, @found
found mov qxa, }qxb
add #qbstep, found
djn qbloop, #qbcnt
jmp boot, 0
qbomb dat >qbhop, >1
dat qa1, qb1
qtab dat qa2, qb2
qinc dat qstep, qstep
many thanks for sharing your codes with us :-)
Am really curious about your warriors.
Happy New Year
Happy New Year to you! And thanks for publishing :-)
> It's been a while and I don't remember all the details, so
> figure out how it works yourself!
Thanks much :-/
Actually it is not that hard to decipher, since you avoided using the
'difficult math' that makes q4 work.
In qi's decoder we find:
decide sne *found, @found
add qinc, found
seq nil, *found
mov.x found, found
This is typical of a qscan using sne,seq pairs where the decoder must
select between the four scanned locations, whereas in q4 two of the
locations are eliminated by the math.
Decoding takes 2-6 instructions, a little longer on average than q4
which takes mostly 3. That said, it is a long (26 pairs), dense (all
sne/seq pairs) qscan with minimal table overhead.
The holy grail of course is to have all sne/seq pairs, 3 or fewer
decoding steps, and no table overhead.
You stated that qi pushes us into the complex plane. Since redcode
has no negative numbers, how does it do that?
Looking forward to more great code :-)
P. Kline
Here is a form that answers 2 of the three goals:
q1 sne fnd+((m1+0)*(m2+0))+step*0 ,fnd+((m1+0)*(m2+0))+step*1
seq fnd+((m1+0)*(m2+0))+step*2 ,fnd+((m1+0)*(m2+0))+step*3
jmp dec , dec
sne fnd+((m1-1)*(m2+0))+step*0 ,fnd+((m1-1)*(m2+0))+step*1
seq fnd+((m1-1)*(m2+0))+step*2 ,fnd+((m1-1)*(m2+0))+step*3
jmp dec ,{dec
sne fnd+((m1+1)*(m2+0))+step*0 ,fnd+((m1+1)*(m2+0))+step*1
seq fnd+((m1+1)*(m2+0))+step*2 ,fnd+((m1+1)*(m2+0))+step*3
jmp dec ,}dec
sne fnd+((m2-1)*(m1+0))+step*0 ,fnd+((m2-1)*(m1+0))+step*1
seq fnd+((m2-1)*(m1+0))+step*2 ,fnd+((m2-1)*(m1+0))+step*3
jmp dec ,<dec
sne fnd+((m2+1)*(m1+0))+step*0 ,fnd+((m2+1)*(m1+0))+step*1
seq fnd+((m2+1)*(m1+0))+step*2 ,fnd+((m2+1)*(m1+0))+step*3
jmp dec ,>dec
sne fnd+((m1-1)*(m2-1))+step*0 ,fnd+((m1-1)*(m2-1))+step*1
seq fnd+((m1-1)*(m2-1))+step*2 ,fnd+((m1-1)*(m2-1))+step*3
djn.f dec ,dec
dec mul.x #m1 ,#m2
add dec ,fnd
sne *fnd ,@fnd
add #step ,fnd
sne null ,@fnd
add #step ,fnd
mov qB ,@fnd
fnd mov 0 ,step
add #x ,fnd
djn -3 ,#qc
jmp boot
I do not know if any workable m1/m2 combinations exist, but they
probably do.
This form has no qtab or qinc requirement, uses no funny math, but has
a little slower decoder, 4-6 steps.
It can be doubled in size by adding a line before 'dec':
add #mx ,dec
The second block of scans would jump to this line instead of to 'dec',
and the scan lines would replace 'm2' with 'm2+mx'.
It could be extended again (72 locations!) by placing an 'add #my,dec'
line before the third block of scans which would replace 'm2' with
'm2+my' and all jump to 'dec'.
P. Kline
dec mul.x #m1 ,#m2
add dec ,fnd
sne *fnd ,@fnd
add #step ,fnd
sne null ,@fnd
sub #step ,fnd
mov qB ,@fnd
fnd mov 0 ,@step
add #x ,fnd
djn -3 ,#qc
jmp boot
P. Kline
Sorry, that was also incorrect, how about this one:
dec mul.x #m1 ,#m2
add dec ,fnd
sne *fnd ,@fnd
add #step ,fnd
sne null ,@fnd
add #step ,fnd
> > dec mul.x #m1 ,#m2
> dec mul.x #m1 ,#m2
> > add dec ,fnd
> add dec ,fnd
> > sne *fnd ,@fnd
> sne *fnd ,@fnd
> > add #step ,fnd
> add #step ,fnd
> > sne null ,@fnd
> sne null ,@fnd
Difference:
> > sub #step ,fnd
> add #step ,fnd
> > mov qB ,@fnd
> mov qB ,@fnd
> > fnd mov 0 ,@step
> fnd mov 0 ,@step
> > add #x ,fnd
> add #x ,fnd
> > djn -3 ,#qc
> djn -3 ,#qc
> > jmp boot
> jmp boot
(I was reading it for about 5 minutes before spotting it)