Entendiendo Inform (y olvidando PAWS) Parte I: Lo más básico Parte I: Lo más básico Por dónde empezar.

Por dónde empezar.

Evidentemente, antes de nada, tienes que asegurarte de disponer de todos los ingredientes necesarios para la programación con Inform. Asegurate de tener la última versión de todo, para poder seguir este cursillo. Si no sabes lo que necesitas, mira este enlace. Incluso si lo sabes, se recomienda mirarlo, pues se explica además cómo se usan estos ingredientes para "compilar" un juego, algo que tendrás que hacer muy a menudo a lo largo de este cursillo.

Ahora podemos empezar a diseñar el juego. Lo primero, evidentemente, es el guión, que puede ser una idea genérica que se vaya concretando a medida que se programa, o puede ser una historia totalmente detallada, incluyendo incluso los rompecabezas del juego. Cada uno tiene su estilo a la hora de diseñar el guión, pero en este cursillo te lo vamos a dar ya diseñado y con bastante detalle, para que sepas lo que te espera.

El guión del juego

Estás encerrado en una torre, de la que tienes que escapar. El mapa de la torre es el siguiente, las flechas dobles quieren decir "subir o bajar".

El juego comienza en la habitación llamada PuertaPrincipal, pero no se puede salir de la torre desde ahi. La salida de la torre está en la Mazmorra. Para salir, el jugador deberá:

Antes de lanzarnos a programar todo esto, debemos asentar claramente los principios de programación bajo Inform, que son bien distintos de los de PAWS, por esto iremos muy, muy despacio. No te impacientes, ¡todo llegará!

El juego Inform más pequeño del mundo

Lo siguiente es el esquema básico que debe seguir todo juego Inform. Más adelante iremos rellenando el esquema. Abre un nuevo fichero en tu editor favorito, como si es el Notepad de Windows o el mítico vi/m de Unix.

Constant Story "La Torre";
Constant Headline "^(c) 2000 Zak y Carlos^";
Include "Parser";
! Aqui iría la definición de mensajes de librería.

Include "Verblib";
! Aqui irian las definiciones de las localidades
! y los objetos del juego

[ Initialise ;
];

Include "SpanishG";
! Aqui irían los verbos y acciones específicas de nuestro juego.

Copialo todo tal cual, especialmente pon cuidado en los punto y coma. Aunque parezca increible, eso ya es un programa completo en Inform, puedes compilarlo y tratar de jugarlo con el comando 'inform fichero.inf' y jugarlo con "frotz fichero.z5' o abriéndo el fichero Z5 en WinFrotz. . Naturalmente no podrás hacer gran cosa, ya que no hay localidades ni objetos. Aún así, puedes intentar una gran variedad de acciones (intenta saltar, cantar, ir al norte o al sur, e incluso SAVE y LOAD). Verás que el juego tiene respuestas para todo ¿de dónde las saca? ¡No hemos programado ninguna de esas respuestas!

He aquí uno de los principios básicos de Inform que lo diferencia claramente de PAWS. En PAWS, el programador tenía que programar las respuestas a cada posible verbo bajo cada posible circunstancia. Los casos que no eran contemplados por el programador, no existían en el juego. En Inform, en cambio, el programador sólo necesita especificar las respuestas a algunos verbos y en algunos casos. Todos los casos que el programador no contemple, serán manejados de forma automática por la librería. Es la librería la que tiene todas esas respuestas preparadas para las acciones más corrientes que el jugador intentará.

Pasemos a explicar línea a línea el programa que has copiado. Puedes saltarte esto e ir directamente a la programación del mapa si ya estás familiarizado con la sintaxis de Inform.

Constant Story "La Torre";

Con esto definimos una constante llamada Story. Esta constante debe definirse en todo juego Inform y contiene el título del juego. El valor de esta constante tiene que ser un texto entre comillas. En nuestro caso el texto es "La Torre" Observa que al final del todo debe ponerse un punto y coma. En Inform, todas las "declaraciones" van terminadas por punto y coma.

Constant Headline "^(c) 2000 Zak y Carlos^";

Este es análogo al anterior, sólo que ahora la constante que definimos se llama Headline y su valor es "^(c) 2000 Zak y Carlos^". La constante Headline debe existir también en todo juego Inform y es el "subtítulo" del juego. El signo ^ representa un salto de línea, es decir, causa que antes de imprimir el texto el cursor pase a la línea siguiente (y otro salto tras escribir el texto, puesto que hay otro ^ al final).

Include "Parser";  

Include es lo que se llama una "directiva", esto es, una orden que le das a Inform para que haga algo. En este caso lo que le estás ordenando es que coja el fichero llamado Parser.h (la h se la pone automáticamente) y lo inserte en este punto. El resultado es el mismo que si hubieras copiado a mano tú mismo todo el contenido de Parser.h en este punto del fichero, sólo que usando Include el código fuente del juego queda mucho más limpio y legible (¡el fichero Parser.h son miles de líneas!)

El fichero Parser.h contiene el parser de Inform. Es una parte de la librería que se ocupa de leer lo que el jugador escribe, tratar de comprenderlo y generar acciones dentro del juego. Enseguida veremos qué es eso de las acciones.

! Aqui iría la definición de mensajes de librería.

Esta línea es lo que se llama un "comentario". Si Inform encuentra un signo de exclamación (!) que no esté formando parte de un texto entrecomillado, automáticamente ignorará todo lo que sigue en esa misma línea. Esto lo usaremos para poner anotaciones en el código. Estas anotaciones nunca formarán parte del juego final, una vez compilado, puesto que Inform las ignora.

En este caso la anotación es un recordatorio de dónde tendríamos que poner nuestras definiciones de mensajes de librería, si quisieramos ponerlas. En este juego no las pondremos de momento. Las definiciones de mensajes de librería son un poco como la tabla de mensajes de sistema de PAWS. Es donde se definen textos como "No puedes ir por ahi", "Cogido", "Cantas fatal", etc... Es decir, las respuestas por defecto de la librería ante cada posible acción. Si no definimos nosotros unas, la librería proporcionará otras ya preparadas. Puedes cambiar algunas de ellas si no te gustan sin necesidad de redefinirlas todas (y sin tener que modificar la librería). Luego veremos cómo.

Include "Verblib";

De nuevo mediante Include, cargamos en nuestro juego el fichero Verblib.h, que contiene el código mediante el cual la librería sabe qué es lo que debe hacer ante cada posible acción. (Enseguida veremos qué son las acciones, son un concepto clave de Inform)

! Aqui irian las definiciones de las localidades
! y los objetos del juego

Ahora se trata de unos comentarios recordándonos dónde irán los objetos y las localidades. Por el momento no hay ni objetos ni localidades.

[ Initialise ;
];

Esto es una rutina "libre". En Inform hay dos tipos de rutinas, las rutinas "libres" y las rutinas "incrustadas en objetos". Las libres son las que aparecen, como esta, en medio del código, las incrustadas en objetos aparecen siempre dentro de un objeto, luego daremos más detalles.

Una rutina no es más que un conjunto de instrucciones a las que hemos decidido agrupar y dar un nombre. En cierta manera se parece al concepto de "proceso" del PAWS, solo que en PAWS los procesos se identificaban mediante números (proceso 6, proceso 7,...) y en inform se identifican mediante nombres (rutina Initialise, rutina LugarNuevo, ...)

Todas las rutinas libres tienen la misma estructura:

[ Nombre_de_la_rutina v1 v2 v3;
  instruccion1;
  instruccion2;
  ...
];

Es decir:

Miremos otra vez el código que has escrito

[ Initialise ;
];  

En nuestro caso, la rutina se llama Initialise, su lista de variables locales está vacía (pues no hay nada entre el nombre de la rutina y el primer punto y coma), y también está vacío su "cuerpo", es decir, la lista de instrucciones que la componen (puesto que no hay nada entre el primer punto y coma y el signo ] que da por terminada la rutina).

En esencia: la rutina Initialise que hemos escrito es una rutina totalmente vacía que no hace nada de nada. ¿Por qué la ponemos entonces? La razón es que esta rutina tiene que existir en todo programa Inform, o de lo contrario Inform se negará a crear tu juego. Prueba a quitarla y lo verás.

Truco Para probar a quitar trozos de código mientras estás de pruebas, basta poner un signo de admiración delante de cada línea que quieras quitar. Esto convierte el código en "comentarios", por lo que se hace invisible a ojos de Inform. Si más tarde quieres restituir el código, basta borrar el signo de admiración.

Normalmente esta rutina se ocuparía de especificar cuál es la localidad en que comienza el juego, y de imprimir algún mensaje de bienvenida, pero en este primer esbozo la hemos dejado vacía. Aún así funciona, no es ilegal escribir una rutina que no haga nada, aunque resulta poco útil.

 

Programando el mapeado

Vamos a escribir el código de cada localidad. En Inform, cada localidad es un objeto. Esto puede sonarte un poco raro si pensabas que los objetos eran cosas como "una piedra", "una espada", etc. Pero es que el concepto de Objeto de Inform es mucho más amplio.

Clave En PAWS se llamaba "objetos" a las cosas que el jugador podía coger y llevarse. En Inform el concepto es muchísimo más amplio:

Para Inform, un objeto es en realidad un elemento del juego. Por tanto, los lugares son objetos, los PNJ son objetos, el propio jugador es un objeto, un "tema de conversación" puede ser un objeto. Prácticamente cualquier elemento de los que componen el juego son objetos (excepto las acciones o el vocabulario). Por eso se dice que Inform es orientado a objetos.

Aunque todos los objetos tienen siempre una misma estructura, no vamos a entrar aún a describir la estructura general de los objetos, y nos centraremos de momento en la estructura de los objetos que representan lugares. Esta es su estructura:

Object nombre_interno "nombre corto"
with   description "Descripción larga de la localidad",
       n_to ... ,
       s_to ... ,
       e_to ... ,
       w_to ... ,
       u_to ... ,
       d_to ... ,  
       in_to ... ,
       out_to ... ,
has light;

Es decir:

Truco Para los autores que usan informATE!, puede parecerles dificultoso tener que lidiar ahora con los nombres de propiedades, atributos, etc en ingles. Para aliviar un poco el asunto, INFSP provee la extensión Alias.h, la cual da soporte para que se puedan seguir usando los atributos y propiedades en español (como en informATE!). 

Una vez comprendida la estructura de las localidades, codificar el mapa es pan comido. Copia el siguiente código en la zona donde estaba el comentario "Aquí irían las definiciones de las localidades y los objetos del juego". Observa que, de momento, ponemos conexión "normal" en lugar de la puerta secreta.

Object  PuertaPrincipal "Puerta Principal"
 with   description "Estás junto a la puerta principal. 
            A su lado puedes ver una mesa de guardia y en la pared 
            norte hay una chimenea.",
        e_to Dormitorio,
 has    light;

Object  Dormitorio "Dormitorio"
 with   description "Varios maltrechos catres se amontonan en esta 
            habitación.",
        w_to PuertaPrincipal,
        e_to EscaleraCaracol1,
 has    light;

Object  EscaleraCaracol1 "Escalera de caracol"
 with   description "El viento ulula a través de la empinada 
            escalera de caracol, una vieja armadura parece vigilar 
            la escalera.",
        u_to EscaleraCaracol2,
        w_to Dormitorio,
 has    light;

Object  Mazmorra "Mazmorra"
 with   description "Una silenciosa estancia débilmente alumbrada 
            por los rayos de luna que se filtran a través de un 
            pequeño ventanuco. El suelo está lleno de paja, colgando 
            de unos grilletes en la pared observas un esqueleto 
            humano.",

        e_to EscaleraCaracol2,
 has    light;

Object  EscaleraCaracol2 "Escalera de caracol"
 with   description "Los desgastados peldaños de piedra resbalan en 
            ocasiones. A mitad de la escalera una antorcha en la 
            pared impide que la oscuridad sea completa.",
        d_to EscaleraCaracol1,
        w_to Mazmorra,
        u_to AltoTorre,
 has    light;

Object AltoTorre "Alto de la torre"
 with   description "Una gran cama preside la estancia, los gruesos 
            barrotes no permiten la salida por la ventana, aunque de 
            todos modos estaría demasiado alta.",
        d_to EscaleraCaracol2,
 has    light;

Unas notas sobre el código anterior:

Ahora será necesario también modificar la rutina Initialise para indicar en cuál de esas localidades comienza el juego.

En Inform, existe una variable global llamada location que contiene siempre la localidad en la que se halla el jugador. El concepto de variable global es muy similar al concepto de "Bandera" de PAWS, si bien en PAWS las banderas se identificaban mediante un número (así la bandera que indicaba dónde está el jugador, era la bandera número 254), mientras que en Inform se identifican mediante un nombre (location es el nombre de esta "bandera"). Otras importantes diferencias son que en PAWS el número de banderas estaba limitado a 255, y no era necesario "declararlas" de antemano, mientras que en Inform no hay límite al número de variables globales, pero es necesario declararlas de antemano (es decir, "anunciar" a Inform de que vamos a crear una nueva variable global, indicándole el nombre que vamos a darle). La variable location es declarada en Parser.h, el fichero que hemos incluido al principio. Otra diferencia importante es que en PAWS una bandera sólo podía servir para almacenar un número entre 0 y 255, mientras que en Inform puede usarse para almacenar un número entre -32768 y +32767, o también una palabra, una frase, un objeto, un lugar.. ¡cualquier cosa!

Para hacer que el lugar de comienzo sea la puerta principal, basta cargar en la variable location el objeto PuertaPrincipal. La carga de una variable es algo análogo al condacto LET del PAWS, pero en Inform se usa la siguiente sintaxis:

  variable = valor;

Así, por ejemplo:

  v2 = 32;

Guardaría el número 32 dentro de la variable v2, de forma análoga a lo que hacía el condacto LET, mientras que:

  v1=v2;

Copiaría el valor de la variable v2 en la variable v1, de forma análoga a lo que hacía el condacto COPYFF

De modo que ahora debes modificar la rutina Initialise para que ponga:

[ Initialise ;
   location = PuertaPrincipal;
];  

Observa que ahora Initialise ya no está vacía. Tiene una sola instrucción que sirve para asignar un valor a la variable location. Recuerda que la instrucción debe terminar con punto y coma.

Otra interesante variable de Inform es una llamada lookmode, que controla si la descripción de la localidad debe repetirse o no cada vez que el jugador vuelve a entrar en una localidad en la que ya había estado. El valor por defecto de esta variable implica que la descripción sólo se le muestre una vez, y si desea volver a verla debe escribir el verbo MIRAR. Si prefieres que la descripción se muestre siempre, debes hacer que esta variable tenga el valor 2 cuando el juego comience, es decir, modifica Initialise para que sea:

[ Initialise ;
   location = PuertaPrincipal;
   lookmode=2;
];  

Es importante que te acostumbres desde el primer momento a "comentar" tu código, para que otros puedan comprenderlo y para que tú mismo lo entiendas cuando lo mires unas semanas más tarde. Añadir comentarios al juego no lo hace crecer de tamaño ¡recuerda que Inform ignora tus comentarios! Así que una rutina Initialise más "profesional" sería así:

[ Initialise ;
    ! Lugar de comienzo: la puerta principal
    location=PuertaPrincipal;
    
    ! Activamos esta variable para que la descripción de los lugares
    ! se repita siempre, incluso si el jugador ya ha estado allí
    lookmode=2;
];

Es habitual también incluir en la rutina Initialise algún mensaje de bienvenida al juego, o una introducción para situar al jugador. El comando para mostrar texto en Inform es print, seguido del texto en cuestión encerrado entre comillas dobles. Por ejemplo:

  print "¡¡Bienvenido a mi primer juego!!^^";

Como ya sabes, el signo ^ representa un salto de línea. Poniendo dos seguidos dejamos una línea en blanco debajo del texto anterior. Observa que en Inform no hay tablas de mensajes de usuario. No necesitas guardar tus textos en una tabla para después acceder a ellos mediante un número, sino que el texto lo pones directamente a continuación del print. No olvides encerrarlo entre comillas.

Los juegos conversacionales escriben mucho texto. En juegos complicados esto significa que habrá que usar muchas veces la orden print, por ello Inform permite una abreviatura especialmente útil, pero un poco peligrosa para los principiantes. Consiste en no poner print, sino simplemente el texto entre comillas. Cuando Inform encuentra un texto entrecomillado en un lugar donde esperaba una instrucción (o sea, dentro de una rutina), lo que hará será imprimir ese texto como si hubieras puesto print delante, añadir un salto de línea al final (como si hubieras puesto un ^ justo antes de cerrar las comillas), y terminar la ejecución de la rutina (algo equivalente al DONE del PAWS).

Clave Esto es muy importante, merece la pena repetirlo: una cadena entrecomillada en lugar de una instrucción equivale a un print de la cadena, seguido de un salto de línea y seguido del retorno inmediato de la rutina en que aparece.

Por tanto, si queremos escribir un mensaje de bienvenida desde nuestra rutina Initialise , tenemos varias posibilidades. En primer lugar, usando print (forma recomendada a los principiantes):

[ Initialise;
    ! Lugar de comienzo: la puerta principal
    location=PuertaPrincipal;
    
    ! Activamos esta variable para que la descripción de los lugares
    ! se repita siempre, incluso si el jugador ya ha estado allí
    lookmode=2;
    
    ! Mensaje de bienvenida
    print "¡¡Bienvenido a mi primer juego!!^^";
];

La orden print puede aparecer en cualquier lugar dentro de Initialise , a fin de cuentas da lo mismo imprimir la bienvenida antes o después de haber inicializado las variables. La segunda forma, para programadores más expertos, es usar la abreviatura en la que no se pone print. Quedaría así:

[ Initialise;
    ! Lugar de comienzo: la puerta principal
    location=PuertaPrincipal;
    
    ! Activamos esta variable para que la descripción de los lugares
    ! se repita siempre, incluso si el jugador ya ha estado allí
    lookmode=2;
    
    ! Mensaje de bienvenida
    "¡¡Bienvenido a mi primer juego!!^";
];

En este caso, observa con atención los detalles siguientes:

Puedes ver el código fuente con todo esto ya tecleado aqui. Crea un nuevo fichero 'torre.inf' con el contenido del código, guárdalo (que no sea con Word, si no con Notepad o Vi, editor de texto plano), y lanza "inform torre.inf" desde CMD para compilarlo. Para ejecutarlo, lanza "frotz torre.z5" o bien arrastra el fichero Z5 encima del icono de WinFrotz.

Prueba a cambiar la descripción de una localidad, no tengas miedo de experimentar, es la única forma de aprender. ¿Cómo modificarías el programa para que bajando desde la PuertaPrincipal se llegue a un Sotano? ¡Hazlo! ¿Cómo eliminarías la conexión que hay entre la EscaleraCaracol1 y la Mazmorra? ¡Hazlo!


Zak McKraken - spinf_2000@yahoo.com.
Adaptado a JIF por Luis Fernandez nfseoi (en) yahoo.es bajo la licencia Creative Commons Attribution-ShareAlike 2.0
Adaptado a JIF3+INFSP por Sarganar - sarganar (en) gmail.com bajo la misma licencia.

Entendiendo Inform (y olvidando PAWS) Parte I: Lo más básico Parte I: Lo más básico Por dónde empezar.