@ agnasg

permafrost-engine review

02-06-2021 11:17 AM

Estaba analizando este código fuente de un juego RTS (real time strategic, o juego de estrategia a tiempo real), y mi opinión en general coincide con los comentarios que aparecen en este hilo de discusión en hackers news (también en reddit, pero hace un año).

Bueno, no exactamente “excelente” pero tiene un buen nivel de calidad. El programador es un profesional. Me llama la atención la forma consistente y repetitiva tanto en hn como en reddit de comentarios como “bravo!”, “Nice and clean code”, “awesome”, “amazing”, en forma uniforme y generalizada. Bien inusual. Más bien raro.

Algunas observaciones:

Buena organización (mencionado en los comentarios y también por el programador). Esto claramente es lo que impacta desde el comienzo. Los juegos son piezas de software bien complicadas, por lo que mantener una consistente y clara forma de organizar los distintos componentes es la clave. He visto docenas de juegos que hacen un genuino intento en lograr esto, fracasando la mayor parte de las veces. En khpx los resultados han sido mixtos y mi apreciación es que al igual del manejo de las estructuras de datos, lograr una organización óptima, eficiente, clara, que facilite el mantenimiento del código no solamente es difícil, sino que consume una inmensa y costosisima cantidad de tiempo. Yo he ido dilatando esta labor pero es algo que hay que atacar a tiempo antes de perder el control del engine.

Uso de goto. Algunos comentadores aplaudieron el uso de “goto” de forma de generar una salida única para las funciones. Es decir, el código está lleno de cosas como esta:

static bool rstate_init (...)
{
    if(!rstate->sq_lock)
        goto fail_sq_lock;
    ...
    if(!rstate->sq_cond)
        goto fail_sq_cond;
    ...
fail_sq_cond:
    SDL_DestroyMutex(rstate->sq_lock);
fail_sq_lock:
    return false;
}

Y la respuesta es que es más fácil de seguir, o que es más facil agregar instrucciones en un punto único de salida. En mi opinión un “goto” nunca es más facil de seguir, y genera rápidamente código espaguetti indescifrable. Además, no se supone que las funciones deben tener unas 30-50 líneas (no más de 100)? Y que las funciones deben tener 1 quizás 2 actividades que realizar? Entonces por qué un único punto de salida es importante si debería haber en una función 1-2 salidas? De acuerdo a mi script bash, en la permafrost-engine hay 667 “goto”s. En khpx hay 0.

Es un proyecto grande, pues tiene 127k líneas de código (sin incluir scripts y utilities). khpx luego de 3 años tiene la mitad, algo más de 60k. En el hilo de reddit mencionan 38KLOC (hace un año), no sé cómo hacen el conteo de líneas de código. Yo hago un conteo crudo con mi script todo propósito / todo terreno en una línea de código Bash:

find . -type f -exec cat {} + | wc -l

Reinvención de la rueda. Esto es algo que yo he estado evadiendo al máximo en khpx, por ello utilizo algunas librerías como Dear Imgui y el STL (el standard template library). Nadie discute que el STL está suficientemente probado y optimizado. No hay razón para utilizar algo diferente. permafrost-engine re-implementa todo, incluyendo vectores, queues, y… ta ta: malloc, su propio sistema de manejo de memoria. Nada más por eso yo descartaría esta engine. Ni idea por qué los aplausos.

Poca documentación, y los pocos comentarios sufren el síndrome de inutilidad:

/* Submit and run the queued batch to completion */
render_thread_start_work();

Uso de macros. No usar macros es una buena práctica. permafrost-engine usa macros masivamente. Hay 1357 “#define”s. No sé, yo voy a seguir “no usándolos”, o usándolos al minimo: hay 170 defines en khpx.

Indirección redirigida. Si buscamos el caracter ‘&’ en permafrost-engine el resultado son 8282 matches. En khpx es 1350. ¿Pero por qué? Porque esta engine usa cosas como “&task->ctx” al máximo. Festival universal ilustrado de apuntadores. No hay nada malo per se en ello. Pero es una mala práctica en 2021.

Extra. Por cierto, ¿recuerdan mi post sobre *scanf? En permafrost-engine hay 53 ocurrencias, en khpx hay 0.

Variables / data structures globales. Excelente manejo. Todas están definidas como “static” y confinadas a su archivo. En khpx las estructuras de datos vuelan por todo el engine sin control de acceso alguno. Este es un punto que en algún momento tengo que corregir, por dificil que me parezca en este momento.

Conclusiones

Como digo al comienzo es un trabajo profesional y la engine es de alta calidad. Salvo los comentarios anteriores, fue una buena experiencia revisar el código y lo recomiendo altamente. De hecho voy a utilizar ideas de esta engine para resolver el problema que tiene khpx al manejar las estructuras de datos.

Mi página bitcoin

04-05-2021 8:09 AM

Este post lo comencé a escribir en 2017. Si por aquélla época hubiera comprado, siquiera un bitcoin, mi ganancia sería de 29x. La razón por lo que no lo hice es porque nunca tuve tiempo para entender lo que tenía que hacer. Por ejemplo, estos son los enlaces y comentarios que escribí por aquélla época:

  • En esta página se dice que el alerta integrado en la red bitcoin va a ser retirado. Se menciona Bitcoin Core 0.13.1 y Armory 0.94.1+ No hay un enlace así que un novato no sabe a qué se refiere Armory.
  • Al hacer en google “bitcoin Armory” el primer enlace es https://www.bitcoinarmory.com/
  • Si Ud. va a https://bitcoin.org/en/choose-your-wallet como es sugerido en el faq de reddit, por defecto no aparece Armory como un wallet. Aparece al hacer click en “Desktop”, pero el enlace es https://btcarmory.com/
  • Aquí dice que “bitcoinarmory.com is no longer Armory’s official website.” (bitcoinarmory.com ya no es el sitio oficial de Armory). Pero se requiere mucha búsqueda y análisis para determinar esto.

Yo pensaba que tenía que instalar el código fuente del wallet, bajar todas las transacciones (que son decenas de gigabytes) y entonces correr un nodo local.

No

Lo que hay que hacer es crear una wallet (o billetera). En este momento, mayo de 2021, la solución es Electrum (https://electrum.org/). Punto, sin más discusión. Hay que seguir TODAS las recomendaciones de seguridad, revisar el faq de bitcoin sobretodo la parte de seguridad (y otros artículos muy especialmente este).

Hay que tener los bitcoins en tu wallet. No se deben dejar los bitcoin en Coinbase y menos aun en Robinhood, porque es como si tuvieras bitcoins pero realmente son de ellos. Lo mismo con paypal y otros jugadores similares.

Mi confusión con bitcoin en 2017 se originó en cosas como estas:

El universo Bitcoin usa una jerga incomprensible: este reciente twitter por ejemplo:”Miners: it’s up to you to make Bitcoin great again by fixing transaction malleability. Fastest path forward: activate Segregated Witness.”

(“Mineros: depende de vosotros hacer que Bitcoin vuelva a ser grande arreglando la maleabilidad de las transacciones. El camino más rápido: activar el Testigo Segregado.”

Quién entiende eso.

No es que ahora sea más simple: es igual de enrevesado. Pero luego de quitar la jerga técnica, es simple:

  1. Crear una wallet en Electrum (https://electrum.org/)
  2. Antes de comprar vigila el precio en ftx.com y busca el mejor momento.
  3. Comprar bitcoins y colocarlos en tu wallet. ¿Cuánto? Lo que estés dispuesto a perder, o lo que realmente no necesites. Los bitcoin se pueden dividir hasta 8 decimales así que es posible comprar 0.00000001 BTC.
  4. Olvidarte de ellos (el precio va a subir y bajar como una montaña rusa). Ignora todo lo que se diga.
  5. Sentarte a esperar tus ganancias.
  6. Convierte un porcentaje de tus ganancias a otros instrumentos financieros para diversificar tu cartera.
  7. Felicidad total.

La dimensión desconocida

30-04-2021 7:29 PM

Droidscript , una aplicación que permite el desarrollo de aplicaciones Android usando Javascript ha sido unilateral y unánimente declarada por Google un malware, sin posibilidades de apelación. Esto significa que la aplicación ha sido removida del Play Store.

7 años de desarrollo han quedado en suspenso debido a una medida tomada por una empresa que delega su seguridad a scripts automatizados tan confiables como una hiena en las praderas de Tanzania. Estoy exagerando: Google no es una hiena, ni el internet es el Serengeti. Pero atender a los usuarios en forma automatizada es igual de incontrolable e incierto.

Noticias como las de Droidscript son aterradoras, pero más que eso, una sólida advertencia de que no podemos depender de una empresa que maneja su relación con los clientes de una forma fria, automática, algorítimica, kafkiana. El resultado parece ser que Google está permitiendo que esto suceda: las historias de terror ya tienen demasiado tiempo circulando como para que ellos las ignoren: y eso es lo que están haciendo. Nosotros no podemos cometer el mismo error, e ignorarlas también.

Ya hay voces en internet (enlace) que están dando repetidas advertencias. Al menos, si tenemos una aplicación en el App store de google no debemos usar sus productos de anuncios ( AdMob/AdSense), porque podemos ser acusados de fraude, al hacer click en nuestros propios anuncios.

Esto es una teoría, porque nadie sabe a ciencia ciertas las razones de estos bloqueos, porque no se suministran las razones. Google no quiere que se sepa cómo funcionan sus algoritmos.

Discusión en hacker news.

Misiones en khpx

27-04-2021 1:32 PM

Desde hace 4 años he estado desarrollando un juego espacial llamado khpx. En el enlace hay más información y hay una categoría de posts dedicados al juego.

En este momento, khpx es “a hard core low level full featured pixel art solo dev mmo space game” (traducción aproximada al español: “un juego de bajo nivel, con características avanzadas, diseño gráfico tipo pixel, desarrollado por un solo programador, multijugador ambientado en el espacio

En este post voy a hablar de misiones, o quests como se llaman en inglés. khpx tiene como piedra angular los quests, como Wizard101 o World of Warcraft.

Hay varias formas de progresar en khpx, siendo las misiones la más fácil y accesible. Es posible seguir un camino separado sin hacer ninguna misión, pero conseguir algunos equipos y acceder a algunos planetas es mucho más difícil.

Quiero comparar las misiones de khpx con una misión de Runescape, el MMORPG medieval. No por alguna razón en particular, simplemente que es el juego que he estado jugando últimanente (dejé Wow al año pasado, luego del desastre de Shadowlands).

Runescape tiene sus peculiaridades. Puedes comer en medio de una pelea, lo cual te hace recuperar los hitpoints, es decir tu salud o vida. Puedes cambiar de armas inclusive en medio de la pelea. En ese sentido es bastante libre. Pero. Para tu inventario tienes solamente una bolsa de 28 posiciones. Eso es todo lo que puedes cargar. No puedes comprar una bolsa más grande, o más bolsas. Toda la economía gira alrededor de esta limitación lo que permite mantener la oferta de los recursos baja. Las libertades con las peleas se ven compensadas con esa y otras limitaciones no tan frecuentes o tros mmo. Me refiero a los combates a bajo nivel, mi personaje es nivel 36, no tengo idea cómo son las cosas más adelante.

Voy a tomar un quest de Runescape para mostrar la serie de pasos que hay que dar para completarlo, y comparar con los quests de khpx, para ver sus diferencias y similitudes. Pero no lo incluí arriba en la lista de juegos con muchos quests, porque en realidad se puede progresar en Runescape sin hacer quests.

Por ejemplo, el quest “El rescate del principe Ali“. Prefiero este quest porque su ejecución tiene más o menos sentido. Por el contrario, el quest Ernest el Pollo es de esos quests que rayan en lo absurdo, no porque uno de los protagonistas termina convertido en pollo, sino que en la búsqueda de los elementos para restituirle su forma humana, hay que resolver un puzzle de bajar y subir palancas, lo cual siempre es irritante, en mi opinión.

Voy a resumir rápidamente todo lo que hay para resolver el quest del principe Ali, para ver el nivel de complejidad involucrado:

  1. Tienes que hablar con el canciller Hassan, quien te explica que el principe Ali ha sido capturado y se encuentra cautivo en una prisión en el pueblo de Draynor. Te pide ayuda para liberarlo, y te dice que hables con Osman fuera del palacio.
  2. Osman te da algunas instrucciones y te dice que para más detalles hables con su hija Leela.
  3. Leela te dice que el plan es copiar la llave de la celda donde el principe está cautivo, disfrazarlo, sobornar al carcelero, para finalmente liberar al principe.
  4. Para ello debes conseguir 3 rollos de lana, cuerda, tinte amarillo, 1 fresa roja, un pote de harina, cenizas, un cubo de agua, arcilla blanda, una barra de bronce, 3 cervezas y 50 monedas. No, nada más.
  5. Tienes que pelear con los guardias nivel 21, o escabullirte dentro de la prisión.
  6. Con todo eso distraes a Lady Keli, quien tiene la llave, la engañas, ella te muestra la llave, le sacas una copia, regresas con Osman que te va a hacer la copia con la barra de bronce.
  7. Hablas con  Aggie (la bruja)  para que haga una pasta para cambiar el color de la piel del principe.
  8. De nuevo a la prisión, de nuevo peleas con con los guardias nivel 21, distraes al carcelero, lo sobornas con las cervezas, abres la celda, disfrazas al principe y le aplicas la pasta para cambiarle el color de piel.
  9. Sales de la prisión y regresas con el canciller quien te dará tu recompensa.

Por supuesto, todo eso no lo puedes hacer de la forma tradicional, así que necesitas una guía. En los viejos buenos tiempo de La aventura original, Galatea, y Leisure Suit Larry, se suponía que tú tenías que adivinar qué hacer en los quests, y descubrir los puzzles. Hoy en día, al menos en Runescape y World of Warcraft, eso es casi imposible. Porque, en el caso del principe Ali, y suponiendo que se te ocurre lo de disfrazarlo, ¿cómo vas a descubrir quién te puede hacer la crema para cambiar la piel? Concedo que la bruja que lo hace está cerca, pero imaginar el escenario es poco probable, a menos que comiences un interminable ensayo y error.

En khpx, los puzzles y misiones en general están diseñados en forma similar, con características de todos, incluyendo Wizard 101, otro juego que he jugado durante más de una década.

Galatea es un juego tipo parser, similar a “La aventura original”,donde parte del juego es adivinar cuál es el comando o frase que va a permitir avanzar en el juego. Yo he minimizado esto agregando una instrucción en cónsola que indica qué es lo que hay que hacer: “Hablar con Brat”, “Capturar nave TTPP-23”, “Regresar a Mirbel, hablar con Werzaat”. Así que no hay que adivinar, no se necesitan guías como con Runescape. En cierta forma es como Wizard 101, donde en pantalla aparece una flecha y una instrucción del siguiente paso que hay que dar. Si el jugador va a tratar de conseguir una guía para descubrir lo que hay que hacer, por qué no facilitar el trabajo y presentarlo en pantalla.

Esta mecánica es en el modo de dificultad “Normal”. Hay otros dos modos “Difícil” e “Imposible”, donde no hay ayudas visuales. Los jugadores tendrán que recurrir al wiki o a las guías o recordar cómo se hace en el modo normal (que no es necesariamente igual). Los 3 niveles de dificultad están presentes en la actual versión, no se si eso va a permanecer en el tiempo, pero sospecho que puede cambiar.

Como ejemplo, esta es la guía del quest “Los mools te hacen feliz” . Mools es una de las monedas en khpx. Hay 5 tipos de monedas, todas se pueden intercambiar entre ellas. La idea es utilizarlas como los tokens de Wow, como un mecanismo de controlar la economía. La tasa de intercambio varía dependiendo de la oferta y demanda entre ellas. Cada moneda se utiliza en un sector del cubo (un cubo es una región en khpx).

Esta misión tiene como objetivo la captura de un peligroso individuo llamado Neettu que está cortando las líneas de suministro al planeta Mirbel. Para ello, el jugador deberá conseguir un robot de combate tipo PHJM que realizará la captura del criminal. Pero conseguir el robot no será fácil, deberá conseguir un repuesto para el robot primero, llevando a cabo una mini-misión en la superficie del planeta, rescatando a un equipo táctico que se encuentra atrapado en la ciudad. Lamentablemente este equipo táctico se niega a ayudar al jugador a capturar a Neettu, por lo que su única alternativa es el robot de combate.

Guía para completar “Los mools te hacen feliz”

1) talk Brat              // Hablar con el npc la info. de la misión.
2) talk Lappone           // Otro npc con los detalles de la misión.
// Como vamos a llevar pasajeros necesitamos agregar un habit a nuestra
// nave, no viene por defecto. Se puede comprar o conseguir como botín
// al capturar naves. Poco probable pero posible.
3) status habitat         // Verificar el estatus del módulo habitat
5) engage Mirbel          // viajar al planeta Mirbel
// brat es el npc operador del planeta. Es un funcionario, se le llama
// genéricamente brat. Esto es común en el primer cubo, menos común en
// otras partes de la galaxia.
6) brat neettu            // preguntarle al npc "brat" por Neettu (otro npc)
7) talk noreen            // La que nos ayuda a conseguir el robot PHJM
8) capture TTPP-23        // capturar nave enemiga identificada con TTPP-23
// le entregamos el botin que capturamos y ella nos entrega el robot
9) talk noreen            // entregarle el botín de la nave TTPP-23
// pero hay un problema al robot le falta una pieza. Tenemos que regresar
// con brat para que nos ayude a conseguirla.
10) brat estetor          // Pregunt. Brat por el "estetor", parte de robot.
11) talk espiro
12) talk werzaat
// Usar el escanner de la superficie del planeta, localizar el área con
// código "airine"
13) scan map code airine 
// Mover el equipo táctico. Esta misión tiene un componente en la superficie
// del planeta, consiste en mover un equipo táctico de posición. Muy simple.
14) move team
// Más interacción con los npcs.
15) talk wezaat -> receive estetor
// Una vez entregado el "estetor" recibe un robot de penetración de 
// territorio enemigo para capturar al npc "Neettu".
16) talk noreen -> deliver esteror -> receive robot PHJM
// Usando nuevamente el escanner ubicar la zona Balbidere.
17) scan map code balbidere
// Capturar al npc Neettu utilizando el robot PHJM recibido en el pto 16 
18) capture Neettu 
// Hablar con Brat para recibir la recompensa.
19) talk brat -> profit

Cómo se puede ver la estructura es algo así como lo siguiente:

  1. Conflicto. Es el motivador. Lo que motiva a nuestro personaje. Tiene un componente de “drama”, “tragedia”, con un peligro inminente. Por supuesto, nosotros no vamos a arriesgar nuestro pellejo y perder tiempo sin una jugosa recompensa. A veces es solamente en dinero, pero también puede ser un equipo. En este caso, un potente robot PHJM que vamos a necesitar para avanzar en el juego.
  2. La ayuda. Hay uno o varios npcs (personajes no controlados por el jugador) que ayudarán al jugador. En el caso de “Los mools te hacen feliz” hay 4 npcs colaborando. A veces.
  3. Mala suerte. No todo es fácil, las cosas salen mal, hay un npc enemigo imposible de vencer o un equipo difícil de conseguir. En nuestro caso el robot que necesitamos le falta un repuesto. Para colmo, al tratar de conseguirlo nos topamos con un equipo táctico que nos puede ayudar a completar la misión. Ups, se niegan a colaborar. Estos elementos ayudan a calibrar la dificultad de la misión.
  4. Conclusión. Al final todo sale bien y logramos nuestro objetivo. Cobramos nuestra recompensa y somos felices.

Decía que iba a hablar de sus diferencias y similitudes pero realmente no hay grandes diferencias, es muy similar. Como estoy diseñando misiones todos los días (== al menos 1 a la semana) puedo destacar algunos elementos importantes:

  1. Un conflicto con sentido. Claro que va a haber misiones del tipo “Mata a 10 ratas”, pero mi objetivo es que este tipo de misiones rutinarias sean mínimas. Normalmente van a tener sentido con el ambiente y con los objetivos del juego.
  2. Muchos npcs. Me gusta cuando las misiones involucran múltiples npcs. Eso le da mucho realismo, y e incrementa la inmersión. El drama entre los npcs tambiés es un elemento interesante, y la forma como interactúan entre ellos. Ofrece una oportunidad para que el jugador explore una dimensión oscura de los personajes y descubra las historias entre ellos.
  3. Recompensas que valgan la pena. Las misiones siempre tienen dinero o equipos como recompensas. En wow es común complicados quests con un maní de recompensa. Sí es divertido, pero frustrante.
  4. Montañas rusas montadas sobre carruseles girando en un risco. No hay una trama lineal en ningún quests o cadena de quests en khpx. Los enemigos terminan siendo amigos, la recompensa viene del lugar menos esperado, cuando todo parece haber terminado es cuando apenas estamos empezando. Etc.. Esa es la idea.

Los quests en Wow, Runescape y en Wizard101 tienen otro objetivo adicional que es la experiencia que generan. Yo todavía no tengo definida la experiencia (xp) en khpx porque el poder se mide por los recursos que se posee, no por una estadística numérica. Es probable que implemente algo al respecto, pero mi visión es diferente.

La razón es que en khpx hay el concepto de “poder” que es más o menos equivalente a xp pero no es un simple número, sino que viene dado por un conjunto de recursos que posees. Robots, granjas, minas, centros de tecnología, industrias y muy importante el ejército a tu cargo. Para conquistar un planeta y tomar control de sus recursos necesitas un equipo de npcs y robots. Y eso lo consigues a través de las misiones.

Mentira. Si es un número, o termina siendo un número y tiene que existir porque los jugadores quieren saber tu “iLevel” (o poder) para saber lo que puedes o no puedes hacer. Si no existe, los jugadores lo van a inventar o implementar, bien con un plugin, o con una tabla en una página web. En Wow no existía y al final algo tuvo que surgir porque cuando armas raids necesitas saber el poder de cada jugador.

En Runescape en cambio todo gira alrededor de tus skills, no de una simple barra de xp que va avanzando como en Wow. En wow, hay un quiebre en el juego, primero avanzas en xp, y luedo tienes que acumular “algo” (artifact power o azerite o lo que sea) que te permite incrementar el poder de tus armas. En khpx el “poder” se mide a través de tus naves, robots y equipos de npcs, y recursos y es así desde el comienzo hasta el final.

El “poder” entonces te permite saber lo que puedes hacer o no, a través del comando “consider“, que te indica si te puedes enfrentar a un enemigo o tratar de conquistar un planeta.

¿Y por qué ese nombre tan explícito, prosaico: “poder“? Porque el fin del juego es ganarle al emperador de todos los emperadores, lo que te va a permitir ser el amo y señor del universo. ¿Y qué logras con eso?

Poder.