SGB_10.net CORE WARS Steve's Guide for Beginners Iss 10 (v2) Issue 7 looked at one (inefficient) way of copying blocks of code/data around. Issue 8 looked at another variation of copying and at the SPL command. Issue 9 looked at imp-rings and bombers and replicators (by proxy). ====== The first six issues took a week to produce. The next two took another week. The ninth took another week. As I get into it, it all slows down enormously. However I now reckon I have enough knowledge to analyse one of the warriors supplied with PMARS08 - RAVE.RED . ====== The source: ;redcode-94 ;name Rave ;author Stefan Strack ;strategy Carpet-bombing scanner based on Agony and Medusa's ;strategy (written in ICWS'94) ;strategy Submitted: @date@ ;assert CORESIZE==8000 CDIST equ 12 IVAL equ 42 FIRST equ scan+OFFSET+IVAL OFFSET equ (2*IVAL) DJNOFF equ -431 BOMBLEN equ CDIST+2 org comp scan sub.f incr,comp comp cmp.i FIRST,FIRST-CDIST ;larger number is A slt.a #incr-comp+BOMBLEN,comp ;compare to A-number djn.f scan,comp ;post-increment count djn.b split,#0 sub.ab #BOMBLEN,comp jmn.b scan,scan bomb spl.a 0,0 mov.i incr, -4 DJN.B $ -1, # 0 SUB.AB # 14, $ -6 JMN.B $ -8, $ -8 SPL.A $ 0, $ 0 MOV.I $ 1, < -4 DAT.F < -42, < -42 ====== First note that RAVE works with only ONE process until the last parts of its operation. ====== Rave starts by comparing two locations 100+ locns further on. Assuming that there is no opposing warrior there, the CMP (SkipifEQual) will find a matched pair of "empty" (DAT 0,0) instructions. Therefore CMP will skip to the DJN. The DJN pre-decrements a BNumber and uses that as a pointer to another locn where it decrements both A and B Numbers. I'll come back to exactly what gets decremented later. Just assume that it doesn't decrement to both zero, so the DJN jumps to "scan" At "scan", the CMP instruction at "comp" is modified, by subtracting -42 from both A & B Numbers (IE adding 42 to each). The loop of three instructions now repeats but inspecting locations 42 further on. What happens when the two locations aren't the same (IE it has found something - either code or bombs dropped by the enemy)? In that case it executes the SLT (SkipifLessThan) which skips if the immediate ANumber is less than the ANumber in the "comp" instruction. The immediate ANumber is a complicated expression that boils down to 24. This is a means of testing if the "enemy warrior" just detected is actually "yourself". (It is presumably 24 due to the length of RAVE (12) + the comparison separation (also 12). If it has detected itself, it rolls into the DJN and scans round core again, slightly offset as 42 is not a factor of 8000. If it has detected something else, it changes mode. See the appendix to this issue for a list of SLT visits (aka boming runs). ====== Before looking at what it does after the mode change, lets look in more detail at the DJN BOperand. This pre-decrements location "-308". Often this will be "empty" (DAT 0,0), in which case the pre-decrement will change it to DAT 0,-1 so the DJN will decrement the A & B Numbers of locn -309. Again assuming it was empty, this will go from DAT 0,0 to DAT -1,-1. Next time round the loop it will predecrement -308 to DAT 0,-2 and hence decrement and test locn -310. Then -311, then -312 etc. What does this achieve? Well it will usually jump unless enemy code / data is at that locn. If it is there then the code will be corrupted by the decrements. Additionally the pre-decrement acts as a sort of inefficient imp-gate. It is at -308 to stop it being too close to the main body of code as it will easily be found by scanners and bombers. (Note that the CMP will start comparing the decremented (DAT -1,-1) locations after a while. It is phased so that they are equal and we don't compare a decremented DAT -1,-1 with an undecremented DAT 0,0 too often.) (Without being presumptious, I wonder if perhaps this could be improved given the list in the appendix.) ====== Having scanned core and found something what does RAVE do now? It goes into a tight loop bombing 14 locations from the smaller of the two locns which differed. (MOV.AB sets up the loop count, MOV.I bombs, DJN.B loops.) (After the bombing run, the pointer COMP is repaired using SUB.AB .) It then tests the BNumber in "scan" which is a (nearly) constant "1", so it always jumps to "scan" and starts again, stepping on from where it got to looking for more code to attack. Note that the bomb is "SPL 0,0" which will cause the bombed location to malfunction and slow the enemy down by spliting lots of processes off. It won't actually kill the enemy. ====== This is the bit I missed in v1 of this issue. Thanks to those who explained what I was missing. The test of the BNumber in "scan" is not *always* 1. After some number of loops round the code, the ANumber in "comp" is "scan" ("comp-1"). This is interpreted as being enemy code rather than "myself", so the bombing run commences. The bombing run overwrites "scan" with the SPL bomb. When this happen, the JMN doesn't jump back to scan but switches into its final modes. ====== It executes SPL 0 which queues one process to the next instruction and one at SPL again. Thus there is a steady stream of processes being generated by this SPL. The process reaching the next instruction executes a MOV which puts a killing DAT at "count-1" and all locations before that, working backwards round core, clearing it. (This is a core clear.) The process then falls through to the DAT where is dies. However, as it dies, it decrements location "incr"-IVAL (about -30 absolute) twice as part of the Operand address evaluation. This is an imp gate. When the coreclear has gone round memory once, the MOV will be zapped by the DAT, so the coreclear stops and the SPL just feeds the newly moved imp- gate. ====== To summarise: RAVE has a sort-of imp-gate 308 locations before it. RAVE corrupts core, one location at a time backwards. RAVE scans core in jumps of 42 looking for enemies and bomb 14 locations there. RAVE eventually bombs itself and switches to a coreclear and imp-gate. RAVE then sits being an imp-gate till the end of the round. ====== APPENDIX List of values of "comp" at each execution of SLT: It is a worthwhile exercise to understand why each bombing run occurs in a single warrior (rave) environment. The ones with * are "the enemy is me" situations. The one with # is "the enemy is me, but I have left myself exposed". 00001 CMP.I $ 21, $ 9 * 00001 CMP.I $ 1, $ -11 * 00001 CMP.I $ 3, $ -9 * 00001 CMP.I $ 5, $ -7 * 00001 CMP.I $ 7, $ -5 * 00001 CMP.I $ 9, $ -3 * 00001 CMP.I $ -305, $ -317 00001 CMP.I $ -2383, $ -2395 00001 CMP.I $ 11, $ -1 * 00001 CMP.I $ -303, $ -315 00001 CMP.I $ -2381, $ -2393 00001 CMP.I $ 13, $ 1 * 00001 CMP.I $ -679, $ -691 00001 CMP.I $ -301, $ -313 00001 CMP.I $ -2379, $ -2391 00001 CMP.I $ -489, $ -501 00001 CMP.I $ 15, $ 3 * 00001 CMP.I $ -677, $ -689 00001 CMP.I $ -299, $ -311 00001 CMP.I $ -2377, $ -2389 00001 CMP.I $ -487, $ -499 00001 CMP.I $ 17, $ 5 * 00001 CMP.I $ -675, $ -687 00001 CMP.I $ -297, $ -309 00001 CMP.I $ -2375, $ -2387 00001 CMP.I $ -485, $ -497 00001 CMP.I $ -317, $ -329 00001 CMP.I $ 19, $ 7 * 00001 CMP.I $ -2395, $ -2407 00001 CMP.I $ -673, $ -685 00001 CMP.I $ -295, $ -307 00001 CMP.I $ -1, $ -13 *# End of round 1 This data was obtained using: PM RAVE -e write rave.dbg trace 2 g~l 1 >>>lots of repeats using ENTER<<< q EDIT RAVE.DBG ====== Sorry about the length of this issue, but RAVE has turned out to be more complex than I expected when I started this! === Steve Bailey 101374.624@compuserve.com sgb@zed-inst.demon.co.uk http://ourworld.compuserve.com/homepages/SGBailey Work: Electronics Play: Go 2kyu.