Este juego lo había escrito para un concurso de programación hace varios meses, pero no conseguí que las colisiones funcionaran bien, ahora que ya he conseguido arreglarlo minimamente y he añadido un par de cambios, este es el resultado:
Mostrando entradas con la etiqueta juegos. Mostrar todas las entradas
Mostrando entradas con la etiqueta juegos. Mostrar todas las entradas
domingo, 6 de febrero de 2011
viernes, 10 de diciembre de 2010
Concurso de programación de corewars
Me entero por Thoughts on Corewar que están organizando un concurso de programación para este juego. Traduzco el post:
Solo añadir que como dicen en la página web, el deadline es el 31 de diciembre.
Happy coding!
El Primer Concurso Internacional de Programación de Corewars acaba de ser anunciado, con un primer premio de $50 patrocinado por www.corewar.info.
La competición tomará lugar en el área inexplorada entre la configuración '94nop y LP, que ha sido recientemente investigada por Fizmo en Redcode Talk.
La configuración exacta es como sigue:
Estándar: CWS'94 Tamaño del núcleo: 8000 Procesos: 200 Tamaño de la entrada: 20 Puntos de victoria: 3 Puntos de empate: 1 Ciclos: 80000 Rondas: 1000
La línea de comandos de pMARS espmars -p 200 -l 20 -r 1000. STPyLDPestán prohibidos se permiten hasta dos entradas y las batallas serán en un torneo round-robin.
Para más información, hecha un vistazo al anuncio en rec.games.corewar.
Solo añadir que como dicen en la página web, el deadline es el 31 de diciembre.
Happy coding!
domingo, 10 de octubre de 2010
Interactuando con el WiiMote desde Python
El mando de Wii es a día de hoy un cachivache muy capaz de interactuar con el PC, tanto por que funciona a través de bluetooth, como porque sus capacidades impolsaron a la scene a estudiarlo.
El detalle es que después de ver un problema recurrente con estas consolas, que hacían falta pilas para usar el mando incluso cuando al final para jugar solo se utilizaran los que se conectan por cable a la consola, decidí escribir un script que permitiese conectarse a la consola y que, al menos, moviera el cursor y pulsara el boton principal [A] para poder solventar estos casos.
Nota: Hay una librería C para interactuar con el mando, llamada libcwiid
Aunque dicho script aún no está escrito, es más fácil conseguir un mando para trastear y explorar la forma con la que se comunica con la consola que una consola directamente, con ese motivo se escribió este código [pymote.py]. Conecta el dongle/pincho/chuzo bluetooth y comenzemos...
El detalle es que después de ver un problema recurrente con estas consolas, que hacían falta pilas para usar el mando incluso cuando al final para jugar solo se utilizaran los que se conectan por cable a la consola, decidí escribir un script que permitiese conectarse a la consola y que, al menos, moviera el cursor y pulsara el boton principal [A] para poder solventar estos casos.
Nota: Hay una librería C para interactuar con el mando, llamada libcwiid
Aunque dicho script aún no está escrito, es más fácil conseguir un mando para trastear y explorar la forma con la que se comunica con la consola que una consola directamente, con ese motivo se escribió este código [pymote.py]. Conecta el dongle/pincho/chuzo bluetooth y comenzemos...
lunes, 17 de mayo de 2010
VirtualSlug un bot de Real Time Battle
Pues por aqui, en la lanparty FicOnLan, se organizo un torneo de Real Time Battle, que es un juego que consiste en programar un robot (en cualquier lenguaje, la informacion se pasa por la entrada y salida estándar) para que luche contra otros, esto fue lo que presente:
[ VirtualSlug.tar.gz ]
Por supuesto, quedo de ultimo, funciono incluso peor que los robots que se quedaban quietos xD... parece ser que ir de frente al medio de la batalla no es tan buena idea cuando no es un uno contra uno :)
Teneis mucha informacion del tema en [ http://rtb.belay.es/ ] o en [ http://realtimebattle.sourceforge.net/ ]
Tambien hubo un concurso de programacion... pero la verdad es que no me gusto lo que consegui, cuando lo pula un poco (cuando consiga hacer una deteccion de colisiones decente) lo subo
Hasta ahora!
[ VirtualSlug.tar.gz ]
Por supuesto, quedo de ultimo, funciono incluso peor que los robots que se quedaban quietos xD... parece ser que ir de frente al medio de la batalla no es tan buena idea cuando no es un uno contra uno :)
Teneis mucha informacion del tema en [ http://rtb.belay.es/ ] o en [ http://realtimebattle.sourceforge.net/ ]
Tambien hubo un concurso de programacion... pero la verdad es que no me gusto lo que consegui, cuando lo pula un poco (cuando consiga hacer una deteccion de colisiones decente) lo subo
Hasta ahora!
Etiquetas:
juegos,
python,
real time battle,
rtb
jueves, 10 de diciembre de 2009
Jugando a Core Wars [2° Parte/2]
Sigamos con el Core Wars...
Resumiendo, lo que vimos hasta ahora fue:
;Comentarios
;name nombre del programa
;author autor
MOV A,B ;Copia A en B
ADD A,B ;Añade A a B
JMP A ;Se salta la instruccion A
DAT A,B ;Un espacio para datos
Formas de indicar una direccion:
-Inmediata, por de la posicion donde esta el valor, se indica con un '#'
-Directa, por la posicion actual, se representa con '$' (o sin nada)
-Indirecta, por el valor de la posicion indicada, se indica con un '*' si es el primer campo (A), o con '@' si es el segundo campo (B)
Pero hay mas formas de indicar una direccion de forma indirecta:
- La del campo A, restandole 1 antes, '{'
- La del campo B, restandole 1 antes, '<'
- La del campo A, sumandole 1 despues, '}'
- La del campo B, sumandole 1 despues, '>'
Por ejemplo, se podria modificar el programa "dwarf"
;name Dwarf
;author A. K. Dewdney
dwarf ADD #4, bomb
MOV bomb, @bomb
JMP dwarf
bomb DAT #0
Haciendo que llene todos los espacios de memoria 1 a 1, en vez de cuatro en cuatro, y de paso eliminamos una instruccion (con lo que el programa es mas rapido)
dwarf MOV bomb, >bomb
JMP dwarf
bomb DAT #1
Veamos las diferencias, la primera es que ya no esta la instruccion ADD por que lo que hacia (cambiar el valor de "bomb" para evitar estar siempre "golpeando la misma zona")ahora lo hace el MOV.
La segunda es el campo B de la instruccion MOV incrementa el valor del campo B de "bomb" uno de cada vez (por el '>').
La ultima es que el valor al que apunta "bomb" al principio es el siguiente ('#1'), ya que al no haber ADD y a que el incremento es posterior, si fuera el mismo ('#0'), se sobreescribiria, algo totalmente inutil.
Ahora algo mas complejo... aunque no por ello util:
SUB #7,inst ;Para reajustar el puntero de instruccion
SUB #6,pos ; Esto tambien
MOV >inst,>pos
SEQ inst,inst+1 ;Aqui esta el problema XD
JMP -2
JMP -14 ;Al proximo paso
pos DAT #-9
inst DAT #0 ;Los valores que quedaran despues de copiarse a si mismos
DAT #2
Como se puede ver aqui hay instrucciones nuevas:
-La primera es SUB (de substract, restar ), funciona igual que el ADD, pero en vez de sumar, resta (logicamente es igual que hacer ADD de un numero negativo)
-La otra es SEQ (skip if equal, saltar si es igual), compara las dos instucciones y si son iguales se salta la siguiente instruccion
Veamos que hace el codigo entonces :
El DAT con la etiqueta pos, indica la posicion a donde se va a copiar, y el de la etiqueta inst, la instruccion que se va a copiar.
El DAT siguiente al de inst tiene siempre el valor #2, esto servira para comprobar si se acabo de copiar todo el codigo.
-Resta 7 al DAT que indica la instruccion a copiar (para que apunte al principio del codigo) [ SUB #7,inst ]
-Resta 6 al DAT que indica donde se copiara la instruccion (para que apunte a la proxima seccion donde se copiara) [ SUB #6,pos ]
-Copia la instruccion a la que apunta inst a la posicion que indica pos, y incrementa en 1 los dos (para que apunten al siguiente) [ MOV >inst,>pos ]
-Si inst es igual a lo que hay en la siguiente posicions, se salta la siguiente posicion [ SEQ inst,inst+1 ]
-Vuelve atras 2 instrucciones [ JMP -2 ]
-Vuelve atras 14 instrucciones (pasa al bucle siguiente) [ JMP -14 ]
Es decir, que se copia todo hacia atras, hasta que acaba y salta hacia atras, para continuar copiandose.La utilidad que tiene esto es poca, con un minimo cambio en cualquier parte del codigo que se este ejecutando, el programa falla.
Las opciones para cambiar el flujo del programa son:
-SEQ (explicado anteriormente)
-SNE (funciona al reves que SEQ) (Skip if Not Equal, saltar si no es igual)
-SLT (se salta la siguiente instruccion si el campo A es menor que el campo B) (Skip if Less Than, saltar si es menos de)
-JNZ, si el valor del campo A es distinto de 0, se salta a la posicion que indica el campo B (Jump if Not Zero, saltar si no es cero)
-JZ, como JZN, pero si el valor de A es 0 (Jump if Zero, saltar si es cero)
-DJN, como JNZ, pero decrementa previamente el valor de A (Decrement & Jump if Not zero, decrementar y saltar si no es cero)
-SPL, se crea un segundo proceso que empieza en la posicion indicada (Split, separar)
La unica que introduce algo nuevo es SPL, veamos un ejemplo:
SPL 0
MOV 0,1
- SPL 0, crea un proceso mas, que seguira en la misma instruccion (si, asi continuamente)- MOV 0,1 ... un clasico imp (como el primero de todo)
Lo que hace es generar muchos procesos, ejecutando todos el codigo del imp
Si lo ejecutamos veremos que aunque al principio el conjunto de imps avanzan relativamente rapido, poco a poco van mas lentos, esto es por la forma que hay de repartir el tiempo entre los procesos:
Durante el turno de cada programa se ejecuta un proceso suyo y este no se volvera a ejecutar hasta que lo hayan hecho el resto
Esto significa que cuantos mas procesos haya para el programa, mas habra que esperar para que se repita el mismo proceso (por esto y por otras cosas suele haber un limite de procesos por programa)
Ya no se me ocurre nada mas que pueda hacer falta para escribir un programa de Core Wars, asi que eso es todo por ahora.
Quien no tenga problemas con el ingles tiene un buen tutorial en [ http://vyznev.net/corewar/guide.html ]
Actualizacion: Uno mas ( este no lo explicare :)}, es bastante sencillo )
;name Code Runner
;author Kenkeiras
ADD #4,3
SPL >2
JMP -2
DAT #1,#1
Suerte
Resumiendo, lo que vimos hasta ahora fue:
;Comentarios
;name nombre del programa
;author autor
MOV A,B ;Copia A en B
ADD A,B ;Añade A a B
JMP A ;Se salta la instruccion A
DAT A,B ;Un espacio para datos
Formas de indicar una direccion:
-Inmediata, por de la posicion donde esta el valor, se indica con un '#'
-Directa, por la posicion actual, se representa con '$' (o sin nada)
-Indirecta, por el valor de la posicion indicada, se indica con un '*' si es el primer campo (A), o con '@' si es el segundo campo (B)
Pero hay mas formas de indicar una direccion de forma indirecta:
- La del campo A, restandole 1 antes, '{'
- La del campo B, restandole 1 antes, '<'
- La del campo A, sumandole 1 despues, '}'
- La del campo B, sumandole 1 despues, '>'
Por ejemplo, se podria modificar el programa "dwarf"
;name Dwarf
;author A. K. Dewdney
dwarf ADD #4, bomb
MOV bomb, @bomb
JMP dwarf
bomb DAT #0
Haciendo que llene todos los espacios de memoria 1 a 1, en vez de cuatro en cuatro, y de paso eliminamos una instruccion (con lo que el programa es mas rapido)
dwarf MOV bomb, >bomb
JMP dwarf
bomb DAT #1
Veamos las diferencias, la primera es que ya no esta la instruccion ADD por que lo que hacia (cambiar el valor de "bomb" para evitar estar siempre "golpeando la misma zona")ahora lo hace el MOV.
La segunda es el campo B de la instruccion MOV incrementa el valor del campo B de "bomb" uno de cada vez (por el '>').
La ultima es que el valor al que apunta "bomb" al principio es el siguiente ('#1'), ya que al no haber ADD y a que el incremento es posterior, si fuera el mismo ('#0'), se sobreescribiria, algo totalmente inutil.
Ahora algo mas complejo... aunque no por ello util:
SUB #7,inst ;Para reajustar el puntero de instruccion
SUB #6,pos ; Esto tambien
MOV >inst,>pos
SEQ inst,inst+1 ;Aqui esta el problema XD
JMP -2
JMP -14 ;Al proximo paso
pos DAT #-9
inst DAT #0 ;Los valores que quedaran despues de copiarse a si mismos
DAT #2
Como se puede ver aqui hay instrucciones nuevas:
-La primera es SUB (de substract, restar ), funciona igual que el ADD, pero en vez de sumar, resta (logicamente es igual que hacer ADD de un numero negativo)
-La otra es SEQ (skip if equal, saltar si es igual), compara las dos instucciones y si son iguales se salta la siguiente instruccion
Veamos que hace el codigo entonces :
El DAT con la etiqueta pos, indica la posicion a donde se va a copiar, y el de la etiqueta inst, la instruccion que se va a copiar.
El DAT siguiente al de inst tiene siempre el valor #2, esto servira para comprobar si se acabo de copiar todo el codigo.
-Resta 7 al DAT que indica la instruccion a copiar (para que apunte al principio del codigo) [ SUB #7,inst ]
-Resta 6 al DAT que indica donde se copiara la instruccion (para que apunte a la proxima seccion donde se copiara) [ SUB #6,pos ]
-Copia la instruccion a la que apunta inst a la posicion que indica pos, y incrementa en 1 los dos (para que apunten al siguiente) [ MOV >inst,>pos ]
-Si inst es igual a lo que hay en la siguiente posicions, se salta la siguiente posicion [ SEQ inst,inst+1 ]
-Vuelve atras 2 instrucciones [ JMP -2 ]
-Vuelve atras 14 instrucciones (pasa al bucle siguiente) [ JMP -14 ]
Es decir, que se copia todo hacia atras, hasta que acaba y salta hacia atras, para continuar copiandose.La utilidad que tiene esto es poca, con un minimo cambio en cualquier parte del codigo que se este ejecutando, el programa falla.
Las opciones para cambiar el flujo del programa son:
-SEQ (explicado anteriormente)
-SNE (funciona al reves que SEQ) (Skip if Not Equal, saltar si no es igual)
-SLT (se salta la siguiente instruccion si el campo A es menor que el campo B) (Skip if Less Than, saltar si es menos de)
-JNZ, si el valor del campo A es distinto de 0, se salta a la posicion que indica el campo B (Jump if Not Zero, saltar si no es cero)
-JZ, como JZN, pero si el valor de A es 0 (Jump if Zero, saltar si es cero)
-DJN, como JNZ, pero decrementa previamente el valor de A (Decrement & Jump if Not zero, decrementar y saltar si no es cero)
-SPL, se crea un segundo proceso que empieza en la posicion indicada (Split, separar)
La unica que introduce algo nuevo es SPL, veamos un ejemplo:
SPL 0
MOV 0,1
- SPL 0, crea un proceso mas, que seguira en la misma instruccion (si, asi continuamente)- MOV 0,1 ... un clasico imp (como el primero de todo)
Lo que hace es generar muchos procesos, ejecutando todos el codigo del imp
Si lo ejecutamos veremos que aunque al principio el conjunto de imps avanzan relativamente rapido, poco a poco van mas lentos, esto es por la forma que hay de repartir el tiempo entre los procesos:
Durante el turno de cada programa se ejecuta un proceso suyo y este no se volvera a ejecutar hasta que lo hayan hecho el resto
Esto significa que cuantos mas procesos haya para el programa, mas habra que esperar para que se repita el mismo proceso (por esto y por otras cosas suele haber un limite de procesos por programa)
Ya no se me ocurre nada mas que pueda hacer falta para escribir un programa de Core Wars, asi que eso es todo por ahora.
Quien no tenga problemas con el ingles tiene un buen tutorial en [ http://vyznev.net/corewar/guide.html ]
Actualizacion: Uno mas ( este no lo explicare :)}, es bastante sencillo )
;name Code Runner
;author Kenkeiras
ADD #4,3
SPL >2
JMP -2
DAT #1,#1
Suerte
domingo, 6 de diciembre de 2009
Jugando a Core Wars [1° Parte/2]
Aqui veremos como funciona el juego Core wars, en el que hay que escribir un programa que intente eliminar a sus oponentes (para esto hay varios metodos... hacer que dividan por cero, que intenten ejecutar algo que no sea codigo,etc )
No voy a explicar como instalarlo, ya que hay muchos programas que sirven para jugar, puedes encontrar muchos aqui: http://homepages.paradise.net.nz/~anton/cw/corewar-faq.html#CoreWarSystems
En los repositorios de Ubuntu/Debian hay un paquete llamado corewars [ sudo apt-get install corewars ] que sirve perfectamente, pero es posible que despues no este en el menu, si es asi tendras que abrir un terminal y lanzar corewars
El lenguaje que se usa (llamado Redcode) es bastante parecido al Ensamblador, asi que aunque quien maneje este tendra mucho trabajo adelantado (se usan ADD's, MOV's, JMP's...), para est@s ultim@s hay que destacar que la sintaxis es mas parecida a la de AT&T que a la de Intel (por ejemplo en el ADD el primer argumento es la cantidad a añadir y la segunda donde se añadira), se explicara todo como si no se tuviera ninguna nocion de ensamblador.
Nota: desde ya mismo perdon por algunas licencias que me tomare para intentar hacer mas sencillo todo (como llamar "bytes" a las posiciones de memoria)
Como primer ejemplo utilizaremos el programa mas sencillo, llamado imp (de impulso):
;name Imp
;author Walter Hofmann
mov 0,1
Si lo ejecutamos veremos que va llenando la memoria byte a byte (si se le puede llamar asi), uno de cada vez.
Veamos como es el codigo... lo que va despues de un ';' es un comentario (no tiene relevancia en el juego), algunos MARS (las maquinas virtuales donde suceden los "combates") buscan cierta informacion en los comentarios, por ejemplo los que despues de el ';' llevan la palabra "name", especifican el nombre del programa, y los que despues del ';' llevan "author", muestran el nombre del autor del programa.
Hasta ahora no paso nada que afectase a la "maquina" que ejecuta el programa, ahora viene lo divertido,el codigo MOV 0,1 copia la instruccion (MOV) que esta en la posicion 0 desde el codigo (el propio codigo) hasta la posicion 1 desde el codigo, la posicion de memoria siguiente, con lo que la instruccion se copia a la siguiente posicion y despues se ejecuta lo que haya en la siguiente posicion ( si, el mismo codigo otra vez ).
Para entenderlo mejor veamos rapidamente como funciona la maquina:
La memoria de la maquina es circular (no hay punto inicial ni final), es lineal (solo se puede ir hacia adelante o hacia atras) y es relativa (solo se puede especificar una posicion a partir de la actual, no se puede decir por ejemplo, la posicion 74).
El procesador de la maquina ejecuta una instruccion ( que siempre ocupan 1 "byte" ) y a menos que la instruccion implique un cambio en el flujo del programa (JMP, JNZ... ya se explicaran despues) a continuacion se ejecuta la siguiente, si no hay ninguna o la operacion no esta permitida (como una division por 0), el proceso "muere".
Entonces nustro ejemplo pasaria algo asi:
t=0
...
---------------
| ??? |
---------------
| MOV 0,1 | <- (Se va a ejecutar esto)
---------------
| ??? |
---------------
| ??? |
---------------
...
t=1 (despues de ejecutar la primera instruccion)
...
--------------
| ??? |
--------------
| MOV 0,1 |
--------------
| MOV 0,1 | <- (Se va a ejecutar esto)
--------------
| ??? |
--------------
...
t=2 (despues de la segunda instruccion)
...
--------------
| ??? |
--------------
| MOV 0,1 |
--------------
| MOV 0,1 |
--------------
| MOV 0,1 | <- (Se va a ejecutar esto)
--------------
| ??? |
--------------
...
Asi el programa va "haciendo el camino" y sigue hasta que algo lo detenga.
Ahora veamos algo un poco mas complejo.
;name Dwarf
;author A. K. Dewdney
dwarf ADD #4, bomb
MOV bomb, @bomb
JMP dwarf
bomb DAT #0
Aqui se introducen muchas mas posibilidades, empezando por esta:
bomb DAT #0
Esto significa, hay un "byte" que no contiene ninguna instruccion, sino datos, y a esta posicion tiene la etiqueta "bomb" (para no tener que ver donde seria su direccion con cada nueva instruccion), su uso es bastante simple, si alguien intenta ejecutarlo el proceso falla, y se puede utilizar para almacenar datos (de ahi su nombre, DAT).
La segunda es:
dwarf ADD #4, bomb
Un "byte" con la etiqueta "dwarf" y con la instruccion ADD, que añade el valor del primer argumento (en este caso 4), a lo que este en la segunda posicion (en este caso a lo que tiene la etiqueta "bomb" ).
Despues tenemos:
MOV bomb, @bomb
Como ya vimos en el primer ejemplo, la instruccion MOV copia lo que haya en el primer valor, en el segundo,pero en este caso el segundo valor se utiliza para indicar donde se va a copiar...me explico:
Hay tres grupos de formas de indicar una direccion, inmediata, directa e indirecta.
La inmediata es la que se toma partiendo de la posicion de donde se toma el valor, se indica con un '#' antes del valor (por ejemplo, el DAT o el primer valor del ADD).
La directa es la que se calcula partiendo de la posicion actual, se indica con un '$' o no añadiendo nada (por ejemplo, en el primer valor del MOV o en el JMP).
La indirecta, es la que se calcula partiendo de la posicion que indique el "byte" que se indique, dependiendo de si es el que indica el primero (campo A) o el segundo argumento (campo B) del "byte" se indican con un '*' o '@' respectivamente (se pueden hacer mas cosas, pero ya me estoy extendiendo demasiado por ahora)
Entonces MOV bomb, @bomb copia lo que haya en la posicion "bomb" a donde apunte el campo B de "bomb".
Por ultimo...
JMP dwarf
La instruccion JMP salta a la posicion que se indique, en este caso la posicion con la etiqueta dwarf (el principio del codigo).
En resumen, lo que hace el codigo es:
- Añade 4 a la posicion que apunta "bomb" (MOV #4,bomb)
- Copia "bomb" a la posicion que apunta (MOV bomb,@bomb)
- Vuelve al principio (JMP dwarf)
Asi que va llenando la memoria de DAT's, (si algun programa los intenta ejecutar falla), por ejemplo, contra un imp, podria ocurrir esto.
t=0
...
---------------
| MOV 0,1 |
---------------
| MOV 0,1 | <- (Se va a ejecutar esto)
---------------
| ??? |
---------------
| ??? |
---------------
...
t=1 (cuando el imp se copia a la siguiente posicion, y en el mismo "turno" el "bomb" del programa anterior se copia a la misma posicion)
... ...
--------------- ----------------
| MOV 0,1 | | MOV 0,1 |
--------------- ----------------
| MOV 0,1 | | MOV 0,1 |
--------------- => -----------------
| MOV 0,1 | <- (Se va a ejecutar) | DAT | <-
--------------- ------------------
| ??? | | ??? |
--------------- -----------------
... ...
Esto es todo por ahora... hay una guia bastante completa en [http://vyznev.net/corewar/guide.html]
Suerte
No voy a explicar como instalarlo, ya que hay muchos programas que sirven para jugar, puedes encontrar muchos aqui: http://homepages.paradise.net.nz/~anton/cw/corewar-faq.html#CoreWarSystems
En los repositorios de Ubuntu/Debian hay un paquete llamado corewars [ sudo apt-get install corewars ] que sirve perfectamente, pero es posible que despues no este en el menu, si es asi tendras que abrir un terminal y lanzar corewars
El lenguaje que se usa (llamado Redcode) es bastante parecido al Ensamblador, asi que aunque quien maneje este tendra mucho trabajo adelantado (se usan ADD's, MOV's, JMP's...), para est@s ultim@s hay que destacar que la sintaxis es mas parecida a la de AT&T que a la de Intel (por ejemplo en el ADD el primer argumento es la cantidad a añadir y la segunda donde se añadira), se explicara todo como si no se tuviera ninguna nocion de ensamblador.
Nota: desde ya mismo perdon por algunas licencias que me tomare para intentar hacer mas sencillo todo (como llamar "bytes" a las posiciones de memoria)
Como primer ejemplo utilizaremos el programa mas sencillo, llamado imp (de impulso):
;name Imp
;author Walter Hofmann
mov 0,1
Si lo ejecutamos veremos que va llenando la memoria byte a byte (si se le puede llamar asi), uno de cada vez.
Veamos como es el codigo... lo que va despues de un ';' es un comentario (no tiene relevancia en el juego), algunos MARS (las maquinas virtuales donde suceden los "combates") buscan cierta informacion en los comentarios, por ejemplo los que despues de el ';' llevan la palabra "name", especifican el nombre del programa, y los que despues del ';' llevan "author", muestran el nombre del autor del programa.
Hasta ahora no paso nada que afectase a la "maquina" que ejecuta el programa, ahora viene lo divertido,el codigo MOV 0,1 copia la instruccion (MOV) que esta en la posicion 0 desde el codigo (el propio codigo) hasta la posicion 1 desde el codigo, la posicion de memoria siguiente, con lo que la instruccion se copia a la siguiente posicion y despues se ejecuta lo que haya en la siguiente posicion ( si, el mismo codigo otra vez ).
Para entenderlo mejor veamos rapidamente como funciona la maquina:
La memoria de la maquina es circular (no hay punto inicial ni final), es lineal (solo se puede ir hacia adelante o hacia atras) y es relativa (solo se puede especificar una posicion a partir de la actual, no se puede decir por ejemplo, la posicion 74).
El procesador de la maquina ejecuta una instruccion ( que siempre ocupan 1 "byte" ) y a menos que la instruccion implique un cambio en el flujo del programa (JMP, JNZ... ya se explicaran despues) a continuacion se ejecuta la siguiente, si no hay ninguna o la operacion no esta permitida (como una division por 0), el proceso "muere".
Entonces nustro ejemplo pasaria algo asi:
t=0
...
---------------
| ??? |
---------------
| MOV 0,1 | <- (Se va a ejecutar esto)
---------------
| ??? |
---------------
| ??? |
---------------
...
t=1 (despues de ejecutar la primera instruccion)
...
--------------
| ??? |
--------------
| MOV 0,1 |
--------------
| MOV 0,1 | <- (Se va a ejecutar esto)
--------------
| ??? |
--------------
...
t=2 (despues de la segunda instruccion)
...
--------------
| ??? |
--------------
| MOV 0,1 |
--------------
| MOV 0,1 |
--------------
| MOV 0,1 | <- (Se va a ejecutar esto)
--------------
| ??? |
--------------
...
Asi el programa va "haciendo el camino" y sigue hasta que algo lo detenga.
Ahora veamos algo un poco mas complejo.
;name Dwarf
;author A. K. Dewdney
dwarf ADD #4, bomb
MOV bomb, @bomb
JMP dwarf
bomb DAT #0
Aqui se introducen muchas mas posibilidades, empezando por esta:
bomb DAT #0
Esto significa, hay un "byte" que no contiene ninguna instruccion, sino datos, y a esta posicion tiene la etiqueta "bomb" (para no tener que ver donde seria su direccion con cada nueva instruccion), su uso es bastante simple, si alguien intenta ejecutarlo el proceso falla, y se puede utilizar para almacenar datos (de ahi su nombre, DAT).
La segunda es:
dwarf ADD #4, bomb
Un "byte" con la etiqueta "dwarf" y con la instruccion ADD, que añade el valor del primer argumento (en este caso 4), a lo que este en la segunda posicion (en este caso a lo que tiene la etiqueta "bomb" ).
Despues tenemos:
MOV bomb, @bomb
Como ya vimos en el primer ejemplo, la instruccion MOV copia lo que haya en el primer valor, en el segundo,pero en este caso el segundo valor se utiliza para indicar donde se va a copiar...me explico:
Hay tres grupos de formas de indicar una direccion, inmediata, directa e indirecta.
La inmediata es la que se toma partiendo de la posicion de donde se toma el valor, se indica con un '#' antes del valor (por ejemplo, el DAT o el primer valor del ADD).
La directa es la que se calcula partiendo de la posicion actual, se indica con un '$' o no añadiendo nada (por ejemplo, en el primer valor del MOV o en el JMP).
La indirecta, es la que se calcula partiendo de la posicion que indique el "byte" que se indique, dependiendo de si es el que indica el primero (campo A) o el segundo argumento (campo B) del "byte" se indican con un '*' o '@' respectivamente (se pueden hacer mas cosas, pero ya me estoy extendiendo demasiado por ahora)
Entonces MOV bomb, @bomb copia lo que haya en la posicion "bomb" a donde apunte el campo B de "bomb".
Por ultimo...
JMP dwarf
La instruccion JMP salta a la posicion que se indique, en este caso la posicion con la etiqueta dwarf (el principio del codigo).
En resumen, lo que hace el codigo es:
- Añade 4 a la posicion que apunta "bomb" (MOV #4,bomb)
- Copia "bomb" a la posicion que apunta (MOV bomb,@bomb)
- Vuelve al principio (JMP dwarf)
Asi que va llenando la memoria de DAT's, (si algun programa los intenta ejecutar falla), por ejemplo, contra un imp, podria ocurrir esto.
t=0
...
---------------
| MOV 0,1 |
---------------
| MOV 0,1 | <- (Se va a ejecutar esto)
---------------
| ??? |
---------------
| ??? |
---------------
...
t=1 (cuando el imp se copia a la siguiente posicion, y en el mismo "turno" el "bomb" del programa anterior se copia a la misma posicion)
... ...
--------------- ----------------
| MOV 0,1 | | MOV 0,1 |
--------------- ----------------
| MOV 0,1 | | MOV 0,1 |
--------------- => -----------------
| MOV 0,1 | <- (Se va a ejecutar) | DAT | <-
--------------- ------------------
| ??? | | ??? |
--------------- -----------------
... ...
Esto es todo por ahora... hay una guia bastante completa en [http://vyznev.net/corewar/guide.html]
Suerte
Suscribirse a:
Entradas (Atom)