COREDUEL

TUTORIAL

Bienvenido a Core War

Esto es un juego de programación. Escribes un bot en Redcode, un ensamblador diminuto, y lo sueltas en el núcleo: un anillo de 8000 celdas de memoria compartido con los bots enemigos. Cada bot ejecuta una instrucción por turno. No hay muros ni reglas de combate: quien sobrescribe el código del otro, o aguanta vivo más tiempo, gana la ronda. La Arena muestra todo el núcleo como píxeles, así que ves a tu programa arrastrarse, bombardear y escanear en tiempo real.

Las lecciones empiezan con un bot de una sola línea y terminan con un guerrero que cambia de estrategia entre rondas. Puedes saltar adelante o volver atrás cuando quieras desde la lista de pasos. Cada lección trae un bot completo: ábrelo en el editor, lánzalo, cambia un número y vuelve a lanzarlo.

Lección 0: Cómo se juega

Lección 1: El Imp

El núcleo es un anillo de 8000 celdas. Un proceso ejecuta una celda por turno y pasa a la siguiente. MOV copia una celda. Con el modificador .I copia la instrucción entera, y #0 significa "esta misma instrucción".

;redcode-94
;name Imp
;author Tutorial
;strategy Copies itself one cell forward, forever.
        MOV.I   #0, 1
        END

En cada turno, el Imp se copia en la celda siguiente y luego ejecuta esa copia. Recorre todo el núcleo sobrescribiendo lo que encuentra a su paso. Un solo DAT no puede matarlo (simplemente lo sobrescribe), pero tampoco mata nada por sí mismo: suele acabar en empate.

Enfréntalo a Dwarf de la biblioteca y observa el rastro verde.

Lección 2: Dwarf, el bombardero

Un DAT mata al proceso que lo ejecuta. Dwarf lanza DATs cada cuatro celdas, así que cualquier guerrero de más de 3 celdas acaba recibiendo un impacto.

;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

¿Por qué 4? 8000 es divisible por 4, así que el puntero recorre 2000 celdas y vuelve exactamente a target, que ya es un DAT. Dwarf nunca bombardea sus propias tres líneas de código.

Lección 3: Modificadores

El modificador elige qué campos se mueven. Compara:

El Dwarf de arriba usa ADD.AB para que el 4 inmediato (un campo A) vaya al campo B de target. Aquí tienes un Dwarf que lanza instrucciones DAT completas con MOV.I. Su bomba tiene operandos con predecremento: cuando un proceso enemigo la ejecuta, ambos operandos se evalúan antes de que el proceso muera, así que otras dos celdas lejanas también sufren daños.

;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

Enfrenta Dwarf a Dwarf Plus varias veces con la misma semilla.

Lección 4: Modos de direccionamiento y la puerta anti-imp

Los dos operandos se evalúan en cada instrucción, incluso los que JMP ignora. < decrementa el campo B de la celda direccionada antes de usarlo. Un JMP que decrementa una celda una y otra vez es una puerta anti-imp: cuando una copia del Imp (MOV.I 0, 1) cae ahí, su campo B pasa a ser 0, así que se copia sobre sí misma y el proceso avanza hacia núcleo vacío y muere.

;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

Enfrenta Gated Dwarf al Imp: ahora el Imp suele morir en lugar de empatar (la puerta se activa una vez por vuelta del bucle, así que necesita unas cuantas vueltas). Como target y start están 1 y 2 celdas después de gate, y las bombas caen en múltiplos de 4 desde target, la puerta nunca recibe una bomba.

Lección 5: SPL y el anillo de imps

SPL inicia un segundo proceso. Los procesos de un mismo guerrero se turnan. Tres imps separados 2667 celdas (3 x 2667 = 8001, una más que el núcleo) se persiguen y avanzan una celda cada tres copias: un anillo de imps. Es mucho más difícil de detener con una puerta que un solo 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 define una constante. imp+2*step es una expresión que evalúa el ensamblador. Prueba step = 4001 con dos imps.

Lección 6: Escáneres

Un escáner busca al enemigo antes de bombardear. El núcleo vacío es DAT 0, 0, así que un campo B distinto de cero significa "aquí hay algo". JMZ salta si el campo comprobado es cero.

;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

Contra Dwarf, el escáner encuentra rápido el código del bombardero. Contra un Imp, desperdicia bombas en su rastro. Un escáner de verdad usa un paso impar que nunca repite celda y se salta su propio código.

Lección 7: Arranque (boot)

El código que cargas es un blanco fijo. Copia el guerrero real lejos, salta allí y deja que el enemigo malgaste bombas en el lanzador. Un bucle de MOV con punteros con predecremento copia hacia atrás; DJN con un inmediato cuenta las iteraciones en su propio campo B.

;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

Lección 8: P-space, aprender entre rondas

Cada guerrero conserva 500 celdas privadas entre las rondas de una partida. La celda 0 indica cómo fue la última ronda: 0 = morimos, 1 = ganamos, 2 = empate. LDP carga una celda y STP guarda una. Este guerrero recuerda en la celda 1 qué estrategia usó y cambia cada vez que pierde.

;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

Juega una partida de 10 rondas contra Scanner y observa cómo cambia de estrategia tras cada derrota. Los guerreros de p-space reales ("pswitchers") eligen entre varios componentes y son una parte importante del juego competitivo moderno.

Y ahora qué