CoreWar


Nuestro programa lucha contra sus enemigos en una máquina virtual. Solo
una programación inteligente puede darle la victoria. Y su victoria será
tambien la nuestra, en el torneo de CoreWar que está organizando Virus
Report.



En el año 1984, A. K. Dewdney presentó un juego en su columna de
Scientific American (Investigación y Ciencia). En este juego, llamado
CoreWar, dos programas escritos en un assembler imaginario y limitado
luchaban entre si. El juego tuvo tanto éxito que se creó la ICWS
(International Core Wars Society), organización que realiza torneos
internacionales todos los años. No solo eso, sino que la sociedad se
expandió por el mundo e incluso se efectuaron torneos en Buenos Aires,
el primero de ellos en 1988 en la Universidad de Buenos Aires.

El lenguaje

El assembler que se utiliza se llama Redcode, y consta de sólo diez
instrucciones. En el recuadro 1 vemos la lista de las instrucciones. En
este assembler no existen los registros ni el direccionamiento absoluto.
Para ejecutar los programas necesitamos un simulador de la máquina
virtual que los contiene: el MARS. Estas son las siglas de Memory Array
Redcode Simulator, además de significar Marte en inglés, el dios de la
guerra. La memoria de esta máquina es circular, o sea, si tiene 2000
posiciones de memoria, numeradas de 0 a 1999 la posición 2000 equivale
nuevamente a la primera posicion o número 0. De todas formas, los
números veraderos no importan, ya que no existe el direccionamiento
absoluto, sólo trabajamos con posiciones relativas a la actual. Cada
posición de memoria, a diferencia de las máquinas que conocemos,
contiene una instrucción completa con hasta dos operandos. De esta
forma, de una sola vez podemos copiar una instrucción completa o un
dato. Otra cosa extraña que tiene este procesador, es la instrucción
SPL. Con ella podemos dividir el procesamiento de nuestro programa en
varias copias, haciendo un multitasking. Esto tiene sus ventajas obvias,
como tener más frentes de ataque, pero tambien tiene desventajas. Para
hacer multitasking de esta forma el programa primero debe copiarse a
otra posición de memoria y luego pasarle el control del procesador
mediante la instrucción SPL. Cada contrincante tiene uso del procesador
por turnos, y si existe más de una copia de uno de ellos le tocará una
vez a cada copia.

Esto es así: supongamos que existen los programas A y B. Si el A se
divide en A1 y A2, la secuencia de ejecución será: A1, B, A2, B, A1, B,
A2... etc. Vemos que para que el multitasking sea eficaz debemos tener
en cuenta este esquema de funcionamiento para que no sea una molestia
inútil dividirse en varios programas.

Direccionamiento

Como podemos ver en el recuadro 2, hay cuatro modos de direccionamiento.
El primero es inmediato, y se refiere a un número y no a una dirección
de memoria. El segundo es directo, y es el modo usado por default. Este
se refiere a una posición de memoria. El tercero, el indirecto, toma la
posición de memoria como un puntero hacia otra dirección. Y el cuarto,
más complejo, es el de autodecremento indirecto. Es similar al indirecto
pero antes de usar el puntero lo decrementa en uno. Vayamos a algunos
ejemplos:

Mov #0 $1

Pone un 0 en la posición de memoria que se encuentra a una posición de
distancia.

Mov #0 @1
Dat 5

Pone un 0 en la posición apuntada por el Dat, o sea, cinco posiciones
adelante del Mov.

Mov #0 <1
Dat 5

Esto decrementa el Dat en uno, con lo cual pasa a valer cuatro, y pone
un cero en la cuarta celda a partir del Mov.

Para simplificar la programación podemos usar labels como en assembler,
por ejemplo

Bomba 0
Start Mov bomba 5

Esto mueve el contenido de la casilla llamada bomba cinco posiciones
adelante. Tambien tenemos un label especial llamado START que indica
dónde empieza la ejecución de nuestro programa. Tambien, si utilizamos
números negativos el direccionamiento, como es lógico, apuntará a ese
número de casillas atrás de nuestra instrucción.

La lucha

Los programas tienen todo permitido para destruir a su adversario.
Pueden tener tácticas de defensa, de ocultación, o de ataque frontal. La
lucha termina cuando de uno de los dos programas no queda ninguna copia
en funcionamiento. Para que un programa deje de funcionar debe intentar
ejecutar una instrucción ilegal, o sea, una que no esté definida, un
código de operación que no esté de 1 a 10. Es obvio que una táctica
posible es llenar la memoria de ceros para que el otro programa se
tropiece con uno de ellos y muera. Pero hay que tener en cuenta que si
nuestro propio programa encuentra uno de esos ceros tambien va a morir.
Otra forma de terminar la batalla es con empate, es posible que ninguno
de los dos programas destruya al otro en un tiempo razonable, por lo
tanto el MARS detiene su ejecución.

El torneo

Llamamos a todos los programadores que deseen luchar que empiezen a
preparar sus programas. Dentro de unos meses lanzaremos la convocatoria
para nuestro torneo, que tendrá como premio un modem de 2400. Para que
empiecen a practicar, pondremos a disposición de todos en nuestro BBS,
en el 954-1792, las 24 horas, el programa que se usó para el último
torneo de CoreWar en Buenos Aires, escrito por Fabio Friedlaender. En la
próxima nota, para los que prefieren otros lenguajes, hablaremos del
torneo de C-Robots y P-Robots, en C y en Pascal respectivamente. Y
tambien presentaremos ejemplos de programas escritos en Redcode.