COREDUEL

MANUAL DE REDCODE

CoreDuel implementa el estándar ICWS'94 con las extensiones de pMARS (p-space, FOR/ROF, expresiones en EQU). Si conoces pMARS, todo esto te resultará familiar.

0. De qué va este juego

Escribes programas pequeños, bots, y los mandas a la Arena a luchar contra otros bots. Un bot se escribe en Redcode, un lenguaje parecido al ensamblador con 19 instrucciones. Todos los bots de una partida se cargan en una memoria compartida, el núcleo: un anillo de 8000 celdas (el final enlaza con el principio) dentro de un ordenador emulado muy simple llamado MARS. En ese ordenador no hay nada más: ni pantalla, ni archivos, solo instrucciones en celdas y unos pocos procesos que las ejecutan.

Cada bot empieza con un proceso en una posición aleatoria, a por lo menos 100 celdas de los demás. El emulador da turnos a los bots por rotación; en su turno, un bot ejecuta una instrucción de uno de sus procesos. Un proceso muere al ejecutar una instrucción DAT (o al dividir entre cero); un bot muere cuando pierde su último proceso. Como todos comparten la memoria, para ganar hay que sobrescribir el código del rival con bombas DAT, buscarlo escaneando el núcleo o inundar el núcleo con copias de uno mismo, manteniendo vivo el propio código.

Una ronda termina cuando solo queda un bot o tras 80000 ciclos. Una partida son una o más rondas; los supervivientes de cada ronda suman puntos y gana el mejor total. Ese es todo el juego: escribir un programa mejor que el del otro jugador.

Para empezar:

1. El núcleo

El núcleo es un anillo de 8000 celdas. Cada celda contiene una instrucción. Las direcciones dan la vuelta: celda 7999 + 1 = celda 0. En Redcode no hay direcciones absolutas; toda dirección es relativa a la instrucción que la usa.

Antes de cada ronda, todas las celdas contienen DAT.F $0, $0. Los guerreros se colocan en posiciones aleatorias separadas al menos MINDISTANCE (100) celdas. Cada guerrero empieza con un proceso en su ORG.

Los procesos se turnan: el guerrero A ejecuta una instrucción, luego el guerrero B, y así sucesivamente. Un guerrero con varios procesos los ejecuta por turnos rotativos (round-robin), uno por turno.

Un proceso muere cuando ejecuta DAT o divide por cero. Un guerrero muere cuando muere su último proceso. La ronda termina cuando queda un solo guerrero o tras MAXCYCLES (80000) ciclos.

2. Estructura del programa

;redcode-94
;name Dwarf
;author A. K. Dewdney
;strategy Bombs every 4th cell.
;assert CORESIZE == 8000
        ORG     start
target  DAT.F   #0, #0
start   ADD.AB  #4, target
        MOV.AB  #0, @target
        JMP     start
        END

3. Sintaxis de las instrucciones

label   OPCODE.MOD   A-mode A-value, B-mode B-value   ; comment

Cada instrucción tiene un código de operación (opcode), un modificador, un operando A y un operando B. Cada operando es un modo de direccionamiento más un valor. Los valores son expresiones (ver 8) que se evalúan respecto a la dirección de la propia instrucción.

Si escribes un solo operando, el ensamblador completa el otro:

4. Modos de direccionamiento

Cada operando se resuelve en un puntero (una dirección de celda) antes de ejecutar el opcode. Los dos operandos se evalúan siempre, primero A, incluso cuando el opcode ignora uno de ellos. Por eso los efectos secundarios de predecremento/postincremento ocurren incluso en JMP.

Nota: en ICWS'94 el operando inmediato también tiene puntero: la propia instrucción. MOV.I #0, 1 copia la instrucción entera una celda hacia adelante. Es el clásico Imp.

5. Modificadores

El modificador indica qué campos lee y escribe el opcode. Para una instrucción con puntero A a y puntero B b:

Modificador por defecto si lo omites:

6. Códigos de operación

Toda la aritmética es módulo CORESIZE. Los números en el núcleo siempre van de 0 a 7999; -1 se guarda como 7999.

7. Directivas

        ORG     loop
loop    FOR     3
        MOV.I   #0, &loop
        ROF

8. Expresiones

Operadores, de mayor a menor prioridad: unarios - + !, luego * / % (enteros, con truncamiento), luego + -, luego comparaciones == != < > <= >=, luego && y ||. Se admiten paréntesis. Las comparaciones dan 1 o 0.

Constantes predefinidas: CORESIZE, MAXCYCLES, MAXPROCESSES, MAXLENGTH, MINDISTANCE, PSPACESIZE, ROUNDS, WARRIORS (2), VERSION (92), CURLINE (índice de la instrucción actual).

Una etiqueta usada en una expresión vale su distancia a la instrucción actual, así que label+1 es la celda que sigue a label, y start-target es simplemente un número de celdas.

9. P-space

Cada guerrero tiene un array privado de PSPACESIZE (500) celdas que se conserva entre las rondas de una partida. Los índices dan la vuelta. La celda 0 es especial y siempre privada: al comienzo de cada ronda contiene el resultado anterior, 0 si el guerrero murió y, si no, el número de guerreros supervivientes (1 = victoria, 2 = empate). En la primera ronda contiene CORESIZE-1.

LDP.AB #0, x carga ese resultado en el campo B de x. STP.B x, #1 guarda el campo B de x en la celda 1. Un guerrero puede usarlo para cambiar de estrategia tras una derrota.

10. Reglas de la partida

11. Patrones comunes