Esta es una adaptación de Core War , una programación KOTH que data del siglo XX. Para ser más específicos, está utilizando un conjunto de instrucciones increíblemente simplificado basado principalmente en la propuesta original .
Fondo
En Core War, hay dos programas que luchan por el control de la computadora. El objetivo de cada programa es ganar localizando y terminando el programa contrario.
La batalla tiene lugar dentro de la memoria principal de la computadora. Esta memoria se llama Core y contiene 8192 direcciones. Cuando comienza la batalla, el código para cada competidor (llamado guerrero) se coloca en un fragmento aleatorio de memoria. La ejecución del programa alterna entre guerreros, realizando una instrucción de cada uno. Cada instrucción es capaz de modificar una parte del Core, lo que lleva a la posibilidad de programas auto modificables.
El objetivo es terminar el programa contrario. Un programa finaliza cuando intenta ejecutar una instrucción no válida, que es cualquier DAT
instrucción.
El conjunto de instrucciones
Cada programa consta de una serie de instrucciones de bajo nivel, cada una de las cuales toma dos campos, llamados campos A y B.
Este conjunto de instrucciones se basa en gran medida de la especificación original. Los principales cambios son 1) aclaraciones sobre la suma / resta de comandos, y 2) un cambio del #
modo de direccionamiento para permitir que se use en cualquier lugar. La mayoría de las versiones completas de Core Wars tienen más de 20 códigos de operación, 8 modos de direccionamiento y un conjunto de "modificadores de instrucciones".
Opcodes
Cada instrucción debe tener uno de los siete códigos de operación diferentes.
DAT A B
- (datos) - Esto simplemente contiene los númerosA
yB
. Es importante destacar que un proceso muere cuando intenta ejecutar una instrucción DAT.MOV A B
- (mover): mueve el contenido de la ubicaciónA
de la memoria a la ubicación de la memoriaB
. Aquí hay una demostración de antes y después:MOV 2 1 ADD @4 #5 JMP #1 -1
MOV 2 1 JMP #1 -1 JMP #1 -1
ADD A B
- (agregar): agrega el contenido de la ubicaciónA
de la memoria a la ubicación de la memoriaB
. Se agregan los dos primeros campos de ambos, y se agregan los segundos campos.ADD 2 1 MOV @4 #5 JMP #1 -1
ADD 2 1 MOV @5 #4 JMP #1 -1
SUB A B
- (restar): resta el contenido de la ubicación de la memoriaA
(y almacena el resultado en) la ubicación de la memoriaB
.SUB 2 1 MOV @4 #5 JMP #1 -1
SUB 2 1 MOV @3 #6 JMP #1 -1
JMP A B
- (saltar): salta a la ubicaciónA
, que se ejecutará el próximo ciclo.B
debe ser un número pero no hace nada (sin embargo, puede usarlo para almacenar información).JMP 2 1337 ADD 1 2 ADD 2 3
El salto significa que
ADD 2 3
se ejecutará el próximo ciclo.JMZ A B
- (saltar si es cero) - Si ambos campos de líneaB
son 0, entonces el programa salta a la ubicaciónA
.JMZ 2 1 SUB 0 @0 DAT 23 45
Como los dos campos de la instrucción 1 son 0, el comando DAT se ejecutará el próximo turno, lo que provocará la muerte inminente.
CMP A B
- (comparar y omitir si no es igual) - Si los campos en las instruccionesA
yB
no son iguales, omita la siguiente instrucción.CMP #1 2 ADD 2 #3 SUB @2 3
Como los dos campos de las instrucciones 1 y 2 tienen el mismo valor, el comando AGREGAR no se omite y se ejecuta el próximo turno.
Cuando se suman / restan dos instrucciones, los dos campos (A y B) se suman / restan por pares. El modo de direccionamiento y el código de operación no cambian.
Modos de direccionamiento
Hay tres tipos de modos de direccionamiento. Cada uno de los dos campos de una instrucción tiene uno de estos tres modos de direccionamiento.
Inmediato
#X
:X
es la línea que se utilizará directamente en el cálculo. Por ejemplo,#0
es la primera línea del programa. Las líneas negativas se refieren a líneas en el núcleo antes del inicio del programa.... //just a space-filler ... ADD #3 #4 DAT 0 1 DAT 2 4
Esto agregará la primera de las dos líneas DAT a la segunda, ya que están en las líneas 3 y 4, respectivamente. Sin embargo, no querrá usar este código porque el DAT matará a su bot en el próximo ciclo.
Relativo
X
: el númeroX
representa la ubicación de una dirección de memoria de destino, en relación con la dirección actual. El número en esta ubicación se usa en el cálculo. Si la línea#35
se está ejecutando y contiene-5
, entonces#30
se usa la línea .... //just a space-filler ... ADD 2 1 DAT 0 1 DAT 2 4
Esto agregará la segunda línea DAT a la primera.
Indirecta
@X
: el númeroX
representa una dirección relativa. Los contenidos en esa ubicación se agregan temporalmente al número X para formar una nueva dirección relativa, de la que se recupera el número. Si#35
se está ejecutando la línea, y su segundo campo es@4
, y el segundo campo de la línea#39
contiene el número-7
, entonces#32
se usa la línea .... //just a space-filler ... ADD @1 @1 DAT 0 1 DAT 2 4
Esto agregará el primer DAT al segundo, pero de una manera más complicada. El primer campo es @ 1, que obtiene los datos de esa dirección relativa, que es el primer campo del primer DAT, un 0. Esto se interpreta como una segunda dirección relativa de esa ubicación, por lo que 1 + 0 = 1 da el total desplazamiento de la instrucción original. Para el segundo campo, @ 1 obtiene el valor de esa dirección relativa (el 1 en el segundo campo del primer DAT) y lo agrega a sí mismo de la misma manera. El desplazamiento total es entonces 1 + 1 = 2. Entonces, esta instrucción se ejecuta de manera similar a
ADD 1 2
.
Cada programa puede contener hasta 64 instrucciones.
Cuando comienza una ronda, los dos programas se colocan aleatoriamente en un banco de memoria con 8192 ubicaciones. El puntero de instrucción para cada programa comienza al comienzo del programa y se incrementa después de cada ciclo de ejecución. El programa muere una vez que su puntero de instrucción intenta ejecutar una DAT
instrucción.
Parámetros del núcleo
El tamaño del núcleo es 8192, con un tiempo de espera de 8192 * 8 = 65536 ticks. El núcleo es cíclico, por lo que escribir en la dirección 8195 es lo mismo que escribir en la dirección 3. Todas las direcciones no utilizadas se inicializan en DAT #0 #0
.
Cada competidor no debe tener más de 64 líneas. Los enteros se almacenarán como enteros con signo de 32 bits.
Analizando
Para facilitar la programación a los competidores, agregaré una función de etiqueta de línea al analizador. Cualquier palabra que aparezca en una línea antes de un código de operación se interpretará como etiquetas de línea. Por ejemplo, tree mov 4 6
tiene la etiqueta de línea tree
. Si, en cualquier parte del programa, hay un campo que contiene tree
#tree
o @tree
, se sustituirá un número. Además, se ignora la capitalización.
Aquí hay un ejemplo de cómo se sustituyen las etiquetas de línea:
labelA add labelB @labelC
labelB add #labelC labelC
labelC sub labelA @labelB
Aquí, las etiquetas A, B y C están en las líneas 0, 1 y 2. Las instancias de #label
serán sustituidas por el número de línea de la etiqueta. Las instancias de label
o @label
se sustituyen con la ubicación relativa de la etiqueta. Los modos de direccionamiento se conservan.
ADD 1 @2
ADD #2 1
SUB -2 @-1
Tanteo
Para cada par de concursantes, se realiza cada batalla posible. Dado que el resultado de una batalla depende de las compensaciones relativas de los dos programas, se intenta cada posible desplazamiento (aproximadamente 8000 de ellos). Además, cada programa tiene la oportunidad de moverse primero en cada desplazamiento. El programa que gana la mayoría de estas compensaciones es el ganador de la pareja.
Por cada pareja que gana un guerrero, se le otorgan 2 puntos. Por cada empate, un guerrero recibe 1 punto.
Puedes enviar más de un guerrero. Se aplican las reglas típicas para los envíos múltiples, como no trabajar en equipo, no cooperar, no hacer reyes, etc. De todos modos, en realidad no hay espacio para esto en Core War, por lo que no debería ser un gran problema.
El controlador
El código para el controlador, junto con dos bots de ejemplo fáciles, se encuentra aquí . Dado que esta competencia (cuando se ejecuta con la configuración oficial) es completamente determinista, la tabla de clasificación que cree será exactamente la misma que la tabla de clasificación oficial.
Ejemplo de bot
Aquí hay un ejemplo de bot que muestra algunas características del lenguaje.
main mov bomb #-1
add @main main
jmp #main 0
bomb dat 0 -1
Este bot funciona borrando lentamente toda la otra memoria en el núcleo al reemplazarlo con una "bomba". Como la bomba es una DAT
instrucción, cualquier programa que llegue a una bomba será destruido.
Hay dos etiquetas de línea, "principal" y "bomba" que sirven para reemplazar los números. Después del preprocesamiento, el programa se ve así:
MOV 3 #-1
ADD @-1 -1
JMP #0 0
DAT 0 -1
La primera línea copia la bomba en la línea inmediatamente superior al programa. La siguiente línea agrega el valor de la bomba ( 0 -1
) al comando de movimiento, y también demuestra el uso del @
modo de direccionamiento. Esta adición hace que el comando de movimiento apunte a un nuevo objetivo. El siguiente comando salta incondicionalmente al inicio del programa.
Tabla de clasificación actual
24 - Turbo
22 - DwarvenEngineer
20 - HanShotFirst
18 - Dwarf
14 - ScanBomber
10 - Paranoid
10 - FirstTimer
10 - Janitor
10 - Evolved
6 - EasterBunny
6 - CopyPasta
4 - Imp
2 - Slug
Resultados por pares:
Dwarf > Imp
CopyPasta > Imp
Evolved > Imp
FirstTimer > Imp
Imp > Janitor
Imp > ScanBomber
Slug > Imp
DwarvenEngineer > Imp
HanShotFirst > Imp
Turbo > Imp
EasterBunny > Imp
Paranoid > Imp
Dwarf > CopyPasta
Dwarf > Evolved
Dwarf > FirstTimer
Dwarf > Janitor
Dwarf > ScanBomber
Dwarf > Slug
DwarvenEngineer > Dwarf
HanShotFirst > Dwarf
Turbo > Dwarf
Dwarf > EasterBunny
Dwarf > Paranoid
Evolved > CopyPasta
FirstTimer > CopyPasta
Janitor > CopyPasta
ScanBomber > CopyPasta
CopyPasta > Slug
DwarvenEngineer > CopyPasta
HanShotFirst > CopyPasta
Turbo > CopyPasta
CopyPasta > EasterBunny
Paranoid > CopyPasta
Evolved > FirstTimer
Evolved > Janitor
ScanBomber > Evolved
Evolved > Slug
DwarvenEngineer > Evolved
HanShotFirst > Evolved
Turbo > Evolved
EasterBunny > Evolved
Paranoid > Evolved
Janitor > FirstTimer
ScanBomber > FirstTimer
FirstTimer > Slug
DwarvenEngineer > FirstTimer
HanShotFirst > FirstTimer
Turbo > FirstTimer
FirstTimer > EasterBunny
FirstTimer > Paranoid
ScanBomber > Janitor
Janitor > Slug
DwarvenEngineer > Janitor
HanShotFirst > Janitor
Turbo > Janitor
Janitor > EasterBunny
Janitor > Paranoid
ScanBomber > Slug
DwarvenEngineer > ScanBomber
HanShotFirst > ScanBomber
Turbo > ScanBomber
ScanBomber > EasterBunny
ScanBomber > Paranoid
DwarvenEngineer > Slug
HanShotFirst > Slug
Turbo > Slug
EasterBunny > Slug
Paranoid > Slug
DwarvenEngineer > HanShotFirst
Turbo > DwarvenEngineer
DwarvenEngineer > EasterBunny
DwarvenEngineer > Paranoid
Turbo > HanShotFirst
HanShotFirst > EasterBunny
HanShotFirst > Paranoid
Turbo > EasterBunny
Turbo > Paranoid
Paranoid > EasterBunny
La última actualización (nuevas versiones de Turbo y Paranoid) tardó aproximadamente 5 minutos en ejecutarse en una computadora portátil vieja. Me gustaría agradecer a Ilmari Karonen por sus mejoras en el controlador . Si tiene una copia local del controlador, debe actualizar sus archivos.
fuente
Respuestas:
Ingeniero enano
Un nuevo y mejorado enano. Victorias contra todo lo demás presentado hasta ahora. El elegante tamaño de paso optimizado de corestep es probablemente excesivo aquí.
Las características notables incluyen el ciclo de bombardeo rápido que arroja dos bombas en cuatro ciclos, para una velocidad de bombardeo promedio de 0.5c en la antigua jerga de la Guerra del Núcleo, y el uso de
JMZ
detectar cuándo se completa la ejecución del bombardeo y es hora de cambiar al plan B ( aquí, un diablillo).Solía jugar Core War en los años 90 (algunos de ustedes habrán visto la guía básica que escribí en el '97), así que pensé que sería interesante ver qué viejas estrategias del mundo RedCode '88 / '94 podrían Ser útil en esta variante.
Mis primeros pensamientos fueron:
No hay
SPL
, por lo tanto, no hay replicadores (y no hay anillos de imp / espirales). Esto debería hacer que los bombarderos sean fuertes. (Además, todas aquellas estrategias de bombardeo de lujo diseñados para hacer frente a los replicadores e IMP espirales? Totalmente innecesario e inútil aquí. Sólo con cualquier bombaDAT
s.)Por otra parte, el
CMP
escaneo sigue siendo potencialmente más rápido que el bombardeo, por lo que un escáner rápido podría tener una oportunidad.La ausencia de entradas / decrementos hace que los borrados de núcleo sean muy lentos. De hecho, un núcleo claro en esta variante es prácticamente un bombardero con un tamaño de paso (subóptimo) de ± 1. De nuevo, esto también perjudica a los escáneres; Sin embargo, una estrategia de escáner de un solo disparo → bombardero podría funcionar.
Los Quickscanners / quickbombers (una estrategia de juego temprano que usa un ciclo de escaneo / bombardeo desenrollado, para aquellos que no están tan familiarizados con la jerga de Core War) siguen siendo potencialmente útiles, pero solo contra programas largos (que ellos mismos son, por lo que hay una especie de retroalimentación efecto aquí). Es difícil decir si realmente vale la pena.
El sistema de puntuación es interesante. Los empates suman la mitad de puntos que una victoria (en lugar de 1/3, como en la Guerra del Núcleo tradicional), lo que los hace más atractivos. Por otra parte, el único programa que probablemente tenga muchos lazos bajo estas reglas es un diablillo. (Además, la ausencia de de / incrementos puertas hace imp duro, por lo que incluso simples diablillos realmente hacer tener la oportunidad de marcar un empate si llegan a su oponente con vida.)
Además, debido a la clasificación final sólo dependen de qué programas le ganas, y no como mucho les ganas por, tiende a favorecer las entradas generalistas. Es mejor vencer apenas a todos tus oponentes, que destruir totalmente a la mitad de ellos y apenas perder al resto.
Debido a que el código es público, siempre es posible encontrar un programa que pueda superar cualquier envío anterior, posiblemente incluso varios de ellos, sin importar cuán buenos sean en general. Sin embargo, tales trucos (como ajustar el tamaño de tu paso para golpear a tu oponente justo antes de que te golpeen) pueden parecer fácilmente baratos. Y, por supuesto, el jugador objetivo siempre puede enviar una nueva versión con diferentes constantes.
De todos modos, el resultado de todo esto es que decidí que debería tratar de escribir un bombardero rápido o un escáner muy rápido, y tal vez agregarle un escáner / bombardero rápido. Fuera de esas opciones, un bombardero rápido parecía el más simple y más probable que funcionara.
En ese momento, pasé demasiado tiempo ajustando y optimizando el código de intérprete de PhiNotPi, porque pensé que probablemente estaría ejecutando muchas pruebas de fuerza bruta para optimizar las constantes. Como sucede, nunca tuve que hacer eso: el código anterior es más o menos la primera versión que realmente funcionó (después de un par de intentos fallidos que se suicidaron debido a errores tontos).
El truco que hace que mi bombardero sea rápido es usar direccionamiento indirecto para lanzar dos bombas por cada uno
ADD
. Así es como funciona:En el primer ciclo, ejecutamos
MOV bomb @aim
. Esto copia labomb
instrucción a donde sea en el núcleo del campo B deaim
puntos (inicialmente, exactamente 6326 instrucciones antesaim
, o 6328 instrucciones antesstep
; verá por qué esos números importan más adelante).¡En el siguiente paso, ejecutamos la
aim
instrucción en sí! En la primera pasada, se parece a esto:MOV bomb @-6326
. Por lo tanto, se copiabomb
en la ubicación a la que apunta el campo B de la instrucción en 6326 líneas antes.Entonces, ¿qué hay antes en 6326 líneas
aim
? ¡Por qué, es la copiabomb
que acabamos de colocar allí un ciclo antes! Y acabamos de organizar las cosas para que el campo Bbomb
tenga un valor distinto de cero, de modo que la nueva bomba no se copie encima de la anterior, sino a cierta distancia (de hecho, aquí la distancia es 3164, que es la mitad de nuestro tamaño de paso nominal 6328; pero otras compensaciones podrían funcionar, tal vez incluso mejor).En el próximo ciclo, ajustamos nuestro objetivo con
SUB step aim
, que resta los valores de lastep
instrucción (que también resulta ser el salto que vamos a ejecutar a continuación, aunque podría haber sido un simple enDAT
alguna parte)aim
.(Un detalle a tener en cuenta es que tipo de queremos la A-valor de
step
ser cero, por lo que todavía vamos a lanzar las mismas bombas en la siguiente iteración Aun que no es estrictamente necesario, sin embargo;. Sólo tiran las bombas por la primera instrucción necesita tener su campo B igual a 3164, el resto puede ser cualquier cosa).A continuación, la
JMZ
comprobación de que la instrucción 6328 se aleja de ella sigue siendo cero y, de ser así, vuelve a la parte superior del código. Ahora, 6328 es el tamaño de paso de nuestro bombardero, y es divisible por 8 (pero no 16); por lo tanto, si seguimos lanzando bombas cada 6328 pasos, eventualmente volveríamos a donde comenzamos, bombardeando cada octava instrucción en el núcleo (y con las bombas adicionales compensadas por 3163 = 6328/2 ≡ 4 (mod 8) , habríamos acertado cada cuarta instrucción).Pero comenzamos nuestra carrera de bombardeo con 6328 instrucciones antes de la
JMZ
, y retrocedimos -6328 en cada iteración, por lo que vamos a bombardear la ubicación 6328 pasos después de laJMZ
única iteración antes de golpearnosJMZ
. Entonces, cuandoJMZ
detecta una bomba a las 6328 instrucciones posteriores, es una señal de que hemos cubierto la mayor parte del núcleo posible sin golpearnos, y debería cambiar a una estrategia de respaldo antes de matarnos.En cuanto a la estrategia de respaldo, es simplemente un viejo
MOV 0 1
diablillo, porque no puedo pensar en nada mejor por ahora. Desde mi punto de vista, si hemos bombardeado cada cuarta ubicación del núcleo y aún no hemos ganado, probablemente estamos luchando contra algo muy pequeño o muy defensivo, y también podríamos tratar de sobrevivir y conformarnos con un empate. Está bien, porque los programas tan pequeños o defensivos generalmente no son muy buenos para matar cualquier otra cosa, por lo que incluso si solo ganamos algunas peleas por casualidad, probablemente todavía saldremos adelante.PD.
En caso de que alguien más lo quiera, aquí está mi bifurcación ligeramente mejorada del código de torneo de PhiNotPi . Es aproximadamente el doble de rápido, guarda los viejos resultados de la batalla para que no tengas que volver a ejecutarlos y corrige lo que creo que es un error menor en el cálculo de los resultados de la batalla.Los cambios se han fusionado en la versión principal por PhiNotPi. ¡Gracias!fuente
Vista gráfica
Esto se puede usar como una herramienta de depuración. Muestra el núcleo y muestra la ubicación del jugador. Para usarlo debes llamarlo desde el código. También he proporcionado una modificación
Game.java
que muestra automáticamente GraphView.PhiNotPi e Ilmari Karonen cambiaron recientemente el controlador. Ilmari Karonen ha tenido la amabilidad de proporcionar un GameView actualizado en esta ubicación .
Game.java modificado:
fuente
./Game.java:275: error: method toString in class Object cannot be applied to given types; System.out.println(Player.toString(line)); ^ required: no arguments found: int[]
printCore()
método.Turbo
Mi segundo intento de CoreWar. Diseñado para vencer a los enanos. Escanea por 3 en busca de datos, luego coloca una bomba cada 2. Cada etapa se ejecuta en solo 3 instrucciones, con la esperanza de que las bombas de Dwarf la pierdan.
NUEVO Turbo ++ : ahora mejorado. Escanea hacia atrás hasta que encuentra datos, luego se mueve allí, luego bombardea hacia atrás. La esperanza es que el movimiento apunte al oponente o sea a un lugar ya bombardeado y, por lo tanto, seguro (ish).
... Y una edición para escanear más escasamente hace que venza a todos.
fuente
Enano
Un programa común y simple que representa a un enano arrojando piedras. Coloca una
DAT
instrucción cada cuatro direcciones.EDITAR: corrige el direccionamiento. Aparentemente, los modos de direccionamiento son diferentes de la especificación a la que está vinculado el OP.
fuente
add 3 3
, pero luego duplicaría cada ciclo en lugar de agregar, y eso no sería útil.#4
es inmediato, por lo que agrega el número4
al segundo valor en la dirección que está3
después de la dirección actual.#
modo de direccionamiento en el desafío. Como se indica en la especificación, hice un cambio en el#
modo de direccionamiento.Evolucionado
Sinceramente, no entiendo cómo funciona. Parece construir su código fuente antes de hacer nada. Me encantaría que alguien me diera una explicación de cómo funciona.Después de estudiarlo, descubrí que es simplemente un enano modificado con un guardia de diablillos. En lugar de bombardear a los enemigos con
DAT
instrucciones, baraja el código de los enemigos. También bombardea cada dos registros en lugar de cada cuatro registros. Con suficiente tiempo, sin duda se destruiría a sí mismo.fuente
FirstTimer
Si funciona, debería tratar de tomar posición al comienzo del núcleo y crear defensas
fuente
#0
refiere al inicio de su programa (es decir, lo mismo que#main
), no al inicio del núcleo (que de todos modos no es realmente un concepto significativo; el núcleo es circular, su código no puede decir dónde comienza o dónde termina). Lo que sucede es que su primera instrucción (main
) se sobrescribe con laMOV #data #100
, después de lo cual su código efectivamente se convierte en 0.25c (= una instrucción por cuatro ciclos) hacia adelante y hacia el centro.#0
al comienzo del núcleo. Las 5 primeras instrucciones son completamente inútiles entonces.CopyPasta
Nunca participó en un CoreWar, este simple programa solo está tratando de copiar y pegar él mismo y luego ejecutar la copia. Puede que no tenga el comportamiento correcto, por favor dígame si es el caso.
Es demasiado pacifista y, de hecho, no puede ganar.
fuente
JMP loop 0
). Luego, cuando salta a donde debería estar el inicio de la copia, es solo un espacio vacío y pierde.Portero
Debe verificar si las siguientes direcciones están vacías y, de lo contrario, las limpia (por lo tanto, con suerte, borrando el bot oponente).
Editar: esta nueva versión debería ser más rápida (ahora que entendí el
JMZ
comando y la@
referencia correctamente).fuente
ADD 3 -2
, pero tienes razón en que debería cambiarla, creo.JMZ
y pensé queJMZ A B
estaba comprobandoA
y saltando aB
si 0 cuando aparentemente es lo contrario. Gracias por notarlo porque no lo hice :)ScanBomber
Eliminar mis comentarios antes de compilar. Escanea por un tiempo, luego bombardea cuando encuentra un programa. Sin embargo, probablemente todavía perderá contra mi Enano.
fuente
#
completamente diferente a la especificación (lea el enlace al que se vinculó), todavía tengo que arreglar este programa.#
antes de cada referenciazero
? Sí, creo que necesito ...Han disparó primero (v2)
Pensé que la competencia podría usar más diversidad, así que aquí está mi segunda entrada: un
CMP
escáner de una sola vez .Esta es la versión 2 , con defensas anti-Imp mejoradas: ahora puede vencer a Imp, aunque solo sea por un punto. Todavía pierde ante Dwarven Engineer, pero supera todo lo demás hasta el momento, colocándolo actualmente en primer lugar empatado.
Funciona comparando ubicaciones centrales adyacentes con 5 pasos de diferencia, a intervalos de 10 pasos, hasta que encuentre una diferencia. Cuando lo hace, comienza a lanzar bombas a intervalos de 2 pasos hasta que mata a su oponente o recorre todo el núcleo para alcanzarlo.
Si el escaneo no encuentra nada más, eventualmente dará vueltas y encontrará su propio código y lo atacará. Esto sería suicida, pero por la afortunada coincidencia de que la primera bomba aterriza directamente en el
aim
línea, causando que la siguiente bomba sea arrojada 12 posiciones (en lugar de las 2 habituales) por el núcleo, omitiendo convenientemente el código. (Esto también ocurre con un 50% de probabilidad si el escaneo encuentra algo, pero no logra matar al oponente). Dado que el tamaño del núcleo es un múltiplo de dos, esto también seguirá sucediendo si la ejecución del bombardeo gira, eliminando la necesidad de un estrategia de respaldo adicional.(Este truco de auto-bombardeo fue originalmente una pura coincidencia: había planeado una forma completamente diferente de cambiar del modo de escaneo al de bombardeo si no se encontraba nada, pero cuando probé el código por primera vez, las constantes eran correctas para hacerlo trabajar de esta manera, y decidí seguir con eso)
fuente
Diablillo
Simplemente pulgadas a través del programa.
fuente
Babosa
Se arrastra por el espacio de la memoria hacia atrás. Ocasionalmente arroja una bomba muy lejos.
fuente
conejo de Pascua
Le gusta saltar hacia atrás :)
fuente
Paranoico
Es una especie de copia de pasta, pero comprobará si el código ha sido modificado por bombardeos. Si es así, copia más allá de un enano y ejecútalo. Si logro volver a hacer GameView, intentaré cambiar algunas de las constantes.
fuente