Un par de películas interesantes

Me pregunta un lector cómo hacían los chavales de los 80 para aprender a programar el C64 y desarrollar aquellos juegos.

Ya comentaba al comienzo del blog que, al menos en la España de los 80, circulaba poca información. Había algunos libros y algunas revistas. De los primeros, me gustaban los libros blancos y rojos de Data Becker, y de las segundas “Commodore World” y “Commodore Magazine”. Por supuesto, no existía Internet, aunque empezaba a haber algunos servicios en línea (las famosas BBS’s).

Información 80.PNG

En Estados Unidos, Reino Unido y Alemania sí había más información. Si buscáis en Archive.org encontraréis bastantes libros en inglés de aquella época. Aun así, la informática, o al menos la informática personal, estaba en sus comienzos también allí.

Entonces… ¿cómo aprendían los chavales? Pues básicamente eran autodidactas. Suplían la falta de formación e información con muchas ganas, mucho ingenio y muchas horas de dedicación.

Hay un documental que describe este proceso en el caso del Reino Unido: “From bedrooms to billions” (2014). No he conseguido localizarla en las plataformas de streaming habituales (Netflix, Amazon, Movistar, etc.), pero sí he localizado una página web que parece específica de la película:

https://frombedroomstobillions.com/

También relacionada con el C64, aunque no específicamente con el tema de los jóvenes programadores, hay otra película que me gusta: “The Commodore Story” (2018). Se trata de otro documental que revisa la historia de Commodore en general. Incluye muchas entrevistas a los protagonistas de aquella época, incluyendo al hijo de Jack Tramiel y los ingenieros que diseñaron muchos de sus equipos.

Nuevamente, no la he encontrado en las plataformas de streaming habituales, pero sí he localizado esta página:

https://thecommodorestory.com/

¡¡Que las disfrutéis!!

Documentales.PNG

Futuro

En su momento hablamos de desarrollar varios juegos con enfoques diferentes, complejidades crecientes, etc. Pero después de más de 50 entradas, 23 versiones del proyecto, y 200 páginas de contenido, se hacen aconsejables una parada y reflexión.

Hay un autor canadiense llamado Alexander K. Dewdney que en los 80 escribía en Scientific American sobre informática y matemáticas. Sus artículos me gustaban mucho, porque tenían un planteamiento abstracto y, en general, no acababa de resolver completamente los problemas que planteaba, dejando ese reto al lector.

En su día –y habrán pasado más de 30 años– leí un artículo suyo sobre cómo desarrollar un juego de damas, o juegos de tablero en general, que me dejó muy prendado. Quién sabe, quizás me anime con el reto 30 años después y con un C64…

HVSW.

Asteroids: conclusiones

A lo largo de unas 50 entradas y 23 versiones del proyecto, hemos desarrollado paso a paso un juego clásico en ensamblador.

Las principales conclusiones que saco del proceso son:

  • No es suficiente con saber ensamblador del 6510. Además, hay que dominar el mapa de memoria y el hardware del C64. Un buen conocimiento de los chips especiales (VIC, SID y CIAs) es fundamental. Y también del Kernal, aunque no tanto.
  • Es muy importante que el proceso de desarrollo sea paso a paso o incremental. Hay que empezar por lo más sencillo y nuclear, e ir completándolo poco a poco. No parece viable obtener un producto completo de forma directa, especialmente si es complejo.
  • Interesa usar herramientas modernas como CMB prg Studio y VICE. Ni me quiero imaginar cómo podría ser la tarea si se intentara directamente sobre un C64.
  • Disponer de unas librerías de programación para sprites, sonido, entrada / salida, etc., también es muy importante para ser eficientes. Si el programador no dispone de ellas, siempre puede desarrollarlas y mejorarlas con cada juego.
  • Hay que plantearse retos asumibles. Y luego ir subiendo el listón. No vamos a sacar “Uridium” a la primera.
  • El código tiene que estar debidamente estructurado. No podemos tener un único fichero “asm”. Tiene que haber varios ficheros, y estos tiene que ser autocontenidos. Como decían los clásicos “alta cohesión y bajo acomplamiento”.
  • Los juegos suelen tener una inicialización y una actualización. La inicialización es el código que prepara el juego; por tanto, se ejecuta una vez. La actualización es el código que se ejecuta en cada ciclo del bucle de juego. Se utiliza para leer joystick y/o teclado, actualizar posiciones, disparar, detectar colisiones, hacer animaciones, reproducir sonido, etc.
  • El concepto de bucle de juego es muy importante también. El bucle de juego es la ejecución de las actualizaciones. Se ejecuta repetitivamente hasta que el juego termina. Hay tareas que se pueden ejecutar completas en cada ciclo, y otras tareas que hay que ejecutarlas a lo largo de varios ciclos porque, si las ejecutáramos en un único ciclo, serían imperceptibles o para hacerlas perceptibles dejarían el juego “enganchado”.
  • El ensamblador es tan rápido que hay tareas que, para que se puedan hacer bajo control, tienen que ser ralentizadas. Algunos ejemplos son los movimientos de la nave o los disparos. Esta ralentización se suele hacer mediante un “retardo”.
  • Es mejor hacer las cosas bien desde el principio, que corregir los errores en una fase tardía del proyecto, cuando el diseño ya está muy avanzado. No obstante, somos humanos y nos equivocaremos. Al menos, aprendamos de los errores.
  • Salvo que venga muy a cuento, no pongáis información en la zona derecha de la pantalla. Dejad que los sprites se muevan en libertad.
  • Tenemos sprites, caracteres personalizados y bitmaps. Cada cosa tiene su uso. Los sprites son limitados, sólo tenemos ocho. Hay que hacer un uso razonable de los recursos.
  • Las fórmulas matemáticas son un horror en ensamblador. Es mucho más sencillo usar tablas de datos. Y CBM prg Studio tiene un “data generator”.
  • Os encontraréis situaciones imprevistas como letras que desaparecen de la pantalla, asteroides que siempre se expanden, programas que se cuelgan, explosiones inesperadas, etc. Hay que estar preparado para ellas e investigarlas. Esto os consumirá mucho tiempo y esfuerzo.
  • Con frecuencia lo perfecto es enemigo de lo bueno. Quizás los disparos podrían estar más centrados respecto a la nave, pero, ¿cuánto me costaría hacerlo perfecto? Si la nave mirara siempre en la misma dirección podría resolverlo con relativa facilidad, pero admite ocho direcciones. ¿Estoy dispuesto a asumir el coste de hacerlo perfecto? ¿Hay alguna solución subóptima?
  • Es importante reutilizar ideas e intentar ser coherentes en los diseños. Si los asteroides son una mezcla entre la nave y los disparos, porque son sprites como la nave, pero los hay activos e inactivos como los disparos, pues no reinventemos la rueda.
  • Es interesante meter niveles de dificultad progresivos. Hay recursos para generar información pseudoaletoria (relojes del sistema).
  • La detección de colisiones, ya sea sprite – sprite o sprite – texto no es sencilla. Con frecuencia implicará el uso de las posiciones para averiguar con precisión quién choca con qué.
  • La animación de explosiones, igual que la reproducción del sonido, son ejemplos típicos de tareas que interesa extender a lo largo de varios ciclos del bucle de juego.
  • Los juegos no sólo tienen la pantalla de juego (la obvia). También tienen pantallas de carga, pantallas finales, pantallas de puntuación y records, etc. Diseñar las diferentes pantallas es fácil, pero la correcta transición entre ellas puede tener algo más de miga.
  • Lo normal es que los juegos se puedan jugar varias veces seguidas en una “sesión de partidas”. Cuidado con las inicializaciones en este caso, especialmente si confías en la inicialización implícita de las variables mediante directivas “byte” y similares.
  • El SID es complejillo. El manejo de librerías simplifica mucho. Y el uso de tablas para separar música o sonido de programación también.
  • A los humanos nos gustan los números en base diez. La solución obvia, que sería usar codificación y aritmética BCD, no siempre es viable. Siempre está la opción de usar codificación y aritmética binarias, y convertir a BCD antes de imprimir los datos.
  • A programar se aprende programando, y sufriendo en tus carnes los errores. Y disfrutando mucho con el proceso y el resultado, claro.

Así que, lo dicho, espero que hayáis disfrutado mucho del proceso y, sobre todo, que os sirva de inspiración para vuestros propios proyectos.

Asteroids: mapa de memoria y librerías mejoradas

La versión final del proyecto, que es la versión 23, tiene esta distribución en memoria. Nos la da CBM prg Studio al ensamblar:

Asteroids - Asteroids mapa memoria.PNG

Es decir, el juego consta de cinco segmentos de memoria:

  • $0801 – $080c, 12 bytes: Este es el cargador BASIC.
  • $0810 – $1be2, 5.075 bytes: Este es el grueso del juego, librerías incluidas.
  • $3000 – $32ff, 768 bytes: Es la definición de los 12 “frames” para los sprites.
  • $3800 – $4fcf, 6.096 bytes: Son los caracteres personalizados (4 KB) y las pantallas (2 x 1 KB).
  • $c000 – $c094, 149 bytes: Es un programa de prueba para probar la conversión de codificación binaria a BCD. Se podría quitar del proyecto.

En definitiva, vemos como un juego sencillo ya casi ocupa 12 KB. Por supuesto, se podría reducir un poco, por ejemplo, sustituyendo la pantalla de juego (1 KB) por la impresión de una simple línea, quitando librerías o rutinas de librería que no se utilizan, o replanteando el uso de los caracteres personalizados (4 KB).

Pero la idea subyacente es la misma: el C64 tiene muy poca memoria (64 KB, con partes de RAM y ROM solapadas), y para hacer virguerías hay que echarle mucho ingenio, y jugar con los diferentes mapas de memoria posibles. Aquí hemos utilizado el mapa estándar.

Por lo demás, durante el proceso no sólo hemos desarrollado un juego. También hemos mejorado unas librerías. Partíamos de las librerías disponibles aquí. Y, como parte del proceso, hemos mejorado las siguientes librerías:

Librería Rutina / variable Mejora
LibChars.asm configuraColores Admite color del borde
LibSprites.asm posicionaSprite Admite coordenada X de 9 bits
  configuraAvanzada Permite expandir y “desexpandir”
LibText.asm pintaHex2 Permite pintar un número hexadecimal en una posición de pantalla concreta
  pintaCadena3 Permite pintar una cadena de caracteres en una posición de pantalla concreta
  biteToBCD Permite convertir un byte en binario a su codificación BCD
  bitesToBCD Idem con dos bytes
LibSonido.asm offsetVoces Renumera las voces como 0, 1 y 2
LibMath.asm maximo Nueva rutina para calcular el máximo de dos números
  minimo Nueva rutina para calcular el mínimo de dos numeros

Las nuevas librerías quedan disponibles aquí.

Como se habrá podido ver, el uso de unas librerías de rutinas (o macros) simplifica mucho el desarrollo de aplicaciones. Hacerlo desde cero hubiera sido mucho más complejo. Cada programador debe buscar las librerías que sean de su agrado, o desarrollar unas propias.


Nuevas librerías: Lib – V2

Asteroids: el reto de los asteroides que siempre se expanden (solución)

No podemos rematar la faena sin resolver el gran misterio. ¿Por qué cada vez había más asteroides expandidos y menos sin expandir?

La respuesta no estaba en la rutina “actualizaAsteroidesActivos”, como podría parecer, sino que estaba en la rutina “configuraAvanzada” de la librería “LibSprites.asm”. La versión original de esta rutina era así:

Asteroids - Rutina configuración avanzada

Si estudiamos la parte de la rutina dedicada a la expansión (líneas 148 – 164) veremos que la rutina es capaz de pasar de una situación inicial en que el sprite no está expandido, a otra situación final en que sí lo está. Esto se consigue haciendo “ora XXPAND” y “sta XXPAND”, para la expansión horizontal, y “ora YXPAND” y “sta YXPAND”, para la expansión horizontal.

Pero la rutina no es capaz de deshacer esa situación. Es decir, la rutina no es capaz de “desexpandir” un sprite que previamente ya está expandido.

Es decir, la rutina se diseñó para, partiendo de la situación inicial o de arranque del C64 en que ningún sprite está expandido, expandir los sprites que se desee. Pero no se diseñó para hacer también el camino contrario.

Por ello, según avanzaba el juego, algunos asteroides se expandían y otros no. Los expandidos nunca se “desexpandían”. Y los no expandidos, por el mero paso del tiempo y los juegos de probabilidades, antes o después acababan expandidos, sin poder salir de ahí. Al final, todos expandidos.

Sin embargo, a partir de la versión 19 del proyecto, esta rutina se mejora y pasa a ser así (sólo parte dedicada a la expansión):

Asteroids - Rutina configuración avanzada mejorada

Es decir, cuando “caExpansionH” vale 0:

  • Con “lda tablaSpr,x” se obtiene un byte con todos los bits a 0 menos el correspondiente al sprite, que estará a 1.
  • Con “eor #%11111111” se cambian todos los bits de ese byte. Es decir, quedan a 1 todos los bits, menos el correspondiente al sprite, que queda a 0.
  • Con “and XXPAND”y “sta XXPAND” lo que se consigue es desactivar la expansión horizontal del sprite en cuestión.

Y lo mismo para la expansión vertical cuando “caExpansionV” vale 0.

Espero que esto aclare el misterio. A mí me tuvo loco mucho tiempo 🙂 .

Asteroids: algunas sugerencias para el lector

Como hemos dicho, damos el juego por terminado en su versión 23. Eso no quiere decir que el juego sea perfecto, ni mucho menos. De hecho, es un juego relativamente sencillo.

Pero, viendo todo el proceso que nos ha llevado, y las dificultades que han surgido, sirve muy bien para ejemplificar lo complejo que puede llegar a ser desarrollar un juego en ensamblador.

Pensad ahora en vuestros clásicos favoritos: Uridium, Raid Over Moscow, Entombed, Commando, Green Beret, Ant Attack, Booga-Boo, etc. Eran meses de trabajo de equipos con varios especialistas: programadores, diseñadores gráficos, músicos, etc. ¡¡Y con las herramientas de los 80!! Vamos… unos héroes…

Asteroids - Uridium.PNG

Y aprovechando que el juego no es perfecto, aquí quedan algunas sugerencias para el lector con interés:

  • Guardar el record en un fichero y leerlo al empezar el juego.
  • Incluir en la pantalla inicial un bonito bitmap, o incluso un bitmap y una zona de texto.
  • Incluir música más allá del sonido de disparos y explosiones. Intentar reproducir la música mediante interrupciones.
  • Desarrollar una tecla de “hiperespacio” que haga que la nave aparezca en un punto aleatorio de la pantalla. Puede usarse cuando haya riesgo inminente de colisión.
  • Que al explotar los asteroides den lugar a otros asteroides más pequeños.
  • Que aparezcan ovnis en pantalla. Estos ovnis disparan a la nave y pueden colisionar con ella.
  • Etc.

En definitiva, a programar se aprende programando. Y equivocándose muchas veces. Así que… ¡¡mucho ánimo!!


Código del proyecto: Asteroids23

Asteroids: presentación de números en decimal – puntos y record

En primer lugar, los puntos y el record adolecen de un problema: sólo estamos usando un byte para cada uno. Por tanto, dado que cada asteroide destruido nos reporta diez puntos, esto nos da para un máximo de 25 asteroides (255 / 10 = 25,5). Parece poco.

Por tanto, lo primero es ampliar ambas variables para que ocupen dos bytes, el byte “lo” y el byte “hi”. Este cambio es bastante rutinario, y básicamente sólo hay que tener en cuenta dos cosas especiales:

  • Al sumar diez puntos por destruir un asteroide en la rutina “animaExplosionAsteroide”, hay que acordarse de sumarlos a la parte “lo”, y luego sumar el acarreo a la parte “hi”.
  • Al comparar los puntos con el record en la rutina “animaExplosionJugador”, dado que ahora ambos tienen parte “lo” y parte “hi”, hay que empezar por comparar los bytes más significativos (parte “hi”) y, en función del resultado de esa comparación, comparar o no las partes menos significativas (“lo”).

En segundo lugar, los puntos y el record serían candidatos ideales para la codificación BCD. Sus valores no se almacenan en ningún registro especial (VIC, SID, …), y la aritmética que hacemos con ellos es relativamente sencilla (básicamente sumar puntos de diez en diez). Esta medida facilitaría su presentación en pantalla en formato decimal.

Sin embargo, dado que en la entrada anterior ya hemos desarrollado una rutina que es capaz de convertir números codificados en binario a números codificados en BCD, ni siquiera el uso de BCD es necesario. Podemos seguir usando la codificación y la aritmética binarias, convertir a BCD antes de imprimir, e imprimir en decimal con “pintaBCD”.

Aplicando la misma solución que a las coordenadas X e Y (convertir a BCD antes de imprimir), vemos cómo los puntos ya aparecen en decimal, tanto en la pantalla de juego:

Asteroids - Puntos decimal.PNG

como en la pantalla final:

Asteroids - Puntos y record decimal.PNG

Y con esto podemos dar el juego por terminado en su versión 23 aunque, por supuesto, caben muchas mejoras, como comentaremos más adelante.


Código del proyecto: Asteroids23

Asteroids: presentación de números en decimal – coordenadas X e Y

La coordenada Y ocupa un byte y puede tomar los valores 0 a 255, aunque no todos caen dentro de la zona visible de la pantalla. La coordenada X ocupa dos bytes, aunque sólo se usan 9 bits. Por tanto, puede tomar los valores 0 a 511, aunque tampoco todos caen dentro de la zona visible de la pantalla.

En este caso, al superarse el intervalo 0 – 9, podríamos plantearnos dejar de usar la codificación binaria y pasar a usar la codificación y la aritmética BCD, todo con el objeto de facilitar la presentación de estas variables en pantalla en formato decimal.

Sin embargo, hay un problema. El VIC requiere que las coordenadas X e Y que se informan a los registros SP0X, SP0Y y siguientes ($d000 – $d00f) estén codificados en binario, no en BCD.

Por tanto, tenemos que seguir usando la codificación y la aritmética binarias. Podemos convertir a BCD antes de pintar en pantalla o desarrollar alguna rutina que, directamente desde la codificación binaria, imprima los números en decimal.

Y esto es lo que vamos a hacer: una rutina que partiendo de un byte en codificación binaria nos dé el número equivalente en codificación BCD. Y luego imprimiremos ese segundo número BCD en decimal.

Un byte puede tomar los valores decimales 0 – 255. Por tanto, para la codificación BCD necesitamos al menos tres nibbles o tres dígitos decimales (para almacenar el 2, el 5 y el otro 5). Y como en el C64 la unidad de memoria mínima que se puede asignar o reservar es el byte, reservaremos para el retorno de la rutina dos bytes o, lo que es lo mismo, cuatro nibbles o cuatro dígitos decimales. Por tanto, nos sobrará un nibble o dígito decimal.

Empecemos por lo sencillo: el nibble bajo del byte codificado en binario. El nibble bajo puede tomar los valores %0000 – %1111, que en decimal son los valores 0 – 15. El 0 sólo tiene un dígito decimal; por tanto, nos llegaría con un nibble BCD. Sin embargo, el 15 tiene dos dígitos decimales; por tanto, necesitamos dos nibbles BCD para codificarlo (un nibble para el 1 y otro nibble para el 5).

La conversión de lo primero (los 16 posibles valores del nibble bajo) a lo segundo (los nibbles o dígitos BCD) es fácil de conseguir mediante una tabla de conversión:

Nibble bajo Valor decimal Byte BCD Hi Byte BCD Lo
%0000 0 00 00
%0001 1 00 01
%0010 2 00 02
%0011 3 00 03
%0100 4 00 04
%0101 5 00 05
%0110 6 00 06
%0111 7 00 07
%1000 8 00 08
%1001 9 00 09
%1010 10 00 10
%1011 11 00 11
%1100 12 00 12
%1101 13 00 13
%1110 14 00 14
%1111 15 00 15

En definitiva, si el valor del nibble bajo lo pasamos al registro X o Y, y usamos ese registro como índice para acceder a la tabla, obtenemos fácilmente los nibbles o dígitos en BCD.

La conversión de binario a BCD ha sido más fácil de lo que cabía esperar. De hecho, me declaro un absoluto forofo de las tablas de datos. Son mucho más fáciles de usar, y seguro que incluso más rápidas, que las fórmulas matemáticas, que son un horror para implementar en ensamblador en cuanto tienen algo más complejo que sumas, restas, multiplicaciones por dos o divisiones por dos.

La versión en rutina del algoritmo anterior es así de fácil:

Asteroids - Rutina nibble0ToBCD.PNG

El problema es que el byte codificado en binario no sólo tiene el nibble bajo, también tiene el nibble alto. Y con él hay que hacer lo propio. Pero, cuidado, porque ahora el nibble alto “pesa” más que el nibble bajo. Es decir, la tabla de conversión es así:

Nibble alto Valor decimal Byte BCD Hi Byte BCD Lo
%0000 0 x 16 = 0 00 00
%0001 1 x 16 = 16 00 16
%0010 2 x 16 = 32 00 32
%0011 3 x 16 = 48 00 48
%0100 4 x 16 = 64 00 64
%0101 5 x 16 = 80 00 80
%0110 6 x 16 = 96 00 96
%0111 7 x 16 = 112 01 12
%1000 8 x 16 = 128 01 28
%1001 9 x 19 = 144 01 44
%1010 10 x 16 = 160 01 60
%1011 11 x 16 = 176 01 76
%1100 12 x 16 = 192 01 92
%1101 13 x 16 = 208 02 08
%1110 14 x 16 = 224 02 24
%1111 15 x 16 = 240 02 40

Nuevamente, la versión en rutina del algoritmo anterior es así (sólo cambian las tablas de datos):

Asteroids - Rutina nibble1ToBCD

Ahora, llamando a las dos rutinas anteriores y sumando sus resultados (suma decimal con “sed”), ya somos capaces de pasar de un byte codificado en binario (con su nibble bajo y su nibble alto) a dos bytes equivalentes con la codificación BCD:

Asteroids - Rutina byteToBCD

Y los dos bytes BCD resultantes ya se pueden imprimir en formato XXXX (cuatro dígitos decimales) con la rutina “pintaBCD”. Por ejemplo, para la coordenada Y:

Asteroids - Pinta Y en BCD

Por tanto, ya hemos resuelto el problema de imprimir en decimal (no en binario, ni en hexadecimal) un byte que contiene un número en codificación binaria.

Si alguna variable, como la coordenada X, no ocupa un byte, sino que ocupa dos bytes, es posible extender el razonamiento anterior tanto como sea necesario.

El resultado podemos verlo en la versión 23 del proyecto y aquí. Obsérvese cómo las coordenadas X e Y ya aparecen en decimal:

Asteroids - XY en decimal.PNG


Código del proyecto: Asteroids23

Asteroids: presentación de números en decimal – velocidad, ángulo y vidas

De todas las variables que tenemos que presentar en decimal, velocidad, ángulo y vidas son las más sencillas. Y son las más sencillas porque, por el rango de valores que toman actualmente, sus codificaciones binarias y BCD coinciden. Por tanto, podemos actuar como si ya estuvieran codificadas en BCD.

Efectivamente, la velocidad toma valores entre 0 y 3 y, en ese rango de valores, las codificaciones binaria y BCD son iguales. Lo mismo ocurre con el ángulo (0 – 7) y con las vidas (0 – 5). Las dos codificaciones empiezan a ser diferentes a partir del valor 10, que en binario se codifica como %0000-1010 y en BCD se codifica como %0001-0000. Pero hasta ahí son idénticas:

Número Codificación binaria Codificación BCD
0 0000-0000 0000-0000
1 0000-0001 0000-0001
2 0000-0010 0000-0010
3 0000-0011 0000-0011
4 0000-0100 0000-0100
5 0000-0101 0000-0101
6 0000-0110 0000-0110
7 0000-0111 0000-0111
8 0000-1000 0000-1000
9 0000-1001 0000-1001
10 0000-1010 0001-0000

Por tanto, en el caso de la velocidad, el ángulo y las vidas, podemos hacer cualquiera de estas cosas:

  • Cambiar para usar la codificación y la aritmética BCD. No merece la pena.
  • O seguir usando la codificación y la aritmética binaria.

Ni siquiera es necesario pasar usar “pintaBCD”. Se puede seguir usando “pintaHex2”, porque los números en el rango 0 – 9, además de codificarse igual en binario y BCD, también se pintan igual en decimal (“pintaBCD”) y en hexadecimal (“pintaHex2”):

Número Representación decimal Representación hexadecimal
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
10 10 a

En definitiva, para velocidad, ángulo y vidas no hace falta hacer nada, siempre y cuando sigan tomando valores entre 0 y 9. Ahora bien, si algún día se cambia el juego para, por ejemplo, meter 15 vidas, habrá que revisar esta decisión.