TUTORIAL
Welcome to Core War
This is a programming game. You write a bot in Redcode, a tiny assembly language, and drop it into the core: a ring of 8000 memory cells shared with the enemy bots. Each bot runs one instruction per turn. There are no walls and no rules of engagement: whoever overwrites the other's code, or stays alive longer, wins the round. The Arena shows the whole core as pixels, so you can watch your program crawl, bomb and scan in real time.
The lessons below start with a one-line bot and end with a warrior that changes strategy between rounds. You can skip ahead or come back at any time with the step list. Every lesson has a complete bot: open it in the editor, run it, then change one number and run it again.
Lesson 0: How to play
- Bots: your warriors and the read-only library. FORK a library bot to edit a copy.
- Editor: type Redcode; errors show at the bottom. RUN opens the arena with this bot preselected.
- Arena: fill the bot slots (one bot alone is a test run,
+ BOTadds more), set rounds, speed, seed. Watch the core: each pixel is a cell, coloured by the last warrior that wrote it; bright cells are executing. - Saves: a running match is auto-saved; resume it later or share the
.cdsavefile.
Lesson 1: The Imp
The core is a ring of 8000 cells. A process executes one cell per turn and moves to the next. MOV copies a cell. With the .I modifier it copies the whole instruction, and #0 means "this very instruction".
;redcode-94
;name Imp
;author Tutorial
;strategy Copies itself one cell forward, forever.
MOV.I #0, 1
END
Each turn the Imp copies itself to the next cell and then executes that copy. It crawls through the whole core, overwriting everything in its path. It cannot be killed by a single DAT (it just copies over it), but it also never kills anything by itself: it usually ends in a tie.
Run it against Dwarf from the library and watch the green trail.
Lesson 2: Dwarf, the bomber
A DAT kills the process that executes it. Dwarf throws DATs at every fourth cell, so any warrior longer than 3 cells is hit eventually.
;redcode-94
;name Dwarf
;author Tutorial
;strategy Drops a DAT every 4 cells.
ORG start
target DAT.F #0, #0
start ADD.AB #4, target
MOV.AB #0, @target
JMP start
END
ADD.AB #4, target: add 4 to the B-field of target. That field is our pointer.MOV.AB #0, @target:@means "go where target's B-field points"; write 0 into that cell's B-field. This is the exact Dwarf from the ICWS'94 draft, and it is not a realDATbomb: it only zeroes one field. That still breaks most code (an Imp becomesMOV.I 0, 0and stalls). Lesson 3 throws fullDATbombs.JMP start: loop.
Why 4? 8000 is divisible by 4, so the pointer walks 2000 cells and returns exactly to target, which is a DAT already. Dwarf never bombs its own three code lines.
Lesson 3: Modifiers
The modifier picks which fields move. Compare:
MOV.A a, bcopies the A-field only.MOV.B a, bcopies the B-field only.MOV.AB a, bcopies a's A-field into b's B-field.MOV.F a, bboth fields.MOV.I a, bthe whole instruction, opcode included.
Dwarf above uses ADD.AB so the immediate 4 (an A-field) lands in target's B-field. Here is a Dwarf that throws whole DAT instructions with MOV.I. Its bomb has predecrement operands: when an enemy process executes it, both operands are still evaluated before the process dies, so two more cells far away get damaged too.
;redcode-94
;name Dwarf Plus
;author Tutorial
;strategy Full-instruction DAT bombs with decrementing fields.
ORG start
ptr DAT #0, #0
bomb DAT <2667, <5334
start ADD.AB #4, ptr
MOV.I bomb, @ptr
JMP start
END
Compare Dwarf against Dwarf Plus with the same seed several times.
Lesson 4: Addressing modes and the imp gate
Both operands are evaluated every instruction, even ones JMP ignores. < decrements the B-field of the addressed cell before using it. A JMP that keeps decrementing a cell is an imp gate: when an Imp copy (MOV.I 0, 1) lands there, its B-field becomes 0, so it copies onto itself and the process runs into empty core and dies.
;redcode-94
;name Gated Dwarf
;author Tutorial
;strategy Dwarf whose loop instruction also gates the cell before it.
ORG start
gate DAT #0, #0
target DAT #0, #0
start ADD.AB #4, target
MOV.AB #0, @target
JMP start, <gate
END
Run Gated Dwarf against Imp: the Imp now usually dies instead of tying (the gate fires once per loop, so it needs a few laps). Since target and start are 1 and 2 cells after gate, and the bombs fall at multiples of 4 from target, the gate is never bombed.
Lesson 5: SPL and the imp ring
SPL starts a second process. Processes of one warrior take turns. Three imps spaced 2667 cells apart (3 x 2667 = 8001, one more than the core) chase each other and advance one cell every three copies: an imp ring. It is much harder to gate than a single imp.
;redcode-94
;name Imp Ring
;author Tutorial
;strategy 3-point imp ring launched with SPL.
step EQU 2667
ORG start
start MOV.I imp, imp+step
MOV.I imp, imp+2*step
SPL imp+step
SPL imp+2*step
JMP imp
imp MOV.I #0, step
END
EQU defines a constant. imp+2*step is an expression, evaluated by the assembler. Try step = 4001 with two imps.
Lesson 6: Scanners
A scanner looks for the enemy before bombing. Empty core is DAT 0, 0, so a non-zero B-field means "something is here". JMZ jumps if the tested field is zero.
;redcode-94
;name Scanner
;author Tutorial
;strategy Scan every 3039th cell for a non-zero B-field, bomb it.
step EQU 3039
ORG scan
ptr DAT #0, #0
bomb DAT #0, #0
scan ADD.AB #step, ptr
JMZ.B scan, @ptr
MOV.I bomb, @ptr
JMP scan
END
ADD.AB #step, ptradvances the pointer.JMZ.B scan, @ptr: if the B-field of the scanned cell is zero, scan again.- Otherwise drop the bomb and continue.
Against Dwarf the scanner finds the bomber's code quickly. Against an Imp it wastes bombs on the trail. A real scanner uses an odd step that never revisits a cell and skips over its own code.
Lesson 7: Bootstrapping
The code you load is a fixed target. Copy the real warrior far away, jump there, and let the enemy waste bombs on the launcher. A MOV loop with predecrement pointers copies backwards; DJN with an immediate counts the iterations on its own B-field.
;redcode-94
;name Boot Dwarf
;author Tutorial
;strategy Copies Dwarf 3000 cells away and runs the copy.
dist EQU 3000
len EQU 4
ORG boot
boot MOV.I <src, <dst
DJN boot, #len
JMP dwarf+1+dist
src DAT #0, dwarf+len
dst DAT #0, dwarf+len+dist
dwarf DAT.F #0, #0
ADD.AB #4, dwarf
MOV.AB #0, @dwarf
JMP dwarf+1
END
<src: decrement src's B-field, then read the cell it points to: the last Dwarf line first.<dst: same on the destination side.DJN boot, #len: decrement theDJN's own B-field, loop while it is not zero.JMP dwarf+1+dist: dwarf itself is theDAT; execution starts at theADDafter it.- Dwarf's references are relative (
dwarf+1,@dwarf), so the copy works unchanged.
Lesson 8: P-space, learning between rounds
Each warrior keeps 500 private cells across the rounds of a match. Cell 0 says how the last round went: 0 = we died, 1 = we won, 2 = tie. LDP loads a cell, STP stores one. This warrior remembers which strategy it ran in cell 1 and switches whenever it lost.
;redcode-94
;name Switcher
;author Tutorial
;strategy Runs Dwarf or an imp ring; switches after a lost round.
step EQU 2667
ORG start
res DAT #0, #0
cur DAT #0, #0
start LDP.AB #0, res ; res.B = last result
LDP.AB #1, cur ; cur.B = strategy 0 or 1
JMN.B keep, res ; did not lose: keep it
MUL.AB #-1, cur ; toggle 0 <-> 1
ADD.AB #1, cur
keep STP.B cur, #1 ; remember it
JMZ.B dwarf, cur
MOV.I imp, imp+step
MOV.I imp, imp+2*step
SPL imp+step
SPL imp+2*step
JMP imp
imp MOV.I #0, step
target DAT.F #0, #0
dwarf ADD.AB #4, target
MOV.AB #0, @target
JMP dwarf
END
Run a 10-round match against Scanner and watch the strategy flip after losses. Real p-space warriors ("pswitchers") pick from several components and are a large part of modern tournament play.
Where next
- Fork the library classics and read them line by line.
- Change one number at a time and re-run with the same seed.
- Read the Manual sections on default modifiers and evaluation order; most surprises live there.