↓ Skip to main content
  1. posts/

Core War: programs that fight inside memory

·

In Core War the players never touch the game. Each player writes a small program, a warrior, in an assembly language called Redcode. Two warriors are loaded into the same circular block of memory, the core, and each executes one instruction per turn. A warrior loses when all its processes have died by executing a DAT instruction. That is all: two programs overwriting each other’s memory.

Below is a full ICWS'94 simulator (a MARS, Memory Array Redcode Simulator) that I wrote for this page. It uses the standard “94nop” hill settings: an 8000-cell core, up to 8000 processes per warrior and a tie after 80,000 cycles.

How to read the arena
#

Every square is one memory cell. Cells are numbered left to right, top to bottom. The last cell is next to the first, so the core has no edges.

  • Colour shows which warrior wrote the cell last. Bright means recent, and the colour fades with age. Cells holding a DAT are darker, so bombs are easy to tell from live code.
  • White dots are processes, the program counters waiting to run.
  • White flashes are the instructions that just ran.
  • Hover over a cell, or tap it on a phone, to see the instruction inside it.
  • Show code shows the instructions around each warrior’s last executed line, a one-sentence description of that line, and arrows on the core for where it wrote, jumped or split. It works best at low speed or with Step (keyboard: →, and Space to pause).
  • Finish runs the current battle to the end at once. Tournament plays every warrior against every other in a background thread and scores like King-of-the-Hill servers: 3 points for a win, 1 for a tie.
  • Edit warriors lets you change a warrior or paste your own and fight at once.

A short history
#

1961, Darwin. At Bell Labs, Victor Vyssotsky, Robert Morris and Doug McIlroy wrote Darwin, a game for the IBM 7090 in which programs tried to find and destroy each other in memory. Core War descends from it.

1984, the article. In March 1984, D. G. Jones and A. K. Dewdney published the Core War Guidelines. In May 1984, Dewdney’s Computer Recreations column in Scientific American introduced the game to the public, under the title “In the game called Core War hostile programs engage in a battle of bits”. The name comes from core memory, the magnetic-core RAM of older computers. The article had the first two famous warriors, Imp and Dwarf.

1986, the first tournament. The International Core War Society (ICWS) was founded in 1985. The first standard, ICWS'86, and the first tournament both came in 1986. Mice, a self-copying program by Chip Wendell, won it.

1988 and 1994, the standards. ICWS'88 fixed the instruction set for years. The 1994 draft added instruction modifiers (.A, .B, .AB, .F, .I…), new addressing modes and new opcodes. It was never formally ratified, but it became the de facto standard. This page implements it.

1990s, the Usenet era. The newsgroup rec.games.corewar and the automatic King of the Hill servers made Core War a continuous competition. You mailed your warrior to the hill. It fought every warrior already there and stayed only if it scored high enough. The reference simulator pMARS dates from this time. The classic strategies were refined on those hills: imp spirals, paper (Silk), quick-scanners and core clears. A few hills still run, and corewar.co.uk collects history and warriors.

Redcode in two minutes
#

A visual guide to the language, with a step-by-step debugger, is in Redcode, instruction by instruction.

Every cell holds one instruction: an opcode, a modifier and two operands, A and B. Each operand has an addressing mode and a number. All addresses are relative: 1 is the next cell and -1 the previous one. A program never knows where it is in the core.

OpcodeWhat it does
DATData. A process that executes it dies.
MOVCopy a field, or with .I the whole instruction, from A to B.
ADD SUB MUL DIV MODArithmetic on fields. Dividing by zero kills the process.
JMPJump to A.
JMZ / JMNJump to A if B is zero / is not zero.
DJNDecrement B, then jump to A if it is not zero.
SEQ (CMP) SNE SLTCompare A with B and skip the next instruction if the test holds.
SPLStart a new process at A. Its own process carries on with the next instruction.
NOPDo nothing.
ModeMeaning
#5Immediate: the number itself
$5 or 5Direct: the cell 5 ahead
@5B-indirect: go to cell 5 ahead, then follow its B-field
*5A-indirect: the same, following the A-field
<5 {5Like @ / *, but first decrement the pointer field
>5 }5Like @ / *, but increment the pointer field afterwards

Warrior 1 runs one instruction, then warrior 2, and so on. A warrior with many processes gets no more CPU time. Its turn rotates through its process queue. So SPL makes a warrior harder to kill and slower.

The warriors
#

Core War strategies form a rock-paper-scissors triangle: stones (bombers) tend to beat scissors (scanners), scanners beat paper (replicators), and paper beats stones. Imps are a fourth element. They are hard to kill, rarely kill anything and mostly force a tie. The simple warriors here follow the triangle only roughly. Run the tournament and see where they break it.

Imp
#

imp     MOV.I   0, 1

One instruction: copy this cell to the next one. The process moves on and finds the same instruction there. The Imp crawls through the core one cell per turn and leaves a trail of copies. It is almost impossible to kill, because a bomb has to land exactly on the cell it is about to execute. It almost never wins either. When an imp reaches the enemy’s code, it turns that code into imps, the enemy keeps running, and the battle ends in a tie.

Dwarf, a stone
#

dwarf   ADD.AB  #4, bomb
        MOV.I   bomb, @bomb
        JMP     dwarf
bomb    DAT     #0, #0

The first real bomber. Each loop adds 4 to the B-field of bomb and copies the DAT to the address that B-field points to (@bomb). Because 8000 is divisible by 4, the bombs land on every fourth cell. The only part of the Dwarf they can hit is bomb itself, and a DAT over a DAT does no harm. Any enemy longer than 3 instructions gets hit sooner or later, and the process that steps on a bomb dies.

Mice, a replicator
#

Mice copies its 8 instructions to a new place (MOV @ptr, <dest in a DJN loop), starts the copy with SPL @dest and moves its target 653 cells further. Each copy does the same. Within a few thousand cycles the core is full of mice, and a bomber cannot kill them all. This strategy won the first tournament.

Imp Spiral
#

Three imps placed 2667 cells apart. Because 3 × 2667 = 8001, the third imp writes the cell right after the first one. The processes move in lock-step, and each imp rewrites the cell the next imp is about to execute. One DAT bomb cannot stop the spiral, because the next imp repairs the damage. The launcher uses SPL to create several processes at each point, so the spiral also survives losing a few.

Paper (Silk-style)
#

The modern version of Mice. Three SPL 1 instructions create 8 processes. All 8 run SPL 3620 and then MOV >-1, }-1. Each process copies one line, because the post-increment modes advance both pointers. The new copy starts running before it is finished, so paper spreads fast. After copying, the old processes stay behind in a bombing loop. To kill paper you must kill every copy, and there can be hundreds.

Scanner, scissors
#

scan    ADD.AB  #7, ptr
ptr     JMZ.F   scan, trap+7

A scanner looks instead of bombing blindly. It checks every 7th cell and skips empty ones (JMZ.F jumps back while both fields are zero). When it finds something, it plants a SPL #0 trap there. A process that steps on the trap only creates more stuck processes, and the enemy slows almost to a stop. After one lap around the core, the scanner kills everything stuck with a DAT core clear. Scanners are deadly against large, slow targets like paper. Bombers are small and hard to find.

Vampire
#

A bomber with a twist. It throws fangs instead of DAT: JMP instructions whose offsets always point back into its own pit. ADD.F changes both fields of the fang at once, so the fang’s target stays the pit wherever it lands. An enemy process that executes a fang jumps into the pit and becomes a prisoner. Prisoners run a two-line loop, MOV kill, <pit-10 and SPL -1, that clears the core backwards with DAT while their number stays constant. When the clear goes all the way around and erases the SPL, every prisoner dies. The step is a multiple of 4, so a fang can land only on the fang itself or on kill, and the pit still works. That makes the Vampire as regular as the Dwarf. Against the Dwarf it is the bigger target, and the tournament shows the cost.

Write your own
#

Open Edit warriors, change a number and press Load & fight. Try these:

  • Change the Dwarf’s step from #4 to #3. It will eventually bomb itself. Why?
  • Give the Imp a partner: put SPL 1 before it.
  • Change step in the Scanner and see how the tournament ranking changes.

The parser supports labels, EQU, ORG/END, arithmetic in operands and the ;name / ;author / ;strategy comments. Write modifiers explicitly, as above. If you leave one out, the ICWS'94 default applies.

Related