There are two distinct prototypes for scanners. They are B-scanner and CMP-scanner. Their names were derived from their functions that do scanning. B-scanners detect their opponent by searching for any non-zero B-field in their code. CMP-scanners provide more rigid detection by comparing (CMP) for any non-identical instructions between two different locations. In the extent of their functional differences, both kinds of scanners avoid self-attack in interestingly different manner. (For further detail, see Comparison between B-scanners and CMP-scanners).
One of B-scanners' duties might be as follow:
; ... B-scan
; ... throw self-splitting instructions
; ... redo before finish
; ... core-clear
scan ADD #const, ptr
JMZ scan, ptr
During scanning phase, the scanner shouldn't be mistaken with any of its
own codes. An easy way to do it is to add SLT after JMZ, e.g:
scan ADD #const, ptr
JMZ scan, ptr
SLT #num, ptr ; num is number of codes...
; ...in-between ptr and last line
MOV jmp_i, @ptr
MOV spl_i, <ptr
spl_i refers to SPL 0 and jmp_i refers to JMP -1.
JMN scan, scan
SPL 0, 0
MOV dat_i, <-1
JMP -1, 0
; name B-scanner 1
const EQU 3094
init EQU scan
scan ADD #const, ptr
ptr JMZ scan, ptr+init
SLT #dat_i, ptr
throw MOV jmp_i, @ptr
MOV spl_i, <ptr ; pointer is decremented by 1
ADD #1, ptr ; needed to readjust the pointer
redo JMN scan, scan
spl_i SPL 0, 0
MOV dat_i, <-1
jmp_i JMP -1, 0
dat_i END scan
Here is a much more elegant solution to B-scanner, blatantly taken from
a successful classical B-scanner:
B-scanner live in vain.
; name B-scanner 2
const EQU 2234
init EQU scan
scan ADD #const, @2
JMZ scan, @ptr ; hit here
throw MOV jmp_i, @ptr
ptr MOV spl_i, <init+ptr
redo JMN scan, scan
spl_i SPL 0, 0
MOV dat_i, <-1
jmp_i JMP -1, 0
dat_i END scan
The SLT instruction has been dropped off but this program performs
much better. Note that the warrior scans in modulo 2 or one for
every two instructions. Also note that the warrior structure is aligned
such as the B-scanner will scan zero B-field in its own code. This
is how it avoids winding up its own code. There is but one instruction:
the second one that will be read as non-zero when it reads its own code.
This instruction is the indicator for this warrior to begin its core-clear.
CMP-scanners might as well fall into two smaller divisions. Their difference is in the way they handle two non-identical instructions. Their choices are based on their scanning gap. The CMP-scanner with large/medium scanning gap assumes the following: "if it is not the first instruction, then the second one is part of opponent's". It then takes the next step (detailed below) to accomplish its duty. The other CMP-scanner (small scanning gap) assumes that they have touched the intersection of the opponent's code. It then throws in self-splitting instructions at all locations between the two locations it is comparing.
Most CMP-scanners have the following components:
; ... CMP-scan
; ... handle everything to do upon two non-identical instructions.
; ... redo before finish
; ... core-clear
update ADD loc_mod, scan
scan CMP loc, loc + gap
avoid SLT #num, scan
rescan JMP update, 0
The first instruction updates both A-field and B-field of scanning location.
The second instruction does the scanning. The third instruction provides a
mechanism to prevent damaging its own codes. The last instruction loops
back to label update in the case of identical instructions. Most scanners
use the form DJN update, <b-attack as their looping
instruction.
MOV #gap, cnt ; the constant gap is known
MOV spl_i, <scan
cnt DJN -1, #cnt
ADD #gap, scan ; re-adjust the B-field scan ptr
MOV jmp_i, @scan ; on B-field
MOV spl_i, <scan
SUB #gap-1, scan ; now B-field scan has the same value...
; ... as A-field scan
MOV jmp_i, @scan ; on A-field
MOV spl_i, <scan
ADD #gap+1, scan ;resume to B-field scan
MOV jmp_i, @scan
MOV spl_i, <scan
ADD loc_mod2, scan
The last method is intriguing to know. In normal scanning (instruction 1 - 4), both location pointers are updated as from E-F to C-D to A-B ... (below).
* * * * * *
A B C D E F
When it detects different instructions, e.g between E and F, it changes
its scanning pointers as from E-F to D-E. The purpose is to provide way
to access the A-Field.
JMN update, update
; name CMP-scanner (small) ; name CMP-scanner (large)
gap EQU 12 gap EQU 49
const EQU -28 const EQU -98
init EQU update+const init EQU update+const2
const2 EQU -49
update ADD loc_mod, scan update ADD loc_mod, scan
scan CMP init-gap, init scan CMP init-gap, init
SLT #last-update, scan SLT #last-update, scan
rescan DJN update, <6000 rescan DJN update, <6000
MOV spl_i, <scan MOV jmp_i, @scan
cnt DJN -1, #cnt MOV spl_i, <scan
MOV #gap, cnt ADD mod_2, scan
ADD #gap, scan redo JMN scan, scan
redo JMN update, update spl_i SPL 0
spl_i SPL 0 mod_2 MOV const2, <const2+1
loc_mod MOV const, <const jmp_i JMP -1
last END scan loc_mod DAT #const, #const
END scan