COREDUEL

MANUEL REDCODE

CoreDuel implémente la norme ICWS'94 avec les extensions pMARS (p-space, FOR/ROF, expressions EQU). Si vous connaissez pMARS, rien ici ne devrait vous surprendre.

0. De quoi s'agit-il

Vous écrivez de petits programmes, des bots, et vous les envoyez dans l'Arène affronter d'autres bots. Un bot s'écrit en Redcode, un langage proche de l'assembleur avec 19 instructions. Tous les bots d'un match sont chargés dans une mémoire commune, le core : un anneau de 8000 cellules (la fin rejoint le début) dans un ordinateur émulé très simple appelé MARS. Il n'y a rien d'autre dans cet ordinateur : pas d'écran, pas de fichiers, seulement des instructions dans des cellules et quelques processus qui les exécutent.

Chaque bot démarre avec un processus à une position aléatoire, à au moins 100 cellules des autres. L'émulateur donne la main aux bots à tour de rôle ; à son tour, un bot exécute une instruction d'un de ses processus. Un processus meurt en exécutant une instruction DAT (ou en divisant par zéro) ; un bot meurt avec son dernier processus. Comme la mémoire est partagée, on gagne en écrasant le code adverse avec des bombes DAT, en le cherchant par balayage du core ou en inondant le core de copies de soi-même, tout en gardant son propre code en vie.

Une manche se termine quand il ne reste qu'un bot, ou après 80000 cycles. Un match compte une ou plusieurs manches ; les survivants de chaque manche marquent des points et le meilleur total l'emporte. C'est tout le jeu : écrire un meilleur programme que l'adversaire.

Pour commencer :

1. Le core

Le core est un anneau de 8000 cellules. Chaque cellule contient une instruction. Les adresses bouclent : cellule 7999 + 1 = cellule 0. Redcode n'a pas d'adresses absolues ; toute adresse est relative à l'instruction qui l'utilise.

Avant chaque manche, toutes les cellules valent DAT.F $0, $0. Les guerriers sont placés à des positions aléatoires, séparés d'au moins MINDISTANCE (100) cellules. Chaque guerrier démarre avec un seul processus, sur son ORG.

Les processus jouent à tour de rôle : le guerrier A exécute une instruction, puis le guerrier B, et ainsi de suite. Un guerrier qui a plusieurs processus les exécute en tourniquet, un par tour.

Un processus meurt quand il exécute un DAT ou quand il divise par zéro. Un guerrier meurt quand son dernier processus meurt. La manche se termine quand il ne reste qu'un guerrier, ou après MAXCYCLES (80000) cycles.

2. Structure d'un programme

;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. Syntaxe des instructions

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

Chaque instruction a un opcode, un modificateur, un opérande A et un opérande B. Chaque opérande se compose d'un mode d'adressage et d'une valeur. Les valeurs sont des expressions (voir 8), évaluées relativement à l'adresse de l'instruction elle-même.

Si vous n'écrivez qu'un seul opérande, l'assembleur complète l'autre :

4. Modes d'adressage

Chaque opérande est résolu en pointeur (une adresse de cellule) avant l'exécution de l'opcode. Les deux opérandes sont toujours évalués, A d'abord, même quand l'opcode en ignore un. C'est pourquoi les effets de bord de pré/post-incrémentation se produisent même dans un JMP.

Remarque : en ICWS'94, l'opérande immédiat a tout de même un pointeur, l'instruction elle-même. MOV.I #0, 1 copie l'instruction entière une cellule plus loin. C'est l'Imp classique.

5. Modificateurs

Le modificateur indique quels champs l'opcode lit et écrit. Pour une instruction de pointeur A a et de pointeur B b :

Modificateur par défaut quand vous l'omettez :

6. Opcodes

Toute l'arithmétique se fait modulo CORESIZE. Les nombres du core sont toujours compris entre 0 et 7999 ; -1 est stocké sous la forme 7999.

7. Directives

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

8. Expressions

Opérateurs, du plus prioritaire au moins prioritaire : - + ! unaires, puis * / % (entiers, avec troncature), puis + -, puis les comparaisons == != < > <= >=, puis && et ||. Les parenthèses sont autorisées. Les comparaisons renvoient 1 ou 0.

Constantes prédéfinies : CORESIZE, MAXCYCLES, MAXPROCESSES, MAXLENGTH, MINDISTANCE, PSPACESIZE, ROUNDS, WARRIORS (2), VERSION (92), CURLINE (indice de l'instruction courante).

Dans une expression, un label vaut sa distance par rapport à l'instruction courante : label+1 désigne la cellule qui suit label, et start-target est un simple nombre de cellules.

9. P-space

Chaque guerrier dispose d'un tableau privé de PSPACESIZE (500) cellules qui persiste d'une manche à l'autre au cours d'un match. Les indices bouclent. La cellule 0 est spéciale et toujours privée : au début de chaque manche, elle contient le résultat précédent, 0 si le guerrier est mort, sinon le nombre de guerriers survivants (1 = victoire, 2 = égalité). Lors de la première manche, elle contient CORESIZE-1.

LDP.AB #0, x charge ce résultat dans le champ B de x. STP.B x, #1 stocke le champ B de x dans la cellule 1. Un guerrier peut s'en servir pour changer de stratégie après une défaite.

10. Règles du match

11. Motifs courants