@ agnasg

agnasg


Moli está trabajando de taxista…

17-11-2010 7:22 AM

Advertencia: este post es tan deprimente como ver los últimos 45 minutos de Titanic de James Cameron, o como ir de turista a Haití luego de un Huracán. No tiene nada que ver con programación de juegos, es un trabajo de ficción que no guarda relación con nada real, estos personajes no existen, y la Venezuela mencionada aqui se refiere en realidad a una región en la tierra media dominada por los Kobols y los Goblins.  Fue inspirado por Moli…

Mali

Ella consiguió un cupo en la UCV (Universidad Central de Venezuela) casi sin darse cuenta. Se graduó de licenciada a los 23  y a la semana siguiente del acto de graduación ya estaba trabajando. El recuerdo más recurrente de sus años en la universidad es la rumba1 permamente en Choroni. Sin embargo, nunca se empató realmente con nadie y se enfrentó a la vida laboral más soltera que una monja.

Se compró un apartamento,  engordó  20 kilos comiendo pepitos y viendo McGuiver los domingos en la tarde, pero los rebajó completicos cuando la moda de los spa, el yoga y la meditación trascendental llegaron a Caracas. Su trabajo sobrevivió a las 200 huelgas, el paro, los golpes, la docena de elecciones, dos nacionalizaciones, una junta interventora, 10 interpelaciones en la asamblea, cuatro quiebras y tres relanzamientos. Ahora parece que la empresa va a recibir nuevamente financiamiento del imperio porque la crisis hace que los gringos no luzcan tan malvados como parecía al principio. O por lo menos podemos olvidarnos del tema, por los momentos.

Realmente nunca ha estado desempleada e inclusive la revolución no le ha entrado tan mal. Ha viajado por tres continentes, conoce las 10 ciudades más grandes de USA (sí, San Francisco es la más bonita) y tiene bien adelantado el papeleo para irse a vivir a Australia o a Nueva Zelandia dado el caso. Pero lo más probable es que se quede porque parece ser que con la nueva reorganización en la empresa le pueden dar un nuevo ascenso. Sin embargo, eso no la desanima en lo absoluto a ir a cuanta marcha opositora se les ocurra a los locos de siempre, y dice ni un paso atrás sin percatarse del nefasto legado del lema.

Mali sigue soltera y sin planes, y  cuando se le pregunta si es feliz suelta una lágrima. Ni una convención de psicólogos, psiquiatras, sociólogos y videntes podrían descubrir si esa lágrima es de felicidad o de tristeza.

Meli

Dos divorcios, 3 muchachos y 15 empleos después, Meli todavía se pregunta si sus problemas se deben a su inestabilidad emocional. Inclusive cuando alquien le dice que es voluble, explota en improperios y ademanes, más porque no sabe lo que significa la palabra y cree que es un insulto que porque le molesta que le digan la verdad. De hecho, todo el tiempo anda contándole sus problemas a quien tenga la paciencia de oirlos e invariablemente termina el cuento con un “tú que opinas” más parecido a una formalidad que a una pregunta.

Pasó sus años en el liceo y en el instituto diciéndole a todo el mundo que ella estudiaba por amor al arte, porque ella se iba a buscar un marido que la mantenga y le compre un carro. Y como todo el mundo consigue lo que busca eso fue lo que ella consiguió. Pasó los quince años de casada sirviendo platos de comida al barrigón en guarda camisa que la espantaba como a un perro: “quítate que no me dejas ver la televisión”.

Ahora trabaja de asistente, y pasa la semana deseándo encontrar a alguien que la resuelva. Cuando va a la discoteca baila como una diabla, y prefiere siempre a los más buenmozos y los mejores bailarines del local. Pero todos son unos limpios y termina contándole sus desventuras en el metro a un barrigón que baila mal pero tiene con que pagar la cuenta. El día siquiente se le aparece en el trabajo con un refresquito y el barrigón queda anonadado porque no se acuerda que la noche anterior en medio de la borrachera le contó  donde trabajaba. Qué atenta y considerada es Meli.

Mili

Ella es una de esas sifrinas 2 de las que frencuentan las Mercedes. Se graduó de comunicación social y luego comenzó a estudiar diseño gráfico porque en ningún periódico, televisora o radio la tomaban en serio. Si recuerdan a Elle la de Legalmente Rubia tendrán más o menos la fotografía, solo que quitándole 30 puntos de coeficiente intelectual y vistiéndola de azul, verde o negro. Ninguna venezolana se vestiría de rosado jamás. Eso es niche 3.

Cambia de carro cada dos años, vive en la Tahona en un apartamento de su primer divorcio, y sigue asistiendo a cuanto bautizo y cumpleaño se le presenta aunque ya está bastante entrada en años para la gracia. Su actual empleo apenas si la mantiene y todos los gastos, bien voluminosos por cierto, los financia con la pensión que le sacó a su segundo marido. “¿Como que gasto mucho? guadever, deposítame”. Le sigue dando órdenes como cuando eran casados, porque ella no entiende la solemnidad de un papel legal que dice que el vínculo conyugal terminó.

Ella no sabe como se llama el actual ministro de finanzas y no tiene idea que en los últimos 12 meses la mitad del sistema legal venezolano fue adaptado al socialismo del siglo 21. Esas cosas son aburridas y en realidad no tienen importancia. Sus nuevos zapatos de goma que quiere lucir el jueves cuando vaya al gimnasio la tienen distraída.

Moli

Fue dueña de la más grande cadena de tiendas pequeñas de la ciudad. Presidenta de la Asociación de Damas pro Defensa de los Delfines, Miembro ad honoren de la junta parroquial, vecinal, patronal y muchas otras organizaciones que riman con anal. Un ACV mató su esposo, un cáncer a su hijo y un infarto casi la mata a ella. Conduce un taxi desde hace 5 años y no se va dormir hasta que reune la mesada del día. Su resolución es inquebrantable, y ahora cuando ya está rayando los 60, más que nunca.

Pasaba el segundo semestre del año acumulando deudas que después pagaba con las ventas de diciembre. Una sola de sus tiendas financiaba el viaje de vacaciones a Miami, que siempre realizaba, por supuesto, en enero cuando el rebullicio y el marasmo decembrino terminaba. Pagaba a todos proveedores y luego a medida que avanzaba el año las cuentas por pagar aumentaban 20% mensual. Finalmente en los alrededores del día de la raza traía media docena de containers para abastecer sus tiendas y afrontar ufanamente un nuevo diciembre. Todo hubiera seguido igual forever si el paro de 2002 y los 8 meses subsiguientes no acaban con el sueño de la venezuela saudita que comenzó a marchitarse en el ’99.

Luego de pasar meses escondida debajo de la caja registradora evadiendo a los cobradores terminó vendiéndolo todo y pagando todas las deudas. Le quedó para comprarse un refresco. Luego la factura de la clinica donde vivió su hijo los últimos días terminó de degradarla al estrato d de la sociedad, que es como los economistas llaman a los pobres. Los estratos b y c se están quedando desiertos por las Molis que terminan trabajando como taxistas o hacen como nuestra próxima protagonista, Muli, yéndose a trabajar de conserjes a España. Una ironía del destino, porque luego de la guerra civil española, eran ellos los que venían a limpiar edificios aqui.

Muli

Tenían 2 camionetas, dos carros de paseo, un perro poddle, acciones en varios clubes y una casa valorada en un 0.5% del PIB nacional. Cuando con bombos y platillos los adláteres del gobierno celebraron el cierre de la empresa número 6000 Muli y su esposo se quedaron sin trabajo.

Como ellos habían hecho el post grado en España, la emigración lucía como la solución lógica.  No iban a continuar inténtandolo, y trabajar como taxistas estaba fuera de cualquier consideración. Le pidieron favores a los pocos de sus amigos que todavían continuaban en el país, le dieron en custodia el perro a su mejor amiga y se embarcaron en un viaje de descubrimiento a la inversa del viejo continente. 5 años después el perro continuaba aullando por el regreso de sus dueños.

La mecánica en España es muy diferente de la de  aqui, cosa que descubrieron casi al bajar de la carabela, digo, del avión. Allá son desempleados. De los que no tienen trabajo. Esos, sí, los que no trabajan en ninguna compañía. Aqui en Venezuela un “estoy trabajando por mi cuenta” explicaba de una forma confusa y elegante que se habían dedicado a cosas más serias que estar de asalariados. Luego de varios meses se percataron que mientras en Venezuela apenas hay un oscuro y casi sin significado 10% de desempleo, en España hay 4 millones de desempleados. Esos son 4.000.000 con sus 6 ceros completicos. Y ellos formaban parte de esos 6 ceros en forma irremediable y no como podría pensarse, con igual de oportunidades que los demás, no, ni siquiera con el 0.000001% de posibilidad de conseguir trabajo. Ellos estaban en una fila, una cola interminable de 4 millones de personas… y estaban al final de la cola.

Trabajar de taxista, de buhonero4, o cualquiera otra de las soluciones que aqui en el trópico son habituales está fuera de cualquier posibilidad porque la legalidad allá se escribe con letras doradas y se respeta. Es tán dificil hacer un trabajo informal como practicar la medicina siendo extranjero. Para mendigar hay que tener un permiso, a menos que seas gitano, quienes siempre han estado al final de la escala social pero muy por encima de cualquier latinoamericano de esos países cuyos habitantes no tienen verguenza de ir a sentarse en una plaza a esperar que los llamen con un “necesito un plomero, un albañil, un mecánico…”. ¡Yo!, ¡yo!, ¡yo!

Nunca más se supo de ellos, aunque la amiga que se quedó con el poddle  leyó en facebook que se habían dedicado al negocio de mantenimiento inmoviliario. La nota no tenía  detalles que permitieran dislucidar los intrilinguis de ese negocio.

Así termina esta historia contada a 5 voces, que pudieron ser más pero lamentablemente el alfabeto solamente tiene 5 vocales.


1) rumba: fiesta, agasajo, celebración. Dícese de una reunión bailable con bebidas alcohólicas en profusión. Frecuentado por niches y sifrinas por igual.

2)  sifrina: persona de sexo femenino con ademanes fingidos y que habla con un acento que proveniene de la región de Caurimare o el Cafetal,en el este de Caracas. Es un acento que podría ser confundido con el acento niche a las personas no entendidas, o en todo caso, se podría clasificar como un acento niche pero refinado y elegante.

3) niche: persona de malos modales y costumbres. cosa de muy mal gusto o de muy mala calidad (el hecho de que sifrina y niche estén juntos en este pié de página no es intencional, pero es un accidente que agrega un toque adicional al significado de ambas palabras).

4) buhonero: persona que vende baratijas en la acera de la calle, sin permiso y sin pagar impuesto. Hay niches que son buhoneros pero no todos los buhoneros son niches. Las sifrinas nunca le compran a los buhoneros, ni mucho menos se dedicarían a la buhonería, “¡pó favóó!”.

Indice

Sobre nerds

31-10-2010 10:02 AM

Cuando comenzamos a estudiar literatura o expresión literaria descubrimos rápidamente que lo que caracteriza una buena historia es el desarrollo del personaje principal. O de los personajes. ¿Qué significa eso? Significa que el personaje al terminar la historia o novela es distinto a como comenzó, sufre una metamorfosis, bien sea a través de un proceso de transformación interno o de su entorno.  No quiero ser pedante mencionando novelas que probablemente nadie ha leido (la primera que se me ocurre es Gertrudis de Hermann Hesse, donde el personaje se transforma de una forma dramática a través de 200 páginas). Así que mencionaré una película: As good as it get: un escritor obsesivo-compulsivo endiosado en lo más alto del olimpo quien aborrece por igual los convencionalismos y los lugares comunes, se enamora de una mesera, brinda cobijo en su casa a su vecino gay, y sale a comprar pan temprano en la mañana como cualquier mortal. Lo que hace atractiva una historia es el movimiento del personaje, su desarrollo, su evolución. En una palabra: su transformación.

Ya yo no tengo tiempo para ver televisión así que solo veo algunas series ocasionalmente. Dr. House, U.V.E., Two and  Half men. Y The Big Bang Theory.

The Big Bang Theory (una teoría descartada por cierto) es una serie sobre 4 nerds y sus desventuras concientes o no para comunicarse con los demás, y en particular con su común y ordinaria vecina Penny. Trabajan en el departamento de fisica y a lo largo de la serie continuamente intercalan en sus conversaciones contenido nerd (referencias a series de culto como Star Trek), fisica cuántica (el gato de Schrödinger) y tecnología de computación. La interpretación que hace el actor Jim Parson del fisico teórico Sheldon Lee Cooper es perfecta hasta los más mínimos detalles. Es un nerd. Con su molesta impertinencia al buscar la exactitud descriptiva en los detalles irrelevantes de cómo, por qué y para qué las cosas son como son (irrelevantes en el contexto, por supuesto).  Va más allá de la función subyacente del buho en Harry Potter o los torpedos de la NCC-1701, esos son detalles anecdóticos como cuando alguien menciona que un capacitor electrolítico del motor de una impresora está produciendo un retraso de un 1/11 de pulgada cada 3200 líneas por lo que hay que ajustarla en consecuencia: no, se trata de un interlineado, una malla primordial entre conocimiento y el devenir donde se pierde la separación entre uno y otro, y ambos se alimentan mutuamente, se funden y se convierten en una masa uniforme que crece y lo abarca todo hasta explotar en medio de una conversación: ¿de qué habla?

Este nerdismo puede ser contagioso, por ejemplo en la mencionada serie Penny, la común y ordinaria vecina, avezada en las complejidades de poner un plato de comida sobre la mesa se somete a la dialéctica nerd de la misma forma que un juzgado en Texas: ríndete, cualquier resistencia es fútil. Así la vemos utilizando el símil de levantar los escudos para defenderse de los ataques femenimos de la misma forma que lo hace el Enterprise, o utilizando el mencionado gato de Schrödinger como paradigma de la impredictibilidad de nuestra condición humana. Ni más ni menos. Claro, todo es una ilusión, Penny no es una nerd, no lo es ni lo será, es solo el desvarío mercantilista o utilitarista de Chuck F&$#cking Lorre, interpretando como el genio que es el momento historíco de los nerds luego del desagradable incidente de columbine, las continuas historias de abuso y  atropello en contra de los nerds por su frágil condición física, y a pesar de su descomunal fortaleza intelectual, descrita magistralmente al extremun por Gates cuando dijo trata amablemente a los nerds, uno de ellos podría ser tu jefe cuando te gradúes. Incluyendo, por qué no, Penny: la transformación del personaje en una hitoria lo puede todo…

Volviendo a los nerds,  el aislamiento producido por un lenguaje arcano y casi elitesco produce una reducción o un nivelamiento en el número de relaciones interpersonales de los nerds en cualquiera que sea el ámbito donde se desenvuelven (el liceo, la universidad, la oficina) y como en este siglo XXI “ser popular” es un valor así como en la edad media “ser pobre” lo era y ser popular es directamente proporcional al número de relaciones que tenemos, pues, simplemente, los nerds están en una posición complicada. Y es que podemos hacer algo al respecto cuando reconocemos y es importante para nosotros, y “ser popular” para un nerd es un concepto tan extraño y complejo como lo es para cualquier mortal de carne y hueso la determinación del spin negativo del átomo de litio o demostrar que no hay un n donde es cierta la expresión an=bn+cn para n mayor que 2.

¿Dónde están los fuentes? Segunda Parte

21-10-2010 8:09 AM

A veces la gente me llama autista. Y de verdad, si lo soy, mi autismo no me permite ver que soy autista. La mayoría de las veces. Ahora que sé que tengo algunos sintomas de autismo los puedo reconocer con facilidad. Por ejemplo, cuando me preguntan algo y me quedo estático como si no me hubieran preguntado nada. O como si no fuera conmigo. Autista. Pero peor aun es cuando respondo una pregunta diferente a la que me formulan. Este post se originó cuando alguien me preguntó dónde estaban los fuentes. Y ahora me pregunto si la pregunta era “¿dónde están los fuentes en este sitio? Al fin y al cabo en el encabezado dice algó sobre código fuente. Pues aqui no hay fuentes. O por lo menos no los había hasta hoy.  Estoy creando una nueva categoria y una nueva etiqueta llamada código fuente.

¿Cuál es el primer juego que debemos hacer? Tal como dice en estas páginas debe ser algo sencillo. Fácil de diseñar y fácil de terminar. Nuestro primer proyecto no debe ser un motor gráfico. Debe ser algo simple. Pong por ejemplo. El objetivo es darle a la pelota y vencer al programa. Fácil. Simple. Rápido. Algo que se puede hacer en una sentada. Hace siglos estuve en un grupo de programación de juegos donde pasábamos la mayoría del tiempo hablando sobre cómo hacer un juego. Al final a alguien se le ocurrió la brillante idea de dejarnos de habladera y hacer un juego entre todos. De hecho el grupo en sourceforge se llamó averygoodidea.  Hicimos un diagrama, hablamos y hablamos. Formamos grupos de trabajo. Nunca hicimos nada.

Así que lo más importante de un juego es lo siguiente: terminarlo. Calidad, detalles y optimizaciones vienen después. ESTOY HABLANDO EN SERIO.

Como esta versión solamente corre sobre windows vamos a darle un nombre bien original: WinPong.

Esta versión utiliza el api Win32 y está basada en una plantilla estándard. No fue mi primer programa, de hecho lo he estado puliendo recientemente. Incorpora fuentes y pedazos de fuentes de todas partes, quizás algunos con copyright pero como ha ido cambiando de un programa a otro ya les perdí la pista.

Sugerencia:  una de las pesadillas que debemos sufrir como programadores es estudiar código fuente de otros programadores. Cada uno de nosotros tiene su estilo y su idiosincrasia. Si a eso le sumamos el tema del idioma, la pesadilla se convierte en infierno. Yo he visto programas con comentarios en inglés, las variables nombradas con una combinación de estilos y en alemán.

La metodología más usada es la notación Hungara: yo no la uso. Apenas le coloco el prefijo g_ a las variables globales, y “m_” a las variables member. Hasta ahi llegó la notación. Además hay varios estilos: gameObject (primerapalabra en minúscula y la segunda palabra con la primera letra en mayúscula); GameObject (que es la que yo uso para los nombres de las clases); game_object: todo en minúscula y un underscore entre las palabras (esta última es la que utilizo últimamente, porque para colmo voy cambiando a medida que pasa el tiempo). Una regla que aplico para que el código no se vea como una ensalada es utilizar el inglés para todo, incluyendo los comentarios. De esta forma el código luce más uniforme. Los he traducido para este caso. Como quiera que sea la norma establecida es que los hackers escriben en inglés. Finalmente la forma de colocar los paréntesis es la K & R, basada en la forma en que Brian  Kernighan y Dennis  Ritchie utilizaron en el libro original de programación C. Básicamente se distingue por colocar la llave que abre { en la misma línea de la instrucción.

EL código fuente y un ejecutable se puede encontrar aqui. Antes de continuar examine el código fuente para que tenga una idea de su estructura.

La piedra angular de todo juego debe ser la clase GameObject. Esta clase contiene los datos y rutinas de los objetos del juego, que en nuestro caso es la pelota, la raqueta controlada por el computador y la raqueta controlada por el jugador. En nuestro caso debemos controlar la posición (x, y) de nuestro objeto (en las variables m_x y m_y), su velocidad (m_dx, m_dy) y su color. Proveemos rutinas para acceder a estos valores (get_x (); get_y (), etc..) y las rutinas draw () para desplegar la posición del objeto, y update () para actualizar la posición del objeto.


// clase base de los objetos del juego
// pelota, computador y jugador
class GameObject {
protected:
int m_x; // posición x del objeto
int m_y; // posición y del objeto
int m_dx; // delta x (velocidad horizontal)
int m_dy; // delta y (velocidad vertical)
int m_width; // tamaño horizontal
int m_height; // tamaño vertical
HBRUSH m_color; // color del objeto
public:
GameObject(int x, int y, int dx, int dy, int width, int height, COLORREF color)
: m_x (x), m_y (y), m_dx (dx), m_dy(dy), m_width (width), m_height (height)
{
m_color = CreateSolidBrush (color);
};
~GameObject (void)
{
DeleteObject(m_color);
};
// accessors
int get_x (void) { return m_x; };
int get_y (void) { return m_y; };
int get_width (void) { return m_width; };
int get_height (void) { return m_height; };
// los objetos necesitan ser desplegados y y su posición actualizada
virtual void draw (HDC hdc, RECT* prc) = 0;
virtual void update (RECT* prc) = 0;

};

Luego derivamos 3 clases para los 3 objetos. Proveemos el constructor y las dos rutinas draw () y update (), que en la clase base declaramos como virtuales. De esta forma cada objeto tiene su rutina propia para funcionar. Los constructores utilizan la sintaxis Clase (…) : inicialización donde inicialización a su vez es una llamada al constructor de la clase base.


// la pelota es derivada de la clase GameObject
// con sus funciones para desplegar y actualizar su posición
class Ball : public GameObject {
public:
Ball(int x, int y, int dx, int dy, int width, int height, COLORREF color)
: GameObject (x, y, dx, dy, width, height, color) {};
void draw (HDC hdc, RECT* prc);
void update (RECT* prc);
};

// igual la raqueta de la computadora es derivada de la clase GameObject
// con sus funciones para desplegar y actualizar su posición
class Computer : public GameObject {
public:
Computer(int x, int y, int dx, int dy, int width, int height, COLORREF color)
: GameObject (x, y, dx, dy, width, height, color) {};
void draw (HDC hdc, RECT* prc);
void update (RECT* prc);
};

// la raqueta del jugador
class Human : public GameObject {
public:
Human(int x, int y, int dx, int dy, int width, int height, COLORREF color)
: GameObject (x, y, dx, dy, width, height, color) {};
void draw (HDC hdc, RECT* prc);
void update (RECT* prc);

};

Para deplegar los objetos utilizamos una llamada a la función del api Win32 Rectangle. Previamente hemos asignado el color de la imagen haciendo un SelectObject ().

// la función para desplegar el objeto
void GameObject::draw (HDC hdc, RECT* prc)
{
HGDIOBJ old=SelectObject(hdc,m_color);

Rectangle(hdc, this->m_x, this->m_y, this->m_x+this->m_width, this->m_y+this->m_height);

SelectObject(hdc,old);
};

Para actualizar la posición de los objetos debemos aplicar una lógica para establecer su velocidad y recalcular su posición. Por ejemplo, la función update de la raqueta del computador es como sigue:

void Computer::update(RECT* prc)
{
this->m_y += this->m_dy;
if(this->m_y < prc->top) {
this->m_dy = COMPUTER_SPEED;
} else if(this->m_y + this->m_height > prc->bottom) {
this->m_dy = -COMPUTER_SPEED;
}

};

Finalmente capturamos el evento WM_TIMER en WindowProc y colocamos las llamadas a todas estas funciones para que se ejecuten cada cierto tiempo, que hemos definido en WM_CREATE con la llamada a SetTimer (). WindowProc () es la función que se va a ejecutar cada vez que se produzca un evento en el juego. El vento WM_TIMER se genera al dispararse la alarma del timer y WM_CREATE se genera al momento de la creación de la aplicación. Definimos WindowProc como la función que va a manejar los eventos en la WindowsClass, en el WinMain del programa. Fácil.

PS: la idea para este post se me ocurrió hace dos meses.

parsers

17-10-2010 2:27 PM

Un parser es un programa (o parte de un programa) que analiza un archivo (o una entrada en general) y toma acciones de acuerdo al contenido que encuentra. Un parser forma parte de un compilador, pues el primer paso es analizar la entrada y almacenarla en estructuras que al  final permitirán generár código, o puede ejecutar acciones inmediatamente en caso de que sea un script (un programa que debe ejecutarse de inmediato como php o lua, lo que se llama lenguajes interpretados).

Un parser puede ser  requerido para limpiar un código fuente o para modificarlo de alguna forma, incluyendo encriptarlo u ofuscarlo.  Esto es justamente lo que estoy haciendo esta vez. Yo he hecho parsers desde que estudié lenguajes de programación, y si bien todos tienen sus peculiaridades, básicamente se reduce a lo mismo: identificar patrones y mantener el estado del parser, esto es, saber qué cosa se está procesando en este momento y cómo afecta eso el procesamiento futuro. Por ejemplo, si el programa encuentra un comentario que en PHP, C, C++ y otros lenguajes del mismo estilo puede comenzar con //  (en PHP además con #) eso significa que el resto de la línea debe ser ignorada. Si se encuentra un /* se debe ignorar hasta el próximo */. Y así sucesivamente.

Algunos parsers son simples como el que estoy haciendo en este momento que me va a permitir ofuscar código fuente PHP (para que el programa no pueda ser modificado, al menos fácilmente). Los parsers de los compiladores no son tan simples, porque después de identificar las instrucciones del lenguaje deben generar un código intermedio que se ejecutará posteriormente. Por ello el parser debe encargarse de generar ciertas estructuras que van a permitir el procesamiento posterior del compilador.

Un parser es necesario para procesar el lenguaje “scripting” o guión del juego. La primera regla del diseño de juegos es separar la lógica de los distintos motores que lo conforman (motor gráfico; motor de inteligencia artificial, etc). Esta es la arquitectura que ha probado ser más eficiente para el diseño y definición de un juego: en vez de codificar las descripciones y acciones de un sitio en el juego dentro del motor del juego, se define un lenguaje de definición de sitios, que incluya la definición de las acciones que el jugador puede ejecutar y las acciones que los psi ejecutarán. El motor del juego simplemente debe ejecutar este lenguaje. De esta forma se separa el motor del juego de la definición del juego y los diseñadores pueden dedicarse al contenido  sin preocuparse de nada más.

Esta separación entre la definición del juego y el motor del juego ha sido utilizada exitosamente en los juegos MUD. La codebase LPMud utiliza esta arquitectura (a eso se debe su popularidad). BatMud (el MUD que estoy jugando en estos momentos) está diseñado utilizando esta codebase.

La definición se guarda en archivos como cualquier programa para que el motor la lea a tiempo de ejecución. Hay infinidad de sintáxis, todas incompatibles entre sí, porque cada programador quiere incorporar ideas y conceptos propios. Algunas describen una ubicación en el juego en un archivo, otras almacenan varias ubicaciones en el mismo archivo. Por ejemplo, un conjunto de ubicaciones lucen de la siguiente forma:

bosque.def
casa.def
lago.def
pozo.def
pueblo.def

Donde cada archivo guarda la definición del sitio que está describiendo o definiendo. Por ejemplo el archivo bosque.def tiene algo como lo siguiente:


short() {
return "Un lugar en el bosque";
}
long(str)
{

write(“Este es un lugar rodeado de árboles por todas partes. El camino luce amarillo\n”);
write(“por la alfombra de hojas en el suelo.\n”);
write(” Hacia el este se ve una casa.\n”);
write(” Hay un lago al oeste de aqui.\n”);
}

Los que conocen el lenguaje inform descubrirán inmediatamente las similitudes para describir un “room” o ubicación. La rutina “short” presenta la descripción corta del sitio. La rutina “long” presenta una descripción más detallada. Es lo que se despliega al  ejecutar el comando “examinar” o ver. Estos archivos son el alimento para el parser que es el que se encarga de interpretar estos comandos y ejecutar las acciones según los comandos que ejecute el jugador.

EL parser se implementa de diversas formas: yo las he probado todas. El más antiguo enfoque es usar el duo maravillosos lex y yacc (buscarlo en google aparecen miles de enlaces). lex se encarga de generar un programa de análisis lexicográfico que permite identificar los distintos tokens en los que se compone el programa. Cada tokens es una pieza diferente del lenguaje: identificadores (que pueden ser variables o palabras claves del lenguaje), simbolos (+, -, *, /, etc), números y otros componentes. yacc por el otro lado genera un parser que dado los tokens y una gramática va a generar el código ejecutable o las acciones descritas en el archivo de definición.

Ambos programas (lex y yacc) tiene a su vez un archivo de definición. Para lex el archivo es algo como lo siguiente (tomado del parser de mi juego aventura gráfica):


"object" { return(OBJECT); }
"break" { return(BREAK); }
"if" { return(IF); }
"while" { return(WHILE); }
"else" { return(ELSE); }
{L}({L}|{D})* { return(IDENTIFIER); }
'(\\.|[^\\'])+' { return(CONSTANT); }
{D}+{E}{FS}? { return(CONSTANT); }
{D}*"."{D}+({E})?{FS}? { return(CONSTANT); }
{D}+"."{D}*({E})?{FS}? { return(CONSTANT); }
{D}* { return(CONSTANT); }
{I}* { return(CONSTANT); }
\"(\\.|[^\\"])*\" { return(STRING_LITERAL); }
"&&" { return(AND_OP); }
"||" { return(OR_OP); }
"<=" { return(LE_OP); } ">=" { return(GE_OP); }
"==" { return(EQ_OP); }
"!=" { return(NE_OP); }

El programa devuelve el valor indicado ({return (OBJECT);}) cuando encuentra alguno de los patrones en la columna de la izquierda. Por ejemplo, si encuentra la palabra “object” devuelve el identificador OBJECT (que es un número único). Si encuentra {L}({L}|{D})* devuelve IDENTIFIER. Esto último es una expresión regular, la L representa una letra, la D representa un dígito, el * representa 0 o más veces. El | indica el “o” lógico (por ejemplo cuando dices nos vemos el lunes “o” el martes. Es una contrucción lógica). Entonces esto significa que debe devolver un identificador cuando encuentra una letra seguida de una letra o un número 0 o más veces. El yacc requiere un archivo similar para representar la gramática.

Hoy en día (para mi juego de ficción interactiva y) para nunsoot estoy utilizando un parser escrito a mano: sin usar yacc ni lex. Así están programador inform y los LPMuds, y ahora entiendo por qué: mantener y mejorar los archivos de la gramática y el analizador lexicográficos es bien complicado. Además no estoy seguro si hay problemas de licenciamiento detrás de ellos.

Ahora me dispongo en las próximas semanas revisar el código del parser para nunsoot (que va a ser el mismo que utilizaré para panicput) y tengo que confesar que no lo hago con mucho entusiamo: es la parte más complicada del juego. Pero claro con una ventaja igualmente grandísima: facilidad el desarrollo del contenido del juego enormemente.

Los MUDs tienen más de 30 años de inventados pero todos estos conceptos son utilizados por los juegos modernos como World of Warcraft.