Un poco sobre Lua
Llevo sin escribir nada por aquí desde el año pasado. Cada vez me cuesta más encontrar un tema del que hablar, de los que me interesan, del que no haya hablado ya. Por ello, quizá, me concentro en otras cosas y tengo el blog hecho un erial. No quiero decir que esté abandonado, porque a estas alturas y después de tantos años, no creo que lo cierre o lo abandone del todo nunca. Me dedico a mis investigaciones, a estudiar y a aprender, y se me pasa el escribirme mi resumen. También, porque este blog se inició como una forma de recordarme a mí mismo lo que iba aprendiendo y mis herramientas para la toma de notas han evolucionado al punto en que no necesito tanto contarme qué he hecho para guardarlo en la memoria externa. Pero hoy, vengo a hablar sobre Lua, un lenguaje de script incrustable y minimalista al que le estoy dedicando un poco más de atención últimamente.
El objetivo no es otro que aprender. Supongo que habrá quien lea esto, que si es de los que leen de manera habitual, piense: «si ya he visto por este blog código escrito en Lua...». Es cierto, aquí ya he hablado de algunos temas y traído código en este lenguaje. Es minimalista, así que no cuesta nada escribir algunas cosas sencillas sabiendo poco de cómo funciona. Sin embargo, mi intención últimamente ha sido profundizar en esos detalles para los que sueles decir: «otro día lo miro» y no vuelves a mirar nunca.
Liándome la manta a la cabeza decidí leer uno de los libros que tengo descargado desde hace tiempo y que he consultado de vez en cuando para escribir algunos scripts. Me refiero a Programming in Lua , el libro escrito por uno de sus creadores y principales mantenedores. Mis apuntes, los voy poniendo en un Tiddlywiki en este mismo sitio.
Sobre Lua
Como lenguaje es bastante simple. Nada que no esté implementado en el ANSI C, lo encontrarás en Lua. En el libro se hace mucho hincapié en el ANSI C y en su ejecución en cualquier sistema que tenga un compilador de ANSI C que compilará la librería sin problema. Su desempeño también es alto, lleva incorporado el luajit para acelerar la ejecución y, por tanto, lo más destacable de Lua es la sencillez, la presencia en cualquier sistema y la velocidad de ejecución.
Está diseñado, al menos originalmente, para estar incrustado como lenguaje auxiliar en otras aplicaciones. Por ello, Lua es una librería de funciones escritas en C. Puede haber confusión con que cuente con su propio REPL, pero éste no deja de ser una aplicación de consola con la librería de intérprete incrustada.
A pesar de todas las ventajas hay algunas cosas que no terminan de cuadrarme por diversos motivos. La primera es que en la época de los procesadores multihilo, Lua no tenga algún mecanismo que permita la ejecución en paralelo. De hecho, en el propio PiL1, el autor descarga en la aplicación que hospede el intérprete de Lua estos asuntos y sugiere que para la ejecución en paralelo le basta con lanzar varios intérpretes a la vez.
Otra de las cosas que me resultan un poco marcianas, y que me ha dado alguna que otra patada en el trasero mientras hacía los ejercicios, es que los índices se empiecen a numerar en 1 y no en 0 como en la mayoría, por no decir todos, los lenguajes que conozco. Quizá sea sencillo para la gente que no es programadora, pero a los que programamos en otros lenguajes, nos resulta, cuando menos, chocante.
Por otro lado, el otro día hablando con un amigo me llamó la atención
sobre un punto que al que yo no le había echado mucha cuenta pero que
es otra de las cosas un poco marcianas que tiene Lua: la limitación de
que sólo se puede utilizar la instrucción return
como la última de un
bloque, por lo que en algunos casos donde se necesita un return
hay
que proporcionar un bloque tal que do return end
.
Otro de los tropezones que me he encontrado por la diferencia entre C
y Lua, es que pare éste el 0 es un valor verdadero. No siempre me ha
pasado, porque viene avisado en su manual, pero cuando he estado
lidiando con algún ejemplo que mezclara C y Lua, me ha ocurrido en
alguna ocasión, desconcertándome un poco al principio, el que una
misma expresión sea falsa en C y no en Lua. En Lua sólo tienen valor
falso los valores booleanos false
y nil
, el resto de expresiones, como
por ejemplo ""
o {}
o 0
, son todas verdaderas.
Cabe destacar la existencia de las metatablas, un mecanismo que permite algo de magia a la hora de flexibilizar el lenguaje. Se merecen ellas solas todo un artículo por las posibilidades que ofrecen para adecuar el lenguaje a nuestras necesidades. Permiten crear nuevos tipos, hacer de Lua un lenguaje, por poner un ejemplo, orientado a objetos o lo que quieras, pues definen el comportamiento de las tablas. Además, vienen acompañadas de metamétodos, lo que nos permite ajustar esos comportamientos según los tipos que creemos con las metatablas, estableciendo operadores para nuestros tipos o métodos de acceso a los índices de las tablas.
Si alguien pregunta por mi opinión subjetiva personal, es que Lua en general es un lenguaje eficiente y sencillo, pero que mantener esa sencillez y eficiencia le lleva a tener otras cadaunadas con las que lidiar. Algo que no importa demasiado, porque todos los lenguajes tienen de eso.
Proyectos de aprendizaje
Como es habitual, cuando me pongo a aprender algún lenguaje en serio, me gusta utilizarlo para algún proyecto más complejo que hacer un par de ejemplos. Para eso ya he ido haciendo la mayoría de los ejercicios que se proponen en el libro y aprendiendo esos detalles. Pero desarrollar algo desde cero es bastante más complejo.
En un ejercicio no tienes que tomar muchas decisiones, lo haces amparándote en la teoría explicada en el capítulo correspondiente y no hay un esfuerzo intelectual que requiera mucho más. El verdadero problema no es el que te ponga un libro, sino el que te encontrarás en un proyecto de desarrollo desde cero.
Sin embargo, este aprendizaje estaba dirigido a un proyecto en concreto o algo que me ronda la cabeza desde hace algún tiempo y que quería desarrollar. Pero también por el camino se me han pasado por la cabeza algunas ideas más. Al final, me ha surgido la pretensión de hacer algunas cosillas con Lua. Primero, después de quejarme de la falta de ejecución paralela, la idea loca es «pues hazlo tú mismo». La segunda una evolución de la idea original, que era hacer una aventura gráfica (isométrica) de las de point & click con Lua y Löve2D. Al final es básicamente lo mismo pero en 3D.
Procesos en paralelo
En este sentido, mi referencia son los procesos de erlang y sus capacidades de intercomunicación. Está claro que ahora mismo, antes de empezar a escribir una línea de código, todo parece cuadrar perfectamente y que será todo maravilloso. Pero me temo que será uno de esos proyectos que me llevarán al límite de mis capacidades de programación a una velocidad que pueden plantarme delante de un muro infranqueable.
¿Qué me gustaría tener en este proyecto? Pues como mínimo algunas cosillas:
- Intercomunicación entre procesos. En erlang cada proceso maneja su propia memoria, pero puede recibir mensajes desde otros procesos. Estos mensajes los encola en el buzón si está ocupado y va ejecutándolos a su ritmo.
- Un proceso puede levantar otro y controlar que sigue en ejecución. En este principio se basa todo OTP y sus árboles de supervisión que permiten al sistema recuperarse ante un error o problema relanzando los procesos muertos por alguna razón.
No estoy proponiendo crear un OTP completo. El OTP de erlang se basa fuertemente en cómo funciona su máquina virtual BEAM y puede mantener miles de procesos paralelos, algo que creo que una máquina física no puede hacer con las limitadas decenas de hilos que maneja.
Mirando la documentación y otras implementaciones encontré algunas soluciones al multihilo, como lanes, que tiene muy buena pinta y que, seguramente, estará mejor implementado de lo que yo podré hacer. Pero como dije antes, mi objetivo es aprender.
Jugar
El juego es sano. Envejecemos cuando dejamos de jugar y no me gusta la idea de dejar las actividades lúdicas.
En este blog ya hablé sobre löve2d, ese artículo incluía un poco de explicación sobre la programación de gráficos isométricos y cómo capturar entrada de ratón y cómo dibujar una rejilla que serviría de «terreno de juego». La idea original era hacer un jueguecillo en plan aventura gráfica de point & click con múltiples puzles al estilo del mítico Myst.
Sin embargo, por el camino me acordé también de aquella vez que programé un mod para Luanti2, que también lo conté por aquí. La idea se me cruzó porque alguien me habló de Cubic Odyssey y tras ver el trailer y mirarlo un poco detenidamente pensé... «y si hago un juego completo». Por supuesto, será mucho más modesto, porque me encuentro con algunos problemas:
- No puedo hacerlo desde cero porque necesitaría tres vidas para acabarlo. Tendría que aprender (bien) pixelart, entre otras cosas. Pero todo es ponerme, así que no lo descarto.
- Tendría que modelar todo el mundo y los objetos que aparezcan en él.
Además, el motor de Luanti, admite objetos en el formato
.b3d
, un formato binario de Blitz3D. He visto que han actualizado el exportador para Blender3D; la última vez que lo intenté no funcionaba bien en Linux y no conseguí hacer un modelo para importarlo en Luanti.
Otra alternativa es hacer algo a medio camino: sería un módulo, que se integraría en un juego, con sus propios elementos e historia. Algo que haría la función de aventura o quest dentro de un juego más general. Como crear otra dimensión dentro del juego, al estilo de como lo hace El End en Minecraft.
Aún no tengo nada decidido, se admiten sugerencias. Habría que hacer que fuera interesante, con algún premio especial, como por ejemplo, conseguir una capa que le permita al PJ propietario –y sólo a él, para que no se pueda transferir sin haber pasado las pruebas– volar o cualquier otra acción que se encuentre limitada en el juego general a modo de privilegio. Programar un mod para un juego ya hecho plantea la posibilidad de chocar con otros elementos ya presentes en el juego, incompatibilidades del módulo o de sus herramientas, comandos, etc. Por lo que también hay que ser cuidadoso, quizá más que haciendo el juego desde cero, porque en ese caso no se conocen todos los entresijos del juego –que programaron otros–. Pero a cambio, obtienes todo un entorno donde desarrollar tus ideas.
Conclusiones
Lua parece un lenguaje potente y sencillo. Como todos los lenguajes tiene sus cadaunadas e incluso en el PiL habla de Luaismos, expresiones y cosas propias de Lua. Es muy rápido, pero como lenguaje para estar embebido en una aplicación sigo prefiriendo Scheme (Chibi, por poner un ejemplo) o incluso Lisp (ecl, Embeddable Common Lisp).
Con respecto a los proyectos, me atrae más el lúdico Luanti que los demás. Hacerlo sería la manera de obligarme a pensar en Lua, pues es el lenguaje embebido en dicha aplicación. Desarrollar un juego desde cero me lo plantearía si encontrara quien ayudara en algunas tareas. Supongo que texturas y modelos podrían aprovecharse de algunos módulos que los proporcionan con licencias libres, por lo que ese trabajo lo tendría al alcance y podría concentrarme en otros aspectos, como crear un mundo original, poblarlo de criaturas y PnJ con quienes interactuar e invitar a jugadores a que lo habiten.
Quizá sea más alcanzable para un programador sólo el desarrollo de una aventura completa, dentro de un juego ya creado. Aunque si contara con ayuda dicha aventura podría ser en sí misma un juego completo. Imagino una dimensión completa, con estructuras y mobs propios que pongan las cosas difíciles al jugador, que lo hagan pensar, le permitan moverse e interactuar, incluso colaborar con otros jugadores para resolverlo o conseguir un premio conjunto.
Notas al pie de página:
Programming in Lua, libro de referencia sobre Lua.
Antes llamado Minetest: https://luanti.org
Comentarios